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.

1182 lines
25 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #define WIN32_LEAN_AND_MEAN
  8. #include <windows.h>
  9. #include <mmsystem.h>
  10. #include <stdio.h>
  11. #include <math.h>
  12. #include "snd_audio_source.h"
  13. #include "AudioWaveOutput.h"
  14. #include "ISceneManagerSound.h"
  15. #include "utlvector.h"
  16. #include "filesystem.h"
  17. #include "sentence.h"
  18. typedef struct channel_s
  19. {
  20. int leftvol;
  21. int rightvol;
  22. int rleftvol;
  23. int rrightvol;
  24. float pitch;
  25. } channel_t;
  26. #define INPUT_BUFFER_COUNT 32
  27. class CAudioWaveInput : public CAudioInput
  28. {
  29. public:
  30. CAudioWaveInput( void );
  31. ~CAudioWaveInput( void );
  32. // Returns the current count of available samples
  33. int SampleCount( void );
  34. // returns the size of each sample in bytes
  35. int SampleSize( void ) { return m_sampleSize; }
  36. // returns the sampling rate of the data
  37. int SampleRate( void ) { return m_sampleRate; }
  38. // returns a pointer to the actual data
  39. void *SampleData( void );
  40. // release the available data (mark as done)
  41. void SampleRelease( void );
  42. // returns the mono/stereo status of this device (true if stereo)
  43. bool IsStereo( void ) { return m_isStereo; }
  44. // begin sampling
  45. void Start( void );
  46. // stop sampling
  47. void Stop( void );
  48. void WaveMessage( HWAVEIN hdevice, UINT uMsg, DWORD dwParam1, DWORD dwParam2 );
  49. private:
  50. void OpenDevice( void );
  51. bool ValidDevice( void ) { return m_deviceId >= 0; }
  52. void ClearDevice( void ) { m_deviceId = (UINT)-1; }
  53. // returns true if the new format is better
  54. bool BetterFormat( DWORD dwNewFormat, DWORD dwOldFormat );
  55. void InitReadyList( void );
  56. void AddToReadyList( WAVEHDR *pBuffer );
  57. void PopReadyList( void );
  58. WAVEHDR *m_pReadyList;
  59. int m_sampleSize;
  60. int m_sampleRate;
  61. bool m_isStereo;
  62. UINT m_deviceId;
  63. HWAVEIN m_deviceHandle;
  64. WAVEHDR *m_buffers[ INPUT_BUFFER_COUNT ];
  65. };
  66. extern "C" void CALLBACK WaveData( HWAVEIN hwi, UINT uMsg, CAudioWaveInput *pAudio, DWORD dwParam1, DWORD dwParam2 );
  67. CAudioWaveInput::CAudioWaveInput( void )
  68. {
  69. memset( m_buffers, 0, sizeof( m_buffers ) );
  70. int deviceCount = (int)waveInGetNumDevs();
  71. UINT deviceId = (UINT)-1;
  72. DWORD deviceFormat = 0;
  73. int i;
  74. for ( i = 0; i < deviceCount; i++ )
  75. {
  76. WAVEINCAPS waveCaps;
  77. MMRESULT errorCode = waveInGetDevCaps( (UINT)i, &waveCaps, sizeof(waveCaps) );
  78. if ( errorCode == MMSYSERR_NOERROR )
  79. {
  80. // valid device
  81. if ( BetterFormat( waveCaps.dwFormats, deviceFormat ) )
  82. {
  83. deviceId = i;
  84. deviceFormat = waveCaps.dwFormats;
  85. }
  86. }
  87. }
  88. if ( !deviceFormat )
  89. {
  90. m_deviceId = (UINT)-1;
  91. m_sampleSize = 0;
  92. m_sampleRate = 0;
  93. m_isStereo = false;
  94. }
  95. else
  96. {
  97. m_deviceId = deviceId;
  98. m_sampleRate = 44100;
  99. m_isStereo = false;
  100. if ( deviceFormat & WAVE_FORMAT_4M16 )
  101. {
  102. m_sampleSize = 2;
  103. }
  104. else if ( deviceFormat & WAVE_FORMAT_4M08 )
  105. {
  106. m_sampleSize = 1;
  107. }
  108. else
  109. {
  110. // ERROR!
  111. }
  112. OpenDevice();
  113. }
  114. InitReadyList();
  115. }
  116. CAudioWaveInput::~CAudioWaveInput( void )
  117. {
  118. if ( ValidDevice() )
  119. {
  120. Stop();
  121. waveInReset( m_deviceHandle );
  122. waveInClose( m_deviceHandle );
  123. for ( int i = 0; i < INPUT_BUFFER_COUNT; i++ )
  124. {
  125. if ( m_buffers[i] )
  126. {
  127. waveInUnprepareHeader( m_deviceHandle, m_buffers[i], sizeof( *m_buffers[i] ) );
  128. delete[] m_buffers[i]->lpData;
  129. delete m_buffers[i];
  130. }
  131. m_buffers[i] = NULL;
  132. }
  133. ClearDevice();
  134. }
  135. }
  136. void CALLBACK WaveData( HWAVEIN hwi, UINT uMsg, CAudioWaveInput *pAudio, DWORD dwParam1, DWORD dwParam2 )
  137. {
  138. if ( pAudio )
  139. {
  140. pAudio->WaveMessage( hwi, uMsg, dwParam1, dwParam2 );
  141. }
  142. }
  143. void CAudioWaveInput::WaveMessage( HWAVEIN hdevice, UINT uMsg, DWORD dwParam1, DWORD dwParam2 )
  144. {
  145. if ( hdevice != m_deviceHandle )
  146. return;
  147. switch( uMsg )
  148. {
  149. case WIM_DATA:
  150. WAVEHDR *pHeader = (WAVEHDR *)dwParam1;
  151. AddToReadyList( pHeader );
  152. break;
  153. }
  154. }
  155. void CAudioWaveInput::OpenDevice( void )
  156. {
  157. if ( !ValidDevice() )
  158. return;
  159. WAVEFORMATEX format;
  160. memset( &format, 0, sizeof(format) );
  161. format.nAvgBytesPerSec = m_sampleRate * m_sampleSize;
  162. format.nChannels = 1;
  163. format.wBitsPerSample = m_sampleSize * 8;
  164. format.nSamplesPerSec = m_sampleRate;
  165. format.wFormatTag = WAVE_FORMAT_PCM;
  166. format.nBlockAlign = m_sampleSize;
  167. MMRESULT errorCode = waveInOpen( &m_deviceHandle, m_deviceId, &format, (DWORD)WaveData, (DWORD)this, CALLBACK_FUNCTION );
  168. if ( errorCode == MMSYSERR_NOERROR )
  169. {
  170. // valid device opened
  171. int bufferSize = m_sampleSize * m_sampleRate / INPUT_BUFFER_COUNT; // total of one second of data
  172. // allocate buffers
  173. for ( int i = 0; i < INPUT_BUFFER_COUNT; i++ )
  174. {
  175. m_buffers[i] = new WAVEHDR;
  176. m_buffers[i]->lpData = new char[ bufferSize ];
  177. m_buffers[i]->dwBufferLength = bufferSize;
  178. m_buffers[i]->dwUser = 0;
  179. m_buffers[i]->dwFlags = 0;
  180. waveInPrepareHeader( m_deviceHandle, m_buffers[i], sizeof( *m_buffers[i] ) );
  181. waveInAddBuffer( m_deviceHandle, m_buffers[i], sizeof( *m_buffers[i] ) );
  182. }
  183. }
  184. else
  185. {
  186. ClearDevice();
  187. }
  188. }
  189. void CAudioWaveInput::Start( void )
  190. {
  191. if ( !ValidDevice() )
  192. return;
  193. waveInStart( m_deviceHandle );
  194. }
  195. void CAudioWaveInput::Stop( void )
  196. {
  197. if ( !ValidDevice() )
  198. return;
  199. waveInStop( m_deviceHandle );
  200. }
  201. void CAudioWaveInput::InitReadyList( void )
  202. {
  203. m_pReadyList = NULL;
  204. }
  205. void CAudioWaveInput::AddToReadyList( WAVEHDR *pBuffer )
  206. {
  207. WAVEHDR **pList = &m_pReadyList;
  208. waveInUnprepareHeader( m_deviceHandle, pBuffer, sizeof(*pBuffer) );
  209. // insert at the tail of the list
  210. while ( *pList )
  211. {
  212. pList = reinterpret_cast<WAVEHDR **>(&((*pList)->dwUser));
  213. }
  214. pBuffer->dwUser = NULL;
  215. *pList = pBuffer;
  216. }
  217. void CAudioWaveInput::PopReadyList( void )
  218. {
  219. if ( m_pReadyList )
  220. {
  221. WAVEHDR *pBuffer = m_pReadyList;
  222. m_pReadyList = reinterpret_cast<WAVEHDR *>(m_pReadyList->dwUser);
  223. waveInPrepareHeader( m_deviceHandle, pBuffer, sizeof(*pBuffer) );
  224. waveInAddBuffer( m_deviceHandle, pBuffer, sizeof(*pBuffer) );
  225. }
  226. }
  227. #define WAVE_FORMAT_STEREO (WAVE_FORMAT_1S08|WAVE_FORMAT_1S16|WAVE_FORMAT_2S08|WAVE_FORMAT_2S16|WAVE_FORMAT_4S08|WAVE_FORMAT_4S16)
  228. #define WAVE_FORMATS_UNDERSTOOD (0xFFF)
  229. #define WAVE_FORMAT_11K (WAVE_FORMAT_1M08|WAVE_FORMAT_1M16)
  230. #define WAVE_FORMAT_22K (WAVE_FORMAT_2M08|WAVE_FORMAT_2M16)
  231. #define WAVE_FORMAT_44K (WAVE_FORMAT_4M08|WAVE_FORMAT_4M16)
  232. static int HighestBit( DWORD dwFlags )
  233. {
  234. int i = 31;
  235. while ( i )
  236. {
  237. if ( dwFlags & (1<<i) )
  238. return i;
  239. i--;
  240. }
  241. return 0;
  242. }
  243. bool CAudioWaveInput::BetterFormat( DWORD dwNewFormat, DWORD dwOldFormat )
  244. {
  245. dwNewFormat &= WAVE_FORMATS_UNDERSTOOD & (~WAVE_FORMAT_STEREO);
  246. dwOldFormat &= WAVE_FORMATS_UNDERSTOOD & (~WAVE_FORMAT_STEREO);
  247. // our target format is 44.1KHz, mono, 16-bit
  248. if ( HighestBit(dwOldFormat) >= HighestBit(dwNewFormat) )
  249. return false;
  250. return true;
  251. }
  252. int CAudioWaveInput::SampleCount( void )
  253. {
  254. if ( !ValidDevice() )
  255. return 0;
  256. if ( m_pReadyList )
  257. {
  258. switch( SampleSize() )
  259. {
  260. case 2:
  261. return m_pReadyList->dwBytesRecorded >> 1;
  262. case 1:
  263. return m_pReadyList->dwBytesRecorded;
  264. default:
  265. break;
  266. }
  267. }
  268. return 0;
  269. }
  270. void *CAudioWaveInput::SampleData( void )
  271. {
  272. if ( !ValidDevice() )
  273. return NULL;
  274. if ( m_pReadyList )
  275. {
  276. return m_pReadyList->lpData;
  277. }
  278. return NULL;
  279. }
  280. // release the available data (mark as done)
  281. void CAudioWaveInput::SampleRelease( void )
  282. {
  283. PopReadyList();
  284. }
  285. // factory to create a suitable audio input for this system
  286. CAudioInput *CAudioInput::Create( void )
  287. {
  288. // sound source is a singleton for now
  289. static CAudioInput *pSource = NULL;
  290. if ( !pSource )
  291. {
  292. pSource = new CAudioWaveInput;
  293. }
  294. return pSource;
  295. }
  296. void CAudioDeviceSWMix::Mix8Mono( channel_t *pChannel, char *pData, int outputOffset, int inputOffset, int rateScaleFix, int outCount, int timecompress, bool forward )
  297. {
  298. int sampleIndex = 0;
  299. fixedint sampleFrac = inputOffset;
  300. int fixup = 0;
  301. int fixupstep = 1;
  302. if ( !forward )
  303. {
  304. fixup = outCount - 1;
  305. fixupstep = -1;
  306. }
  307. for ( int i = 0; i < outCount; i++, fixup += fixupstep )
  308. {
  309. int dest = max( outputOffset + fixup, 0 );
  310. m_paintbuffer[ dest ].left += pChannel->leftvol * pData[sampleIndex];
  311. m_paintbuffer[ dest ].right += pChannel->rightvol * pData[sampleIndex];
  312. sampleFrac += rateScaleFix;
  313. sampleIndex += FIX_INTPART(sampleFrac);
  314. sampleFrac = FIX_FRACPART(sampleFrac);
  315. }
  316. }
  317. void CAudioDeviceSWMix::Mix8Stereo( channel_t *pChannel, char *pData, int outputOffset, int inputOffset, int rateScaleFix, int outCount, int timecompress, bool forward )
  318. {
  319. int sampleIndex = 0;
  320. fixedint sampleFrac = inputOffset;
  321. int fixup = 0;
  322. int fixupstep = 1;
  323. if ( !forward )
  324. {
  325. fixup = outCount - 1;
  326. fixupstep = -1;
  327. }
  328. for ( int i = 0; i < outCount; i++, fixup += fixupstep )
  329. {
  330. int dest = max( outputOffset + fixup, 0 );
  331. m_paintbuffer[ dest ].left += pChannel->leftvol * pData[sampleIndex];
  332. m_paintbuffer[ dest ].right += pChannel->rightvol * pData[sampleIndex+1];
  333. sampleFrac += rateScaleFix;
  334. sampleIndex += FIX_INTPART(sampleFrac)<<1;
  335. sampleFrac = FIX_FRACPART(sampleFrac);
  336. }
  337. }
  338. void CAudioDeviceSWMix::Mix16Mono( channel_t *pChannel, short *pData, int outputOffset, int inputOffset, int 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])>>8;
  353. m_paintbuffer[ dest ].right += (pChannel->rightvol * pData[sampleIndex])>>8;
  354. sampleFrac += rateScaleFix;
  355. sampleIndex += FIX_INTPART(sampleFrac);
  356. sampleFrac = FIX_FRACPART(sampleFrac);
  357. }
  358. }
  359. void CAudioDeviceSWMix::Mix16Stereo( channel_t *pChannel, short *pData, int outputOffset, int inputOffset, int 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])>>8;
  374. m_paintbuffer[ dest ].right += (pChannel->rightvol * pData[sampleIndex+1])>>8;
  375. sampleFrac += rateScaleFix;
  376. sampleIndex += FIX_INTPART(sampleFrac)<<1;
  377. sampleFrac = FIX_FRACPART(sampleFrac);
  378. }
  379. }
  380. int CAudioDeviceSWMix::MaxSampleCount( void )
  381. {
  382. return PAINTBUFFER_SIZE;
  383. }
  384. void CAudioDeviceSWMix::MixBegin( void )
  385. {
  386. memset( m_paintbuffer, 0, sizeof(m_paintbuffer) );
  387. }
  388. void CAudioDeviceSWMix::TransferBufferStereo16( short *pOutput, int sampleCount )
  389. {
  390. for ( int i = 0; i < sampleCount; i++ )
  391. {
  392. if ( m_paintbuffer[i].left > 32767 )
  393. m_paintbuffer[i].left = 32767;
  394. else if ( m_paintbuffer[i].left < -32768 )
  395. m_paintbuffer[i].left = -32768;
  396. if ( m_paintbuffer[i].right > 32767 )
  397. m_paintbuffer[i].right = 32767;
  398. else if ( m_paintbuffer[i].right < -32768 )
  399. m_paintbuffer[i].right = -32768;
  400. *pOutput++ = (short)m_paintbuffer[i].left;
  401. *pOutput++ = (short)m_paintbuffer[i].right;
  402. }
  403. }
  404. CAudioWaveOutput::CAudioWaveOutput( void )
  405. {
  406. for ( int i = 0; i < OUTPUT_BUFFER_COUNT; i++ )
  407. {
  408. CAudioBuffer *buffer = &m_buffers[ i ];
  409. Assert( buffer );
  410. buffer->hdr = NULL;
  411. buffer->submitted = false;
  412. buffer->submit_sample_count = false;
  413. }
  414. ClearDevice();
  415. OpenDevice();
  416. m_mixTime = -1;
  417. m_sampleIndex = 0;
  418. memset( m_sourceList, 0, sizeof(m_sourceList) );
  419. m_nEstimatedSamplesAhead = (int)( ( float ) OUTPUT_SAMPLE_RATE / 10.0f );
  420. }
  421. void CAudioWaveOutput::RemoveMixerChannelReferences( CAudioMixer *mixer )
  422. {
  423. for ( int i = 0; i < OUTPUT_BUFFER_COUNT; i++ )
  424. {
  425. RemoveFromReferencedList( mixer, &m_buffers[ i ] );
  426. }
  427. }
  428. void CAudioWaveOutput::AddToReferencedList( CAudioMixer *mixer, CAudioBuffer *buffer )
  429. {
  430. // Already in list
  431. for ( int i = 0; i < buffer->m_Referenced.Size(); i++ )
  432. {
  433. if ( buffer->m_Referenced[ i ].mixer == mixer )
  434. {
  435. return;
  436. }
  437. }
  438. // Just remove it
  439. int idx = buffer->m_Referenced.AddToTail();
  440. CAudioMixerState *state = &buffer->m_Referenced[ idx ];
  441. state->mixer = mixer;
  442. state->submit_mixer_sample = mixer->GetSamplePosition();
  443. }
  444. void CAudioWaveOutput::RemoveFromReferencedList( CAudioMixer *mixer, CAudioBuffer *buffer )
  445. {
  446. for ( int i = 0; i < buffer->m_Referenced.Size(); i++ )
  447. {
  448. if ( buffer->m_Referenced[ i ].mixer == mixer )
  449. {
  450. buffer->m_Referenced.Remove( i );
  451. break;
  452. }
  453. }
  454. }
  455. bool CAudioWaveOutput::IsSoundInReferencedList( CAudioMixer *mixer, CAudioBuffer *buffer )
  456. {
  457. for ( int i = 0; i < buffer->m_Referenced.Size(); i++ )
  458. {
  459. if ( buffer->m_Referenced[ i ].mixer == mixer )
  460. {
  461. return true;
  462. }
  463. }
  464. return false;
  465. }
  466. bool CAudioWaveOutput::IsSourceReferencedByActiveBuffer( CAudioMixer *mixer )
  467. {
  468. if ( !ValidDevice() )
  469. return false;
  470. CAudioBuffer *buffer;
  471. for ( int i = 0; i < OUTPUT_BUFFER_COUNT; i++ )
  472. {
  473. buffer = &m_buffers[ i ];
  474. if ( !buffer->submitted )
  475. continue;
  476. if ( buffer->hdr->dwFlags & WHDR_DONE )
  477. continue;
  478. // See if it's referenced
  479. if ( IsSoundInReferencedList( mixer, buffer ) )
  480. return true;
  481. }
  482. return false;
  483. }
  484. CAudioWaveOutput::~CAudioWaveOutput( void )
  485. {
  486. if ( ValidDevice() )
  487. {
  488. waveOutReset( m_deviceHandle );
  489. for ( int i = 0; i < OUTPUT_BUFFER_COUNT; i++ )
  490. {
  491. if ( m_buffers[i].hdr )
  492. {
  493. waveOutUnprepareHeader( m_deviceHandle, m_buffers[i].hdr, sizeof(*m_buffers[i].hdr) );
  494. delete[] m_buffers[i].hdr->lpData;
  495. delete m_buffers[i].hdr;
  496. }
  497. m_buffers[i].hdr = NULL;
  498. m_buffers[i].submitted = false;
  499. m_buffers[i].submit_sample_count = 0;
  500. m_buffers[i].m_Referenced.Purge();
  501. }
  502. waveOutClose( m_deviceHandle );
  503. ClearDevice();
  504. }
  505. }
  506. CAudioBuffer *CAudioWaveOutput::GetEmptyBuffer( void )
  507. {
  508. CAudioBuffer *pOutput = NULL;
  509. if ( ValidDevice() )
  510. {
  511. for ( int i = 0; i < OUTPUT_BUFFER_COUNT; i++ )
  512. {
  513. if ( !(m_buffers[ i ].submitted ) ||
  514. m_buffers[i].hdr->dwFlags & WHDR_DONE )
  515. {
  516. pOutput = &m_buffers[i];
  517. pOutput->submitted = true;
  518. pOutput->m_Referenced.Purge();
  519. break;
  520. }
  521. }
  522. }
  523. return pOutput;
  524. }
  525. void CAudioWaveOutput::SilenceBuffer( short *pSamples, int sampleCount )
  526. {
  527. int i;
  528. for ( i = 0; i < sampleCount; i++ )
  529. {
  530. // left
  531. *pSamples++ = 0;
  532. // right
  533. *pSamples++ = 0;
  534. }
  535. }
  536. void CAudioWaveOutput::Flush( void )
  537. {
  538. waveOutReset( m_deviceHandle );
  539. }
  540. // mix a buffer up to time (time is absolute)
  541. void CAudioWaveOutput::Update( float time )
  542. {
  543. channel_t channel;
  544. channel.leftvol = 200;
  545. channel.rightvol = 200;
  546. channel.pitch = 1.0;
  547. if ( !ValidDevice() )
  548. return;
  549. // reset the system
  550. if ( m_mixTime < 0 || time < m_baseTime )
  551. {
  552. m_baseTime = time;
  553. m_mixTime = 0;
  554. }
  555. // put time in our coordinate frame
  556. time -= m_baseTime;
  557. if ( time > m_mixTime )
  558. {
  559. CAudioBuffer *pBuffer = GetEmptyBuffer();
  560. // no free buffers, mixing is ahead of the playback!
  561. if ( !pBuffer || !pBuffer->hdr )
  562. {
  563. //Con_Printf( "out of buffers\n" );
  564. return;
  565. }
  566. // UNDONE: These numbers are constants
  567. // calc number of samples (2 channels * 2 bytes per sample)
  568. int sampleCount = pBuffer->hdr->dwBufferLength >> 2;
  569. //float oldTime = m_mixTime;
  570. m_mixTime += sampleCount * (1.0f / OUTPUT_SAMPLE_RATE);
  571. short *pSamples = reinterpret_cast<short *>(pBuffer->hdr->lpData);
  572. SilenceBuffer( pSamples, sampleCount );
  573. int tempCount = sampleCount;
  574. while ( tempCount > 0 )
  575. {
  576. if ( tempCount > m_audioDevice.MaxSampleCount() )
  577. sampleCount = m_audioDevice.MaxSampleCount();
  578. else
  579. sampleCount = tempCount;
  580. m_audioDevice.MixBegin();
  581. for ( int i = 0; i < MAX_CHANNELS; i++ )
  582. {
  583. CAudioMixer *pSource = m_sourceList[i];
  584. if ( !pSource )
  585. continue;
  586. int currentsample = pSource->GetSamplePosition();
  587. bool forward = pSource->GetDirection();
  588. if ( pSource->GetActive() )
  589. {
  590. if ( !pSource->MixDataToDevice( &m_audioDevice, &channel, currentsample, sampleCount, SampleRate(), forward ) )
  591. {
  592. // Source becomes inactive when last submitted sample is finally
  593. // submitted. But it lingers until it's no longer referenced
  594. pSource->SetActive( false );
  595. }
  596. else
  597. {
  598. AddToReferencedList( pSource, pBuffer );
  599. }
  600. }
  601. else
  602. {
  603. if ( !IsSourceReferencedByActiveBuffer( pSource ) )
  604. {
  605. if ( !pSource->GetAutoDelete() )
  606. {
  607. FreeChannel( i );
  608. }
  609. }
  610. else
  611. {
  612. pSource->IncrementSamples( &channel, currentsample, sampleCount, SampleRate(), forward );
  613. }
  614. }
  615. }
  616. m_audioDevice.TransferBufferStereo16( pSamples, sampleCount );
  617. m_sampleIndex += sampleCount;
  618. tempCount -= sampleCount;
  619. pSamples += sampleCount * 2;
  620. }
  621. // if the buffers aren't aligned on sample boundaries, this will hard-lock the machine!
  622. pBuffer->submit_sample_count = GetOutputPosition();
  623. waveOutWrite( m_deviceHandle, pBuffer->hdr, sizeof(*(pBuffer->hdr)) );
  624. }
  625. }
  626. int CAudioWaveOutput::GetNumberofSamplesAhead( void )
  627. {
  628. ComputeSampleAheadAmount();
  629. return m_nEstimatedSamplesAhead;
  630. }
  631. float CAudioWaveOutput::GetAmountofTimeAhead( void )
  632. {
  633. ComputeSampleAheadAmount();
  634. return ( (float)m_nEstimatedSamplesAhead / (float)OUTPUT_SAMPLE_RATE );
  635. }
  636. // Find the most recent submitted sample that isn't flagged as whdr_done
  637. void CAudioWaveOutput::ComputeSampleAheadAmount( void )
  638. {
  639. m_nEstimatedSamplesAhead = 0;
  640. int newest_sample_index = -1;
  641. int newest_sample_count = 0;
  642. CAudioBuffer *buffer;
  643. if ( ValidDevice() )
  644. {
  645. for ( int i = 0; i < OUTPUT_BUFFER_COUNT; i++ )
  646. {
  647. buffer = &m_buffers[ i ];
  648. if ( !buffer->submitted )
  649. continue;
  650. if ( buffer->hdr->dwFlags & WHDR_DONE )
  651. continue;
  652. if ( buffer->submit_sample_count > newest_sample_count )
  653. {
  654. newest_sample_index = i;
  655. newest_sample_count = buffer->submit_sample_count;
  656. }
  657. }
  658. }
  659. if ( newest_sample_index == -1 )
  660. return;
  661. buffer = &m_buffers[ newest_sample_index ];
  662. int currentPos = GetOutputPosition() ;
  663. m_nEstimatedSamplesAhead = currentPos - buffer->submit_sample_count;
  664. }
  665. int CAudioWaveOutput::FindSourceIndex( CAudioMixer *pSource )
  666. {
  667. for ( int i = 0; i < MAX_CHANNELS; i++ )
  668. {
  669. if ( pSource == m_sourceList[i] )
  670. {
  671. return i;
  672. }
  673. }
  674. return -1;
  675. }
  676. CAudioMixer *CAudioWaveOutput::GetMixerForSource( CAudioSource *source )
  677. {
  678. for ( int i = 0; i < MAX_CHANNELS; i++ )
  679. {
  680. if ( !m_sourceList[i] )
  681. continue;
  682. if ( source == m_sourceList[i]->GetSource() )
  683. {
  684. return m_sourceList[i];
  685. }
  686. }
  687. return NULL;
  688. }
  689. void CAudioWaveOutput::AddSource( CAudioMixer *pSource )
  690. {
  691. int slot = 0;
  692. for ( int i = 0; i < MAX_CHANNELS; i++ )
  693. {
  694. if ( !m_sourceList[i] )
  695. {
  696. slot = i;
  697. break;
  698. }
  699. }
  700. if ( m_sourceList[slot] )
  701. {
  702. FreeChannel( slot );
  703. }
  704. SetChannel( slot, pSource );
  705. pSource->SetActive( true );
  706. }
  707. void CAudioWaveOutput::StopSounds( void )
  708. {
  709. for ( int i = 0; i < MAX_CHANNELS; i++ )
  710. {
  711. if ( m_sourceList[i] )
  712. {
  713. FreeChannel( i );
  714. }
  715. }
  716. }
  717. void CAudioWaveOutput::SetChannel( int channelIndex, CAudioMixer *pSource )
  718. {
  719. if ( channelIndex < 0 || channelIndex >= MAX_CHANNELS )
  720. return;
  721. m_sourceList[channelIndex] = pSource;
  722. }
  723. void CAudioWaveOutput::FreeChannel( int channelIndex )
  724. {
  725. if ( channelIndex < 0 || channelIndex >= MAX_CHANNELS )
  726. return;
  727. if ( m_sourceList[channelIndex] )
  728. {
  729. RemoveMixerChannelReferences( m_sourceList[channelIndex] );
  730. delete m_sourceList[channelIndex];
  731. m_sourceList[channelIndex] = NULL;
  732. }
  733. }
  734. int CAudioWaveOutput::GetOutputPosition( void )
  735. {
  736. if ( !m_deviceHandle )
  737. return 0;
  738. MMTIME mmtime;
  739. mmtime.wType = TIME_SAMPLES;
  740. waveOutGetPosition( m_deviceHandle, &mmtime, sizeof( MMTIME ) );
  741. // Convert time to sample count
  742. return ( mmtime.u.sample );
  743. }
  744. void CAudioWaveOutput::OpenDevice( void )
  745. {
  746. WAVEFORMATEX waveFormat;
  747. memset( &waveFormat, 0, sizeof(waveFormat) );
  748. // Select a PCM, 16-bit stereo playback device
  749. waveFormat.cbSize = sizeof(waveFormat);
  750. waveFormat.nAvgBytesPerSec = OUTPUT_SAMPLE_RATE * 2 * 2;
  751. waveFormat.nBlockAlign = 2 * 2; // channels * sample size
  752. waveFormat.nChannels = 2; // stereo
  753. waveFormat.nSamplesPerSec = OUTPUT_SAMPLE_RATE;
  754. waveFormat.wBitsPerSample = 16;
  755. waveFormat.wFormatTag = WAVE_FORMAT_PCM;
  756. MMRESULT errorCode = waveOutOpen( &m_deviceHandle, WAVE_MAPPER, &waveFormat, 0, 0, CALLBACK_NULL );
  757. if ( errorCode == MMSYSERR_NOERROR )
  758. {
  759. int bufferSize = 4 * ( OUTPUT_SAMPLE_RATE / OUTPUT_BUFFER_COUNT ); // total of 1 second of data
  760. // Got one!
  761. for ( int i = 0; i < OUTPUT_BUFFER_COUNT; i++ )
  762. {
  763. m_buffers[i].hdr = new WAVEHDR;
  764. m_buffers[i].hdr->lpData = new char[ bufferSize ];
  765. long align = (long)m_buffers[i].hdr->lpData;
  766. if ( align & 3 )
  767. {
  768. m_buffers[i].hdr->lpData = (char *) ( (align+3) &~3 );
  769. }
  770. m_buffers[i].hdr->dwBufferLength = bufferSize - (align&3);
  771. m_buffers[i].hdr->dwFlags = 0;
  772. if ( waveOutPrepareHeader( m_deviceHandle, m_buffers[i].hdr, sizeof(*m_buffers[i].hdr) ) != MMSYSERR_NOERROR )
  773. {
  774. ClearDevice();
  775. return;
  776. }
  777. }
  778. }
  779. else
  780. {
  781. ClearDevice();
  782. }
  783. }
  784. // factory to create a suitable audio output for this system
  785. CAudioOutput *CAudioOutput::Create( void )
  786. {
  787. // sound device is a singleton for now
  788. static CAudioOutput *pWaveOut = NULL;
  789. if ( !pWaveOut )
  790. {
  791. pWaveOut = new CAudioWaveOutput;
  792. }
  793. return pWaveOut;
  794. }
  795. struct CSoundFile
  796. {
  797. char filename[ 512 ];
  798. CAudioSource *source;
  799. long filetime;
  800. };
  801. //-----------------------------------------------------------------------------
  802. // Purpose:
  803. //-----------------------------------------------------------------------------
  804. class CSceneManagerSound : public ISceneManagerSound
  805. {
  806. public:
  807. ~CSceneManagerSound( void );
  808. void Init( void );
  809. void Shutdown( void );
  810. void Update( float dt );
  811. void Flush( void );
  812. CAudioSource *LoadSound( const char *wavfile );
  813. void PlaySound( const char *wavfile, CAudioMixer **ppMixer );
  814. void PlaySound( CAudioSource *source, CAudioMixer **ppMixer );
  815. bool IsSoundPlaying( CAudioMixer *pMixer );
  816. CAudioMixer *FindMixer( CAudioSource *source );
  817. void StopAll( void );
  818. void StopSound( CAudioMixer *mixer );
  819. CAudioOuput *GetAudioOutput( void );
  820. virtual CAudioSource *FindOrAddSound( const char *filename );
  821. private:
  822. CAudioOutput *m_pAudio;
  823. float m_flElapsedTime;
  824. CUtlVector < CSoundFile > m_ActiveSounds;
  825. };
  826. static CSceneManagerSound g_FacePoserSound;
  827. ISceneManagerSound *sound = ( ISceneManagerSound * )&g_FacePoserSound;
  828. CSceneManagerSound::~CSceneManagerSound( void )
  829. {
  830. OutputDebugString( va( "Removing %i sounds\n", m_ActiveSounds.Size() ) );
  831. for ( int i = 0 ; i < m_ActiveSounds.Size(); i++ )
  832. {
  833. CSoundFile *p = &m_ActiveSounds[ i ];
  834. OutputDebugString( va( "Removing sound: %s\n", p->filename ) );
  835. delete p->source;
  836. }
  837. m_ActiveSounds.RemoveAll();
  838. }
  839. //-----------------------------------------------------------------------------
  840. // Purpose:
  841. //-----------------------------------------------------------------------------
  842. CAudioOuput *CSceneManagerSound::GetAudioOutput( void )
  843. {
  844. return (CAudioOuput *)m_pAudio;
  845. }
  846. CAudioSource *CSceneManagerSound::FindOrAddSound( const char *filename )
  847. {
  848. CSoundFile *s;
  849. int i;
  850. for ( i = 0; i < m_ActiveSounds.Size(); i++ )
  851. {
  852. s = &m_ActiveSounds[ i ];
  853. Assert( s );
  854. if ( !stricmp( s->filename, filename ) )
  855. {
  856. long filetime = filesystem->GetFileTime( filename );
  857. if ( filetime != s->filetime )
  858. {
  859. Con_Printf( "Reloading sound %s\n", filename );
  860. delete s->source;
  861. s->source = LoadSound( filename );
  862. s->filetime = filetime;
  863. }
  864. return s->source;
  865. }
  866. }
  867. i = m_ActiveSounds.AddToTail();
  868. s = &m_ActiveSounds[ i ];
  869. strcpy( s->filename, filename );
  870. s->source = LoadSound( filename );
  871. s->filetime = filesystem->GetFileTime( filename );
  872. return s->source;
  873. }
  874. void CSceneManagerSound::Init( void )
  875. {
  876. m_flElapsedTime = 0.0f;
  877. m_pAudio = CAudioOutput::Create();
  878. }
  879. void CSceneManagerSound::Shutdown( void )
  880. {
  881. }
  882. CAudioSource *CSceneManagerSound::LoadSound( const char *wavfile )
  883. {
  884. if ( !m_pAudio )
  885. return NULL;
  886. CAudioSource *wave = AudioSource_Create( wavfile );
  887. return wave;
  888. }
  889. void CSceneManagerSound::PlaySound( const char *wavfile, CAudioMixer **ppMixer )
  890. {
  891. if ( m_pAudio )
  892. {
  893. CAudioSource *wave = FindOrAddSound( wavfile );
  894. if ( !wave )
  895. return;
  896. CAudioMixer *pMixer = wave->CreateMixer();
  897. if ( ppMixer )
  898. {
  899. *ppMixer = pMixer;
  900. }
  901. m_pAudio->AddSource( pMixer );
  902. }
  903. }
  904. void CSceneManagerSound::PlaySound( CAudioSource *source, CAudioMixer **ppMixer )
  905. {
  906. if ( ppMixer )
  907. {
  908. *ppMixer = NULL;
  909. }
  910. if ( m_pAudio )
  911. {
  912. CAudioMixer *mixer = source->CreateMixer();
  913. if ( ppMixer )
  914. {
  915. *ppMixer = mixer;
  916. }
  917. m_pAudio->AddSource( mixer );
  918. }
  919. }
  920. void CSceneManagerSound::Update( float dt )
  921. {
  922. if ( m_pAudio )
  923. {
  924. m_pAudio->Update( m_flElapsedTime );
  925. }
  926. m_flElapsedTime += dt;
  927. }
  928. void CSceneManagerSound::Flush( void )
  929. {
  930. if ( m_pAudio )
  931. {
  932. m_pAudio->Flush();
  933. }
  934. }
  935. void CSceneManagerSound::StopAll( void )
  936. {
  937. if ( m_pAudio )
  938. {
  939. m_pAudio->StopSounds();
  940. }
  941. }
  942. void CSceneManagerSound::StopSound( CAudioMixer *mixer )
  943. {
  944. int idx = m_pAudio->FindSourceIndex( mixer );
  945. if ( idx != -1 )
  946. {
  947. m_pAudio->FreeChannel( idx );
  948. }
  949. }
  950. bool CSceneManagerSound::IsSoundPlaying( CAudioMixer *pMixer )
  951. {
  952. if ( !m_pAudio || !pMixer )
  953. {
  954. return false;
  955. }
  956. //
  957. int index = m_pAudio->FindSourceIndex( pMixer );
  958. if ( index != -1 )
  959. return true;
  960. return false;
  961. }
  962. CAudioMixer *CSceneManagerSound::FindMixer( CAudioSource *source )
  963. {
  964. if ( !m_pAudio )
  965. return NULL;
  966. return m_pAudio->GetMixerForSource( source );
  967. }