🐛 seed the synth idle (not 0) for cableless tweaked voices — fix-verify regression
The fix-verify pass flagged one CONFIRMED regression in the #1 floor loop: it pinned any tweaked cableless non-note dest to a hard 0, but two dests have a non-zero synth idle — filter.cutoff (d(...,0.3)) and tempo.nudge (d(...,0.5)). So touching the filter knob in zero (or, before this, merely opening OMNI, which created a neutral tweak) pinned filter.cutoff to 0 → 250 Hz, darkening the lead. - new DEST_IDLE map; the floor loop seeds destVals[k]=DEST_IDLE[k]||0, so a neutral/reset knob returns a voice to its idle (filter 0.3), an offset rides from the idle, and mute still → 0. (verified: reset filter → 0.3 not 0; drag up → 0.767; mute → 0) - OMNI update() + knob pointerdown now read tweaks[k] directly instead of tw(k), so rendering/opening the panel no longer creates phantom neutral tweaks (which also kept the tweaks map — and saved dimensions — clean). (verified: open OMNI → filter has no tweak) A clean instrument (no tweaks) stays byte-identical; the public house patch was already masked (filter.cutoff is cabled to sun.speed). Deploy gate: GO. Console clean, syntax clean, 21 knobs, field healthy. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
fa948823a7
commit
fb32d10991
@ -2448,6 +2448,10 @@
|
||||
return v;
|
||||
}
|
||||
|
||||
// Synth-side idle for the two dests whose "no value" default isn't 0 (see the
|
||||
// d("filter.cutoff",0.3) / d("tempo.nudge",0.5) fallbacks). The cableless-tweak
|
||||
// floor seeds THIS, so a neutral/reset knob returns a voice to its idle, not to 0.
|
||||
const DEST_IDLE = { "filter.cutoff": 0.3, "tempo.nudge": 0.5 };
|
||||
let clientMatrix = false; // true once the house patch has been cloned in
|
||||
function computeDests() {
|
||||
if (!clientMatrix) return;
|
||||
@ -2491,8 +2495,8 @@
|
||||
for (const k in destVals) destVals[k] = clamp(destVals[k], 0, 1);
|
||||
for (const k in notes) destVals[k] = notes[k];
|
||||
for (const [k, n] of dests) { // any hand-tweaked cableless voice: emit its ACTUAL value —
|
||||
if (n.isNote || (k in destVals)) continue; // an offset floor gives it a level from nothing, and a
|
||||
if (tweaks[k]) destVals[k] = 0; // reset/mute/lower writes 0 too (else the last value sticks in the synth)
|
||||
if (n.isNote || (k in destVals)) continue; // an offset floor gives it a level from its idle, and a
|
||||
if (tweaks[k]) destVals[k] = DEST_IDLE[k] || 0; // reset/mute/lower re-emit too — seed the synth idle (not a blank 0), so a neutral filter/tempo doesn't pin dark
|
||||
}
|
||||
for (const k in destVals) {
|
||||
const tk = tweaks[k];
|
||||
@ -3500,7 +3504,7 @@
|
||||
const val = wrap.querySelector(".val"), dot = wrap.querySelector(".dot");
|
||||
if (!isNote) {
|
||||
let dragging = false, sy = 0, so = 0;
|
||||
wrap.addEventListener("pointerdown", (e) => { if (e.button !== 0) return; dragging = true; sy = e.clientY; so = (tw(key).offset || 0); try { wrap.setPointerCapture(e.pointerId); } catch (x) {} e.preventDefault(); });
|
||||
wrap.addEventListener("pointerdown", (e) => { if (e.button !== 0) return; dragging = true; sy = e.clientY; so = ((tweaks[key] && tweaks[key].offset) || 0); try { wrap.setPointerCapture(e.pointerId); } catch (x) {} e.preventDefault(); });
|
||||
wrap.addEventListener("pointermove", (e) => { if (!dragging) return; setParamLocal(key, "offset", clamp(so + (sy - e.clientY) / 150, -1, 1)); });
|
||||
const end = (e) => { dragging = false; try { wrap.releasePointerCapture(e.pointerId); } catch (x) {} if (zeroMode) zeroUI.persist(); }; // a knob shape is part of the zero build
|
||||
wrap.addEventListener("pointerup", end); wrap.addEventListener("pointercancel", end);
|
||||
@ -3519,7 +3523,7 @@
|
||||
const frac = n ? clamp(n.normDisp != null ? n.normDisp : (n.norm || 0), 0, 1) : 0;
|
||||
k.val.style.strokeDashoffset = (1000 * (1 - frac)).toFixed(1);
|
||||
if (!k.isNote) {
|
||||
const off = tw(k.key).offset || 0;
|
||||
const off = (tweaks[k.key] && tweaks[k.key].offset) || 0; // read-only — don't create a neutral tweak just by rendering
|
||||
const a = (135 + ((off + 1) / 2) * 270) * Math.PI / 180;
|
||||
k.dot.setAttribute("cx", (50 + 34 * Math.cos(a)).toFixed(1));
|
||||
k.dot.setAttribute("cy", (50 + 34 * Math.sin(a)).toFixed(1));
|
||||
|
||||
Loading…
Reference in New Issue
Block a user