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.

903 lines
23 KiB

  1. //===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //===========================================================================//
  8. #include "snd_dev_wave.h"
  9. #define WIN32_LEAN_AND_MEAN
  10. #include <windows.h>
  11. #pragma warning( disable: 4201 )
  12. #include <mmsystem.h>
  13. #pragma warning( default: 4201 )
  14. #include <stdio.h>
  15. #include <math.h>
  16. #include "soundsystem/snd_audio_source.h"
  17. #include "soundsystem.h"
  18. #include "soundsystem/snd_device.h"
  19. #include "tier1/utlvector.h"
  20. #include "FileSystem.h"
  21. #include "sentence.h"
  22. // NOTE: This has to be the last file included!
  23. #include "tier0/memdbgon.h"
  24. DEFINE_LOGGING_CHANNEL_NO_TAGS( LOG_SoundSystem, "SoundSystem", 0, LS_ERROR );
  25. //-----------------------------------------------------------------------------
  26. // Forward declarations
  27. //-----------------------------------------------------------------------------
  28. class CAudioMixer;
  29. //-----------------------------------------------------------------------------
  30. // Important constants
  31. //-----------------------------------------------------------------------------
  32. // 64K is > 1 second at 16-bit, 22050 Hz
  33. // 44k: UNDONE - need to double buffers now that we're playing back at 44100?
  34. #define OUTPUT_CHANNEL_COUNT 2
  35. #define BYTES_PER_SAMPLE 2
  36. #define OUTPUT_SAMPLE_RATE SOUND_DMA_SPEED
  37. #define OUTPUT_BUFFER_COUNT 64
  38. #define OUTPUT_BUFFER_MASK 0x3F
  39. #define OUTPUT_BUFFER_SAMPLE_COUNT (OUTPUT_BUFFER_SIZE_BYTES / BYTES_PER_SAMPLE)
  40. #define OUTPUT_BUFFER_SIZE_BYTES 1024
  41. #define PAINTBUFFER_SIZE 1024
  42. #define MAX_CHANNELS 16
  43. //-----------------------------------------------------------------------------
  44. // Implementation of IAudioDevice for WAV files
  45. //-----------------------------------------------------------------------------
  46. class CAudioDeviceWave : public IAudioDevice
  47. {
  48. public:
  49. // Inherited from IAudioDevice
  50. virtual bool Init( void );
  51. virtual void Shutdown( void );
  52. virtual const char *DeviceName( void ) const;
  53. virtual int DeviceChannels( void ) const;
  54. virtual int DeviceSampleBits( void ) const;
  55. virtual int DeviceSampleBytes( void ) const;
  56. virtual int DeviceSampleRate( void ) const;
  57. virtual int DeviceSampleCount( void ) const;
  58. virtual void Mix8Mono( channel_t *pChannel, char *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress, bool forward = true );
  59. virtual void Mix8Stereo( channel_t *pChannel, char *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress, bool forward = true );
  60. virtual void Mix16Mono( channel_t *pChannel, short *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress, bool forward = true );
  61. virtual void Mix16Stereo( channel_t *pChannel, short *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress, bool forward = true );
  62. virtual int PaintBufferSampleCount( void ) const;
  63. virtual void MixBegin( void );
  64. // mix a buffer up to time (time is absolute)
  65. void Update( float time );
  66. void Flush( void );
  67. void TransferBufferStereo16( short *pOutput, int sampleCount );
  68. int GetOutputPosition( void );
  69. float GetAmountofTimeAhead( void );
  70. int GetNumberofSamplesAhead( void );
  71. void AddSource( CAudioMixer *pSource );
  72. void StopSounds( void );
  73. int FindSourceIndex( CAudioMixer *pSource );
  74. CAudioMixer *GetMixerForSource( CAudioSource *source );
  75. private:
  76. class CAudioMixerState
  77. {
  78. public:
  79. CAudioMixer *mixer;
  80. };
  81. class CAudioBuffer
  82. {
  83. public:
  84. WAVEHDR *hdr;
  85. bool submitted;
  86. int submit_sample_count;
  87. CUtlVector< CAudioMixerState > m_Referenced;
  88. };
  89. struct portable_samplepair_t
  90. {
  91. int left;
  92. int right;
  93. };
  94. void OpenWaveOut( void );
  95. void CloseWaveOut( void );
  96. void AllocateOutputBuffers();
  97. void FreeOutputBuffers();
  98. void* AllocOutputMemory( int nSize, HGLOBAL &hMemory );
  99. void FreeOutputMemory( HGLOBAL &hMemory );
  100. bool ValidWaveOut( void ) const;
  101. CAudioBuffer *GetEmptyBuffer( void );
  102. void SilenceBuffer( short *pSamples, int sampleCount );
  103. void SetChannel( int channelIndex, CAudioMixer *pSource );
  104. void FreeChannel( int channelIndex );
  105. void RemoveMixerChannelReferences( CAudioMixer *mixer );
  106. void AddToReferencedList( CAudioMixer *mixer, CAudioBuffer *buffer );
  107. void RemoveFromReferencedList( CAudioMixer *mixer, CAudioBuffer *buffer );
  108. bool IsSourceReferencedByActiveBuffer( CAudioMixer *mixer );
  109. bool IsSoundInReferencedList( CAudioMixer *mixer, CAudioBuffer *buffer );
  110. // Compute how many samples we've mixed since most recent buffer submission
  111. void ComputeSampleAheadAmount( void );
  112. // This is a single allocation for all wave headers (there are OUTPUT_BUFFER_COUNT of them)
  113. HGLOBAL m_hWaveHdr;
  114. // This is a single allocation for all wave data (there are OUTPUT_BUFFER_COUNT of them)
  115. HANDLE m_hWaveData;
  116. HWAVEOUT m_waveOutHandle;
  117. float m_mixTime;
  118. float m_baseTime;
  119. int m_sampleIndex;
  120. CAudioBuffer m_buffers[ OUTPUT_BUFFER_COUNT ];
  121. CAudioMixer *m_sourceList[MAX_CHANNELS];
  122. int m_nEstimatedSamplesAhead;
  123. portable_samplepair_t m_paintbuffer[ PAINTBUFFER_SIZE ];
  124. };
  125. //-----------------------------------------------------------------------------
  126. // Singleton
  127. //-----------------------------------------------------------------------------
  128. IAudioDevice *Audio_CreateWaveDevice( void )
  129. {
  130. return new CAudioDeviceWave;
  131. }
  132. //-----------------------------------------------------------------------------
  133. // Init, shutdown
  134. //-----------------------------------------------------------------------------
  135. bool CAudioDeviceWave::Init( void )
  136. {
  137. m_hWaveData = NULL;
  138. m_hWaveHdr = NULL;
  139. m_waveOutHandle = NULL;
  140. for ( int i = 0; i < OUTPUT_BUFFER_COUNT; i++ )
  141. {
  142. CAudioBuffer *buffer = &m_buffers[ i ];
  143. Assert( buffer );
  144. buffer->hdr = NULL;
  145. buffer->submitted = false;
  146. buffer->submit_sample_count = false;
  147. }
  148. OpenWaveOut();
  149. m_mixTime = m_baseTime = -1;
  150. m_sampleIndex = 0;
  151. memset( m_sourceList, 0, sizeof(m_sourceList) );
  152. m_nEstimatedSamplesAhead = (int)( ( float ) OUTPUT_SAMPLE_RATE / 10.0f );
  153. return true;
  154. }
  155. void CAudioDeviceWave::Shutdown( void )
  156. {
  157. CloseWaveOut();
  158. }
  159. //-----------------------------------------------------------------------------
  160. // WAV out device
  161. //-----------------------------------------------------------------------------
  162. inline bool CAudioDeviceWave::ValidWaveOut( void ) const
  163. {
  164. return m_waveOutHandle != 0;
  165. }
  166. //-----------------------------------------------------------------------------
  167. // Opens the windows wave out device
  168. //-----------------------------------------------------------------------------
  169. void CAudioDeviceWave::OpenWaveOut( void )
  170. {
  171. WAVEFORMATEX waveFormat;
  172. memset( &waveFormat, 0, sizeof(waveFormat) );
  173. // Select a PCM, 16-bit stereo playback device
  174. waveFormat.cbSize = sizeof(waveFormat);
  175. waveFormat.wFormatTag = WAVE_FORMAT_PCM;
  176. waveFormat.nChannels = DeviceChannels();
  177. waveFormat.wBitsPerSample = DeviceSampleBits();
  178. waveFormat.nSamplesPerSec = DeviceSampleRate();
  179. waveFormat.nBlockAlign = waveFormat.nChannels * waveFormat.wBitsPerSample / 8;
  180. waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign;
  181. MMRESULT errorCode = waveOutOpen( &m_waveOutHandle, WAVE_MAPPER, &waveFormat, 0, 0L, CALLBACK_NULL );
  182. while ( errorCode != MMSYSERR_NOERROR )
  183. {
  184. if ( errorCode != MMSYSERR_ALLOCATED )
  185. {
  186. Log_Warning( LOG_SoundSystem, "waveOutOpen failed\n" );
  187. m_waveOutHandle = 0;
  188. return;
  189. }
  190. int nRetVal = MessageBox( NULL,
  191. "The sound hardware is in use by another app.\n\n"
  192. "Select Retry to try to start sound again or Cancel to run with no sound.",
  193. "Sound not available",
  194. MB_RETRYCANCEL | MB_SETFOREGROUND | MB_ICONEXCLAMATION);
  195. if ( nRetVal != IDRETRY )
  196. {
  197. Log_Warning( LOG_SoundSystem, "waveOutOpen failure--hardware already in use\n" );
  198. m_waveOutHandle = 0;
  199. return;
  200. }
  201. errorCode = waveOutOpen( &m_waveOutHandle, WAVE_MAPPER, &waveFormat, 0, 0L, CALLBACK_NULL );
  202. }
  203. AllocateOutputBuffers();
  204. }
  205. //-----------------------------------------------------------------------------
  206. // Closes the windows wave out device
  207. //-----------------------------------------------------------------------------
  208. void CAudioDeviceWave::CloseWaveOut( void )
  209. {
  210. if ( ValidWaveOut() )
  211. {
  212. waveOutReset( m_waveOutHandle );
  213. FreeOutputBuffers();
  214. waveOutClose( m_waveOutHandle );
  215. m_waveOutHandle = NULL;
  216. }
  217. }
  218. //-----------------------------------------------------------------------------
  219. // Alloc output memory
  220. //-----------------------------------------------------------------------------
  221. void* CAudioDeviceWave::AllocOutputMemory( int nSize, HGLOBAL &hMemory )
  222. {
  223. // Output memory for waveform data+hdrs must be
  224. // globally allocated with GMEM_MOVEABLE and GMEM_SHARE flags.
  225. hMemory = GlobalAlloc( GMEM_MOVEABLE | GMEM_SHARE, nSize );
  226. if ( !hMemory )
  227. {
  228. Log_Warning( LOG_SoundSystem, "Sound: Out of memory.\n");
  229. CloseWaveOut();
  230. return NULL;
  231. }
  232. HPSTR lpData = (char *)GlobalLock( hMemory );
  233. if ( !lpData )
  234. {
  235. Log_Warning( LOG_SoundSystem, "Sound: Failed to lock.\n");
  236. GlobalFree( hMemory );
  237. hMemory = NULL;
  238. CloseWaveOut();
  239. return NULL;
  240. }
  241. memset( lpData, 0, nSize );
  242. return lpData;
  243. }
  244. //-----------------------------------------------------------------------------
  245. // Free output memory
  246. //-----------------------------------------------------------------------------
  247. void CAudioDeviceWave::FreeOutputMemory( HGLOBAL &hMemory )
  248. {
  249. if ( hMemory )
  250. {
  251. GlobalUnlock( hMemory );
  252. GlobalFree( hMemory );
  253. hMemory = NULL;
  254. }
  255. }
  256. //-----------------------------------------------------------------------------
  257. // Allocate, free output buffers
  258. //-----------------------------------------------------------------------------
  259. void CAudioDeviceWave::AllocateOutputBuffers()
  260. {
  261. // Allocate and lock memory for the waveform data.
  262. int nBufferSize = OUTPUT_BUFFER_SIZE_BYTES * OUTPUT_BUFFER_COUNT;
  263. HPSTR lpData = (char *)AllocOutputMemory( nBufferSize, m_hWaveData );
  264. if ( !lpData )
  265. return;
  266. // Allocate and lock memory for the waveform header
  267. int nHdrSize = sizeof( WAVEHDR ) * OUTPUT_BUFFER_COUNT;
  268. LPWAVEHDR lpWaveHdr = (LPWAVEHDR)AllocOutputMemory( nHdrSize, m_hWaveHdr );
  269. if ( !lpWaveHdr )
  270. return;
  271. // After allocation, set up and prepare headers.
  272. for ( int i=0 ; i < OUTPUT_BUFFER_COUNT; i++ )
  273. {
  274. LPWAVEHDR lpHdr = lpWaveHdr + i;
  275. lpHdr->dwBufferLength = OUTPUT_BUFFER_SIZE_BYTES;
  276. lpHdr->lpData = lpData + (i * OUTPUT_BUFFER_SIZE_BYTES);
  277. MMRESULT nResult = waveOutPrepareHeader( m_waveOutHandle, lpHdr, sizeof(WAVEHDR) );
  278. if ( nResult != MMSYSERR_NOERROR )
  279. {
  280. Log_Warning( LOG_SoundSystem, "Sound: failed to prepare wave headers\n" );
  281. CloseWaveOut();
  282. return;
  283. }
  284. m_buffers[i].hdr = lpHdr;
  285. }
  286. }
  287. void CAudioDeviceWave::FreeOutputBuffers()
  288. {
  289. // Unprepare headers.
  290. for ( int i=0 ; i < OUTPUT_BUFFER_COUNT; i++ )
  291. {
  292. if ( m_buffers[i].hdr )
  293. {
  294. waveOutUnprepareHeader( m_waveOutHandle, m_buffers[i].hdr, sizeof(WAVEHDR) );
  295. m_buffers[i].hdr = NULL;
  296. }
  297. m_buffers[i].submitted = false;
  298. m_buffers[i].submit_sample_count = 0;
  299. m_buffers[i].m_Referenced.Purge();
  300. }
  301. FreeOutputMemory( m_hWaveData );
  302. FreeOutputMemory( m_hWaveHdr );
  303. }
  304. //-----------------------------------------------------------------------------
  305. // Device parameters
  306. //-----------------------------------------------------------------------------
  307. const char *CAudioDeviceWave::DeviceName( void ) const
  308. {
  309. return "Windows WAVE";
  310. }
  311. int CAudioDeviceWave::DeviceChannels( void ) const
  312. {
  313. return 2;
  314. }
  315. int CAudioDeviceWave::DeviceSampleBits( void ) const
  316. {
  317. return (BYTES_PER_SAMPLE * 8);
  318. }
  319. int CAudioDeviceWave::DeviceSampleBytes( void ) const
  320. {
  321. return BYTES_PER_SAMPLE;
  322. }
  323. int CAudioDeviceWave::DeviceSampleRate( void ) const
  324. {
  325. return OUTPUT_SAMPLE_RATE;
  326. }
  327. int CAudioDeviceWave::DeviceSampleCount( void ) const
  328. {
  329. return OUTPUT_BUFFER_SAMPLE_COUNT;
  330. }
  331. int CAudioDeviceWave::PaintBufferSampleCount( void ) const
  332. {
  333. return PAINTBUFFER_SIZE;
  334. }
  335. //-----------------------------------------------------------------------------
  336. // Mixing routines
  337. //-----------------------------------------------------------------------------
  338. void CAudioDeviceWave::Mix8Mono( channel_t *pChannel, char *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress, bool forward )
  339. {
  340. int sampleIndex = 0;
  341. fixedint sampleFrac = inputOffset;
  342. int fixup = 0;
  343. int fixupstep = 1;
  344. if ( !forward )
  345. {
  346. fixup = outCount - 1;
  347. fixupstep = -1;
  348. }
  349. for ( int i = 0; i < outCount; i++, fixup += fixupstep )
  350. {
  351. int dest = max( outputOffset + fixup, 0 );
  352. m_paintbuffer[ dest ].left += pChannel->leftvol * pData[sampleIndex];
  353. m_paintbuffer[ dest ].right += pChannel->rightvol * pData[sampleIndex];
  354. sampleFrac += rateScaleFix;
  355. sampleIndex += FIX_INTPART(sampleFrac);
  356. sampleFrac = FIX_FRACPART(sampleFrac);
  357. }
  358. }
  359. void CAudioDeviceWave::Mix8Stereo( channel_t *pChannel, char *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress, bool forward )
  360. {
  361. int sampleIndex = 0;
  362. fixedint sampleFrac = inputOffset;
  363. int fixup = 0;
  364. int fixupstep = 1;
  365. if ( !forward )
  366. {
  367. fixup = outCount - 1;
  368. fixupstep = -1;
  369. }
  370. for ( int i = 0; i < outCount; i++, fixup += fixupstep )
  371. {
  372. int dest = max( outputOffset + fixup, 0 );
  373. m_paintbuffer[ dest ].left += pChannel->leftvol * pData[sampleIndex];
  374. m_paintbuffer[ dest ].right += pChannel->rightvol * pData[sampleIndex+1];
  375. sampleFrac += rateScaleFix;
  376. sampleIndex += FIX_INTPART(sampleFrac)<<1;
  377. sampleFrac = FIX_FRACPART(sampleFrac);
  378. }
  379. }
  380. void CAudioDeviceWave::Mix16Mono( channel_t *pChannel, short *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress, bool forward )
  381. {
  382. int sampleIndex = 0;
  383. fixedint sampleFrac = inputOffset;
  384. int fixup = 0;
  385. int fixupstep = 1;
  386. if ( !forward )
  387. {
  388. fixup = outCount - 1;
  389. fixupstep = -1;
  390. }
  391. for ( int i = 0; i < outCount; i++, fixup += fixupstep )
  392. {
  393. int dest = max( outputOffset + fixup, 0 );
  394. m_paintbuffer[ dest ].left += (pChannel->leftvol * pData[sampleIndex])>>8;
  395. m_paintbuffer[ dest ].right += (pChannel->rightvol * pData[sampleIndex])>>8;
  396. sampleFrac += rateScaleFix;
  397. sampleIndex += FIX_INTPART(sampleFrac);
  398. sampleFrac = FIX_FRACPART(sampleFrac);
  399. }
  400. }
  401. void CAudioDeviceWave::Mix16Stereo( channel_t *pChannel, short *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress, bool forward )
  402. {
  403. int sampleIndex = 0;
  404. fixedint sampleFrac = inputOffset;
  405. int fixup = 0;
  406. int fixupstep = 1;
  407. if ( !forward )
  408. {
  409. fixup = outCount - 1;
  410. fixupstep = -1;
  411. }
  412. for ( int i = 0; i < outCount; i++, fixup += fixupstep )
  413. {
  414. int dest = max( outputOffset + fixup, 0 );
  415. m_paintbuffer[ dest ].left += (pChannel->leftvol * pData[sampleIndex])>>8;
  416. m_paintbuffer[ dest ].right += (pChannel->rightvol * pData[sampleIndex+1])>>8;
  417. sampleFrac += rateScaleFix;
  418. sampleIndex += FIX_INTPART(sampleFrac)<<1;
  419. sampleFrac = FIX_FRACPART(sampleFrac);
  420. }
  421. }
  422. void CAudioDeviceWave::MixBegin( void )
  423. {
  424. memset( m_paintbuffer, 0, sizeof(m_paintbuffer) );
  425. }
  426. void CAudioDeviceWave::TransferBufferStereo16( short *pOutput, int sampleCount )
  427. {
  428. for ( int i = 0; i < sampleCount; i++ )
  429. {
  430. if ( m_paintbuffer[i].left > 32767 )
  431. m_paintbuffer[i].left = 32767;
  432. else if ( m_paintbuffer[i].left < -32768 )
  433. m_paintbuffer[i].left = -32768;
  434. if ( m_paintbuffer[i].right > 32767 )
  435. m_paintbuffer[i].right = 32767;
  436. else if ( m_paintbuffer[i].right < -32768 )
  437. m_paintbuffer[i].right = -32768;
  438. *pOutput++ = (short)m_paintbuffer[i].left;
  439. *pOutput++ = (short)m_paintbuffer[i].right;
  440. }
  441. }
  442. void CAudioDeviceWave::RemoveMixerChannelReferences( CAudioMixer *mixer )
  443. {
  444. for ( int i = 0; i < OUTPUT_BUFFER_COUNT; i++ )
  445. {
  446. RemoveFromReferencedList( mixer, &m_buffers[ i ] );
  447. }
  448. }
  449. void CAudioDeviceWave::AddToReferencedList( CAudioMixer *mixer, CAudioBuffer *buffer )
  450. {
  451. // Already in list
  452. for ( int i = 0; i < buffer->m_Referenced.Count(); i++ )
  453. {
  454. if ( buffer->m_Referenced[ i ].mixer == mixer )
  455. return;
  456. }
  457. // Just remove it
  458. int idx = buffer->m_Referenced.AddToTail();
  459. CAudioMixerState *state = &buffer->m_Referenced[ idx ];
  460. state->mixer = mixer;
  461. }
  462. void CAudioDeviceWave::RemoveFromReferencedList( CAudioMixer *mixer, CAudioBuffer *buffer )
  463. {
  464. for ( int i = 0; i < buffer->m_Referenced.Count(); i++ )
  465. {
  466. if ( buffer->m_Referenced[ i ].mixer == mixer )
  467. {
  468. buffer->m_Referenced.Remove( i );
  469. break;
  470. }
  471. }
  472. }
  473. bool CAudioDeviceWave::IsSoundInReferencedList( CAudioMixer *mixer, CAudioBuffer *buffer )
  474. {
  475. for ( int i = 0; i < buffer->m_Referenced.Count(); i++ )
  476. {
  477. if ( buffer->m_Referenced[ i ].mixer == mixer )
  478. {
  479. return true;
  480. }
  481. }
  482. return false;
  483. }
  484. bool CAudioDeviceWave::IsSourceReferencedByActiveBuffer( CAudioMixer *mixer )
  485. {
  486. if ( !ValidWaveOut() )
  487. return false;
  488. CAudioBuffer *buffer;
  489. for ( int i = 0; i < OUTPUT_BUFFER_COUNT; i++ )
  490. {
  491. buffer = &m_buffers[ i ];
  492. if ( !buffer->submitted )
  493. continue;
  494. if ( buffer->hdr->dwFlags & WHDR_DONE )
  495. continue;
  496. // See if it's referenced
  497. if ( IsSoundInReferencedList( mixer, buffer ) )
  498. return true;
  499. }
  500. return false;
  501. }
  502. CAudioDeviceWave::CAudioBuffer *CAudioDeviceWave::GetEmptyBuffer( void )
  503. {
  504. CAudioBuffer *pOutput = NULL;
  505. if ( ValidWaveOut() )
  506. {
  507. for ( int i = 0; i < OUTPUT_BUFFER_COUNT; i++ )
  508. {
  509. if ( !(m_buffers[ i ].submitted ) ||
  510. m_buffers[i].hdr->dwFlags & WHDR_DONE )
  511. {
  512. pOutput = &m_buffers[i];
  513. pOutput->submitted = true;
  514. pOutput->m_Referenced.Purge();
  515. break;
  516. }
  517. }
  518. }
  519. return pOutput;
  520. }
  521. void CAudioDeviceWave::SilenceBuffer( short *pSamples, int sampleCount )
  522. {
  523. int i;
  524. for ( i = 0; i < sampleCount; i++ )
  525. {
  526. // left
  527. *pSamples++ = 0;
  528. // right
  529. *pSamples++ = 0;
  530. }
  531. }
  532. void CAudioDeviceWave::Flush( void )
  533. {
  534. waveOutReset( m_waveOutHandle );
  535. }
  536. // mix a buffer up to time (time is absolute)
  537. void CAudioDeviceWave::Update( float time )
  538. {
  539. if ( !ValidWaveOut() )
  540. return;
  541. // reset the system
  542. if ( m_mixTime < 0 || time < m_baseTime )
  543. {
  544. m_baseTime = time;
  545. m_mixTime = 0;
  546. }
  547. // put time in our coordinate frame
  548. time -= m_baseTime;
  549. if ( time > m_mixTime )
  550. {
  551. CAudioBuffer *pBuffer = GetEmptyBuffer();
  552. // no free buffers, mixing is ahead of the playback!
  553. if ( !pBuffer || !pBuffer->hdr )
  554. {
  555. //Con_Printf( "out of buffers\n" );
  556. return;
  557. }
  558. // UNDONE: These numbers are constants
  559. // calc number of samples (2 channels * 2 bytes per sample)
  560. int sampleCount = pBuffer->hdr->dwBufferLength >> 2;
  561. m_mixTime += sampleCount * (1.0f / OUTPUT_SAMPLE_RATE);
  562. short *pSamples = reinterpret_cast<short *>(pBuffer->hdr->lpData);
  563. SilenceBuffer( pSamples, sampleCount );
  564. int tempCount = sampleCount;
  565. while ( tempCount > 0 )
  566. {
  567. if ( tempCount > PaintBufferSampleCount() )
  568. {
  569. sampleCount = PaintBufferSampleCount();
  570. }
  571. else
  572. {
  573. sampleCount = tempCount;
  574. }
  575. MixBegin();
  576. for ( int i = 0; i < MAX_CHANNELS; i++ )
  577. {
  578. CAudioMixer *pSource = m_sourceList[i];
  579. if ( !pSource )
  580. continue;
  581. int currentsample = pSource->GetSamplePosition();
  582. bool forward = pSource->GetDirection();
  583. if ( pSource->GetActive() )
  584. {
  585. if ( !pSource->MixDataToDevice( this, pSource->GetChannel(), currentsample, sampleCount, DeviceSampleRate(), forward ) )
  586. {
  587. // Source becomes inactive when last submitted sample is finally
  588. // submitted. But it lingers until it's no longer referenced
  589. pSource->SetActive( false );
  590. }
  591. else
  592. {
  593. AddToReferencedList( pSource, pBuffer );
  594. }
  595. }
  596. else
  597. {
  598. if ( !IsSourceReferencedByActiveBuffer( pSource ) )
  599. {
  600. if ( !pSource->GetAutoDelete() )
  601. {
  602. FreeChannel( i );
  603. }
  604. }
  605. else
  606. {
  607. pSource->IncrementSamples( pSource->GetChannel(), currentsample, sampleCount, DeviceSampleRate(), forward );
  608. }
  609. }
  610. }
  611. TransferBufferStereo16( pSamples, sampleCount );
  612. m_sampleIndex += sampleCount;
  613. tempCount -= sampleCount;
  614. pSamples += sampleCount * 2;
  615. }
  616. // if the buffers aren't aligned on sample boundaries, this will hard-lock the machine!
  617. pBuffer->submit_sample_count = GetOutputPosition();
  618. waveOutWrite( m_waveOutHandle, pBuffer->hdr, sizeof(*(pBuffer->hdr)) );
  619. }
  620. }
  621. /*
  622. int CAudioDeviceWave::GetNumberofSamplesAhead( void )
  623. {
  624. ComputeSampleAheadAmount();
  625. return m_nEstimatedSamplesAhead;
  626. }
  627. float CAudioDeviceWave::GetAmountofTimeAhead( void )
  628. {
  629. ComputeSampleAheadAmount();
  630. return ( (float)m_nEstimatedSamplesAhead / (float)OUTPUT_SAMPLE_RATE );
  631. }
  632. // Find the most recent submitted sample that isn't flagged as whdr_done
  633. void CAudioDeviceWave::ComputeSampleAheadAmount( void )
  634. {
  635. m_nEstimatedSamplesAhead = 0;
  636. int newest_sample_index = -1;
  637. int newest_sample_count = 0;
  638. CAudioBuffer *buffer;
  639. if ( ValidDevice() )
  640. {
  641. for ( int i = 0; i < OUTPUT_BUFFER_COUNT; i++ )
  642. {
  643. buffer = &m_buffers[ i ];
  644. if ( !buffer->submitted )
  645. continue;
  646. if ( buffer->hdr->dwFlags & WHDR_DONE )
  647. continue;
  648. if ( buffer->submit_sample_count > newest_sample_count )
  649. {
  650. newest_sample_index = i;
  651. newest_sample_count = buffer->submit_sample_count;
  652. }
  653. }
  654. }
  655. if ( newest_sample_index == -1 )
  656. return;
  657. buffer = &m_buffers[ newest_sample_index ];
  658. int currentPos = GetOutputPosition() ;
  659. m_nEstimatedSamplesAhead = currentPos - buffer->submit_sample_count;
  660. }
  661. */
  662. int CAudioDeviceWave::FindSourceIndex( CAudioMixer *pSource )
  663. {
  664. for ( int i = 0; i < MAX_CHANNELS; i++ )
  665. {
  666. if ( pSource == m_sourceList[i] )
  667. {
  668. return i;
  669. }
  670. }
  671. return -1;
  672. }
  673. CAudioMixer *CAudioDeviceWave::GetMixerForSource( CAudioSource *source )
  674. {
  675. for ( int i = 0; i < MAX_CHANNELS; i++ )
  676. {
  677. if ( !m_sourceList[i] )
  678. continue;
  679. if ( source == m_sourceList[i]->GetSource() )
  680. {
  681. return m_sourceList[i];
  682. }
  683. }
  684. return NULL;
  685. }
  686. void CAudioDeviceWave::AddSource( CAudioMixer *pSource )
  687. {
  688. int slot = 0;
  689. for ( int i = 0; i < MAX_CHANNELS; i++ )
  690. {
  691. if ( !m_sourceList[i] )
  692. {
  693. slot = i;
  694. break;
  695. }
  696. }
  697. if ( m_sourceList[slot] )
  698. {
  699. FreeChannel( slot );
  700. }
  701. SetChannel( slot, pSource );
  702. pSource->SetActive( true );
  703. }
  704. void CAudioDeviceWave::StopSounds( void )
  705. {
  706. for ( int i = 0; i < MAX_CHANNELS; i++ )
  707. {
  708. if ( m_sourceList[i] )
  709. {
  710. FreeChannel( i );
  711. }
  712. }
  713. }
  714. void CAudioDeviceWave::SetChannel( int channelIndex, CAudioMixer *pSource )
  715. {
  716. if ( channelIndex < 0 || channelIndex >= MAX_CHANNELS )
  717. return;
  718. m_sourceList[channelIndex] = pSource;
  719. }
  720. void CAudioDeviceWave::FreeChannel( int channelIndex )
  721. {
  722. if ( channelIndex < 0 || channelIndex >= MAX_CHANNELS )
  723. return;
  724. if ( m_sourceList[channelIndex] )
  725. {
  726. RemoveMixerChannelReferences( m_sourceList[channelIndex] );
  727. delete m_sourceList[channelIndex];
  728. m_sourceList[channelIndex] = NULL;
  729. }
  730. }
  731. int CAudioDeviceWave::GetOutputPosition( void )
  732. {
  733. if ( !m_waveOutHandle )
  734. return 0;
  735. MMTIME mmtime;
  736. mmtime.wType = TIME_SAMPLES;
  737. waveOutGetPosition( m_waveOutHandle, &mmtime, sizeof( MMTIME ) );
  738. // Convert time to sample count
  739. return ( mmtime.u.sample );
  740. }