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:     xma2defs.h
6
 * Content:  Constants, data types and functions for XMA2 compressed audio.
7
 *
8
 ***************************************************************************/
9
 
10
#ifndef __XMA2DEFS_INCLUDED__
11
#define __XMA2DEFS_INCLUDED__
12
 
13
#include <sal.h>        // Markers for documenting API semantics
14
#include <winerror.h>   // For S_OK, E_FAIL
15
#include <audiodefs.h>  // Basic data types and constants for audio work
16
 
17
 
18
/***************************************************************************
19
 *  Overview
20
 ***************************************************************************/
21
 
22
// A typical XMA2 file contains these RIFF chunks:
23
//
24
// 'fmt' or 'XMA2' chunk (or both): A description of the XMA data's structure
25
// and characteristics (length, channels, sample rate, loops, block size, etc).
26
//
27
// 'seek' chunk: A seek table to help navigate the XMA data.
28
//
29
// 'data' chunk: The encoded XMA2 data.
30
//
31
// The encoded XMA2 data is structured as a set of BLOCKS, which contain PACKETS,
32
// which contain FRAMES, which contain SUBFRAMES (roughly speaking).  The frames
33
// in a file may also be divided into several subsets, called STREAMS.
34
//
35
// FRAME: A variable-sized segment of XMA data that decodes to exactly 512 mono
36
//      or stereo PCM samples.  This is the smallest unit of XMA data that can
37
//      be decoded in isolation.  Frames are an arbitrary number of bits in
38
//      length, and need not be byte-aligned.  See "XMA frame structure" below.
39
//
40
// SUBFRAME: A region of bits in an XMA frame that decodes to 128 mono or stereo
41
//      samples.  The XMA decoder cannot decode a subframe in isolation; it needs
42
//      a whole frame to work with.  However, it can begin emitting the frame's
43
//      decoded samples at any one of the four subframe boundaries.  Subframes
44
//      can be addressed for seeking and looping purposes.
45
//
46
// PACKET: A 2Kb region containing a 32-bit header and some XMA frames.  Frames
47
//      can (and usually do) span packets.  A packet's header includes the offset
48
//      in bits of the first frame that begins within that packet.  All of the
49
//      frames that begin in a given packet belong to the same "stream" (see the
50
//      Multichannel Audio section below).
51
//
52
// STREAM: A set of packets within an XMA file that all contain data for the
53
//      same mono or stereo component of a PCM file with more than two channels.
54
//      The packets comprising a given stream may be interleaved with each other
55
//      more or less arbitrarily; see Multichannel Audio.
56
//
57
// BLOCK: An array of XMA packets; or, to break it down differently, a series of
58
//      consecutive XMA frames, padded at the end with reserved data.  A block
59
//      must contain at least one 2Kb packet per stream, and it can hold up to
60
//      4095 packets (8190Kb), but its size is typically in the 32Kb-128Kb range.
61
//      (The size chosen involves a trade-off between memory use and efficiency
62
//      of reading from permanent storage.)
63
//
64
//      XMA frames do not span blocks, so a block is guaranteed to begin with a
65
//      set of complete frames, one per stream.  Also, a block in a multi-stream
66
//      XMA2 file always contains the same number of samples for each stream;
67
//      see Multichannel Audio.
68
//
69
// The 'data' chunk in an XMA2 file is an array of XMA2WAVEFORMAT.BlockCount XMA
70
// blocks, all the same size (as specified in XMA2WAVEFORMAT.BlockSizeInBytes)
71
// except for the last one, which may be shorter.
72
 
73
 
74
// MULTICHANNEL AUDIO: the XMA decoder can only decode raw XMA data into either
75
// mono or stereo PCM data.  In order to encode a 6-channel file (say), the file
76
// must be deinterleaved into 3 stereo streams that are encoded independently,
77
// producing 3 encoded XMA data streams.  Then the packets in these 3 streams
78
// are interleaved to produce a single XMA2 file, and some information is added
79
// to the file so that the original 6-channel audio can be reconstructed at
80
// decode time.  This works using the concept of an XMA stream (see above).
81
//
82
// The frames for all the streams in an XMA file are interleaved in an arbitrary
83
// order.  To locate a frame that belongs to a given stream in a given XMA block,
84
// you must examine the first few packets in the block.  Here (and only here) the
85
// packets are guaranteed to be presented in stream order, so that all frames
86
// beginning in packet 0 belong to stream 0 (the first stereo pair), etc.
87
//
88
// (This means that when decoding multi-stream XMA files, only entire XMA blocks
89
// should be submitted to the decoder; otherwise it cannot know which frames
90
// belong to which stream.)
91
//
92
// Once you have one frame that belongs to a given stream, you can find the next
93
// one by looking at the frame's 'NextFrameOffsetBits' value (which is stored in
94
// its first 15 bits; see XMAFRAME below).  The GetXmaFrameBitPosition function
95
// uses this technique.
96
 
97
 
98
// SEEKING IN XMA2 FILES: Here is some pseudocode to find the byte position and
99
// subframe in an XMA2 file which will contain sample S when decoded.
100
//
101
// 1. Traverse the seek table to find the XMA2 block containing sample S. The
102
//    seek table is an array of big-endian DWORDs, one per block in the file.
103
//    The Nth DWORD is the total number of PCM samples that would be obtained
104
//    by decoding the entire XMA file up to the end of block N.  Hence, the
105
//    block we want is the first one whose seek table entry is greater than S.
106
//    (See the GetXmaBlockContainingSample helper function.)
107
//
108
// 2. Calculate which frame F within the block found above contains sample S.
109
//    Since each frame decodes to 512 samples, this is straightforward.  The
110
//    first frame in the block produces samples X to X + 512, where X is the
111
//    seek table entry for the prior block.  So F is (S - X) / 512.
112
//
113
// 3. Find the bit offset within the block where frame F starts.  Since frames
114
//    are variable-sized, this can only be done by traversing all the frames in
115
//    the block until we reach frame F.  (See GetXmaFrameBitPosition.)
116
//
117
// 4. Frame F has four 128-sample subframes.  To find the subframe containing S,
118
//    we can use the formula (S % 512) / 128.
119
//
120
// In the case of multi-stream XMA files, sample S is a multichannel sample with
121
// parts coming from several frames, one per stream.  To find all these frames,
122
// steps 2-4 need to be repeated for each stream N, using the knowledge that the
123
// first packets in a block are presented in stream order.  The frame traversal
124
// in step 3 must be started at the first frame in the Nth packet of the block,
125
// which will be the first frame for stream N.  (And the packet header will tell
126
// you the first frame's start position within the packet.)
127
//
128
// Step 1 can be performed using the GetXmaBlockContainingSample function below,
129
// and steps 2-4 by calling GetXmaDecodePositionForSample once for each stream.
130
 
131
 
132
 
133
/***************************************************************************
134
 *  XMA constants
135
 ***************************************************************************/
136
 
137
// Size of the PCM samples produced by the XMA decoder
138
#define XMA_OUTPUT_SAMPLE_BYTES         2u
139
#define XMA_OUTPUT_SAMPLE_BITS          (XMA_OUTPUT_SAMPLE_BYTES * 8u)
140
 
141
// Size of an XMA packet
142
#define XMA_BYTES_PER_PACKET            2048u
143
#define XMA_BITS_PER_PACKET             (XMA_BYTES_PER_PACKET * 8u)
144
 
145
// Size of an XMA packet header
146
#define XMA_PACKET_HEADER_BYTES         4u
147
#define XMA_PACKET_HEADER_BITS          (XMA_PACKET_HEADER_BYTES * 8u)
148
 
149
// Sample blocks in a decoded XMA frame
150
#define XMA_SAMPLES_PER_FRAME           512u
151
 
152
// Sample blocks in a decoded XMA subframe
153
#define XMA_SAMPLES_PER_SUBFRAME        128u
154
 
155
// Maximum encoded data that can be submitted to the XMA decoder at a time
156
#define XMA_READBUFFER_MAX_PACKETS      4095u
157
#define XMA_READBUFFER_MAX_BYTES        (XMA_READBUFFER_MAX_PACKETS * XMA_BYTES_PER_PACKET)
158
 
159
// Maximum size allowed for the XMA decoder's output buffers
160
#define XMA_WRITEBUFFER_MAX_BYTES       (31u * 256u)
161
 
162
// Required byte alignment of the XMA decoder's output buffers
163
#define XMA_WRITEBUFFER_BYTE_ALIGNMENT  256u
164
 
165
// Decode chunk sizes for the XMA_PLAYBACK_INIT.subframesToDecode field
166
#define XMA_MIN_SUBFRAMES_TO_DECODE     1u
167
#define XMA_MAX_SUBFRAMES_TO_DECODE     8u
168
#define XMA_OPTIMAL_SUBFRAMES_TO_DECODE 4u
169
 
170
// LoopCount<255 means finite repetitions; LoopCount=255 means infinite looping
171
#define XMA_MAX_LOOPCOUNT               254u
172
#define XMA_INFINITE_LOOP               255u
173
 
174
 
175
 
176
/***************************************************************************
177
 *  XMA format structures
178
 ***************************************************************************/
179
 
180
// The currently recommended way to express format information for XMA2 files
181
// is the XMA2WAVEFORMATEX structure.  This structure is fully compliant with
182
// the WAVEFORMATEX standard and contains all the information needed to parse
183
// and manage XMA2 files in a compact way.
184
 
185
#define WAVE_FORMAT_XMA2 0x166
186
 
187
typedef struct XMA2WAVEFORMATEX
188
{
189
    WAVEFORMATEX wfx;
190
    // Meaning of the WAVEFORMATEX fields here:
191
    //    wFormatTag;        // Audio format type; always WAVE_FORMAT_XMA2
192
    //    nChannels;         // Channel count of the decoded audio
193
    //    nSamplesPerSec;    // Sample rate of the decoded audio
194
    //    nAvgBytesPerSec;   // Used internally by the XMA encoder
195
    //    nBlockAlign;       // Decoded sample size; channels * wBitsPerSample / 8
196
    //    wBitsPerSample;    // Bits per decoded mono sample; always 16 for XMA
197
    //    cbSize;            // Size in bytes of the rest of this structure (34)
198
 
199
    WORD  NumStreams;        // Number of audio streams (1 or 2 channels each)
200
    DWORD ChannelMask;       // Spatial positions of the channels in this file,
201
                             // stored as SPEAKER_xxx values (see audiodefs.h)
202
    DWORD SamplesEncoded;    // Total number of PCM samples the file decodes to
203
    DWORD BytesPerBlock;     // XMA block size (but the last one may be shorter)
204
    DWORD PlayBegin;         // First valid sample in the decoded audio
205
    DWORD PlayLength;        // Length of the valid part of the decoded audio
206
    DWORD LoopBegin;         // Beginning of the loop region in decoded sample terms
207
    DWORD LoopLength;        // Length of the loop region in decoded sample terms
208
    BYTE  LoopCount;         // Number of loop repetitions; 255 = infinite
209
    BYTE  EncoderVersion;    // Version of XMA encoder that generated the file
210
    WORD  BlockCount;        // XMA blocks in file (and entries in its seek table)
211
} XMA2WAVEFORMATEX, *PXMA2WAVEFORMATEX;
212
 
213
 
214
// The legacy XMA format structures are described here for reference, but they
215
// should not be used in new content.  XMAWAVEFORMAT was the structure used in
216
// XMA version 1 files.  XMA2WAVEFORMAT was used in early XMA2 files; it is not
217
// placed in the usual 'fmt' RIFF chunk but in its own 'XMA2' chunk.
218
 
219
#ifndef WAVE_FORMAT_XMA
220
#define WAVE_FORMAT_XMA 0x0165
221
 
222
// Values used in the ChannelMask fields below.  Similar to the SPEAKER_xxx
223
// values defined in audiodefs.h, but modified to fit in a single byte.
224
#ifndef XMA_SPEAKER_LEFT
225
    #define XMA_SPEAKER_LEFT            0x01
226
    #define XMA_SPEAKER_RIGHT           0x02
227
    #define XMA_SPEAKER_CENTER          0x04
228
    #define XMA_SPEAKER_LFE             0x08
229
    #define XMA_SPEAKER_LEFT_SURROUND   0x10
230
    #define XMA_SPEAKER_RIGHT_SURROUND  0x20
231
    #define XMA_SPEAKER_LEFT_BACK       0x40
232
    #define XMA_SPEAKER_RIGHT_BACK      0x80
233
#endif
234
 
235
 
236
// Used in XMAWAVEFORMAT for per-stream data
237
typedef struct XMASTREAMFORMAT
238
{
239
    DWORD PsuedoBytesPerSec; // Used by the XMA encoder (typo preserved for legacy reasons)
240
    DWORD SampleRate;        // The stream's decoded sample rate (in XMA2 files,
241
                             // this is the same for all streams in the file).
242
    DWORD LoopStart;         // Bit offset of the frame containing the loop start
243
                             // point, relative to the beginning of the stream.
244
    DWORD LoopEnd;           // Bit offset of the frame containing the loop end.
245
    BYTE  SubframeData;      // Two 4-bit numbers specifying the exact location of
246
                             // the loop points within the frames that contain them.
247
                             //   SubframeEnd: Subframe of the loop end frame where
248
                             //                the loop ends.  Ranges from 0 to 3.
249
                             //   SubframeSkip: Subframes to skip in the start frame to
250
                             //                 reach the loop.  Ranges from 0 to 4.
251
    BYTE  Channels;          // Number of channels in the stream (1 or 2)
252
    WORD  ChannelMask;       // Spatial positions of the channels in the stream
253
} XMASTREAMFORMAT;
254
 
255
// Legacy XMA1 format structure
256
typedef struct XMAWAVEFORMAT
257
{
258
    WORD FormatTag;          // Audio format type (always WAVE_FORMAT_XMA)
259
    WORD BitsPerSample;      // Bit depth (currently required to be 16)
260
    WORD EncodeOptions;      // Options for XMA encoder/decoder
261
    WORD LargestSkip;        // Largest skip used in interleaving streams
262
    WORD NumStreams;         // Number of interleaved audio streams
263
    BYTE LoopCount;          // Number of loop repetitions; 255 = infinite
264
    BYTE Version;            // XMA encoder version that generated the file.
265
                             // Always 3 or higher for XMA2 files.
266
    XMASTREAMFORMAT XmaStreams[1]; // Per-stream format information; the actual
267
                                   // array length is in the NumStreams field.
268
} XMAWAVEFORMAT;
269
 
270
 
271
// Used in XMA2WAVEFORMAT for per-stream data
272
typedef struct XMA2STREAMFORMAT
273
{
274
    BYTE Channels;           // Number of channels in the stream (1 or 2)
275
    BYTE RESERVED;           // Reserved for future use
276
    WORD ChannelMask;        // Spatial positions of the channels in the stream
277
} XMA2STREAMFORMAT;
278
 
279
// Legacy XMA2 format structure (big-endian byte ordering)
280
typedef struct XMA2WAVEFORMAT
281
{
282
    BYTE  Version;           // XMA encoder version that generated the file.
283
                             // Always 3 or higher for XMA2 files.
284
    BYTE  NumStreams;        // Number of interleaved audio streams
285
    BYTE  RESERVED;          // Reserved for future use
286
    BYTE  LoopCount;         // Number of loop repetitions; 255 = infinite
287
    DWORD LoopBegin;         // Loop begin point, in samples
288
    DWORD LoopEnd;           // Loop end point, in samples
289
    DWORD SampleRate;        // The file's decoded sample rate
290
    DWORD EncodeOptions;     // Options for the XMA encoder/decoder
291
    DWORD PsuedoBytesPerSec; // Used internally by the XMA encoder
292
    DWORD BlockSizeInBytes;  // Size in bytes of this file's XMA blocks (except
293
                             // possibly the last one).  Always a multiple of
294
                             // 2Kb, since XMA blocks are arrays of 2Kb packets.
295
    DWORD SamplesEncoded;    // Total number of PCM samples encoded in this file
296
    DWORD SamplesInSource;   // Actual number of PCM samples in the source
297
                             // material used to generate this file
298
    DWORD BlockCount;        // Number of XMA blocks in this file (and hence
299
                             // also the number of entries in its seek table)
300
    XMA2STREAMFORMAT Streams[1]; // Per-stream format information; the actual
301
                                 // array length is in the NumStreams field.
302
} XMA2WAVEFORMAT;
303
 
304
#endif // #ifndef WAVE_FORMAT_XMA
305
 
306
 
307
 
308
/***************************************************************************
309
 *  XMA packet structure (in big-endian form)
310
 ***************************************************************************/
311
 
312
typedef struct XMA2PACKET
313
{
314
    int FrameCount        :  6;  // Number of XMA frames that begin in this packet
315
    int FrameOffsetInBits : 15;  // Bit of XmaData where the first complete frame begins
316
    int PacketMetaData    :  3;  // Metadata stored in the packet (always 1 for XMA2)
317
    int PacketSkipCount   :  8;  // How many packets belonging to other streams must be
318
                                 // skipped to find the next packet belonging to this one
319
    BYTE XmaData[XMA_BYTES_PER_PACKET - sizeof(DWORD)];  // XMA encoded data
320
} XMA2PACKET;
321
 
322
// E.g. if the first DWORD of a packet is 0x30107902:
323
//
324
// 001100 000001000001111 001 00000010
325
//    |          |         |      |____ Skip 2 packets to find the next one for this stream
326
//    |          |         |___________ XMA2 signature (always 001)
327
//    |          |_____________________ First frame starts 527 bits into packet
328
//    |________________________________ Packet contains 12 frames
329
 
330
 
331
// Helper functions to extract the fields above from an XMA packet.  (Note that
332
// the bitfields cannot be read directly on little-endian architectures such as
333
// the Intel x86, as they are laid out in big-endian form.)
334
 
335
__inline DWORD GetXmaPacketFrameCount(__in_bcount(1) const BYTE* pPacket)
336
{
337
    return (DWORD)(pPacket[0] >> 2);
338
}
339
 
340
__inline DWORD GetXmaPacketFirstFrameOffsetInBits(__in_bcount(3) const BYTE* pPacket)
341
{
342
    return ((DWORD)(pPacket[0] & 0x3) << 13) |
343
           ((DWORD)(pPacket[1]) << 5) |
344
           ((DWORD)(pPacket[2]) >> 3);
345
}
346
 
347
__inline DWORD GetXmaPacketMetadata(__in_bcount(3) const BYTE* pPacket)
348
{
349
    return (DWORD)(pPacket[2] & 0x7);
350
}
351
 
352
__inline DWORD GetXmaPacketSkipCount(__in_bcount(4) const BYTE* pPacket)
353
{
354
    return (DWORD)(pPacket[3]);
355
}
356
 
357
 
358
 
359
/***************************************************************************
360
 *  XMA frame structure
361
 ***************************************************************************/
362
 
363
// There is no way to represent the XMA frame as a C struct, since it is a
364
// variable-sized string of bits that need not be stored at a byte-aligned
365
// position in memory.  This is the layout:
366
//
367
// XMAFRAME
368
// {
369
//    LengthInBits: A 15-bit number representing the length of this frame.
370
//    XmaData: Encoded XMA data; its size in bits is (LengthInBits - 15).
371
// }
372
 
373
// Size in bits of the frame's initial LengthInBits field
374
#define XMA_BITS_IN_FRAME_LENGTH_FIELD 15
375
 
376
// Special LengthInBits value that marks an invalid final frame
377
#define XMA_FINAL_FRAME_MARKER 0x7FFF
378
 
379
 
380
 
381
/***************************************************************************
382
 *  XMA helper functions
383
 ***************************************************************************/
384
 
385
// We define a local ASSERT macro to equal the global one if it exists.
386
// You can define XMA2DEFS_ASSERT in advance to override this default.
387
#ifndef XMA2DEFS_ASSERT
388
    #ifdef ASSERT
389
        #define XMA2DEFS_ASSERT ASSERT
390
    #else
391
        #define XMA2DEFS_ASSERT(a) /* No-op by default */
392
    #endif
393
#endif
394
 
395
 
396
// GetXmaBlockContainingSample: Use a given seek table to find the XMA block
397
// containing a given decoded sample.  Note that the seek table entries in an
398
// XMA file are stored in big-endian form and may need to be converted prior
399
// to calling this function.
400
 
401
__inline HRESULT GetXmaBlockContainingSample
402
(
403
    DWORD nBlockCount,                      // Blocks in the file (= seek table entries)
404
    __in_ecount(nBlockCount) const DWORD* pSeekTable,  // Pointer to the seek table data
405
    DWORD nDesiredSample,                   // Decoded sample to locate
406
    __out DWORD* pnBlockContainingSample,   // Index of the block containing the sample
407
    __out DWORD* pnSampleOffsetWithinBlock  // Position of the sample in this block
408
)
409
{
410
    DWORD nPreviousTotalSamples = 0;
411
    DWORD nBlock;
412
    DWORD nTotalSamplesSoFar;
413
 
414
    XMA2DEFS_ASSERT(pSeekTable);
415
    XMA2DEFS_ASSERT(pnBlockContainingSample);
416
    XMA2DEFS_ASSERT(pnSampleOffsetWithinBlock);
417
 
418
    for (nBlock = 0; nBlock < nBlockCount; ++nBlock)
419
    {
420
        nTotalSamplesSoFar = pSeekTable[nBlock];
421
        if (nTotalSamplesSoFar > nDesiredSample)
422
        {
423
            *pnBlockContainingSample = nBlock;
424
            *pnSampleOffsetWithinBlock = nDesiredSample - nPreviousTotalSamples;
425
            return S_OK;
426
        }
427
        nPreviousTotalSamples = nTotalSamplesSoFar;
428
    }
429
 
430
    return E_FAIL;
431
}
432
 
433
 
434
// GetXmaFrameLengthInBits: Reads a given frame's LengthInBits field.
435
 
436
__inline DWORD GetXmaFrameLengthInBits
437
(
438
    __in_bcount(nBitPosition / 8 + 3)
439
    __in const BYTE* pPacket,  // Pointer to XMA packet[s] containing the frame
440
    DWORD nBitPosition         // Bit offset of the frame within this packet
441
)
442
{
443
    DWORD nRegion;
444
    DWORD nBytePosition = nBitPosition / 8;
445
    DWORD nBitOffset = nBitPosition % 8;
446
 
447
    if (nBitOffset < 2) // Only need to read 2 bytes (and might not be safe to read more)
448
    {
449
        nRegion = (DWORD)(pPacket[nBytePosition+0]) << 8 |
450
                  (DWORD)(pPacket[nBytePosition+1]);
451
        return (nRegion >> (1 - nBitOffset)) & 0x7FFF;  // Last 15 bits
452
    }
453
    else // Need to read 3 bytes
454
    {
455
        nRegion = (DWORD)(pPacket[nBytePosition+0]) << 16 |
456
                  (DWORD)(pPacket[nBytePosition+1]) << 8 |
457
                  (DWORD)(pPacket[nBytePosition+2]);
458
        return (nRegion >> (9 - nBitOffset)) & 0x7FFF;  // Last 15 bits
459
    }
460
}
461
 
462
 
463
// GetXmaFrameBitPosition: Calculates the bit offset of a given frame within
464
// an XMA block or set of blocks.  Returns 0 on failure.
465
 
466
__inline DWORD GetXmaFrameBitPosition
467
(
468
    __in_bcount(nXmaDataBytes) const BYTE* pXmaData,  // Pointer to XMA block[s]
469
    DWORD nXmaDataBytes,                              // Size of pXmaData in bytes
470
    DWORD nStreamIndex,                               // Stream within which to seek
471
    DWORD nDesiredFrame                               // Frame sought
472
)
473
{
474
    const BYTE* pCurrentPacket;
475
    DWORD nPacketsExamined = 0;
476
    DWORD nFrameCountSoFar = 0;
477
    DWORD nFramesToSkip;
478
    DWORD nFrameBitOffset;
479
 
480
    XMA2DEFS_ASSERT(pXmaData);
481
    XMA2DEFS_ASSERT(nXmaDataBytes % XMA_BYTES_PER_PACKET == 0);
482
 
483
    // Get the first XMA packet belonging to the desired stream, relying on the
484
    // fact that the first packets for each stream are in consecutive order at
485
    // the beginning of an XMA block.
486
 
487
    pCurrentPacket = pXmaData + nStreamIndex * XMA_BYTES_PER_PACKET;
488
    for (;;)
489
    {
490
        // If we have exceeded the size of the XMA data, return failure
491
        if (pCurrentPacket + XMA_BYTES_PER_PACKET > pXmaData + nXmaDataBytes)
492
        {
493
            return 0;
494
        }
495
 
496
        // If the current packet contains the frame we are looking for...
497
        if (nFrameCountSoFar + GetXmaPacketFrameCount(pCurrentPacket) > nDesiredFrame)
498
        {
499
            // See how many frames in this packet we need to skip to get to it
500
            XMA2DEFS_ASSERT(nDesiredFrame >= nFrameCountSoFar);
501
            nFramesToSkip = nDesiredFrame - nFrameCountSoFar;
502
 
503
            // Get the bit offset of the first frame in this packet
504
            nFrameBitOffset = XMA_PACKET_HEADER_BITS + GetXmaPacketFirstFrameOffsetInBits(pCurrentPacket);
505
 
506
            // Advance nFrameBitOffset to the frame of interest
507
            while (nFramesToSkip--)
508
            {
509
                nFrameBitOffset += GetXmaFrameLengthInBits(pCurrentPacket, nFrameBitOffset);
510
            }
511
 
512
            // The bit offset to return is the number of bits from pXmaData to
513
            // pCurrentPacket plus the bit offset of the frame of interest
514
            return (DWORD)(pCurrentPacket - pXmaData) * 8 + nFrameBitOffset;
515
        }
516
 
517
        // If we haven't found the right packet yet, advance our counters
518
        ++nPacketsExamined;
519
        nFrameCountSoFar += GetXmaPacketFrameCount(pCurrentPacket);
520
 
521
        // And skip to the next packet belonging to the same stream
522
        pCurrentPacket += XMA_BYTES_PER_PACKET * (GetXmaPacketSkipCount(pCurrentPacket) + 1);
523
    }
524
}
525
 
526
 
527
// GetLastXmaFrameBitPosition: Calculates the bit offset of the last complete
528
// frame in an XMA block or set of blocks.
529
 
530
__inline DWORD GetLastXmaFrameBitPosition
531
(
532
    __in_bcount(nXmaDataBytes) const BYTE* pXmaData,  // Pointer to XMA block[s]
533
    DWORD nXmaDataBytes,                              // Size of pXmaData in bytes
534
    DWORD nStreamIndex                                // Stream within which to seek
535
)
536
{
537
    const BYTE* pLastPacket;
538
    DWORD nBytesToNextPacket;
539
    DWORD nFrameBitOffset;
540
    DWORD nFramesInLastPacket;
541
 
542
    XMA2DEFS_ASSERT(pXmaData);
543
    XMA2DEFS_ASSERT(nXmaDataBytes % XMA_BYTES_PER_PACKET == 0);
544
    XMA2DEFS_ASSERT(nXmaDataBytes >= XMA_BYTES_PER_PACKET * (nStreamIndex + 1));
545
 
546
    // Get the first XMA packet belonging to the desired stream, relying on the
547
    // fact that the first packets for each stream are in consecutive order at
548
    // the beginning of an XMA block.
549
    pLastPacket = pXmaData + nStreamIndex * XMA_BYTES_PER_PACKET;
550
 
551
    // Search for the last packet belonging to the desired stream
552
    for (;;)
553
    {
554
        nBytesToNextPacket = XMA_BYTES_PER_PACKET * (GetXmaPacketSkipCount(pLastPacket) + 1);
555
        XMA2DEFS_ASSERT(nBytesToNextPacket);
556
        if (pLastPacket + nBytesToNextPacket + XMA_BYTES_PER_PACKET > pXmaData + nXmaDataBytes)
557
        {
558
            break;  // The next packet would extend beyond the end of pXmaData
559
        }
560
        pLastPacket += nBytesToNextPacket;
561
    }
562
 
563
    // The last packet can sometimes have no seekable frames, in which case we
564
    // have to use the previous one
565
    if (GetXmaPacketFrameCount(pLastPacket) == 0)
566
    {
567
        pLastPacket -= nBytesToNextPacket;
568
    }
569
 
570
    // Found the last packet.  Get the bit offset of its first frame.
571
    nFrameBitOffset = XMA_PACKET_HEADER_BITS + GetXmaPacketFirstFrameOffsetInBits(pLastPacket);
572
 
573
    // Traverse frames until we reach the last one
574
    nFramesInLastPacket = GetXmaPacketFrameCount(pLastPacket);
575
    while (--nFramesInLastPacket)
576
    {
577
        nFrameBitOffset += GetXmaFrameLengthInBits(pLastPacket, nFrameBitOffset);
578
    }
579
 
580
    // The bit offset to return is the number of bits from pXmaData to
581
    // pLastPacket plus the offset of the last frame in this packet.
582
    return (DWORD)(pLastPacket - pXmaData) * 8 + nFrameBitOffset;
583
}
584
 
585
 
586
// GetXmaDecodePositionForSample: Obtains the information needed to make the
587
// decoder generate audio starting at a given sample position relative to the
588
// beginning of the given XMA block: the bit offset of the appropriate frame,
589
// and the right subframe within that frame.  This data can be passed directly
590
// to the XMAPlaybackSetDecodePosition function.
591
 
592
__inline HRESULT GetXmaDecodePositionForSample
593
(
594
    __in_bcount(nXmaDataBytes) const BYTE* pXmaData,  // Pointer to XMA block[s]
595
    DWORD nXmaDataBytes,                              // Size of pXmaData in bytes
596
    DWORD nStreamIndex,                               // Stream within which to seek
597
    DWORD nDesiredSample,                             // Sample sought
598
    __out DWORD* pnBitOffset,                         // Returns the bit offset within pXmaData of
599
                                                      // the frame containing the sample sought
600
    __out DWORD* pnSubFrame                           // Returns the subframe containing the sample
601
)
602
{
603
    DWORD nDesiredFrame = nDesiredSample / XMA_SAMPLES_PER_FRAME;
604
    DWORD nSubFrame = (nDesiredSample % XMA_SAMPLES_PER_FRAME) / XMA_SAMPLES_PER_SUBFRAME;
605
    DWORD nBitOffset = GetXmaFrameBitPosition(pXmaData, nXmaDataBytes, nStreamIndex, nDesiredFrame);
606
 
607
    XMA2DEFS_ASSERT(pnBitOffset);
608
    XMA2DEFS_ASSERT(pnSubFrame);
609
 
610
    if (nBitOffset)
611
    {
612
        *pnBitOffset = nBitOffset;
613
        *pnSubFrame = nSubFrame;
614
        return S_OK;
615
    }
616
    else
617
    {
618
        return E_FAIL;
619
    }
620
}
621
 
622
 
623
// GetXmaSampleRate: Obtains the legal XMA sample rate (24, 32, 44.1 or 48Khz)
624
// corresponding to a generic sample rate.
625
 
626
__inline DWORD GetXmaSampleRate(DWORD dwGeneralRate)
627
{
628
    DWORD dwXmaRate = 48000; // Default XMA rate for all rates above 44100Hz
629
 
630
    if (dwGeneralRate <= 24000)      dwXmaRate = 24000;
631
    else if (dwGeneralRate <= 32000) dwXmaRate = 32000;
632
    else if (dwGeneralRate <= 44100) dwXmaRate = 44100;
633
 
634
    return dwXmaRate;
635
}
636
 
637
 
638
// Functions to convert between WAVEFORMATEXTENSIBLE channel masks (combinations
639
// of the SPEAKER_xxx flags defined in audiodefs.h) and XMA channel masks (which
640
// are limited to eight possible speaker positions: left, right, center, low
641
// frequency, side left, side right, back left and back right).
642
 
643
__inline DWORD GetStandardChannelMaskFromXmaMask(BYTE bXmaMask)
644
{
645
    DWORD dwStandardMask = 0;
646
 
647
    if (bXmaMask & XMA_SPEAKER_LEFT)           dwStandardMask |= SPEAKER_FRONT_LEFT;
648
    if (bXmaMask & XMA_SPEAKER_RIGHT)          dwStandardMask |= SPEAKER_FRONT_RIGHT;
649
    if (bXmaMask & XMA_SPEAKER_CENTER)         dwStandardMask |= SPEAKER_FRONT_CENTER;
650
    if (bXmaMask & XMA_SPEAKER_LFE)            dwStandardMask |= SPEAKER_LOW_FREQUENCY;
651
    if (bXmaMask & XMA_SPEAKER_LEFT_SURROUND)  dwStandardMask |= SPEAKER_SIDE_LEFT;
652
    if (bXmaMask & XMA_SPEAKER_RIGHT_SURROUND) dwStandardMask |= SPEAKER_SIDE_RIGHT;
653
    if (bXmaMask & XMA_SPEAKER_LEFT_BACK)      dwStandardMask |= SPEAKER_BACK_LEFT;
654
    if (bXmaMask & XMA_SPEAKER_RIGHT_BACK)     dwStandardMask |= SPEAKER_BACK_RIGHT;
655
 
656
    return dwStandardMask;
657
}
658
 
659
__inline BYTE GetXmaChannelMaskFromStandardMask(DWORD dwStandardMask)
660
{
661
    BYTE bXmaMask = 0;
662
 
663
    if (dwStandardMask & SPEAKER_FRONT_LEFT)    bXmaMask |= XMA_SPEAKER_LEFT;
664
    if (dwStandardMask & SPEAKER_FRONT_RIGHT)   bXmaMask |= XMA_SPEAKER_RIGHT;
665
    if (dwStandardMask & SPEAKER_FRONT_CENTER)  bXmaMask |= XMA_SPEAKER_CENTER;
666
    if (dwStandardMask & SPEAKER_LOW_FREQUENCY) bXmaMask |= XMA_SPEAKER_LFE;
667
    if (dwStandardMask & SPEAKER_SIDE_LEFT)     bXmaMask |= XMA_SPEAKER_LEFT_SURROUND;
668
    if (dwStandardMask & SPEAKER_SIDE_RIGHT)    bXmaMask |= XMA_SPEAKER_RIGHT_SURROUND;
669
    if (dwStandardMask & SPEAKER_BACK_LEFT)     bXmaMask |= XMA_SPEAKER_LEFT_BACK;
670
    if (dwStandardMask & SPEAKER_BACK_RIGHT)    bXmaMask |= XMA_SPEAKER_RIGHT_BACK;
671
 
672
    return bXmaMask;
673
}
674
 
675
 
676
// LocalizeXma2Format: Modifies a XMA2WAVEFORMATEX structure in place to comply
677
// with the current platform's byte-ordering rules (little- or big-endian).
678
 
679
__inline HRESULT LocalizeXma2Format(__inout XMA2WAVEFORMATEX* pXma2Format)
680
{
681
    #define XMASWAP2BYTES(n) ((WORD)(((n) >> 8) | (((n) & 0xff) << 8)))
682
    #define XMASWAP4BYTES(n) ((DWORD)((n) >> 24 | (n) << 24 | ((n) & 0xff00) << 8 | ((n) & 0xff0000) >> 8))
683
 
684
    if (pXma2Format->wfx.wFormatTag == WAVE_FORMAT_XMA2)
685
    {
686
        return S_OK;
687
    }
688
    else if (XMASWAP2BYTES(pXma2Format->wfx.wFormatTag) == WAVE_FORMAT_XMA2)
689
    {
690
        pXma2Format->wfx.wFormatTag      = XMASWAP2BYTES(pXma2Format->wfx.wFormatTag);
691
        pXma2Format->wfx.nChannels       = XMASWAP2BYTES(pXma2Format->wfx.nChannels);
692
        pXma2Format->wfx.nSamplesPerSec  = XMASWAP4BYTES(pXma2Format->wfx.nSamplesPerSec);
693
        pXma2Format->wfx.nAvgBytesPerSec = XMASWAP4BYTES(pXma2Format->wfx.nAvgBytesPerSec);
694
        pXma2Format->wfx.nBlockAlign     = XMASWAP2BYTES(pXma2Format->wfx.nBlockAlign);
695
        pXma2Format->wfx.wBitsPerSample  = XMASWAP2BYTES(pXma2Format->wfx.wBitsPerSample);
696
        pXma2Format->wfx.cbSize          = XMASWAP2BYTES(pXma2Format->wfx.cbSize);
697
        pXma2Format->NumStreams          = XMASWAP2BYTES(pXma2Format->NumStreams);
698
        pXma2Format->ChannelMask         = XMASWAP4BYTES(pXma2Format->ChannelMask);
699
        pXma2Format->SamplesEncoded      = XMASWAP4BYTES(pXma2Format->SamplesEncoded);
700
        pXma2Format->BytesPerBlock       = XMASWAP4BYTES(pXma2Format->BytesPerBlock);
701
        pXma2Format->PlayBegin           = XMASWAP4BYTES(pXma2Format->PlayBegin);
702
        pXma2Format->PlayLength          = XMASWAP4BYTES(pXma2Format->PlayLength);
703
        pXma2Format->LoopBegin           = XMASWAP4BYTES(pXma2Format->LoopBegin);
704
        pXma2Format->LoopLength          = XMASWAP4BYTES(pXma2Format->LoopLength);
705
        pXma2Format->BlockCount          = XMASWAP2BYTES(pXma2Format->BlockCount);
706
        return S_OK;
707
    }
708
    else
709
    {
710
        return E_FAIL; // Not a recognizable XMA2 format
711
    }
712
 
713
    #undef XMASWAP2BYTES
714
    #undef XMASWAP4BYTES
715
}
716
 
717
 
718
#endif // #ifndef __XMA2DEFS_INCLUDED__