class DispatchAudioWorkletClass extends AudioWorkletProcessor { constructor() { super(); this.BufferLen = 0; //缓冲区长度 共享内存模式:缓冲区总长度 消息模式:单次消息长度 this.MessageBufferLen = 0; this.Shared_Buffer = false; //是否启用SharedArrayBuffer 共享内存模式 this.Audio_Play_Empty = new Int16Array(128); //空帧 //共享内存模式相关 this.AudioBuffer_Play_Left = null; //左声道播放缓冲区 this.AudioBuffer_Play_Right = null; //右声道播放缓冲区 this.Audio_Play_Write_Index = null; //播放缓冲区写地址 this.Audio_Play_Read_Index = null; //播放缓冲区读地址 this.Audio_Play_Length = null; //播放缓冲区长度 this.AudioBuffer_Capture = null; //采集缓冲区 this.Audio_Capture_Flag = null; //采集标志位 this.Audio_Capture_Write_Index = null; //采集缓冲区写地址 this.Audio_Capture_Read_Index = null; //采集缓冲区读指针 this.Audio_Capture_Length = null; //采集缓冲区长度 this.Audio_Play_Len = 0; /* DispatchPocLib.AudioWorkletNode.port.postMessage({ Msg: "AudioEcho", start: 0, }) */ this.AudioEcho = 0; var self = this; this.port.onmessage = event => { if (event && event.data && event.data.Msg) { if (event.data.Msg == "AudioBufferInit") { if (event.data.Mode == "SharedArrayBuffer") { self.Shared_Buffer = true; self.BufferLen = event.data.BufferLen; self.MessageBufferLen = event.data.Message_BufferLen; self.AudioBuffer_Play_Left = new Int16Array(event.data.Shared_Play_Left); self.AudioBuffer_Play_Right = new Int16Array(event.data.Shared_Play_Right); self.Audio_Play_Write_Index = new Uint32Array(event.data.Shared_Play_Write_Index); self.Audio_Play_Read_Index = new Uint32Array(event.data.Shared_Play_Read_Index); self.Audio_Play_Length = new Uint32Array(event.data.Shared_Play_Length); self.AudioBuffer_Capture = new Int16Array(event.data.Shared_Capture); self.Audio_Capture_Flag = new Uint32Array(event.data.Shared_Capture_Flag); self.Audio_Capture_Write_Index = new Uint32Array(event.data.Shared_Capture_Write_Index); self.Audio_Capture_Read_Index = new Uint32Array(event.data.Shared_Capture_Read_Index); self.Audio_Capture_Length = new Uint32Array(event.data.Shared_Capture_Length); } else { self.Shared_Buffer = false; self.BufferLen = event.data.BufferLen; self.MessageBufferLen = event.data.Message_BufferLen; self.AudioBuffer_Play_Left = new Int16Array(event.data.BufferLen); self.AudioBuffer_Play_Right = new Int16Array(event.data.BufferLen); self.Audio_Play_Write_Index = new Uint32Array(1); self.Audio_Play_Read_Index = new Uint32Array(1); self.Audio_Play_Length = new Uint32Array(1); self.AudioBuffer_Capture = new Int16Array(event.data.BufferLen); self.Audio_Capture_Flag = new Uint32Array(1); self.Audio_Capture_Write_Index = new Uint32Array(1); self.Audio_Capture_Read_Index = new Uint32Array(1); self.Audio_Capture_Length = new Uint32Array(1); self.Audio_Capture_Flag[0] = 0; } self.Audio_Play_Length[0] = 0; self.Audio_Capture_Length[0] = 0; for (var i = 0; i < 128; i++) { self.Audio_Play_Empty[i] = 0; } } else if (event.data.Msg == "AudioCaptureStart") { self.Audio_Capture_Flag[0] = 1 console.log("DispatchAudioWorklet AudioCaptureStart"); } else if (event.data.Msg == "AudioCaptureStop") { self.Audio_Capture_Flag[0] = 0 console.log("DispatchAudioWorklet AudioCaptureStop"); } else if (event.data.Msg == "AudioPlayBuffer") { self.AudioBuffer_Play_Left.set(event.data.BufferLeft, self.Audio_Play_Write_Index[0]); self.AudioBuffer_Play_Right.set(event.data.BufferRight, self.Audio_Play_Write_Index[0]); //console.log("DispatchAudioWorklet fill write_index:", self.Audio_Play_Write_Index[0], " len:", event.data.BufferLeft.length, "read_index:", self.Audio_Play_Read_Index[0]); self.Audio_Play_Write_Index[0] = self.Audio_Play_Write_Index[0] + event.data.BufferLeft.length; if (self.Audio_Play_Write_Index[0] >= self.BufferLen) { self.Audio_Play_Write_Index[0] = 0; } self.Audio_Play_Length[0] = self.Audio_Play_Length[0] + event.data.BufferLeft.length; } else if (event.data.Msg == "AudioEcho") { self.AudioEcho = event.data.start; } } } self.port.postMessage({ Msg: "AudioWorkletInit", }); console.log("DispatchAudioWorklet Begin"); } process(inputs, outputs, parameters) { //Float32Array if (this.Audio_Capture_Read_Index !== null) { const frameLen = 128; var input = inputs[0][0]; if (input && this.AudioEcho) { //回声测试 outputs[0][0].set(input); outputs[0][1].set(input); return true; } //采集 if (input && (this.Audio_Capture_Flag[0] == 1)) { //Float32Array->Int16Array var cap_short = new Int16Array(frameLen); for (var i = 0; i < frameLen; i++) { cap_short[i] = parseInt(32767*input[i]); } //写入缓冲区 this.AudioBuffer_Capture.set(cap_short, this.Audio_Capture_Write_Index[0]); //写地址后移 this.Audio_Capture_Write_Index[0] = this.Audio_Capture_Write_Index[0] + cap_short.length; this.Audio_Capture_Length[0] = this.Audio_Capture_Length[0] + cap_short.length; if (!this.Shared_Buffer) { //消息模式 if (this.Audio_Capture_Write_Index[0] % this.MessageBufferLen == 0) { this.port.postMessage({ Msg: "AudioCapBuffer", Buffer: this.AudioBuffer_Capture.subarray(this.Audio_Capture_Write_Index[0] - this.MessageBufferLen, this.Audio_Capture_Write_Index[0]) }); } } if (this.Audio_Capture_Write_Index[0] >= this.BufferLen) { this.Audio_Capture_Write_Index[0] = 0; } //console.log("DispatchAudioWorklet Audio_Capture Write ", this.Audio_Capture_Write_Index[0], " len:", this.Audio_Capture_Length[0], " Read ",this.Audio_Capture_Read_Index[0]); } //播放 if (this.Audio_Play_Length[0] >= frameLen) { var play_float_left = new Float32Array(frameLen); for (var i = 0; i < frameLen; i++) { play_float_left[i] = this.AudioBuffer_Play_Left[this.Audio_Play_Read_Index[0] + i] / 32767.0; } if (outputs[0][0]) { outputs[0][0].set(play_float_left); //左声道 } var play_float_right = new Float32Array(frameLen); for (var i = 0; i < frameLen; i++) { play_float_right[i] = this.AudioBuffer_Play_Right[this.Audio_Play_Read_Index[0] + i] / 32767.0; } if (outputs[0][1]) { outputs[0][1].set(play_float_right); //右声道 } this.Audio_Play_Read_Index[0] = this.Audio_Play_Read_Index[0] + frameLen; if (this.Audio_Play_Read_Index[0] >= this.BufferLen) { this.Audio_Play_Read_Index[0] = 0; } this.Audio_Play_Length[0] = this.Audio_Play_Length[0] - frameLen; } else { if (outputs[0][0]) { outputs[0][0].set(this.Audio_Play_Empty); } if (outputs[0][1]) { outputs[0][1].set(this.Audio_Play_Empty); } } } return true; } } registerProcessor('DispatchAudioWorklet', DispatchAudioWorkletClass);