zya zya - 9 days ago 6
Javascript Question

Web Audio API Oscillator Node object life span and stop() method

I am trying to understand Web Audio API timing and scheduling methods.

But i still have not understood the Oscillator Node's

stop()
method completely.

Here i'm trying to schedule to play 4 oscillator with tempo of 120 BPM.

But it seems like as soon as the
stop()
method kicks in on the release time, it stops all the oscillators.

Here is the code:

var context = new webkitAudioContext();
var now = context.currentTime;
var tempo = 120;
var releaseTime = 0.5;
var secondsPerBeat = 60.0 / tempo;

for(var i = 0; i < 4; i++){
var now = context.currentTime;
var osc = context.createOscillator();
osc.connect(context.destination);
osc.start(now + (i*secondsPerBeat));
var now = context.currentTime;
osc.stop(now + releaseTime);
}


Why is that happening and how i can prevent this?

Thanks

Answer

First thing, about Javascript : there is no block scope in Js, so maybe it will be clearer to put all vars definitions at the start of current execution context.
Secondly, you do start your sound with a delay, but stop them at the very same time, which is not what you seek.
Thirdly, the currentTime will be almost the same within a for loop : you cannot rely on the for loop to induce a delay.

var context = new webkitAudioContext();
var tempo = 120;
var releaseTime = 0.5;
var secondsPerBeat = 60.0 / tempo;

var now = context.currentTime;
var i = 0, startTime=0, osc = null;

for(i = 0; i < 4; i++) {
    startTime = now + (i*secondsPerBeat) ;
    osc = context.createOscillator();
    osc.connect(context.destination);
    osc.start();
    osc.stop(startTime + releaseTime);
} 

Soon enough you'll want to write a function to create your oscillator to further clear up the code.

Edit : about the lifetime of your objects, best is to look at the specs :
https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html
look at the 4.2.3. Lifetime part.

to sum it up : if playing or connected to a referenced context, they will survive, and die otherwise.

You can either :
- keep the same context, and store the 4 oscillator within an array to just start/stop them after when needed.
- or recreate a new context + new oscillators each time.

(but you cannot keep creating new oscillators on same context or they pile up since they are still connected, and use too much memory).

Comments