Merge branch 'pantheon/b-godsquash'

This commit is contained in:
monsterrobotparty 2026-07-13 15:52:02 +10:00
commit 3d913b97fd

View File

@ -3496,7 +3496,7 @@
["pad.brightness", "pad — glows"], ["drone.voices", "drone — hums"], ["perc.density", "perc — taps"]] },
{ grp: "space & grit", items: [["filter.cutoff", "filter"], ["reverb.size", "reverb"],
["delay.feedback", "delay"], ["saturation", "saturation"], ["glitch", "glitch"],
["granular.density", "granular"], ["crush", "crush"], ["wavetable.morph", "morph"],
["granular.density", "granular"], ["crush", "crush"], ["squash", "squash"], ["wavetable.morph", "morph"],
["lfo.rate", "lfo"], ["master.space", "space"]] },
];
function _grpMembers(key) { const gi = groupsInfo[key]; return (gi && gi.members) || []; }
@ -4066,12 +4066,12 @@
root: null, head: null, body: null, knobs: [], _open: false,
MODULES: [
{ title: "voices", accent: [124, 255, 178], keys: ["lead.note", "bass.note", "pad.brightness", "drone.voices", "perc.density"] },
{ title: "fx rack", accent: [120, 170, 255], keys: ["filter.cutoff", "reverb.size", "delay.feedback", "saturation", "glitch", "granular.density", "crush", "wavetable.morph", "lfo.rate", "master.space"] },
{ title: "fx rack", accent: [120, 170, 255], keys: ["filter.cutoff", "reverb.size", "delay.feedback", "saturation", "glitch", "granular.density", "crush", "squash", "wavetable.morph", "lfo.rate", "master.space"] },
],
ECHO: { title: "🌀 earth echo", accent: [184, 150, 255], keys: ["echo.time", "echo.feedback", "echo.tone", "echo.flutter", "echo.wear", "echo.wet"] },
LABELS: { "lead.note": "lead", "bass.note": "bass", "pad.brightness": "pad", "drone.voices": "drone", "perc.density": "perc",
"filter.cutoff": "filter", "reverb.size": "reverb", "delay.feedback": "delay", "saturation": "saturation", "glitch": "glitch",
"granular.density": "granular", "crush": "crush", "wavetable.morph": "morph", "lfo.rate": "lfo", "master.space": "space",
"granular.density": "granular", "crush": "crush", "squash": "squash", "wavetable.morph": "morph", "lfo.rate": "lfo", "master.space": "space",
"echo.time": "time", "echo.feedback": "feedback", "echo.tone": "tone", "echo.flutter": "flutter", "echo.wear": "wear", "echo.wet": "wet" },
ARC: "M25.96 74.04 A34 34 0 1 1 74.04 74.04", // 270° gauge, opening at the bottom
isOpen() { return this._open; },
@ -8523,7 +8523,15 @@
const out = ctx.createGain(); out.gain.value = 0; // fades in on start
const lim = ctx.createDynamicsCompressor(); // safety limiter
lim.threshold.value = -8; lim.ratio.value = 12; lim.attack.value = 0.003; lim.release.value = 0.25;
out.connect(lim); lim.connect(ctx.destination);
// 🫀 GODSQUASH — the master squeeze the world can pump. out → squash → makeup → lim.
// knee/attack are static; threshold/ratio/release/makeup ride the `squash` dest in params().
// Baseline is the sq=0 transparent state (ratio 1:1) so it's clean before params() first runs.
// The GODSONIQ recorder tap on N.out (in loadWorklets) stays PRE-squash — captures are pre-limiter by design.
const squash = ctx.createDynamicsCompressor();
squash.knee.value = 12; squash.attack.value = 0.004;
squash.threshold.value = -6; squash.ratio.value = 1; squash.release.value = 0.12;
const squashMakeup = ctx.createGain(); squashMakeup.gain.value = 1;
out.connect(squash); squash.connect(squashMakeup); squashMakeup.connect(lim); lim.connect(ctx.destination);
const conv = ctx.createConvolver(); conv.buffer = impulse(1.8, 3.2); // tighter room, faster decay
const revSend = ctx.createGain(); revSend.gain.value = 0;
@ -8674,7 +8682,7 @@
g.connect(pan); pan.connect(drumBus); drums[dv] = { g, pan };
}
return { out, preSat, glitch, revSend, fb, satDry, satWet, leadA, leadB, morphA, morphB, leadFilt, leadAmp,
return { out, squash, squashMakeup, preSat, glitch, revSend, fb, satDry, satWet, leadA, leadB, morphA, morphB, leadFilt, leadAmp,
bassOsc, bassAmp, padOscs, padFilt, padAmp, droneOscs, droneAmp,
echoDelay, echoFilt, echoFb, echoWet, echoFlutAmt, hissGain, chorusWet,
drumBus, drums, noiseBuf, duckG };
@ -8818,6 +8826,12 @@
crusher.parameters.get("bits").value = 16 - cb * 12; // 16 clean → 4 crunchy
crusher.parameters.get("reduction").value = 1 + cb * 8; // 1 → 9× downsample
}
// 🫀 GODSQUASH — one knob squeezes the whole master bus; a world route can pump it.
const sq = c01(d("squash", 0)); // 0 = transparent (no route, no squeeze)
S(N.squash.threshold, -6 - sq * 30, 0.1); // 6 → 36 dB
S(N.squash.ratio, 1 + sq * 7, 0.1); // 1:1 → 8:1
N.squash.release.setTargetAtTime(0.12 + sq * 0.13, t, 0.2);
S(N.squashMakeup.gain, 1 + sq * sq, 0.1); // makeup: quadratic, gain-compensates the compressor's ~5.95·sq² dB RMS drop (measured) — loudness stays level ±0.5 dB while crest falls
S(N.droneAmp.gain, d("drone.voices", 0) * 0.08, 0.3);
S(N.revSend.gain, (d("reverb.size", 0) * 0.5 + d("master.space", 0) * 0.5) * 0.30, 0.3);
S(N.fb.gain, Math.min(0.55, d("delay.feedback", 0) * 0.6), 0.2);