diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /engine/EngineSoundClient.cpp | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'engine/EngineSoundClient.cpp')
| -rw-r--r-- | engine/EngineSoundClient.cpp | 510 |
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 +} + |