Skip to content

Sound Effects — Audit & Phased Build-Out Plan

Sound Effects — Audit & Phased Build-Out Plan

Section titled “Sound Effects — Audit & Phased Build-Out Plan”

Date: 2026-07-01 Status: Design — awaiting review Goal: Take audio from “one placeholder sound bolted onto every event” to a full, distinct, mixed soundscape (SFX + music) across weapons, enemies, bosses, player events, and UI — with a living document that always shows what’s implemented vs. still silent.


Audio was added in a single commit (30e5ca7) that reused chess-defense’s SFX files as placeholders. A full codebase audit (2026-07-01) found:

  • 11 of 17 shipped .wav files are actually loaded; 6 are dead weight (attack, enemy_hit, special_aegis, special_freeze, special_rally, wave_clear — never referenced).
  • Every weapon fire event is silent. All 6 weapons (base + 7 evolutions) emit an fx_events kind (bolt/beam/slash/nova) or nothing at all (Orbit/Turret/Scatter emit no fx kind whatsoever, visual or audio), and none is mapped to a sound.
  • Every boss telegraph/attack that has any sound at all shares the exact same one (special_barrage.wav) — Warden’s barrage/spiral, Boss2’s cutter/artillery/rings/charge/summon, FunZo’s dash/enrage, Graviton’s singularity, The Eye’s blink — all sonically identical, and identical to a routine mid-combat elemental reaction proc.
  • Two events double-sound (two unrelated sounds fire together in the same tick): weapon pickup (pickup + named reaction) and the NUKE powerup (special_stomp + trailing generic pickup).
  • special_freeze.wav sits unused while the FREEZE powerup plays the generic ui_tap.wav pickup sound instead.
  • ui_nav()/ui_buy() are fully implemented but have zero call sites anywhere — no menu, panel, or shop in the game makes UI sound.
  • No audio bus layout — everything hardcoded to the Master bus, no SFX/Music/UI separation, no volume controls, no ducking.
  • No music anywhere in the shipped game (a marketing trailer theme exists in marketing/audio/ but is not wired into the runtime).
  • No platform gatingAudioManager runs unconditionally on all platforms, relying on Godot’s dummy audio driver being a safe no-op headless/in CI. This has been fine because every sound to date is a short one-shot; untested for looping/long-duration audio (relevant once Phase 5 adds music).

Full call-site-by-call-site detail lives in audio/SOUND_MAP.md (§2 below) — this spec captures decisions and phasing, the map is the living inventory.


2. The living audit document — audio/SOUND_MAP.md

Section titled “2. The living audit document — audio/SOUND_MAP.md”

A permanent, git-tracked markdown file, organized into sections that mirror the phase plan below (Weapons / Enemies / Bosses / Player / UI / Music / Mixing-Infra). Updated in place every time a sound is added or changed — this repo’s equivalent of the Design Bible being the source of truth for content, but for audio state.

Row schema per event:

Column Meaning
Event The gameplay thing that should make sound (e.g. “Pulse fire”, “Charger dash release”)
Trigger fx_events kind, or the discrete method/call site, with file:line
Sound file Which .wav plays today, or
Status See vocabulary below
Sound type needed Closed taxonomy, see below
Notes Anything that affects sourcing/wiring (e.g. “evolution should layer, not replace”)

Status vocabulary:

  • SILENT — no sound at all
  • GENERIC — plays, but shares a sound with unrelated events (e.g. every boss telegraph today)
  • MISWIRED — plays the wrong/mismatched sound while a better-fitting unused asset exists (e.g. FREEZE powerup)
  • DOUBLE — two sounds fire for one event
  • DONE — distinct, correct sound

Sound type taxonomy (closed vocabulary, used consistently when sourcing from sample packs): impact · zap-cast · whoosh-cast · explosion · drone-ambient · telegraph-cue · ui-feedback · music-stinger · music-loop.

This document is populated now (as part of this spec’s delivery) from the full codebase audit, and gets a status update at the end of every phase below.


Each phase is scoped as one self-contained bh-dev-chunk cycle (TDD → boot-check → determinism-reverify → commit → tvOS-sync), matching how every other content cycle in this project has shipped. Audio is render-side only (AudioManager extends Node, no /sim involvement), so determinism re-verification in every phase is expected to be a no-op confirmation, not a real risk.

  1. Foundation & fixes — no new content, fixes what’s broken:

    • Audio bus layout: Master → {SFX, Music, UI}.
    • Fix the weapon-pickup and NUKE double-sounds (skip the generic pickup emit when a named special-case already covers the same event).
    • Wire special_freeze.wav to the FREEZE powerup.
    • Decide fate of the 6 dead .wav files (repurpose or delete).
    • Add explicit platform-gate parity check (confirm the “dummy driver is safe” assumption still holds; no code change expected unless it doesn’t).
  2. Weapon fire sounds — the single biggest silent gap. 6 base weapons get a distinct fire sound; 7 evolutions layer/intensify rather than replace (matching the existing “power grows, doesn’t replace” balance philosophy). Orbit/Turret/Scatter need a new fx_events kind added first (they currently emit none, audio or visual) — same shape as the cycle-10 “invisible entity” fix.

  3. Enemy & boss distinct sounds — universal enemy telegraph cues (dash charge/release, ranged-attack fire) currently 100% silent; each boss’s 3-5 attacks gets its own sound instead of sharing one. FunZo zone-creation/jester-spawn/confetti need a new fx_events kind first (same gap as Orbit/Turret/Scatter).

  4. UI sound — wire the already-built ui_nav()/ui_buy() into start_menu.gd / level_up_panel.gd / meta_shop_panel.gd / pause_menu.gd; add new hooks for any remaining gaps (panel open/close).

  5. Music — menu theme, survival loop, 4 story-region themes, boss stinger, victory/defeat. Largest asset-sourcing lift; done last since it’s independent of the SFX work. First place to explicitly verify looping-audio behavior on tvOS (see platform note above) rather than assume it.

Phase 1 gets its own implementation plan doc (docs/superpowers/plans/) next, per this project’s brainstorming → writing-plans flow. Phases 2-5 each get their own plan doc when their turn comes, scoped against whatever SOUND_MAP.md still shows as SILENT/GENERIC at that time.


  • Sourcing: licensed sample packs (Chris’s choice over AI-generation or keeping placeholders). Each SOUND_MAP.md row’s “sound type needed” column makes picking from a pack a lookup, not a re-analysis. Specific pack/license selection happens per-phase, not in this spec.
  • Format: stay on .wav (matches all 17 existing files, simplest for the current AudioStreamPlayer pool). No format standardization forced if a pack only ships .ogg/.mp3 — Godot imports either.
  • Platform: no new gating needed for SFX (existing no-gate approach holds). Music (Phase 5) is the one place to explicitly verify tvOS looping/long-duration behavior, since it’s the first time this class of audio exists in the game.
  • Testing: extend tests/test_audio_manager.gd per phase (e.g. “every weapon fire kind has a SOUND_FOR_FX entry”, “no fx kind double-fires two sounds”) — no new test framework needed.

  • Picking specific sample packs or license terms — a sourcing task inside each content phase, not a design decision.
  • Spatial/3D audio (panning by world position) — not requested, current game has no stereo-relevant camera behavior that would benefit.
  • A player-facing volume settings screen — mixing infra (Phase 1) adds the buses; exposing a UI slider is a separate, smaller follow-up if Chris wants one after playing with the bus levels.