How to access input/output of worklet node from main file?

473 views Asked by At

I have created a real time voice chat application for a game I am making. I got it to work completely fine using audiocontext.createScriptProcessor() method.

Here's the code, I left out parts that weren't relevant

//establish websocket connection

const audioData = []
//websocket connection.onMessage (data) => 
  audioData.push(decodeBase64(data)) //push audio data coming from another player into array


//on get user media (stream) =>
    const audioCtx = new AudioContext({latencyHint: "interactive", sampleRate: 22050,})
    const inputNode = audioCtx.createMediaStreamSource(stream)
    var processor = audioCtx.createScriptProcessor(2048, 1, 1);
    var outputNode = audioCtx.destination

    inputNode.connect(tunerNode)
    processor.connect(outputNode)
    
    processor.onaudioprocess = function (e) {
        var input = e.inputBuffer.getChannelData(0);
        webSocketSend(input) //send microphone input to other sockets via a function set up in a different file, all it does is base 64 encode then send.
        
        //if there is data from the server, play it, else, play nothing
        var output 
        if(audioData.length > 0){
          output = audioData[0]
          audioData.splice(0,1)
        }else output = new Array(2048).fill(0)
    };

the only issue is that the createScriptProccessor() method is deprecated. As recommended, I attempted to do this using Audio Worklet Nodes. However I quickly ran into a problem. I can't access the user's microphone input, or set the output from the main file where the WebSocket connection is.

Here is my code for main.js:

document.getElementById('btn').onclick = () => {createVoiceChatSession()}

//establish websocket connection

const audioData = []
//webSocket connection.onMessage (data) =>
audioData.push(data) //how do I get this data to the worklet Node???

var voiceChatContext
function createVoiceChatSession(){
    voiceChatContext = new AudioContext()
    navigator.mediaDevices.getUserMedia({audio: true}).then( async stream => {
        await voiceChatContext.audioWorklet.addModule('module.js')
        const microphone = voiceChatContext.createMediaStreamSource(stream)
        const processor = new AudioWorkletNode(voiceChatContext, 'processor')
        microphone.connect(processor).connect(voiceChatContext.destination)
    }).catch(err => console.log(err))
}

Here is my code for module.js:

class processor extends AudioWorkletProcessor {
    constructor() {
      super()
    }
    
    //copies the input to the output 
  
    process(inputList, outputList) { // how do I get the input list data (the data from my microphone) to the main file so I can send it via websocket ???
      for(var i = 0; i < inputList[0][0].length; i++){
        outputList[0][0][i] = inputList[0][0][i]
        outputList[0][1][i] = inputList[0][1][i]
      }
      return true;
    }
}
  
registerProcessor("processor", processor);

So I can record and process the input, but I can't send input via WebSocket or pass in data that is coming from the server to the worklet node because I can't access the input list or output list from the main file where the WebSocket connection is. Does anyone know a way to work around this? Or is there a better solution that doesn't use audio worklet nodes?

Thank you to all who can help!

1

There are 1 answers

0
BigChungus443 On

I figured it out, all I needed to do was use the port.onmessage method to exchange data between the worklet and the main file.

processor.port.onmessage = (e) => {//do something with e.data}