|
| bool | init () |
| | Initialise SDL audio subsystem, open default playback device, load all clips.
|
| void | update (float dt) |
| | Per-frame update: decrement cooldowns and retire finished voices.
|
| void | update (float dt, const Registry ®istry) |
| | Per-frame update: decrement cooldowns, retire finished voices, detect state changes.
|
| void | quit () |
| | Destroy active sources, close the audio device, quit audio subsystem.
|
| void | handleEvent (const SDL_Event &event) |
| | Forward SDL audio-device events so the system can handle hot-swap.
|
| void | play (SfxId id, float gain=1.0f) |
| | Play a sound immediately.
|
| SourceHandle | play2D (SfxId id, float gain=1.0f, float priority=1.0f) |
| SourceHandle | playUi (UiSoundAction action, float gain=1.0f) |
| SourceHandle | play3D (SfxId id, const glm::vec3 &position, const glm::vec3 &velocity=glm::vec3{0.0f}, float gain=1.0f, float priority=1.0f) |
| SourceHandle | startLoop (SfxId id, bool positional=false, const glm::vec3 &position=glm::vec3{0.0f}, float gain=1.0f, float priority=1.0f) |
| void | updateSource (SourceHandle handle, const glm::vec3 &position, const glm::vec3 &velocity=glm::vec3{0.0f}, float gain=1.0f) |
| void | stopSource (SourceHandle handle) |
| void | playMusic (SfxId id, float gain=1.0f) |
| void | stopMusic () |
| void | setListener (const audio::ListenerState &listener) |
| void | setAudioObjectTransform (audio::AudioObjectId object, const glm::vec3 &position, const glm::vec3 &velocity=glm::vec3{0.0f}) |
| void | removeAudioObject (audio::AudioObjectId object) |
| void | setAudioRtpc (audio::AudioObjectId object, audio::RtpcId rtpc, float value) |
| void | setAudioSwitch (audio::AudioObjectId object, audio::SwitchGroupId group, audio::SwitchValueId value) |
| void | setAudioState (audio::StateGroupId group, audio::StateValueId value) |
| void | setAudioBusVolume (audio::AudioBusId bus, float volume) |
| bool | reloadAudioManifest () |
| SourceHandle | postAudioEvent (std::string_view eventName, audio::AudioObjectId object=audio::kGlobalObject, float gain=1.0f) |
| SourceHandle | postLocalAudioEvent (std::string_view eventName, audio::AudioObjectId object=audio::kGlobalObject, float gain=1.0f) |
| void | submitVoiceFrame (ClientId speaker, std::uint16_t sequence, std::span< const float > monoPcm48k, const glm::vec3 &position, const glm::vec3 &velocity=glm::vec3{0.0f}) |
| void | stop (SfxId id) |
| | Stop all active voices playing the given sound.
|
| void | setMasterVolume (float v) |
| void | setCategoryVolume (SfxCategory cat, float v) |
| void | setPlaybackDeviceName (std::string_view name) |
| float | masterVolume () const |
| float | categoryVolume (SfxCategory cat) const |
| void | onWeaponFired (const WeaponFiredEvent &e) |
| void | onExplosion (const ExplosionEvent &e) |
| bool | isInitialized () const |
| | True after a successful init().
|
| const audio::AudioRuntime & | audioRuntime () const noexcept |
| const audio::AudioRuntimeStats & | audioStats () const noexcept |
| const SfxRuntimeStats & | sfxStats () const noexcept |
| float | clipDuration (SfxId id) const noexcept |
| std::uint32_t | activeSourceCount () const noexcept |
| std::uint32_t | activeVoiceSourceCount () const noexcept |
|
| bool | loadClip (SfxId id, const char *filename, SfxCategory cat, float gain, float cooldownSecs) |
| | Decode a single MP3 from assets/sounds/ and store it as clip[id].
|
| Source * | acquireSource (float priority, SfxId id=SfxId::_Count, audio::AudioBusId bus=audio::kInvalidBus, std::uint16_t maxInstances=0, std::uint16_t maxBusInstances=0) |
| Source * | findSource (SourceHandle handle) |
| Source * | findVoiceSource (ClientId speaker) |
| SourceHandle | startSource (SfxId id, bool positional, bool loop, const glm::vec3 &position, const glm::vec3 &velocity, float gain, float priority, audio::AudioBusId bus, float busGain, std::uint16_t maxInstances, std::uint16_t maxBusInstances, float cooldownOverrideSeconds=-1.0f, float fullGainDistance=audio::k_fullGainDistance, float silentDistance=audio::k_silentDistance) |
| SourceHandle | playCommand (const audio::AudioCommand &command) |
| float | effectiveGain (SfxId id, float extraGain) const |
| | master × category × clip × extraGain.
|
| void | convertClipToMixer (SoundClip &clip, const char *debugName) |
| void | synthesizeClip (SfxId id, SfxCategory cat, float gain, float cooldownSecs) |
| bool | isOccluded (const glm::vec3 &position) const |
| void | mixIntoStream (SDL_AudioStream *stream, int additionalAmount) |
| bool | openDevice () |
| | Open a specific physical playback device (macOS) or the default (other platforms).
|
| void | reopenDevice () |
| | Tear down all active voices/streams, close the device, then reopen.
|
| void | warmUpDevice () |
| | Push a tiny silent buffer to force AudioQueue buffer pre-allocation.
|
| void | convertClipsToMixer () |
|
| SDL_AudioDeviceID | device_ = 0 |
| | Logical playback device (0 = not initialised).
|
| SDL_AudioDeviceID | physicalDeviceId_ = 0 |
| | Logical device ID we opened (for event matching).
|
| SDL_AudioStream * | mixStream_ = nullptr |
| | Single SDL stream that receives our mixed stereo output.
|
| SDL_AudioSpec | mixerSpec_ {} |
| std::array< SoundClip, static_cast< size_t >(SfxId::_Count)> | clips_ |
| std::array< Source, kMaxSources > | sources_ {} |
| SourceHandle | nextSourceHandle_ = 1 |
| std::unordered_map< int, SourceHandle > | voiceSources_ |
| SourceHandle | musicHandle_ = kInvalidSource |
| SfxId | currentMusic_ = SfxId::_Count |
| float | masterVolume_ = 0.8f |
| std::array< float, static_cast< size_t >(SfxCategory::_Count)> | categoryVolumes_ {} |
| audio::AudioRuntime | audioRuntime_ |
| SfxRuntimeStats | sfxStats_ {} |
| std::string | manifestPath_ |
| std::string | playbackDeviceName_ |
| audio::ListenerState | listener_ {} |
| std::array< float, 48000 > | reverbDelayL_ {} |
| std::array< float, 48000 > | reverbDelayR_ {} |
| std::size_t | reverbWrite_ = 0 |
| float | deathMuffleTarget_ = 0.0f |
| float | deathMuffleAmount_ = 0.0f |
| float | deathMuffleStateL_ = 0.0f |
| float | deathMuffleStateR_ = 0.0f |
| std::mutex | mixerMutex_ |
| std::array< float, static_cast< size_t >(SfxId::_Count)> | cooldowns_ {} |
| | Per-SfxId countdown to next allowed play (seconds remaining).
|
| std::array< float, static_cast< size_t >(UiSoundAction::_Count)> | uiActionCooldowns_ {} |
| std::array< std::size_t, static_cast< size_t >(UiSoundAction::_Count)> | uiActionVariantCursors_ {} |
| float | prevHealth_ = 100.0f |
| float | prevArmor_ = 100.0f |
| int | prevDeaths_ = 0 |
| int | prevKills_ = 0 |
| bool | prevLocalReloading_ = false |
| bool | prevLocalRailgunCharging_ = false |
| std::unordered_map< entt::entity, float > | prevGrenadeCooldowns_ |
| std::unordered_map< entt::entity, bool > | knownFireFields_ |
| float | healingSoundCooldown_ = 0.0f |
| | Throttle the looping heal tick sound.
|
| bool | stateInitialized_ = false |
| | Skip sounds on the very first update().
|
| bool | pendingReopen_ = false |
| | Set by handleEvent(), processed at the start of update().
|
Client-side sound effects system.
All audio is local to the client — the server never drives sounds directly. Weapon-fire SFX hook into the existing WeaponFiredEvent on the dispatcher. Health/death/kill changes are detected by comparing previous-frame state in update(), because the server's handleDeath() immediately calls handleRespawn() in the same tick so IsDead never survives to a registry sync.
On macOS, device hot-swap (e.g. plugging/unplugging headphones) is handled via SDL_EVENT_AUDIO_DEVICE_REMOVED / ADDED events which trigger a graceful reopen of the default playback device.