mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-10 10:08:18 +00:00
Implement sound logic for shaped sounds, fix rectangle height property in editor and submit voice shape information to audio interface
This commit is contained in:
parent
485aa4ce54
commit
98d42adf9d
|
@ -40,7 +40,7 @@ struct CChannel
|
|||
{
|
||||
int m_Vol;
|
||||
int m_Pan;
|
||||
} ;
|
||||
};
|
||||
|
||||
struct CVoice
|
||||
{
|
||||
|
@ -51,7 +51,15 @@ struct CVoice
|
|||
int m_Vol; // 0 - 255
|
||||
int m_Flags;
|
||||
int m_X, m_Y;
|
||||
} ;
|
||||
float m_Falloff; // [0.0, 1.0]
|
||||
|
||||
int m_Shape;
|
||||
union
|
||||
{
|
||||
ISound::CVoiceShapeCircle m_Circle;
|
||||
ISound::CVoiceShapeRectangle m_Rectangle;
|
||||
};
|
||||
};
|
||||
|
||||
static CSample m_aSamples[NUM_SAMPLES] = { {0} };
|
||||
static CVoice m_aVoices[NUM_VOICES] = { {0} };
|
||||
|
@ -134,20 +142,79 @@ static void Mix(short *pFinalOut, unsigned Frames)
|
|||
// TODO: we should respect the channel panning value
|
||||
int dx = v->m_X - m_CenterX;
|
||||
int dy = v->m_Y - m_CenterY;
|
||||
int Dist = (int)sqrtf((float)dx*dx+dy*dy); // float here. nasty
|
||||
//
|
||||
int p = IntAbs(dx);
|
||||
int Range = DefaultDistance;
|
||||
if(Dist >= 0 && Dist < Range)
|
||||
float FalloffX = 0.0f;
|
||||
float FalloffY = 0.0f;
|
||||
|
||||
int RangeX = 0; // for panning
|
||||
bool InVoiceField = false;
|
||||
|
||||
switch(v->m_Shape)
|
||||
{
|
||||
case ISound::SHAPE_CIRCLE:
|
||||
{
|
||||
float r = v->m_Circle.m_Radius;
|
||||
RangeX = r;
|
||||
|
||||
int Dist = (int)sqrtf((float)dx*dx+dy*dy); // nasty float
|
||||
if(Dist < r)
|
||||
{
|
||||
InVoiceField = true;
|
||||
|
||||
// falloff
|
||||
int FalloffDistance = r*v->m_Falloff;
|
||||
if(Dist > FalloffDistance)
|
||||
FalloffX = FalloffY = (r-Dist)/(r-FalloffDistance);
|
||||
else
|
||||
FalloffX = FalloffY = 1.0f;
|
||||
}
|
||||
else
|
||||
InVoiceField = false;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ISound::SHAPE_RECTANGLE:
|
||||
{
|
||||
RangeX = v->m_Rectangle.m_Width/2.0f;
|
||||
|
||||
int abs_dx = abs(dx);
|
||||
int abs_dy = abs(dy);
|
||||
|
||||
int w = v->m_Rectangle.m_Width/2.0f;
|
||||
int h = v->m_Rectangle.m_Height/2.0f;
|
||||
|
||||
if(abs_dx < w && abs_dy < h)
|
||||
{
|
||||
InVoiceField = true;
|
||||
|
||||
// falloff
|
||||
int fx = v->m_Falloff * w;
|
||||
int fy = v->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;
|
||||
}
|
||||
else
|
||||
InVoiceField = false;
|
||||
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
if(InVoiceField)
|
||||
{
|
||||
// panning
|
||||
if(dx > 0)
|
||||
Lvol = ((Range-p)*Lvol)/Range;
|
||||
Lvol = ((RangeX-p)*Lvol)/RangeX;
|
||||
else
|
||||
Rvol = ((Range-p)*Rvol)/Range;
|
||||
Rvol = ((RangeX-p)*Rvol)/RangeX;
|
||||
|
||||
// falloff
|
||||
Lvol = (Lvol*(Range-Dist))/Range;
|
||||
Rvol = (Rvol*(Range-Dist))/Range;
|
||||
{
|
||||
Lvol *= FalloffX;
|
||||
Rvol *= FalloffY;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -645,6 +712,20 @@ void CSound::SetVoiceVolume(CVoiceHandle Voice, float Volume)
|
|||
m_aVoices[VoiceID].m_Vol = (int)(Volume*255.0f);
|
||||
}
|
||||
|
||||
void CSound::SetVoiceFalloff(CVoiceHandle Voice, float Falloff)
|
||||
{
|
||||
if(!Voice.IsValid())
|
||||
return;
|
||||
|
||||
int VoiceID = Voice.Id();
|
||||
|
||||
if(m_aVoices[VoiceID].m_Age != Voice.Age())
|
||||
return;
|
||||
|
||||
Falloff = clamp(Falloff, 0.0f, 1.0f);
|
||||
m_aVoices[VoiceID].m_Falloff = Falloff;
|
||||
}
|
||||
|
||||
void CSound::SetVoiceLocation(CVoiceHandle Voice, float x, float y)
|
||||
{
|
||||
if(!Voice.IsValid())
|
||||
|
@ -696,6 +777,35 @@ void CSound::SetVoiceTimeOffset(CVoiceHandle Voice, float offset)
|
|||
lock_release(m_SoundLock);
|
||||
}
|
||||
|
||||
void CSound::SetVoiceCircle(CVoiceHandle Voice, float Radius)
|
||||
{
|
||||
if(!Voice.IsValid())
|
||||
return;
|
||||
|
||||
int VoiceID = Voice.Id();
|
||||
|
||||
if(m_aVoices[VoiceID].m_Age != Voice.Age())
|
||||
return;
|
||||
|
||||
m_aVoices[VoiceID].m_Shape = ISound::SHAPE_CIRCLE;
|
||||
m_aVoices[VoiceID].m_Circle.m_Radius = max(0.0f, Radius);
|
||||
}
|
||||
|
||||
void CSound::SetVoiceRectangle(CVoiceHandle Voice, float Width, float Height)
|
||||
{
|
||||
if(!Voice.IsValid())
|
||||
return;
|
||||
|
||||
int VoiceID = Voice.Id();
|
||||
|
||||
if(m_aVoices[VoiceID].m_Age != Voice.Age())
|
||||
return;
|
||||
|
||||
m_aVoices[VoiceID].m_Shape = ISound::SHAPE_RECTANGLE;
|
||||
m_aVoices[VoiceID].m_Rectangle.m_Width = max(0.0f, Width);
|
||||
m_aVoices[VoiceID].m_Rectangle.m_Height = max(0.0f, Height);
|
||||
}
|
||||
|
||||
void CSound::SetChannel(int ChannelID, float Vol, float Pan)
|
||||
{
|
||||
m_aChannels[ChannelID].m_Vol = (int)(Vol*255.0f);
|
||||
|
@ -735,6 +845,9 @@ ISound::CVoiceHandle CSound::Play(int ChannelID, int SampleID, int Flags, float
|
|||
m_aVoices[VoiceID].m_Flags = Flags;
|
||||
m_aVoices[VoiceID].m_X = (int)x;
|
||||
m_aVoices[VoiceID].m_Y = (int)y;
|
||||
m_aVoices[VoiceID].m_Falloff = 0.0f;
|
||||
m_aVoices[VoiceID].m_Shape = ISound::SHAPE_CIRCLE;
|
||||
m_aVoices[VoiceID].m_Circle.m_Radius = DefaultDistance;
|
||||
Age = m_aVoices[VoiceID].m_Age;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,9 +41,13 @@ public:
|
|||
virtual void SetChannel(int ChannelID, float Vol, float Pan);
|
||||
|
||||
virtual void SetVoiceVolume(CVoiceHandle Voice, float Volume);
|
||||
virtual void SetVoiceFalloff(CVoiceHandle Voice, float Falloff);
|
||||
virtual void SetVoiceLocation(CVoiceHandle Voice, float x, float y);
|
||||
virtual void SetVoiceTimeOffset(CVoiceHandle Voice, float offset); // in s
|
||||
|
||||
virtual void SetVoiceCircle(CVoiceHandle Voice, float Radius);
|
||||
virtual void SetVoiceRectangle(CVoiceHandle Voice, float Width, float Height);
|
||||
|
||||
CVoiceHandle Play(int ChannelID, int SampleID, int Flags, float x, float y);
|
||||
virtual CVoiceHandle PlayAt(int ChannelID, int SampleID, int Flags, float x, float y);
|
||||
virtual CVoiceHandle Play(int ChannelID, int SampleID, int Flags);
|
||||
|
|
|
@ -16,6 +16,23 @@ public:
|
|||
FLAG_ALL=3
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
SHAPE_CIRCLE,
|
||||
SHAPE_RECTANGLE,
|
||||
};
|
||||
|
||||
struct CVoiceShapeCircle
|
||||
{
|
||||
float m_Radius;
|
||||
};
|
||||
|
||||
struct CVoiceShapeRectangle
|
||||
{
|
||||
float m_Width;
|
||||
float m_Height;
|
||||
};
|
||||
|
||||
class CVoiceHandle
|
||||
{
|
||||
friend class ISound;
|
||||
|
@ -48,9 +65,13 @@ public:
|
|||
virtual void SetListenerPos(float x, float y) = 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 SetVoiceTimeOffset(CVoiceHandle Voice, float offset) = 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 void Stop(int SampleID) = 0;
|
||||
|
|
|
@ -123,6 +123,21 @@ void CMapSounds::OnRender()
|
|||
|
||||
pSource->m_Voice = m_pClient->m_pSounds->PlaySampleAt(CSounds::CHN_MAPSOUND, m_aSounds[pSource->m_Sound], 1.0f, vec2(fx2f(pSource->m_pSource->m_Position.x), fx2f(pSource->m_pSource->m_Position.y)), Flags);
|
||||
Sound()->SetVoiceTimeOffset(pSource->m_Voice, offset);
|
||||
Sound()->SetVoiceFalloff(pSource->m_Voice, pSource->m_pSource->m_Falloff/255.0f);
|
||||
switch(pSource->m_pSource->m_Shape.m_Type)
|
||||
{
|
||||
case CSoundShape::SHAPE_CIRCLE:
|
||||
{
|
||||
Sound()->SetVoiceCircle(pSource->m_Voice, pSource->m_pSource->m_Shape.m_Circle.m_Radius);
|
||||
break;
|
||||
}
|
||||
|
||||
case CSoundShape::SHAPE_RECTANGLE:
|
||||
{
|
||||
Sound()->SetVoiceRectangle(pSource->m_Voice, fx2f(pSource->m_pSource->m_Shape.m_Rectangle.m_Width), fx2f(pSource->m_pSource->m_Shape.m_Rectangle.m_Height));
|
||||
break;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
@ -782,7 +782,7 @@ int CEditor::PopupSource(CEditor *pEditor, CUIRect View)
|
|||
pEditor->m_Map.m_Modified = true;
|
||||
|
||||
if(Prop == PROP_RECTANGLE_WIDTH) pSource->m_Shape.m_Rectangle.m_Width = NewVal*1024;
|
||||
//if(Prop == PROP_RECTANGLE_HEIGHT) pSource->m_Shape.m_Rectangle.m_Height = NewVal*1024;
|
||||
if(Prop == PROP_RECTANGLE_HEIGHT) pSource->m_Shape.m_Rectangle.m_Height = NewVal*1024;
|
||||
|
||||
break;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue