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.

598 lines
16 KiB

  1. /***************************************************************************
  2. *
  3. * Copyright (c) Microsoft Corporation. All rights reserved.
  4. *
  5. * File: xact3wb.h
  6. * Content: XACT 3 wave bank definitions.
  7. *
  8. ****************************************************************************/
  9. #ifndef __XACT3WB_H__
  10. #define __XACT3WB_H__
  11. #ifdef _XBOX
  12. # include <xtl.h>
  13. #else
  14. # include <math.h>
  15. #endif
  16. #include <audiodefs.h>
  17. #include <xma2defs.h>
  18. #pragma warning(push)
  19. #pragma warning(disable:4201)
  20. #pragma warning(disable:4214) // nonstandard extension used : bit field types other than int
  21. #pragma pack(push, 1)
  22. #if !defined(_X86_)
  23. #define XACTUNALIGNED __unaligned
  24. #else
  25. #define XACTUNALIGNED
  26. #endif
  27. #ifdef _M_PPCBE
  28. #pragma bitfield_order(push, lsb_to_msb)
  29. #endif
  30. #define WAVEBANK_HEADER_SIGNATURE 'DNBW' // WaveBank RIFF chunk signature
  31. #define WAVEBANK_HEADER_VERSION 44 // Current wavebank file version
  32. #define WAVEBANK_BANKNAME_LENGTH 64 // Wave bank friendly name length, in characters
  33. #define WAVEBANK_ENTRYNAME_LENGTH 64 // Wave bank entry friendly name length, in characters
  34. #define WAVEBANK_MAX_DATA_SEGMENT_SIZE 0xFFFFFFFF // Maximum wave bank data segment size, in bytes
  35. #define WAVEBANK_MAX_COMPACT_DATA_SEGMENT_SIZE 0x001FFFFF // Maximum compact wave bank data segment size, in bytes
  36. typedef DWORD WAVEBANKOFFSET;
  37. //
  38. // Bank flags
  39. //
  40. #define WAVEBANK_TYPE_BUFFER 0x00000000 // In-memory buffer
  41. #define WAVEBANK_TYPE_STREAMING 0x00000001 // Streaming
  42. #define WAVEBANK_TYPE_MASK 0x00000001
  43. #define WAVEBANK_FLAGS_ENTRYNAMES 0x00010000 // Bank includes entry names
  44. #define WAVEBANK_FLAGS_COMPACT 0x00020000 // Bank uses compact format
  45. #define WAVEBANK_FLAGS_SYNC_DISABLED 0x00040000 // Bank is disabled for audition sync
  46. #define WAVEBANK_FLAGS_SEEKTABLES 0x00080000 // Bank includes seek tables.
  47. #define WAVEBANK_FLAGS_MASK 0x000F0000
  48. //
  49. // Entry flags
  50. //
  51. #define WAVEBANKENTRY_FLAGS_READAHEAD 0x00000001 // Enable stream read-ahead
  52. #define WAVEBANKENTRY_FLAGS_LOOPCACHE 0x00000002 // One or more looping sounds use this wave
  53. #define WAVEBANKENTRY_FLAGS_REMOVELOOPTAIL 0x00000004 // Remove data after the end of the loop region
  54. #define WAVEBANKENTRY_FLAGS_IGNORELOOP 0x00000008 // Used internally when the loop region can't be used
  55. #define WAVEBANKENTRY_FLAGS_MASK 0x00000008
  56. //
  57. // Entry wave format identifiers
  58. //
  59. #define WAVEBANKMINIFORMAT_TAG_PCM 0x0 // PCM data
  60. #define WAVEBANKMINIFORMAT_TAG_XMA 0x1 // XMA data
  61. #define WAVEBANKMINIFORMAT_TAG_ADPCM 0x2 // ADPCM data
  62. #define WAVEBANKMINIFORMAT_TAG_WMA 0x3 // WMA data
  63. #define WAVEBANKMINIFORMAT_BITDEPTH_8 0x0 // 8-bit data (PCM only)
  64. #define WAVEBANKMINIFORMAT_BITDEPTH_16 0x1 // 16-bit data (PCM only)
  65. //
  66. // Arbitrary fixed sizes
  67. //
  68. #define WAVEBANKENTRY_XMASTREAMS_MAX 3 // enough for 5.1 channel audio
  69. #define WAVEBANKENTRY_XMACHANNELS_MAX 6 // enough for 5.1 channel audio (cf. XAUDIOCHANNEL_SOURCEMAX)
  70. //
  71. // DVD data sizes
  72. //
  73. #define WAVEBANK_DVD_SECTOR_SIZE 2048
  74. #define WAVEBANK_DVD_BLOCK_SIZE (WAVEBANK_DVD_SECTOR_SIZE * 16)
  75. //
  76. // Bank alignment presets
  77. //
  78. #define WAVEBANK_ALIGNMENT_MIN 4 // Minimum alignment
  79. #define WAVEBANK_ALIGNMENT_DVD WAVEBANK_DVD_SECTOR_SIZE // DVD-optimized alignment
  80. //
  81. // Wave bank segment identifiers
  82. //
  83. typedef enum WAVEBANKSEGIDX
  84. {
  85. WAVEBANK_SEGIDX_BANKDATA = 0, // Bank data
  86. WAVEBANK_SEGIDX_ENTRYMETADATA, // Entry meta-data
  87. WAVEBANK_SEGIDX_SEEKTABLES, // Storage for seek tables for the encoded waves.
  88. WAVEBANK_SEGIDX_ENTRYNAMES, // Entry friendly names
  89. WAVEBANK_SEGIDX_ENTRYWAVEDATA, // Entry wave data
  90. WAVEBANK_SEGIDX_COUNT
  91. } WAVEBANKSEGIDX, *LPWAVEBANKSEGIDX;
  92. typedef const WAVEBANKSEGIDX *LPCWAVEBANKSEGIDX;
  93. //
  94. // Endianness
  95. //
  96. #ifdef __cplusplus
  97. namespace XACTWaveBank
  98. {
  99. __inline void SwapBytes(XACTUNALIGNED DWORD &dw)
  100. {
  101. #ifdef _X86_
  102. __asm
  103. {
  104. mov edi, dw
  105. mov eax, [edi]
  106. bswap eax
  107. mov [edi], eax
  108. }
  109. #else // _X86_
  110. dw = _byteswap_ulong(dw);
  111. #endif // _X86_
  112. }
  113. __inline void SwapBytes(XACTUNALIGNED WORD &w)
  114. {
  115. #ifdef _X86_
  116. __asm
  117. {
  118. mov edi, w
  119. mov ax, [edi]
  120. xchg ah, al
  121. mov [edi], ax
  122. }
  123. #else // _X86_
  124. w = _byteswap_ushort(w);
  125. #endif // _X86_
  126. }
  127. }
  128. #endif // __cplusplus
  129. //
  130. // Wave bank region in bytes.
  131. //
  132. typedef struct WAVEBANKREGION
  133. {
  134. DWORD dwOffset; // Region offset, in bytes.
  135. DWORD dwLength; // Region length, in bytes.
  136. #ifdef __cplusplus
  137. void SwapBytes(void)
  138. {
  139. XACTWaveBank::SwapBytes(dwOffset);
  140. XACTWaveBank::SwapBytes(dwLength);
  141. }
  142. #endif // __cplusplus
  143. } WAVEBANKREGION, *LPWAVEBANKREGION;
  144. typedef const WAVEBANKREGION *LPCWAVEBANKREGION;
  145. //
  146. // Wave bank region in samples.
  147. //
  148. typedef struct WAVEBANKSAMPLEREGION
  149. {
  150. DWORD dwStartSample; // Start sample for the region.
  151. DWORD dwTotalSamples; // Region length in samples.
  152. #ifdef __cplusplus
  153. void SwapBytes(void)
  154. {
  155. XACTWaveBank::SwapBytes(dwStartSample);
  156. XACTWaveBank::SwapBytes(dwTotalSamples);
  157. }
  158. #endif // __cplusplus
  159. } WAVEBANKSAMPLEREGION, *LPWAVEBANKSAMPLEREGION;
  160. typedef const WAVEBANKSAMPLEREGION *LPCWAVEBANKSAMPLEREGION;
  161. //
  162. // Wave bank file header
  163. //
  164. typedef struct WAVEBANKHEADER
  165. {
  166. DWORD dwSignature; // File signature
  167. DWORD dwVersion; // Version of the tool that created the file
  168. DWORD dwHeaderVersion; // Version of the file format
  169. WAVEBANKREGION Segments[WAVEBANK_SEGIDX_COUNT]; // Segment lookup table
  170. #ifdef __cplusplus
  171. void SwapBytes(void)
  172. {
  173. XACTWaveBank::SwapBytes(dwSignature);
  174. XACTWaveBank::SwapBytes(dwVersion);
  175. XACTWaveBank::SwapBytes(dwHeaderVersion);
  176. for(int i = 0; i < WAVEBANK_SEGIDX_COUNT; i++)
  177. {
  178. Segments[i].SwapBytes();
  179. }
  180. }
  181. #endif // __cplusplus
  182. } WAVEBANKHEADER, *LPWAVEBANKHEADER;
  183. typedef const WAVEBANKHEADER *LPCWAVEBANKHEADER;
  184. //
  185. // Table for converting WMA Average Bytes per Second values to the WAVEBANKMINIWAVEFORMAT wBlockAlign field
  186. // NOTE: There can be a max of 8 values in the table.
  187. //
  188. #define MAX_WMA_AVG_BYTES_PER_SEC_ENTRIES 7
  189. static const DWORD aWMAAvgBytesPerSec[] =
  190. {
  191. 12000,
  192. 24000,
  193. 4000,
  194. 6000,
  195. 8000,
  196. 20000,
  197. 2500
  198. };
  199. // bitrate = entry * 8
  200. //
  201. // Table for converting WMA Block Align values to the WAVEBANKMINIWAVEFORMAT wBlockAlign field
  202. // NOTE: There can be a max of 32 values in the table.
  203. //
  204. #define MAX_WMA_BLOCK_ALIGN_ENTRIES 17
  205. static const DWORD aWMABlockAlign[] =
  206. {
  207. 929,
  208. 1487,
  209. 1280,
  210. 2230,
  211. 8917,
  212. 8192,
  213. 4459,
  214. 5945,
  215. 2304,
  216. 1536,
  217. 1485,
  218. 1008,
  219. 2731,
  220. 4096,
  221. 6827,
  222. 5462,
  223. 1280
  224. };
  225. struct WAVEBANKENTRY;
  226. //
  227. // Entry compressed data format
  228. //
  229. typedef union WAVEBANKMINIWAVEFORMAT
  230. {
  231. struct
  232. {
  233. DWORD wFormatTag : 2; // Format tag
  234. DWORD nChannels : 3; // Channel count (1 - 6)
  235. DWORD nSamplesPerSec : 18; // Sampling rate
  236. DWORD wBlockAlign : 8; // Block alignment. For WMA, lower 6 bits block alignment index, upper 2 bits bytes-per-second index.
  237. DWORD wBitsPerSample : 1; // Bits per sample (8 vs. 16, PCM only); WMAudio2/WMAudio3 (for WMA)
  238. };
  239. DWORD dwValue;
  240. #ifdef __cplusplus
  241. void SwapBytes(void)
  242. {
  243. XACTWaveBank::SwapBytes(dwValue);
  244. }
  245. WORD BitsPerSample() const
  246. {
  247. if (wFormatTag == WAVEBANKMINIFORMAT_TAG_XMA)
  248. return XMA_OUTPUT_SAMPLE_BITS; // First, because most common on Xbox 360
  249. if (wFormatTag == WAVEBANKMINIFORMAT_TAG_WMA)
  250. return 16;
  251. if (wFormatTag == WAVEBANKMINIFORMAT_TAG_ADPCM)
  252. return 4; // MSADPCM_BITS_PER_SAMPLE == 4
  253. // wFormatTag must be WAVEBANKMINIFORMAT_TAG_PCM (2 bits can only represent 4 different values)
  254. return (wBitsPerSample == WAVEBANKMINIFORMAT_BITDEPTH_16) ? 16 : 8;
  255. }
  256. #define ADPCM_MINIWAVEFORMAT_BLOCKALIGN_CONVERSION_OFFSET 22
  257. DWORD BlockAlign() const
  258. {
  259. DWORD dwReturn = 0;
  260. switch (wFormatTag)
  261. {
  262. case WAVEBANKMINIFORMAT_TAG_PCM:
  263. dwReturn = wBlockAlign;
  264. break;
  265. case WAVEBANKMINIFORMAT_TAG_XMA:
  266. dwReturn = nChannels * XMA_OUTPUT_SAMPLE_BITS / 8;
  267. break;
  268. case WAVEBANKMINIFORMAT_TAG_ADPCM:
  269. dwReturn = (wBlockAlign + ADPCM_MINIWAVEFORMAT_BLOCKALIGN_CONVERSION_OFFSET) * nChannels;
  270. break;
  271. case WAVEBANKMINIFORMAT_TAG_WMA:
  272. {
  273. DWORD dwBlockAlignIndex = wBlockAlign & 0x1F;
  274. if (dwBlockAlignIndex < MAX_WMA_BLOCK_ALIGN_ENTRIES)
  275. dwReturn = aWMABlockAlign[dwBlockAlignIndex];
  276. }
  277. break;
  278. }
  279. return dwReturn;
  280. }
  281. DWORD AvgBytesPerSec() const
  282. {
  283. DWORD dwReturn = 0;
  284. switch (wFormatTag)
  285. {
  286. case WAVEBANKMINIFORMAT_TAG_PCM:
  287. case WAVEBANKMINIFORMAT_TAG_XMA:
  288. dwReturn = nSamplesPerSec * wBlockAlign;
  289. break;
  290. case WAVEBANKMINIFORMAT_TAG_ADPCM:
  291. {
  292. DWORD blockAlign = BlockAlign();
  293. DWORD samplesPerAdpcmBlock = AdpcmSamplesPerBlock();
  294. dwReturn = blockAlign * nSamplesPerSec / samplesPerAdpcmBlock;
  295. }
  296. break;
  297. case WAVEBANKMINIFORMAT_TAG_WMA:
  298. {
  299. DWORD dwBytesPerSecIndex = wBlockAlign >> 5;
  300. if (dwBytesPerSecIndex < MAX_WMA_AVG_BYTES_PER_SEC_ENTRIES)
  301. dwReturn = aWMAAvgBytesPerSec[dwBytesPerSecIndex];
  302. }
  303. break;
  304. }
  305. return dwReturn;
  306. }
  307. DWORD EncodeWMABlockAlign(DWORD dwBlockAlign, DWORD dwAvgBytesPerSec) const
  308. {
  309. DWORD dwReturn = 0;
  310. DWORD dwBlockAlignIndex = 0;
  311. DWORD dwBytesPerSecIndex = 0;
  312. for (; dwBlockAlignIndex < MAX_WMA_BLOCK_ALIGN_ENTRIES && dwBlockAlign != aWMABlockAlign[dwBlockAlignIndex]; dwBlockAlignIndex++);
  313. if (dwBlockAlignIndex < MAX_WMA_BLOCK_ALIGN_ENTRIES)
  314. {
  315. for (; dwBytesPerSecIndex < MAX_WMA_AVG_BYTES_PER_SEC_ENTRIES && dwAvgBytesPerSec != aWMAAvgBytesPerSec[dwBytesPerSecIndex]; dwBytesPerSecIndex++);
  316. if (dwBytesPerSecIndex < MAX_WMA_AVG_BYTES_PER_SEC_ENTRIES)
  317. {
  318. dwReturn = dwBlockAlignIndex | (dwBytesPerSecIndex << 5);
  319. }
  320. }
  321. return dwReturn;
  322. }
  323. void XMA2FillFormatEx(XMA2WAVEFORMATEX *fmt, WORD blockCount, const struct WAVEBANKENTRY* entry) const;
  324. DWORD AdpcmSamplesPerBlock() const
  325. {
  326. DWORD nBlockAlign = (wBlockAlign + ADPCM_MINIWAVEFORMAT_BLOCKALIGN_CONVERSION_OFFSET) * nChannels;
  327. return nBlockAlign * 2 / (DWORD)nChannels - 12;
  328. }
  329. void AdpcmFillCoefficientTable(ADPCMWAVEFORMAT *fmt) const
  330. {
  331. // These are fixed since we are always using MS ADPCM
  332. fmt->wNumCoef = 7; /* MSADPCM_NUM_COEFFICIENTS */
  333. static ADPCMCOEFSET aCoef[7] = { { 256, 0}, {512, -256}, {0,0}, {192,64}, {240,0}, {460, -208}, {392,-232} };
  334. memcpy( &fmt->aCoef, aCoef, sizeof(aCoef) );
  335. }
  336. #endif // __cplusplus
  337. } WAVEBANKMINIWAVEFORMAT, *LPWAVEBANKMINIWAVEFORMAT;
  338. typedef const WAVEBANKMINIWAVEFORMAT *LPCWAVEBANKMINIWAVEFORMAT;
  339. //
  340. // Entry meta-data
  341. //
  342. typedef struct WAVEBANKENTRY
  343. {
  344. union
  345. {
  346. struct
  347. {
  348. // Entry flags
  349. DWORD dwFlags : 4;
  350. // Duration of the wave, in units of one sample.
  351. // For instance, a ten second long wave sampled
  352. // at 48KHz would have a duration of 480,000.
  353. // This value is not affected by the number of
  354. // channels, the number of bits per sample, or the
  355. // compression format of the wave.
  356. DWORD Duration : 28;
  357. };
  358. DWORD dwFlagsAndDuration;
  359. };
  360. WAVEBANKMINIWAVEFORMAT Format; // Entry format.
  361. WAVEBANKREGION PlayRegion; // Region within the wave data segment that contains this entry.
  362. WAVEBANKSAMPLEREGION LoopRegion; // Region within the wave data (in samples) that should loop.
  363. #ifdef __cplusplus
  364. void SwapBytes(void)
  365. {
  366. XACTWaveBank::SwapBytes(dwFlagsAndDuration);
  367. Format.SwapBytes();
  368. PlayRegion.SwapBytes();
  369. LoopRegion.SwapBytes();
  370. }
  371. #endif // __cplusplus
  372. } WAVEBANKENTRY, *LPWAVEBANKENTRY;
  373. typedef const WAVEBANKENTRY *LPCWAVEBANKENTRY;
  374. //
  375. // Compact entry meta-data
  376. //
  377. typedef struct WAVEBANKENTRYCOMPACT
  378. {
  379. DWORD dwOffset : 21; // Data offset, in sectors
  380. DWORD dwLengthDeviation : 11; // Data length deviation, in bytes
  381. #ifdef __cplusplus
  382. void SwapBytes(void)
  383. {
  384. XACTWaveBank::SwapBytes(*(LPDWORD)this);
  385. }
  386. #endif // __cplusplus
  387. } WAVEBANKENTRYCOMPACT, *LPWAVEBANKENTRYCOMPACT;
  388. typedef const WAVEBANKENTRYCOMPACT *LPCWAVEBANKENTRYCOMPACT;
  389. //
  390. // Bank data segment
  391. //
  392. typedef struct WAVEBANKDATA
  393. {
  394. DWORD dwFlags; // Bank flags
  395. DWORD dwEntryCount; // Number of entries in the bank
  396. CHAR szBankName[WAVEBANK_BANKNAME_LENGTH]; // Bank friendly name
  397. DWORD dwEntryMetaDataElementSize; // Size of each entry meta-data element, in bytes
  398. DWORD dwEntryNameElementSize; // Size of each entry name element, in bytes
  399. DWORD dwAlignment; // Entry alignment, in bytes
  400. WAVEBANKMINIWAVEFORMAT CompactFormat; // Format data for compact bank
  401. FILETIME BuildTime; // Build timestamp
  402. #ifdef __cplusplus
  403. void SwapBytes(void)
  404. {
  405. XACTWaveBank::SwapBytes(dwFlags);
  406. XACTWaveBank::SwapBytes(dwEntryCount);
  407. XACTWaveBank::SwapBytes(dwEntryMetaDataElementSize);
  408. XACTWaveBank::SwapBytes(dwEntryNameElementSize);
  409. XACTWaveBank::SwapBytes(dwAlignment);
  410. CompactFormat.SwapBytes();
  411. XACTWaveBank::SwapBytes(BuildTime.dwLowDateTime);
  412. XACTWaveBank::SwapBytes(BuildTime.dwHighDateTime);
  413. }
  414. #endif // __cplusplus
  415. } WAVEBANKDATA, *LPWAVEBANKDATA;
  416. typedef const WAVEBANKDATA *LPCWAVEBANKDATA;
  417. inline void WAVEBANKMINIWAVEFORMAT::XMA2FillFormatEx(XMA2WAVEFORMATEX *fmt, WORD blockCount, const WAVEBANKENTRY* entry) const
  418. {
  419. // Note caller is responsbile for filling out fmt->wfx with other helper functions.
  420. fmt->NumStreams = (WORD)( (nChannels + 1) / 2 );
  421. switch (nChannels)
  422. {
  423. case 1: fmt->ChannelMask = SPEAKER_MONO; break;
  424. case 2: fmt->ChannelMask = SPEAKER_STEREO; break;
  425. case 3: fmt->ChannelMask = SPEAKER_2POINT1; break;
  426. case 4: fmt->ChannelMask = SPEAKER_QUAD; break;
  427. case 5: fmt->ChannelMask = SPEAKER_4POINT1; break;
  428. case 6: fmt->ChannelMask = SPEAKER_5POINT1; break;
  429. case 7: fmt->ChannelMask = SPEAKER_5POINT1 | SPEAKER_BACK_CENTER; break;
  430. case 8: fmt->ChannelMask = SPEAKER_7POINT1; break;
  431. default: fmt->ChannelMask = 0; break;
  432. }
  433. fmt->SamplesEncoded = entry->Duration;
  434. fmt->BytesPerBlock = 65536; /* XACT_FIXED_XMA_BLOCK_SIZE */
  435. fmt->PlayBegin = entry->PlayRegion.dwOffset;
  436. fmt->PlayLength = entry->PlayRegion.dwLength;
  437. if (entry->LoopRegion.dwTotalSamples > 0)
  438. {
  439. fmt->LoopBegin = entry->LoopRegion.dwStartSample;
  440. fmt->LoopLength = entry->LoopRegion.dwTotalSamples;
  441. fmt->LoopCount = 0xff; /* XACTLOOPCOUNT_INFINITE */
  442. }
  443. else
  444. {
  445. fmt->LoopBegin = 0;
  446. fmt->LoopLength = 0;
  447. fmt->LoopCount = 0;
  448. }
  449. fmt->EncoderVersion = 4; // XMAENCODER_VERSION_XMA2
  450. fmt->BlockCount = blockCount;
  451. }
  452. #ifdef _M_PPCBE
  453. #pragma bitfield_order(pop)
  454. #endif
  455. #pragma warning(pop)
  456. #pragma pack(pop)
  457. #endif // __XACTWB_H__