fix: VCA CV scaler always 1 so envelope works regardless of gain param

Bug: if VCA gain was 0 when CV was connected, cvMod (initialized with
p.gain=0) would multiply envelope by 0 = silence forever.

Fix: cvMod always has gain=1 (full pass-through). The envelope (0-1)
controls the VCA amplitude directly. When CV is connected, base gain
is zeroed so only the envelope signal is heard. When disconnected,
base gain is restored from the param value.

Before: cvMod.gain = p.gain → envelope × 0 = 0 (broken)
After:  cvMod.gain = 1      → envelope × 1 = envelope (correct)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jose Luis
2026-03-21 18:55:29 +01:00
parent 49c016d0a6
commit 02db83b896

View File

@@ -127,8 +127,9 @@ function createNode(mod) {
} }
case 'vca': { case 'vca': {
const gain = new Tone.Gain(p.gain); const gain = new Tone.Gain(p.gain);
// CV modulation scaler: envelope (0-1) × gain param → added to gain.gain // CV scaler: always gain=1 so envelope (0-1) passes through fully.
const cvMod = new Tone.Gain(p.gain); // When CV is connected, base gain is zeroed — envelope controls amplitude entirely.
const cvMod = new Tone.Gain(1);
cvMod.connect(gain.gain); cvMod.connect(gain.gain);
return { return {
node: gain, node: gain,
@@ -401,9 +402,10 @@ export function updateParam(moduleId, paramName, value) {
break; break;
case 'vca': case 'vca':
if (paramName === 'gain') { if (paramName === 'gain') {
// Only update base gain if no CV is connected (CV zeroes it)
const hasCV = state.connections.some(c => c.to.moduleId === moduleId && c.to.port === 'cv'); const hasCV = state.connections.some(c => c.to.moduleId === moduleId && c.to.port === 'cv');
if (!hasCV) entry.node.gain.value = value; if (!hasCV) entry.node.gain.value = value;
if (entry._cvMod) entry._cvMod.gain.value = value; // cvMod stays at 1 always — envelope controls full range
} }
break; break;
case 'delay': case 'delay':