summaryrefslogtreecommitdiff
path: root/engine/EngineSoundClient.cpp
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /engine/EngineSoundClient.cpp
downloadarchived-source-engine-2018-hl2-src-3bf9df6b2785fa6d951086978a3e66f49427166a.tar.xz
archived-source-engine-2018-hl2-src-3bf9df6b2785fa6d951086978a3e66f49427166a.zip
Diffstat (limited to 'engine/EngineSoundClient.cpp')
-rw-r--r--engine/EngineSoundClient.cpp510
1 files changed, 510 insertions, 0 deletions
diff --git a/engine/EngineSoundClient.cpp b/engine/EngineSoundClient.cpp
new file mode 100644
index 0000000..d367f24
--- /dev/null
+++ b/engine/EngineSoundClient.cpp
@@ -0,0 +1,510 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#include "engine/IEngineSound.h"
+#include "tier0/dbg.h"
+#include "sound.h"
+#include "client.h"
+#include "vox.h"
+#include "icliententity.h"
+#include "icliententitylist.h"
+#include "enginesingleuserfilter.h"
+#include "snd_audio_source.h"
+#if defined(_X360)
+#include "xmp.h"
+#endif
+#include "tier0/vprof.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+// HACK: expose in sound.h maybe?
+void DSP_FastReset(int dsp);
+
+//-----------------------------------------------------------------------------
+//
+// Client-side implementation of the engine sound interface
+//
+//-----------------------------------------------------------------------------
+class CEngineSoundClient : public IEngineSound
+{
+public:
+ // constructor, destructor
+ CEngineSoundClient();
+ virtual ~CEngineSoundClient();
+
+ virtual bool PrecacheSound( const char *pSample, bool bPreload, bool bIsUISound );
+ virtual bool IsSoundPrecached( const char *pSample );
+ virtual void PrefetchSound( const char *pSample );
+
+ virtual float GetSoundDuration( const char *pSample );
+
+ virtual void EmitSound( IRecipientFilter& filter, int iEntIndex, int iChannel, const char *pSample,
+ float flVolume, float flAttenuation, int iFlags, int iPitch, int iSpecialDSP,
+ const Vector *pOrigin, const Vector *pDirection, CUtlVector< Vector >* pUtlVecOrigins, bool bUpdatePositions, float soundtime = 0.0f, int speakerentity = -1 );
+
+ virtual void EmitSound( IRecipientFilter& filter, int iEntIndex, int iChannel, const char *pSample,
+ float flVolume, soundlevel_t iSoundLevel, int iFlags, int iPitch, int iSpecialDSP,
+ const Vector *pOrigin, const Vector *pDirection, CUtlVector< Vector >* pUtlVecOrigins, bool bUpdatePositions, float soundtime = 0.0f, int speakerentity = -1 );
+
+ virtual void EmitSentenceByIndex( IRecipientFilter& filter, int iEntIndex, int iChannel, int iSentenceIndex,
+ float flVolume, soundlevel_t iSoundLevel, int iFlags, int iPitch, int iSpecialDSP,
+ const Vector *pOrigin, const Vector *pDirection, CUtlVector< Vector >* pUtlVecOrigins, bool bUpdatePositions, float soundtime = 0.0f, int speakerentity = -1 );
+
+ virtual void StopSound( int iEntIndex, int iChannel, const char *pSample );
+
+ virtual void StopAllSounds(bool bClearBuffers);
+
+ virtual void SetRoomType( IRecipientFilter& filter, int roomType );
+ virtual void SetPlayerDSP( IRecipientFilter& filter, int dspType, bool fastReset );
+
+ virtual void EmitAmbientSound( const char *pSample, float flVolume,
+ int iPitch, int flags, float soundtime = 0.0f );
+
+ virtual float GetDistGainFromSoundLevel( soundlevel_t soundlevel, float dist );
+
+ // Client .dll only functions
+ virtual int GetGuidForLastSoundEmitted();
+ virtual bool IsSoundStillPlaying( int guid );
+ virtual void StopSoundByGuid( int guid );
+ // Set's master volume (0.0->1.0)
+ virtual void SetVolumeByGuid( int guid, float fvol );
+
+ // Retrieves list of all active sounds
+ virtual void GetActiveSounds( CUtlVector< SndInfo_t >& sndlist );
+
+ virtual void PrecacheSentenceGroup( const char *pGroupName );
+ virtual void NotifyBeginMoviePlayback();
+ virtual void NotifyEndMoviePlayback();
+
+private:
+ void EmitSoundInternal( IRecipientFilter& filter, int iEntIndex, int iChannel, const char *pSample,
+ float flVolume, soundlevel_t iSoundLevel, int iFlags, int iPitch, int iSpecialDSP,
+ const Vector *pOrigin, const Vector *pDirection, CUtlVector< Vector >* pUtlVecOrigins, bool bUpdatePositions, float soundtime = 0.0f, int speakerentity = -1 );
+
+};
+
+
+//-----------------------------------------------------------------------------
+// Client-server neutral sound interface accessor
+//-----------------------------------------------------------------------------
+static CEngineSoundClient s_EngineSoundClient;
+EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CEngineSoundClient, IEngineSound,
+ IENGINESOUND_CLIENT_INTERFACE_VERSION, s_EngineSoundClient );
+
+IEngineSound *EngineSoundClient()
+{
+ return &s_EngineSoundClient;
+}
+
+
+//-----------------------------------------------------------------------------
+// constructor, destructor
+//-----------------------------------------------------------------------------
+CEngineSoundClient::CEngineSoundClient()
+{
+}
+
+CEngineSoundClient::~CEngineSoundClient()
+{
+}
+
+
+//-----------------------------------------------------------------------------
+// Precache a particular sample
+//-----------------------------------------------------------------------------
+bool CEngineSoundClient::PrecacheSound( const char *pSample, bool bPreload, bool bIsUISound )
+{
+ CSfxTable *pTable = S_PrecacheSound( pSample );
+ if ( pTable )
+ {
+ if ( bIsUISound )
+ {
+ S_MarkUISound( pTable );
+ }
+ return true;
+ }
+
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : *pSample -
+//-----------------------------------------------------------------------------
+void CEngineSoundClient::PrefetchSound( const char *pSample )
+{
+ S_PrefetchSound( pSample, true );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : *pSample -
+// Output : Returns true on success, false on failure.
+//-----------------------------------------------------------------------------
+bool CEngineSoundClient::IsSoundPrecached( const char *pSample )
+{
+ if ( pSample && TestSoundChar(pSample, CHAR_SENTENCE) )
+ {
+ return true;
+ }
+
+ int idx = cl.LookupSoundIndex( pSample );
+ if ( idx == -1 )
+ return false;
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Actually does the work of emitting a sound
+//-----------------------------------------------------------------------------
+void CEngineSoundClient::EmitSoundInternal( IRecipientFilter& filter, int iEntIndex, int iChannel, const char *pSample,
+ float flVolume, soundlevel_t iSoundLevel, int iFlags, int iPitch, int iSpecialDSP,
+ const Vector *pOrigin, const Vector *pDirection, CUtlVector< Vector >* pUtlVecOrigins, bool bUpdatePositions, float soundtime /*= 0.0f*/, int speakerentity /*= -1*/ )
+{
+ tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s", __FUNCTION__ );
+ if (flVolume < 0 || flVolume > 1)
+ {
+ Warning ("EmitSound: volume out of bounds = %f\n", flVolume);
+ return;
+ }
+
+ if ( ( iSoundLevel < soundlevel_t(MIN_SNDLVL_VALUE) ) || ( iSoundLevel > soundlevel_t(MAX_SNDLVL_VALUE) ) )
+ {
+ Warning ("EmitSound: soundlevel out of bounds = %d\n", iSoundLevel);
+ return;
+ }
+
+ if (iPitch < 0 || iPitch > 255)
+ {
+ Warning ("EmitSound: pitch out of bounds = %i\n", iPitch);
+ return;
+ }
+
+ int iSoundSource = iEntIndex;
+
+ // Handle client UI sounds
+ if ( iSoundSource != SOUND_FROM_UI_PANEL )
+ {
+ if (iSoundSource < 0)
+ iSoundSource = cl.m_nViewEntity;
+
+ // See if local player is a recipient
+ int i = 0;
+ int c = filter.GetRecipientCount();
+ for ( ; i < c ; i++ )
+ {
+ int index = filter.GetRecipientIndex( i );
+ if ( index == cl.m_nPlayerSlot + 1 )
+ break;
+ }
+
+ // Local player not receiving sound
+ if ( i >= c )
+ return;
+ }
+
+ CSfxTable *pSound = S_PrecacheSound(pSample);
+ if (!pSound)
+ return;
+
+ Vector vecDummyOrigin;
+ Vector vecDirection;
+ if ( iSoundSource == SOUND_FROM_UI_PANEL )
+ {
+ vecDummyOrigin.Init();
+ vecDirection.Init();
+ pOrigin = &vecDummyOrigin;
+ pDirection = &vecDirection;
+ }
+ else
+ {
+ // Point at origin if they didn't specify a sound source.
+ if (!pOrigin)
+ {
+ // Try to use the origin of the entity
+ IClientEntity *pEnt = entitylist->GetClientEntity( iEntIndex );
+ // don't update position if we stop this sound
+ if (pEnt && !(iFlags & SND_STOP) )
+ {
+ vecDummyOrigin = pEnt->GetRenderOrigin();
+ }
+ else
+ {
+ vecDummyOrigin.Init();
+ }
+
+ pOrigin = &vecDummyOrigin;
+ }
+
+ if (!pDirection)
+ {
+ IClientEntity *pEnt = entitylist->GetClientEntity( iEntIndex );
+ if (pEnt && !(iFlags & SND_STOP))
+ {
+ QAngle angles;
+ angles = pEnt->GetAbsAngles();
+ AngleVectors( angles, &vecDirection );
+ }
+ else
+ {
+ vecDirection.Init();
+ }
+
+ pDirection = &vecDirection;
+ }
+ }
+
+ if ( pUtlVecOrigins )
+ {
+ (*pUtlVecOrigins).AddToTail( *pOrigin );
+ }
+
+ float delay = 0.0f;
+ if ( soundtime != 0.0f )
+ {
+ // this sound was played directly on the client, use its clock sync
+ delay = S_ComputeDelayForSoundtime( soundtime, CLOCK_SYNC_CLIENT );
+#if 0
+ static float lastSoundTime = 0;
+ Msg("[%.3f] Play %s at %.3f %.1fsms delay\n", soundtime - lastSoundTime, pSample, soundtime, delay * 1000.0f );
+ lastSoundTime = soundtime;
+#endif
+ // anything over 250ms is assumed to be intentional skipping
+ if ( delay <= 0 && delay > -0.250f )
+ {
+ // leave a little delay to flag the channel in the low-level sound system
+ delay = 1e-6f;
+ }
+ }
+
+ StartSoundParams_t params;
+ params.staticsound = iChannel == CHAN_STATIC;
+ params.soundsource = iSoundSource;
+ params.entchannel = iChannel;
+ params.pSfx = pSound;
+ params.origin = *pOrigin;
+ params.direction = *pDirection;
+ params.bUpdatePositions = bUpdatePositions;
+ params.fvol = flVolume;
+ params.soundlevel = iSoundLevel;
+ params.flags = iFlags;
+ params.pitch = iPitch;
+ params.specialdsp = iSpecialDSP;
+ params.fromserver = false;
+ params.delay = delay;
+ params.speakerentity = speakerentity;
+
+ S_StartSound( params );
+}
+
+
+//-----------------------------------------------------------------------------
+// Plays a sentence
+//-----------------------------------------------------------------------------
+void CEngineSoundClient::EmitSentenceByIndex( IRecipientFilter& filter, int iEntIndex, int iChannel,
+ int iSentenceIndex, float flVolume, soundlevel_t iSoundLevel, int iFlags, int iPitch, int iSpecialDSP,
+ const Vector *pOrigin, const Vector *pDirection, CUtlVector< Vector >* pUtlVecOrigins, bool bUpdatePosition, float soundtime /*= 0.0f*/, int speakerentity /*= -1*/ )
+{
+ if ( iSentenceIndex >= 0 )
+ {
+ char pName[8];
+ Q_snprintf( pName, sizeof(pName), "!%d", iSentenceIndex );
+ EmitSoundInternal( filter, iEntIndex, iChannel, pName, flVolume, iSoundLevel,
+ iFlags, iPitch, iSpecialDSP, pOrigin, pDirection, pUtlVecOrigins, bUpdatePosition, soundtime, speakerentity );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Emits a sound
+//-----------------------------------------------------------------------------
+void CEngineSoundClient::EmitSound( IRecipientFilter& filter, int iEntIndex, int iChannel, const char *pSample,
+ float flVolume, float flAttenuation, int iFlags, int iPitch, int iSpecialDSP,
+ const Vector *pOrigin, const Vector *pDirection, CUtlVector< Vector >* pUtlVecOrigins, bool bUpdatePositions, float soundtime /*= 0.0f*/, int speakerentity /*= -1*/ )
+{
+ VPROF( "CEngineSoundClient::EmitSound" );
+ EmitSound( filter, iEntIndex, iChannel, pSample, flVolume, ATTN_TO_SNDLVL( flAttenuation ), iFlags,
+ iPitch, iSpecialDSP, pOrigin, pDirection, pUtlVecOrigins, bUpdatePositions, soundtime, speakerentity );
+
+}
+
+
+void CEngineSoundClient::EmitSound( IRecipientFilter& filter, int iEntIndex, int iChannel, const char *pSample,
+ float flVolume, soundlevel_t iSoundLevel, int iFlags, int iPitch, int iSpecialDSP,
+ const Vector *pOrigin, const Vector *pDirection, CUtlVector< Vector >* pUtlVecOrigins, bool bUpdatePositions, float soundtime /*= 0.0f*/, int speakerentity /*= -1*/ )
+{
+ VPROF( "CEngineSoundClient::EmitSound" );
+ if ( pSample && TestSoundChar(pSample, CHAR_SENTENCE) )
+ {
+ int iSentenceIndex = -1;
+ VOX_LookupString( PSkipSoundChars(pSample), &iSentenceIndex );
+ if (iSentenceIndex >= 0)
+ {
+ EmitSentenceByIndex( filter, iEntIndex, iChannel, iSentenceIndex, flVolume,
+ iSoundLevel, iFlags, iPitch, iSpecialDSP, pOrigin, pDirection, pUtlVecOrigins, bUpdatePositions, soundtime, speakerentity );
+ }
+ else
+ {
+ DevWarning( 2, "Unable to find %s in sentences.txt\n", PSkipSoundChars(pSample));
+ }
+ }
+ else
+ {
+ EmitSoundInternal( filter, iEntIndex, iChannel, pSample, flVolume, iSoundLevel,
+ iFlags, iPitch, iSpecialDSP, pOrigin, pDirection, pUtlVecOrigins, bUpdatePositions, soundtime, speakerentity );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Stops a sound
+//-----------------------------------------------------------------------------
+void CEngineSoundClient::StopSound( int iEntIndex, int iChannel, const char *pSample )
+{
+ CEngineSingleUserFilter filter( cl.m_nPlayerSlot + 1 );
+ EmitSound( filter, iEntIndex, iChannel, pSample, 0, SNDLVL_NONE, SND_STOP, PITCH_NORM, 0,
+ NULL, NULL, NULL, true );
+}
+
+
+void CEngineSoundClient::SetRoomType( IRecipientFilter& filter, int roomType )
+{
+ extern ConVar dsp_room;
+ dsp_room.SetValue( roomType );
+}
+
+void CEngineSoundClient::SetPlayerDSP( IRecipientFilter& filter, int dspType, bool fastReset )
+{
+ extern ConVar dsp_player;
+ dsp_player.SetValue( dspType );
+ if ( fastReset )
+ {
+ DSP_FastReset( dspType );
+ }
+}
+
+
+void CEngineSoundClient::EmitAmbientSound( const char *pSample, float flVolume,
+ int iPitch, int flags, float soundtime /*= 0.0f*/ )
+{
+ float delay = 0.0f;
+ if ( soundtime != 0.0f )
+ {
+ delay = soundtime - cl.m_flLastServerTickTime;
+ }
+
+ CSfxTable *pSound = S_PrecacheSound(pSample);
+
+ StartSoundParams_t params;
+ params.staticsound = true;
+ params.soundsource = SOUND_FROM_LOCAL_PLAYER;
+ params.entchannel = CHAN_STATIC;
+ params.pSfx = pSound;
+ params.origin = vec3_origin;
+ params.fvol = flVolume;
+ params.soundlevel = SNDLVL_NONE;
+ params.flags = flags;
+ params.pitch = iPitch;
+ params.specialdsp = 0;
+ params.fromserver = false;
+ params.delay = delay;
+
+ S_StartSound( params );
+}
+
+void CEngineSoundClient::StopAllSounds(bool bClearBuffers)
+{
+ S_StopAllSounds( bClearBuffers );
+}
+
+float CEngineSoundClient::GetDistGainFromSoundLevel( soundlevel_t soundlevel, float dist )
+{
+ return S_GetGainFromSoundLevel( soundlevel, dist );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : *pSample -
+// Output : float
+//-----------------------------------------------------------------------------
+float CEngineSoundClient::GetSoundDuration( const char *pSample )
+{
+ return AudioSource_GetSoundDuration( pSample );
+}
+
+// Client .dll only functions
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : -
+// Output : int
+//-----------------------------------------------------------------------------
+int CEngineSoundClient::GetGuidForLastSoundEmitted()
+{
+ return S_GetGuidForLastSoundEmitted();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : guid -
+// Output : Returns true on success, false on failure.
+//-----------------------------------------------------------------------------
+bool CEngineSoundClient::IsSoundStillPlaying( int guid )
+{
+ return S_IsSoundStillPlaying( guid );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : guid -
+//-----------------------------------------------------------------------------
+void CEngineSoundClient::StopSoundByGuid( int guid )
+{
+ S_StopSoundByGuid( guid );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Retrieves list of all active sounds
+// Input : sndlist -
+//-----------------------------------------------------------------------------
+void CEngineSoundClient::GetActiveSounds( CUtlVector< SndInfo_t >& sndlist )
+{
+ S_GetActiveSounds( sndlist );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Set's master volume (0.0->1.0)
+// Input : guid -
+// fvol -
+//-----------------------------------------------------------------------------
+void CEngineSoundClient::SetVolumeByGuid( int guid, float fvol )
+{
+ S_SetVolumeByGuid( guid, fvol );
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+void CEngineSoundClient::PrecacheSentenceGroup( const char *pGroupName )
+{
+ VOX_PrecacheSentenceGroup( this, pGroupName );
+}
+
+void CEngineSoundClient::NotifyBeginMoviePlayback()
+{
+ StopAllSounds(true);
+#if _X360
+ XMPOverrideBackgroundMusic();
+#endif
+}
+
+void CEngineSoundClient::NotifyEndMoviePlayback()
+{
+#if _X360
+ XMPRestoreBackgroundMusic();
+#endif
+}
+