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 <cstdint>
22#include <mutex>
23#include <span>
24#include <string>
25#include <unordered_map>
26#include <vector>
27
29{
30 std::uint64_t sourcesStarted = 0;
31 std::uint64_t droppedByCooldown = 0;
32 std::uint64_t droppedByLimit = 0;
33 std::uint64_t stolenSources = 0;
34 std::uint64_t virtualizedFrames = 0;
35};
36
49{
50public:
51 using SourceHandle = std::uint32_t;
52 static constexpr SourceHandle kInvalidSource = 0;
53
56 bool init();
57
61 void update(float dt, const Registry& registry);
62
64 void quit();
65
70 void handleEvent(const SDL_Event& event);
71
75 void play(SfxId id, float gain = 1.0f);
76 SourceHandle play2D(SfxId id, float gain = 1.0f, float priority = 1.0f);
78 const glm::vec3& position,
79 const glm::vec3& velocity = glm::vec3{0.0f},
80 float gain = 1.0f,
81 float priority = 1.0f);
83 bool positional = false,
84 const glm::vec3& position = glm::vec3{0.0f},
85 float gain = 1.0f,
86 float priority = 1.0f);
87 void updateSource(SourceHandle handle,
88 const glm::vec3& position,
89 const glm::vec3& velocity = glm::vec3{0.0f},
90 float gain = 1.0f);
91 void stopSource(SourceHandle handle);
92 void setListener(const audio::ListenerState& listener);
93 void setAudioObjectTransform(audio::AudioObjectId object,
94 const glm::vec3& position,
95 const glm::vec3& velocity = glm::vec3{0.0f});
96 void removeAudioObject(audio::AudioObjectId object);
97 void setAudioRtpc(audio::AudioObjectId object, audio::RtpcId rtpc, float value);
98 void setAudioSwitch(audio::AudioObjectId object, audio::SwitchGroupId group, audio::SwitchValueId value);
99 void setAudioState(audio::StateGroupId group, audio::StateValueId value);
100 void setAudioBusVolume(audio::AudioBusId bus, float volume);
101 bool reloadAudioManifest();
103 postAudioEvent(std::string_view eventName, audio::AudioObjectId object = audio::kGlobalObject, float gain = 1.0f);
104 SourceHandle postLocalAudioEvent(std::string_view eventName,
105 audio::AudioObjectId object = audio::kGlobalObject,
106 float gain = 1.0f);
107 void submitVoiceFrame(ClientId speaker,
108 std::uint16_t sequence,
109 std::span<const float> monoPcm48k,
110 const glm::vec3& position,
111 const glm::vec3& velocity = glm::vec3{0.0f});
112
114 void stop(SfxId id);
115
116 // --- Volume control ---
117 void setMasterVolume(float v) { masterVolume_ = v; }
118 void setCategoryVolume(SfxCategory cat, float v);
119 float masterVolume() const { return masterVolume_; }
120 float categoryVolume(SfxCategory cat) const;
121
122 // --- entt::dispatcher event handlers ---
123 void onWeaponFired(const WeaponFiredEvent& e);
124 void onExplosion(const ExplosionEvent& e);
125
127 bool isInitialized() const { return device_ != 0; }
128 [[nodiscard]] const audio::AudioRuntime& audioRuntime() const noexcept { return audioRuntime_; }
129 [[nodiscard]] const audio::AudioRuntimeStats& audioStats() const noexcept { return audioRuntime_.stats(); }
130 [[nodiscard]] const SfxRuntimeStats& sfxStats() const noexcept { return sfxStats_; }
131 [[nodiscard]] std::uint32_t activeSourceCount() const noexcept;
132 [[nodiscard]] std::uint32_t activeVoiceSourceCount() const noexcept;
133
134private:
135 SDL_AudioDeviceID device_ = 0;
136 SDL_AudioDeviceID physicalDeviceId_ = 0;
137 SDL_AudioStream* mixStream_ = nullptr;
138 SDL_AudioSpec mixerSpec_{};
139
140 std::array<SoundClip, static_cast<size_t>(SfxId::_Count)> clips_;
141
142 struct Source
143 {
144 bool active = false;
145 bool loop = false;
146 bool positional = false;
147 bool voiceStream = false;
151 float cursor = 0.0f;
152 float gain = 1.0f;
153 float priority = 1.0f;
155 float busGain = 1.0f;
156 std::uint16_t maxInstances = 0;
157 std::uint16_t maxBusInstances = 0;
160 float age = 0.0f;
161 float lowPassStateL = 0.0f;
162 float lowPassStateR = 0.0f;
163 std::uint16_t newestVoiceSeq = 0;
164 bool hasVoiceSeq = false;
165 bool occluded = false;
166 glm::vec3 position{0.0f};
167 glm::vec3 velocity{0.0f};
168 std::vector<float> voicePcm;
169 std::size_t voiceReadFrame = 0;
170 };
171 static constexpr int kMaxSources = 64;
172 static constexpr std::size_t kMaxVoiceQueuedFrames = 48000 / 2; // 500 ms per speaker.
173 std::array<Source, kMaxSources> sources_{};
175 std::unordered_map<int, SourceHandle> voiceSources_;
176
177 float masterVolume_ = 0.8f;
178 std::array<float, static_cast<size_t>(SfxCategory::_Count)> categoryVolumes_{};
181 std::string manifestPath_;
183 std::array<float, 48000> reverbDelayL_{};
184 std::array<float, 48000> reverbDelayR_{};
185 std::size_t reverbWrite_ = 0;
186 mutable std::mutex mixerMutex_;
187
189 std::array<float, static_cast<size_t>(SfxId::_Count)> cooldowns_{};
190
191 // --- Client-side state tracking for event detection ---
192 float prevHealth_ = 100.0f;
193 float prevArmor_ = 100.0f;
194 int prevDeaths_ = 0;
195 int prevKills_ = 0;
197 bool stateInitialized_ = false;
198
199 bool pendingReopen_ = false;
200
202 bool loadClip(SfxId id, const char* filename, SfxCategory cat, float gain, float cooldownSecs);
203
204 Source* acquireSource(float priority,
205 SfxId id = SfxId::_Count,
207 std::uint16_t maxInstances = 0,
208 std::uint16_t maxBusInstances = 0);
212 bool positional,
213 bool loop,
214 const glm::vec3& position,
215 const glm::vec3& velocity,
216 float gain,
217 float priority,
219 float busGain,
220 std::uint16_t maxInstances,
221 std::uint16_t maxBusInstances,
222 float cooldownOverrideSeconds = -1.0f,
223 float fullGainDistance = audio::k_fullGainDistance,
224 float silentDistance = audio::k_silentDistance);
226
228 float effectiveGain(SfxId id, float extraGain) const;
229 void convertClipToMixer(SoundClip& clip, const char* debugName);
230 void synthesizeClip(SfxId id, SfxCategory cat, float gain, float cooldownSecs);
231 bool isOccluded(const glm::vec3& position) const;
232 static void mixCallback(void* userdata, SDL_AudioStream* stream, int additionalAmount, int totalAmount);
233 void mixIntoStream(SDL_AudioStream* stream, int additionalAmount);
234
237 bool openDevice();
238
240 void reopenDevice();
241
246 void warmUpDevice();
247
248 void convertClipsToMixer();
249};
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:89
SfxCategory
Sound category for per-category volume control.
Definition SfxTypes.hpp:94
@ _Count
Definition SfxTypes.hpp:101
Client-side sound effects system.
Definition SfxSystem.hpp:49
int prevKills_
Definition SfxSystem.hpp:195
void setMasterVolume(float v)
Definition SfxSystem.hpp:117
audio::AudioRuntime audioRuntime_
Definition SfxSystem.hpp:179
void setAudioState(audio::StateGroupId group, audio::StateValueId value)
Definition SfxSystem.cpp:286
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:835
bool init()
Initialise SDL audio subsystem, open default playback device, load all clips.
Definition SfxSystem.cpp:68
bool pendingReopen_
Set by handleEvent(), processed at the start of update().
Definition SfxSystem.hpp:199
void updateSource(SourceHandle handle, const glm::vec3 &position, const glm::vec3 &velocity=glm::vec3{0.0f}, float gain=1.0f)
Definition SfxSystem.cpp:227
void quit()
Destroy active sources, close the audio device, quit audio subsystem.
Definition SfxSystem.cpp:183
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:216
void setCategoryVolume(SfxCategory cat, float v)
Definition SfxSystem.cpp:394
float categoryVolume(SfxCategory cat) const
Definition SfxSystem.cpp:399
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:222
static constexpr int kMaxSources
Definition SfxSystem.hpp:171
const audio::AudioRuntimeStats & audioStats() const noexcept
Definition SfxSystem.hpp:129
std::array< Source, kMaxSources > sources_
Definition SfxSystem.hpp:173
SourceHandle nextSourceHandle_
Definition SfxSystem.hpp:174
std::string manifestPath_
Definition SfxSystem.hpp:181
void removeAudioObject(audio::AudioObjectId object)
Definition SfxSystem.cpp:271
float healingSoundCooldown_
Throttle the looping heal tick sound.
Definition SfxSystem.hpp:196
SourceHandle postAudioEvent(std::string_view eventName, audio::AudioObjectId object=audio::kGlobalObject, float gain=1.0f)
Definition SfxSystem.cpp:309
std::array< float, 48000 > reverbDelayL_
Definition SfxSystem.hpp:183
void play(SfxId id, float gain=1.0f)
Play a sound immediately.
Definition SfxSystem.cpp:204
void setAudioBusVolume(audio::AudioBusId bus, float volume)
Definition SfxSystem.cpp:291
const SfxRuntimeStats & sfxStats() const noexcept
Definition SfxSystem.hpp:130
void onExplosion(const ExplosionEvent &e)
Definition SfxSystem.cpp:435
SourceHandle play2D(SfxId id, float gain=1.0f, float priority=1.0f)
Definition SfxSystem.cpp:209
SDL_AudioDeviceID physicalDeviceId_
Logical device ID we opened (for event matching).
Definition SfxSystem.hpp:136
const audio::AudioRuntime & audioRuntime() const noexcept
Definition SfxSystem.hpp:128
SDL_AudioSpec mixerSpec_
Definition SfxSystem.hpp:138
bool reloadAudioManifest()
Definition SfxSystem.cpp:296
std::uint32_t activeSourceCount() const noexcept
Definition SfxSystem.cpp:1120
std::mutex mixerMutex_
Definition SfxSystem.hpp:186
void setAudioObjectTransform(audio::AudioObjectId object, const glm::vec3 &position, const glm::vec3 &velocity=glm::vec3{0.0f})
Definition SfxSystem.cpp:264
void stopSource(SourceHandle handle)
Definition SfxSystem.cpp:241
SourceHandle postLocalAudioEvent(std::string_view eventName, audio::AudioObjectId object=audio::kGlobalObject, float gain=1.0f)
Definition SfxSystem.cpp:321
std::array< float, 48000 > reverbDelayR_
Definition SfxSystem.hpp:184
std::unordered_map< int, SourceHandle > voiceSources_
Definition SfxSystem.hpp:175
void handleEvent(const SDL_Event &event)
Forward SDL audio-device events so the system can handle hot-swap.
Definition SfxSystem.cpp:442
void update(float dt, const Registry &registry)
Per-frame update: decrement cooldowns, retire finished voices, detect state changes.
Definition SfxSystem.cpp:458
void reopenDevice()
Tear down all active voices/streams, close the device, then reopen.
Definition SfxSystem.cpp:956
float masterVolume_
Definition SfxSystem.hpp:177
SfxRuntimeStats sfxStats_
Definition SfxSystem.hpp:180
std::uint32_t SourceHandle
Definition SfxSystem.hpp:51
static void mixCallback(void *userdata, SDL_AudioStream *stream, int additionalAmount, int totalAmount)
Definition SfxSystem.cpp:991
void setAudioSwitch(audio::AudioObjectId object, audio::SwitchGroupId group, audio::SwitchValueId value)
Definition SfxSystem.cpp:281
void setListener(const audio::ListenerState &listener)
Definition SfxSystem.cpp:254
static constexpr SourceHandle kInvalidSource
Definition SfxSystem.hpp:52
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:738
Source * findSource(SourceHandle handle)
Definition SfxSystem.cpp:811
void convertClipToMixer(SoundClip &clip, const char *debugName)
Definition SfxSystem.cpp:702
bool stateInitialized_
Skip sounds on the very first update().
Definition SfxSystem.hpp:197
audio::ListenerState listener_
Definition SfxSystem.hpp:182
Source * findVoiceSource(ClientId speaker)
Definition SfxSystem.cpp:822
void onWeaponFired(const WeaponFiredEvent &e)
Definition SfxSystem.cpp:404
std::size_t reverbWrite_
Definition SfxSystem.hpp:185
std::array< SoundClip, static_cast< size_t >(SfxId::_Count)> clips_
Definition SfxSystem.hpp:140
std::uint32_t activeVoiceSourceCount() const noexcept
Definition SfxSystem.cpp:1130
int prevDeaths_
Definition SfxSystem.hpp:194
static constexpr std::size_t kMaxVoiceQueuedFrames
Definition SfxSystem.hpp:172
void mixIntoStream(SDL_AudioStream *stream, int additionalAmount)
Definition SfxSystem.cpp:997
float prevArmor_
Definition SfxSystem.hpp:193
void convertClipsToMixer()
Definition SfxSystem.cpp:726
float masterVolume() const
Definition SfxSystem.hpp:119
std::array< float, static_cast< size_t >(SfxCategory::_Count)> categoryVolumes_
Definition SfxSystem.hpp:178
float prevHealth_
Definition SfxSystem.hpp:192
void setAudioRtpc(audio::AudioObjectId object, audio::RtpcId rtpc, float value)
Definition SfxSystem.cpp:276
SourceHandle playCommand(const audio::AudioCommand &command)
Definition SfxSystem.cpp:896
SDL_AudioStream * mixStream_
Single SDL stream that receives our mixed stereo output.
Definition SfxSystem.hpp:137
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:333
bool isOccluded(const glm::vec3 &position) const
Definition SfxSystem.cpp:924
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:531
bool openDevice()
Open a specific physical playback device (macOS) or the default (other platforms).
Definition SfxSystem.cpp:934
float effectiveGain(SfxId id, float extraGain) const
master × category × clip × extraGain.
Definition SfxSystem.cpp:918
void synthesizeClip(SfxId id, SfxCategory cat, float gain, float cooldownSecs)
Definition SfxSystem.cpp:604
SDL_AudioDeviceID device_
Logical playback device (0 = not initialised).
Definition SfxSystem.hpp:135
void stop(SfxId id)
Stop all active voices playing the given sound.
Definition SfxSystem.cpp:382
bool isInitialized() const
True after a successful init().
Definition SfxSystem.hpp:127
void warmUpDevice()
Push a tiny silent buffer to force AudioQueue buffer pre-allocation.
Definition SfxSystem.cpp:981
std::array< float, static_cast< size_t >(SfxId::_Count)> cooldowns_
Per-SfxId countdown to next allowed play (seconds remaining).
Definition SfxSystem.hpp:189
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:29
std::uint64_t droppedByLimit
Definition SfxSystem.hpp:32
std::uint64_t virtualizedFrames
Definition SfxSystem.hpp:34
std::uint64_t droppedByCooldown
Definition SfxSystem.hpp:31
std::uint64_t sourcesStarted
Definition SfxSystem.hpp:30
std::uint64_t stolenSources
Definition SfxSystem.hpp:33
Definition SfxSystem.hpp:143
float fullGainDistance
Definition SfxSystem.hpp:158
float age
Definition SfxSystem.hpp:160
float lowPassStateL
Definition SfxSystem.hpp:161
SfxId playingId
Which sound this voice is playing.
Definition SfxSystem.hpp:148
bool positional
Definition SfxSystem.hpp:146
bool hasVoiceSeq
Definition SfxSystem.hpp:164
float cursor
Definition SfxSystem.hpp:151
float priority
Definition SfxSystem.hpp:153
float silentDistance
Definition SfxSystem.hpp:159
std::size_t voiceReadFrame
Definition SfxSystem.hpp:169
float gain
Definition SfxSystem.hpp:152
SourceHandle handle
Definition SfxSystem.hpp:149
std::uint16_t maxBusInstances
Definition SfxSystem.hpp:157
float busGain
Definition SfxSystem.hpp:155
glm::vec3 position
Definition SfxSystem.hpp:166
ClientId speaker
Definition SfxSystem.hpp:150
std::uint16_t maxInstances
Definition SfxSystem.hpp:156
audio::AudioBusId bus
Definition SfxSystem.hpp:154
bool occluded
Definition SfxSystem.hpp:165
bool voiceStream
Definition SfxSystem.hpp:147
float lowPassStateR
Definition SfxSystem.hpp:162
bool active
Definition SfxSystem.hpp:144
std::vector< float > voicePcm
Definition SfxSystem.hpp:168
glm::vec3 velocity
Definition SfxSystem.hpp:167
bool loop
Definition SfxSystem.hpp:145
std::uint16_t newestVoiceSeq
Definition SfxSystem.hpp:163
A decoded sound clip ready for playback.
Definition SfxTypes.hpp:106
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