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.

899 lines
22 KiB

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