Contract: src/core/worlds.ts (three pocket worlds above the booth walls, portal/entry/exit anchors, stamp count) + additive world/stamp bus events. Briefs: SIDEB overview + WORLDS / MACHINES / SOCIAL(ambience) / AUDIO lanes, rescoped around the already-shipped SOCIAL_RESET (emotes, reset ritual, avatars) and first-five-minutes (heartbeat, beacons, flythrough) phases. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
3.5 KiB
SIDE B — Lane E2: per-world grooves + SIDE B sound
Read docs/briefs/SIDEB.md + src/core/worlds.ts first. You own
src/audio/**. React to bus events only. The main booth groove/stems
engine is yours already — extend, don't fork.
A1. World grooves (the big one)
On world:enter {world}: duck the booth mix out (300 ms) and start that
world's loop; on world:exit: reverse. Same synth toolkit (synth.ts), same
shrunk-time BPM feel. Keep each loop 2–4 bars, hypnotic, mixable levels.
- acid: 118 BPM, four-on-floor kick + off-hat, and THE 303: a 16-step
sawtooth acid line through a resonant lowpass (Q high) + accent/slide feel.
The line's filter cutoff is driven by three bands mapped to
fader:move {faderId:'acid_0'|'acid_1'|'acid_2'}(0..1 from Lane M's pedestals): 0 = detuned/wrong (cutoff badly off per-band offsets), target ≈ band's sweet value (Lane M owns the targets; you just map value→cutoff smoothly so sweeping is AUDIBLE and finding the sweet spot is satisfying — add a subtle "lock shimmer" layer per locked band viamachine:interact {action:'acid_lock'}). On stamp: the full line + a clap layer for 4 bars of glory. - dub: 74 BPM half-time — deep sub bassline, sparse rimshot skank on the
2/4 through a feedback echo (delay ~3/8, feedback 0.55, highcut) and a
spring-reverb boing patch.
machine:interact {action:'dub_feed'}= the big SPROING (bandpassed noise burst into the echo, feedback momentarily 0.8). While carrying the charge (Lane M emitsmachine:interact {action:'dub_pickup'|'dub_drop'}): the echo wet rises — you carry the wet. - disco: 122 BPM — four-on-floor, octave bass, offbeat open hat, a little
string stab loop.
machine:interact {action:'disco_cue', index}= per-tile cue blip (pitch by index, pentatonic); player steps echo the blip a fifth down. Stamp = filtered-disco string swell.
A2. SIDE B SFX + stem tie-ins
- Portal:
world:enterwhoosh-drop (pitch dive + vinyl slow-down effect),world:exitreverse spin-up. stamp:got: press-stamp THUNK + one-shot fanfare in that world's key.stamp:all: golden riser; then permanently add a bonus percussion stem (shaker/conga layer) to the booth mix (new stem in the stems set, unmuted only when stamp:all has fired — persists via Lane M's synced stamp state; derive "all stamped" at boot by listening forstamp:gotcount===total or an initial re-emit — coordinate exact boot handshake in your handoff).machine:interact {action:'bunny_flee'}: a shy squeak (soft, quiet, rare).
Already shipped — coexist, don't rebuild: emote audio (airhorn etc.),
the reset ritual's power-down collapse, and the zero-repair HEARTBEAT
(commit caac3da) are live. World grooves must duck WHATEVER the booth is
playing — including the heartbeat pre-first-repair — and hand it back on
exit; verify entering a pocket in a dead booth and in a won booth both sound
right, and that a reset while you're inside a pocket doesn't wedge the mix
(the exit handback must re-evaluate booth state, not restore a stale snapshot).
Verify + handoff
Typecheck clean; extend demo-audio.html with a SIDE B panel (world
enter/exit buttons, the three acid faders, dub feed, disco cues, emote pops,
reset) and verify every path by ear + zero console errors in the demo AND a
real-game smoke (launch config turncraft-laneB port 5184 if free).
Handoff: docs/SIDEB_E2_handoff.md incl. any events you need Lane M to emit
that aren't listed here (coordinate via handoff, not by editing their code).