javascriptweb-audio-apienvelopeweb-midi

Web Audio API - Correct way to stop oscillator connected to release envelope


I'm creating a polyphonic synthesizer using WebAudioAPI and WebMIDIAPI. I have a gain node for each of my two oscillators which is then connected to a master gain node.

I was wondering how to correctly stop (and delete if necessary?) the oscillator after the release. I am unsure whether or not it is necessary to call oscillator.stop() and delete the oscillator from the arrays.

If I do, the release envelope doesn't work and the note stops immediately, If I don't, the release envelope does work but the note can sometimes carry on playing forever.

EDIT: It Seems that when the .stop() functionality isn't implemented and two notes are simultaneously played together one of the oscillators will always stay on. Not sure if it is my code or ??

My code for noteOff function is below:

/**
 * Note is being released
 */
this.noteOff = function (frequency, velocity, note){

    var now = this.context.currentTime;

    // Get the release values
    var osc1ReleaseVal = now + this.osc1Release;
    var osc2ReleaseVal = now + this.osc2Release;

    // Cancel scheduled values
    this.oscGain.gain.cancelScheduledValues(now);
    this.osc2Gain.gain.cancelScheduledValues(now);

    // Set the value
    this.oscGain.gain.setValueAtTime(this.oscGain.gain.value, now);
    this.osc2Gain.gain.setValueAtTime(this.osc2Gain.gain.value, now);

    // Release the note
    this.oscGain.gain.linearRampToValueAtTime(0.0, osc1ReleaseVal);
    this.osc2Gain.gain.linearRampToValueAtTime(0.0, osc2ReleaseVal);

    // ----- IF I COMMENT THE `forEach` Loop the release works correctly but with side-effects!
    // Stop the oscillators
    this.oscillators[frequency].forEach(function (oscillator) {
        oscillator.stop(now);
        oscillator.disconnect();
        delete oscillator;
    });
};

Any help would be greatly appreciated, thanks!


Solution

  • Don't use oscillator.stop(now). Use oscillator.stop(osc1ReleaseVal) to schedule the oscillator to stop at the same time as the gain goes to 0.

    You don't have to disconnect and delete the oscillators. Once stopped, the oscillator can disconnect itself from the gain node by itself. If you drop the reference to the oscillator, it can be garbage collected.