From 4f4e8a700b65f64edb1ff5edd118825268f0c4e3 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sat, 29 Nov 2025 16:23:06 -0600 Subject: [PATCH] feat(sound): add SESound::ProcessVolumeUpdates --- src/sound/SESound.cpp | 98 +++++++++++++++++++++++++++++++++++++++++++ src/sound/SESound.hpp | 1 + 2 files changed, 99 insertions(+) diff --git a/src/sound/SESound.cpp b/src/sound/SESound.cpp index 43aae40..48b1d15 100644 --- a/src/sound/SESound.cpp +++ b/src/sound/SESound.cpp @@ -2,6 +2,7 @@ #include "event/Event.hpp" #include "console/CVar.hpp" #include "util/SFile.hpp" +#include #include #include #include @@ -248,6 +249,10 @@ int32_t SESound::Heartbeat(const void* data, void* param) { // TODO + SESound::ProcessVolumeUpdates(); + + // TODO + SESound::ProcessReadyDiskSounds(); // TODO @@ -599,6 +604,99 @@ void SESound::ProcessReadyDiskSounds() { } } +void SESound::ProcessVolumeUpdates() { + if (!SESound::s_Initialized) { + return; + } + + static uint32_t lastProcessedMs = OsGetAsyncTimeMsPrecise(); + + uint32_t currentMs = OsGetAsyncTimeMsPrecise(); + uint32_t elapsedMs = currentMs - lastProcessedMs; + float elapsedSeconds = elapsedMs / 1000.0f; + + if (currentMs - lastProcessedMs < 0) { + lastProcessedMs = currentMs; + return; + } + + // Determine dirty channel groups + + bool dirtyChannelGroups[SESound::s_ChannelGroups.Count()]; + memset(dirtyChannelGroups, 0, SESound::s_ChannelGroups.Count() * sizeof(bool)); + + for (uint32_t i = 0; i < SESound::s_ChannelGroups.Count(); i++) { + auto channelGroup = &SESound::s_ChannelGroups[i]; + + if (channelGroup->m_dirty) { + channelGroup->m_dirty = false; + dirtyChannelGroups[i] = true; + } + } + + for (uint32_t i = 0; i < SESound::s_ChannelGroups.Count(); i++) { + auto channelGroup = &SESound::s_ChannelGroups[i]; + + if (!dirtyChannelGroups[i] && dirtyChannelGroups[channelGroup->m_parentChannelGroup]) { + dirtyChannelGroups[i] = true; + } + } + + SESound::s_InternalCritSect.Enter(); + + for (auto internal = SESound::s_InternalList.Head(); internal; internal = SESound::s_InternalList.Link(internal)->Next()) { + internal->UpdateVolume(); + + if (internal->m_fadeOut) { + internal->m_fadeVolume -= elapsedSeconds / internal->m_fadeOutTime; + + if (internal->m_fadeVolume < 0.0f || internal->m_fadeOutTime < 0.0f) { + internal->m_fadeVolume = 0.0f; + } + + if (internal->m_fadeVolume == 0.0f) { + internal->m_fadeOut = false; + + SESound sound; + sound.m_internal = nullptr; + + if (!internal->m_sound) { + internal->m_sound = &sound; + sound.m_internal = internal; + } + + // TODO callback + + internal->m_sound->StopOrFadeOut(1, -1.0f); + + // TODO + } + } else if (internal->m_fadeIn) { + internal->m_fadeVolume += elapsedSeconds / internal->m_fadeInTime; + + if (internal->m_fadeVolume > 1.0f) { + internal->m_fadeVolume = 1.0f; + } + + internal->UpdateVolume(); + + if (internal->m_fadeVolume == 1.0f) { + internal->m_fadeIn = false; + } + } else { + // Likely redundant call give the UpdateVolume call at the start of the list iterator. + // Included here for posterity. + if (dirtyChannelGroups[internal->m_channelGroup]) { + internal->UpdateVolume(); + } + } + } + + SESound::s_InternalCritSect.Leave(); + + lastProcessedMs = currentMs; +} + void SESound::SetChannelGroupVolume(const char* name, float volume) { if (!SESound::s_Initialized) { return; diff --git a/src/sound/SESound.hpp b/src/sound/SESound.hpp index 0763cfc..344f8ea 100644 --- a/src/sound/SESound.hpp +++ b/src/sound/SESound.hpp @@ -58,6 +58,7 @@ class SESound { static void CreateMasterChannelGroup(); static int32_t LoadDiskSound(FMOD::System* fmodSystem, const char* filename, FMOD_MODE fmodMode, SESound* sound, FMOD::SoundGroup* fmodSoundGroup1, FMOD::SoundGroup* fmodSoundGroup2, bool a7, int32_t a8, uint32_t a9, int32_t a10, uint32_t decodeBufferSize, int32_t a12, float a13, float a14, float a15, float* a16); static void ProcessReadyDiskSounds(); + static void ProcessVolumeUpdates(); // Private member variables SESoundInternal* m_internal = nullptr;