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