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.

521 lines
14 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. #define WIN32_LEAN_AND_MEAN
  9. #include <windows.h>
  10. #pragma warning( disable: 4201 )
  11. #include <mmsystem.h>
  12. #pragma warning( default: 4201 )
  13. #include <mmreg.h>
  14. #include "snd_wave_source.h"
  15. #include "snd_wave_mixer_adpcm.h"
  16. #include "snd_wave_mixer_private.h"
  17. #include "soundsystem.h"
  18. // NOTE: This has to be the last file included!
  19. #include "tier0/memdbgon.h"
  20. // max size of ADPCM block in bytes
  21. #define MAX_BLOCK_SIZE 4096
  22. //-----------------------------------------------------------------------------
  23. // Purpose: Mixer for ADPCM encoded audio
  24. //-----------------------------------------------------------------------------
  25. class CAudioMixerWaveADPCM : public CAudioMixerWave
  26. {
  27. public:
  28. CAudioMixerWaveADPCM( CWaveData *data );
  29. ~CAudioMixerWaveADPCM( void );
  30. virtual void Mix( IAudioDevice *pDevice, channel_t *pChannel, void *pData, int outputOffset, int inputOffset, fixedint fracRate, int outCount, int timecompress, bool forward = true );
  31. virtual int GetOutputData( void **pData, int samplePosition, int sampleCount, bool forward = true );
  32. virtual bool SetSamplePosition( int position, bool scrubbing = false );
  33. private:
  34. bool DecodeBlock( void );
  35. int NumChannels( void );
  36. void DecompressBlockMono( short *pOut, const char *pIn, int count );
  37. void DecompressBlockStereo( short *pOut, const char *pIn, int count );
  38. void SetCurrentBlock( int block );
  39. int GetCurrentBlock( void ) const;
  40. int GetBlockNumberForSample( int samplePosition );
  41. bool IsSampleInCurrentBlock( int samplePosition );
  42. int GetFirstSampleForBlock( int blocknum ) const;
  43. const ADPCMWAVEFORMAT *m_pFormat;
  44. const ADPCMCOEFSET *m_pCoefficients;
  45. short *m_pSamples;
  46. int m_sampleCount;
  47. int m_samplePosition;
  48. int m_blockSize;
  49. int m_offset;
  50. int m_currentBlock;
  51. };
  52. CAudioMixerWaveADPCM::CAudioMixerWaveADPCM( CWaveData *data ) : CAudioMixerWave( data )
  53. {
  54. m_currentBlock = -1;
  55. m_pSamples = NULL;
  56. m_sampleCount = 0;
  57. m_samplePosition = 0;
  58. m_offset = 0;
  59. m_pFormat = (const ADPCMWAVEFORMAT *)m_pData->Source().GetHeader();
  60. if ( m_pFormat )
  61. {
  62. m_pCoefficients = (ADPCMCOEFSET *)((char *)m_pFormat + sizeof(WAVEFORMATEX) + 4);
  63. // create the decode buffer
  64. m_pSamples = new short[m_pFormat->wSamplesPerBlock * m_pFormat->wfx.nChannels];
  65. // number of bytes for samples
  66. m_blockSize = ((m_pFormat->wSamplesPerBlock - 2) * m_pFormat->wfx.nChannels ) / 2;
  67. // size of channel header
  68. m_blockSize += 7 * m_pFormat->wfx.nChannels;
  69. // Assert(m_blockSize < MAX_BLOCK_SIZE);
  70. }
  71. }
  72. CAudioMixerWaveADPCM::~CAudioMixerWaveADPCM( void )
  73. {
  74. delete[] m_pSamples;
  75. }
  76. int CAudioMixerWaveADPCM::NumChannels( void )
  77. {
  78. if ( m_pFormat )
  79. {
  80. return m_pFormat->wfx.nChannels;
  81. }
  82. return 0;
  83. }
  84. void CAudioMixerWaveADPCM::Mix( IAudioDevice *pDevice, channel_t *pChannel, void *pData, int outputOffset, int inputOffset, fixedint fracRate, int outCount, int timecompress, bool forward /*= true*/ )
  85. {
  86. if ( NumChannels() == 1 )
  87. pDevice->Mix16Mono( pChannel, (short *)pData, outputOffset, inputOffset, fracRate, outCount, timecompress, forward );
  88. else
  89. pDevice->Mix16Stereo( pChannel, (short *)pData, outputOffset, inputOffset, fracRate, outCount, timecompress, forward );
  90. }
  91. static int error_sign_lut[] = { 0, 1, 2, 3, 4, 5, 6, 7, -8, -7, -6, -5, -4, -3, -2, -1 };
  92. static int error_coefficients_lut[] = { 230, 230, 230, 230, 307, 409, 512, 614,
  93. 768, 614, 512, 409, 307, 230, 230, 230 };
  94. //-----------------------------------------------------------------------------
  95. // Purpose: ADPCM decompress a single block of 1-channel audio
  96. // Input : *pOut - output buffer 16-bit
  97. // *pIn - input block
  98. // count - number of samples to decode (to support partial blocks)
  99. //-----------------------------------------------------------------------------
  100. void CAudioMixerWaveADPCM::DecompressBlockMono( short *pOut, const char *pIn, int count )
  101. {
  102. int pred = *pIn++;
  103. int co1 = m_pCoefficients[pred].iCoef1;
  104. int co2 = m_pCoefficients[pred].iCoef2;
  105. // read initial delta
  106. int delta = *((short *)pIn);
  107. pIn += 2;
  108. // read initial samples for prediction
  109. int samp1 = *((short *)pIn);
  110. pIn += 2;
  111. int samp2 = *((short *)pIn);
  112. pIn += 2;
  113. // write out the initial samples (stored in reverse order)
  114. *pOut++ = (short)samp2;
  115. *pOut++ = (short)samp1;
  116. // subtract the 2 samples in the header
  117. count -= 2;
  118. // this is a toggle to read nibbles, first nibble is high
  119. int high = 1;
  120. int error = 0, sample = 0;
  121. // now process the block
  122. while ( count )
  123. {
  124. // read the error nibble from the input stream
  125. if ( high )
  126. {
  127. sample = (unsigned char) (*pIn++);
  128. // high nibble
  129. error = sample >> 4;
  130. // cache low nibble for next read
  131. sample = sample & 0xf;
  132. // Next read is from cache, not stream
  133. high = 0;
  134. }
  135. else
  136. {
  137. // stored in previous read (low nibble)
  138. error = sample;
  139. // next read is from stream
  140. high = 1;
  141. }
  142. // convert to signed with LUT
  143. int errorSign = error_sign_lut[error];
  144. // interpolate the new sample
  145. int predSample = (samp1 * co1) + (samp2 * co2);
  146. // coefficients are fixed point 8-bit, so shift back to 16-bit integer
  147. predSample >>= 8;
  148. // Add in current error estimate
  149. predSample += (errorSign * delta);
  150. // Correct error estimate
  151. delta = (delta * error_coefficients_lut[error]) >> 8;
  152. // Clamp error estimate
  153. if ( delta < 16 )
  154. delta = 16;
  155. // clamp
  156. if ( predSample > 32767L )
  157. predSample = 32767L;
  158. else if ( predSample < -32768L )
  159. predSample = -32768L;
  160. // output
  161. *pOut++ = (short)predSample;
  162. // move samples over
  163. samp2 = samp1;
  164. samp1 = predSample;
  165. count--;
  166. }
  167. }
  168. //-----------------------------------------------------------------------------
  169. // Purpose: Decode a single block of stereo ADPCM audio
  170. // Input : *pOut - 16-bit output buffer
  171. // *pIn - ADPCM encoded block data
  172. // count - number of sample pairs to decode
  173. //-----------------------------------------------------------------------------
  174. void CAudioMixerWaveADPCM::DecompressBlockStereo( short *pOut, const char *pIn, int count )
  175. {
  176. int pred[2], co1[2], co2[2];
  177. int i;
  178. for ( i = 0; i < 2; i++ )
  179. {
  180. pred[i] = *pIn++;
  181. co1[i] = m_pCoefficients[pred[i]].iCoef1;
  182. co2[i] = m_pCoefficients[pred[i]].iCoef2;
  183. }
  184. int delta[2], samp1[2], samp2[2];
  185. for ( i = 0; i < 2; i++, pIn += 2 )
  186. {
  187. // read initial delta
  188. delta[i] = *((short *)pIn);
  189. }
  190. // read initial samples for prediction
  191. for ( i = 0; i < 2; i++, pIn += 2 )
  192. {
  193. samp1[i] = *((short *)pIn);
  194. }
  195. for ( i = 0; i < 2; i++, pIn += 2 )
  196. {
  197. samp2[i] = *((short *)pIn);
  198. }
  199. // write out the initial samples (stored in reverse order)
  200. *pOut++ = (short)samp2[0]; // left
  201. *pOut++ = (short)samp2[1]; // right
  202. *pOut++ = (short)samp1[0]; // left
  203. *pOut++ = (short)samp1[1]; // right
  204. // subtract the 2 samples in the header
  205. count -= 2;
  206. // this is a toggle to read nibbles, first nibble is high
  207. int high = 1;
  208. int error, sample = 0;
  209. // now process the block
  210. while ( count )
  211. {
  212. for ( i = 0; i < 2; i++ )
  213. {
  214. // read the error nibble from the input stream
  215. if ( high )
  216. {
  217. sample = (unsigned char) (*pIn++);
  218. // high nibble
  219. error = sample >> 4;
  220. // cache low nibble for next read
  221. sample = sample & 0xf;
  222. // Next read is from cache, not stream
  223. high = 0;
  224. }
  225. else
  226. {
  227. // stored in previous read (low nibble)
  228. error = sample;
  229. // next read is from stream
  230. high = 1;
  231. }
  232. // convert to signed with LUT
  233. int errorSign = error_sign_lut[error];
  234. // interpolate the new sample
  235. int predSample = (samp1[i] * co1[i]) + (samp2[i] * co2[i]);
  236. // coefficients are fixed point 8-bit, so shift back to 16-bit integer
  237. predSample >>= 8;
  238. // Add in current error estimate
  239. predSample += (errorSign * delta[i]);
  240. // Correct error estimate
  241. delta[i] = (delta[i] * error_coefficients_lut[error]) >> 8;
  242. // Clamp error estimate
  243. if ( delta[i] < 16 )
  244. delta[i] = 16;
  245. // clamp
  246. if ( predSample > 32767L )
  247. predSample = 32767L;
  248. else if ( predSample < -32768L )
  249. predSample = -32768L;
  250. // output
  251. *pOut++ = (short)predSample;
  252. // move samples over
  253. samp2[i] = samp1[i];
  254. samp1[i] = predSample;
  255. }
  256. count--;
  257. }
  258. }
  259. bool CAudioMixerWaveADPCM::DecodeBlock( void )
  260. {
  261. char tmpBlock[MAX_BLOCK_SIZE];
  262. char *pData;
  263. int available = m_pData->ReadSourceData( (void **) (&pData), m_offset, m_blockSize );
  264. if ( available < m_blockSize )
  265. {
  266. int total = 0;
  267. while ( available && total < m_blockSize )
  268. {
  269. memcpy( tmpBlock + total, pData, available );
  270. total += available;
  271. available = m_pData->ReadSourceData( (void **) (&pData), m_offset + total, m_blockSize - total );
  272. }
  273. pData = tmpBlock;
  274. available = total;
  275. }
  276. Assert( m_blockSize > 0 );
  277. // Current block number is based on starting offset
  278. int blockNumber = m_offset / m_blockSize;
  279. SetCurrentBlock( blockNumber );
  280. if ( !available )
  281. {
  282. return false;
  283. }
  284. // advance the file pointer
  285. m_offset += available;
  286. int channelCount = NumChannels();
  287. // this is sample pairs for stereo, samples for mono
  288. m_sampleCount = m_pFormat->wSamplesPerBlock;
  289. // short block?, fixup sample count (2 samples per byte, divided by number of channels per sample set)
  290. m_sampleCount -= ((m_blockSize - available) * 2) / channelCount;
  291. // new block, start at the first sample
  292. m_samplePosition = 0;
  293. // no need to subclass for different channel counts...
  294. if ( channelCount == 1 )
  295. {
  296. DecompressBlockMono( m_pSamples, pData, m_sampleCount );
  297. }
  298. else
  299. {
  300. DecompressBlockStereo( m_pSamples, pData, m_sampleCount );
  301. }
  302. return true;
  303. }
  304. //-----------------------------------------------------------------------------
  305. // Purpose:
  306. // Input : block -
  307. //-----------------------------------------------------------------------------
  308. void CAudioMixerWaveADPCM::SetCurrentBlock( int block )
  309. {
  310. m_currentBlock = block;
  311. }
  312. //-----------------------------------------------------------------------------
  313. // Purpose:
  314. // Output : int
  315. //-----------------------------------------------------------------------------
  316. int CAudioMixerWaveADPCM::GetCurrentBlock( void ) const
  317. {
  318. return m_currentBlock;
  319. }
  320. //-----------------------------------------------------------------------------
  321. // Purpose:
  322. // Input : samplePosition -
  323. // Output : int
  324. //-----------------------------------------------------------------------------
  325. int CAudioMixerWaveADPCM::GetBlockNumberForSample( int samplePosition )
  326. {
  327. int blockNum = samplePosition / m_pFormat->wSamplesPerBlock;
  328. return blockNum;
  329. }
  330. //-----------------------------------------------------------------------------
  331. // Purpose:
  332. // Input : samplePosition -
  333. // Output : Returns true on success, false on failure.
  334. //-----------------------------------------------------------------------------
  335. bool CAudioMixerWaveADPCM::IsSampleInCurrentBlock( int samplePosition )
  336. {
  337. int currentBlock = GetCurrentBlock();
  338. int startSample = currentBlock * m_pFormat->wSamplesPerBlock;
  339. int endSample = startSample + m_pFormat->wSamplesPerBlock - 1;
  340. if ( samplePosition >= startSample &&
  341. samplePosition <= endSample )
  342. {
  343. return true;
  344. }
  345. return false;
  346. }
  347. //-----------------------------------------------------------------------------
  348. // Purpose:
  349. // Input : blocknum -
  350. // Output : int
  351. //-----------------------------------------------------------------------------
  352. int CAudioMixerWaveADPCM::GetFirstSampleForBlock( int blocknum ) const
  353. {
  354. return m_pFormat->wSamplesPerBlock * blocknum;
  355. }
  356. //-----------------------------------------------------------------------------
  357. // Purpose: Read existing buffer or decompress a new block when necessary
  358. // Input : **pData - output data pointer
  359. // sampleCount - number of samples (or pairs)
  360. // Output : int - available samples (zero to stop decoding)
  361. //-----------------------------------------------------------------------------
  362. int CAudioMixerWaveADPCM::GetOutputData( void **pData, int samplePosition, int sampleCount, bool forward /*= true*/ )
  363. {
  364. int requestedBlock = GetBlockNumberForSample( samplePosition );
  365. if ( requestedBlock != GetCurrentBlock() )
  366. {
  367. // Ran out of data!!!
  368. if ( !SetSamplePosition( samplePosition ) )
  369. return 0;
  370. }
  371. Assert( requestedBlock == GetCurrentBlock() );
  372. if ( m_samplePosition >= m_sampleCount )
  373. {
  374. if ( !DecodeBlock() )
  375. return 0;
  376. }
  377. if ( m_samplePosition < m_sampleCount )
  378. {
  379. *pData = (void *)(m_pSamples + m_samplePosition * NumChannels());
  380. int available = m_sampleCount - m_samplePosition;
  381. if ( available > sampleCount )
  382. available = sampleCount;
  383. m_samplePosition += available;
  384. return available;
  385. }
  386. return 0;
  387. }
  388. //-----------------------------------------------------------------------------
  389. // Purpose:
  390. // Input : position -
  391. //-----------------------------------------------------------------------------
  392. bool CAudioMixerWaveADPCM::SetSamplePosition( int position, bool scrubbing )
  393. {
  394. position = max( 0, position );
  395. CAudioMixerWave::SetSamplePosition( position, scrubbing );
  396. int requestedBlock = GetBlockNumberForSample( position );
  397. int firstSample = GetFirstSampleForBlock( requestedBlock );
  398. if ( firstSample >= m_pData->Source().SampleCount() )
  399. {
  400. // Read past end of file!!!
  401. return false;
  402. }
  403. int currentSample = ( position - firstSample );
  404. if ( requestedBlock != GetCurrentBlock() )
  405. {
  406. // Rewind file to beginning of block
  407. m_offset = requestedBlock * m_blockSize;
  408. if ( !DecodeBlock() )
  409. {
  410. return false;
  411. }
  412. }
  413. m_samplePosition = currentSample;
  414. return true;
  415. }
  416. //-----------------------------------------------------------------------------
  417. // Purpose: Abstract factory function for ADPCM mixers
  418. // Input : *data - wave data access object
  419. // channels -
  420. // Output : CAudioMixer
  421. //-----------------------------------------------------------------------------
  422. CAudioMixer *CreateADPCMMixer( CWaveData *data )
  423. {
  424. return new CAudioMixerWaveADPCM( data );
  425. }