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.

1531 lines
41 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. /***************************************************************************
  3. *
  4. * Copyright (C) 2001 Microsoft Corporation. All Rights Reserved.
  5. *
  6. * File: imaadpcm.cpp
  7. * Content: IMA ADPCM CODEC.
  8. * History:
  9. * Date By Reason
  10. * ==== == ======
  11. * 04/29/01 dereks Created.
  12. * 06/12/01 jharding Adapted for command-line encode
  13. *
  14. ****************************************************************************/
  15. #include <stdio.h>
  16. #include <wtypes.h>
  17. #include <assert.h>
  18. #include "imaadpcm.h"
  19. // 1/2 the range of the searchable step indices
  20. // for a particular block when optimizing on a
  21. // per-block basis. Widening or narrowing this
  22. // range may produce better/worse encodings.
  23. // Experimentation may be necessary. Higher values
  24. // cause each block to be encoded better, but may
  25. // produce popping in particularly fast attacks across
  26. // blocks, while smaller values limit the number
  27. // of encodings you consider
  28. #define STEPINDEXSEARCHRANGE (24)
  29. /****************************************************************************
  30. *
  31. * CImaAdpcmCodec
  32. *
  33. * Description:
  34. * Object constructor.
  35. *
  36. * Arguments:
  37. * (void)
  38. *
  39. * Returns:
  40. * (void)
  41. *
  42. ****************************************************************************/
  43. //
  44. // This array is used by NextStepIndex to determine the next step index to use.
  45. // The step index is an index to the m_asStep[] array, below.
  46. //
  47. const short CImaAdpcmCodec::m_asNextStep[16] =
  48. {
  49. -1, -1, -1, -1, 2, 4, 6, 8,
  50. -1, -1, -1, -1, 2, 4, 6, 8
  51. };
  52. //
  53. // This array contains the array of step sizes used to encode the ADPCM
  54. // samples. The step index in each ADPCM block is an index to this array.
  55. //
  56. const short CImaAdpcmCodec::m_asStep[89] =
  57. {
  58. 7, 8, 9, 10, 11, 12, 13,
  59. 14, 16, 17, 19, 21, 23, 25,
  60. 28, 31, 34, 37, 41, 45, 50,
  61. 55, 60, 66, 73, 80, 88, 97,
  62. 107, 118, 130, 143, 157, 173, 190,
  63. 209, 230, 253, 279, 307, 337, 371,
  64. 408, 449, 494, 544, 598, 658, 724,
  65. 796, 876, 963, 1060, 1166, 1282, 1411,
  66. 1552, 1707, 1878, 2066, 2272, 2499, 2749,
  67. 3024, 3327, 3660, 4026, 4428, 4871, 5358,
  68. 5894, 6484, 7132, 7845, 8630, 9493, 10442,
  69. 11487, 12635, 13899, 15289, 16818, 18500, 20350,
  70. 22385, 24623, 27086, 29794, 32767
  71. };
  72. CImaAdpcmCodec::CImaAdpcmCodec
  73. (
  74. void
  75. )
  76. {
  77. }
  78. /****************************************************************************
  79. *
  80. * ~CImaAdpcmCodec
  81. *
  82. * Description:
  83. * Object destructor.
  84. *
  85. * Arguments:
  86. * (void)
  87. *
  88. * Returns:
  89. * (void)
  90. *
  91. ****************************************************************************/
  92. CImaAdpcmCodec::~CImaAdpcmCodec
  93. (
  94. void
  95. )
  96. {
  97. }
  98. /****************************************************************************
  99. *
  100. * Initialize
  101. *
  102. * Description:
  103. * Initializes the object.
  104. *
  105. * Arguments:
  106. * LPCIMAADPCMWAVEFORMAT [in]: encoded data format.
  107. * BOOL [in]: TRUE to initialize the object as an encoder.
  108. *
  109. * Returns:
  110. * BOOL: TRUE on success.
  111. *
  112. ****************************************************************************/
  113. BOOL
  114. CImaAdpcmCodec::Initialize
  115. (
  116. LPCIMAADPCMWAVEFORMAT pwfxEncode,
  117. CODEC_MODE cmCodecMode
  118. )
  119. {
  120. static const LPFNIMAADPCMCONVERT apfnConvert[2][2] =
  121. {
  122. {
  123. DecodeM16,
  124. DecodeS16
  125. },
  126. {
  127. EncodeM16,
  128. EncodeS16
  129. }
  130. };
  131. if(!IsValidImaAdpcmFormat(pwfxEncode))
  132. {
  133. return FALSE;
  134. }
  135. //
  136. // Save the format data
  137. //
  138. m_wfxEncode = *pwfxEncode;
  139. m_cmCodecMode = cmCodecMode;
  140. //
  141. // Set up the conversion function
  142. //
  143. m_pfnConvert = apfnConvert[!(m_cmCodecMode == CODEC_MODE_DECODE)][m_wfxEncode.wfx.nChannels - 1];
  144. //
  145. // Initialize the stepping indices
  146. //
  147. m_nStepIndexL = m_nStepIndexR = 0;
  148. return TRUE;
  149. }
  150. /****************************************************************************
  151. *
  152. * Convert
  153. *
  154. * Description:
  155. * Converts data from the source to destination format.
  156. *
  157. * Arguments:
  158. * LPCVOID [in]: source buffer.
  159. * LPVOID [out]: destination buffer.
  160. * UINT [in]: block count.
  161. *
  162. * Returns:
  163. * BOOL: TRUE on success.
  164. *
  165. ****************************************************************************/
  166. BOOL
  167. CImaAdpcmCodec::Convert
  168. (
  169. LPCVOID pvSrc,
  170. LPVOID pvDst,
  171. UINT cBlocks
  172. )
  173. {
  174. // Array of decoders
  175. static const LPFNIMAADPCMCONVERT apfnDecoders[2] =
  176. {
  177. DecodeM16,
  178. DecodeS16
  179. };
  180. // Both destination and source block sizes
  181. DWORD dwSrcBlockSize = m_wfxEncode.wfx.nChannels * m_wfxEncode.wSamplesPerBlock * sizeof(short);
  182. DWORD dwDstBlockSize = m_wfxEncode.wfx.nBlockAlign;
  183. // Zero out the output
  184. ZeroMemory( pvDst, cBlocks * dwDstBlockSize );
  185. switch( m_cmCodecMode )
  186. {
  187. case CODEC_MODE_DECODE:
  188. // If we are decoding, just do it
  189. return m_pfnConvert( (LPBYTE)pvSrc, (LPBYTE)pvDst, cBlocks, m_wfxEncode.wfx.nBlockAlign, m_wfxEncode.wSamplesPerBlock, &m_nStepIndexL, &m_nStepIndexR );
  190. case CODEC_MODE_ENCODE_NORMAL:
  191. // Normal encode
  192. // We have some output right now, so this becomes a separate case.
  193. // Otherwise, it would be the same as CODEC_MODE_DECODE
  194. {
  195. printf("Using normal encoding...\n");
  196. // Allocate temporary buffers
  197. LPBYTE pvDecoded = new BYTE[cBlocks * dwSrcBlockSize];
  198. if( !pvDecoded )
  199. return FALSE;
  200. // Find the decoder
  201. LPFNIMAADPCMCONVERT pfnOppConvert;
  202. pfnOppConvert = apfnDecoders[m_wfxEncode.wfx.nChannels - 1];
  203. // Encode the stream
  204. if( !m_pfnConvert( (LPBYTE)pvSrc, (LPBYTE)pvDst, cBlocks, m_wfxEncode.wfx.nBlockAlign, m_wfxEncode.wSamplesPerBlock, &m_nStepIndexL, &m_nStepIndexR ) )
  205. {
  206. delete[] pvDecoded;
  207. return FALSE;
  208. }
  209. // Decode it back
  210. if( !pfnOppConvert( (LPBYTE)pvDst, pvDecoded, cBlocks, m_wfxEncode.wfx.nBlockAlign, XBOX_ADPCM_SAMPLES_PER_BLOCK, &m_nStepIndexL, &m_nStepIndexR ) )
  211. {
  212. delete[] pvDecoded;
  213. return FALSE;
  214. }
  215. // Report the normal difference
  216. printf( "Difference between original and decoded streams: 0x%I64x\n",
  217. CalcDifference( (LPBYTE)pvSrc, pvDecoded, cBlocks, cBlocks, dwSrcBlockSize ) );
  218. delete[] pvDecoded;
  219. }
  220. break;
  221. case CODEC_MODE_ENCODE_OPTIMIZE_WHOLE_FILE:
  222. // Optimize whole file encode
  223. // Encode the file with each possible starting step index
  224. // and pick the best one
  225. {
  226. printf("Using whole file encoding...\n");
  227. // Allocate temporary buffers
  228. LPBYTE pvTempDst = new BYTE[cBlocks * dwDstBlockSize];
  229. if(!pvTempDst)
  230. return FALSE;
  231. LPBYTE pvDecoded = new BYTE[cBlocks * dwSrcBlockSize];
  232. if(!pvDecoded)
  233. {
  234. delete[] pvTempDst;
  235. return FALSE;
  236. }
  237. // Find the decoder
  238. LPFNIMAADPCMCONVERT pfnOppConvert;
  239. pfnOppConvert = apfnDecoders[m_wfxEncode.wfx.nChannels - 1];
  240. // Keep track of the best encoding, as well as the chosen step index
  241. ULONGLONG ullLeastDiff = (ULONGLONG)-1;
  242. UINT uChosen = (UINT)-1;
  243. // Encode the entire stream with each step index and choose the best one
  244. for( UINT i = 0; i < ARRAYSIZE(m_asStep); ++i )
  245. {
  246. ZeroMemory( pvTempDst, cBlocks * dwDstBlockSize );
  247. ZeroMemory( pvDecoded, cBlocks * dwSrcBlockSize );
  248. // Encode
  249. m_nStepIndexL = m_nStepIndexR = i;
  250. if( !m_pfnConvert( (LPBYTE)pvSrc, pvTempDst, cBlocks, m_wfxEncode.wfx.nBlockAlign, m_wfxEncode.wSamplesPerBlock, &m_nStepIndexL, &m_nStepIndexR ) )
  251. continue;
  252. // Decode
  253. if( !pfnOppConvert( pvTempDst, pvDecoded, cBlocks, m_wfxEncode.wfx.nBlockAlign, XBOX_ADPCM_SAMPLES_PER_BLOCK, &m_nStepIndexL, &m_nStepIndexR ) )
  254. continue;
  255. // Diff
  256. ULONGLONG ullDiff = CalcDifference( (LPBYTE)pvSrc, pvDecoded, cBlocks, cBlocks, dwSrcBlockSize );
  257. if( ullDiff < ullLeastDiff )
  258. {
  259. ullLeastDiff = ullDiff;
  260. uChosen = i;
  261. CopyMemory( (LPBYTE)pvDst, pvTempDst, cBlocks * dwDstBlockSize );
  262. }
  263. }
  264. // Report the optimized difference
  265. printf( "Difference between original and decoded streams: 0x%I64x\n", ullLeastDiff );
  266. printf( "Step index chosen: %d\n", uChosen );
  267. delete[] pvTempDst;
  268. delete[] pvDecoded;
  269. }
  270. break;
  271. case CODEC_MODE_ENCODE_OPTIMIZE_EACH_BLOCK:
  272. // Optimize per block encode
  273. // Encode each block within the file with each
  274. // possible starting step index and pick the
  275. // best one for each block
  276. {
  277. printf("Using per-block encoding\n\n");
  278. // Allocate temporary buffers
  279. LPBYTE pvTempDst = new BYTE[dwDstBlockSize];
  280. if( !pvTempDst )
  281. return FALSE;
  282. LPBYTE pvDecoded = new BYTE[dwSrcBlockSize];
  283. if( !pvDecoded )
  284. {
  285. delete[] pvTempDst;
  286. return FALSE;
  287. }
  288. // Find the decoder
  289. LPFNIMAADPCMCONVERT pfnOppConvert;
  290. pfnOppConvert = apfnDecoders[m_wfxEncode.wfx.nChannels - 1];
  291. // We keep track of the best step index of the previous block
  292. // This enables us to search a small range of values close to
  293. // this value (the size of 2*STEPINDEXSEARCHRANGE)
  294. // To begin, the previous block's best step index was -1.
  295. INT iPreviousBestStepIndex = -1;
  296. for( UINT c = 0; c < cBlocks; ++c )
  297. {
  298. ULONGLONG ullLeastDiff = (ULONGLONG)-1;
  299. INT iThisBestStepIndex = -1;
  300. INT iStartIndex, iStopIndex;
  301. // Setup the start/stop indices properly
  302. if( iPreviousBestStepIndex == -1 )
  303. {
  304. // If the previous best step index is -1,
  305. // then we haven't yet encoded a block. Search
  306. // through the entire range of step indices,
  307. // rather than just in a limited range
  308. iStartIndex = 0;
  309. iStopIndex = ARRAYSIZE( m_asStep );
  310. }
  311. else
  312. {
  313. // Keep the range of indices to search limited
  314. // to around the previously chosen step index
  315. iStartIndex = iPreviousBestStepIndex - STEPINDEXSEARCHRANGE;
  316. iStopIndex = iPreviousBestStepIndex + STEPINDEXSEARCHRANGE + 1;
  317. }
  318. // Try each step index in the searchable range and choose the best one
  319. // for this block
  320. for( INT i = iStartIndex; i < iStopIndex; ++i )
  321. {
  322. // Don't consider anything out of range
  323. if( i < 0 || i >= ARRAYSIZE( m_asStep ) )
  324. continue;
  325. // Zero out the temporary buffers
  326. ZeroMemory( pvTempDst, dwDstBlockSize );
  327. ZeroMemory( pvDecoded, dwSrcBlockSize );
  328. // Encode
  329. m_nStepIndexL = m_nStepIndexR = i;
  330. if( !m_pfnConvert( (LPBYTE)pvSrc + c*dwSrcBlockSize, pvTempDst, 1, m_wfxEncode.wfx.nBlockAlign, m_wfxEncode.wSamplesPerBlock, &m_nStepIndexL, &m_nStepIndexR ) )
  331. continue;
  332. // Decode
  333. if( !pfnOppConvert( pvTempDst, pvDecoded, 1, m_wfxEncode.wfx.nBlockAlign, XBOX_ADPCM_SAMPLES_PER_BLOCK, &m_nStepIndexL, &m_nStepIndexR ) )
  334. continue;
  335. // Diff
  336. ULONGLONG ullDiff = CalcDifference( (LPBYTE)pvSrc + c*dwSrcBlockSize, pvDecoded, 1, cBlocks, dwSrcBlockSize );
  337. if( ullDiff < ullLeastDiff )
  338. {
  339. ullLeastDiff = ullDiff;
  340. iThisBestStepIndex = i;
  341. CopyMemory( (LPBYTE)pvDst + c*dwDstBlockSize, (LPBYTE)pvTempDst, dwDstBlockSize );
  342. }
  343. }
  344. // Save the best step index for this block
  345. iPreviousBestStepIndex = iThisBestStepIndex;
  346. }
  347. delete[] pvTempDst;
  348. delete[] pvDecoded;
  349. // Report on the optimized difference
  350. pvDecoded = new BYTE[cBlocks * dwSrcBlockSize];
  351. pfnOppConvert( (LPBYTE)pvDst, pvDecoded, cBlocks, m_wfxEncode.wfx.nBlockAlign, XBOX_ADPCM_SAMPLES_PER_BLOCK, &m_nStepIndexL, &m_nStepIndexR );
  352. printf( "Difference between original and decoded streams: 0x%I64x\n", CalcDifference( (LPBYTE)pvSrc, pvDecoded, cBlocks, cBlocks, dwSrcBlockSize ) );
  353. delete[] pvDecoded;
  354. }
  355. break;
  356. }
  357. return TRUE;
  358. }
  359. /****************************************************************************
  360. *
  361. * Reset
  362. *
  363. * Description:
  364. * Resets the conversion operation.
  365. *
  366. * Arguments:
  367. * (void)
  368. *
  369. * Returns:
  370. * (void)
  371. *
  372. ****************************************************************************/
  373. void
  374. CImaAdpcmCodec::Reset
  375. (
  376. void
  377. )
  378. {
  379. //
  380. // Reset the stepping indices
  381. //
  382. m_nStepIndexL = m_nStepIndexR = 0;
  383. }
  384. /****************************************************************************
  385. *
  386. * GetEncodeAlignment
  387. *
  388. * Description:
  389. * Gets the alignment of an encoded buffer.
  390. *
  391. * Arguments:
  392. * (void)
  393. *
  394. * Returns:
  395. * WORD: alignment, in bytes.
  396. *
  397. ****************************************************************************/
  398. WORD
  399. CImaAdpcmCodec::GetEncodeAlignment
  400. (
  401. void
  402. )
  403. {
  404. return m_wfxEncode.wfx.nBlockAlign;
  405. }
  406. /****************************************************************************
  407. *
  408. * GetDecodeAlignment
  409. *
  410. * Description:
  411. * Gets the alignment of a decoded buffer.
  412. *
  413. * Arguments:
  414. * (void)
  415. *
  416. * Returns:
  417. * DWORD: alignment, in bytes.
  418. *
  419. ****************************************************************************/
  420. WORD
  421. CImaAdpcmCodec::GetDecodeAlignment
  422. (
  423. void
  424. )
  425. {
  426. return m_wfxEncode.wSamplesPerBlock * m_wfxEncode.wfx.nChannels * IMAADPCM_PCM_BITS_PER_SAMPLE / 8;
  427. }
  428. /****************************************************************************
  429. *
  430. * CalculateEncodeAlignment
  431. *
  432. * Description:
  433. * Calculates an encoded data block alignment based on a PCM sample
  434. * count and an alignment multiplier.
  435. *
  436. * Arguments:
  437. * WORD [in]: channel count.
  438. * WORD [in]: PCM samples per block.
  439. *
  440. * Returns:
  441. * WORD: alignment, in bytes.
  442. *
  443. ****************************************************************************/
  444. WORD
  445. CImaAdpcmCodec::CalculateEncodeAlignment
  446. (
  447. WORD nChannels,
  448. WORD nSamplesPerBlock
  449. )
  450. {
  451. const WORD nEncodedSampleBits = nChannels * IMAADPCM_BITS_PER_SAMPLE;
  452. const WORD nHeaderBytes = nChannels * IMAADPCM_HEADER_LENGTH;
  453. INT nBlockAlign;
  454. //
  455. // Calculate the raw block alignment that nSamplesPerBlock dictates. This
  456. // value may include a partial encoded sample, so be sure to round up.
  457. //
  458. // Start with the samples-per-block, minus 1. The first sample is actually
  459. // stored in the header.
  460. //
  461. nBlockAlign = nSamplesPerBlock - 1;
  462. //
  463. // Convert to encoded sample size
  464. //
  465. nBlockAlign *= nEncodedSampleBits;
  466. nBlockAlign += 7;
  467. nBlockAlign /= 8;
  468. //
  469. // The stereo encoder requires that there be at least two DWORDs to process
  470. //
  471. nBlockAlign += 7;
  472. nBlockAlign /= 8;
  473. nBlockAlign *= 8;
  474. //
  475. // Add the header
  476. //
  477. nBlockAlign += nHeaderBytes;
  478. // We used an INT temporarily, but the final result should fit into a WORD
  479. assert( nBlockAlign < 0xFFFF );
  480. return (WORD)nBlockAlign;
  481. }
  482. /****************************************************************************
  483. *
  484. * CreatePcmFormat
  485. *
  486. * Description:
  487. * Creates a PCM format descriptor.
  488. *
  489. * Arguments:
  490. * WORD [in]: channel count.
  491. * DWORD [in]: sampling rate.
  492. * LPWAVEFORMATEX [out]: format descriptor.
  493. *
  494. * Returns:
  495. * (void)
  496. *
  497. ****************************************************************************/
  498. void
  499. CImaAdpcmCodec::CreatePcmFormat
  500. (
  501. WORD nChannels,
  502. DWORD nSamplesPerSec,
  503. LPWAVEFORMATEX pwfx
  504. )
  505. {
  506. pwfx->wFormatTag = WAVE_FORMAT_PCM;
  507. pwfx->nChannels = nChannels;
  508. pwfx->nSamplesPerSec = nSamplesPerSec;
  509. pwfx->nBlockAlign = nChannels * IMAADPCM_PCM_BITS_PER_SAMPLE / 8;
  510. pwfx->nAvgBytesPerSec = pwfx->nBlockAlign * pwfx->nSamplesPerSec;
  511. pwfx->wBitsPerSample = IMAADPCM_PCM_BITS_PER_SAMPLE;
  512. }
  513. /****************************************************************************
  514. *
  515. * CreateImaAdpcmFormat
  516. *
  517. * Description:
  518. * Creates an IMA ADPCM format descriptor.
  519. *
  520. * Arguments:
  521. * WORD [in]: channel count.
  522. * DWORD [in]: sampling rate.
  523. * LPIMAADPCMWAVEFORMAT [out]: format descriptor.
  524. *
  525. * Returns:
  526. * (void)
  527. *
  528. ****************************************************************************/
  529. void
  530. CImaAdpcmCodec::CreateImaAdpcmFormat
  531. (
  532. WORD nChannels,
  533. DWORD nSamplesPerSec,
  534. WORD nSamplesPerBlock,
  535. LPIMAADPCMWAVEFORMAT pwfx
  536. )
  537. {
  538. pwfx->wfx.wFormatTag = WAVE_FORMAT_XBOX_ADPCM;
  539. pwfx->wfx.nChannels = nChannels;
  540. pwfx->wfx.nSamplesPerSec = nSamplesPerSec;
  541. pwfx->wfx.nBlockAlign = CalculateEncodeAlignment(nChannels, nSamplesPerBlock);
  542. pwfx->wfx.nAvgBytesPerSec = nSamplesPerSec * pwfx->wfx.nBlockAlign / nSamplesPerBlock;
  543. pwfx->wfx.wBitsPerSample = IMAADPCM_BITS_PER_SAMPLE;
  544. pwfx->wfx.cbSize = sizeof(*pwfx) - sizeof(pwfx->wfx);
  545. pwfx->wSamplesPerBlock = nSamplesPerBlock;
  546. }
  547. /****************************************************************************
  548. *
  549. * IsValidPcmFormat
  550. *
  551. * Description:
  552. * Validates a format structure.
  553. *
  554. * Arguments:
  555. * LPCWAVEFORMATEX [in]: format.
  556. *
  557. * Returns:
  558. * BOOL: TRUE on success.
  559. *
  560. ****************************************************************************/
  561. BOOL
  562. CImaAdpcmCodec::IsValidPcmFormat
  563. (
  564. LPCWAVEFORMATEX pwfx
  565. )
  566. {
  567. if(WAVE_FORMAT_PCM != pwfx->wFormatTag)
  568. {
  569. return FALSE;
  570. }
  571. if((pwfx->nChannels < 1) || (pwfx->nChannels > IMAADPCM_MAX_CHANNELS))
  572. {
  573. return FALSE;
  574. }
  575. if(IMAADPCM_PCM_BITS_PER_SAMPLE != pwfx->wBitsPerSample)
  576. {
  577. return FALSE;
  578. }
  579. if(pwfx->nChannels * pwfx->wBitsPerSample / 8 != pwfx->nBlockAlign)
  580. {
  581. return FALSE;
  582. }
  583. if(pwfx->nBlockAlign * pwfx->nSamplesPerSec != pwfx->nAvgBytesPerSec)
  584. {
  585. return FALSE;
  586. }
  587. return TRUE;
  588. }
  589. /****************************************************************************
  590. *
  591. * IsValidXboxAdpcmFormat
  592. *
  593. * Description:
  594. * Validates a format structure.
  595. *
  596. * Arguments:
  597. * LPCIMAADPCMWAVEFORMAT [in]: format.
  598. *
  599. * Returns:
  600. * BOOL: TRUE on success.
  601. *
  602. ****************************************************************************/
  603. BOOL
  604. CImaAdpcmCodec::IsValidImaAdpcmFormat
  605. (
  606. LPCIMAADPCMWAVEFORMAT pwfx
  607. )
  608. {
  609. if(WAVE_FORMAT_XBOX_ADPCM != pwfx->wfx.wFormatTag)
  610. {
  611. return FALSE;
  612. }
  613. if(sizeof(*pwfx) - sizeof(pwfx->wfx) != pwfx->wfx.cbSize)
  614. {
  615. return FALSE;
  616. }
  617. if((pwfx->wfx.nChannels < 1) || (pwfx->wfx.nChannels > IMAADPCM_MAX_CHANNELS))
  618. {
  619. return FALSE;
  620. }
  621. if(IMAADPCM_BITS_PER_SAMPLE != pwfx->wfx.wBitsPerSample)
  622. {
  623. return FALSE;
  624. }
  625. if(CalculateEncodeAlignment(pwfx->wfx.nChannels, pwfx->wSamplesPerBlock) != pwfx->wfx.nBlockAlign)
  626. {
  627. return FALSE;
  628. }
  629. return TRUE;
  630. }
  631. /****************************************************************************
  632. *
  633. * CalcDifference
  634. *
  635. * Description:
  636. * Calculates the error between two audio buffers. The error is clamped
  637. * at (ULONGLONG)-1. Also, the error of a block acts as a percentage of
  638. * the maximum possible contribution of a block.
  639. *
  640. * Arguments:
  641. * LPBYTE [in]: First buffer
  642. * LPBYTE [in]: Second buffer
  643. * UINT [in]: Number of blocks-worth to compare
  644. * UINT [in]: Total number of blocks being converted
  645. * DWORD [in]: Size of a single block in bytes
  646. *
  647. * Returns:
  648. * ULONGLONG: Difference of the two buffers
  649. *
  650. ****************************************************************************/
  651. ULONGLONG CImaAdpcmCodec::CalcDifference(LPBYTE pvBuffer1, LPBYTE pvBuffer2, UINT cBlocks, UINT cTotalBlocks, DWORD dwBlockSize)
  652. {
  653. ULONGLONG ullDiff = 0;
  654. // Each block worth of error can contribute a maximum of this value
  655. const ULONGLONG ullMaxBlockContribution = ( (ULONGLONG)-1 / cTotalBlocks );
  656. // The maximum error in a block is
  657. // (2^16)^2 * m_wfxEncode.wSamplesPerBlock
  658. // = ( 1 << 32 ) * m_wfxEncode.wSamplesPerBlock
  659. const ULONGLONG ullMaxBlockDiff = ( (ULONGLONG)1 << 32 ) * m_wfxEncode.wSamplesPerBlock;
  660. // Now we go through the buffers sample by sample and find the difference
  661. // on a block-by-block basis. The factored difference of a block is
  662. // ullBlockDiff / ullMaxBlockDiff * ullMaxBlockContribution
  663. for( UINT i = 0; i < cBlocks; ++i )
  664. {
  665. PSHORT pSamples1 = (PSHORT)(pvBuffer1 + i * dwBlockSize);
  666. PSHORT pSamples2 = (PSHORT)(pvBuffer2 + i * dwBlockSize);
  667. ULONGLONG ullBlockDiff = 0;
  668. // Find the block difference
  669. for( UINT j = 0; j < m_wfxEncode.wSamplesPerBlock; ++j )
  670. {
  671. ULONGLONG ullSampleDiff = (ULONGLONG)(pSamples2[j]) - (ULONGLONG)(pSamples1[j]);
  672. ullBlockDiff += ( ullSampleDiff * ullSampleDiff );
  673. }
  674. // Assert that we didn't go over the maximum possible
  675. assert( ullBlockDiff <= ullMaxBlockDiff );
  676. // Add the contribution of this block to the error
  677. ullDiff += (ULONGLONG)( ( (DOUBLE)ullBlockDiff / (DOUBLE)ullMaxBlockDiff ) * ullMaxBlockContribution );
  678. }
  679. assert( ullDiff <= cBlocks * ullMaxBlockContribution );
  680. return ullDiff;
  681. }
  682. /****************************************************************************
  683. *
  684. * EncodeSample
  685. *
  686. * Description:
  687. * Encodes a sample.
  688. *
  689. * Arguments:
  690. * int [in]: the sample to be encoded.
  691. * LPINT [in/out]: the predicted value of the sample.
  692. * int [in]: the quantization step size used to encode the sample.
  693. *
  694. * Returns:
  695. * int: the encoded ADPCM sample.
  696. *
  697. ****************************************************************************/
  698. int
  699. CImaAdpcmCodec::EncodeSample
  700. (
  701. int nInputSample,
  702. LPINT pnPredictedSample,
  703. int nStepSize
  704. )
  705. {
  706. int nPredictedSample;
  707. LONG lDifference;
  708. int nEncodedSample;
  709. nPredictedSample = *pnPredictedSample;
  710. lDifference = nInputSample - nPredictedSample;
  711. nEncodedSample = 0;
  712. if(lDifference < 0)
  713. {
  714. nEncodedSample = 8;
  715. lDifference = -lDifference;
  716. }
  717. if(lDifference >= nStepSize)
  718. {
  719. nEncodedSample |= 4;
  720. lDifference -= nStepSize;
  721. }
  722. nStepSize >>= 1;
  723. if(lDifference >= nStepSize)
  724. {
  725. nEncodedSample |= 2;
  726. lDifference -= nStepSize;
  727. }
  728. nStepSize >>= 1;
  729. if(lDifference >= nStepSize)
  730. {
  731. nEncodedSample |= 1;
  732. lDifference -= nStepSize;
  733. }
  734. if(nEncodedSample & 8)
  735. {
  736. nPredictedSample = nInputSample + lDifference - (nStepSize >> 1);
  737. }
  738. else
  739. {
  740. nPredictedSample = nInputSample - lDifference + (nStepSize >> 1);
  741. }
  742. if(nPredictedSample > 32767)
  743. {
  744. nPredictedSample = 32767;
  745. }
  746. else if(nPredictedSample < -32768)
  747. {
  748. nPredictedSample = -32768;
  749. }
  750. *pnPredictedSample = nPredictedSample;
  751. return nEncodedSample;
  752. }
  753. /****************************************************************************
  754. *
  755. * DecodeSample
  756. *
  757. * Description:
  758. * Decodes an encoded sample.
  759. *
  760. * Arguments:
  761. * int [in]: the sample to be decoded.
  762. * int [in]: the predicted value of the sample.
  763. * int [i]: the quantization step size used to encode the sample.
  764. *
  765. * Returns:
  766. * int: the decoded PCM sample.
  767. *
  768. ****************************************************************************/
  769. int
  770. CImaAdpcmCodec::DecodeSample
  771. (
  772. int nEncodedSample,
  773. int nPredictedSample,
  774. int nStepSize
  775. )
  776. {
  777. LONG lDifference;
  778. LONG lNewSample;
  779. lDifference = nStepSize >> 3;
  780. if(nEncodedSample & 4)
  781. {
  782. lDifference += nStepSize;
  783. }
  784. if(nEncodedSample & 2)
  785. {
  786. lDifference += nStepSize >> 1;
  787. }
  788. if(nEncodedSample & 1)
  789. {
  790. lDifference += nStepSize >> 2;
  791. }
  792. if(nEncodedSample & 8)
  793. {
  794. lDifference = -lDifference;
  795. }
  796. lNewSample = nPredictedSample + lDifference;
  797. if((LONG)(short)lNewSample != lNewSample)
  798. {
  799. if(lNewSample < -32768)
  800. {
  801. lNewSample = -32768;
  802. }
  803. else
  804. {
  805. lNewSample = 32767;
  806. }
  807. }
  808. return (int)lNewSample;
  809. }
  810. /****************************************************************************
  811. *
  812. * Conversion Routines
  813. *
  814. * Description:
  815. * Converts a PCM buffer to ADPCM, or the reverse.
  816. *
  817. * Arguments:
  818. * LPBYTE [in]: source buffer.
  819. * LPBYTE [out]: destination buffer.
  820. * UINT [in]: block count.
  821. * UINT [in]: block alignment of the ADPCM data, in bytes.
  822. * UINT [in]: the number of samples in each ADPCM block (not used in
  823. * decoding).
  824. * LPINT [in/out]: left-channel stepping index.
  825. * LPINT [in/out]: right-channel stepping index.
  826. *
  827. * Returns:
  828. * BOOL: TRUE on success.
  829. *
  830. ****************************************************************************/
  831. BOOL
  832. CImaAdpcmCodec::EncodeM16
  833. (
  834. LPBYTE pbSrc,
  835. LPBYTE pbDst,
  836. UINT cBlocks,
  837. UINT nBlockAlignment,
  838. UINT cSamplesPerBlock,
  839. LPINT pnStepIndexL,
  840. LPINT
  841. )
  842. {
  843. LPBYTE pbBlock;
  844. UINT cSamples;
  845. int nSample;
  846. int nStepSize;
  847. int nEncSample1;
  848. int nEncSample2;
  849. int nPredSample;
  850. int nStepIndex;
  851. //
  852. // Save a local copy of the step index so we're not constantly
  853. // dereferencing a pointer.
  854. //
  855. nStepIndex = *pnStepIndexL;
  856. //
  857. // Enter the main loop
  858. //
  859. while(cBlocks--)
  860. {
  861. pbBlock = pbDst;
  862. cSamples = cSamplesPerBlock - 1;
  863. //
  864. // Block header
  865. //
  866. nPredSample = *(short *)pbSrc;
  867. pbSrc += sizeof(short);
  868. *(LONG *)pbBlock = MAKELONG(nPredSample, nStepIndex);
  869. pbBlock += sizeof(LONG);
  870. //
  871. // We have written the header for this block--now write the data
  872. // chunk (which consists of a bunch of encoded nibbles). Note
  873. // that if we don't have enough data to fill a complete byte, then
  874. // we add a 0 nibble on the end.
  875. //
  876. while(cSamples)
  877. {
  878. //
  879. // Sample 1
  880. //
  881. nSample = *(short *)pbSrc;
  882. pbSrc += sizeof(short);
  883. cSamples--;
  884. nStepSize = m_asStep[nStepIndex];
  885. nEncSample1 = EncodeSample(nSample, &nPredSample, nStepSize);
  886. nStepIndex = NextStepIndex(nEncSample1, nStepIndex);
  887. //
  888. // Sample 2
  889. //
  890. if(cSamples)
  891. {
  892. nSample = *(short *)pbSrc;
  893. pbSrc += sizeof(short);
  894. cSamples--;
  895. nStepSize = m_asStep[nStepIndex];
  896. nEncSample2 = EncodeSample(nSample, &nPredSample, nStepSize);
  897. nStepIndex = NextStepIndex(nEncSample2, nStepIndex);
  898. }
  899. else
  900. {
  901. nEncSample2 = 0;
  902. }
  903. //
  904. // Write out encoded byte.
  905. //
  906. *pbBlock++ = (BYTE)(nEncSample1 | (nEncSample2 << 4));
  907. }
  908. //
  909. // Skip padding
  910. //
  911. pbDst += nBlockAlignment;
  912. }
  913. //
  914. // Restore the value of the step index to be used on the next buffer.
  915. //
  916. *pnStepIndexL = nStepIndex;
  917. return TRUE;
  918. }
  919. BOOL
  920. CImaAdpcmCodec::EncodeS16
  921. (
  922. LPBYTE pbSrc,
  923. LPBYTE pbDst,
  924. UINT cBlocks,
  925. UINT nBlockAlignment,
  926. UINT cSamplesPerBlock,
  927. LPINT pnStepIndexL,
  928. LPINT pnStepIndexR
  929. )
  930. {
  931. LPBYTE pbBlock;
  932. UINT cSamples;
  933. UINT cSubSamples;
  934. int nSample;
  935. int nStepSize;
  936. DWORD dwLeft;
  937. DWORD dwRight;
  938. int nEncSampleL;
  939. int nPredSampleL;
  940. int nStepIndexL;
  941. int nEncSampleR;
  942. int nPredSampleR;
  943. int nStepIndexR;
  944. UINT i;
  945. //
  946. // Save a local copy of the step indices so we're not constantly
  947. // dereferencing a pointer.
  948. //
  949. nStepIndexL = *pnStepIndexL;
  950. nStepIndexR = *pnStepIndexR;
  951. //
  952. // Enter the main loop
  953. //
  954. while(cBlocks--)
  955. {
  956. pbBlock = pbDst;
  957. cSamples = cSamplesPerBlock - 1;
  958. //
  959. // LEFT channel block header
  960. //
  961. nPredSampleL = *(short *)pbSrc;
  962. pbSrc += sizeof(short);
  963. *(LONG *)pbBlock = MAKELONG(nPredSampleL, nStepIndexL);
  964. pbBlock += sizeof(LONG);
  965. //
  966. // RIGHT channel block header
  967. //
  968. nPredSampleR = *(short *)pbSrc;
  969. pbSrc += sizeof(short);
  970. *(LONG *)pbBlock = MAKELONG(nPredSampleR, nStepIndexR);
  971. pbBlock += sizeof(LONG);
  972. //
  973. // We have written the header for this block--now write the data
  974. // chunk. This consists of 8 left samples (one DWORD of output)
  975. // followed by 8 right samples (also one DWORD). Since the input
  976. // samples are interleaved, we create the left and right DWORDs
  977. // sample by sample, and then write them both out.
  978. //
  979. while(cSamples)
  980. {
  981. dwLeft = 0;
  982. dwRight = 0;
  983. cSubSamples = min(cSamples, 8);
  984. for(i = 0; i < cSubSamples; i++)
  985. {
  986. //
  987. // LEFT channel
  988. //
  989. nSample = *(short *)pbSrc;
  990. pbSrc += sizeof(short);
  991. nStepSize = m_asStep[nStepIndexL];
  992. nEncSampleL = EncodeSample(nSample, &nPredSampleL, nStepSize);
  993. nStepIndexL = NextStepIndex(nEncSampleL, nStepIndexL);
  994. dwLeft |= (DWORD)nEncSampleL << (4 * i);
  995. //
  996. // RIGHT channel
  997. //
  998. nSample = *(short *)pbSrc;
  999. pbSrc += sizeof(short);
  1000. nStepSize = m_asStep[nStepIndexR];
  1001. nEncSampleR = EncodeSample(nSample, &nPredSampleR, nStepSize);
  1002. nStepIndexR = NextStepIndex(nEncSampleR, nStepIndexR);
  1003. dwRight |= (DWORD)nEncSampleR << (4 * i);
  1004. }
  1005. //
  1006. // Write out encoded DWORDs.
  1007. //
  1008. *(LPDWORD)pbBlock = dwLeft;
  1009. pbBlock += sizeof(DWORD);
  1010. *(LPDWORD)pbBlock = dwRight;
  1011. pbBlock += sizeof(DWORD);
  1012. cSamples -= cSubSamples;
  1013. }
  1014. //
  1015. // Skip padding
  1016. //
  1017. pbDst += nBlockAlignment;
  1018. }
  1019. //
  1020. // Restore the value of the step index to be used on the next buffer.
  1021. //
  1022. *pnStepIndexL = nStepIndexL;
  1023. *pnStepIndexR = nStepIndexR;
  1024. return TRUE;
  1025. }
  1026. BOOL
  1027. CImaAdpcmCodec::DecodeM16
  1028. (
  1029. LPBYTE pbSrc,
  1030. LPBYTE pbDst,
  1031. UINT cBlocks,
  1032. UINT nBlockAlignment,
  1033. UINT cSamplesPerBlock,
  1034. LPINT,
  1035. LPINT
  1036. )
  1037. {
  1038. BOOL fSuccess = TRUE;
  1039. LPBYTE pbBlock;
  1040. UINT cSamples;
  1041. BYTE bSample;
  1042. int nStepSize;
  1043. int nEncSample;
  1044. int nPredSample;
  1045. int nStepIndex;
  1046. DWORD dwHeader;
  1047. //
  1048. // Enter the main loop
  1049. //
  1050. while(cBlocks--)
  1051. {
  1052. pbBlock = pbSrc;
  1053. cSamples = cSamplesPerBlock - 1;
  1054. //
  1055. // Block header
  1056. //
  1057. dwHeader = *(LPDWORD)pbBlock;
  1058. pbBlock += sizeof(DWORD);
  1059. nPredSample = (int)(short)LOWORD(dwHeader);
  1060. nStepIndex = (int)(BYTE)HIWORD(dwHeader);
  1061. if(!ValidStepIndex(nStepIndex))
  1062. {
  1063. //
  1064. // The step index is out of range - this is considered a fatal
  1065. // error as the input stream is corrupted. We fail by returning
  1066. // zero bytes converted.
  1067. //
  1068. fSuccess = FALSE;
  1069. break;
  1070. }
  1071. //
  1072. // Write out first sample
  1073. //
  1074. *(short *)pbDst = (short)nPredSample;
  1075. pbDst += sizeof(short);
  1076. //
  1077. // Enter the block loop
  1078. //
  1079. while(cSamples)
  1080. {
  1081. bSample = *pbBlock++;
  1082. //
  1083. // Sample 1
  1084. //
  1085. nEncSample = (bSample & (BYTE)0x0F);
  1086. nStepSize = m_asStep[nStepIndex];
  1087. nPredSample = DecodeSample(nEncSample, nPredSample, nStepSize);
  1088. nStepIndex = NextStepIndex(nEncSample, nStepIndex);
  1089. *(short *)pbDst = (short)nPredSample;
  1090. pbDst += sizeof(short);
  1091. cSamples--;
  1092. //
  1093. // Sample 2
  1094. //
  1095. if(cSamples)
  1096. {
  1097. nEncSample = (bSample >> 4);
  1098. nStepSize = m_asStep[nStepIndex];
  1099. nPredSample = DecodeSample(nEncSample, nPredSample, nStepSize);
  1100. nStepIndex = NextStepIndex(nEncSample, nStepIndex);
  1101. *(short *)pbDst = (short)nPredSample;
  1102. pbDst += sizeof(short);
  1103. cSamples--;
  1104. }
  1105. }
  1106. //
  1107. // Skip padding
  1108. //
  1109. pbSrc += nBlockAlignment;
  1110. }
  1111. return fSuccess;
  1112. }
  1113. BOOL
  1114. CImaAdpcmCodec::DecodeS16
  1115. (
  1116. LPBYTE pbSrc,
  1117. LPBYTE pbDst,
  1118. UINT cBlocks,
  1119. UINT nBlockAlignment,
  1120. UINT cSamplesPerBlock,
  1121. LPINT,
  1122. LPINT
  1123. )
  1124. {
  1125. BOOL fSuccess = TRUE;
  1126. LPBYTE pbBlock;
  1127. UINT cSamples;
  1128. UINT cSubSamples;
  1129. int nStepSize;
  1130. DWORD dwHeader;
  1131. DWORD dwLeft;
  1132. DWORD dwRight;
  1133. int nEncSampleL;
  1134. int nPredSampleL;
  1135. int nStepIndexL;
  1136. int nEncSampleR;
  1137. int nPredSampleR;
  1138. int nStepIndexR;
  1139. UINT i;
  1140. //
  1141. // Enter the main loop
  1142. //
  1143. while(cBlocks--)
  1144. {
  1145. pbBlock = pbSrc;
  1146. cSamples = cSamplesPerBlock - 1;
  1147. //
  1148. // LEFT channel header
  1149. //
  1150. dwHeader = *(LPDWORD)pbBlock;
  1151. pbBlock += sizeof(DWORD);
  1152. nPredSampleL = (int)(short)LOWORD(dwHeader);
  1153. nStepIndexL = (int)(BYTE)HIWORD(dwHeader);
  1154. if(!ValidStepIndex(nStepIndexL))
  1155. {
  1156. //
  1157. // The step index is out of range - this is considered a fatal
  1158. // error as the input stream is corrupted. We fail by returning
  1159. // zero bytes converted.
  1160. //
  1161. fSuccess = FALSE;
  1162. break;
  1163. }
  1164. //
  1165. // RIGHT channel header
  1166. //
  1167. dwHeader = *(LPDWORD)pbBlock;
  1168. pbBlock += sizeof(DWORD);
  1169. nPredSampleR = (int)(short)LOWORD(dwHeader);
  1170. nStepIndexR = (int)(BYTE)HIWORD(dwHeader);
  1171. if(!ValidStepIndex(nStepIndexR))
  1172. {
  1173. //
  1174. // The step index is out of range - this is considered a fatal
  1175. // error as the input stream is corrupted. We fail by returning
  1176. // zero bytes converted.
  1177. //
  1178. fSuccess = FALSE;
  1179. break;
  1180. }
  1181. //
  1182. // Write out first sample
  1183. //
  1184. *(LPDWORD)pbDst = MAKELONG(nPredSampleL, nPredSampleR);
  1185. pbDst += sizeof(DWORD);
  1186. //
  1187. // The first DWORD contains 4 left samples, the second DWORD
  1188. // contains 4 right samples. We process the source in 8-byte
  1189. // chunks to make it easy to interleave the output correctly.
  1190. //
  1191. while(cSamples)
  1192. {
  1193. dwLeft = *(LPDWORD)pbBlock;
  1194. pbBlock += sizeof(DWORD);
  1195. dwRight = *(LPDWORD)pbBlock;
  1196. pbBlock += sizeof(DWORD);
  1197. cSubSamples = min(cSamples, 8);
  1198. for(i = 0; i < cSubSamples; i++)
  1199. {
  1200. //
  1201. // LEFT channel
  1202. //
  1203. nEncSampleL = (dwLeft & 0x0F);
  1204. nStepSize = m_asStep[nStepIndexL];
  1205. nPredSampleL = DecodeSample(nEncSampleL, nPredSampleL, nStepSize);
  1206. nStepIndexL = NextStepIndex(nEncSampleL, nStepIndexL);
  1207. //
  1208. // RIGHT channel
  1209. //
  1210. nEncSampleR = (dwRight & 0x0F);
  1211. nStepSize = m_asStep[nStepIndexR];
  1212. nPredSampleR = DecodeSample(nEncSampleR, nPredSampleR, nStepSize);
  1213. nStepIndexR = NextStepIndex(nEncSampleR, nStepIndexR);
  1214. //
  1215. // Write out sample
  1216. //
  1217. *(LPDWORD)pbDst = MAKELONG(nPredSampleL, nPredSampleR);
  1218. pbDst += sizeof(DWORD);
  1219. //
  1220. // Shift the next input sample into the low-order 4 bits.
  1221. //
  1222. dwLeft >>= 4;
  1223. dwRight >>= 4;
  1224. }
  1225. cSamples -= cSubSamples;
  1226. }
  1227. //
  1228. // Skip padding
  1229. //
  1230. pbSrc += nBlockAlignment;
  1231. }
  1232. return fSuccess;
  1233. }
  1234. int XboxADPCMSize( int sampleCount, int channelCount, int sampleRate )
  1235. {
  1236. CImaAdpcmCodec codec;
  1237. IMAADPCMWAVEFORMAT wfxEncode;
  1238. // Create an APDCM format structure based off the source format
  1239. codec.CreateImaAdpcmFormat( (WORD)channelCount, sampleRate, XBOX_ADPCM_SAMPLES_PER_BLOCK, &wfxEncode );
  1240. // Calculate number of ADPCM blocks and length of ADPCM data
  1241. DWORD dwDestBlocks = sampleCount / XBOX_ADPCM_SAMPLES_PER_BLOCK;
  1242. DWORD dwDestLength = dwDestBlocks * wfxEncode.wfx.nBlockAlign;
  1243. return dwDestLength;
  1244. }
  1245. void Convert16ToXboxADPCM( const short *pInputBuffer, byte *pOutputBuffer, byte *pOutFormat, int sampleCount, int channelCount, int sampleRate )
  1246. {
  1247. CImaAdpcmCodec codec;
  1248. IMAADPCMWAVEFORMAT wfxEncode;
  1249. // Create an APDCM format structure based off the source format
  1250. codec.CreateImaAdpcmFormat( (WORD)channelCount, sampleRate, XBOX_ADPCM_SAMPLES_PER_BLOCK, &wfxEncode );
  1251. if ( pOutFormat )
  1252. {
  1253. memcpy( pOutFormat, &wfxEncode, sizeof(wfxEncode) );
  1254. }
  1255. // Initialize the codec
  1256. if ( FALSE == codec.Initialize( &wfxEncode, CODEC_MODE_ENCODE_OPTIMIZE_EACH_BLOCK ) )
  1257. {
  1258. printf( "Couldn't initialize codec.\n" );
  1259. return;
  1260. }
  1261. // Convert the data
  1262. DWORD dwDestBlocks = sampleCount / XBOX_ADPCM_SAMPLES_PER_BLOCK;
  1263. if ( FALSE == codec.Convert( (const byte *)pInputBuffer, pOutputBuffer, dwDestBlocks ) )
  1264. return;
  1265. }