group2 0.1.0
CSE 125 Group 2
Loading...
Searching...
No Matches
SfxSystem.hpp
Go to the documentation of this file.
1
8
9#pragma once
10
11#include "AudioMath.hpp"
12#include "AudioRuntime.hpp"
13#include "SfxTypes.hpp"
17
18#include <SDL3/SDL.h>
19
20#include <array>
21#include <cstddef>
22#include <cstdint>
23#include <mutex>
24#include <span>
25#include <string>
26#include <unordered_map>
27#include <vector>
28
30{
31 std::uint64_t sourcesStarted = 0;
32 std::uint64_t droppedByCooldown = 0;
33 std::uint64_t droppedByLimit = 0;
34 std::uint64_t stolenSources = 0;
35 std::uint64_t virtualizedFrames = 0;
36};
37
50{
51public:
52 using SourceHandle = std::uint32_t;
53 static constexpr SourceHandle kInvalidSource = 0;
54
57 bool init();
58
60 void update(float dt);
61
65 void update(float dt, const Registry& registry);
66
68 void quit();
69
74 void handleEvent(const SDL_Event& event);
75
79 void play(SfxId id, float gain = 1.0f);
80 SourceHandle play2D(SfxId id, float gain = 1.0f, float priority = 1.0f);
81 SourceHandle playUi(UiSoundAction action, float gain = 1.0f);
83 const glm::vec3& position,
84 const glm::vec3& velocity = glm::vec3{0.0f},
85 float gain = 1.0f,
86 float priority = 1.0f);
88 bool positional = false,
89 const glm::vec3& position = glm::vec3{0.0f},
90 float gain = 1.0f,
91 float priority = 1.0f);
92 void updateSource(SourceHandle handle,
93 const glm::vec3& position,
94 const glm::vec3& velocity = glm::vec3{0.0f},
95 float gain = 1.0f);
96 void stopSource(SourceHandle handle);
97 void playMusic(SfxId id, float gain = 1.0f);
98 void stopMusic();
99 void setListener(const audio::ListenerState& listener);
100 void setAudioObjectTransform(audio::AudioObjectId object,
101 const glm::vec3& position,
102 const glm::vec3& velocity = glm::vec3{0.0f});
103 void removeAudioObject(audio::AudioObjectId object);
104 void setAudioRtpc(audio::AudioObjectId object, audio::RtpcId rtpc, float value);
105 void setAudioSwitch(audio::AudioObjectId object, audio::SwitchGroupId group, audio::SwitchValueId value);
106 void setAudioState(audio::StateGroupId group, audio::StateValueId value);
107 void setAudioBusVolume(audio::AudioBusId bus, float volume);
108 bool reloadAudioManifest();
110 postAudioEvent(std::string_view eventName, audio::AudioObjectId object = audio::kGlobalObject, float gain = 1.0f);
111 SourceHandle postLocalAudioEvent(std::string_view eventName,
112 audio::AudioObjectId object = audio::kGlobalObject,
113 float gain = 1.0f);
114 void submitVoiceFrame(ClientId speaker,
115 std::uint16_t sequence,
116 std::span<const float> monoPcm48k,
117 const glm::vec3& position,
118 const glm::vec3& velocity = glm::vec3{0.0f});
119
121 void stop(SfxId id);
122
123 // --- Volume control ---
124 void setMasterVolume(float v) { masterVolume_ = v; }
125 void setCategoryVolume(SfxCategory cat, float v);
126 void setPlaybackDeviceName(std::string_view name);
127 float masterVolume() const { return masterVolume_; }
128 float categoryVolume(SfxCategory cat) const;
129
130 // --- entt::dispatcher event handlers ---
131 void onWeaponFired(const WeaponFiredEvent& e);
132 void onExplosion(const ExplosionEvent& e);
133
135 bool isInitialized() const { return device_ != 0; }
136 [[nodiscard]] const audio::AudioRuntime& audioRuntime() const noexcept { return audioRuntime_; }
137 [[nodiscard]] const audio::AudioRuntimeStats& audioStats() const noexcept { return audioRuntime_.stats(); }
138 [[nodiscard]] const SfxRuntimeStats& sfxStats() const noexcept { return sfxStats_; }
139 [[nodiscard]] float clipDuration(SfxId id) const noexcept;
140 [[nodiscard]] std::uint32_t activeSourceCount() const noexcept;
141 [[nodiscard]] std::uint32_t activeVoiceSourceCount() const noexcept;
142
143private:
144 SDL_AudioDeviceID device_ = 0;
145 SDL_AudioDeviceID physicalDeviceId_ = 0;
146 SDL_AudioStream* mixStream_ = nullptr;
147 SDL_AudioSpec mixerSpec_{};
148
149 std::array<SoundClip, static_cast<size_t>(SfxId::_Count)> clips_;
150
151 struct Source
152 {
153 bool active = false;
154 bool loop = false;
155 bool positional = false;
156 bool voiceStream = false;
160 float cursor = 0.0f;
161 float gain = 1.0f;
162 float priority = 1.0f;
164 float busGain = 1.0f;
165 std::uint16_t maxInstances = 0;
166 std::uint16_t maxBusInstances = 0;
169 float age = 0.0f;
170 float lowPassStateL = 0.0f;
171 float lowPassStateR = 0.0f;
172 std::uint16_t newestVoiceSeq = 0;
173 bool hasVoiceSeq = false;
174 bool occluded = false;
175 glm::vec3 position{0.0f};
176 glm::vec3 velocity{0.0f};
177 std::vector<float> voicePcm;
178 std::size_t voiceReadFrame = 0;
179 };
180 static constexpr int kMaxSources = 64;
181 static constexpr std::size_t kMaxVoiceQueuedFrames = 48000 / 2; // 500 ms per speaker.
182 std::array<Source, kMaxSources> sources_{};
184 std::unordered_map<int, SourceHandle> voiceSources_;
187
188 float masterVolume_ = 0.8f;
189 std::array<float, static_cast<size_t>(SfxCategory::_Count)> categoryVolumes_{};
192 std::string manifestPath_;
195 std::array<float, 48000> reverbDelayL_{};
196 std::array<float, 48000> reverbDelayR_{};
197 std::size_t reverbWrite_ = 0;
198 float deathMuffleTarget_ = 0.0f;
199 float deathMuffleAmount_ = 0.0f;
200 float deathMuffleStateL_ = 0.0f;
201 float deathMuffleStateR_ = 0.0f;
202 mutable std::mutex mixerMutex_;
203
205 std::array<float, static_cast<size_t>(SfxId::_Count)> cooldowns_{};
206 std::array<float, static_cast<size_t>(UiSoundAction::_Count)> uiActionCooldowns_{};
207 std::array<std::size_t, static_cast<size_t>(UiSoundAction::_Count)> uiActionVariantCursors_{};
208
209 // --- Client-side state tracking for event detection ---
210 float prevHealth_ = 100.0f;
211 float prevArmor_ = 100.0f;
212 int prevDeaths_ = 0;
213 int prevKills_ = 0;
216 std::unordered_map<entt::entity, float> prevGrenadeCooldowns_;
217 std::unordered_map<entt::entity, bool> knownFireFields_;
219 bool stateInitialized_ = false;
220
221 bool pendingReopen_ = false;
222
224 bool loadClip(SfxId id, const char* filename, SfxCategory cat, float gain, float cooldownSecs);
225
226 Source* acquireSource(float priority,
227 SfxId id = SfxId::_Count,
229 std::uint16_t maxInstances = 0,
230 std::uint16_t maxBusInstances = 0);
234 bool positional,
235 bool loop,
236 const glm::vec3& position,
237 const glm::vec3& velocity,
238 float gain,
239 float priority,
241 float busGain,
242 std::uint16_t maxInstances,
243 std::uint16_t maxBusInstances,
244 float cooldownOverrideSeconds = -1.0f,
245 float fullGainDistance = audio::k_fullGainDistance,
246 float silentDistance = audio::k_silentDistance);
248
250 float effectiveGain(SfxId id, float extraGain) const;
251 void convertClipToMixer(SoundClip& clip, const char* debugName);
252 void synthesizeClip(SfxId id, SfxCategory cat, float gain, float cooldownSecs);
253 bool isOccluded(const glm::vec3& position) const;
254 static void mixCallback(void* userdata, SDL_AudioStream* stream, int additionalAmount, int totalAmount);
255 void mixIntoStream(SDL_AudioStream* stream, int additionalAmount);
256
259 bool openDevice();
260
262 void reopenDevice();
263
268 void warmUpDevice();
269
270 void convertClipsToMixer();
271};
Pure helpers for spatial audio attenuation, panning, Doppler, and occlusion.
Wwise-like data-driven audio runtime definitions and resolver.
Network client identifier component for multiplayer entities.
Event structs dispatched via entt::dispatcher for particle spawning.
Shared ECS registry type alias for the game engine.
entt::registry Registry
Shared ECS registry type alias.
Definition Registry.hpp:11
Sound effect identifiers, categories, and the SoundClip data type.
SfxId
Identifies a loaded sound clip.
Definition SfxTypes.hpp:16
@ _Count
Definition SfxTypes.hpp:118
SfxCategory
Sound category for per-category volume control.
Definition SfxTypes.hpp:140
@ _Count
Definition SfxTypes.hpp:148
UiSoundAction
Semantic menu/UI sound actions.
Definition SfxTypes.hpp:123
@ _Count
Definition SfxTypes.hpp:135
Client-side sound effects system.
Definition SfxSystem.hpp:50
int prevKills_
Definition SfxSystem.hpp:213
void setMasterVolume(float v)
Definition SfxSystem.hpp:124
audio::AudioRuntime audioRuntime_
Definition SfxSystem.hpp:190
void setAudioState(audio::StateGroupId group, audio::StateValueId value)
Definition SfxSystem.cpp:558
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)
Definition SfxSystem.cpp:1217
bool init()
Initialise SDL audio subsystem, open default playback device, load all clips.
Definition SfxSystem.cpp:223
bool pendingReopen_
Set by handleEvent(), processed at the start of update().
Definition SfxSystem.hpp:221
void updateSource(SourceHandle handle, const glm::vec3 &position, const glm::vec3 &velocity=glm::vec3{0.0f}, float gain=1.0f)
Definition SfxSystem.cpp:452
void quit()
Destroy active sources, close the audio device, quit audio subsystem.
Definition SfxSystem.cpp:380
std::array< float, static_cast< size_t >(UiSoundAction::_Count)> uiActionCooldowns_
Definition SfxSystem.hpp:206
SourceHandle play3D(SfxId id, const glm::vec3 &position, const glm::vec3 &velocity=glm::vec3{0.0f}, float gain=1.0f, float priority=1.0f)
Definition SfxSystem.cpp:441
void setCategoryVolume(SfxCategory cat, float v)
Definition SfxSystem.cpp:667
float categoryVolume(SfxCategory cat) const
Definition SfxSystem.cpp:682
SourceHandle startLoop(SfxId id, bool positional=false, const glm::vec3 &position=glm::vec3{0.0f}, float gain=1.0f, float priority=1.0f)
Definition SfxSystem.cpp:447
static constexpr int kMaxSources
Definition SfxSystem.hpp:180
const audio::AudioRuntimeStats & audioStats() const noexcept
Definition SfxSystem.hpp:137
std::array< Source, kMaxSources > sources_
Definition SfxSystem.hpp:182
SourceHandle nextSourceHandle_
Definition SfxSystem.hpp:183
std::string manifestPath_
Definition SfxSystem.hpp:192
void removeAudioObject(audio::AudioObjectId object)
Definition SfxSystem.cpp:543
float healingSoundCooldown_
Throttle the looping heal tick sound.
Definition SfxSystem.hpp:218
SourceHandle postAudioEvent(std::string_view eventName, audio::AudioObjectId object=audio::kGlobalObject, float gain=1.0f)
Definition SfxSystem.cpp:581
std::array< float, 48000 > reverbDelayL_
Definition SfxSystem.hpp:195
std::unordered_map< entt::entity, bool > knownFireFields_
Definition SfxSystem.hpp:217
void play(SfxId id, float gain=1.0f)
Play a sound immediately.
Definition SfxSystem.cpp:403
void setAudioBusVolume(audio::AudioBusId bus, float volume)
Definition SfxSystem.cpp:563
const SfxRuntimeStats & sfxStats() const noexcept
Definition SfxSystem.hpp:138
void onExplosion(const ExplosionEvent &e)
Definition SfxSystem.cpp:722
SourceHandle play2D(SfxId id, float gain=1.0f, float priority=1.0f)
Definition SfxSystem.cpp:408
SDL_AudioDeviceID physicalDeviceId_
Logical device ID we opened (for event matching).
Definition SfxSystem.hpp:145
const audio::AudioRuntime & audioRuntime() const noexcept
Definition SfxSystem.hpp:136
SDL_AudioSpec mixerSpec_
Definition SfxSystem.hpp:147
std::string playbackDeviceName_
Definition SfxSystem.hpp:193
bool reloadAudioManifest()
Definition SfxSystem.cpp:568
std::uint32_t activeSourceCount() const noexcept
Definition SfxSystem.cpp:1514
std::array< std::size_t, static_cast< size_t >(UiSoundAction::_Count)> uiActionVariantCursors_
Definition SfxSystem.hpp:207
std::mutex mixerMutex_
Definition SfxSystem.hpp:202
void setAudioObjectTransform(audio::AudioObjectId object, const glm::vec3 &position, const glm::vec3 &velocity=glm::vec3{0.0f})
Definition SfxSystem.cpp:536
float clipDuration(SfxId id) const noexcept
Definition SfxSystem.cpp:1534
bool prevLocalReloading_
Definition SfxSystem.hpp:214
SfxId currentMusic_
Definition SfxSystem.hpp:186
void stopSource(SourceHandle handle)
Definition SfxSystem.cpp:466
SourceHandle postLocalAudioEvent(std::string_view eventName, audio::AudioObjectId object=audio::kGlobalObject, float gain=1.0f)
Definition SfxSystem.cpp:593
float deathMuffleStateR_
Definition SfxSystem.hpp:201
std::array< float, 48000 > reverbDelayR_
Definition SfxSystem.hpp:196
std::unordered_map< int, SourceHandle > voiceSources_
Definition SfxSystem.hpp:184
void setPlaybackDeviceName(std::string_view name)
Definition SfxSystem.cpp:672
void handleEvent(const SDL_Event &event)
Forward SDL audio-device events so the system can handle hot-swap.
Definition SfxSystem.cpp:729
float deathMuffleAmount_
Definition SfxSystem.hpp:199
void reopenDevice()
Tear down all active voices/streams, close the device, then reopen.
Definition SfxSystem.cpp:1339
float masterVolume_
Definition SfxSystem.hpp:188
SfxRuntimeStats sfxStats_
Definition SfxSystem.hpp:191
float deathMuffleTarget_
Definition SfxSystem.hpp:198
std::uint32_t SourceHandle
Definition SfxSystem.hpp:52
static void mixCallback(void *userdata, SDL_AudioStream *stream, int additionalAmount, int totalAmount)
Definition SfxSystem.cpp:1374
bool prevLocalRailgunCharging_
Definition SfxSystem.hpp:215
void setAudioSwitch(audio::AudioObjectId object, audio::SwitchGroupId group, audio::SwitchValueId value)
Definition SfxSystem.cpp:553
void setListener(const audio::ListenerState &listener)
Definition SfxSystem.cpp:526
static constexpr SourceHandle kInvalidSource
Definition SfxSystem.hpp:53
void update(float dt)
Per-frame update: decrement cooldowns and retire finished voices.
Definition SfxSystem.cpp:745
Source * acquireSource(float priority, SfxId id=SfxId::_Count, audio::AudioBusId bus=audio::kInvalidBus, std::uint16_t maxInstances=0, std::uint16_t maxBusInstances=0)
Definition SfxSystem.cpp:1120
Source * findSource(SourceHandle handle)
Definition SfxSystem.cpp:1193
void convertClipToMixer(SoundClip &clip, const char *debugName)
Definition SfxSystem.cpp:1084
bool stateInitialized_
Skip sounds on the very first update().
Definition SfxSystem.hpp:219
void playMusic(SfxId id, float gain=1.0f)
Definition SfxSystem.cpp:483
void stopMusic()
Definition SfxSystem.cpp:518
audio::ListenerState listener_
Definition SfxSystem.hpp:194
std::unordered_map< entt::entity, float > prevGrenadeCooldowns_
Definition SfxSystem.hpp:216
Source * findVoiceSource(ClientId speaker)
Definition SfxSystem.cpp:1204
void onWeaponFired(const WeaponFiredEvent &e)
Definition SfxSystem.cpp:687
std::size_t reverbWrite_
Definition SfxSystem.hpp:197
std::array< SoundClip, static_cast< size_t >(SfxId::_Count)> clips_
Definition SfxSystem.hpp:149
SourceHandle playUi(UiSoundAction action, float gain=1.0f)
Definition SfxSystem.cpp:414
SourceHandle musicHandle_
Definition SfxSystem.hpp:185
std::uint32_t activeVoiceSourceCount() const noexcept
Definition SfxSystem.cpp:1524
int prevDeaths_
Definition SfxSystem.hpp:212
static constexpr std::size_t kMaxVoiceQueuedFrames
Definition SfxSystem.hpp:181
void mixIntoStream(SDL_AudioStream *stream, int additionalAmount)
Definition SfxSystem.cpp:1380
float prevArmor_
Definition SfxSystem.hpp:211
void convertClipsToMixer()
Definition SfxSystem.cpp:1108
float masterVolume() const
Definition SfxSystem.hpp:127
std::array< float, static_cast< size_t >(SfxCategory::_Count)> categoryVolumes_
Definition SfxSystem.hpp:189
float prevHealth_
Definition SfxSystem.hpp:210
void setAudioRtpc(audio::AudioObjectId object, audio::RtpcId rtpc, float value)
Definition SfxSystem.cpp:548
SourceHandle playCommand(const audio::AudioCommand &command)
Definition SfxSystem.cpp:1278
SDL_AudioStream * mixStream_
Single SDL stream that receives our mixed stereo output.
Definition SfxSystem.hpp:146
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})
Definition SfxSystem.cpp:605
bool isOccluded(const glm::vec3 &position) const
Definition SfxSystem.cpp:1306
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].
Definition SfxSystem.cpp:913
bool openDevice()
Open a specific physical playback device (macOS) or the default (other platforms).
Definition SfxSystem.cpp:1316
float effectiveGain(SfxId id, float extraGain) const
master × category × clip × extraGain.
Definition SfxSystem.cpp:1300
void synthesizeClip(SfxId id, SfxCategory cat, float gain, float cooldownSecs)
Definition SfxSystem.cpp:986
SDL_AudioDeviceID device_
Logical playback device (0 = not initialised).
Definition SfxSystem.hpp:144
void stop(SfxId id)
Stop all active voices playing the given sound.
Definition SfxSystem.cpp:655
float deathMuffleStateL_
Definition SfxSystem.hpp:200
bool isInitialized() const
True after a successful init().
Definition SfxSystem.hpp:135
void warmUpDevice()
Push a tiny silent buffer to force AudioQueue buffer pre-allocation.
Definition SfxSystem.cpp:1364
std::array< float, static_cast< size_t >(SfxId::_Count)> cooldowns_
Per-SfxId countdown to next allowed play (seconds remaining).
Definition SfxSystem.hpp:205
Definition AudioRuntime.hpp:310
constexpr float k_fullGainDistance
Definition AudioMath.hpp:14
constexpr AudioObjectId kGlobalObject
Definition AudioRuntime.hpp:84
constexpr AudioBusId kInvalidBus
Definition AudioRuntime.hpp:85
constexpr float k_silentDistance
Definition AudioMath.hpp:15
Definition AudioRuntime.hpp:365
Associates an entity with a connected network client.
Definition ClientId.hpp:10
Emitted when a rocket/grenade explodes.
Definition ParticleEvents.hpp:34
Definition SfxSystem.hpp:30
std::uint64_t droppedByLimit
Definition SfxSystem.hpp:33
std::uint64_t virtualizedFrames
Definition SfxSystem.hpp:35
std::uint64_t droppedByCooldown
Definition SfxSystem.hpp:32
std::uint64_t sourcesStarted
Definition SfxSystem.hpp:31
std::uint64_t stolenSources
Definition SfxSystem.hpp:34
Definition SfxSystem.hpp:152
float fullGainDistance
Definition SfxSystem.hpp:167
float age
Definition SfxSystem.hpp:169
float lowPassStateL
Definition SfxSystem.hpp:170
SfxId playingId
Which sound this voice is playing.
Definition SfxSystem.hpp:157
bool positional
Definition SfxSystem.hpp:155
bool hasVoiceSeq
Definition SfxSystem.hpp:173
float cursor
Definition SfxSystem.hpp:160
float priority
Definition SfxSystem.hpp:162
float silentDistance
Definition SfxSystem.hpp:168
std::size_t voiceReadFrame
Definition SfxSystem.hpp:178
float gain
Definition SfxSystem.hpp:161
SourceHandle handle
Definition SfxSystem.hpp:158
std::uint16_t maxBusInstances
Definition SfxSystem.hpp:166
float busGain
Definition SfxSystem.hpp:164
glm::vec3 position
Definition SfxSystem.hpp:175
ClientId speaker
Definition SfxSystem.hpp:159
std::uint16_t maxInstances
Definition SfxSystem.hpp:165
audio::AudioBusId bus
Definition SfxSystem.hpp:163
bool occluded
Definition SfxSystem.hpp:174
bool voiceStream
Definition SfxSystem.hpp:156
float lowPassStateR
Definition SfxSystem.hpp:171
bool active
Definition SfxSystem.hpp:153
std::vector< float > voicePcm
Definition SfxSystem.hpp:177
glm::vec3 velocity
Definition SfxSystem.hpp:176
bool loop
Definition SfxSystem.hpp:154
std::uint16_t newestVoiceSeq
Definition SfxSystem.hpp:172
A decoded sound clip ready for playback.
Definition SfxTypes.hpp:153
Emitted when a weapon fires (both hitscan and projectile).
Definition ParticleEvents.hpp:13
Definition AudioRuntime.hpp:43
Definition AudioRuntime.hpp:240
Definition AudioRuntime.hpp:266
Definition AudioMath.hpp:18