From 47c85f8540386d36c42c5bc64f952bde12ac79d5 Mon Sep 17 00:00:00 2001 From: jeromew Date: Thu, 16 Oct 2025 14:06:33 +0200 Subject: [PATCH 1/5] fix interoperability of `all` with hydra Hydra add methods on Array.prototype which breaks the Array enumeration with for...in. Use for...of instead cf https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of#difference_between_for...of_and_for...in for details on the issue without this fix, it is impossible to use both `await initHydra()` and `all` in the same strudel code. Strudel errors with "Error: got "undefined" instead of pattern." example code: https://strudel.cc/#YXdhaXQgaW5pdEh5ZHJhKCkKCmFsbChwaWFub3JvbGwpCgokOiBzKCJiZCIp --- packages/core/repl.mjs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/core/repl.mjs b/packages/core/repl.mjs index 171697eb9..064ef1eb8 100644 --- a/packages/core/repl.mjs +++ b/packages/core/repl.mjs @@ -227,8 +227,8 @@ export function repl({ pattern = eachTransform(pattern); } if (allTransforms.length) { - for (let i in allTransforms) { - pattern = allTransforms[i](pattern); + for (const transform of allTransforms) { + pattern = transform(pattern); } } From 907f03f3bfe35bc4b6695490030e6f4822747629 Mon Sep 17 00:00:00 2001 From: jeromew Date: Thu, 20 Nov 2025 17:40:51 +0000 Subject: [PATCH 2/5] [perf] fix `connect-leak` in fm modulation --- packages/superdough/helpers.mjs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/superdough/helpers.mjs b/packages/superdough/helpers.mjs index de64df0e8..58c4aa35e 100644 --- a/packages/superdough/helpers.mjs +++ b/packages/superdough/helpers.mjs @@ -362,9 +362,9 @@ const mod = (freq, range = 1, type = 'sine') => { } osc.start(); - const g = new GainNode(ctx, { gain: range }); + const g = gainNode(range); osc.connect(g); // -range, range - return { node: g, stop: (t) => osc.stop(t) }; + return { node: g, stop: (t) => osc.stop(t), osc: osc }; }; const fm = (frequencyparam, harmonicityRatio, modulationIndex, wave = 'sine') => { const carrfreq = frequencyparam.value; @@ -416,6 +416,11 @@ export function applyFM(param, value, begin) { modulator.connect(envGain); envGain.connect(param); } + fmmod.osc.onended = () => { + envGain.disconnect(); + modulator.disconnect(); + fmmod.osc.disconnect(); + }; } return { stop }; } From f637b8b0dd0c3bbe29c53d128a943b9e6260be9b Mon Sep 17 00:00:00 2001 From: jeromew Date: Thu, 20 Nov 2025 17:40:51 +0000 Subject: [PATCH 3/5] [perf] fix `connect-leak` in fm modulation --- packages/superdough/helpers.mjs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/superdough/helpers.mjs b/packages/superdough/helpers.mjs index de64df0e8..58c4aa35e 100644 --- a/packages/superdough/helpers.mjs +++ b/packages/superdough/helpers.mjs @@ -362,9 +362,9 @@ const mod = (freq, range = 1, type = 'sine') => { } osc.start(); - const g = new GainNode(ctx, { gain: range }); + const g = gainNode(range); osc.connect(g); // -range, range - return { node: g, stop: (t) => osc.stop(t) }; + return { node: g, stop: (t) => osc.stop(t), osc: osc }; }; const fm = (frequencyparam, harmonicityRatio, modulationIndex, wave = 'sine') => { const carrfreq = frequencyparam.value; @@ -416,6 +416,11 @@ export function applyFM(param, value, begin) { modulator.connect(envGain); envGain.connect(param); } + fmmod.osc.onended = () => { + envGain.disconnect(); + modulator.disconnect(); + fmmod.osc.disconnect(); + }; } return { stop }; } From 2efd56e33155096dd4454f9fe68e6b5f43bdc1e1 Mon Sep 17 00:00:00 2001 From: "Jade (Rose) Rowland" Date: Sat, 22 Nov 2025 18:10:28 -0500 Subject: [PATCH 4/5] add synonym --- packages/core/controls.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/controls.mjs b/packages/core/controls.mjs index 9a2be7f44..8297746dc 100644 --- a/packages/core/controls.mjs +++ b/packages/core/controls.mjs @@ -1840,7 +1840,7 @@ export const { octave } = registerControl('octave'); * s("~ sd ~ sd").delay(.5).delaytime(.125).orbit(2) * ) */ -export const { orbit } = registerControl('orbit'); +export const { orbit } = registerControl('orbit', 'o'); // TODO: what is this? not found in tidal doc Answer: gain is limited to maximum of 2. This allows you to go over that export const { overgain } = registerControl('overgain'); // TODO: what is this? not found in tidal doc. Similar to above, but limited to 1 From 3b2df0b72510a1a217242fd6281e6a06270e18a5 Mon Sep 17 00:00:00 2001 From: "Jade (Rose) Rowland" Date: Sun, 23 Nov 2025 19:05:57 -0500 Subject: [PATCH 5/5] synonym: --- packages/core/controls.mjs | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/core/controls.mjs b/packages/core/controls.mjs index 8297746dc..809a45ab2 100644 --- a/packages/core/controls.mjs +++ b/packages/core/controls.mjs @@ -1833,6 +1833,7 @@ export const { octave } = registerControl('octave'); * An `orbit` is a global parameter context for patterns. Patterns with the same orbit will share the same global effects. * * @name orbit + * @synonyms o * @param {number | Pattern} number * @example * stack(