Team Fortress 2 Source Code as on 22/4/2020
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.

278 lines
6.7 KiB

  1. //========= Copyright 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. //-----------------------------------------------------------------------------
  19. // External interfaces
  20. //-----------------------------------------------------------------------------
  21. IAudioDevice *g_pAudioDevice = NULL;
  22. ISoundSystem *g_pSoundSystem = NULL;
  23. IDataCache *g_pDataCache = 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. private:
  51. struct CSoundFile
  52. {
  53. char filename[ 512 ];
  54. CAudioSource *source;
  55. long filetime;
  56. };
  57. IAudioDevice *m_pAudioDevice;
  58. float m_flElapsedTime;
  59. CUtlVector < CSoundFile > m_ActiveSounds;
  60. };
  61. //-----------------------------------------------------------------------------
  62. // Singleton interface
  63. //-----------------------------------------------------------------------------
  64. static CSoundSystem s_SoundSystem;
  65. EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CSoundSystem, ISoundSystem, SOUNDSYSTEM_INTERFACE_VERSION, s_SoundSystem );
  66. //-----------------------------------------------------------------------------
  67. // Connect, disconnect
  68. //-----------------------------------------------------------------------------
  69. bool CSoundSystem::Connect( CreateInterfaceFn factory )
  70. {
  71. if ( !BaseClass::Connect( factory ) )
  72. return false;
  73. g_pDataCache = (IDataCache*)factory( DATACACHE_INTERFACE_VERSION, NULL );
  74. g_pSoundSystem = this;
  75. return (g_pFullFileSystem != NULL) && (g_pDataCache != NULL);
  76. }
  77. void CSoundSystem::Disconnect()
  78. {
  79. g_pSoundSystem = NULL;
  80. g_pDataCache = NULL;
  81. BaseClass::Disconnect();
  82. }
  83. //-----------------------------------------------------------------------------
  84. // Query interface
  85. //-----------------------------------------------------------------------------
  86. void *CSoundSystem::QueryInterface( const char *pInterfaceName )
  87. {
  88. if (!Q_strncmp( pInterfaceName, SOUNDSYSTEM_INTERFACE_VERSION, Q_strlen(SOUNDSYSTEM_INTERFACE_VERSION) + 1))
  89. return (ISoundSystem*)this;
  90. return NULL;
  91. }
  92. //-----------------------------------------------------------------------------
  93. // Init, shutdown
  94. //-----------------------------------------------------------------------------
  95. InitReturnVal_t CSoundSystem::Init()
  96. {
  97. InitReturnVal_t nRetVal = BaseClass::Init();
  98. if ( nRetVal != INIT_OK )
  99. return nRetVal;
  100. MathLib_Init( 2.2f, 2.2f, 0.0f, 2.0f );
  101. m_flElapsedTime = 0.0f;
  102. m_pAudioDevice = Audio_CreateWaveDevice();
  103. if ( !m_pAudioDevice->Init() )
  104. return INIT_FAILED;
  105. return INIT_OK;
  106. }
  107. void CSoundSystem::Shutdown()
  108. {
  109. Msg( "Removing %i sounds\n", m_ActiveSounds.Size() );
  110. for ( int i = 0 ; i < m_ActiveSounds.Size(); i++ )
  111. {
  112. CSoundFile *p = &m_ActiveSounds[ i ];
  113. Msg( "Removing sound: %s\n", p->filename );
  114. delete p->source;
  115. }
  116. m_ActiveSounds.RemoveAll();
  117. if ( m_pAudioDevice )
  118. {
  119. m_pAudioDevice->Shutdown();
  120. delete m_pAudioDevice;
  121. }
  122. BaseClass::Shutdown();
  123. }
  124. //-----------------------------------------------------------------------------
  125. // Purpose:
  126. //-----------------------------------------------------------------------------
  127. CAudioSource *CSoundSystem::FindOrAddSound( const char *filename )
  128. {
  129. CSoundFile *s;
  130. int i;
  131. for ( i = 0; i < m_ActiveSounds.Size(); i++ )
  132. {
  133. s = &m_ActiveSounds[ i ];
  134. Assert( s );
  135. if ( !stricmp( s->filename, filename ) )
  136. {
  137. long filetime = g_pFullFileSystem->GetFileTime( filename );
  138. if ( filetime != s->filetime )
  139. {
  140. Msg( "Reloading sound %s\n", filename );
  141. delete s->source;
  142. s->source = LoadSound( filename );
  143. s->filetime = filetime;
  144. }
  145. return s->source;
  146. }
  147. }
  148. i = m_ActiveSounds.AddToTail();
  149. s = &m_ActiveSounds[ i ];
  150. strcpy( s->filename, filename );
  151. s->source = LoadSound( filename );
  152. s->filetime = g_pFullFileSystem->GetFileTime( filename );
  153. return s->source;
  154. }
  155. CAudioSource *CSoundSystem::LoadSound( const char *wavfile )
  156. {
  157. if ( !m_pAudioDevice )
  158. return NULL;
  159. CAudioSource *wave = AudioSource_Create( wavfile );
  160. return wave;
  161. }
  162. void CSoundSystem::PlaySound( CAudioSource *source, float volume, CAudioMixer **ppMixer )
  163. {
  164. if ( ppMixer )
  165. {
  166. *ppMixer = NULL;
  167. }
  168. if ( m_pAudioDevice )
  169. {
  170. CAudioMixer *mixer = source->CreateMixer();
  171. if ( ppMixer )
  172. {
  173. *ppMixer = mixer;
  174. }
  175. mixer->SetVolume( volume );
  176. m_pAudioDevice->AddSource( mixer );
  177. }
  178. }
  179. void CSoundSystem::Update( float dt )
  180. {
  181. // closecaptionmanager->PreProcess( g_nSoundFrameCount );
  182. if ( m_pAudioDevice )
  183. {
  184. m_pAudioDevice->Update( m_flElapsedTime );
  185. }
  186. // closecaptionmanager->PostProcess( g_nSoundFrameCount, dt );
  187. m_flElapsedTime += dt;
  188. g_nSoundFrameCount++;
  189. }
  190. void CSoundSystem::Flush( void )
  191. {
  192. if ( m_pAudioDevice )
  193. {
  194. m_pAudioDevice->Flush();
  195. }
  196. }
  197. void CSoundSystem::StopAll( void )
  198. {
  199. if ( m_pAudioDevice )
  200. {
  201. m_pAudioDevice->StopSounds();
  202. }
  203. }
  204. void CSoundSystem::StopSound( CAudioMixer *mixer )
  205. {
  206. int idx = m_pAudioDevice->FindSourceIndex( mixer );
  207. if ( idx != -1 )
  208. {
  209. m_pAudioDevice->FreeChannel( idx );
  210. }
  211. }
  212. bool CSoundSystem::IsSoundPlaying( CAudioMixer *pMixer )
  213. {
  214. if ( !m_pAudioDevice || !pMixer )
  215. return false;
  216. //
  217. int index = m_pAudioDevice->FindSourceIndex( pMixer );
  218. if ( index != -1 )
  219. return true;
  220. return false;
  221. }
  222. CAudioMixer *CSoundSystem::FindMixer( CAudioSource *source )
  223. {
  224. if ( !m_pAudioDevice )
  225. return NULL;
  226. return m_pAudioDevice->GetMixerForSource( source );
  227. }