Search code examples
javascriptweb-audio-api

Web Audio API: performance problems?


I've got a little chime maker going here. It generates several overtones at once, and uses variable gain on each overtone to produce a rich chime sound. I call a function to play a series of these in sequence. But if I rapidly press the button a few times, the sound output stops, as though it's running out of memory:

https://codepen.io/ophello/pen/OJVRMQe

function ding(freq) {
    var toneGen = new AudioContext()
    var duration = 15
    var T = toneGen.currentTime
    var overtones = [1,2.76,5.4,8.93,13.34,18.64]
    overtones.forEach(function(overtone,i) {
        var osc = toneGen.createOscillator()
        osc.type = "sine"
        var freqVal = freq * overtone
        if (freqVal <= 22050) {
            osc.frequency.value = freq * overtone
            var envelope = toneGen.createGain()
            osc.connect(envelope)
            envelope.gain.setValueAtTime(0.1/Math.pow((i+1),5), T)
            envelope.gain.exponentialRampToValueAtTime(0.00001, T + duration)
            envelope.connect(toneGen.destination)
            osc.start(T)
            osc.stop(T + duration)
        }
    })
}

var hzValues = [216, 288, 324, 405, 432, 648]

$("#b1").mousedown(() => { 
    hzValues.forEach((thisHz,i) => { 
        setTimeout(() => { ding(thisHz) }, 100 * i); 
    })
})

Why does this stop working after a few presses? Am I missing something critical here? I don't know where in the console to look for any problems with this. Is this a memory issue?


Solution

  • Thanks to dandavis above, I got this working by adding a timeout function:

    setTimeout(toneGen.close.bind(toneGen), duration*1000);
    

    Update: Improved by moving the audio context outside the main function!