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); }