Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

305 lines
7.3 KiB

  1. //===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose: DLL interface for low-level sound utilities
  4. //
  5. //===========================================================================//
  6. #include "soundsystem/isoundsystem.h"
  7. #include "filesystem.h"
  8. #include "tier1/strtools.h"
  9. #include "tier1/convar.h"
  10. #include "mathlib/mathlib.h"
  11. #include "soundsystem/snd_device.h"
  12. #include "datacache/idatacache.h"
  13. #include "soundchars.h"
  14. #include "tier1/utldict.h"
  15. #include "snd_wave_source.h"
  16. #include "snd_dev_wave.h"
  17. #include "tier2/tier2.h"
  18. // NOTE: This has to be the last file included!
  19. #include "tier0/memdbgon.h"
  20. //-----------------------------------------------------------------------------
  21. // External interfaces
  22. //-----------------------------------------------------------------------------
  23. IAudioDevice *g_pAudioDevice = NULL;
  24. //-----------------------------------------------------------------------------
  25. // Globals
  26. //-----------------------------------------------------------------------------
  27. int g_nSoundFrameCount = 0;
  28. //-----------------------------------------------------------------------------
  29. // Purpose: DLL interface for low-level sound utilities
  30. //-----------------------------------------------------------------------------
  31. class CSoundSystem : public CTier2AppSystem< ISoundSystem >
  32. {
  33. typedef CTier2AppSystem< ISoundSystem > BaseClass;
  34. public:
  35. // Inherited from IAppSystem
  36. virtual bool Connect( CreateInterfaceFn factory );
  37. virtual void Disconnect();
  38. virtual void *QueryInterface( const char *pInterfaceName );
  39. virtual InitReturnVal_t Init();
  40. virtual void Shutdown();
  41. void Update( float dt );
  42. void Flush( void );
  43. CAudioSource *FindOrAddSound( const char *filename );
  44. CAudioSource *LoadSound( const char *wavfile );
  45. void PlaySound( CAudioSource *source, float volume, CAudioMixer **ppMixer );
  46. bool IsSoundPlaying( CAudioMixer *pMixer );
  47. CAudioMixer *FindMixer( CAudioSource *source );
  48. void StopAll( void );
  49. void StopSound( CAudioMixer *mixer );
  50. void GetAudioDevices(CUtlVector< audio_device_description_t >& deviceListOut) const;
  51. private:
  52. struct CSoundFile
  53. {
  54. char filename[ 512 ];
  55. CAudioSource *source;
  56. long filetime;
  57. };
  58. IAudioDevice *m_pAudioDevice;
  59. float m_flElapsedTime;
  60. CUtlVector < CSoundFile > m_ActiveSounds;
  61. };
  62. //-----------------------------------------------------------------------------
  63. // Singleton interface
  64. //-----------------------------------------------------------------------------
  65. static CSoundSystem s_SoundSystem;
  66. EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CSoundSystem, ISoundSystem, SOUNDSYSTEM_INTERFACE_VERSION, s_SoundSystem );
  67. //-----------------------------------------------------------------------------
  68. // Connect, disconnect
  69. //-----------------------------------------------------------------------------
  70. bool CSoundSystem::Connect( CreateInterfaceFn factory )
  71. {
  72. if ( !BaseClass::Connect( factory ) )
  73. return false;
  74. g_pDataCache = (IDataCache*)factory( DATACACHE_INTERFACE_VERSION, NULL );
  75. g_pSoundSystem = this;
  76. return (g_pFullFileSystem != NULL) && (g_pDataCache != NULL);
  77. }
  78. void CSoundSystem::Disconnect()
  79. {
  80. g_pSoundSystem = NULL;
  81. g_pDataCache = NULL;
  82. BaseClass::Disconnect();
  83. }
  84. //-----------------------------------------------------------------------------
  85. // Query interface
  86. //-----------------------------------------------------------------------------
  87. void *CSoundSystem::QueryInterface( const char *pInterfaceName )
  88. {
  89. if (!Q_strncmp( pInterfaceName, SOUNDSYSTEM_INTERFACE_VERSION, Q_strlen(SOUNDSYSTEM_INTERFACE_VERSION) + 1))
  90. return (ISoundSystem*)this;
  91. return NULL;
  92. }
  93. //-----------------------------------------------------------------------------
  94. // Init, shutdown
  95. //-----------------------------------------------------------------------------
  96. InitReturnVal_t CSoundSystem::Init()
  97. {
  98. InitReturnVal_t nRetVal = BaseClass::Init();
  99. if ( nRetVal != INIT_OK )
  100. return nRetVal;
  101. MathLib_Init( 2.2f, 2.2f, 0.0f, 2.0f );
  102. m_flElapsedTime = 0.0f;
  103. m_pAudioDevice = Audio_CreateWaveDevice();
  104. if ( !m_pAudioDevice->Init() )
  105. return INIT_FAILED;
  106. return INIT_OK;
  107. }
  108. void CSoundSystem::Shutdown()
  109. {
  110. Msg( "Removing %i sounds\n", m_ActiveSounds.Count() );
  111. for ( int i = 0 ; i < m_ActiveSounds.Count(); i++ )
  112. {
  113. CSoundFile *p = &m_ActiveSounds[ i ];
  114. Msg( "Removing sound: %s\n", p->filename );
  115. delete p->source;
  116. }
  117. m_ActiveSounds.RemoveAll();
  118. if ( m_pAudioDevice )
  119. {
  120. m_pAudioDevice->Shutdown();
  121. delete m_pAudioDevice;
  122. }
  123. BaseClass::Shutdown();
  124. }
  125. //-----------------------------------------------------------------------------
  126. // Purpose:
  127. //-----------------------------------------------------------------------------
  128. CAudioSource *CSoundSystem::FindOrAddSound( const char *filename )
  129. {
  130. CSoundFile *s;
  131. int i;
  132. for ( i = 0; i < m_ActiveSounds.Count(); i++ )
  133. {
  134. s = &m_ActiveSounds[ i ];
  135. Assert( s );
  136. if ( !stricmp( s->filename, filename ) )
  137. {
  138. long filetime = g_pFullFileSystem->GetFileTime( filename );
  139. if ( filetime != s->filetime )
  140. {
  141. Msg( "Reloading sound %s\n", filename );
  142. delete s->source;
  143. s->source = LoadSound( filename );
  144. s->filetime = filetime;
  145. }
  146. return s->source;
  147. }
  148. }
  149. i = m_ActiveSounds.AddToTail();
  150. s = &m_ActiveSounds[ i ];
  151. strcpy( s->filename, filename );
  152. s->source = LoadSound( filename );
  153. s->filetime = g_pFullFileSystem->GetFileTime( filename );
  154. return s->source;
  155. }
  156. CAudioSource *CSoundSystem::LoadSound( const char *wavfile )
  157. {
  158. if ( !m_pAudioDevice )
  159. return NULL;
  160. CAudioSource *wave = AudioSource_Create( wavfile );
  161. return wave;
  162. }
  163. void CSoundSystem::PlaySound( CAudioSource *source, float volume, CAudioMixer **ppMixer )
  164. {
  165. if ( ppMixer )
  166. {
  167. *ppMixer = NULL;
  168. }
  169. if ( m_pAudioDevice )
  170. {
  171. CAudioMixer *mixer = source->CreateMixer();
  172. if ( ppMixer )
  173. {
  174. *ppMixer = mixer;
  175. }
  176. mixer->SetVolume( volume );
  177. m_pAudioDevice->AddSource( mixer );
  178. }
  179. }
  180. void CSoundSystem::Update( float dt )
  181. {
  182. // closecaptionmanager->PreProcess( g_nSoundFrameCount );
  183. if ( m_pAudioDevice )
  184. {
  185. m_pAudioDevice->Update( m_flElapsedTime );
  186. }
  187. // closecaptionmanager->PostProcess( g_nSoundFrameCount, dt );
  188. m_flElapsedTime += dt;
  189. g_nSoundFrameCount++;
  190. }
  191. void CSoundSystem::Flush( void )
  192. {
  193. if ( m_pAudioDevice )
  194. {
  195. m_pAudioDevice->Flush();
  196. }
  197. }
  198. void CSoundSystem::StopAll( void )
  199. {
  200. if ( m_pAudioDevice )
  201. {
  202. m_pAudioDevice->StopSounds();
  203. }
  204. }
  205. void CSoundSystem::StopSound( CAudioMixer *mixer )
  206. {
  207. int idx = m_pAudioDevice->FindSourceIndex( mixer );
  208. if ( idx != -1 )
  209. {
  210. m_pAudioDevice->FreeChannel( idx );
  211. }
  212. }
  213. static eSubSystems_t GetDefaultAudioSubsystem()
  214. {
  215. eSubSystems_t nSubsystem = AUDIO_SUBSYSTEM_XAUDIO;
  216. #if IS_WINDOWS_PC
  217. if (CommandLine()->CheckParm("-directsound"))
  218. {
  219. nSubsystem = AUDIO_SUBSYSTEM_DSOUND;
  220. }
  221. #endif
  222. return nSubsystem;
  223. }
  224. void CSoundSystem::GetAudioDevices(CUtlVector< audio_device_description_t >& deviceListOut) const
  225. {
  226. CAudioDeviceList list;
  227. eSubSystems_t nSubsystem = GetDefaultAudioSubsystem();
  228. list.BuildDeviceList(nSubsystem);
  229. deviceListOut = list.m_list;
  230. }
  231. bool CSoundSystem::IsSoundPlaying( CAudioMixer *pMixer )
  232. {
  233. if ( !m_pAudioDevice || !pMixer )
  234. return false;
  235. //
  236. int index = m_pAudioDevice->FindSourceIndex( pMixer );
  237. if ( index != -1 )
  238. return true;
  239. return false;
  240. }
  241. CAudioMixer *CSoundSystem::FindMixer( CAudioSource *source )
  242. {
  243. if ( !m_pAudioDevice )
  244. return NULL;
  245. return m_pAudioDevice->GetMixerForSource( source );
  246. }