Audio
Audio (src/Engine/Audio/) is fully event-driven on top of SDL2_mixer. An AudioSystem is registered automatically at window creation, so in game code you only ever send events — no setup, no handles to manage.
Playing sounds
#include "Audio/audiosystem.h"
// music: one stream, loops = -1 means forever
ecsRef->sendEvent(StartAudio{"res/audio/music.ogg", -1});
ecsRef->sendEvent(StopAudio{});
ecsRef->sendEvent(PauseAudio{});
ecsRef->sendEvent(ResumeAudio{});
// sound effects: loops = 0 means play once, channel = -1 means first free channel
ecsRef->sendEvent(PlaySoundEffect{"res/audio/hit.ogg"});
ecsRef->sendEvent(PlaySoundEffect{"res/audio/rain.ogg", /*loops*/ 3, /*channel*/ 2});
// volume: floats in 0.0 - 1.0; effective volume is master x (music | sfx)
ecsRef->sendEvent(SetMasterVolume{0.8f});
ecsRef->sendEvent(SetMusicVolume{0.3f});
ecsRef->sendEvent(SetSoundEffectsVolume{0.6f});
PgScript gets the same surface via the audio module: playAudio, stopAudio, pauseAudio, resumeAudio, playSoundEffect.
The model
Music is a single stream (
Mix_Music); starting a new track frees the previous one. Not cached.Sound effects play on mixing channels — 6 by default (
AudioSystem::setNumberOfChannelto change). If every channel is busy, the effect is silently skipped, not queued — size your channel count for your worst-case burst.Effect chunks are cached by path after first load, so repeated
PlaySoundEffectevents are cheap. First play of a large file does disk IO — consider firing a muted play at load time if that matters.PlaySoundEffectis processed as a queued event (in the audio system’s own frame slot); the others are handled at event-drain time.Device: opened at 96 kHz with a 1024-sample buffer. OGG and WAV are the safe formats (MP3 support depends on the SDL2_mixer build —
Mix_Init(MIX_INIT_MP3)is currently not called).
Volumes default to master 1.0, music 0.1, sfx 0.1 — turn them up in your init if things sound quiet.
Platform notes
Emscripten: same API, same constants; paths get the leading
/like all web asset paths ("/res/audio/hit.ogg"). Browsers block audio until the first user gesture — start music from a click/keypress, not frominit().Shutdown ordering (engine programmers): the
AudioSystemis owned by the ECS, butcloseSDLMixer()must run beforedelete ecs— the window teardown does this ordering on purpose (see the comment inwindow.cpp); reproduce it in any custom shutdown path or ASan will flag a use-after-free.
Current limitations
No spatial/positional audio, no mixing graph or effects bus, no crossfades — the surface is deliberately small. For a jam game: one music stream + cached one-shot effects covers the standard needs; anything fancier is game code today.