Subversion Repositories Games.Chess Giants

Rev

Blame | Last modification | View Log | Download | RSS feed

  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__
  719.