javascriptwebsocketaudiocontextaudio-worklet

Send AudioBuffer to Speaker


Here's what I want to do:

  1. Send microphone audio to AudioWorketProcessor (works)
  2. Send results from AudioWorkletProcessor to a server using WebSockets (works)
  3. Receive back the data over WebSockets (works)
  4. Send data to the computer's speakers (how to do it?)

Everything works except I don't know how to implement #4. Here's what I have, some things simplified to keep focus on the problem:

//1. The code to set up the audio context. Connects the microphone to the worklet

    const audioContext = new AudioContext({ sampleRate: 8000 });
    audioContext.audioWorklet.addModule('/common/recorderworkletprocess.js').then(
        function () {
            const recorder = new AudioWorkletNode(audioContext, 'recorder-worklet');
            let constraints = { audio: true };
            navigator.mediaDevices.getUserMedia(constraints).then(function (stream) {
                const microphone = audioContext.createMediaStreamSource(stream);
                microphone.connect(recorder);
                recorder.connect(audioContext.destination);
            });
        }
    );

//2. The AudioWorkletProcessor. Sends audio to the WebSocket, which sends it to the server as binary:

  class RecorderWorkletProcessor extends AudioWorkletProcessor {
     constructor() {
        super();
     }
     process(inputs) {
        const inputChannel = inputs[0][0];  //inputChannel Float32Array(128)
        socket.send(inputChannel);  // sent as byte[512]
        return true;
     }
  }
  registerProcessor('recorder-worklet', RecorderWorkletProcessor);

//3 and 4. Finally, the server sends back the data exactly as it was received. The WebSocket converts it to ArrayBuffer(512). Here I want to do whatever it takes to output it to the computer's speaker as audio:

socket.messageReceived = function (evt) {
// evt.data contains an ArrayBuffer with length of 512
// I want this to be played on the computer's speakers. How to do this?
  }

Any guidance would be appreciated.


Solution

  • Ok, I believe I can answer my question. This is not robust but it provides what I needed to know.

      socket.messageReceived = function (evt) {
         // evt.data contains an ArrayBuffer with length of 512
         // I want this to be played on the computer's speakers. How to do this?
         let fArr = new Float32Array(evt.data);
         let.buf = audioContext.createBuffer(1, 128, 8000);
         buf.copyToChannel(fArr, 0);
         let player = audioContext.createBufferSource();
         player.buffer = buf;
         player.connect(audioContext.destination);    
         player.start(0);
      }