From 4e07db47344a697a9cd3df4b94e1ac4aa2862500 Mon Sep 17 00:00:00 2001 From: themuffinator Date: Sun, 2 Nov 2025 14:54:02 +0000 Subject: [PATCH] Refactor sound system state management --- inc/client/sound/dma.hpp | 2 - src/client/sound/SoundSystem.cpp | 65 +++++++++++ src/client/sound/SoundSystem.hpp | 25 ++++ src/client/sound/al.cpp | 56 ++++----- src/client/sound/dma.cpp | 99 +++++++++------- src/client/sound/main.cpp | 195 +++++++++++++++++++------------ src/client/sound/mem.cpp | 5 +- src/client/sound/ogg.cpp | 43 ++++--- src/client/sound/sound.hpp | 7 -- src/windows/wave.cpp | 3 +- 10 files changed, 329 insertions(+), 171 deletions(-) diff --git a/inc/client/sound/dma.hpp b/inc/client/sound/dma.hpp index fca58c5..95bdfda 100644 --- a/inc/client/sound/dma.hpp +++ b/inc/client/sound/dma.hpp @@ -46,6 +46,4 @@ typedef struct { } snddma_driver_t; extern dma_t dma; -extern int s_paintedtime; - extern cvar_t *s_khz; diff --git a/src/client/sound/SoundSystem.cpp b/src/client/sound/SoundSystem.cpp index 2e53e23..6f76f74 100644 --- a/src/client/sound/SoundSystem.cpp +++ b/src/client/sound/SoundSystem.cpp @@ -54,6 +54,71 @@ void SoundSystem::increment_registration_sequence() ++registration_sequence_; } +SoundBackend SoundSystem::backend() const +{ + return backend_; +} + +void SoundSystem::set_backend(SoundBackend backend) +{ + backend_ = backend; +} + +const sndapi_t *SoundSystem::api() const +{ + return api_; +} + +void SoundSystem::set_api(const sndapi_t *api) +{ + api_ = api; +} + +bool SoundSystem::supports_float() const +{ + return supports_float_; +} + +void SoundSystem::set_supports_float(bool supports) +{ + supports_float_ = supports; +} + +bool SoundSystem::is_active() const +{ + return active_; +} + +void SoundSystem::set_active(bool active) +{ + active_ = active; +} + +bool SoundSystem::is_registering() const +{ + return registering_; +} + +void SoundSystem::set_registering(bool registering) +{ + registering_ = registering; +} + +int SoundSystem::painted_time() const +{ + return painted_time_; +} + +int &SoundSystem::painted_time() +{ + return painted_time_; +} + +void SoundSystem::set_painted_time(int time) +{ + painted_time_ = time; +} + sfx_t *SoundSystem::known_sfx_data() { return known_sfx_.data(); diff --git a/src/client/sound/SoundSystem.hpp b/src/client/sound/SoundSystem.hpp index 05b7fa6..c03b091 100644 --- a/src/client/sound/SoundSystem.hpp +++ b/src/client/sound/SoundSystem.hpp @@ -26,6 +26,21 @@ class SoundSystem { void reset_registration_sequence(); void increment_registration_sequence(); + SoundBackend backend() const; + void set_backend(SoundBackend backend); + + const sndapi_t *api() const; + void set_api(const sndapi_t *api); + + bool supports_float() const; + void set_supports_float(bool supports); + + bool is_active() const; + void set_active(bool active); + + bool is_registering() const; + void set_registering(bool registering); + sfx_t *known_sfx_data(); const sfx_t *known_sfx_data() const; int num_sfx() const; @@ -60,6 +75,10 @@ class SoundSystem { void StopAllSounds(); void Update(); + int painted_time() const; + int &painted_time(); + void set_painted_time(int time); + vec3_t &listener_origin(); vec3_t &listener_forward(); vec3_t &listener_right(); @@ -71,6 +90,12 @@ class SoundSystem { Config config_{}; unsigned registration_sequence_ = 1; + SoundBackend backend_ = SoundBackend::Not; + const sndapi_t *api_ = nullptr; + bool supports_float_ = false; + bool active_ = false; + bool registering_ = false; + int painted_time_ = 0; std::vector known_sfx_; int num_sfx_ = 0; std::vector channels_; diff --git a/src/client/sound/al.cpp b/src/client/sound/al.cpp index f5c4a19..bf6f338 100644 --- a/src/client/sound/al.cpp +++ b/src/client/sound/al.cpp @@ -654,7 +654,7 @@ static bool AL_Init(void) s_loop_points = qalIsExtensionPresent("AL_SOFT_loop_points"); s_source_spatialize = qalIsExtensionPresent("AL_SOFT_source_spatialize"); - s_supports_float = qalIsExtensionPresent("AL_EXT_float32"); + soundSystem.set_supports_float(qalIsExtensionPresent("AL_EXT_float32")); // init distance model qalDistanceModel(AL_LINEAR_DISTANCE_CLAMPED); @@ -765,7 +765,7 @@ static ALenum AL_GetSampleFormat(int width, int channels) case 2: return AL_FORMAT_MONO16 + (channels - 1) * 2; case 4: - if (!s_supports_float) + if (!S_GetSoundSystem().supports_float()) return 0; return AL_FORMAT_MONO_FLOAT32 + (channels - 1); default: @@ -832,7 +832,7 @@ static void AL_DeleteSfx(sfx_t *s) static int AL_GetBeginofs(float timeofs) { - return s_paintedtime + timeofs * 1000; + return S_GetSoundSystem().painted_time() + timeofs * 1000; } static void AL_Spatialize(channel_t *ch) @@ -957,7 +957,7 @@ static void AL_IssuePlaysounds(void) playsound_t *ps = soundSystem.PeekPendingPlay(); if (!ps) break; // no more pending sounds - if (ps->begin > s_paintedtime) + if (ps->begin > soundSystem.painted_time()) break; S_GetSoundSystem().IssuePlaysound(ps); } @@ -1012,6 +1012,7 @@ static void AL_MergeLoopSounds(void) sfxcache_t *sc; int num; entity_state_t *ent; + SoundSystem &soundSystem = S_GetSoundSystem(); vec3_t origin; if (!S_GetSoundSystem().BuildSoundList(sounds)) @@ -1021,7 +1022,7 @@ static void AL_MergeLoopSounds(void) if (!sounds[i]) continue; - sfx = S_GetSoundSystem().SfxForHandle(cl.sound_precache[sounds[i]]); + sfx = soundSystem.SfxForHandle(cl.sound_precache[sounds[i]]); if (!sfx) continue; // bad sound effect sc = sfx->cache; @@ -1042,9 +1043,9 @@ static void AL_MergeLoopSounds(void) VectorSubtract(origin, offset, base); CL_DebugTrail(base, origin); } - S_GetSoundSystem().SpatializeOrigin(origin, vol, att, - &left_total, &right_total, - S_GetEntityLoopStereoPan(ent)); + soundSystem.SpatializeOrigin(origin, vol, att, + &left_total, &right_total, + S_GetEntityLoopStereoPan(ent)); for (j = i + 1; j < cl.frame.numEntities; j++) { if (sounds[j] != sounds[i]) continue; @@ -1059,11 +1060,11 @@ static void AL_MergeLoopSounds(void) VectorSubtract(origin, offset, base); CL_DebugTrail(base, origin); } - S_GetSoundSystem().SpatializeOrigin(origin, - S_GetEntityLoopVolume(ent), - S_GetEntityLoopDistMult(ent), - &left, &right, - S_GetEntityLoopStereoPan(ent)); + soundSystem.SpatializeOrigin(origin, + S_GetEntityLoopVolume(ent), + S_GetEntityLoopDistMult(ent), + &left, &right, + S_GetEntityLoopStereoPan(ent)); left_total += left; right_total += right; } @@ -1084,16 +1085,16 @@ static void AL_MergeLoopSounds(void) qalSourcef(ch->srcnum, AL_GAIN, gain); qalSource3f(ch->srcnum, AL_POSITION, pan, 0.0f, pan2); ch->autoframe = s_framecount; - ch->end = s_paintedtime + sc->length; + ch->end = soundSystem.painted_time() + sc->length; continue; } // allocate a channel - ch = S_GetSoundSystem().PickChannel(0, 0); + ch = soundSystem.PickChannel(0, 0); if (!ch) continue; - channel_t *channels = S_GetSoundSystem().channels_data(); + channel_t *channels = soundSystem.channels_data(); if (channels) { ch->srcnum = s_srcnums[ch - channels]; } else { @@ -1116,7 +1117,7 @@ static void AL_MergeLoopSounds(void) ch->entnum = ent->number; ch->master_vol = vol; ch->dist_mult = att; - ch->end = s_paintedtime + sc->length; + ch->end = soundSystem.painted_time() + sc->length; // play it qalSourcePlay(ch->srcnum); @@ -1139,13 +1140,13 @@ static void AL_AddLoopSounds(void) if (cls.state != ca_active || sv_paused->integer || !s_ambient->integer) return; - S_GetSoundSystem().BuildSoundList(sounds); + soundSystem.BuildSoundList(sounds); for (i = 0; i < cl.frame.numEntities; i++) { if (!sounds[i]) continue; - sfx = S_GetSoundSystem().SfxForHandle(cl.sound_precache[sounds[i]]); + sfx = soundSystem.SfxForHandle(cl.sound_precache[sounds[i]]); if (!sfx) continue; // bad sound effect sc = sfx->cache; @@ -1158,12 +1159,12 @@ static void AL_AddLoopSounds(void) ch = AL_FindLoopingSound(ent->number, sfx); if (ch) { ch->autoframe = s_framecount; - ch->end = s_paintedtime + sc->length; + ch->end = soundSystem.painted_time() + sc->length; continue; } // allocate a channel - ch = S_GetSoundSystem().PickChannel(0, 0); + ch = soundSystem.PickChannel(0, 0); if (!ch) continue; @@ -1173,7 +1174,7 @@ static void AL_AddLoopSounds(void) ch->entnum = ent->number; ch->master_vol = S_GetEntityLoopVolume(ent); ch->dist_mult = S_GetEntityLoopDistMult(ent); - ch->end = s_paintedtime + sc->length; + ch->end = soundSystem.painted_time() + sc->length; AL_PlayChannel(ch); } @@ -1212,7 +1213,7 @@ static void AL_StreamPause(bool paused) s_stream_paused = paused; // force pause if not active - if (!s_active) + if (!S_GetSoundSystem().is_active()) paused = true; ALint state = 0; @@ -1311,14 +1312,15 @@ static void AL_Update(void) channel_t *channels = soundSystem.channels_data(); int num_channels = soundSystem.num_channels(); - if (!s_active) + if (!soundSystem.is_active()) return; // handle time wraparound. FIXME: get rid of this? i = cls.realtime & MASK(30); - if (i < s_paintedtime) - S_GetSoundSystem().StopAllSounds(); - s_paintedtime = i; + int &painted_time = soundSystem.painted_time(); + if (i < painted_time) + soundSystem.StopAllSounds(); + painted_time = i; // set listener parameters qalListener3f(AL_POSITION, AL_UnpackVector(listener_origin)); diff --git a/src/client/sound/dma.cpp b/src/client/sound/dma.cpp index ba05d82..b9e9a23 100644 --- a/src/client/sound/dma.cpp +++ b/src/client/sound/dma.cpp @@ -112,13 +112,15 @@ RAW SAMPLES static bool DMA_RawSamples(int samples, int rate, int width, int channels, const void *data, float volume) { + SoundSystem &soundSystem = S_GetSoundSystem(); float stepscale = (float)rate / dma.speed; int i, j, k, frac, fracstep = stepscale * 256; int outcount = samples / stepscale; float vol = snd_vol * volume; - if (s_rawend < s_paintedtime) - s_rawend = s_paintedtime; + const int painted_time = soundSystem.painted_time(); + if (s_rawend < painted_time) + s_rawend = painted_time; if (width == 4) { const float *src = (const float *)data; @@ -171,7 +173,7 @@ static bool DMA_RawSamples(int samples, int rate, int width, int channels, const static int DMA_HaveRawSamples(void) { - return Q_clip(s_rawend - s_paintedtime, 0, MAX_RAW_SAMPLES); + return Q_clip(s_rawend - S_GetSoundSystem().painted_time(), 0, MAX_RAW_SAMPLES); } static int DMA_NeedRawSamples(void) @@ -182,7 +184,7 @@ static int DMA_NeedRawSamples(void) static void DMA_DropRawSamples(void) { memset(s_rawsamples, 0, sizeof(s_rawsamples)); - s_rawend = s_paintedtime; + s_rawend = S_GetSoundSystem().painted_time(); } /* @@ -195,7 +197,7 @@ PAINTBUFFER TRANSFER static void TransferStereo16(const samplepair_t *samp, int endtime) { - int ltime = s_paintedtime; + int ltime = S_GetSoundSystem().painted_time(); int size = dma.samples >> 1; while (ltime < endtime) { @@ -216,10 +218,11 @@ static void TransferStereo16(const samplepair_t *samp, int endtime) static void TransferStereo(const samplepair_t *samp, int endtime) { + const int painted_time = S_GetSoundSystem().painted_time(); const float *p = (const float *)samp; - int count = (endtime - s_paintedtime) * dma.channels; + int count = (endtime - painted_time) * dma.channels; int out_mask = dma.samples - 1; - int out_idx = s_paintedtime * dma.channels & out_mask; + int out_idx = painted_time * dma.channels & out_mask; int step = 3 - dma.channels; int val; @@ -244,17 +247,18 @@ static void TransferStereo(const samplepair_t *samp, int endtime) static void TransferPaintBuffer(samplepair_t *samp, int endtime) { + const int painted_time = S_GetSoundSystem().painted_time(); int i; if (s_testsound->integer) { // write a fixed sine wave - for (i = 0; i < endtime - s_paintedtime; i++) { - samp[i].left = samp[i].right = sinf((s_paintedtime + i) * 0.1f) * 20000; + for (i = 0; i < endtime - painted_time; i++) { + samp[i].left = samp[i].right = sinf((painted_time + i) * 0.1f) * 20000; } } if (s_swapstereo->integer) { - for (i = 0; i < endtime - s_paintedtime; i++) { + for (i = 0; i < endtime - painted_time; i++) { SWAP(float, samp[i].left, samp[i].right); } } @@ -431,17 +435,18 @@ static void PaintChannels(int endtime) bool underwater = S_IsUnderWater(); SoundSystem &soundSystem = S_GetSoundSystem(); + int &painted_time = soundSystem.painted_time(); - while (s_paintedtime < endtime) { + while (painted_time < endtime) { // if paintbuffer is smaller than DMA buffer - int end = min(endtime, s_paintedtime + PAINTBUFFER_SIZE); + int end = min(endtime, painted_time + PAINTBUFFER_SIZE); // start any playsounds while (1) { playsound_t *ps = soundSystem.PeekPendingPlay(); if (!ps) break; // no more pending sounds - if (ps->begin > s_paintedtime) { + if (ps->begin > painted_time) { end = min(end, ps->begin); // stop here break; } @@ -449,13 +454,13 @@ static void PaintChannels(int endtime) } // clear the paint buffer - memset(paintbuffer, 0, (end - s_paintedtime) * sizeof(paintbuffer[0])); + memset(paintbuffer, 0, (end - painted_time) * sizeof(paintbuffer[0])); // paint in the channels. channel_t *channels = soundSystem.channels_data(); int num_channels = soundSystem.num_channels(); for (i = 0, ch = channels; ch && i < num_channels; i++, ch++) { - int ltime = s_paintedtime; + int ltime = painted_time; while (ltime < end) { if (!ch->sfx || (!ch->leftvol && !ch->rightvol)) @@ -471,7 +476,7 @@ static void PaintChannels(int endtime) if (count > 0) { int func = (sc->width - 1) * 3 + (sc->channels - 1) * (S_IsFullVolume(ch) + 1); Q_assert(func < q_countof(paintfuncs)); - paintfuncs[func](ch, sc, count, &paintbuffer[ltime - s_paintedtime]); + paintfuncs[func](ch, sc, count, &paintbuffer[ltime - painted_time]); ch->pos += count; ltime += count; } @@ -494,20 +499,20 @@ static void PaintChannels(int endtime) } if (underwater) - underwater_filter(paintbuffer, end - s_paintedtime); + underwater_filter(paintbuffer, end - painted_time); // add from the streaming sound source - int count = min(end, s_rawend) - s_paintedtime; + int count = min(end, s_rawend) - painted_time; for (i = 0; i < count; i++) { - int s = (s_paintedtime + i) & (MAX_RAW_SAMPLES - 1); + int s = (painted_time + i) & (MAX_RAW_SAMPLES - 1); paintbuffer[i].left += s_rawsamples[s].left; paintbuffer[i].right += s_rawsamples[s].right; } // transfer out according to DMA format TransferPaintBuffer(paintbuffer, end); - s_paintedtime = end; + painted_time = end; } } @@ -599,7 +604,7 @@ static bool DMA_Init(void) SoundSystem &soundSystem = S_GetSoundSystem(); soundSystem.num_channels() = soundSystem.max_channels(); - s_supports_float = true; + soundSystem.set_supports_float(true); Com_Printf("sound sampling rate: %i\n", dma.speed); @@ -620,7 +625,7 @@ static void DMA_Activate(void) { if (snddma->activate) { S_GetSoundSystem().StopAllSounds(); - snddma->activate(s_active); + snddma->activate(S_GetSoundSystem().is_active()); } } @@ -636,20 +641,21 @@ static int DMA_DriftBeginofs(float timeofs) { static int s_beginofs; int start; + const int painted_time = S_GetSoundSystem().painted_time(); // drift s_beginofs start = cl.servertime * 0.001f * dma.speed + s_beginofs; - if (start < s_paintedtime) { - start = s_paintedtime; + if (start < painted_time) { + start = painted_time; s_beginofs = start - (cl.servertime * 0.001f * dma.speed); - } else if (start > s_paintedtime + 0.3f * dma.speed) { - start = s_paintedtime + 0.1f * dma.speed; + } else if (start > painted_time + 0.3f * dma.speed) { + start = painted_time + 0.1f * dma.speed; s_beginofs = start - (cl.servertime * 0.001f * dma.speed); } else { s_beginofs -= 10; } - return timeofs ? start + timeofs * dma.speed : s_paintedtime; + return timeofs ? start + timeofs * dma.speed : painted_time; } static void DMA_ClearBuffer(void) @@ -717,15 +723,16 @@ static void AddLoopSounds(void) int num; entity_state_t *ent; vec3_t origin; + SoundSystem &soundSystem = S_GetSoundSystem(); - if (!S_GetSoundSystem().BuildSoundList(sounds)) + if (!soundSystem.BuildSoundList(sounds)) return; for (i = 0; i < cl.frame.numEntities; i++) { if (!sounds[i]) continue; - sfx = S_GetSoundSystem().SfxForHandle(cl.sound_precache[sounds[i]]); + sfx = soundSystem.SfxForHandle(cl.sound_precache[sounds[i]]); if (!sfx) continue; // bad sound effect sc = sfx->cache; @@ -746,8 +753,8 @@ static void AddLoopSounds(void) VectorSubtract(origin, offset, base); CL_DebugTrail(base, origin); } - S_GetSoundSystem().SpatializeOrigin(origin, vol, att, &left_total, - &right_total, GET_STEREO(ent)); + soundSystem.SpatializeOrigin(origin, vol, att, &left_total, + &right_total, GET_STEREO(ent)); for (j = i + 1; j < cl.frame.numEntities; j++) { if (sounds[j] != sounds[i]) continue; @@ -762,10 +769,10 @@ static void AddLoopSounds(void) VectorSubtract(origin, offset, base); CL_DebugTrail(base, origin); } - S_GetSoundSystem().SpatializeOrigin(origin, - S_GetEntityLoopVolume(ent), - S_GetEntityLoopDistMult(ent), - &left, &right, GET_STEREO(ent)); + soundSystem.SpatializeOrigin(origin, + S_GetEntityLoopVolume(ent), + S_GetEntityLoopDistMult(ent), + &left, &right, GET_STEREO(ent)); left_total += left; right_total += right; } @@ -774,7 +781,7 @@ static void AddLoopSounds(void) continue; // not audible // allocate a channel - ch = S_GetSoundSystem().PickChannel(0, 0); + ch = soundSystem.PickChannel(0, 0); if (!ch) return; @@ -784,8 +791,9 @@ static void AddLoopSounds(void) ch->dist_mult = att; // for S_IsFullVolume() ch->autosound = true; // remove next frame ch->sfx = sfx; - ch->pos = s_paintedtime % sc->length; - ch->end = s_paintedtime + sc->length - ch->pos; + const int painted_time = soundSystem.painted_time(); + ch->pos = painted_time % sc->length; + ch->end = painted_time + sc->length - ch->pos; } } @@ -794,16 +802,18 @@ static int DMA_GetTime(void) static int buffers; static int oldsamplepos; int fullsamples = dma.samples >> (dma.channels - 1); + SoundSystem &soundSystem = S_GetSoundSystem(); + int &painted_time = soundSystem.painted_time(); // it is possible to miscount buffers if it has wrapped twice between // calls to S_Update. Oh well. if (dma.samplepos < oldsamplepos) { buffers++; // buffer wrapped - if (s_paintedtime > 0x40000000) { + if (painted_time > 0x40000000) { // time to chop things off to avoid 32 bit limits buffers = 0; - s_rawend = s_paintedtime = fullsamples; - S_GetSoundSystem().StopAllSounds(); + s_rawend = painted_time = fullsamples; + soundSystem.StopAllSounds(); } } oldsamplepos = dma.samplepos; @@ -821,6 +831,7 @@ static void DMA_Update(void) SoundSystem &soundSystem = S_GetSoundSystem(); channel_t *channels = soundSystem.channels_data(); int num_channels = soundSystem.num_channels(); + int &painted_time = soundSystem.painted_time(); // update spatialization for dynamic sounds for (i = 0, ch = channels; channels && i < num_channels; i++, ch++) { @@ -853,7 +864,7 @@ static void DMA_Update(void) } } if (s_show->integer > 1 || total) { - Com_Printf("----(%i)---- painted: %i\n", total, s_paintedtime); + Com_Printf("----(%i)---- painted: %i\n", total, painted_time); } } #endif @@ -867,9 +878,9 @@ static void DMA_Update(void) soundtime = DMA_GetTime(); // check to make sure that we haven't overshot - if (s_paintedtime < soundtime) { + if (painted_time < soundtime) { Com_DPrintf("%s: overflow\n", __func__); - s_paintedtime = soundtime; + painted_time = soundtime; } // mix ahead of current position diff --git a/src/client/sound/main.cpp b/src/client/sound/main.cpp index 895d4ff..fca002b 100644 --- a/src/client/sound/main.cpp +++ b/src/client/sound/main.cpp @@ -27,15 +27,6 @@ with this program; if not, write to the Free Software Foundation, Inc., // Internal sound data & structures // ======================================================================= -SoundBackend s_started; -bool s_active; -bool s_supports_float; -const sndapi_t *s_api; - -bool s_registering; - -int s_paintedtime; // sample PAIRS - cvar_t *s_volume; cvar_t *s_ambient; #if USE_DEBUG @@ -55,12 +46,16 @@ static cvar_t *s_auto_focus; static void S_SoundInfo_f(void) { - if (s_started == SoundBackend::Not) { + SoundSystem &soundSystem = S_GetSoundSystem(); + + if (soundSystem.backend() == SoundBackend::Not) { Com_Printf("Sound system not started.\n"); return; } - s_api->sound_info(); + if (const sndapi_t *api = soundSystem.api()) { + api->sound_info(); + } } static void S_SoundList_f(void) @@ -127,15 +122,22 @@ S_Init */ void S_Init(void) { + SoundSystem &soundSystem = S_GetSoundSystem(); + s_enable = Cvar_Get("s_enable", "2", CVAR_SOUND); if (s_enable->integer <= static_cast(SoundBackend::Not)) { Com_Printf("Sound initialization disabled.\n"); + soundSystem.set_backend(SoundBackend::Not); + soundSystem.set_api(nullptr); + soundSystem.set_supports_float(false); + soundSystem.set_active(false); + soundSystem.set_registering(false); + soundSystem.set_painted_time(0); return; } Com_Printf("------- S_Init -------\n"); - SoundSystem &soundSystem = S_GetSoundSystem(); soundSystem.Configure({ SoundSystem::kDefaultMaxSfx, SoundSystem::kDefaultMaxPlaysounds }); s_volume = Cvar_Get("s_volume", "0.7", CVAR_ARCHIVE); @@ -154,27 +156,36 @@ void S_Init(void) soundSystem.num_channels() = 0; // start one of available sound engines - s_started = SoundBackend::Not; + soundSystem.set_backend(SoundBackend::Not); + soundSystem.set_api(nullptr); + soundSystem.set_supports_float(false); + soundSystem.set_active(false); + + SoundBackend started = SoundBackend::Not; + const sndapi_t *api = nullptr; #if USE_OPENAL - if (s_started == SoundBackend::Not && s_enable->integer >= static_cast(SoundBackend::OpenAL) && snd_openal.init()) { - s_started = SoundBackend::OpenAL; - s_api = &snd_openal; + if (started == SoundBackend::Not && s_enable->integer >= static_cast(SoundBackend::OpenAL) && snd_openal.init()) { + started = SoundBackend::OpenAL; + api = &snd_openal; } #endif #if USE_SNDDMA - if (s_started == SoundBackend::Not && s_enable->integer >= static_cast(SoundBackend::DMA) && snd_dma.init()) { - s_started = SoundBackend::DMA; - s_api = &snd_dma; + if (started == SoundBackend::Not && s_enable->integer >= static_cast(SoundBackend::DMA) && snd_dma.init()) { + started = SoundBackend::DMA; + api = &snd_dma; } #endif - if (s_started == SoundBackend::Not) { + if (started == SoundBackend::Not) { Com_EPrintf("Sound failed to initialize.\n"); goto fail; } + soundSystem.set_backend(started); + soundSystem.set_api(api); + Cmd_Register(c_sound); // init playsound list @@ -186,15 +197,16 @@ void S_Init(void) soundSystem.set_num_sfx(0); - s_paintedtime = 0; + soundSystem.set_painted_time(0); soundSystem.reset_registration_sequence(); + soundSystem.set_registering(false); // start the cd track OGG_Play(); fail: - Cvar_SetInteger(s_enable, static_cast(s_started), FROM_CODE); + Cvar_SetInteger(s_enable, static_cast(started), FROM_CODE); Com_Printf("----------------------\n"); } @@ -205,8 +217,11 @@ void S_Init(void) static void S_FreeSound(sfx_t *sfx) { - if (s_started != SoundBackend::Not && s_api->delete_sfx) - s_api->delete_sfx(sfx); + SoundSystem &soundSystem = S_GetSoundSystem(); + const sndapi_t *api = soundSystem.api(); + + if (soundSystem.backend() != SoundBackend::Not && api && api->delete_sfx) + api->delete_sfx(sfx); Z_Free(sfx->cache); Z_Free(sfx->truename); memset(sfx, 0, sizeof(*sfx)); @@ -231,25 +246,29 @@ void S_FreeAllSounds(void) void S_Shutdown(void) { - if (s_started == SoundBackend::Not) + SoundSystem &soundSystem = S_GetSoundSystem(); + + if (soundSystem.backend() == SoundBackend::Not) return; - S_GetSoundSystem().StopAllSounds(); + soundSystem.StopAllSounds(); S_FreeAllSounds(); OGG_Stop(); - SoundSystem &soundSystem = S_GetSoundSystem(); soundSystem.clear_channels(); soundSystem.num_channels() = 0; soundSystem.max_channels() = 0; soundSystem.ResetPlaysounds(); - s_api->shutdown(); - s_api = NULL; + if (const sndapi_t *api = soundSystem.api()) { + api->shutdown(); + } - s_started = SoundBackend::Not; - s_active = false; - s_supports_float = false; + soundSystem.set_api(nullptr); + soundSystem.set_backend(SoundBackend::Not); + soundSystem.set_active(false); + soundSystem.set_supports_float(false); + soundSystem.set_registering(false); s_auto_focus->changed = NULL; @@ -263,20 +282,24 @@ void S_Activate(void) bool active; active_t level; - if (s_started == SoundBackend::Not) + SoundSystem &soundSystem = S_GetSoundSystem(); + + if (soundSystem.backend() == SoundBackend::Not) return; level = static_cast(Cvar_ClampInteger(s_auto_focus, ACT_MINIMIZED, ACT_ACTIVATED)); active = cls.active >= level; - if (active == s_active) + if (active == soundSystem.is_active()) return; Com_DDDPrintf("%s: %d\n", __func__, active); - s_active = active; + soundSystem.set_active(active); - s_api->activate(); + if (const sndapi_t *api = soundSystem.api()) { + api->activate(); + } } // ======================================================================= @@ -357,8 +380,9 @@ S_BeginRegistration */ void S_BeginRegistration(void) { - S_GetSoundSystem().increment_registration_sequence(); - s_registering = true; + SoundSystem &soundSystem = S_GetSoundSystem(); + soundSystem.increment_registration_sequence(); + soundSystem.set_registering(true); } /* @@ -369,16 +393,16 @@ S_RegisterSound */ qhandle_t S_RegisterSound(const char *name) { + SoundSystem &soundSystem = S_GetSoundSystem(); char buffer[MAX_QPATH]; sfx_t *sfx; size_t len; - if (s_started == SoundBackend::Not) + if (soundSystem.backend() == SoundBackend::Not) return 0; Q_assert(name); - SoundSystem &soundSystem = S_GetSoundSystem(); sfx_t *known_sfx = soundSystem.known_sfx_data(); // empty names are legal, silently ignore them @@ -413,7 +437,7 @@ qhandle_t S_RegisterSound(const char *name) return 0; } - if (!s_registering) { + if (!soundSystem.is_registering()) { soundSystem.LoadSound(sfx); } @@ -427,6 +451,7 @@ S_RegisterSexedSound */ static sfx_t *S_RegisterSexedSound(int entnum, const char *base) { + SoundSystem &soundSystem = S_GetSoundSystem(); sfx_t *sfx; const char *model; char buffer[MAX_QPATH]; @@ -449,7 +474,7 @@ static sfx_t *S_RegisterSexedSound(int entnum, const char *base) sfx = S_FindName(buffer, FS_NormalizePath(buffer)); // see if it exists - if (sfx && !sfx->truename && !s_registering && !S_GetSoundSystem().LoadSound(sfx)) { + if (sfx && !sfx->truename && !soundSystem.is_registering() && !soundSystem.LoadSound(sfx)) { // no, revert to the male sound in the pak0.pak if (Q_concat(buffer, MAX_QPATH, "sound/player/male/", base + 1) < MAX_QPATH) { FS_NormalizePath(buffer); @@ -502,6 +527,7 @@ void S_EndRegistration(void) SoundSystem &soundSystem = S_GetSoundSystem(); sfx_t *known_sfx = soundSystem.known_sfx_data(); int num_sfx = soundSystem.num_sfx(); + const sndapi_t *api = soundSystem.api(); S_RegisterSexedSounds(); @@ -519,8 +545,8 @@ void S_EndRegistration(void) continue; } // make sure it is paged in - if (s_started != SoundBackend::Not && s_api->page_in_sfx) - s_api->page_in_sfx(sfx); + if (soundSystem.backend() != SoundBackend::Not && api && api->page_in_sfx) + api->page_in_sfx(sfx); } // load everything in @@ -531,10 +557,10 @@ void S_EndRegistration(void) soundSystem.LoadSound(sfx); } - if (s_started != SoundBackend::Not && s_api->end_registration) - s_api->end_registration(); + if (soundSystem.backend() != SoundBackend::Not && api && api->end_registration) + api->end_registration(); - s_registering = false; + soundSystem.set_registering(false); } @@ -575,8 +601,8 @@ channel_t *SoundSystem::PickChannel(int entnum, int entchannel) if (ch->entnum == listener_entnum_ && entnum != listener_entnum_ && ch->sfx) continue; - if (ch->end - s_paintedtime < life_left) { - life_left = ch->end - s_paintedtime; + if (ch->end - painted_time_ < life_left) { + life_left = ch->end - painted_time_; first_to_die = ch_idx; } } @@ -585,8 +611,8 @@ channel_t *SoundSystem::PickChannel(int entnum, int entchannel) return NULL; ch = &channels_[first_to_die]; - if (s_api->stop_channel) - s_api->stop_channel(ch); + if (api_ && api_->stop_channel) + api_->stop_channel(ch); memset(ch, 0, sizeof(*ch)); ch->has_spatial_offset = false; @@ -637,9 +663,10 @@ void SoundSystem::IssuePlaysound(playsound_t *ps) VectorCopy(ps->origin, ch->origin); ch->fixed_origin = ps->fixed_origin; ch->pos = 0; - ch->end = s_paintedtime + sc->length; + ch->end = painted_time_ + sc->length; - s_api->play_channel(ch); + if (api_ && api_->play_channel) + api_->play_channel(ch); // free the playsound FreePlaysound(ps); @@ -664,9 +691,11 @@ void SoundSystem::StartSound(const vec3_t origin, int entnum, int entchannel, qh playsound_t *ps; sfx_t *sfx; - if (s_started == SoundBackend::Not) + if (backend_ == SoundBackend::Not) + return; + if (!active_) return; - if (!s_active) + if (!api_) return; if (!(sfx = SfxForHandle(hSfx))) return; @@ -682,6 +711,9 @@ void SoundSystem::StartSound(const vec3_t origin, int entnum, int entchannel, qh if (!sc) return; // couldn't load the sound's data + if (!api_->get_begin_ofs) + return; + // make the playsound_t ps = AllocatePlaysound(); if (!ps) @@ -699,7 +731,7 @@ void SoundSystem::StartSound(const vec3_t origin, int entnum, int entchannel, qh ps->attenuation = attenuation; ps->volume = vol; ps->sfx = sfx; - ps->begin = s_api->get_begin_ofs(timeofs); + ps->begin = api_->get_begin_ofs(timeofs); // sort into the pending sound list QueuePendingPlay(ps); @@ -729,17 +761,21 @@ S_StartLocalSound */ void S_StartLocalSound(const char *sound) { - if (s_started != SoundBackend::Not) { + SoundSystem &soundSystem = S_GetSoundSystem(); + + if (soundSystem.backend() != SoundBackend::Not) { qhandle_t sfx = S_RegisterSound(sound); - S_GetSoundSystem().StartSound(NULL, listener_entnum, 0, sfx, 1, ATTN_NONE, 0); + soundSystem.StartSound(NULL, listener_entnum, 0, sfx, 1, ATTN_NONE, 0); } } void S_StartLocalSoundOnce(const char *sound) { - if (s_started != SoundBackend::Not) { + SoundSystem &soundSystem = S_GetSoundSystem(); + + if (soundSystem.backend() != SoundBackend::Not) { qhandle_t sfx = S_RegisterSound(sound); - S_GetSoundSystem().StartSound(NULL, listener_entnum, 256, sfx, 1, ATTN_NONE, 0); + soundSystem.StartSound(NULL, listener_entnum, 256, sfx, 1, ATTN_NONE, 0); } } @@ -750,39 +786,51 @@ S_StopAllSounds */ void SoundSystem::StopAllSounds() { - if (s_started == SoundBackend::Not) + if (backend_ == SoundBackend::Not) return; ResetPlaysounds(); - if (s_api && s_api->stop_all_sounds) - s_api->stop_all_sounds(); + if (api_ && api_->stop_all_sounds) + api_->stop_all_sounds(); clear_channels(); } void S_RawSamples(int samples, int rate, int width, int channels, const void *data) { - if (s_started != SoundBackend::Not && s_active) - s_api->raw_samples(samples, rate, width, channels, data, 1.0f); + SoundSystem &soundSystem = S_GetSoundSystem(); + + if (soundSystem.backend() != SoundBackend::Not && soundSystem.is_active()) { + if (const sndapi_t *api = soundSystem.api()) + api->raw_samples(samples, rate, width, channels, data, 1.0f); + } } int S_GetSampleRate(void) { - if (s_api && s_api->get_sample_rate) - return s_api->get_sample_rate(); + SoundSystem &soundSystem = S_GetSoundSystem(); + + if (const sndapi_t *api = soundSystem.api()) { + if (api->get_sample_rate) + return api->get_sample_rate(); + } return 0; } bool S_SupportsFloat(void) { - return s_supports_float; + return S_GetSoundSystem().supports_float(); } void S_PauseRawSamples(bool paused) { - if (s_api && s_api->pause_raw_samples) - s_api->pause_raw_samples(paused); + SoundSystem &soundSystem = S_GetSoundSystem(); + + if (const sndapi_t *api = soundSystem.api()) { + if (api->pause_raw_samples) + api->pause_raw_samples(paused); + } } // ======================================================================= @@ -794,7 +842,7 @@ int SoundSystem::BuildSoundList(int *sounds) int i, num, count; entity_state_t *ent; - if (cls.state != ca_active || !s_active || sv_paused->integer || !s_ambient->integer) + if (cls.state != ca_active || !active_ || sv_paused->integer || !s_ambient->integer) return 0; for (i = count = 0; i < cl.frame.numEntities; i++) { @@ -876,7 +924,7 @@ void SoundSystem::Update() return; } - if (s_started == SoundBackend::Not) + if (backend_ == SoundBackend::Not || !api_) return; // if the loading plaque is up, clear everything @@ -897,5 +945,6 @@ void SoundSystem::Update() OGG_Update(); - s_api->update(); + if (api_->update) + api_->update(); } diff --git a/src/client/sound/mem.cpp b/src/client/sound/mem.cpp index 47edd79..4167d7a 100644 --- a/src/client/sound/mem.cpp +++ b/src/client/sound/mem.cpp @@ -525,7 +525,10 @@ sfxcache_t *SoundSystem::LoadSound(sfx_t *s) if (s_info.format == FORMAT_PCM) ConvertSamples(); - sc = s_api->upload_sfx(s); + if (api_ && api_->upload_sfx) + sc = api_->upload_sfx(s); + else + sc = nullptr; #if USE_AVCODEC if (s_info.format != FORMAT_PCM) diff --git a/src/client/sound/ogg.cpp b/src/client/sound/ogg.cpp index 94fd48f..75264df 100644 --- a/src/client/sound/ogg.cpp +++ b/src/client/sound/ogg.cpp @@ -16,6 +16,7 @@ with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include "SoundSystem.hpp" #include "sound.hpp" #include "common/hash_map.hpp" #include "../ffmpeg_utils.hpp" @@ -242,8 +243,9 @@ void OGG_Play(void) { const char *s, *path; bool force = cls.state < ca_connected; + SoundSystem &soundSystem = S_GetSoundSystem(); - if (s_started == SoundBackend::Not || cls.state == ca_cinematic || ogg_manual_play) + if (soundSystem.backend() == SoundBackend::Not || cls.state == ca_cinematic || ogg_manual_play) return; if (cls.state >= ca_connected) @@ -287,8 +289,8 @@ void OGG_Play(void) Com_DPrintf("No such track: %s\n", s); } - if (s_api) - s_api->drop_raw_samples(); + if (const sndapi_t *api = S_GetSoundSystem().api()) + api->drop_raw_samples(); } void OGG_Stop(void) @@ -305,8 +307,8 @@ void OGG_Stop(void) ogg_manual_play = false; ogg_paused = false; - if (s_api) - s_api->drop_raw_samples(); + if (const sndapi_t *api = S_GetSoundSystem().api()) + api->drop_raw_samples(); } static int read_packet(AVPacket *pkt) @@ -404,7 +406,7 @@ static int reconfigure_swr(void) ret = Q_AVChannelLayoutDefault(&out->ch_layout, 2); if (ret < 0) return ret; - out->format = s_supports_float ? AV_SAMPLE_FMT_FLT : AV_SAMPLE_FMT_S16; + out->format = S_GetSoundSystem().supports_float() ? AV_SAMPLE_FMT_FLT : AV_SAMPLE_FMT_S16; out->sample_rate = sample_rate; out->nb_samples = MAX_RAW_SAMPLES; @@ -438,11 +440,13 @@ static void flush_samples(const AVFrame *out) { Com_DDDPrintf("%d raw samples\n", out->nb_samples); - if (!s_api->raw_samples(out->nb_samples, out->sample_rate, - av_get_bytes_per_sample(static_cast(out->format)), - out->ch_layout.nb_channels, - out->data[0], ogg_volume->value)) - s_api->drop_raw_samples(); + if (const sndapi_t *api = S_GetSoundSystem().api()) { + if (!api->raw_samples(out->nb_samples, out->sample_rate, + av_get_bytes_per_sample(static_cast(out->format)), + out->ch_layout.nb_channels, + out->data[0], ogg_volume->value)) + api->drop_raw_samples(); + } } static int convert_frame(AVFrame *out, AVFrame *in) @@ -464,7 +468,11 @@ static int convert_audio(void) return 0; // get available free space - need = s_api->need_raw_samples(); + const sndapi_t *api = S_GetSoundSystem().api(); + if (!api) + return 0; + + need = api->need_raw_samples(); if (need <= 0) return 0; @@ -563,12 +571,15 @@ static int convert_audio(void) void OGG_Update(void) { - if (s_started == SoundBackend::Not || !s_active) + SoundSystem &soundSystem = S_GetSoundSystem(); + const sndapi_t *api = soundSystem.api(); + + if (soundSystem.backend() == SoundBackend::Not || !soundSystem.is_active()) return; if (!ogg.dec_ctx && !ogg_swr_draining) { // resume auto playback if manual playback just stopped - if (ogg_manual_play && !s_api->have_raw_samples()) { + if (ogg_manual_play && api && !api->have_raw_samples()) { ogg_manual_play = false; OGG_Play(); } @@ -673,7 +684,7 @@ static void OGG_Play_f(void) return; } - if (s_started == SoundBackend::Not) { + if (S_GetSoundSystem().backend() == SoundBackend::Not) { Com_Printf("Sound system not started.\n"); return; } @@ -726,7 +737,7 @@ static void OGG_Cmd_c(genctx_t *ctx, int argnum) static void OGG_Next_f(void) { - if (s_started == SoundBackend::Not) { + if (S_GetSoundSystem().backend() == SoundBackend::Not) { Com_Printf("Sound system not started.\n"); return; } diff --git a/src/client/sound/sound.hpp b/src/client/sound/sound.hpp index c8f6aa3..e60d83a 100644 --- a/src/client/sound/sound.hpp +++ b/src/client/sound/sound.hpp @@ -149,13 +149,6 @@ enum class SoundBackend { #endif }; -extern SoundBackend s_started; -extern bool s_active; -extern bool s_supports_float; -extern const sndapi_t *s_api; - -extern int s_paintedtime; - extern wavinfo_t s_info; extern cvar_t *s_volume; diff --git a/src/windows/wave.cpp b/src/windows/wave.cpp index 8d3a32b..48f9958 100644 --- a/src/windows/wave.cpp +++ b/src/windows/wave.cpp @@ -17,6 +17,7 @@ with this program; if not, write to the Free Software Foundation, Inc., */ #include "client.hpp" +#include "SoundSystem.hpp" #include "client/sound/dma.hpp" #include @@ -290,7 +291,7 @@ static void WAVE_Submit(void) // while (((snd_sent - snd_completed) >> sample16) < 8) { h = lpWaveHdr + (snd_sent & WAV_MASK); - if (s_paintedtime / 256 <= snd_sent) + if (S_GetSoundSystem().painted_time() / 256 <= snd_sent) break; snd_sent++; /*