summaryrefslogtreecommitdiff
path: root/engine/EngineSoundServer.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/EngineSoundServer.cpp
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'engine/EngineSoundServer.cpp')
-rw-r--r--engine/EngineSoundServer.cpp455
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
+} */
+
+
+