From f7175c05057a75302c9b0bf0dde2357f3a4de333 Mon Sep 17 00:00:00 2001 From: Aria Date: Thu, 8 Jan 2026 19:40:50 -0600 Subject: [PATCH 1/2] Properly handle subcontrols --- packages/superdough/modulators.mjs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/superdough/modulators.mjs b/packages/superdough/modulators.mjs index 7d119a06b..05674baa0 100644 --- a/packages/superdough/modulators.mjs +++ b/packages/superdough/modulators.mjs @@ -32,8 +32,9 @@ const getNodeParam = (node, name) => { const controlTargets = getSuperdoughControlTargets(); -const getControlData = (control) => { - return controlTargets[control.split('_')[0]]; +const getControlData = (control, subControl) => { + const controlNoIdx = control.split('_')[0]; + return controlTargets[`${controlNoIdx}_${subControl}`] ?? controlTargets[controlNoIdx]; }; const getRangeForParam = (paramName, currentValue) => { @@ -59,8 +60,7 @@ const clampWithWaveShaper = (modulator, min, max) => { }; const getTargetParamsForControl = (control, nodes, subControl) => { - const lookupKey = subControl ? `${control}_${subControl}` : control; - const targetInfo = getControlData(lookupKey) ?? getControlData(control); + const targetInfo = getControlData(control, subControl); if (!targetInfo) { errorLogger( new Error(`Could not find control data for target '${control}'. It may not be modulatable.`), From f6a43f1b1019c081c321bc7dc96b73dcb6167466 Mon Sep 17 00:00:00 2001 From: Aria Date: Thu, 8 Jan 2026 20:28:53 -0600 Subject: [PATCH 2/2] Make the scaling by freq in FM a separate node so that modulators behave like the fm control --- packages/superdough/helpers.mjs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/superdough/helpers.mjs b/packages/superdough/helpers.mjs index 8bd8b067b..460dd283c 100644 --- a/packages/superdough/helpers.mjs +++ b/packages/superdough/helpers.mjs @@ -461,10 +461,11 @@ export function applyFM(param, value, begin) { nodes[`fm_${idx}`] = [osc]; } const { input, output, freq, osc, toCleanup } = fms[idx]; - const g = gainNode(amt * freq); - io.push(isMod ? output.connect(g) : input); - cleanupOnEnd(osc, [...toCleanup, g]); - nodes[`fm_${idx}_gain`] = [g]; + const gAmt = gainNode(amt); + const gFreq = gainNode(freq); + io.push(isMod ? output.connect(gAmt).connect(gFreq) : input); + cleanupOnEnd(osc, [...toCleanup, gAmt, gFreq]); + nodes[`fm_${idx}_gain`] = [gAmt]; } if (!io[1]) { logger(