Skip to content

Design cancelScheduledValues and hold

rtoy edited this page Aug 25, 2016 · 1 revision

How cancelScheduledValues(tc) should work.

  1. Let E1 be the event (if any) at time t1 where t1 is the largest number satisfying t1 ≤ tc.
  2. Let E2 be the event (if any) at time t2 where t2 is the smallest number satisfying tc<t2.
  3. If E2 exists:
  4. If E2 is a linear or exponential ramp, 1. Rewrite E2 to be the same kind of ramp ending at time tc with an end value that would be the value of the original ramp at time tc.
1. Go to step 5.
  1. Otherwise, go to step 4.
  2. If E1 exists:
  3. If E1 is a setTarget, 1. Implicitly insert at setValueAtTime at time tc with the value that the setTarget would have at time tc.
1. Go to step 5.
  1. If E1 is a setValueCurve(c, t3, d) 1. If tc>t3+d, go to step 5. 1. Otherwise,
    1. effectively replace this event with setValueCurve(c,t3, tc-t3). However, this is not a true replacement; this automation must take care to produce the same output as the original, and not one computed using a different duration. (That would cause sampling at the wrong points.)
    2. Go to step 5.
  2. Otherwise, go to step 5.
  3. Remove all events with time greater than tc.

It is undefined if new events are inserted between t1 and tc, after having called cancelScheduledValues(tc), but calling cancelScheduledValues again between t1and tcis valid to cancel the cancel event.

Corner Cases

SetTarget with Ramps

E1 is setTarget and E2 is a linear or exponential ramp. This is easy if E1 hasn’t started yet; we don’t need to do anything special because E2 will essentially overwrite the setTarget.

If E1 has started, we want to make sure the curve is continuous. An example of how this can happen:

gain.gain.setTargetAtTime(v1, t1, timeconst);
<wait until t1 has passed>
gain.gain.linearRampToValueAtTime(v2, t2);
gain.gain.cancelScheduledValues(tc);  // tc < t2

If everything were running on one thread, the call to canceScheduledValues could grab the current value of the gain and use that to adjust the linear ramp. However, this isn’t possible because the audio thread is the one computing all of these values. So by the time cancelScheduledValues is run, the main thread doesn’t know what the current value is.

I think that means E2 can’t be rewritten/updated until we’re running the timeline and have started processing E2. I think this mean we actually have to have an internal CancelValues event that remembers E2. When we’re processing CancelValues (i.e. the next event is CancelValues), we can rewrite E2 then. I think this is also the only time we need a CancelValues event.