Use currentTime for exact scheduling

This commit is contained in:
Aria
2025-09-06 10:09:44 -05:00
parent 9c108862ef
commit 798eb22d9a
3 changed files with 47 additions and 46 deletions
+4 -4
View File
@@ -590,12 +590,12 @@ export const { duckdepth } = registerControl('duckdepth');
* @param {number | Pattern} time The onset time in seconds
* @example
* // Clicks
* sound: n(run(8)).scale("c:minor").s("sawtooth").lpf(200).delay(.7).orbit(2)
* duckerWithClick: s("bd*4").duckorbit(2).duckonset(0).postgain(0)
* sound: freq("63.2388").s("sine").orbit(2).gain(4)
* duckerWithClick: s("bd*4").duckorbit(2).duckattack(0.3).duckonset(0).postgain(0)
* @example
* // No clicks
* sound: n(run(8)).scale("c:minor").s("sawtooth").lpf(200).delay(.7).orbit(2)
* duckerWithoutClick: s("bd*4").duckorbit(2).duckonset(0.003).postgain(0)
* sound: freq("63.2388").s("sine").orbit(2).gain(4)
* duckerWithoutClick: s("bd*4").duckorbit(2).duckattack(0.3).duckonset(0.01).postgain(0)
* @example
* // Rhythmic
* noise: s("pink").distort("2:1").orbit(4) // used rhythmically with 0.3 onset below
+11 -10
View File
@@ -420,7 +420,7 @@ function setOrbit(audioContext, orbit, channels) {
}
}
function duckOrbit(audioContext, targetOrbit, t, onsettime = 0.003, attacktime = 0.1, duckdepth = 1) {
function duckOrbit(audioContext, targetOrbit, t, onsettime = 0, attacktime = 0.1, duckdepth = 1) {
const targetArr = [targetOrbit].flat();
const onsetArr = [onsettime].flat();
const attackArr = [attacktime].flat();
@@ -438,17 +438,18 @@ function duckOrbit(audioContext, targetOrbit, t, onsettime = 0.003, attacktime =
webAudioTimeout(
audioContext,
() => {
gainParam.cancelScheduledValues(t);
const now = audioContext.currentTime;
// cancelScheduledValues and setValueAtTime together emulate cancelAndHoldAtTime
// on browsers which lack that method
const currVal = gainParam.value;
gainParam.cancelScheduledValues(now);
gainParam.setValueAtTime(currVal, now);
const t0 = Math.max(t, now); // guard against now > t
const duckedVal = clamp(1 - Math.sqrt(depth), 0.01, currVal);
// Guarantees the value is set to currVal at time t. This in conjunction with
// cancelScheduledValues above emulates cancelAndHoldAtTime on browsers which lack
// that method
gainParam.setValueAtTime(currVal, t);
gainParam.exponentialRampToValueAtTime(duckedVal, t + onset);
gainParam.exponentialRampToValueAtTime(1, t + onset + attack);
gainParam.exponentialRampToValueAtTime(duckedVal, t0 + onset);
gainParam.exponentialRampToValueAtTime(1, t0 + onset + attack);
},
0,
t - 0.01,
+32 -32
View File
@@ -3170,43 +3170,43 @@ exports[`runs examples > example "duckdepth" example index 1 1`] = `
exports[`runs examples > example "duckonset" example index 0 1`] = `
[
"[ 0/1 → 1/4 | s:bd duckorbit:2 duckonset:0 postgain:0 ]",
"[ 1/4 → 1/2 | s:bd duckorbit:2 duckonset:0 postgain:0 ]",
"[ 1/2 → 3/4 | s:bd duckorbit:2 duckonset:0 postgain:0 ]",
"[ 3/4 → 1/1 | s:bd duckorbit:2 duckonset:0 postgain:0 ]",
"[ 1/1 → 5/4 | s:bd duckorbit:2 duckonset:0 postgain:0 ]",
"[ 5/4 → 3/2 | s:bd duckorbit:2 duckonset:0 postgain:0 ]",
"[ 3/2 → 7/4 | s:bd duckorbit:2 duckonset:0 postgain:0 ]",
"[ 7/4 → 2/1 | s:bd duckorbit:2 duckonset:0 postgain:0 ]",
"[ 2/1 → 9/4 | s:bd duckorbit:2 duckonset:0 postgain:0 ]",
"[ 9/4 → 5/2 | s:bd duckorbit:2 duckonset:0 postgain:0 ]",
"[ 5/2 → 11/4 | s:bd duckorbit:2 duckonset:0 postgain:0 ]",
"[ 11/4 → 3/1 | s:bd duckorbit:2 duckonset:0 postgain:0 ]",
"[ 3/1 → 13/4 | s:bd duckorbit:2 duckonset:0 postgain:0 ]",
"[ 13/4 → 7/2 | s:bd duckorbit:2 duckonset:0 postgain:0 ]",
"[ 7/2 → 15/4 | s:bd duckorbit:2 duckonset:0 postgain:0 ]",
"[ 15/4 → 4/1 | s:bd duckorbit:2 duckonset:0 postgain:0 ]",
"[ 0/1 → 1/4 | s:bd duckorbit:2 duckattack:0.3 duckonset:0 postgain:0 ]",
"[ 1/4 → 1/2 | s:bd duckorbit:2 duckattack:0.3 duckonset:0 postgain:0 ]",
"[ 1/2 → 3/4 | s:bd duckorbit:2 duckattack:0.3 duckonset:0 postgain:0 ]",
"[ 3/4 → 1/1 | s:bd duckorbit:2 duckattack:0.3 duckonset:0 postgain:0 ]",
"[ 1/1 → 5/4 | s:bd duckorbit:2 duckattack:0.3 duckonset:0 postgain:0 ]",
"[ 5/4 → 3/2 | s:bd duckorbit:2 duckattack:0.3 duckonset:0 postgain:0 ]",
"[ 3/2 → 7/4 | s:bd duckorbit:2 duckattack:0.3 duckonset:0 postgain:0 ]",
"[ 7/4 → 2/1 | s:bd duckorbit:2 duckattack:0.3 duckonset:0 postgain:0 ]",
"[ 2/1 → 9/4 | s:bd duckorbit:2 duckattack:0.3 duckonset:0 postgain:0 ]",
"[ 9/4 → 5/2 | s:bd duckorbit:2 duckattack:0.3 duckonset:0 postgain:0 ]",
"[ 5/2 → 11/4 | s:bd duckorbit:2 duckattack:0.3 duckonset:0 postgain:0 ]",
"[ 11/4 → 3/1 | s:bd duckorbit:2 duckattack:0.3 duckonset:0 postgain:0 ]",
"[ 3/1 → 13/4 | s:bd duckorbit:2 duckattack:0.3 duckonset:0 postgain:0 ]",
"[ 13/4 → 7/2 | s:bd duckorbit:2 duckattack:0.3 duckonset:0 postgain:0 ]",
"[ 7/2 → 15/4 | s:bd duckorbit:2 duckattack:0.3 duckonset:0 postgain:0 ]",
"[ 15/4 → 4/1 | s:bd duckorbit:2 duckattack:0.3 duckonset:0 postgain:0 ]",
]
`;
exports[`runs examples > example "duckonset" example index 1 1`] = `
[
"[ 0/1 → 1/4 | s:bd duckorbit:2 duckonset:0.003 postgain:0 ]",
"[ 1/4 → 1/2 | s:bd duckorbit:2 duckonset:0.003 postgain:0 ]",
"[ 1/2 → 3/4 | s:bd duckorbit:2 duckonset:0.003 postgain:0 ]",
"[ 3/4 → 1/1 | s:bd duckorbit:2 duckonset:0.003 postgain:0 ]",
"[ 1/1 → 5/4 | s:bd duckorbit:2 duckonset:0.003 postgain:0 ]",
"[ 5/4 → 3/2 | s:bd duckorbit:2 duckonset:0.003 postgain:0 ]",
"[ 3/2 → 7/4 | s:bd duckorbit:2 duckonset:0.003 postgain:0 ]",
"[ 7/4 → 2/1 | s:bd duckorbit:2 duckonset:0.003 postgain:0 ]",
"[ 2/1 → 9/4 | s:bd duckorbit:2 duckonset:0.003 postgain:0 ]",
"[ 9/4 → 5/2 | s:bd duckorbit:2 duckonset:0.003 postgain:0 ]",
"[ 5/2 → 11/4 | s:bd duckorbit:2 duckonset:0.003 postgain:0 ]",
"[ 11/4 → 3/1 | s:bd duckorbit:2 duckonset:0.003 postgain:0 ]",
"[ 3/1 → 13/4 | s:bd duckorbit:2 duckonset:0.003 postgain:0 ]",
"[ 13/4 → 7/2 | s:bd duckorbit:2 duckonset:0.003 postgain:0 ]",
"[ 7/2 → 15/4 | s:bd duckorbit:2 duckonset:0.003 postgain:0 ]",
"[ 15/4 → 4/1 | s:bd duckorbit:2 duckonset:0.003 postgain:0 ]",
"[ 0/1 → 1/4 | s:bd duckorbit:2 duckattack:0.3 duckonset:0.01 postgain:0 ]",
"[ 1/4 → 1/2 | s:bd duckorbit:2 duckattack:0.3 duckonset:0.01 postgain:0 ]",
"[ 1/2 → 3/4 | s:bd duckorbit:2 duckattack:0.3 duckonset:0.01 postgain:0 ]",
"[ 3/4 → 1/1 | s:bd duckorbit:2 duckattack:0.3 duckonset:0.01 postgain:0 ]",
"[ 1/1 → 5/4 | s:bd duckorbit:2 duckattack:0.3 duckonset:0.01 postgain:0 ]",
"[ 5/4 → 3/2 | s:bd duckorbit:2 duckattack:0.3 duckonset:0.01 postgain:0 ]",
"[ 3/2 → 7/4 | s:bd duckorbit:2 duckattack:0.3 duckonset:0.01 postgain:0 ]",
"[ 7/4 → 2/1 | s:bd duckorbit:2 duckattack:0.3 duckonset:0.01 postgain:0 ]",
"[ 2/1 → 9/4 | s:bd duckorbit:2 duckattack:0.3 duckonset:0.01 postgain:0 ]",
"[ 9/4 → 5/2 | s:bd duckorbit:2 duckattack:0.3 duckonset:0.01 postgain:0 ]",
"[ 5/2 → 11/4 | s:bd duckorbit:2 duckattack:0.3 duckonset:0.01 postgain:0 ]",
"[ 11/4 → 3/1 | s:bd duckorbit:2 duckattack:0.3 duckonset:0.01 postgain:0 ]",
"[ 3/1 → 13/4 | s:bd duckorbit:2 duckattack:0.3 duckonset:0.01 postgain:0 ]",
"[ 13/4 → 7/2 | s:bd duckorbit:2 duckattack:0.3 duckonset:0.01 postgain:0 ]",
"[ 7/2 → 15/4 | s:bd duckorbit:2 duckattack:0.3 duckonset:0.01 postgain:0 ]",
"[ 15/4 → 4/1 | s:bd duckorbit:2 duckattack:0.3 duckonset:0.01 postgain:0 ]",
]
`;