The code below (also live here) seems to demonstrate inconsistent performance from setTargetAtTime... it "should" swell to maximum at 2 seconds, then fade to silence at 7 seconds, then terminate the oscillator at 12 seconds (safely quiet enough to avoid "the ugly click".)
Instead, it swells to maximum at 2 seconds, then begins a fade which is not finished yet at 12 seconds, at which point we do hear the ugly click.
Can anyone explain why this is happening? Note that a short value (the commented //0.3
) drops it quickly enough to avoid the click. I've tried this in a variety of contexts, and it seems as if, (when fading to 0 anyway) that third parameter stretches out proportionally further beyond the proper stop time as the value rises.
<button id = "button" >
Start then stop oscillators
</button>
<script>
var audioContext = new AudioContext();
var fadeIn = 2;
var fadeOut = 5; //0.3
var gainNode = audioContext.createGain();
var osc = audioContext.createOscillator();
osc.type = "sine";
osc.frequency.value = 300;
osc.connect(gainNode);
gainNode.gain.value = 0;
gainNode.connect(audioContext.destination);
function startAndStop() {
osc.start(audioContext.currentTime);
gainNode.gain.setTargetAtTime(1, audioContext.currentTime, fadeIn);
gainNode.gain.setTargetAtTime(0, audioContext.currentTime + fadeIn, fadeOut);
osc.stop(audioContext.currentTime + fadeIn + fadeOut + 5);
};
var button = document.getElementById("button");
button.addEventListener("click", startAndStop);
</script>