javascriptweb-audio-apiaudio-worklet

new Function() inside of AudioWorklet


I want to create an audio editor where you can connect nodes together to create custom audio components. Every time the nodes change, they get compiled into javascript and then will be run by a new Function() to get better performance. I just read up that there is the possibility to create an AudioWorklet, which runs on a separate thread. Now I am wondering if there is a possibility of combining both ideas in a way where my algorithm gets passed to the AudioWorklet as a string of javascript code, where it then gets put into a function using new Function(codeString) inside of the constructor. Then the audioworklet's process() function will call the custom function somehow.

Is this possible in some way, or am I asking for too much? I would like to get a "yes, that's possible" or a "no, sorry" before I spend hours trying to get it to work...

Thanks for your help,

dogefromage


Solution

  • With the help of @AKX's comment, I crafted together this solution. The code inside the string will later be replaced by a compiler.

    
    
    function generateProcessor()
    {
        return (`
    
    class TestProcessor extends AudioWorkletProcessor 
    {
        process(inputs, outputs) 
        {
            const input = inputs[0];
            const output = outputs[0];
    
            for (let channel = 0; channel < output.length; ++channel) {
                for (let i = 0; i < output[channel].length; i++) {
                    output[channel][i] = 0.01 * Math.acos(input[channel][i]);
                }
            }
    
            return true;
        }
    }
    
    registerProcessor('test-processor', TestProcessor);
    
    `);
    }
    
    const button = document.querySelector('#button');
    
    button.addEventListener('click', async (e) =>
    {
        const audioContext = new AudioContext();
    
        await audioContext.audioWorklet.addModule(
            URL.createObjectURL(new Blob([
                generateProcessor()
            ], {type: "application/javascript"})));
    
        const oscillator = new OscillatorNode(audioContext);
    
        const testProcessor = new AudioWorkletNode(audioContext, 'test-processor');
    
        oscillator.connect(testProcessor).connect(audioContext.destination);
    
        oscillator.start();
    });