Audio & SFX Design
pixelsp33d — audio plan (new file, 2026-08-02 — replaces the earlier note, which suggested using real audio clips for “I am the boss” lines. Dropped.
Status
[done] Gameplay SFX — procedurally synthesized from scratch, no source material, no licensing to track. tools/make_sfx.py generates 14 chiptune-style WAVs into assets/gen/sfx/, wired into the engine via src/engine/audio.ts and triggered from src/main.ts:
- jump - rising pulse-wave sweep, on takeoff
- land - low thud + noise burst, on landing
- collect - two-note blip, ordinary food pickups
- collect_dropchicken - light double-cluck, the harmless half
of the egg-dish pair (Lidl Lunch)
- collect_speed - ascending 3-note run, River Cola / speed tier
- collect_powerup - richer chime, uervel knight
- hurt - descending buzz + crunch, obstacle hit
- defeat_enemy - ascending zap, knight defeats a poison egg
- goal - whistle trill + fanfare, Soccer's footballGoal
(walked up to directly, or a well-aimed kick)
- kick - snappy impact, Soccer's soccerBall
- portal_enter - descending warp sweep, stepping into the Underworld
- portal_exit - ascending warp sweep (mirror of the above), climbing back out
- chest_open - wooden creak + a bright sparkle, Underworld treasure trove
- level_complete - short victory fanfare, boss reached
Verified in a headless-Chrome playthrough: SFX preload/decode and
every trigger path run with zero console errors.
[done] Level background music — also procedurally synthesized, same “no source material, no licensing” reasoning as the SFX above. The original plan below (source a CC0/CC-BY track per level) turned out unnecessary: tools/make_music.py builds a real step-sequencer (note-name parsing, chord/bass/melody voices, optional kick/hihat) on the same numpy pulse/triangle/envelope approach as the SFX file, generating one genuine ~10-25s loop per level into assets/gen/music/, distinct in key/tempo/ instrumentation to match each level’s mood:
- Minigolf - breezy, relaxed major-key arpeggio, 100 BPM
- Lidl Lunch - upbeat, bouncy bass + kick/hat, 128 BPM
- Soccer - driving, pumping bassline, kick every beat, 142 BPM
- Tanzstunde - a genuine 3/4 waltz (oom-pah-pah), 132 BPM
- Above the Clouds - airy, sustained triangle-wave pads, no
percussion, 74 BPM
Loops natively (AudioBufferSourceNode.loop=true), crossfades
(~200ms) between tracks on level change, respects the same
gesture-gate the SFX system already needed (browsers block audio
until a click/keydown). A mute toggle (M key) exists - built to
audition new SFX against a quiet background, kept as an ordinary
player option.
[todo] Ambient / organic sounds — crowd cheer (Soccer level), footsteps, wind. Procedural synthesis is a worse fit than real recorded texture for these. Plan is Freesound.org (mixed CC0/CC-BY, check per file) or Kenney.nl audio packs (CC0, already retro-styled — may also fit some SFX better than my synth pass once tried).
[todo] Narration — per-level lines, narrated by Moritz (alias pixelsp33d) in German. Not a library at all: captions are already wired per the technical plan (PLAN.md), audio slots are empty, and dropping in his recordings later is a data change, not a code change.
Open question
Do the synthesized SFX and music actually feel right once you hear them in context? First pass is a reasonable default tuning (durations, frequencies, decay, tempo) but easy to retune — tools/make_sfx.py and tools/make_music.py are both plain Python scripts, rerunning either after tweaking any number is cheap.