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.

801 lines
29 KiB

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