Subversion Repositories Games.Chess Giants

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 pmbaty 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
 
193
} WAVEBANKREGION, *LPWAVEBANKREGION;
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
 
217
} WAVEBANKSAMPLEREGION, *LPWAVEBANKSAMPLEREGION;
218
 
219
typedef const WAVEBANKSAMPLEREGION *LPCWAVEBANKSAMPLEREGION;
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
 
249
} WAVEBANKHEADER, *LPWAVEBANKHEADER;
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
 
306
typedef union WAVEBANKMINIWAVEFORMAT
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
 
442
} WAVEBANKMINIWAVEFORMAT, *LPWAVEBANKMINIWAVEFORMAT;
443
 
444
typedef const WAVEBANKMINIWAVEFORMAT *LPCWAVEBANKMINIWAVEFORMAT;
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
 
486
} WAVEBANKENTRY, *LPWAVEBANKENTRY;
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
 
508
} WAVEBANKENTRYCOMPACT, *LPWAVEBANKENTRYCOMPACT;
509
 
510
typedef const WAVEBANKENTRYCOMPACT *LPCWAVEBANKENTRYCOMPACT;
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
 
543
} WAVEBANKDATA, *LPWAVEBANKDATA;
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