OHAO · Implementation Monograph

Monograph · 10 · Audio

10

Systems · full depth

Audio

Chapter contract

miniaudio behind a small facade: init, SoundCategory buses, spatial vs non-spatial play, listener = camera, volume product, handle lifecycle. Aligned with audio_system.hpp.

Initialize / shutdown

AudioSystem::initialize
  1. If already initialized, return true
  2. new ma_engine + ma_engine_config_init
  3. ma_engine_init — on failure log code and return false
  4. Store unique_ptr with custom deleter → ma_engine_uninit
  5. m_initialized = true

Shutdown stops sounds, clears map, resets engine. Uninitialized play APIs return INVALID_SOUND_HANDLE (0).

SoundCategory buses

EnumIndexUse
SoundCategory::SFX0One-shots
SoundCategory::Music1Looping score
SoundCategory::Ambient2Spatial beds

Helpers: soundCategoryName, isValidSoundCategory. Convenience: playSfx, playMusic (loop default true), playAmbientAt.

playSound workflow

Non-spatial
  1. Guard path + initialized
  2. ma_sound_init_from_file
  3. ma_sound_set_spatialization_enabled(false)
  4. Loop flag; volume; start
  5. Insert into handle map; return handle

playSoundAt workflow

Spatial
  1. Init from file; enable spatialization
  2. Set position; min distance 1; max 50; inverse attenuation model
  3. Loop/volume; start; store handle
  4. Update with setSoundPosition if emitter moves

Listener sync

setListenerPosition(pos, forward, up)ma_engine_listener_set_* on listener 0. Call every frame from camera. Godot host docs: synced automatically.

Why camera = ears

Spatial audio without matching viewpoint feels “wrong room” even when emitter coordinates are correct.

Volume product

\[ g=g_{\mathrm{master}}\cdot g_{\mathrm{SoundCategory}}\cdot g_{\mathrm{voice}}\in[0,1] \]

Clamped buses let users mute Music without killing SFX.

Handles & bulk ops

SoundHandle = uint32; 0 invalid. stop/pause/resume/setVolume/isPlaying/activeSoundCount. Bulk: stop category, pause category, stop all. Facade never returns raw ma_sound* — deleters live in .cpp with full miniaudio types (header only forward-declares).

Design

Forward-declare ma_engine

miniaudio header is huge; keep includes out of engine-wide headers.

audio_system.hppSoundCategory · API
audio_system.cppma_* calls
docs/audio.mdHost/GDScript
tests/audio/*Unit tests

Design units in this module

Each card is a focused design page (what / how / why + sources). Full tree: Sitemap.