From 6c6fd86d1d48e9cbce0094631ca1a34e0587e97a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sun, 26 May 2024 11:03:02 +0200 Subject: [PATCH 1/4] Remove unnecessary initialization of sound listener position The initial value is already the zero-position and the listener position is always set while online. --- src/game/client/components/sounds.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/game/client/components/sounds.cpp b/src/game/client/components/sounds.cpp index 073fc40be..6d38d943c 100644 --- a/src/game/client/components/sounds.cpp +++ b/src/game/client/components/sounds.cpp @@ -79,8 +79,6 @@ void CSounds::OnInit() Sound()->SetChannel(CSounds::CHN_GLOBAL, m_GameSoundVolume, 0.0f); Sound()->SetChannel(CSounds::CHN_MAPSOUND, m_MapSoundVolume, 1.0f); - Sound()->SetListenerPos(0.0f, 0.0f); - ClearQueue(); // load sounds From e0e1ef8001fa3bb7ae75bc6e5e9dfcd82fbc7c4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sun, 26 May 2024 11:08:04 +0200 Subject: [PATCH 2/4] Fix incorrect channel panning value after changing volume Fix incorrect panning value (`1.0f`) being set for GUI and Global sound channels after sound volume is changed, whereas the panning value is initialized to `0.0f`. Now the panning value is set to `0.0f` consistently. This should not have had any effect, as GUI and Global sounds do not have a position which would be affected by the panning value. --- src/game/client/components/sounds.cpp | 75 ++++++++++++--------------- src/game/client/components/sounds.h | 9 ++-- 2 files changed, 39 insertions(+), 45 deletions(-) diff --git a/src/game/client/components/sounds.cpp b/src/game/client/components/sounds.cpp index 6d38d943c..776b3e304 100644 --- a/src/game/client/components/sounds.cpp +++ b/src/game/client/components/sounds.cpp @@ -43,6 +43,38 @@ void CSoundLoading::Run() } } +void CSounds::UpdateChannels() +{ + const float NewGuiSoundVolume = g_Config.m_SndChatSoundVolume / 100.0f; + if(NewGuiSoundVolume != m_GuiSoundVolume) + { + m_GuiSoundVolume = NewGuiSoundVolume; + Sound()->SetChannel(CSounds::CHN_GUI, m_GuiSoundVolume, 0.0f); + } + + const float NewGameSoundVolume = g_Config.m_SndGameSoundVolume / 100.0f; + if(NewGameSoundVolume != m_GameSoundVolume) + { + m_GameSoundVolume = NewGameSoundVolume; + Sound()->SetChannel(CSounds::CHN_WORLD, 0.9f * m_GameSoundVolume, 1.0f); + Sound()->SetChannel(CSounds::CHN_GLOBAL, m_GameSoundVolume, 0.0f); + } + + const float NewMapSoundVolume = g_Config.m_SndMapSoundVolume / 100.0f; + if(NewMapSoundVolume != m_MapSoundVolume) + { + m_MapSoundVolume = NewMapSoundVolume; + Sound()->SetChannel(CSounds::CHN_MAPSOUND, m_MapSoundVolume, 1.0f); + } + + const float NewBackgroundMusicVolume = g_Config.m_SndBackgroundMusicVolume / 100.0f; + if(NewBackgroundMusicVolume != m_BackgroundMusicVolume) + { + m_BackgroundMusicVolume = NewBackgroundMusicVolume; + Sound()->SetChannel(CSounds::CHN_MUSIC, m_BackgroundMusicVolume, 1.0f); + } +} + int CSounds::GetSampleId(int SetId) { if(!g_Config.m_SndEnable || !Sound()->IsSoundEnabled() || m_WaitForSoundJob || SetId < 0 || SetId >= g_pData->m_NumSounds) @@ -67,18 +99,7 @@ int CSounds::GetSampleId(int SetId) void CSounds::OnInit() { - // setup sound channels - m_GuiSoundVolume = g_Config.m_SndChatSoundVolume / 100.0f; - m_GameSoundVolume = g_Config.m_SndGameSoundVolume / 100.0f; - m_MapSoundVolume = g_Config.m_SndMapSoundVolume / 100.0f; - m_BackgroundMusicVolume = g_Config.m_SndBackgroundMusicVolume / 100.0f; - - Sound()->SetChannel(CSounds::CHN_GUI, m_GuiSoundVolume, 0.0f); - Sound()->SetChannel(CSounds::CHN_MUSIC, m_BackgroundMusicVolume, 1.0f); - Sound()->SetChannel(CSounds::CHN_WORLD, 0.9f * m_GameSoundVolume, 1.0f); - Sound()->SetChannel(CSounds::CHN_GLOBAL, m_GameSoundVolume, 0.0f); - Sound()->SetChannel(CSounds::CHN_MAPSOUND, m_MapSoundVolume, 1.0f); - + UpdateChannels(); ClearQueue(); // load sounds @@ -125,35 +146,7 @@ void CSounds::OnRender() // set listener pos Sound()->SetListenerPos(m_pClient->m_Camera.m_Center.x, m_pClient->m_Camera.m_Center.y); - // update volume - float NewGuiSoundVol = g_Config.m_SndChatSoundVolume / 100.0f; - if(NewGuiSoundVol != m_GuiSoundVolume) - { - m_GuiSoundVolume = NewGuiSoundVol; - Sound()->SetChannel(CSounds::CHN_GUI, m_GuiSoundVolume, 1.0f); - } - - float NewGameSoundVol = g_Config.m_SndGameSoundVolume / 100.0f; - if(NewGameSoundVol != m_GameSoundVolume) - { - m_GameSoundVolume = NewGameSoundVol; - Sound()->SetChannel(CSounds::CHN_WORLD, 0.9f * m_GameSoundVolume, 1.0f); - Sound()->SetChannel(CSounds::CHN_GLOBAL, m_GameSoundVolume, 1.0f); - } - - float NewMapSoundVol = g_Config.m_SndMapSoundVolume / 100.0f; - if(NewMapSoundVol != m_MapSoundVolume) - { - m_MapSoundVolume = NewMapSoundVol; - Sound()->SetChannel(CSounds::CHN_MAPSOUND, m_MapSoundVolume, 1.0f); - } - - float NewBackgroundMusicVol = g_Config.m_SndBackgroundMusicVolume / 100.0f; - if(NewBackgroundMusicVol != m_BackgroundMusicVolume) - { - m_BackgroundMusicVolume = NewBackgroundMusicVol; - Sound()->SetChannel(CSounds::CHN_MUSIC, m_BackgroundMusicVolume, 1.0f); - } + UpdateChannels(); // play sound from queue if(m_QueuePos > 0) diff --git a/src/game/client/components/sounds.h b/src/game/client/components/sounds.h index 4ee5df561..b412425da 100644 --- a/src/game/client/components/sounds.h +++ b/src/game/client/components/sounds.h @@ -34,12 +34,13 @@ class CSounds : public CComponent std::shared_ptr m_pSoundJob; bool m_WaitForSoundJob; + void UpdateChannels(); int GetSampleId(int SetId); - float m_GuiSoundVolume; - float m_GameSoundVolume; - float m_MapSoundVolume; - float m_BackgroundMusicVolume; + float m_GuiSoundVolume = -1.0f; + float m_GameSoundVolume = -1.0f; + float m_MapSoundVolume = -1.0f; + float m_BackgroundMusicVolume = -1.0f; public: // sound channels From 986916400d387bb6495ee5fdb1a9541311fcd598 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sun, 26 May 2024 11:18:16 +0200 Subject: [PATCH 3/4] Use `vec2`s for sound positions Simply usage and readability of sound functions by using `vec2`s instead of two separate `float`s for positions. --- src/engine/client/sound.cpp | 78 +++++++++--------------- src/engine/client/sound.h | 16 ++--- src/engine/sound.h | 8 ++- src/game/client/components/mapsounds.cpp | 2 +- src/game/client/components/sounds.cpp | 8 +-- 5 files changed, 47 insertions(+), 65 deletions(-) diff --git a/src/engine/client/sound.cpp b/src/engine/client/sound.cpp index 6813cde9f..c04fd1db7 100644 --- a/src/engine/client/sound.cpp +++ b/src/engine/client/sound.cpp @@ -63,12 +63,10 @@ void CSound::Mix(short *pFinalOut, unsigned Frames) if(Voice.m_Flags & ISound::FLAG_POS && Voice.m_pChannel->m_Pan) { // TODO: we should respect the channel panning value - const int dx = Voice.m_X - m_CenterX.load(std::memory_order_relaxed); - const int dy = Voice.m_Y - m_CenterY.load(std::memory_order_relaxed); - float FalloffX = 0.0f; - float FalloffY = 0.0f; + const vec2 Delta = Voice.m_Position - vec2(m_ListenerPositionX.load(std::memory_order_relaxed), m_ListenerPositionY.load(std::memory_order_relaxed)); + vec2 Falloff = vec2(0.0f, 0.0f); - int RangeX = 0; // for panning + float RangeX = 0.0f; // for panning bool InVoiceField = false; switch(Voice.m_Shape) @@ -78,50 +76,34 @@ void CSound::Mix(short *pFinalOut, unsigned Frames) const float Radius = Voice.m_Circle.m_Radius; RangeX = Radius; - // dx and dy can be larger than 46341 and thus the calculation would go beyond the limits of a integer, - // therefore we cast them into float - const int Dist = (int)length(vec2(dx, dy)); + const float Dist = length(Delta); if(Dist < Radius) { InVoiceField = true; // falloff - int FalloffDistance = Radius * Voice.m_Falloff; - if(Dist > FalloffDistance) - FalloffX = FalloffY = (Radius - Dist) / (Radius - FalloffDistance); - else - FalloffX = FalloffY = 1.0f; + const float FalloffDistance = Radius * Voice.m_Falloff; + Falloff.x = Falloff.y = Dist > FalloffDistance ? (Radius - Dist) / (Radius - FalloffDistance) : 1.0f; } - else - InVoiceField = false; - break; } case ISound::SHAPE_RECTANGLE: { - RangeX = Voice.m_Rectangle.m_Width / 2.0f; + const vec2 AbsoluteDelta = vec2(absolute(Delta.x), absolute(Delta.y)); + const float w = Voice.m_Rectangle.m_Width / 2.0f; + const float h = Voice.m_Rectangle.m_Height / 2.0f; + RangeX = w; - const int abs_dx = absolute(dx); - const int abs_dy = absolute(dy); - - const int w = Voice.m_Rectangle.m_Width / 2.0f; - const int h = Voice.m_Rectangle.m_Height / 2.0f; - - if(abs_dx < w && abs_dy < h) + if(AbsoluteDelta.x < w && AbsoluteDelta.y < h) { InVoiceField = true; // falloff - int fx = Voice.m_Falloff * w; - int fy = Voice.m_Falloff * h; - - FalloffX = abs_dx > fx ? (float)(w - abs_dx) / (w - fx) : 1.0f; - FalloffY = abs_dy > fy ? (float)(h - abs_dy) / (h - fy) : 1.0f; + const vec2 FalloffDistance = vec2(w, h) * Voice.m_Falloff; + Falloff.x = AbsoluteDelta.x > FalloffDistance.x ? (w - AbsoluteDelta.x) / (w - FalloffDistance.x) : 1.0f; + Falloff.y = AbsoluteDelta.y > FalloffDistance.y ? (h - AbsoluteDelta.y) / (h - FalloffDistance.y) : 1.0f; } - else - InVoiceField = false; - break; } }; @@ -131,15 +113,15 @@ void CSound::Mix(short *pFinalOut, unsigned Frames) // panning if(!(Voice.m_Flags & ISound::FLAG_NO_PANNING)) { - if(dx > 0) - VolumeL = ((RangeX - absolute(dx)) * VolumeL) / RangeX; + if(Delta.x > 0) + VolumeL = ((RangeX - absolute(Delta.x)) * VolumeL) / RangeX; else - VolumeR = ((RangeX - absolute(dx)) * VolumeR) / RangeX; + VolumeR = ((RangeX - absolute(Delta.x)) * VolumeR) / RangeX; } { - VolumeL *= FalloffX * FalloffY; - VolumeR *= FalloffX * FalloffY; + VolumeL *= Falloff.x * Falloff.y; + VolumeR *= Falloff.x * Falloff.y; } } else @@ -723,10 +705,10 @@ void CSound::SetChannel(int ChannelId, float Vol, float Pan) m_aChannels[ChannelId].m_Pan = (int)(Pan * 255.0f); // TODO: this is only on and off right now } -void CSound::SetListenerPos(float x, float y) +void CSound::SetListenerPosition(vec2 Position) { - m_CenterX.store((int)x, std::memory_order_relaxed); - m_CenterY.store((int)y, std::memory_order_relaxed); + m_ListenerPositionX.store(Position.x, std::memory_order_relaxed); + m_ListenerPositionY.store(Position.y, std::memory_order_relaxed); } void CSound::SetVoiceVolume(CVoiceHandle Voice, float Volume) @@ -759,7 +741,7 @@ void CSound::SetVoiceFalloff(CVoiceHandle Voice, float Falloff) m_aVoices[VoiceId].m_Falloff = Falloff; } -void CSound::SetVoiceLocation(CVoiceHandle Voice, float x, float y) +void CSound::SetVoicePosition(CVoiceHandle Voice, vec2 Position) { if(!Voice.IsValid()) return; @@ -770,8 +752,7 @@ void CSound::SetVoiceLocation(CVoiceHandle Voice, float x, float y) if(m_aVoices[VoiceId].m_Age != Voice.Age()) return; - m_aVoices[VoiceId].m_X = x; - m_aVoices[VoiceId].m_Y = y; + m_aVoices[VoiceId].m_Position = Position; } void CSound::SetVoiceTimeOffset(CVoiceHandle Voice, float TimeOffset) @@ -839,7 +820,7 @@ void CSound::SetVoiceRectangle(CVoiceHandle Voice, float Width, float Height) m_aVoices[VoiceId].m_Rectangle.m_Height = maximum(0.0f, Height); } -ISound::CVoiceHandle CSound::Play(int ChannelId, int SampleId, int Flags, float x, float y) +ISound::CVoiceHandle CSound::Play(int ChannelId, int SampleId, int Flags, vec2 Position) { const CLockScope LockScope(m_SoundLock); @@ -877,8 +858,7 @@ ISound::CVoiceHandle CSound::Play(int ChannelId, int SampleId, int Flags, float } m_aVoices[VoiceId].m_Vol = 255; m_aVoices[VoiceId].m_Flags = Flags; - m_aVoices[VoiceId].m_X = (int)x; - m_aVoices[VoiceId].m_Y = (int)y; + m_aVoices[VoiceId].m_Position = Position; m_aVoices[VoiceId].m_Falloff = 0.0f; m_aVoices[VoiceId].m_Shape = ISound::SHAPE_CIRCLE; m_aVoices[VoiceId].m_Circle.m_Radius = 1500; @@ -888,14 +868,14 @@ ISound::CVoiceHandle CSound::Play(int ChannelId, int SampleId, int Flags, float return CreateVoiceHandle(VoiceId, Age); } -ISound::CVoiceHandle CSound::PlayAt(int ChannelId, int SampleId, int Flags, float x, float y) +ISound::CVoiceHandle CSound::PlayAt(int ChannelId, int SampleId, int Flags, vec2 Position) { - return Play(ChannelId, SampleId, Flags | ISound::FLAG_POS, x, y); + return Play(ChannelId, SampleId, Flags | ISound::FLAG_POS, Position); } ISound::CVoiceHandle CSound::Play(int ChannelId, int SampleId, int Flags) { - return Play(ChannelId, SampleId, Flags, 0, 0); + return Play(ChannelId, SampleId, Flags, vec2(0.0f, 0.0f)); } void CSound::Pause(int SampleId) diff --git a/src/engine/client/sound.h b/src/engine/client/sound.h index d688ed955..dfd166abb 100644 --- a/src/engine/client/sound.h +++ b/src/engine/client/sound.h @@ -44,7 +44,7 @@ struct CVoice int m_Tick; int m_Vol; // 0 - 255 int m_Flags; - int m_X, m_Y; + vec2 m_Position; float m_Falloff; // [0.0, 1.0] int m_Shape; @@ -76,8 +76,10 @@ class CSound : public IEngineSound int m_NextVoice = 0; uint32_t m_MaxFrames = 0; - std::atomic m_CenterX = 0; - std::atomic m_CenterY = 0; + // This is not an std::atomic as this would require linking with + // libatomic with clang x86 as there is no native support for this. + std::atomic m_ListenerPositionX = 0.0f; + std::atomic m_ListenerPositionY = 0.0f; std::atomic m_SoundVolume = 100; int m_MixingRate = 48000; @@ -112,18 +114,18 @@ public: void SetSampleCurrentTime(int SampleId, float Time) override REQUIRES(!m_SoundLock); void SetChannel(int ChannelId, float Vol, float Pan) override; - void SetListenerPos(float x, float y) override; + void SetListenerPosition(vec2 Position) override; void SetVoiceVolume(CVoiceHandle Voice, float Volume) override REQUIRES(!m_SoundLock); void SetVoiceFalloff(CVoiceHandle Voice, float Falloff) override REQUIRES(!m_SoundLock); - void SetVoiceLocation(CVoiceHandle Voice, float x, float y) override REQUIRES(!m_SoundLock); + void SetVoicePosition(CVoiceHandle Voice, vec2 Position) override REQUIRES(!m_SoundLock); void SetVoiceTimeOffset(CVoiceHandle Voice, float TimeOffset) override REQUIRES(!m_SoundLock); // in s void SetVoiceCircle(CVoiceHandle Voice, float Radius) override REQUIRES(!m_SoundLock); void SetVoiceRectangle(CVoiceHandle Voice, float Width, float Height) override REQUIRES(!m_SoundLock); - CVoiceHandle Play(int ChannelId, int SampleId, int Flags, float x, float y) REQUIRES(!m_SoundLock); - CVoiceHandle PlayAt(int ChannelId, int SampleId, int Flags, float x, float y) override REQUIRES(!m_SoundLock); + CVoiceHandle Play(int ChannelId, int SampleId, int Flags, vec2 Position) REQUIRES(!m_SoundLock); + CVoiceHandle PlayAt(int ChannelId, int SampleId, int Flags, vec2 Position) override REQUIRES(!m_SoundLock); CVoiceHandle Play(int ChannelId, int SampleId, int Flags) override REQUIRES(!m_SoundLock); void Pause(int SampleId) override REQUIRES(!m_SoundLock); void Stop(int SampleId) override REQUIRES(!m_SoundLock); diff --git a/src/engine/sound.h b/src/engine/sound.h index 43c354124..846aa8aa4 100644 --- a/src/engine/sound.h +++ b/src/engine/sound.h @@ -6,6 +6,8 @@ #include #include +#include + class ISound : public IInterface { MACRO_INTERFACE("sound") @@ -74,17 +76,17 @@ public: virtual void SetSampleCurrentTime(int SampleId, float Time) = 0; virtual void SetChannel(int ChannelId, float Volume, float Panning) = 0; - virtual void SetListenerPos(float x, float y) = 0; + virtual void SetListenerPosition(vec2 Position) = 0; virtual void SetVoiceVolume(CVoiceHandle Voice, float Volume) = 0; virtual void SetVoiceFalloff(CVoiceHandle Voice, float Falloff) = 0; - virtual void SetVoiceLocation(CVoiceHandle Voice, float x, float y) = 0; + virtual void SetVoicePosition(CVoiceHandle Voice, vec2 Position) = 0; virtual void SetVoiceTimeOffset(CVoiceHandle Voice, float TimeOffset) = 0; // in s virtual void SetVoiceCircle(CVoiceHandle Voice, float Radius) = 0; virtual void SetVoiceRectangle(CVoiceHandle Voice, float Width, float Height) = 0; - virtual CVoiceHandle PlayAt(int ChannelId, int SampleId, int Flags, float x, float y) = 0; + virtual CVoiceHandle PlayAt(int ChannelId, int SampleId, int Flags, vec2 Position) = 0; virtual CVoiceHandle Play(int ChannelId, int SampleId, int Flags) = 0; virtual void Pause(int SampleId) = 0; virtual void Stop(int SampleId) = 0; diff --git a/src/game/client/components/mapsounds.cpp b/src/game/client/components/mapsounds.cpp index 0ddae91c2..05eafd829 100644 --- a/src/game/client/components/mapsounds.cpp +++ b/src/game/client/components/mapsounds.cpp @@ -239,7 +239,7 @@ void CMapSounds::OnRender() x -= pGroup->m_OffsetX; y -= pGroup->m_OffsetY; - Sound()->SetVoiceLocation(Voice.m_Voice, x, y); + Sound()->SetVoicePosition(Voice.m_Voice, vec2(x, y)); ColorRGBA Volume = ColorRGBA(1.0f, 0.0f, 0.0f, 0.0f); CMapLayers::EnvelopeEval(Voice.m_pSource->m_SoundEnvOffset, Voice.m_pSource->m_SoundEnv, Volume, 1, &m_pClient->m_MapLayersBackground); diff --git a/src/game/client/components/sounds.cpp b/src/game/client/components/sounds.cpp index 776b3e304..8717bf1e7 100644 --- a/src/game/client/components/sounds.cpp +++ b/src/game/client/components/sounds.cpp @@ -143,9 +143,7 @@ void CSounds::OnRender() return; } - // set listener pos - Sound()->SetListenerPos(m_pClient->m_Camera.m_Center.x, m_pClient->m_Camera.m_Center.y); - + Sound()->SetListenerPosition(m_pClient->m_Camera.m_Center); UpdateChannels(); // play sound from queue @@ -224,7 +222,7 @@ void CSounds::PlayAt(int Channel, int SetId, float Vol, vec2 Pos) if(Channel == CHN_MUSIC) Flags = ISound::FLAG_LOOP; - Sound()->PlayAt(Channel, SampleId, Flags, Pos.x, Pos.y); + Sound()->PlayAt(Channel, SampleId, Flags, Pos); } void CSounds::Stop(int SetId) @@ -269,5 +267,5 @@ ISound::CVoiceHandle CSounds::PlaySampleAt(int Channel, int SampleId, float Vol, if(Channel == CHN_MUSIC) Flags |= ISound::FLAG_LOOP; - return Sound()->PlayAt(Channel, SampleId, Flags, Pos.x, Pos.y); + return Sound()->PlayAt(Channel, SampleId, Flags, Pos); } From cc7aa4cb8efce6372a7b4f1e58cd8cb28e803758 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sun, 26 May 2024 11:22:57 +0200 Subject: [PATCH 4/4] Add volume parameter to sound play functions, fix unused volume The functions of the client component `CSounds` had a volume parameter which was unused. In some cases, the wrong value (`0`, presumably for the flags) was passed as the volume, which is now changed to `1.0f`. The player ground skid sound was previously set to play only at `0.25f` volume though this parameter was unused, which is also changed to `1.0f` to preserve the historic behavior. A parameter is added to the engine sound play functions to directly set the volume without having to acquire the lock again. Fix sound position not being respected for hook hit and ground jump sounds as the position parameter was ignored in the `CSounds::PlayAndRecord` function. Add TODOs for issues with this function for demo recording. Parameters are ordered consistently and default parameter values are removed. Duplicate code in the `CSounds` play functions is reduced by reusing the `PlaySample`/`PlaySampleAt` functions. --- src/engine/client/sound.cpp | 12 +++--- src/engine/client/sound.h | 6 +-- src/engine/sound.h | 4 +- src/game/client/components/chat.cpp | 6 +-- src/game/client/components/mapsounds.cpp | 8 ++-- src/game/client/components/mapsounds.h | 2 +- src/game/client/components/players.cpp | 2 +- src/game/client/components/sounds.cpp | 53 +++++++----------------- src/game/client/components/sounds.h | 10 ++--- src/game/client/components/voting.cpp | 2 +- src/game/editor/editor.cpp | 2 +- 11 files changed, 42 insertions(+), 65 deletions(-) diff --git a/src/engine/client/sound.cpp b/src/engine/client/sound.cpp index c04fd1db7..63df6cdb5 100644 --- a/src/engine/client/sound.cpp +++ b/src/engine/client/sound.cpp @@ -820,7 +820,7 @@ void CSound::SetVoiceRectangle(CVoiceHandle Voice, float Width, float Height) m_aVoices[VoiceId].m_Rectangle.m_Height = maximum(0.0f, Height); } -ISound::CVoiceHandle CSound::Play(int ChannelId, int SampleId, int Flags, vec2 Position) +ISound::CVoiceHandle CSound::Play(int ChannelId, int SampleId, int Flags, float Volume, vec2 Position) { const CLockScope LockScope(m_SoundLock); @@ -856,7 +856,7 @@ ISound::CVoiceHandle CSound::Play(int ChannelId, int SampleId, int Flags, vec2 P { m_aVoices[VoiceId].m_Tick = 0; } - m_aVoices[VoiceId].m_Vol = 255; + m_aVoices[VoiceId].m_Vol = (int)(clamp(Volume, 0.0f, 1.0f) * 255.0f); m_aVoices[VoiceId].m_Flags = Flags; m_aVoices[VoiceId].m_Position = Position; m_aVoices[VoiceId].m_Falloff = 0.0f; @@ -868,14 +868,14 @@ ISound::CVoiceHandle CSound::Play(int ChannelId, int SampleId, int Flags, vec2 P return CreateVoiceHandle(VoiceId, Age); } -ISound::CVoiceHandle CSound::PlayAt(int ChannelId, int SampleId, int Flags, vec2 Position) +ISound::CVoiceHandle CSound::PlayAt(int ChannelId, int SampleId, int Flags, float Volume, vec2 Position) { - return Play(ChannelId, SampleId, Flags | ISound::FLAG_POS, Position); + return Play(ChannelId, SampleId, Flags | ISound::FLAG_POS, Volume, Position); } -ISound::CVoiceHandle CSound::Play(int ChannelId, int SampleId, int Flags) +ISound::CVoiceHandle CSound::Play(int ChannelId, int SampleId, int Flags, float Volume) { - return Play(ChannelId, SampleId, Flags, vec2(0.0f, 0.0f)); + return Play(ChannelId, SampleId, Flags, Volume, vec2(0.0f, 0.0f)); } void CSound::Pause(int SampleId) diff --git a/src/engine/client/sound.h b/src/engine/client/sound.h index dfd166abb..f7cc4b82c 100644 --- a/src/engine/client/sound.h +++ b/src/engine/client/sound.h @@ -124,9 +124,9 @@ public: void SetVoiceCircle(CVoiceHandle Voice, float Radius) override REQUIRES(!m_SoundLock); void SetVoiceRectangle(CVoiceHandle Voice, float Width, float Height) override REQUIRES(!m_SoundLock); - CVoiceHandle Play(int ChannelId, int SampleId, int Flags, vec2 Position) REQUIRES(!m_SoundLock); - CVoiceHandle PlayAt(int ChannelId, int SampleId, int Flags, vec2 Position) override REQUIRES(!m_SoundLock); - CVoiceHandle Play(int ChannelId, int SampleId, int Flags) override REQUIRES(!m_SoundLock); + CVoiceHandle Play(int ChannelId, int SampleId, int Flags, float Volume, vec2 Position) REQUIRES(!m_SoundLock); + CVoiceHandle PlayAt(int ChannelId, int SampleId, int Flags, float Volume, vec2 Position) override REQUIRES(!m_SoundLock); + CVoiceHandle Play(int ChannelId, int SampleId, int Flags, float Volume) override REQUIRES(!m_SoundLock); void Pause(int SampleId) override REQUIRES(!m_SoundLock); void Stop(int SampleId) override REQUIRES(!m_SoundLock); void StopAll() override REQUIRES(!m_SoundLock); diff --git a/src/engine/sound.h b/src/engine/sound.h index 846aa8aa4..e4462a95a 100644 --- a/src/engine/sound.h +++ b/src/engine/sound.h @@ -86,8 +86,8 @@ public: virtual void SetVoiceCircle(CVoiceHandle Voice, float Radius) = 0; virtual void SetVoiceRectangle(CVoiceHandle Voice, float Width, float Height) = 0; - virtual CVoiceHandle PlayAt(int ChannelId, int SampleId, int Flags, vec2 Position) = 0; - virtual CVoiceHandle Play(int ChannelId, int SampleId, int Flags) = 0; + virtual CVoiceHandle PlayAt(int ChannelId, int SampleId, int Flags, float Volume, vec2 Position) = 0; + virtual CVoiceHandle Play(int ChannelId, int SampleId, int Flags, float Volume) = 0; virtual void Pause(int SampleId) = 0; virtual void Stop(int SampleId) = 0; virtual void StopAll() = 0; diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index c31098abc..877978726 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -822,7 +822,7 @@ void CChat::AddLine(int ClientId, int Team, const char *pLine) { if(g_Config.m_SndServerMessage) { - m_pClient->m_Sounds.Play(CSounds::CHN_GUI, SOUND_CHAT_SERVER, 0); + m_pClient->m_Sounds.Play(CSounds::CHN_GUI, SOUND_CHAT_SERVER, 1.0f); m_aLastSoundPlayed[CHAT_SERVER] = Now; } } @@ -840,7 +840,7 @@ void CChat::AddLine(int ClientId, int Team, const char *pLine) Client()->Notify("DDNet Chat", aBuf); if(g_Config.m_SndHighlight) { - m_pClient->m_Sounds.Play(CSounds::CHN_GUI, SOUND_CHAT_HIGHLIGHT, 0); + m_pClient->m_Sounds.Play(CSounds::CHN_GUI, SOUND_CHAT_HIGHLIGHT, 1.0f); m_aLastSoundPlayed[CHAT_HIGHLIGHT] = Now; } @@ -863,7 +863,7 @@ void CChat::AddLine(int ClientId, int Team, const char *pLine) #endif if(PlaySound) { - m_pClient->m_Sounds.Play(CSounds::CHN_GUI, SOUND_CHAT_CLIENT, 0); + m_pClient->m_Sounds.Play(CSounds::CHN_GUI, SOUND_CHAT_CLIENT, 1.0f); m_aLastSoundPlayed[CHAT_CLIENT] = Now; } } diff --git a/src/game/client/components/mapsounds.cpp b/src/game/client/components/mapsounds.cpp index 05eafd829..eee0017fc 100644 --- a/src/game/client/components/mapsounds.cpp +++ b/src/game/client/components/mapsounds.cpp @@ -22,15 +22,15 @@ void CMapSounds::Play(int SoundId) if(SoundId < 0 || SoundId >= m_Count) return; - m_pClient->m_Sounds.PlaySample(CSounds::CHN_MAPSOUND, m_aSounds[SoundId], 1.0f, 0); + m_pClient->m_Sounds.PlaySample(CSounds::CHN_MAPSOUND, m_aSounds[SoundId], 0, 1.0f); } -void CMapSounds::PlayAt(int SoundId, vec2 Pos) +void CMapSounds::PlayAt(int SoundId, vec2 Position) { if(SoundId < 0 || SoundId >= m_Count) return; - m_pClient->m_Sounds.PlaySampleAt(CSounds::CHN_MAPSOUND, m_aSounds[SoundId], 1.0f, Pos, 0); + m_pClient->m_Sounds.PlaySampleAt(CSounds::CHN_MAPSOUND, m_aSounds[SoundId], 0, 1.0f, Position); } void CMapSounds::OnMapLoad() @@ -163,7 +163,7 @@ void CMapSounds::OnRender() if(!Source.m_pSource->m_Pan) Flags |= ISound::FLAG_NO_PANNING; - Source.m_Voice = m_pClient->m_Sounds.PlaySampleAt(CSounds::CHN_MAPSOUND, m_aSounds[Source.m_Sound], 1.0f, vec2(fx2f(Source.m_pSource->m_Position.x), fx2f(Source.m_pSource->m_Position.y)), Flags); + Source.m_Voice = m_pClient->m_Sounds.PlaySampleAt(CSounds::CHN_MAPSOUND, m_aSounds[Source.m_Sound], Flags, 1.0f, vec2(fx2f(Source.m_pSource->m_Position.x), fx2f(Source.m_pSource->m_Position.y))); Sound()->SetVoiceTimeOffset(Source.m_Voice, Offset); Sound()->SetVoiceFalloff(Source.m_Voice, Source.m_pSource->m_Falloff / 255.0f); switch(Source.m_pSource->m_Shape.m_Type) diff --git a/src/game/client/components/mapsounds.h b/src/game/client/components/mapsounds.h index 2f89d402b..a623303aa 100644 --- a/src/game/client/components/mapsounds.h +++ b/src/game/client/components/mapsounds.h @@ -34,7 +34,7 @@ public: virtual int Sizeof() const override { return sizeof(*this); } void Play(int SoundId); - void PlayAt(int SoundId, vec2 Pos); + void PlayAt(int SoundId, vec2 Position); virtual void OnMapLoad() override; virtual void OnRender() override; diff --git a/src/game/client/components/players.cpp b/src/game/client/components/players.cpp index 85ea937ba..3876c5331 100644 --- a/src/game/client/components/players.cpp +++ b/src/game/client/components/players.cpp @@ -526,7 +526,7 @@ void CPlayers::RenderPlayer( if(time() - m_SkidSoundTime > time_freq() / 10) { if(g_Config.m_SndGame) - m_pClient->m_Sounds.PlayAt(CSounds::CHN_WORLD, SOUND_PLAYER_SKID, 0.25f, Position); + m_pClient->m_Sounds.PlayAt(CSounds::CHN_WORLD, SOUND_PLAYER_SKID, 1.0f, Position); m_SkidSoundTime = time(); } diff --git a/src/game/client/components/sounds.cpp b/src/game/client/components/sounds.cpp index 8717bf1e7..d04a20fdf 100644 --- a/src/game/client/components/sounds.cpp +++ b/src/game/client/components/sounds.cpp @@ -180,49 +180,26 @@ void CSounds::Enqueue(int Channel, int SetId) m_aQueue[m_QueuePos++].m_SetId = SetId; } -void CSounds::PlayAndRecord(int Channel, int SetId, float Vol, vec2 Pos) +void CSounds::PlayAndRecord(int Channel, int SetId, float Volume, vec2 Position) { + // TODO: Volume and position are currently not recorded for sounds played with this function + // TODO: This also causes desync sounds during demo playback of demos recorded on high ping servers: + // https://github.com/ddnet/ddnet/issues/1282 CNetMsg_Sv_SoundGlobal Msg; Msg.m_SoundId = SetId; Client()->SendPackMsgActive(&Msg, MSGFLAG_NOSEND | MSGFLAG_RECORD); - Play(Channel, SetId, Vol); + PlayAt(Channel, SetId, Volume, Position); } -void CSounds::Play(int Channel, int SetId, float Vol) +void CSounds::Play(int Channel, int SetId, float Volume) { - if(m_pClient->m_SuppressEvents) - return; - if(Channel == CHN_MUSIC && !g_Config.m_SndMusic) - return; - - int SampleId = GetSampleId(SetId); - if(SampleId == -1) - return; - - int Flags = 0; - if(Channel == CHN_MUSIC) - Flags = ISound::FLAG_LOOP; - - Sound()->Play(Channel, SampleId, Flags); + PlaySample(Channel, GetSampleId(SetId), 0, Volume); } -void CSounds::PlayAt(int Channel, int SetId, float Vol, vec2 Pos) +void CSounds::PlayAt(int Channel, int SetId, float Volume, vec2 Position) { - if(m_pClient->m_SuppressEvents) - return; - if(Channel == CHN_MUSIC && !g_Config.m_SndMusic) - return; - - int SampleId = GetSampleId(SetId); - if(SampleId == -1) - return; - - int Flags = 0; - if(Channel == CHN_MUSIC) - Flags = ISound::FLAG_LOOP; - - Sound()->PlayAt(Channel, SampleId, Flags, Pos); + PlaySampleAt(Channel, GetSampleId(SetId), 0, Volume, Position); } void CSounds::Stop(int SetId) @@ -248,24 +225,24 @@ bool CSounds::IsPlaying(int SetId) return false; } -ISound::CVoiceHandle CSounds::PlaySample(int Channel, int SampleId, float Vol, int Flags) +ISound::CVoiceHandle CSounds::PlaySample(int Channel, int SampleId, int Flags, float Volume) { - if((Channel == CHN_MUSIC && !g_Config.m_SndMusic) || SampleId == -1) + if(m_pClient->m_SuppressEvents || (Channel == CHN_MUSIC && !g_Config.m_SndMusic) || SampleId == -1) return ISound::CVoiceHandle(); if(Channel == CHN_MUSIC) Flags |= ISound::FLAG_LOOP; - return Sound()->Play(Channel, SampleId, Flags); + return Sound()->Play(Channel, SampleId, Flags, Volume); } -ISound::CVoiceHandle CSounds::PlaySampleAt(int Channel, int SampleId, float Vol, vec2 Pos, int Flags) +ISound::CVoiceHandle CSounds::PlaySampleAt(int Channel, int SampleId, int Flags, float Volume, vec2 Position) { - if((Channel == CHN_MUSIC && !g_Config.m_SndMusic) || SampleId == -1) + if(m_pClient->m_SuppressEvents || (Channel == CHN_MUSIC && !g_Config.m_SndMusic) || SampleId == -1) return ISound::CVoiceHandle(); if(Channel == CHN_MUSIC) Flags |= ISound::FLAG_LOOP; - return Sound()->PlayAt(Channel, SampleId, Flags, Pos); + return Sound()->PlayAt(Channel, SampleId, Flags, Volume, Position); } diff --git a/src/game/client/components/sounds.h b/src/game/client/components/sounds.h index b412425da..8671f3bf8 100644 --- a/src/game/client/components/sounds.h +++ b/src/game/client/components/sounds.h @@ -61,14 +61,14 @@ public: void ClearQueue(); void Enqueue(int Channel, int SetId); - void Play(int Channel, int SetId, float Vol); - void PlayAt(int Channel, int SetId, float Vol, vec2 Pos); - void PlayAndRecord(int Channel, int SetId, float Vol, vec2 Pos); + void Play(int Channel, int SetId, float Volume); + void PlayAt(int Channel, int SetId, float Volume, vec2 Position); + void PlayAndRecord(int Channel, int SetId, float Volume, vec2 Position); void Stop(int SetId); bool IsPlaying(int SetId); - ISound::CVoiceHandle PlaySample(int Channel, int SampleId, float Vol, int Flags = 0); - ISound::CVoiceHandle PlaySampleAt(int Channel, int SampleId, float Vol, vec2 Pos, int Flags = 0); + ISound::CVoiceHandle PlaySample(int Channel, int SampleId, int Flags, float Volume); + ISound::CVoiceHandle PlaySampleAt(int Channel, int SampleId, int Flags, float Volume, vec2 Position); }; #endif diff --git a/src/game/client/components/voting.cpp b/src/game/client/components/voting.cpp index 8a0282fdb..462a14e8d 100644 --- a/src/game/client/components/voting.cpp +++ b/src/game/client/components/voting.cpp @@ -269,7 +269,7 @@ void CVoting::OnMessage(int MsgType, void *pRawMsg) char aBuf[512]; str_format(aBuf, sizeof(aBuf), "%s (%s)", m_aDescription, m_aReason); Client()->Notify("DDNet Vote", aBuf); - m_pClient->m_Sounds.Play(CSounds::CHN_GUI, SOUND_CHAT_HIGHLIGHT, 0); + m_pClient->m_Sounds.Play(CSounds::CHN_GUI, SOUND_CHAT_HIGHLIGHT, 1.0f); } } } diff --git a/src/game/editor/editor.cpp b/src/game/editor/editor.cpp index 39e957dab..439c8b870 100644 --- a/src/game/editor/editor.cpp +++ b/src/game/editor/editor.cpp @@ -956,7 +956,7 @@ void CEditor::DoAudioPreview(CUIRect View, const void *pPlayPauseButtonId, const if(SampleId != m_ToolbarPreviewSound && m_ToolbarPreviewSound >= 0 && Sound()->IsPlaying(m_ToolbarPreviewSound)) Sound()->Pause(m_ToolbarPreviewSound); - Sound()->Play(CSounds::CHN_GUI, SampleId, ISound::FLAG_PREVIEW); + Sound()->Play(CSounds::CHN_GUI, SampleId, ISound::FLAG_PREVIEW, 1.0f); } } }