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/EngineSoundServer.cpp | |
| download | archived-source-engine-2018-hl2-src-3bf9df6b2785fa6d951086978a3e66f49427166a.tar.xz archived-source-engine-2018-hl2-src-3bf9df6b2785fa6d951086978a3e66f49427166a.zip | |
Diffstat (limited to 'engine/EngineSoundServer.cpp')
| -rw-r--r-- | engine/EngineSoundServer.cpp | 455 |
1 files changed, 455 insertions, 0 deletions
diff --git a/engine/EngineSoundServer.cpp b/engine/EngineSoundServer.cpp new file mode 100644 index 0000000..7433033 --- /dev/null +++ b/engine/EngineSoundServer.cpp @@ -0,0 +1,455 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include "engine/IEngineSound.h" +#include "tier0/dbg.h" +#include "quakedef.h" +#include "vox.h" +#include "server.h" +#include "sv_main.h" +#include "edict.h" +#include "sound.h" +#include "host.h" +#include "vengineserver_impl.h" +#include "enginesingleuserfilter.h" +#include "snd_audio_source.h" +#include "soundchars.h" +#include "tier0/vprof.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +//----------------------------------------------------------------------------- +// +// Server-side implementation of the engine sound interface +// +//----------------------------------------------------------------------------- +class CEngineSoundServer : public IEngineSound +{ +public: + // constructor, destructor + CEngineSoundServer(); + virtual ~CEngineSoundServer(); + + 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 ); + + // Set the room type for a player + virtual void SetRoomType( IRecipientFilter& filter, int roomType ); + virtual void SetPlayerDSP( IRecipientFilter& filter, int dspType, bool fastReset ); + + // emit an "ambient" sound that isn't spatialized - specify left/right volume + // only available on the client, assert on server + 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() + { + Warning( "Can't call GetGuidForLastSoundEmitted from server\n" ); + return 0; + } + virtual bool IsSoundStillPlaying( int guid ) + { + Warning( "Can't call IsSoundStillPlaying from server\n" ); + return false; + } + virtual void StopSoundByGuid( int guid ) + { + Warning( "Can't call StopSoundByGuid from server\n" ); + return; + } + + // Retrieves list of all active sounds + virtual void GetActiveSounds( CUtlVector< SndInfo_t >& sndlist ) + { + Warning( "Can't call GetActiveSounds from server\n" ); + return; + } + + // Set's master volume (0.0->1.0) + virtual void SetVolumeByGuid( int guid, float fvol ) + { + Warning( "Can't call SetVolumeByGuid from server\n" ); + return; + } + virtual void PrecacheSentenceGroup( const char *pGroupName ) + { + VOX_PrecacheSentenceGroup( this, pGroupName ); + } + virtual void NotifyBeginMoviePlayback() + { + AssertMsg( 0, "Not supported" ); + } + + virtual void NotifyEndMoviePlayback() + { + AssertMsg( 0, "Not supported" ); + } + + +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 CEngineSoundServer s_EngineSoundServer; +EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CEngineSoundServer, IEngineSound, + IENGINESOUND_SERVER_INTERFACE_VERSION, s_EngineSoundServer ); + +IEngineSound *EngineSoundServer() +{ + return &s_EngineSoundServer; +} + + + +//----------------------------------------------------------------------------- +// constructor, destructor +//----------------------------------------------------------------------------- +CEngineSoundServer::CEngineSoundServer() +{ +} + +CEngineSoundServer::~CEngineSoundServer() +{ +} + + +//----------------------------------------------------------------------------- +// Precache a particular sample +//----------------------------------------------------------------------------- +bool CEngineSoundServer::PrecacheSound( const char *pSample, bool bPreload, bool bIsUISound ) +{ + int i; + + if ( pSample && TestSoundChar( pSample, CHAR_SENTENCE ) ) + { + return true; + } + + if ( pSample[0] <= ' ' ) + { + Host_Error( "CEngineSoundServer::PrecacheSound: Bad string: %s", pSample ); + } + + // add the sound to the precache list + // Start at 1, since 0 is used to indicate an error in the sound precache + i = SV_FindOrAddSound( pSample, bPreload ); + if ( i >= 0 ) + return true; + + Host_Error( "CEngineSoundServer::PrecacheSound: '%s' overflow", pSample ); + return false; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *pSample - +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool CEngineSoundServer::IsSoundPrecached( const char *pSample ) +{ + if ( pSample && TestSoundChar(pSample, CHAR_SENTENCE) ) + { + return true; + } + + int idx = SV_SoundIndex( pSample ); + if ( idx == -1 ) + { + return false; + } + + return true; +} + +void CEngineSoundServer::PrefetchSound( const char *pSample ) +{ + if ( pSample && TestSoundChar(pSample, CHAR_SENTENCE) ) + { + return; + } + + int idx = SV_SoundIndex( pSample ); + if ( idx == -1 ) + { + return; + } + + // Tell clients to prefetch the sound + SVC_Prefetch msg; + msg.m_fType = SVC_Prefetch::SOUND; + msg.m_nSoundIndex = idx; + + sv.BroadcastMessage( msg, true, false ); +} + +//----------------------------------------------------------------------------- +// Stops a sound +//----------------------------------------------------------------------------- +void CEngineSoundServer::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*/ ) +{ + AssertMsg( pDirection == NULL, "Direction specification not currently supported on server sounds" ); + AssertMsg( bUpdatePositions, "Non-updated positions not currently supported on server sounds" ); + + 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; + } + + edict_t *pEdict = (iEntIndex >= 0) ? &sv.edicts[iEntIndex] : NULL; + SV_StartSound( filter, pEdict, iChannel, pSample, flVolume, iSoundLevel, + iFlags, iPitch, iSpecialDSP, pOrigin, soundtime, speakerentity, pUtlVecOrigins ); +} + + +//----------------------------------------------------------------------------- +// Plays a sentence +//----------------------------------------------------------------------------- +void CEngineSoundServer::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*/ ) +{ + 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, bUpdatePositions, soundtime, speakerentity ); + } +} + + +//----------------------------------------------------------------------------- +// Emits a sound +//----------------------------------------------------------------------------- +void CEngineSoundServer::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( "CEngineSoundServer::EmitSound" ); + EmitSound( filter, iEntIndex, iChannel, pSample, flVolume, ATTN_TO_SNDLVL( flAttenuation ), iFlags, + iPitch, iSpecialDSP, pOrigin, pDirection, pUtlVecOrigins, bUpdatePositions, soundtime, speakerentity ); +} + + +void CEngineSoundServer::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( "CEngineSoundServer::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 ); + } +} + +void BuildRecipientList( CUtlVector< edict_t * >& list, const IRecipientFilter& filter ) +{ + int c = filter.GetRecipientCount(); + for ( int i = 0; i < c; i++ ) + { + int playerindex = filter.GetRecipientIndex( i ); + if ( playerindex < 1 || playerindex > sv.GetClientCount() ) + continue; + + CGameClient *cl = sv.Client( playerindex - 1 ); + // Never output to bots + if ( cl->IsFakeClient() ) + continue; + + if ( !cl->IsSpawned() ) + continue; + + list.AddToTail( cl->edict ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : filter - +// roomType - +//----------------------------------------------------------------------------- +void CEngineSoundServer::SetRoomType( IRecipientFilter& filter, int roomType ) +{ + CUtlVector< edict_t * > players; + BuildRecipientList( players, filter ); + + for ( int i = 0 ; i < players.Count(); i++ ) + { + g_pVEngineServer->ClientCommand( players[ i ], "room_type %i\n", roomType ); + } +} + +// Set the dsp preset for a player (client only) +//----------------------------------------------------------------------------- +// Purpose: +// Input : filter - +// dspType - +//----------------------------------------------------------------------------- +void CEngineSoundServer::SetPlayerDSP( IRecipientFilter& filter, int dspType, bool fastReset ) +{ + Assert( !fastReset ); + if ( fastReset ) + { + Warning( "SetPlayerDSP: fastReset only valid from client\n" ); + } + + CUtlVector< edict_t * > players; + BuildRecipientList( players, filter ); + + for ( int i = 0 ; i < players.Count(); i++ ) + { + g_pVEngineServer->ClientCommand( players[ i ], "dsp_player %i\n", dspType ); + } +} + +void CEngineSoundServer::StopAllSounds(bool bClearBuffers) +{ + AssertMsg( 0, "Not supported" ); +} + +void CEngineSoundServer::EmitAmbientSound( const char *pSample, float flVolume, int iPitch, int flags, float soundtime /*= 0.0f*/ ) +{ + AssertMsg( 0, "Not supported" ); +} + +//----------------------------------------------------------------------------- +// Stops a sound +//----------------------------------------------------------------------------- +void CEngineSoundServer::StopSound( int iEntIndex, int iChannel, const char *pSample ) +{ + CEngineRecipientFilter filter; + filter.AddAllPlayers(); + filter.MakeReliable(); + + EmitSound( filter, iEntIndex, iChannel, pSample, 0, SNDLVL_NONE, SND_STOP, PITCH_NORM, 0, + NULL, NULL, NULL, true ); +} + +float SV_GetSoundDuration( const char *pSample ) +{ +#ifdef SWDS + return 0; // TODO: make this return a real value (i.e implement an OS independent version of the sound code) +#else + return AudioSource_GetSoundDuration( PSkipSoundChars( pSample ) ); +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *pSample - +// Output : float +//----------------------------------------------------------------------------- +float CEngineSoundServer::GetSoundDuration( const char *pSample ) +{ + return Host_GetSoundDuration( pSample ); +} + +float CEngineSoundServer::GetDistGainFromSoundLevel( soundlevel_t soundlevel, float dist ) +{ + return S_GetGainFromSoundLevel( soundlevel, dist ); +} + +/* +//----------------------------------------------------------------------------- +// FIXME: Move into the CEngineSoundServer class? +//----------------------------------------------------------------------------- +void Host_RestartAmbientSounds() +{ + if (!sv.active) + { + return; + } + + +#ifndef SWDS + const int NUM_INFOS = 64; + SoundInfo_t soundInfo[NUM_INFOS]; + + int nSounds = S_GetCurrentStaticSounds( soundInfo, NUM_INFOS, CHAN_STATIC ); + + for ( int i = 0; i < nSounds; i++) + { + if (soundInfo[i].looping && + soundInfo[i].entity != -1 ) + { + Msg("Restarting sound %s...\n", soundInfo[i].name); + S_StopSound(soundInfo[i].entity, soundInfo[i].channel); + CEngineRecipientFilter filter; + filter.AddAllPlayers(); + + SV_StartSound( filter, EDICT_NUM(soundInfo[i].entity), + CHAN_STATIC, + soundInfo[i].name, + soundInfo[i].volume, + soundInfo[i].soundlevel, + 0, // @Q (toml 05-09-02): Is this correct, or will I need to squirrel away the original flags? + soundInfo[i].pitch ); + } + } +#endif +} */ + + + |