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?
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!