swithinbank
swithinbank

Reputation: 2039

Oscillator clicks when switching between gain envelopes

I’m working on a small Web Audio API app that reads from a JSON file containing “cues” that control the frequency and amplitude of a single oscillator node.

These cues can be of arbitrary length, e.g.

"amplitude": [0,50,0.025,2000,0.1,2000,0.3,1500]

where the first value of each pair represents an amplitude (0–1), and the second value represents the time to ramp to that amplitude (in milliseconds).

I pass these arrays to a function that uses them to build a gain envelope:

now = audioContext.currentTime;
oscGainNodeVal = oscGainNode.gain.value;
oscGainNode.gain.cancelScheduledValues(now);
oscGainNode.gain.setValueAtTime(oscGainNodeVal, now);
var rampTime = 0;
for (i=0; i<(gainPairs.length/2); i++) {
  rampTime = rampTime + (gainPairs[2*i+1]/1000);
  oscGainNode.gain.linearRampToValueAtTime(gainPairs[2*i], now + rampTime);
}

This works perfectly, but when I trigger a new cue, which calls the above function again, if the beginning of my new amplitude envelope does not match the current amplitude of the gain node, it clicks.

I can’t figure out why that should be. In theory, the initial amplitude pair, e.g. [0,50], ought to ramp from whatever the previous value was by setting the gain node’s value with the setValueAtTime() method. Does anyone know what’s going on?

The entire project is here if that’s of any use: https://github.com/delucis/troglodyte-angels

And there’s a demo deployment here: http://organist-tar-74864.netlify.com/

Edit: I did some further testing, and the clicks appear to only occur in Firefox (44.0) and Chrome (48.0.2564.97) under OS X (10.9.5). In Safari desktop (9.0.3), Safari (9.0) & Chrome (47.0.2526.107) under iOS (9.2), and Chrome (47.0.2526.83) under Android (4.2.2), it’s behaving as expected. So this is presumably a spec-implementation issue?

Upvotes: 2

Views: 583

Answers (1)

cwilso
cwilso

Reputation: 13908

By definition, the scheduler doesn't ramp from the current value and current time - it ramps from the last schedule point. This can cause discontinuous jumps, if you're not careful - but it also handles the case where you insert schedule points into the future cleanly. We'd talked about creating a "cancel scheduled values and checkpoint with current value" method.

Upvotes: 3

Related Questions