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.

788 lines
28 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=====================================================================================//
  6. #include "audio_pch.h"
  7. #include "fmtstr.h"
  8. #include "sysexternal.h"
  9. // memdbgon must be the last include file in a .cpp file!!!
  10. #include "tier0/memdbgon.h"
  11. extern bool FUseHighQualityPitch( channel_t *pChannel );
  12. //-----------------------------------------------------------------------------
  13. // These mixers provide an abstraction layer between the audio device and
  14. // mixing/decoding code. They allow data to be decoded and mixed using
  15. // optimized, format sensitive code by calling back into the device that
  16. // controls them.
  17. //-----------------------------------------------------------------------------
  18. //-----------------------------------------------------------------------------
  19. // Purpose: maps mixing to 8-bit mono mixer
  20. //-----------------------------------------------------------------------------
  21. class CAudioMixerWave8Mono : public CAudioMixerWave
  22. {
  23. public:
  24. CAudioMixerWave8Mono( IWaveData *data ) : CAudioMixerWave( data ) {}
  25. virtual int GetMixSampleSize() { return CalcSampleSize(8, 1); }
  26. virtual void Mix( IAudioDevice *pDevice, channel_t *pChannel, void *pData, int outputOffset, int inputOffset, fixedint fracRate, int outCount, int timecompress )
  27. {
  28. pDevice->Mix8Mono( pChannel, (char *)pData, outputOffset, inputOffset, fracRate, outCount, timecompress );
  29. }
  30. };
  31. //-----------------------------------------------------------------------------
  32. // Purpose: maps mixing to 8-bit stereo mixer
  33. //-----------------------------------------------------------------------------
  34. class CAudioMixerWave8Stereo : public CAudioMixerWave
  35. {
  36. public:
  37. CAudioMixerWave8Stereo( IWaveData *data ) : CAudioMixerWave( data ) {}
  38. virtual int GetMixSampleSize( ) { return CalcSampleSize(8, 2); }
  39. virtual void Mix( IAudioDevice *pDevice, channel_t *pChannel, void *pData, int outputOffset, int inputOffset, fixedint fracRate, int outCount, int timecompress )
  40. {
  41. pDevice->Mix8Stereo( pChannel, (char *)pData, outputOffset, inputOffset, fracRate, outCount, timecompress );
  42. }
  43. };
  44. //-----------------------------------------------------------------------------
  45. // Purpose: maps mixing to 16-bit mono mixer
  46. //-----------------------------------------------------------------------------
  47. class CAudioMixerWave16Mono : public CAudioMixerWave
  48. {
  49. public:
  50. CAudioMixerWave16Mono( IWaveData *data ) : CAudioMixerWave( data ) {}
  51. virtual int GetMixSampleSize() { return CalcSampleSize(16, 1); }
  52. virtual void Mix( IAudioDevice *pDevice, channel_t *pChannel, void *pData, int outputOffset, int inputOffset, fixedint fracRate, int outCount, int timecompress )
  53. {
  54. pDevice->Mix16Mono( pChannel, (short *)pData, outputOffset, inputOffset, fracRate, outCount, timecompress );
  55. }
  56. };
  57. //-----------------------------------------------------------------------------
  58. // Purpose: maps mixing to 16-bit stereo mixer
  59. //-----------------------------------------------------------------------------
  60. class CAudioMixerWave16Stereo : public CAudioMixerWave
  61. {
  62. public:
  63. CAudioMixerWave16Stereo( IWaveData *data ) : CAudioMixerWave( data ) {}
  64. virtual int GetMixSampleSize() { return CalcSampleSize(16, 2); }
  65. virtual void Mix( IAudioDevice *pDevice, channel_t *pChannel, void *pData, int outputOffset, int inputOffset, fixedint fracRate, int outCount, int timecompress )
  66. {
  67. pDevice->Mix16Stereo( pChannel, (short *)pData, outputOffset, inputOffset, fracRate, outCount, timecompress );
  68. }
  69. };
  70. //-----------------------------------------------------------------------------
  71. // Purpose: Create an appropriate mixer type given the data format
  72. // Input : *data - data access abstraction
  73. // format - pcm or adpcm (1 or 2 -- RIFF format)
  74. // channels - number of audio channels (1 = mono, 2 = stereo)
  75. // bits - bits per sample
  76. // Output : CAudioMixer * abstract mixer type that maps mixing to appropriate code
  77. //-----------------------------------------------------------------------------
  78. CAudioMixer *CreateWaveMixer( IWaveData *data, int format, int nChannels, int bits, int initialStreamPosition )
  79. {
  80. CAudioMixer *pMixer = NULL;
  81. if ( format == WAVE_FORMAT_PCM )
  82. {
  83. if ( nChannels > 1 )
  84. {
  85. if ( bits == 8 )
  86. pMixer = new CAudioMixerWave8Stereo( data );
  87. else
  88. pMixer = new CAudioMixerWave16Stereo( data );
  89. }
  90. else
  91. {
  92. if ( bits == 8 )
  93. pMixer = new CAudioMixerWave8Mono( data );
  94. else
  95. pMixer = new CAudioMixerWave16Mono( data );
  96. }
  97. }
  98. else if ( format == WAVE_FORMAT_ADPCM )
  99. {
  100. return CreateADPCMMixer( data );
  101. }
  102. #if defined( _X360 )
  103. else if ( format == WAVE_FORMAT_XMA )
  104. {
  105. return CreateXMAMixer( data, initialStreamPosition );
  106. }
  107. #endif
  108. else
  109. {
  110. // unsupported format or wav file missing!!!
  111. return NULL;
  112. }
  113. if ( pMixer )
  114. {
  115. Assert( CalcSampleSize(bits, nChannels ) == pMixer->GetMixSampleSize() );
  116. }
  117. else
  118. {
  119. Assert( 0 );
  120. }
  121. return pMixer;
  122. }
  123. //-----------------------------------------------------------------------------
  124. // Purpose: Init the base WAVE mixer.
  125. // Input : *data - data access object
  126. //-----------------------------------------------------------------------------
  127. CAudioMixerWave::CAudioMixerWave( IWaveData *data ) : m_pData(data)
  128. {
  129. CAudioSource *pSource = GetSource();
  130. if ( pSource )
  131. {
  132. pSource->ReferenceAdd( this );
  133. }
  134. m_fsample_index = 0;
  135. m_sample_max_loaded = 0;
  136. m_sample_loaded_index = -1;
  137. m_finished = false;
  138. m_forcedEndSample = 0;
  139. m_delaySamples = 0;
  140. }
  141. //-----------------------------------------------------------------------------
  142. // Purpose: Frees the data access object (we own it after construction)
  143. //-----------------------------------------------------------------------------
  144. CAudioMixerWave::~CAudioMixerWave( void )
  145. {
  146. CAudioSource *pSource = GetSource();
  147. if ( pSource )
  148. {
  149. pSource->ReferenceRemove( this );
  150. }
  151. delete m_pData;
  152. }
  153. bool CAudioMixerWave::IsReadyToMix()
  154. {
  155. return m_pData->IsReadyToMix();
  156. }
  157. //-----------------------------------------------------------------------------
  158. // Purpose: Decode and read the data
  159. // by default we just pass the request on to the data access object
  160. // other mixers may need to buffer or decode the data for some reason
  161. //
  162. // Input : **pData - dest pointer
  163. // sampleCount - number of samples needed
  164. // Output : number of samples available in this batch
  165. //-----------------------------------------------------------------------------
  166. int CAudioMixerWave::GetOutputData( void **pData, int sampleCount, char copyBuf[AUDIOSOURCE_COPYBUF_SIZE] )
  167. {
  168. int samples_loaded;
  169. // clear this out in case the underlying code leaves it unmodified
  170. *pData = NULL;
  171. samples_loaded = m_pData->ReadSourceData( pData, m_sample_max_loaded, sampleCount, copyBuf );
  172. // keep track of total samples loaded
  173. m_sample_max_loaded += samples_loaded;
  174. // keep track of index of last sample loaded
  175. m_sample_loaded_index += samples_loaded;
  176. return samples_loaded;
  177. }
  178. //-----------------------------------------------------------------------------
  179. // Purpose: calls through the wavedata to get the audio source
  180. // Output : CAudioSource
  181. //-----------------------------------------------------------------------------
  182. CAudioSource *CAudioMixerWave::GetSource( void )
  183. {
  184. if ( m_pData )
  185. return &m_pData->Source();
  186. return NULL;
  187. }
  188. //-----------------------------------------------------------------------------
  189. // Purpose: Gets the current sample location in playback (index of next sample
  190. // to be loaded).
  191. // Output : int (samples from start of wave)
  192. //-----------------------------------------------------------------------------
  193. int CAudioMixerWave::GetSamplePosition( void )
  194. {
  195. return m_sample_max_loaded;
  196. }
  197. //-----------------------------------------------------------------------------
  198. // Purpose:
  199. // Input : delaySamples -
  200. //-----------------------------------------------------------------------------
  201. void CAudioMixerWave::SetStartupDelaySamples( int delaySamples )
  202. {
  203. m_delaySamples = delaySamples;
  204. }
  205. // Move the current position to newPosition
  206. void CAudioMixerWave::SetSampleStart( int newPosition )
  207. {
  208. CAudioSource *pSource = GetSource();
  209. if ( pSource )
  210. newPosition = pSource->ZeroCrossingAfter( newPosition );
  211. m_fsample_index = newPosition;
  212. // index of last sample loaded - set to sample at new position
  213. m_sample_loaded_index = newPosition;
  214. m_sample_max_loaded = m_sample_loaded_index + 1;
  215. }
  216. // End playback at newEndPosition
  217. void CAudioMixerWave::SetSampleEnd( int newEndPosition )
  218. {
  219. // forced end of zero means play the whole sample
  220. if ( !newEndPosition )
  221. newEndPosition = 1;
  222. CAudioSource *pSource = GetSource();
  223. if ( pSource )
  224. newEndPosition = pSource->ZeroCrossingBefore( newEndPosition );
  225. // past current position? limit.
  226. if ( newEndPosition < m_fsample_index )
  227. newEndPosition = m_fsample_index;
  228. m_forcedEndSample = newEndPosition;
  229. }
  230. //-----------------------------------------------------------------------------
  231. // Purpose: Skip source data (read but don't mix). The mixer must provide the
  232. // full amount of samples or have silence in its output stream.
  233. //-----------------------------------------------------------------------------
  234. int CAudioMixerWave::SkipSamples( channel_t *pChannel, int sampleCount, int outputRate, int outputOffset )
  235. {
  236. float flTempPitch = pChannel->pitch;
  237. pChannel->pitch = 1.0f;
  238. int nRetVal = MixDataToDevice_( NULL, pChannel, sampleCount, outputRate, outputOffset, true );
  239. pChannel->pitch = flTempPitch;
  240. return nRetVal;
  241. }
  242. // wrapper routine to append without overflowing the temp buffer
  243. static uint AppendToBuffer( char *pBuffer, const char *pSampleData, size_t nBytes, const char *pBufferEnd )
  244. {
  245. #if defined(_WIN32) && !defined(_X360)
  246. // FIXME: Some clients are crashing here. Let's try to detect why.
  247. if ( nBytes > 0 && ( (size_t)pBuffer <= 0xFFF || (size_t)pSampleData <= 0xFFF ) )
  248. {
  249. Warning( "AppendToBuffer received potentially bad values (%p, %p, %u, %p)\n", pBuffer, pSampleData, (int)nBytes, pBufferEnd );
  250. }
  251. #endif
  252. if ( pBufferEnd > pBuffer )
  253. {
  254. size_t nAvail = pBufferEnd - pBuffer;
  255. size_t nCopy = MIN( nBytes, nAvail );
  256. Q_memcpy( pBuffer, pSampleData, nCopy );
  257. return nCopy;
  258. }
  259. else
  260. {
  261. return 0;
  262. }
  263. }
  264. // Load a static copy buffer (g_temppaintbuffer) with the requested number of samples,
  265. // with the first sample(s) in the buffer always set up as the last sample(s) of the previous load.
  266. // Return a pointer to the head of the copy buffer.
  267. // This ensures that interpolating pitch shifters always have the previous sample to reference.
  268. // pChannel: sound's channel data
  269. // sample_load_request: number of samples to load from source data
  270. // pSamplesLoaded: returns the actual number of samples loaded (should always = sample_load_request)
  271. // copyBuf: req'd by GetOutputData, used by some Mixers
  272. // Returns: NULL ptr to data if no samples available, otherwise always fills remainder of copy buffer with
  273. // 0 to pad remainder.
  274. // NOTE: DO NOT MODIFY THIS ROUTINE (KELLYB)
  275. char *CAudioMixerWave::LoadMixBuffer( channel_t *pChannel, int sample_load_request, int *pSamplesLoaded, char copyBuf[AUDIOSOURCE_COPYBUF_SIZE] )
  276. {
  277. int samples_loaded;
  278. char *pSample = NULL;
  279. char *pData = NULL;
  280. int cCopySamps = 0;
  281. // save index of last sample loaded (updated in GetOutputData)
  282. int sample_loaded_index = m_sample_loaded_index;
  283. // get data from source (copyBuf is expected to be available for use)
  284. samples_loaded = GetOutputData( (void **)&pData, sample_load_request, copyBuf );
  285. if ( !samples_loaded && sample_load_request )
  286. {
  287. // none available, bail out
  288. // 360 might not be able to get samples due to latency of loop seek
  289. // could also be the valid EOF for non-loops (caller keeps polling for data, until no more)
  290. AssertOnce( IsX360() || !m_pData->Source().IsLooped() );
  291. *pSamplesLoaded = 0;
  292. return NULL;
  293. }
  294. int samplesize = GetMixSampleSize();
  295. const int nTempCopyBufferSize = ( TEMP_COPY_BUFFER_SIZE * sizeof( portable_samplepair_t ) );
  296. char *pCopy = (char *)g_temppaintbuffer;
  297. const char *pCopyBufferEnd = pCopy + nTempCopyBufferSize;
  298. if ( IsX360() || IsDebug() )
  299. {
  300. // for safety, 360 always validates sample request, due to new xma audio code and possible logic flaws
  301. // PC can expect number of requested samples to be within tolerances due to exisiting aged code
  302. // otherwise buffer overruns cause hard to track random crashes
  303. if ( ( ( sample_load_request + 1 ) * samplesize ) > nTempCopyBufferSize )
  304. {
  305. // make sure requested samples will fit in temp buffer.
  306. // if this assert fails, then pitch is too high (ie: > 2.0) or the sample counters have diverged.
  307. // NOTE: to prevent this, pitch should always be capped in MixDataToDevice (but isn't nor are the sample counters).
  308. DevWarning( "LoadMixBuffer: sample load request %d exceeds buffer sizes\n", sample_load_request );
  309. Assert( 0 );
  310. *pSamplesLoaded = 0;
  311. return NULL;
  312. }
  313. }
  314. // copy all samples from pData to copy buffer, set 0th sample to saved previous sample - this ensures
  315. // interpolation pitch shift routines always have a previous sample to reference.
  316. // copy previous sample(s) to head of copy buffer pCopy
  317. // In some cases, we'll need the previous 2 samples. This occurs when
  318. // Rate < 1.0 - in example below, sample 4.86 - 6.48 requires samples 4-7 (previous samples saved are 4 & 5)
  319. /*
  320. Example:
  321. rate = 0.81, sampleCount = 3 (ie: # of samples to return )
  322. _____load 3______ ____load 3_______ __load 2__
  323. 0 1 2 3 4 5 6 7 sample_index (whole samples)
  324. ^ ^ ^ ^ ^ ^ ^ ^ ^
  325. | | | | | | | | |
  326. 0 0.81 1.68 2.43 3.24 4.05 4.86 5.67 6.48 m_fsample_index (rate*sample)
  327. _______________ ________________ ________________
  328. ^ ^ ^ ^
  329. | | | |
  330. m_sample_loaded_index | | m_sample_loaded_index
  331. | |
  332. m_fsample_index---- ----m_fsample_index
  333. [return 3 samp] [return 3 samp] [return 3 samp]
  334. */
  335. pSample = &(pChannel->sample_prev[0]);
  336. // determine how many saved samples we need to copy to head of copy buffer (0,1 or 2)
  337. // so that pitch interpolation will correctly reference samples.
  338. // NOTE: pitch interpolators always reference the sample before and after the indexed sample.
  339. // cCopySamps = sample_max_loaded - floor(m_fsample_index);
  340. if ( sample_loaded_index < 0 || (floor(m_fsample_index) > sample_loaded_index))
  341. {
  342. // no samples previously loaded, or
  343. // next sample index is entirely within the next block of samples to be loaded,
  344. // so we won't need any samples from the previous block. (can occur when rate > 2.0)
  345. cCopySamps = 0;
  346. }
  347. else if ( m_fsample_index < sample_loaded_index )
  348. {
  349. // next sample index is entirely within the previous block of samples loaded,
  350. // so we'll need the last 2 samples loaded. (can occur when rate < 1.0)
  351. Assert ( ceil(m_fsample_index + 0.00000001) == sample_loaded_index );
  352. cCopySamps = 2;
  353. }
  354. else
  355. {
  356. // next sample index is between the next block and the previously loaded block,
  357. // so we'll need the last sample loaded. (can occur when 1.0 < rate < 2.0)
  358. Assert( floor(m_fsample_index) == sample_loaded_index );
  359. cCopySamps = 1;
  360. }
  361. Assert( cCopySamps >= 0 && cCopySamps <= 2 );
  362. // point to the sample(s) we are to copy
  363. if ( cCopySamps )
  364. {
  365. pSample = cCopySamps == 1 ? pSample + samplesize : pSample;
  366. pCopy += AppendToBuffer( pCopy, pSample, samplesize * cCopySamps, pCopyBufferEnd );
  367. }
  368. // copy loaded samples from pData into pCopy
  369. // and update pointer to free space in copy buffer
  370. if ( ( samples_loaded * samplesize ) != 0 && !pData )
  371. {
  372. char const *pWavName = "";
  373. CSfxTable *source = pChannel->sfx;
  374. if ( source )
  375. {
  376. pWavName = source->getname();
  377. }
  378. Warning( "CAudioMixerWave::LoadMixBuffer: '%s' samples_loaded * samplesize = %i but pData == NULL\n", pWavName, ( samples_loaded * samplesize ) );
  379. *pSamplesLoaded = 0;
  380. return NULL;
  381. }
  382. pCopy += AppendToBuffer( pCopy, pData, samples_loaded * samplesize, pCopyBufferEnd );
  383. // if we loaded fewer samples than we wanted to, and we're not
  384. // delaying, load more samples or, if we run out of samples from non-looping source,
  385. // pad copy buffer.
  386. if ( samples_loaded < sample_load_request )
  387. {
  388. // retry loading source data until 0 bytes returned, or we've loaded enough data.
  389. // if we hit 0 bytes, fill remaining space in copy buffer with 0 and exit
  390. int samples_load_extra;
  391. int samples_loaded_retry = -1;
  392. for ( int k = 0; (k < 10000 && samples_loaded_retry && samples_loaded < sample_load_request); k++ )
  393. {
  394. // how many more samples do we need to satisfy load request
  395. samples_load_extra = sample_load_request - samples_loaded;
  396. samples_loaded_retry = GetOutputData( (void**)&pData, samples_load_extra, copyBuf );
  397. // copy loaded samples from pData into pCopy
  398. if ( samples_loaded_retry )
  399. {
  400. if ( ( samples_loaded_retry * samplesize ) != 0 && !pData )
  401. {
  402. Warning( "CAudioMixerWave::LoadMixBuffer: samples_loaded_retry * samplesize = %i but pData == NULL\n", ( samples_loaded_retry * samplesize ) );
  403. *pSamplesLoaded = 0;
  404. return NULL;
  405. }
  406. pCopy += AppendToBuffer( pCopy, pData, samples_loaded_retry * samplesize, pCopyBufferEnd );
  407. samples_loaded += samples_loaded_retry;
  408. }
  409. }
  410. }
  411. // if we still couldn't load the requested samples, fill rest of copy buffer with 0
  412. if ( samples_loaded < sample_load_request )
  413. {
  414. // should always be able to get as many samples as we request from looping sound sources
  415. AssertOnce ( IsX360() || !m_pData->Source().IsLooped() );
  416. // these samples are filled with 0, not loaded.
  417. // non-looping source hit end of data, fill rest of g_temppaintbuffer with 0
  418. int samples_zero_fill = sample_load_request - samples_loaded;
  419. int nAvail = pCopyBufferEnd - pCopy;
  420. int nFill = samples_zero_fill * samplesize;
  421. nFill = MIN( nAvail, nFill );
  422. Q_memset( pCopy, 0, nFill );
  423. pCopy += nFill;
  424. samples_loaded += samples_zero_fill;
  425. }
  426. if ( samples_loaded >= 2 )
  427. {
  428. // always save last 2 samples from copy buffer to channel
  429. // (we'll need 0,1 or 2 samples as start of next buffer for interpolation)
  430. Assert( sizeof( pChannel->sample_prev ) >= samplesize*2 );
  431. pSample = pCopy - samplesize*2;
  432. Q_memcpy( &(pChannel->sample_prev[0]), pSample, samplesize*2 );
  433. }
  434. // this routine must always return as many samples loaded (or zeros) as requested.
  435. Assert( samples_loaded == sample_load_request );
  436. *pSamplesLoaded = samples_loaded;
  437. return (char *)g_temppaintbuffer;
  438. }
  439. // Helper routine to round (rate * samples) down to fixed point precision
  440. double RoundToFixedPoint( double rate, int samples, bool bInterpolated_pitch )
  441. {
  442. fixedint fixp_rate;
  443. int64 d64_newSamps; // need to use double precision int to avoid overflow
  444. double newSamps;
  445. // get rate, in fixed point, determine new samples at rate
  446. if ( bInterpolated_pitch )
  447. fixp_rate = FIX_FLOAT14(rate); // 14 bit iterator
  448. else
  449. fixp_rate = FIX_FLOAT(rate); // 28 bit iterator
  450. // get number of new samples, convert back to float
  451. d64_newSamps = (int64)fixp_rate * (int64)samples;
  452. if ( bInterpolated_pitch )
  453. newSamps = FIX_14TODOUBLE(d64_newSamps);
  454. else
  455. newSamps = FIX_TODOUBLE(d64_newSamps);
  456. return newSamps;
  457. }
  458. extern double MIX_GetMaxRate( double rate, int sampleCount );
  459. // Helper routine for MixDataToDevice:
  460. // Compute number of new samples to load at 'rate' so we can
  461. // output 'sampleCount' samples, from m_fsample_index to fsample_index_end (inclusive)
  462. // rate: sample rate
  463. // sampleCountOut: number of samples calling routine needs to output
  464. // bInterpolated_pitch: true if mixers use interpolating pitch shifters
  465. int CAudioMixerWave::GetSampleLoadRequest( double rate, int sampleCountOut, bool bInterpolated_pitch )
  466. {
  467. double fsample_index_end; // index of last sample we'll need
  468. int sample_index_high; // rounded up last sample index
  469. int sample_load_request; // number of samples to load
  470. // NOTE: we must use fixed point math here, identical to math in mixers, to make sure
  471. // we predict iteration results exactly.
  472. // get floating point sample index of last sample we'll need
  473. fsample_index_end = m_fsample_index + RoundToFixedPoint( rate, sampleCountOut-1, bInterpolated_pitch );
  474. // always round up to ensure we'll have that n+1 sample for interpolation
  475. sample_index_high = (int)( ceil( fsample_index_end ) );
  476. // make sure we always round the floating point index up by at least 1 sample,
  477. // ie: make sure integer sample_index_high is greater than floating point sample index
  478. if ( (double)sample_index_high <= fsample_index_end )
  479. {
  480. sample_index_high++;
  481. }
  482. Assert ( sample_index_high > fsample_index_end );
  483. // attempt to load enough samples so we can reach sample_index_high sample.
  484. sample_load_request = sample_index_high - m_sample_loaded_index;
  485. Assert( sample_index_high >= m_sample_loaded_index );
  486. // NOTE: we can actually return 0 samples to load if rate < 1.0
  487. // and sampleCountOut == 1. In this case, the output sample
  488. // is computed from the previously saved buffer data.
  489. return sample_load_request;
  490. }
  491. int CAudioMixerWave::MixDataToDevice( IAudioDevice *pDevice, channel_t *pChannel, int sampleCount, int outputRate, int outputOffset )
  492. {
  493. return MixDataToDevice_(pDevice, pChannel, sampleCount, outputRate, outputOffset, false );
  494. }
  495. //-----------------------------------------------------------------------------
  496. // Purpose: The device calls this to request data. The mixer must provide the
  497. // full amount of samples or have silence in its output stream.
  498. // Mix channel to all active paintbuffers.
  499. // NOTE: cannot be called consecutively to mix into multiple paintbuffers!
  500. // Input : *pDevice - requesting device
  501. // sampleCount - number of samples at the output rate - should never be more than size of paintbuffer.
  502. // outputRate - sampling rate of the request
  503. // outputOffset - starting offset to mix to in paintbuffer
  504. // bskipallmixing - true if we just want to skip ahead in source data
  505. // Output : Returns true to keep mixing, false to delete this mixer
  506. // NOTE: DO NOT MODIFY THIS ROUTINE (KELLYB)
  507. //-----------------------------------------------------------------------------
  508. int CAudioMixerWave::MixDataToDevice_( IAudioDevice *pDevice, channel_t *pChannel, int sampleCount, int outputRate, int outputOffset, bool bSkipAllMixing )
  509. {
  510. // shouldn't be playing this if finished, but return if we are
  511. if ( m_finished )
  512. return 0;
  513. tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s", __FUNCTION__ );
  514. // save this to compute total output
  515. int startingOffset = outputOffset;
  516. double inputRate = (pChannel->pitch * m_pData->Source().SampleRate());
  517. double rate_max = inputRate / outputRate;
  518. // If we are terminating this wave prematurely, then make sure we detect the limit
  519. if ( m_forcedEndSample )
  520. {
  521. // How many total input samples will we need?
  522. int samplesRequired = (int)(sampleCount * rate_max);
  523. // will this hit the end?
  524. if ( m_fsample_index + samplesRequired >= m_forcedEndSample )
  525. {
  526. // yes, mark finished and truncate the sample request
  527. m_finished = true;
  528. sampleCount = (int)( (m_forcedEndSample - m_fsample_index) / rate_max );
  529. }
  530. }
  531. /*
  532. Example:
  533. rate = 1.2, sampleCount = 3 (ie: # of samples to return )
  534. ______load 4 samples_____ ________load 4 samples____ ___load 3 samples__
  535. 0 1 2 3 4 5 6 7 8 9 10 sample_index (whole samples)
  536. ^ ^ ^ ^ ^ ^ ^ ^ ^
  537. | | | | | | | | |
  538. 0 1.2 2.4 3.6 4.8 6.0 7.2 8.4 9.6 m_fsample_index (rate*sample)
  539. _______return 3_______ _______return 3_______ _______return 3__________
  540. ^ ^
  541. | |
  542. m_sample_loaded_index----- | (after first load 4 samples, this is where pointers are)
  543. m_fsample_index---------
  544. */
  545. while ( sampleCount > 0 )
  546. {
  547. bool advanceSample = true;
  548. int samples_loaded, outputSampleCount;
  549. char *pData = NULL;
  550. double fsample_index_prev = m_fsample_index; // save so we can modify in LoadMixBuffer
  551. bool bInterpolated_pitch = FUseHighQualityPitch( pChannel );
  552. double rate;
  553. VPROF_( bInterpolated_pitch ? "CAudioMixerWave::MixData innerloop interpolated" : "CAudioMixerWave::MixData innerloop not interpolated", 2, VPROF_BUDGETGROUP_OTHER_SOUND, false, BUDGETFLAG_OTHER );
  554. // process samples in paintbuffer-sized batches
  555. int sampleCountOut = min( sampleCount, PAINTBUFFER_SIZE );
  556. // cap rate so that we never overflow the input copy buffer.
  557. rate = MIX_GetMaxRate( rate_max, sampleCountOut );
  558. if ( m_delaySamples > 0 )
  559. {
  560. // If we are preceding sample playback with a delay,
  561. // just fill data buffer with 0 value samples.
  562. // Because there is no pitch shift applied, outputSampleCount == sampleCountOut.
  563. int num_zero_samples = min( m_delaySamples, sampleCountOut );
  564. // Decrement delay counter
  565. m_delaySamples -= num_zero_samples;
  566. int sampleSize = GetMixSampleSize();
  567. int readBytes = sampleSize * num_zero_samples;
  568. // make sure we don't overflow temp copy buffer (g_temppaintbuffer)
  569. Assert ( (TEMP_COPY_BUFFER_SIZE * sizeof(portable_samplepair_t)) > readBytes );
  570. pData = (char *)g_temppaintbuffer;
  571. // Now copy in some zeroes
  572. memset( pData, 0, readBytes );
  573. // we don't pitch shift these samples, so outputSampleCount == samples_loaded
  574. samples_loaded = num_zero_samples;
  575. outputSampleCount = num_zero_samples;
  576. advanceSample = false;
  577. // the zero samples are at the output rate, so set the input/output ratio to 1.0
  578. rate = 1.0f;
  579. }
  580. else
  581. {
  582. // ask the source for the data...
  583. // temp buffer req'd by some data loaders
  584. char copyBuf[AUDIOSOURCE_COPYBUF_SIZE];
  585. // compute number of new samples to load at 'rate' so we can
  586. // output 'sampleCount' samples, from m_fsample_index to fsample_index_end (inclusive)
  587. int sample_load_request = GetSampleLoadRequest( rate, sampleCountOut, bInterpolated_pitch );
  588. // return pointer to a new copy buffer (g_temppaintbuffer) loaded with sample_load_request samples +
  589. // first sample(s), which are always the last sample(s) from the previous load.
  590. // Always returns sample_load_request samples. Updates m_sample_max_loaded, m_sample_loaded_index.
  591. pData = LoadMixBuffer( pChannel, sample_load_request, &samples_loaded, copyBuf );
  592. // LoadMixBuffer should always return requested samples.
  593. Assert ( !pData || ( samples_loaded == sample_load_request ) );
  594. outputSampleCount = sampleCountOut;
  595. }
  596. // no samples available
  597. if ( !pData )
  598. {
  599. break;
  600. }
  601. // get sample fraction from 0th sample in copy buffer
  602. double sampleFraction = m_fsample_index - floor( m_fsample_index );
  603. // if just skipping samples in source, don't mix, just keep reading
  604. if ( !bSkipAllMixing )
  605. {
  606. // mix this data to all active paintbuffers
  607. // Verify that we won't get a buffer overrun.
  608. Assert( floor( sampleFraction + RoundToFixedPoint(rate, (outputSampleCount-1), bInterpolated_pitch) ) <= samples_loaded );
  609. int saveIndex = MIX_GetCurrentPaintbufferIndex();
  610. for ( int i = 0 ; i < g_paintBuffers.Count(); i++ )
  611. {
  612. if ( g_paintBuffers[i].factive )
  613. {
  614. // mix channel into all active paintbuffers
  615. MIX_SetCurrentPaintbuffer( i );
  616. Mix(
  617. pDevice, // Device.
  618. pChannel, // Channel.
  619. pData, // Input buffer.
  620. outputOffset, // Output position.
  621. FIX_FLOAT( sampleFraction ), // Iterators.
  622. FIX_FLOAT( rate ),
  623. outputSampleCount,
  624. 0 );
  625. }
  626. }
  627. MIX_SetCurrentPaintbuffer( saveIndex );
  628. }
  629. if ( advanceSample )
  630. {
  631. // update sample index to point to the next sample to output
  632. // if we're not delaying
  633. // Use fixed point math to make sure we exactly match results of mix
  634. // iterators.
  635. m_fsample_index = fsample_index_prev + RoundToFixedPoint( rate, outputSampleCount, bInterpolated_pitch );
  636. }
  637. outputOffset += outputSampleCount;
  638. sampleCount -= outputSampleCount;
  639. }
  640. // Did we run out of samples? if so, mark finished
  641. if ( sampleCount > 0 )
  642. {
  643. m_finished = true;
  644. }
  645. // total number of samples mixed !!! at the output clock rate !!!
  646. return outputOffset - startingOffset;
  647. }
  648. bool CAudioMixerWave::ShouldContinueMixing( void )
  649. {
  650. return !m_finished;
  651. }
  652. float CAudioMixerWave::ModifyPitch( float pitch )
  653. {
  654. return pitch;
  655. }
  656. float CAudioMixerWave::GetVolumeScale( void )
  657. {
  658. return 1.0f;
  659. }