Enable sound with the speaker button. Escape → Make yourself comfortable → Set your sound opens overall, ambience and traveler-footstep levels. Levels survive reload; playback always requires a new explicit gesture. Menus, chat, focus loss and graphics recovery use the player's pause path to silence the mix. Resuming restores the chosen levels.
The house fireplace and garden water have positional sound. Turning changes their stereo direction; walking away reduces their level, with a smooth fade to silence at their authored radius. Garden wind provides a quiet nonspatial bed. Nearby moving travelers and Mara have footsteps following the renderer's displayed poses. Idle, airborne, stalled, distant or removed actors stop producing footsteps. These are procedural loops, not yet animation-contact events or final recorded sound design.
#Engine contract
packages/audio owns a reusable Web Audio graph, with independent master, music, ambience, dialogue and effects gains. It accepts game-supplied mono PCM clips and frame-sampled listener/emitter data. It has no game, DOM, storage or room dependency. The caller owns the context, user gesture and lifecycle. The player creates one context lazily, shares an in-flight resume and checks current mute/disposal state after that resume resolves.
Limits: eight clips, thirty seconds each, 16 MiB total PCM, 24 active voices. Clip data is copied into native buffers. Validation precedes graph mutation. Listener axes must be orthonormal; levels, positions, radius, IDs, clip references and duplicates are checked. Stable emitters retain their source and panner. Departing emitters stop and disconnect; disposal clears all voices, buffers and graph connections. The mixer uses equal-power stereo panning, inverse distance attenuation, and an explicit smooth range cutoff. This initial slice does not include occlusion, reverb zones, streaming clips, shared-clock music, decoded asset import or recorded dialogue.
Game-authored sound loops and place mapping live in games/darkwind/sound.ts. The player feeds the same camera orientation used by rendering and the renderer's sampled remote/NPC actor poses. There is no audio-frame network stream and no world/save/protocol change. Sound preferences live at darkwind:audio:v1, independently of saved games. Invalid preferences use defaults; failed preference writes keep the session usable.
#Acceptance
The diagnostics page's Check spatial sound runs real OfflineAudioContext rendering without speaker playback. It measures channel energy for left/right positioning and near/far attenuation, exact silence for pause/mute/effects-bus mute/range cutoff/removal, stable voice reuse, atomic invalid-frame rejection and disposal. A separate browser journey exercises explicit activation, pause/resume, independent saved volume levels and reload without autoplay. Headless contract checks cover malformed data, bounded crowds, pose eligibility and deterministic loop assets.
Automated signal checks establish functionality, not a subjective headphone review. Final sound design and the deferred character-art redesign remain open.