chrisguttandin / audio-context-timers

A replacement for setInterval() and setTimeout() which works in unfocused windows.
MIT License
15 stars 2 forks source link

Memory leak? #465

Closed Avijobo closed 11 months ago

Avijobo commented 11 months ago

I am not a Javascript expert, but I wonder: each time this function below is called, a new audioBufferSourceNode is created. When will these nodes become garbage-collected? Isn't this a memory leak?

`const scheduleFunction = (id: number, delay: number, type: TTimerType) => {
    const now = performance.now();

    const audioBufferSourceNode = new AudioBufferSourceNode(MINIMAL_AUDIO_CONTEXT, { buffer: AUDIO_BUFFER });

    audioBufferSourceNode.onended = () => {
        const elapsedTime = performance.now() - now;

        if (elapsedTime >= delay) {
            callIntervalFunction(id, type);
        } else {
            scheduleFunction(id, delay - elapsedTime, type);
        }
    };
    audioBufferSourceNode.connect(MINIMAL_AUDIO_CONTEXT.destination);
    audioBufferSourceNode.start(Math.max(0, MINIMAL_AUDIO_CONTEXT.currentTime + delay / 1000 - SAMPLE_DURATION));
};`
chrisguttandin commented 11 months ago

I remember that this got me thinking the first time I heard of the AudioBufferSourceNode, too. Apparently the AudioBufferSourceNode as well as the OscillatorNode and the ConstantSourceNode are meant to be used only once. Their start() function can only be called once.

I can only speculate but I imagine it was created like that to simplify the communication between the main thread and the audio thread.

The browser should normally garbage collect any ended and unreachable AudioNode by itself but just to make sure everything got cleaned up correctly we could at least disconnect it manually. I will go ahead and add that.

Thanks a lot for reading the code thoroughly and creating this issue.