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.

263 lines
9.6 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: This abstracts the various hardware dependent implementations of sound
  4. // At the time of this writing there are Windows WAVEOUT, Direct Sound,
  5. // and Null implementations.
  6. //
  7. //=====================================================================================//
  8. #ifndef SOUNDSYSTEM_LOWLEVEL_H
  9. #define SOUNDSYSTEM_LOWLEVEL_H
  10. #pragma once
  11. #include "utlvector.h"
  12. #define SOUND_DEVICE_MAX_CHANNELS 8 // we support 2, 4, 6, & 8 channels currently.
  13. // Long term we may build 4 & 8 as matrix mix-downs of 6 channels
  14. #define MIX_BUFFER_SIZE 512
  15. class IAudioDevice2;
  16. struct audio_device_init_params_t;
  17. class ALIGN16 CAudioMixBuffer
  18. {
  19. public:
  20. float m_flData[MIX_BUFFER_SIZE];
  21. } ALIGN16_POST;
  22. const float MIX_DEFAULT_SAMPLING_RATE = 44100.0f;
  23. const float SECONDS_PER_SAMPLE = (1.0f / MIX_DEFAULT_SAMPLING_RATE);
  24. const float MIX_SECONDS_PER_BUFFER = float( MIX_BUFFER_SIZE ) / float( MIX_DEFAULT_SAMPLING_RATE );
  25. const float MIX_BUFFERS_PER_SECOND = float( MIX_DEFAULT_SAMPLING_RATE ) / float( MIX_BUFFER_SIZE );
  26. enum eSubSystems_t
  27. {
  28. AUDIO_SUBSYSTEM_XAUDIO = 0,
  29. AUDIO_SUBSYSTEM_DSOUND = 1,
  30. AUDIO_SUBSYSTEM_SDL = 2,
  31. AUDIO_SUBSYSTEM_NULL = 3, // fake, emulated device for failure cases
  32. };
  33. #define AUDIO_DEVICE_NAME_MAX 256
  34. struct audio_device_description_t
  35. {
  36. wchar_t m_deviceName[AUDIO_DEVICE_NAME_MAX];
  37. char m_friendlyName[AUDIO_DEVICE_NAME_MAX];
  38. uint8 m_nSubsystemId;
  39. uint8 m_nChannelCount;
  40. bool m_bIsDefault : 1;
  41. bool m_bIsAvailable : 1;
  42. audio_device_description_t() {}
  43. explicit audio_device_description_t( eSubSystems_t nSubsystem ) : m_nSubsystemId( (uint8)nSubsystem ) { Assert( nSubsystem >= 0 && nSubsystem <= UINT8_MAX ); }
  44. inline void InitAsNullDevice()
  45. {
  46. V_memset( m_deviceName, 0, sizeof(m_deviceName) );
  47. V_memset( m_friendlyName, 0, sizeof(m_friendlyName) );
  48. m_nChannelCount = 2;
  49. m_nSubsystemId = AUDIO_SUBSYSTEM_NULL;
  50. m_bIsDefault = true;
  51. m_bIsAvailable = true;
  52. }
  53. };
  54. class CAudioDeviceList
  55. {
  56. public:
  57. eSubSystems_t m_nSubsystem;
  58. CUtlVector<audio_device_description_t> m_list;
  59. int m_nDefaultDevice;
  60. CAudioDeviceList() {}
  61. void BuildDeviceList( eSubSystems_t nPreferredSubsystem );
  62. bool UpdateDeviceList(); // returns true if new devices or defaults show up
  63. audio_device_description_t *FindDeviceById( const char *pId ); // returns NULL if not found
  64. audio_device_description_t *GetDefaultDevice(); // returns NULL if not set
  65. bool IsValid() { return m_list.Count() > 0; }
  66. IAudioDevice2 *CreateDevice( audio_device_init_params_t &params );
  67. const wchar_t *GetDeviceToCreate( audio_device_init_params_t &params );
  68. private:
  69. uint m_nDeviceStamp;
  70. void UpdateDefaultDevice();
  71. enum finddevice_t
  72. {
  73. FIND_ANY_DEVICE = 0,
  74. FIND_AVAILABLE_DEVICE_ONLY = 1,
  75. };
  76. int FindDeviceById( const wchar_t *pId, finddevice_t nFind );
  77. };
  78. #define DEFAULT_MIX_BUFFER_COUNT 4
  79. #define DEFAULT_MIX_BUFFER_SAMPLE_COUNT MIX_BUFFER_SIZE
  80. struct audio_device_init_params_t
  81. {
  82. const audio_device_description_t *m_pDesc;
  83. void *m_pWindowHandle;
  84. int m_nOutputBufferCount;
  85. int m_nSampleCountPerOutputBuffer;
  86. int m_nOverrideSpeakerConfig; // only used if m_bOverrideSpeakerConfig is true
  87. bool m_bOverrideDevice; // If this is set use m_overrideDevice
  88. bool m_bOverrideSpeakerConfig;
  89. bool m_bPlayEvenWhenNotInFocus;
  90. // When we set the override device it is important to copy the memory since
  91. // the original device description may get realloced and thus become a stale
  92. // pointer.
  93. wchar_t m_overrideDeviceName[AUDIO_DEVICE_NAME_MAX];
  94. int m_nOverrideSubsystem;
  95. inline void OverrideDevice( audio_device_description_t *pDevice )
  96. {
  97. m_bOverrideDevice = true;
  98. V_wcscpy_safe( m_overrideDeviceName, pDevice->m_deviceName );
  99. m_nOverrideSubsystem = pDevice->m_nSubsystemId;
  100. }
  101. inline void OverrideSpeakerConfig( int nSpeakerConfig )
  102. {
  103. Assert(nSpeakerConfig >= 0 && nSpeakerConfig < 8);
  104. m_nOverrideSpeakerConfig = nSpeakerConfig;
  105. m_bOverrideSpeakerConfig = true;
  106. }
  107. audio_device_init_params_t() : m_bOverrideSpeakerConfig(false), m_bOverrideDevice(false) {}
  108. inline void Defaults()
  109. {
  110. m_nOutputBufferCount = DEFAULT_MIX_BUFFER_COUNT;
  111. m_nSampleCountPerOutputBuffer = MIX_BUFFER_SIZE;
  112. m_bOverrideDevice = false;
  113. m_bOverrideSpeakerConfig = false;
  114. m_nOverrideSpeakerConfig = 0;
  115. m_bPlayEvenWhenNotInFocus = true;
  116. m_pWindowHandle = NULL;
  117. }
  118. };
  119. extern int Audio_EnumerateDevices( eSubSystems_t nSubsystem, audio_device_description_t *pDeviceListOut, int nListCount );
  120. extern int Audio_EnumerateXAudio2Devices( audio_device_description_t *pDeviceListOut, int nListCount );
  121. extern int Audio_EnumerateDSoundDevices( audio_device_description_t *pDeviceListOut, int nListCount );
  122. #ifdef POSIX
  123. extern int Audio_EnumerateSDLDevices( audio_device_description_t *pDeviceListOut, int nListCount );
  124. #endif
  125. // return true if there was an error event and the device needs to be restarted
  126. extern bool Audio_PollErrorEvents();
  127. class IAudioDevice2
  128. {
  129. public:
  130. virtual ~IAudioDevice2() {}
  131. virtual void OutputBuffer( int nChannels, CAudioMixBuffer *pChannelArray ) = 0;
  132. virtual void Shutdown( void ) = 0;
  133. virtual int QueuedBufferCount() = 0;
  134. virtual int EmptyBufferCount() = 0;
  135. virtual void CancelOutput( void ) = 0;
  136. virtual void WaitForComplete() = 0;
  137. virtual void UpdateFocus( bool bWindowHasFocus ) = 0;
  138. virtual void ClearBuffer() = 0;
  139. virtual const wchar_t *GetDeviceID() const = 0;
  140. virtual void OutputDebugInfo() const = 0;
  141. virtual bool SetShouldPlayWhenNotInFocus( bool bPlayEvenWhenNotInFocus ) = 0;
  142. inline const char *Name() const { return m_pName; }
  143. inline int ChannelCount() const { return m_nChannels; }
  144. inline int MixChannelCount() const { return m_nChannels > 6 ? 6 : m_nChannels; } // 7.1 mixes as 5.1
  145. inline int BitsPerSample() const { return m_nSampleBits; }
  146. inline int SampleRate() const { return m_nSampleRate; }
  147. inline bool IsSurround() const { return m_nChannels > 2 ? true : false; }
  148. inline bool IsSurroundCenter() const { return m_nChannels > 4 ? true : false; }
  149. inline bool IsActive() const { return m_bIsActive; }
  150. inline bool IsHeadphone() const { return m_bIsHeadphone; } // mixing makes some choices differently for stereo vs headphones, expose that here.
  151. inline bool CanDetectBufferStarvation() { return m_bSupportsBufferStarvationDetection; }
  152. inline bool IsCaptureDevice() { return m_bIsCaptureDevice; }
  153. inline int DeviceSampleBytes( void ) const { return BitsPerSample() / 8; }
  154. // UNDONE: Need to implement these
  155. void Pause() {}
  156. void UnPause() {}
  157. void TransferSamples( uint32 nEndTimeIgnored );
  158. protected:
  159. // NOTE: Derived classes MUST initialize these before returning a device from a factory
  160. const char *m_pName;
  161. int m_nChannels;
  162. int m_nSampleBits;
  163. int m_nSampleRate;
  164. bool m_bIsActive;
  165. bool m_bIsHeadphone;
  166. bool m_bSupportsBufferStarvationDetection;
  167. bool m_bIsCaptureDevice;
  168. };
  169. // device handling
  170. extern IAudioDevice2 *Audio_CreateXAudio2Device( const audio_device_init_params_t &params );
  171. extern IAudioDevice2 *Audio_CreateDSoundDevice( const audio_device_init_params_t &params );
  172. #ifdef POSIX
  173. extern IAudioDevice2 *Audio_CreateSDLDevice( const audio_device_init_params_t &params );
  174. #endif
  175. extern IAudioDevice2 *Audio_CreateNullDevice();
  176. #if IS_WINDOWS_PC
  177. extern bool GetWindowsDefaultAudioDevice( wchar_t *pName, size_t nNameBufSize );
  178. #endif
  179. // speaker config
  180. extern int SpeakerConfigValueToChannelCount( int nSpeakerConfig );
  181. extern int ChannelCountToSpeakerConfigValue( int nChannelCount, bool bIsHeadphone );
  182. // buffer library
  183. extern void ScaleBuffer( float flOutput[MIX_BUFFER_SIZE], const float flInput[MIX_BUFFER_SIZE], float flScale );
  184. extern void ScaleBufferRamp( float flOutput[MIX_BUFFER_SIZE], const float flInput[MIX_BUFFER_SIZE], float flScaleStart, float flScaleEnd );
  185. extern void MixBuffer( float flOutput[MIX_BUFFER_SIZE], const float flInput[MIX_BUFFER_SIZE], float flScale );
  186. extern void MixBufferRamp( float flOutput[MIX_BUFFER_SIZE], const float flInput[MIX_BUFFER_SIZE], float flScaleStart, float flScaleEnd );
  187. inline void ScaleBufferAuto( float flOutput[MIX_BUFFER_SIZE], const float flInput[MIX_BUFFER_SIZE], float flScaleStart, float flScaleEnd )
  188. {
  189. if ( flScaleStart == flScaleEnd )
  190. {
  191. ScaleBuffer( flOutput, flInput, flScaleEnd );
  192. }
  193. else
  194. {
  195. ScaleBufferRamp( flOutput, flInput, flScaleStart, flScaleEnd );
  196. }
  197. }
  198. inline void MixBufferAuto( float flOutput[MIX_BUFFER_SIZE], const float flInput[MIX_BUFFER_SIZE], float flScaleStart, float flScaleEnd )
  199. {
  200. if ( flScaleStart == flScaleEnd )
  201. {
  202. MixBuffer( flOutput, flInput, flScaleEnd );
  203. }
  204. else
  205. {
  206. MixBufferRamp( flOutput, flInput, flScaleStart, flScaleEnd );
  207. }
  208. }
  209. extern void SilenceBuffer( float flBuffer[MIX_BUFFER_SIZE] );
  210. extern void SilenceBuffers( CAudioMixBuffer *pBuffers, int nBufferCount );
  211. extern void SumBuffer2x1( float flOutput[MIX_BUFFER_SIZE], float flInput0[MIX_BUFFER_SIZE], float flScale0, float flInput1[MIX_BUFFER_SIZE], float flScale1 );
  212. extern void SwapBuffersInPlace( float flInput0[MIX_BUFFER_SIZE], float flInput1[MIX_BUFFER_SIZE] );
  213. extern float BufferLevel( float flInput[MIX_BUFFER_SIZE] );
  214. extern float AvergeBufferAmplitude( float flInput[MIX_BUFFER_SIZE] );
  215. extern void ConvertFloat32Int16_Clamp_Interleave2( short *pOut, float *pflLeft, float *pflRight, int nSampleCount );
  216. extern void ConvertFloat32Int16_Clamp_InterleaveStride( short *pOut, int nOutputChannelCount, int nChannelStrideFloats, float *pflChannel0, int nInputChannelCount, int nSampleCount );
  217. #if IS_WINDOWS_PC
  218. void InitCOM();
  219. void ShutdownCOM();
  220. #else
  221. inline void InitCOM() {}
  222. inline void ShutdownCOM() {}
  223. #endif
  224. #endif // SOUNDSYSTEM_LOWLEVEL_H