Skip to content

Commit

Permalink
Merge pull request ddnet#9023 from Robyt3/Sound-Volume-Position-Refac…
Browse files Browse the repository at this point in the history
…toring

Add volume parameter to sound play functions, fix unused volume, refactoring
  • Loading branch information
def- authored Sep 24, 2024
2 parents f9df4a8 + cc7aa4c commit 8715a64
Show file tree
Hide file tree
Showing 11 changed files with 119 additions and 168 deletions.
82 changes: 31 additions & 51 deletions src/engine/client/sound.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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 int abs_dx = absolute(dx);
const int abs_dy = absolute(dy);
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 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;
}
};
Expand All @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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;
Expand All @@ -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)
Expand Down Expand Up @@ -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, float Volume, vec2 Position)
{
const CLockScope LockScope(m_SoundLock);

Expand Down Expand Up @@ -875,10 +856,9 @@ ISound::CVoiceHandle CSound::Play(int ChannelId, int SampleId, int Flags, float
{
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_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;
Expand All @@ -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, float Volume, vec2 Position)
{
return Play(ChannelId, SampleId, Flags | ISound::FLAG_POS, x, y);
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, 0, 0);
return Play(ChannelId, SampleId, Flags, Volume, vec2(0.0f, 0.0f));
}

void CSound::Pause(int SampleId)
Expand Down
18 changes: 10 additions & 8 deletions src/engine/client/sound.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -76,8 +76,10 @@ class CSound : public IEngineSound
int m_NextVoice = 0;
uint32_t m_MaxFrames = 0;

std::atomic<int> m_CenterX = 0;
std::atomic<int> m_CenterY = 0;
// This is not an std::atomic<vec2> as this would require linking with
// libatomic with clang x86 as there is no native support for this.
std::atomic<float> m_ListenerPositionX = 0.0f;
std::atomic<float> m_ListenerPositionY = 0.0f;
std::atomic<int> m_SoundVolume = 100;
int m_MixingRate = 48000;

Expand Down Expand Up @@ -112,19 +114,19 @@ class CSound : public IEngineSound
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) 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);
Expand Down
10 changes: 6 additions & 4 deletions src/engine/sound.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#include <engine/kernel.h>
#include <engine/storage.h>

#include <base/vmath.h>

class ISound : public IInterface
{
MACRO_INTERFACE("sound")
Expand Down Expand Up @@ -74,18 +76,18 @@ class ISound : public IInterface
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 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;
Expand Down
6 changes: 3 additions & 3 deletions src/game/client/components/chat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
Expand All @@ -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;
}

Expand All @@ -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;
}
}
Expand Down
10 changes: 5 additions & 5 deletions src/game/client/components/mapsounds.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion src/game/client/components/mapsounds.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class CMapSounds : public CComponent
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;
Expand Down
2 changes: 1 addition & 1 deletion src/game/client/components/players.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}

Expand Down
Loading

0 comments on commit 8715a64

Please sign in to comment.