TURNCRAFT/docs/briefs/SIDEB_AUDIO.md
type-two 758e9dc4d3 SIDE B briefs + contracts: crate worlds, per-world quests, stamps
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>
2026-08-16 14:55:12 +10:00

3.5 KiB
Raw Permalink Blame History

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 24 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 via machine: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 emits machine: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:enter whoosh-drop (pitch dive + vinyl slow-down effect), world:exit reverse 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 for stamp:got count===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).