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.

563 lines
16 KiB

  1. //===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose:
  4. //
  5. //===========================================================================//
  6. #include "audio_pch.h"
  7. // memdbgon must be the last include file in a .cpp file!!!
  8. #include "tier0/memdbgon.h"
  9. extern bool snd_firsttime;
  10. extern bool MIX_ScaleChannelVolume( paintbuffer_t *ppaint, channel_t *pChannel, float volume[CCHANVOLUMES], int mixchans );
  11. //extern void S_SpatializeChannel( int nSlot, int volume[6], int master_vol, const Vector *psourceDir, float gain, float mono );
  12. // 64K is > 1 second at 16-bit, 22050 Hz
  13. // 44k: UNDONE - need to double buffers now that we're playing back at 44100?
  14. #define WAV_BUFFERS 64
  15. #define WAV_MASK 0x3F
  16. #define WAV_BUFFER_SIZE 0x0400
  17. //-----------------------------------------------------------------------------
  18. //
  19. // NOTE: This only allows 16-bit, stereo wave out
  20. //
  21. //-----------------------------------------------------------------------------
  22. class CAudioDeviceWave : public CAudioDeviceBase
  23. {
  24. public:
  25. bool IsActive( void );
  26. bool Init( void );
  27. void Shutdown( void );
  28. void PaintEnd( void );
  29. int GetOutputPosition( void );
  30. void ChannelReset( int entnum, int channelIndex, float distanceMod );
  31. void Pause( void );
  32. void UnPause( void );
  33. float MixDryVolume( void );
  34. bool Should3DMix( void );
  35. void StopAllSounds( void );
  36. int64 PaintBegin( float mixAheadTime, int64 soundtime, int64 paintedtime );
  37. void ClearBuffer( void );
  38. void MixBegin( int sampleCount );
  39. void MixUpsample( int sampleCount, int filtertype );
  40. void Mix8Mono( channel_t *pChannel, char *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress );
  41. void Mix8Stereo( channel_t *pChannel, char *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress );
  42. void Mix16Mono( channel_t *pChannel, short *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress );
  43. void Mix16Stereo( channel_t *pChannel, short *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress );
  44. void TransferSamples( int end );
  45. // void SpatializeChannel( int nSlot, int volume[CCHANVOLUMES/2], int master_vol, const Vector& sourceDir, float gain, float mono);
  46. void ApplyDSPEffects( int idsp, portable_samplepair_t *pbuffront, portable_samplepair_t *pbufrear, portable_samplepair_t *pbufcenter, int samplecount );
  47. const char *DeviceName( void ) { return "Windows WAVE"; }
  48. int DeviceChannels( void ) { return 2; }
  49. int DeviceSampleBits( void ) { return 16; }
  50. int DeviceSampleBytes( void ) { return 2; }
  51. int DeviceDmaSpeed( void ) { return SOUND_DMA_SPEED; }
  52. int DeviceSampleCount( void ) { return m_deviceSampleCount; }
  53. private:
  54. void OpenWaveOut( void );
  55. void CloseWaveOut( void );
  56. void AllocateOutputBuffers();
  57. void FreeOutputBuffers();
  58. void* AllocOutputMemory( int nSize, HGLOBAL &hMemory );
  59. void FreeOutputMemory( HGLOBAL &hMemory );
  60. bool ValidWaveOut( void ) const;
  61. int m_deviceSampleCount;
  62. int m_buffersSent;
  63. int m_buffersCompleted;
  64. int m_pauseCount;
  65. // This is a single allocation for all wave headers (there are OUTPUT_BUFFER_COUNT of them)
  66. HGLOBAL m_hWaveHdr;
  67. // This is a single allocation for all wave data (there are OUTPUT_BUFFER_COUNT of them)
  68. HANDLE m_hWaveData;
  69. HWAVEOUT m_waveOutHandle;
  70. // Memory for the wave data + wave headers
  71. void *m_pBuffer;
  72. LPWAVEHDR m_pWaveHdr;
  73. };
  74. //-----------------------------------------------------------------------------
  75. // Class factory
  76. //-----------------------------------------------------------------------------
  77. IAudioDevice *Audio_CreateWaveDevice( void )
  78. {
  79. static CAudioDeviceWave *wave = NULL;
  80. if ( !wave )
  81. {
  82. wave = new CAudioDeviceWave;
  83. }
  84. if ( wave->Init() )
  85. return wave;
  86. delete wave;
  87. wave = NULL;
  88. return NULL;
  89. }
  90. //-----------------------------------------------------------------------------
  91. // Init, shutdown
  92. //-----------------------------------------------------------------------------
  93. bool CAudioDeviceWave::Init( void )
  94. {
  95. m_buffersSent = 0;
  96. m_buffersCompleted = 0;
  97. m_pauseCount = 0;
  98. m_waveOutHandle = 0;
  99. m_pBuffer = NULL;
  100. m_pWaveHdr = NULL;
  101. m_hWaveHdr = NULL;
  102. m_hWaveData = NULL;
  103. OpenWaveOut();
  104. if ( snd_firsttime )
  105. {
  106. DevMsg( "Wave sound initialized\n" );
  107. }
  108. return ValidWaveOut();
  109. }
  110. void CAudioDeviceWave::Shutdown( void )
  111. {
  112. CloseWaveOut();
  113. }
  114. //-----------------------------------------------------------------------------
  115. // WAV out device
  116. //-----------------------------------------------------------------------------
  117. inline bool CAudioDeviceWave::ValidWaveOut( void ) const
  118. {
  119. return m_waveOutHandle != 0;
  120. }
  121. //-----------------------------------------------------------------------------
  122. // Opens the windows wave out device
  123. //-----------------------------------------------------------------------------
  124. void CAudioDeviceWave::OpenWaveOut( void )
  125. {
  126. WAVEFORMATEX waveFormat;
  127. memset( &waveFormat, 0, sizeof(waveFormat) );
  128. // Select a PCM, 16-bit stereo playback device
  129. waveFormat.cbSize = sizeof(waveFormat);
  130. waveFormat.wFormatTag = WAVE_FORMAT_PCM;
  131. waveFormat.nChannels = DeviceChannels();
  132. waveFormat.wBitsPerSample = DeviceSampleBits();
  133. waveFormat.nSamplesPerSec = DeviceDmaSpeed(); // DeviceSampleRate
  134. waveFormat.nBlockAlign = waveFormat.nChannels * waveFormat.wBitsPerSample / 8;
  135. waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign;
  136. MMRESULT errorCode = waveOutOpen( &m_waveOutHandle, WAVE_MAPPER, &waveFormat, 0, 0L, CALLBACK_NULL );
  137. while ( errorCode != MMSYSERR_NOERROR )
  138. {
  139. if ( errorCode != MMSYSERR_ALLOCATED )
  140. {
  141. DevWarning( "waveOutOpen failed\n" );
  142. m_waveOutHandle = 0;
  143. return;
  144. }
  145. int nRetVal = MessageBox( NULL,
  146. "The sound hardware is in use by another app.\n\n"
  147. "Select Retry to try to start sound again or Cancel to run with no sound.",
  148. "Sound not available",
  149. MB_RETRYCANCEL | MB_SETFOREGROUND | MB_ICONEXCLAMATION);
  150. if ( nRetVal != IDRETRY )
  151. {
  152. DevWarning( "waveOutOpen failure--hardware already in use\n" );
  153. m_waveOutHandle = 0;
  154. return;
  155. }
  156. errorCode = waveOutOpen( &m_waveOutHandle, WAVE_MAPPER, &waveFormat, 0, 0L, CALLBACK_NULL );
  157. }
  158. AllocateOutputBuffers();
  159. }
  160. //-----------------------------------------------------------------------------
  161. // Closes the windows wave out device
  162. //-----------------------------------------------------------------------------
  163. void CAudioDeviceWave::CloseWaveOut( void )
  164. {
  165. if ( ValidWaveOut() )
  166. {
  167. waveOutReset( m_waveOutHandle );
  168. FreeOutputBuffers();
  169. waveOutClose( m_waveOutHandle );
  170. m_waveOutHandle = NULL;
  171. }
  172. }
  173. //-----------------------------------------------------------------------------
  174. // Alloc output memory
  175. //-----------------------------------------------------------------------------
  176. void* CAudioDeviceWave::AllocOutputMemory( int nSize, HGLOBAL &hMemory )
  177. {
  178. // Output memory for waveform data+hdrs must be
  179. // globally allocated with GMEM_MOVEABLE and GMEM_SHARE flags.
  180. hMemory = GlobalAlloc( GMEM_MOVEABLE | GMEM_SHARE, nSize );
  181. if ( !hMemory )
  182. {
  183. DevWarning( "Sound: Out of memory.\n");
  184. CloseWaveOut();
  185. return NULL;
  186. }
  187. HPSTR lpData = (char *)GlobalLock( hMemory );
  188. if ( !lpData )
  189. {
  190. DevWarning( "Sound: Failed to lock.\n");
  191. GlobalFree( hMemory );
  192. hMemory = NULL;
  193. CloseWaveOut();
  194. return NULL;
  195. }
  196. memset( lpData, 0, nSize );
  197. return lpData;
  198. }
  199. //-----------------------------------------------------------------------------
  200. // Free output memory
  201. //-----------------------------------------------------------------------------
  202. void CAudioDeviceWave::FreeOutputMemory( HGLOBAL &hMemory )
  203. {
  204. if ( hMemory )
  205. {
  206. GlobalUnlock( hMemory );
  207. GlobalFree( hMemory );
  208. hMemory = NULL;
  209. }
  210. }
  211. //-----------------------------------------------------------------------------
  212. // Allocate output buffers
  213. //-----------------------------------------------------------------------------
  214. void CAudioDeviceWave::AllocateOutputBuffers()
  215. {
  216. // Allocate and lock memory for the waveform data.
  217. int nBufferSize = WAV_BUFFER_SIZE * WAV_BUFFERS;
  218. HPSTR lpData = (char *)AllocOutputMemory( nBufferSize, m_hWaveData );
  219. if ( !lpData )
  220. return;
  221. // Allocate and lock memory for the waveform header
  222. int nHdrSize = sizeof( WAVEHDR ) * WAV_BUFFERS;
  223. LPWAVEHDR lpWaveHdr = (LPWAVEHDR)AllocOutputMemory( nHdrSize, m_hWaveHdr );
  224. if ( !lpWaveHdr )
  225. return;
  226. // After allocation, set up and prepare headers.
  227. for ( int i=0 ; i < WAV_BUFFERS; i++ )
  228. {
  229. LPWAVEHDR lpHdr = lpWaveHdr + i;
  230. lpHdr->dwBufferLength = WAV_BUFFER_SIZE;
  231. lpHdr->lpData = lpData + (i * WAV_BUFFER_SIZE);
  232. MMRESULT nResult = waveOutPrepareHeader( m_waveOutHandle, lpHdr, sizeof(WAVEHDR) );
  233. if ( nResult != MMSYSERR_NOERROR )
  234. {
  235. DevWarning( "Sound: failed to prepare wave headers\n" );
  236. CloseWaveOut();
  237. return;
  238. }
  239. }
  240. m_deviceSampleCount = nBufferSize / DeviceSampleBytes();
  241. m_pBuffer = (void *)lpData;
  242. m_pWaveHdr = lpWaveHdr;
  243. }
  244. //-----------------------------------------------------------------------------
  245. // Free output buffers
  246. //-----------------------------------------------------------------------------
  247. void CAudioDeviceWave::FreeOutputBuffers()
  248. {
  249. // Unprepare headers.
  250. if ( m_pWaveHdr )
  251. {
  252. for ( int i=0 ; i < WAV_BUFFERS; i++ )
  253. {
  254. waveOutUnprepareHeader( m_waveOutHandle, m_pWaveHdr+i, sizeof(WAVEHDR) );
  255. }
  256. }
  257. m_pWaveHdr = NULL;
  258. m_pBuffer = NULL;
  259. FreeOutputMemory( m_hWaveData );
  260. FreeOutputMemory( m_hWaveHdr );
  261. }
  262. //-----------------------------------------------------------------------------
  263. // Mixing setup
  264. //-----------------------------------------------------------------------------
  265. int64 CAudioDeviceWave::PaintBegin( float mixAheadTime, int64 soundtime, int64 paintedtime )
  266. {
  267. // soundtime - total samples that have been played out to hardware at dmaspeed
  268. // paintedtime - total samples that have been mixed at speed
  269. // endtime - target for samples in mixahead buffer at speed
  270. int64 endtime = soundtime + mixAheadTime * DeviceDmaSpeed();
  271. int samps = DeviceSampleCount() >> (DeviceChannels()-1);
  272. if ((int)(endtime - soundtime) > samps)
  273. endtime = soundtime + samps;
  274. if ((endtime - paintedtime) & 0x3)
  275. {
  276. // The difference between endtime and painted time should align on
  277. // boundaries of 4 samples. This is important when upsampling from 11khz -> 44khz.
  278. endtime -= (endtime - paintedtime) & 0x3;
  279. }
  280. return endtime;
  281. }
  282. //-----------------------------------------------------------------------------
  283. // Actually performs the mixing
  284. //-----------------------------------------------------------------------------
  285. void CAudioDeviceWave::PaintEnd( void )
  286. {
  287. LPWAVEHDR h;
  288. int wResult;
  289. int cblocks;
  290. //
  291. // find which sound blocks have completed
  292. //
  293. while (1)
  294. {
  295. if ( m_buffersCompleted == m_buffersSent )
  296. {
  297. //DevMsg ("Sound overrun\n");
  298. break;
  299. }
  300. if ( ! (m_pWaveHdr[ m_buffersCompleted & WAV_MASK].dwFlags & WHDR_DONE) )
  301. {
  302. break;
  303. }
  304. m_buffersCompleted++; // this buffer has been played
  305. }
  306. //
  307. // submit a few new sound blocks
  308. //
  309. // 22K sound support
  310. // 44k: UNDONE - double blocks out now that we're at 44k playback?
  311. cblocks = 4 << 1;
  312. while (((m_buffersSent - m_buffersCompleted) >> SAMPLE_16BIT_SHIFT) < cblocks)
  313. {
  314. h = m_pWaveHdr + ( m_buffersSent&WAV_MASK );
  315. m_buffersSent++;
  316. /*
  317. * Now the data block can be sent to the output device. The
  318. * waveOutWrite function returns immediately and waveform
  319. * data is sent to the output device in the background.
  320. */
  321. wResult = waveOutWrite( m_waveOutHandle, h, sizeof(WAVEHDR) );
  322. if (wResult != MMSYSERR_NOERROR)
  323. {
  324. Warning( "Failed to write block to device\n");
  325. Shutdown();
  326. return;
  327. }
  328. }
  329. }
  330. int CAudioDeviceWave::GetOutputPosition( void )
  331. {
  332. int s = m_buffersSent * WAV_BUFFER_SIZE;
  333. s >>= SAMPLE_16BIT_SHIFT;
  334. s &= (DeviceSampleCount()-1);
  335. return s / DeviceChannels();
  336. }
  337. //-----------------------------------------------------------------------------
  338. // Pausing
  339. //-----------------------------------------------------------------------------
  340. void CAudioDeviceWave::Pause( void )
  341. {
  342. m_pauseCount++;
  343. if (m_pauseCount == 1)
  344. {
  345. waveOutReset( m_waveOutHandle );
  346. }
  347. }
  348. void CAudioDeviceWave::UnPause( void )
  349. {
  350. if ( m_pauseCount > 0 )
  351. {
  352. m_pauseCount--;
  353. }
  354. }
  355. bool CAudioDeviceWave::IsActive( void )
  356. {
  357. return ( m_pauseCount == 0 );
  358. }
  359. float CAudioDeviceWave::MixDryVolume( void )
  360. {
  361. return 0;
  362. }
  363. bool CAudioDeviceWave::Should3DMix( void )
  364. {
  365. return false;
  366. }
  367. void CAudioDeviceWave::ClearBuffer( void )
  368. {
  369. int clear;
  370. if ( !m_pBuffer )
  371. return;
  372. clear = 0;
  373. Q_memset(m_pBuffer, clear, DeviceSampleCount() * DeviceSampleBytes() );
  374. }
  375. void CAudioDeviceWave::MixBegin( int sampleCount )
  376. {
  377. MIX_ClearAllPaintBuffers( sampleCount, false );
  378. }
  379. void CAudioDeviceWave::MixUpsample( int sampleCount, int filtertype )
  380. {
  381. paintbuffer_t *ppaint = MIX_GetCurrentPaintbufferPtr();
  382. int ifilter = ppaint->ifilter;
  383. Assert (ifilter < CPAINTFILTERS);
  384. S_MixBufferUpsample2x( sampleCount, ppaint->pbuf, &(ppaint->fltmem[ifilter][0]), CPAINTFILTERMEM, filtertype );
  385. ppaint->ifilter++;
  386. }
  387. void CAudioDeviceWave::Mix8Mono( channel_t *pChannel, char *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress )
  388. {
  389. float volume[CCHANVOLUMES];
  390. paintbuffer_t *ppaint = MIX_GetCurrentPaintbufferPtr();
  391. if (!MIX_ScaleChannelVolume( ppaint, pChannel, volume, 1))
  392. return;
  393. Mix8MonoWavtype( pChannel, ppaint->pbuf + outputOffset, volume, (byte *)pData, inputOffset, rateScaleFix, outCount );
  394. }
  395. void CAudioDeviceWave::Mix8Stereo( channel_t *pChannel, char *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress )
  396. {
  397. float volume[CCHANVOLUMES];
  398. paintbuffer_t *ppaint = MIX_GetCurrentPaintbufferPtr();
  399. if (!MIX_ScaleChannelVolume( ppaint, pChannel, volume, 2 ))
  400. return;
  401. Mix8StereoWavtype( pChannel, ppaint->pbuf + outputOffset, volume, (byte *)pData, inputOffset, rateScaleFix, outCount );
  402. }
  403. void CAudioDeviceWave::Mix16Mono( channel_t *pChannel, short *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress )
  404. {
  405. float volume[CCHANVOLUMES];
  406. paintbuffer_t *ppaint = MIX_GetCurrentPaintbufferPtr();
  407. if (!MIX_ScaleChannelVolume( ppaint, pChannel, volume, 1 ))
  408. return;
  409. Mix16MonoWavtype( pChannel, ppaint->pbuf + outputOffset, volume, pData, inputOffset, rateScaleFix, outCount );
  410. }
  411. void CAudioDeviceWave::Mix16Stereo( channel_t *pChannel, short *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress )
  412. {
  413. float volume[CCHANVOLUMES];
  414. paintbuffer_t *ppaint = MIX_GetCurrentPaintbufferPtr();
  415. if (!MIX_ScaleChannelVolume( ppaint, pChannel, volume, 2 ))
  416. return;
  417. Mix16StereoWavtype( pChannel, ppaint->pbuf + outputOffset, volume, pData, inputOffset, rateScaleFix, outCount );
  418. }
  419. void CAudioDeviceWave::ChannelReset( int entnum, int channelIndex, float distanceMod )
  420. {
  421. }
  422. void CAudioDeviceWave::TransferSamples( int end )
  423. {
  424. int64 lpaintedtime = g_paintedtime;
  425. int64 endtime = end;
  426. // resumes playback...
  427. if ( m_pBuffer )
  428. {
  429. S_TransferStereo16( m_pBuffer, PAINTBUFFER, lpaintedtime, endtime );
  430. }
  431. }
  432. // temporarily deprecating to be sure which version of SpatializeChannel is used
  433. /*void CAudioDeviceWave::SpatializeChannel( int nSlot, int volume[CCHANVOLUMES/2], int master_vol, const Vector& sourceDir, float gain, float mono )
  434. {
  435. VPROF("CAudioDeviceWave::SpatializeChannel");
  436. S_SpatializeChannel( nSlot, volume, master_vol, &sourceDir, gain, mono );
  437. }
  438. */
  439. void CAudioDeviceWave::StopAllSounds( void )
  440. {
  441. }
  442. void CAudioDeviceWave::ApplyDSPEffects( int idsp, portable_samplepair_t *pbuffront, portable_samplepair_t *pbufrear, portable_samplepair_t *pbufcenter, int samplecount )
  443. {
  444. //SX_RoomFX( endtime, filter, timefx );
  445. DSP_Process( idsp, pbuffront, pbufrear, pbufcenter, samplecount );
  446. }