4

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!

Alistair Hughes
  • 387
  • 2
  • 3
  • 13
  • Indeed Im not sure that you should delete your osc form the array. What about using a function that would cut the gain off after you release the note? So you can make sure the volume is off at some point, without necessary stop and delete the osc? Just an idea... I would need to spend some time on it ahah... – DevMoutarde Apr 25 '17 at 12:55
  • @DevMoutarde A good idea perhaps, I tried quickly to put `oscillator.stop()` in a `setTimeout` function with the time set to the `osc1ReleaseVal` and `osc2ReleaseVal` but didn't work.. think I'll need to think of something else to add to that – Alistair Hughes Apr 25 '17 at 13:22
  • Oh, too bad it didn't work because it sounds like a good way to go. Maybe (I guess you did already) you should give a look to some html/js synths on the internet to see how they manage to make a handy play/stop. I used to play with gain nodes myself instead of stopping the osc – DevMoutarde Apr 25 '17 at 13:33

1 Answers1

2

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.

Raymond Toy
  • 5,490
  • 10
  • 13
  • Thanks for the answer, this does work _to an extent_. I guess it is probably my code but although **this does stop the sustained forever note bug**, it seems that now when two notes are pressed simultaneously it doesn't do `linearRampToValueAtTime` and comes to an abrupt end with a clicking sound. Any ideas for this? If not I will probably accept your answer anyway because it answers my problem. – Alistair Hughes Apr 25 '17 at 15:01
  • Does the code snippet above illustrate this? Kind of hard to know what's happening without seeing the bit of code that shows the issue. – Raymond Toy Apr 25 '17 at 17:01
  • Yeah I mean this is the only code that is executed to stop the oscillators, it could be linked to how I am creating them but I thought that was out of scope of the question. I may edit it to include the creation of oscillators, would you care to see? – Alistair Hughes Apr 26 '17 at 09:53
  • I think that's up to you. But since it doesn't work for some use case that you wish it did, and the current example doesn't really show a problem, it would probably help a lot to have a real snippet that illustrates the problem. – Raymond Toy Apr 26 '17 at 14:40