🌊 Juno-106 chorus — the whole synth, warmer and wider

The safest, highest-value vintage borrow: an always-on subtle BBD-style chorus
on the master bus — two short delays each warbled by its own slow LFO, panned
wide, ~0.3 wet. Universally warms and widens the dry oscillators; can't sound
bad, can't error. Parallel send off `post`, chorusWet exposed for future
world-modulation. Verified: graph builds clean on synth start, no errors.

(FM mode, supersaw, and the 12-bit bitcrush are the next step — deferred to a
listening pass since they reshape core timbre and want real ears to tune, not
a backgrounded preview tab.)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
type-two 2026-07-10 00:48:33 +10:00
parent 75dbe81749
commit 1938874707

View File

@ -6627,6 +6627,27 @@
post.connect(glitch); glitch.connect(out); post.connect(delSend); post.connect(revSend);
post.connect(echoIn); // the mix onto the Earth Echo tape
// ---- Juno-106-style BBD chorus — two short delays, each warbled by its own
// slow LFO and panned wide. Always gently on, so the dry oscillators sound
// warm and stereo. The single best-value vintage borrow: universally widens
// the mix and can't sound bad. World-modulatable via chorusWet if wanted. ----
const chorusWet = ctx.createGain(); chorusWet.gain.value = 0.3;
const chIn = ctx.createGain(); chIn.gain.value = 1;
const chD1 = ctx.createDelay(0.05); chD1.delayTime.value = 0.017;
const chD2 = ctx.createDelay(0.05); chD2.delayTime.value = 0.023;
const chLfo1 = ctx.createOscillator(); chLfo1.frequency.value = 0.62;
const chLfo2 = ctx.createOscillator(); chLfo2.frequency.value = 0.47;
const chDep1 = ctx.createGain(); chDep1.gain.value = 0.0038; // ±3.8 ms warble
const chDep2 = ctx.createGain(); chDep2.gain.value = 0.0044;
const chPanL = ctx.createStereoPanner(); chPanL.pan.value = -0.75;
const chPanR = ctx.createStereoPanner(); chPanR.pan.value = 0.75;
chLfo1.connect(chDep1); chDep1.connect(chD1.delayTime);
chLfo2.connect(chDep2); chDep2.connect(chD2.delayTime);
chIn.connect(chD1); chD1.connect(chPanL); chPanL.connect(chorusWet);
chIn.connect(chD2); chD2.connect(chPanR); chPanR.connect(chorusWet);
chorusWet.connect(out); post.connect(chIn);
chLfo1.start(); chLfo2.start();
lfo = ctx.createOscillator(); lfo.frequency.value = 0.2;
const lfoAmt = ctx.createGain(); lfoAmt.gain.value = 260; lfo.connect(lfoAmt);
@ -6681,7 +6702,7 @@
lfo.start();
return { out, preSat, glitch, revSend, fb, satDry, satWet, leadOsc, leadFilt, leadAmp,
bassOsc, bassAmp, padOscs, padFilt, padAmp, droneOscs, droneAmp,
echoDelay, echoFilt, echoFb, echoWet, echoFlutAmt, hissGain };
echoDelay, echoFilt, echoFb, echoWet, echoFlutAmt, hissGain, chorusWet };
}
function hit(node, peak, dec) { // pluck envelope