Ada计算机图形DirectX之xma2defs

----------------------------------------
-- File : xma2defs.ads                --
-- Translator:Dongfeng.Gu,2018/10/30  --
-- Mail: [email protected]                --
-- Progress:100%                      --
----------------------------------------

with win32;                           use win32;
with win32.Objbase;                   use win32.objbase;

with audiodefs;                       use audiodefs;

package xma2defs is


   function Shift_Left(A:dword;B:Natural) return dword with import,convention=>Intrinsic;
   function Lsh(A:dword;B:Natural) return dword is (Shift_Left(A,B));

   function Shift_Right(A:dword;B:Natural) return dword with import,convention=>Intrinsic;
   function Rsh(A:dword;B:Natural) return dword is (Shift_Right(A,B));


   XMA_OUTPUT_SAMPLE_BYTES : constant := 2;

   XMA_OUTPUT_SAMPLE_BITS : constant := (XMA_OUTPUT_SAMPLE_BYTES * 8);

   XMA_BYTES_PER_PACKET : constant := 2048;

   XMA_BITS_PER_PACKET : constant := (XMA_BYTES_PER_PACKET * 8);

   XMA_PACKET_HEADER_BYTES : constant := 4;

   XMA_PACKET_HEADER_BITS : constant := (XMA_PACKET_HEADER_BYTES * 8);

   XMA_SAMPLES_PER_FRAME : constant := 512;

   XMA_SAMPLES_PER_SUBFRAME : constant := 128;

   XMA_READBUFFER_MAX_PACKETS : constant := 4095;

   XMA_READBUFFER_MAX_BYTES : constant := (XMA_READBUFFER_MAX_PACKETS * XMA_BYTES_PER_PACKET);

   XMA_WRITEBUFFER_MAX_BYTES : constant := (31 * 256);

   XMA_WRITEBUFFER_BYTE_ALIGNMENT : constant := 256;

   XMA_MIN_SUBFRAMES_TO_DECODE : constant := 1;

   XMA_MAX_SUBFRAMES_TO_DECODE : constant := 8;

   XMA_OPTIMAL_SUBFRAMES_TO_DECODE : constant := 4;

   XMA_MAX_LOOPCOUNT : constant := 254;

   XMA_INFINITE_LOOP : constant := 255;

   WAVE_FORMAT_XMA2 : constant := 16#166#;

   type XMA2WAVEFORMATEX is record
      wfx: WAVEFORMATEX;
      NumStreams: WORD;
      ChannelMask: DWORD;
      SamplesEncoded: DWORD;
      BytesPerBlock: DWORD;
      PlayBegin: DWORD;
      PlayLength: DWORD;
      LoopBegin: DWORD;
      LoopLength: DWORD;
      LoopCount: BYTE;
      EncoderVersion: BYTE;
      BlockCount: WORD;
   end record;

   type PXMA2WAVEFORMATEX is access all XMA2WAVEFORMATEX;

   WAVE_FORMAT_XMA : constant := 16#0165#;

   XMA_SPEAKER_LEFT : constant := 16#01#;

   XMA_SPEAKER_RIGHT : constant := 16#02#;

   XMA_SPEAKER_CENTER : constant := 16#04#;

   XMA_SPEAKER_LFE : constant := 16#08#;

   XMA_SPEAKER_LEFT_SURROUND : constant := 16#10#;

   XMA_SPEAKER_RIGHT_SURROUND : constant := 16#20#;

   XMA_SPEAKER_LEFT_BACK : constant := 16#40#;

   XMA_SPEAKER_RIGHT_BACK : constant := 16#80#;

   type XMASTREAMFORMAT is record
      PsuedoBytesPerSec: DWORD;
      SampleRate: DWORD;
      LoopStart: DWORD;
      LoopEnd: DWORD;
      SubframeData: BYTE;
      Channels: BYTE;
      ChannelMask: WORD;
   end record;

   type XMASTREAMFORMAT_Array is array (Natural range<>) of XMASTREAMFORMAT;


   type XMAWAVEFORMAT is record
      FormatTag: WORD;
      BitsPerSample: WORD;
      EncodeOptions: WORD;
      LargestSkip: WORD;
      NumStreams: WORD;
      LoopCount: BYTE;
      Version: BYTE;
      XmaStreams: XMASTREAMFORMAT_Array(0..0);
   end record;

   type XMA2STREAMFORMAT is record
      Channels: BYTE;
      RESERVED: BYTE;
      ChannelMask: WORD;
   end record;

   type XMA2STREAMFORMAT_Array is array (Natural range<>) of XMA2STREAMFORMAT;

   type XMA2WAVEFORMAT is record
      Version: BYTE;
      NumStreams: BYTE;
      RESERVED: BYTE;
      LoopCount: BYTE;
      LoopBegin: DWORD;
      LoopEnd: DWORD;
      SampleRate: DWORD;
      EncodeOptions: DWORD;
      PsuedoBytesPerSec: DWORD;
      BlockSizeInBytes: DWORD;
      SamplesEncoded: DWORD;
      SamplesInSource: DWORD;
      BlockCount: DWORD;
      Streams: XMA2STREAMFORMAT_Array(0..0);
   end record;

   pragma Implicit_Packing;
   type XMA2PACKET is record
      FrameCount: Bits6;
      FrameOffsetInBits: Bits15;
      PacketMetaData: Bits3;
      PacketSkipCount: Bits8;
      XmaData: BYTE_Array(0..XMA_BYTES_PER_PACKET-5);
   end record;

   --
   -- inline funcitons,以下的函数在C源文件中的参数是const BYTE* ,函数的目标是取得位域值,故而如下修改
   --
   function GetXmaPacketFrameCount(pPacket:access constant XMA2PACKET) return dword is (dword(pPacket.FrameCount)) with Inline_Always;

   function GetXmaPacketFirstFrameOffsetInBits(pPacket:access constant XMA2PACKET) return dword is (dword(pPacket.FrameOffsetInBits)) with Inline_Always;

   function GetXmaPacketMetadata(pPacket:access constant XMA2PACKET) return dword is (dword(pPacket.PacketMetaData)) with Inline_Always;

   function GetXmaPacketSkipCount(pPacket:access constant XMA2PACKET) return dword is (dword(pPacket.PacketSkipCount)) with Inline_Always;

   XMA_BITS_IN_FRAME_LENGTH_FIELD:constant:=15;

   XMA_FINAL_FRAME_MARKER :constant:=16#7FFF#;

   --
   -- 以下的函数过程比较复杂,就拿来主义了
   --

   pragma Linker_Options("xma2defsAdaC.c");

   function GetXmaBlockContainingSample(nBlockCount:dword;pSeekTable:access constant dword;nDesiredSample:dword;pnBlockContainingSample:lpDWORD;pnSampleOffsetWithinBlock:LPDWORD) return HRESULT with Inline_Always,Import,external_name=>"GetXmaBlockContainingSample";

   function GetXmaFrameLengthInBits(pPacket:access constant BYTE;nBitPosition:DWORD) return DWORD with Inline_Always,Import,external_name=>"GetXmaFrameLengthInBits";

   function GetXmaFrameBitPosition(pXmaData:access constant BYTE;nXmaDataBytes:DWORD;nStreamIndex:DWORD;nDesiredFrame:DWORD) return DWORD with Inline_Always,Import,external_name=>"GetXmaFrameBitPosition";

   function GetLastXmaFrameBitPosition(pXmaData:access constant BYTE;nXmaDataBytes:DWORD;nStreamIndex:DWORD) return DWORD with Inline_Always,Import,external_name=>"GetLastXmaFrameBitPosition";

   function GetXmaDecodePositionForSample(pXmaData:access constant BYTE;nXmaDataBytes:DWORD;nStreamIndex:DWORD;nDesiredSample:DWORD;pnBitOffset:LPDWORD;pnSubFrame:LPDWORD) return HRESULT with Inline_Always,Import,external_name=>"GetXmaDecodePositionForSample";

   function GetXmaSampleRate(dwGeneralRate:DWORD) return DWORD with Inline_Always,Import,external_name=>"GetXmaSampleRate";

   function GetStandardChannelMaskFromXmaMask(bXmaMask:BYTE) return DWORD with Inline_Always,Import,external_name=>"GetStandardChannelMaskFromXmaMask";

   function GetXmaChannelMaskFromStandardMask(dwStandardMask:DWORD) return BYTE with Inline_Always,Import,external_name=>"GetXmaChannelMaskFromStandardMask";

   function LocalizeXma2Format(pXma2Format:access XMA2WAVEFORMATEX) return HRESULT with Inline_Always,Import,external_name=>"LocalizeXma2Format";




   --
   -- THE END.
   --







end xma2defs;

附带文件2:xma2defsAdaC.c

/* ----------------------------------------
 * -- File : xma2defsAdaC.c              --
 * -- Translator:Dongfeng.Gu,2018/10/30  --
 * -- Mail: [email protected]                --
 * -- Progress:100%                      --
 * ----------------------------------------
 */

#include <windows.h>
#include <objbase.h>

/***************************************************************************
 *  XMA constants
 ***************************************************************************/

// Size of the PCM samples produced by the XMA decoder
#define XMA_OUTPUT_SAMPLE_BYTES         2u
#define XMA_OUTPUT_SAMPLE_BITS          (XMA_OUTPUT_SAMPLE_BYTES * 8u)

// Size of an XMA packet
#define XMA_BYTES_PER_PACKET            2048u
#define XMA_BITS_PER_PACKET             (XMA_BYTES_PER_PACKET * 8u)

// Size of an XMA packet header
#define XMA_PACKET_HEADER_BYTES         4u
#define XMA_PACKET_HEADER_BITS          (XMA_PACKET_HEADER_BYTES * 8u)

// Sample blocks in a decoded XMA frame
#define XMA_SAMPLES_PER_FRAME           512u

// Sample blocks in a decoded XMA subframe
#define XMA_SAMPLES_PER_SUBFRAME        128u

// Maximum encoded data that can be submitted to the XMA decoder at a time
#define XMA_READBUFFER_MAX_PACKETS      4095u
#define XMA_READBUFFER_MAX_BYTES        (XMA_READBUFFER_MAX_PACKETS * XMA_BYTES_PER_PACKET)

// Maximum size allowed for the XMA decoder's output buffers
#define XMA_WRITEBUFFER_MAX_BYTES       (31u * 256u)

// Required byte alignment of the XMA decoder's output buffers
#define XMA_WRITEBUFFER_BYTE_ALIGNMENT  256u

// Decode chunk sizes for the XMA_PLAYBACK_INIT.subframesToDecode field
#define XMA_MIN_SUBFRAMES_TO_DECODE     1u
#define XMA_MAX_SUBFRAMES_TO_DECODE     8u
#define XMA_OPTIMAL_SUBFRAMES_TO_DECODE 4u

// LoopCount<255 means finite repetitions; LoopCount=255 means infinite looping
#define XMA_MAX_LOOPCOUNT               254u
#define XMA_INFINITE_LOOP               255u

#define XMA_SPEAKER_LEFT            0x01
    #define XMA_SPEAKER_RIGHT           0x02
    #define XMA_SPEAKER_CENTER          0x04
    #define XMA_SPEAKER_LFE             0x08
    #define XMA_SPEAKER_LEFT_SURROUND   0x10
    #define XMA_SPEAKER_RIGHT_SURROUND  0x20
    #define XMA_SPEAKER_LEFT_BACK       0x40
    #define XMA_SPEAKER_RIGHT_BACK      0x80
    
    #define SPEAKER_FRONT_LEFT            0x00000001
    #define SPEAKER_FRONT_RIGHT           0x00000002
    #define SPEAKER_FRONT_CENTER          0x00000004
    #define SPEAKER_LOW_FREQUENCY         0x00000008
    #define SPEAKER_BACK_LEFT             0x00000010
    #define SPEAKER_BACK_RIGHT            0x00000020
    #define SPEAKER_FRONT_LEFT_OF_CENTER  0x00000040
    #define SPEAKER_FRONT_RIGHT_OF_CENTER 0x00000080
    #define SPEAKER_BACK_CENTER           0x00000100
    #define SPEAKER_SIDE_LEFT             0x00000200
    #define SPEAKER_SIDE_RIGHT            0x00000400
    #define SPEAKER_TOP_CENTER            0x00000800
    #define SPEAKER_TOP_FRONT_LEFT        0x00001000
    #define SPEAKER_TOP_FRONT_CENTER      0x00002000
    #define SPEAKER_TOP_FRONT_RIGHT       0x00004000
    #define SPEAKER_TOP_BACK_LEFT         0x00008000
    #define SPEAKER_TOP_BACK_CENTER       0x00010000
    #define SPEAKER_TOP_BACK_RIGHT        0x00020000
    #define SPEAKER_RESERVED              0x7FFC0000
    #define SPEAKER_ALL                   0x80000000
    
    #define SPEAKER_MONO             (SPEAKER_FRONT_CENTER)
    #define SPEAKER_STEREO           (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT)
    #define SPEAKER_2POINT1          (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_LOW_FREQUENCY)
    #define SPEAKER_SURROUND         (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_BACK_CENTER)
    #define SPEAKER_QUAD             (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT)
    #define SPEAKER_4POINT1          (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT)
    #define SPEAKER_5POINT1          (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT)
    #define SPEAKER_7POINT1          (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_FRONT_LEFT_OF_CENTER | SPEAKER_FRONT_RIGHT_OF_CENTER)
    #define SPEAKER_5POINT1_SURROUND (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT)
    #define SPEAKER_7POINT1_SURROUND (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_SIDE_LEFT  | SPEAKER_SIDE_RIGHT)

    #define WAVE_FORMAT_XMA2 0x166
    
typedef struct XMA2WAVEFORMATEX
{
  WAVEFORMATEX wfx;
  // Meaning of the WAVEFORMATEX fields here:
  //    wFormatTag;        // Audio format type; always WAVE_FORMAT_XMA2
  //    nChannels;         // Channel count of the decoded audio
  //    nSamplesPerSec;    // Sample rate of the decoded audio
  //    nAvgBytesPerSec;   // Used internally by the XMA encoder
  //    nBlockAlign;       // Decoded sample size; channels * wBitsPerSample / 8
  //    wBitsPerSample;    // Bits per decoded mono sample; always 16 for XMA
  //    cbSize;            // Size in bytes of the rest of this structure (34)

  WORD  NumStreams;        // Number of audio streams (1 or 2 channels each)
  DWORD ChannelMask;       // Spatial positions of the channels in this file,
  // stored as SPEAKER_xxx values (see audiodefs.h)
  DWORD SamplesEncoded;    // Total number of PCM samples the file decodes to
  DWORD BytesPerBlock;     // XMA block size (but the last one may be shorter)
  DWORD PlayBegin;         // First valid sample in the decoded audio
  DWORD PlayLength;        // Length of the valid part of the decoded audio
  DWORD LoopBegin;         // Beginning of the loop region in decoded sample terms
  DWORD LoopLength;        // Length of the loop region in decoded sample terms
  BYTE  LoopCount;         // Number of loop repetitions; 255 = infinite
  BYTE  EncoderVersion;    // Version of XMA encoder that generated the file
  WORD  BlockCount;        // XMA blocks in file (and entries in its seek table)
} XMA2WAVEFORMATEX, *PXMA2WAVEFORMATEX;



__inline DWORD GetXmaPacketFrameCount(const BYTE* pPacket)
{
  return (DWORD)(pPacket[0] >> 2);
}

__inline DWORD GetXmaPacketFirstFrameOffsetInBits(const BYTE* pPacket)
{
  return ((DWORD)(pPacket[0] & 0x3) << 13) |
  ((DWORD)(pPacket[1]) << 5) |
  ((DWORD)(pPacket[2]) >> 3);
}

__inline DWORD GetXmaPacketMetadata(const BYTE* pPacket)
{
  return (DWORD)(pPacket[2] & 0x7);
}

__inline DWORD GetXmaPacketSkipCount(const BYTE* pPacket)
{
  return (DWORD)(pPacket[3]);
}


#ifndef XMA2DEFS_ASSERT
    #ifdef ASSERT
        #define XMA2DEFS_ASSERT ASSERT
    #else
        #define XMA2DEFS_ASSERT(a)
    #endif
#endif

__inline HRESULT GetXmaBlockContainingSample
  (
  DWORD nBlockCount,
  const DWORD* pSeekTable,
  DWORD nDesiredSample,
  DWORD* pnBlockContainingSample,
  DWORD* pnSampleOffsetWithinBlock
)
{
  DWORD nPreviousTotalSamples = 0;
  DWORD nBlock;
  DWORD nTotalSamplesSoFar;

  XMA2DEFS_ASSERT(pSeekTable);
  XMA2DEFS_ASSERT(pnBlockContainingSample);
  XMA2DEFS_ASSERT(pnSampleOffsetWithinBlock);

  for (nBlock = 0; nBlock < nBlockCount; ++nBlock)
    {
      nTotalSamplesSoFar = pSeekTable[nBlock];
      if (nTotalSamplesSoFar > nDesiredSample)
    {
     *pnBlockContainingSample = nBlock;
     *pnSampleOffsetWithinBlock = nDesiredSample - nPreviousTotalSamples;
     return S_OK;
    }
      nPreviousTotalSamples = nTotalSamplesSoFar;
    }

  return E_FAIL;
}




__inline DWORD GetXmaFrameLengthInBits
  (
    
  const BYTE* pPacket,
  DWORD nBitPosition
)
{
  DWORD nRegion;
  DWORD nBytePosition = nBitPosition / 8;
  DWORD nBitOffset = nBitPosition % 8;

  if (nBitOffset < 2) // Only need to read 2 bytes (and might not be safe to read more)
    {
      nRegion = (DWORD)(pPacket[nBytePosition+0]) << 8 |
      (DWORD)(pPacket[nBytePosition+1]);
      return (nRegion >> (1 - nBitOffset)) & 0x7FFF;  // Last 15 bits
    }
  else // Need to read 3 bytes
    {
      nRegion = (DWORD)(pPacket[nBytePosition+0]) << 16 |
      (DWORD)(pPacket[nBytePosition+1]) << 8 |
      (DWORD)(pPacket[nBytePosition+2]);
      return (nRegion >> (9 - nBitOffset)) & 0x7FFF;  // Last 15 bits
    }
}


// GetXmaFrameBitPosition: Calculates the bit offset of a given frame within
// an XMA block or set of blocks.  Returns 0 on failure.

__inline DWORD GetXmaFrameBitPosition
  (
  const BYTE* pXmaData,  // Pointer to XMA block[s]
  DWORD nXmaDataBytes,                              // Size of pXmaData in bytes
  DWORD nStreamIndex,                               // Stream within which to seek
  DWORD nDesiredFrame                               // Frame sought
)
{
  const BYTE* pCurrentPacket;
  DWORD nPacketsExamined = 0;
  DWORD nFrameCountSoFar = 0;
  DWORD nFramesToSkip;
  DWORD nFrameBitOffset;

  XMA2DEFS_ASSERT(pXmaData);
  XMA2DEFS_ASSERT(nXmaDataBytes % XMA_BYTES_PER_PACKET == 0);

  // Get the first XMA packet belonging to the desired stream, relying on the
  // fact that the first packets for each stream are in consecutive order at
  // the beginning of an XMA block.

  pCurrentPacket = pXmaData + nStreamIndex * XMA_BYTES_PER_PACKET;
  for (;;)
    {
      // If we have exceeded the size of the XMA data, return failure
      if (pCurrentPacket + XMA_BYTES_PER_PACKET > pXmaData + nXmaDataBytes)
    {
     return 0;
    }

      // If the current packet contains the frame we are looking for...
      if (nFrameCountSoFar + GetXmaPacketFrameCount(pCurrentPacket) > nDesiredFrame)
    {
     // See how many frames in this packet we need to skip to get to it
     XMA2DEFS_ASSERT(nDesiredFrame >= nFrameCountSoFar);
     nFramesToSkip = nDesiredFrame - nFrameCountSoFar;

     // Get the bit offset of the first frame in this packet
     nFrameBitOffset = XMA_PACKET_HEADER_BITS + GetXmaPacketFirstFrameOffsetInBits(pCurrentPacket);

     // Advance nFrameBitOffset to the frame of interest
     while (nFramesToSkip--)
       {
         nFrameBitOffset += GetXmaFrameLengthInBits(pCurrentPacket, nFrameBitOffset);
       }

     // The bit offset to return is the number of bits from pXmaData to
     // pCurrentPacket plus the bit offset of the frame of interest
     return (DWORD)(pCurrentPacket - pXmaData) * 8 + nFrameBitOffset;
    }

      // If we haven't found the right packet yet, advance our counters
      ++nPacketsExamined;
      nFrameCountSoFar += GetXmaPacketFrameCount(pCurrentPacket);

      // And skip to the next packet belonging to the same stream
      pCurrentPacket += XMA_BYTES_PER_PACKET * (GetXmaPacketSkipCount(pCurrentPacket) + 1);
    }
}


// GetLastXmaFrameBitPosition: Calculates the bit offset of the last complete
// frame in an XMA block or set of blocks.

__inline DWORD GetLastXmaFrameBitPosition
  (
  const BYTE* pXmaData,  // Pointer to XMA block[s]
  DWORD nXmaDataBytes,                              // Size of pXmaData in bytes
  DWORD nStreamIndex                                // Stream within which to seek
)
{
  const BYTE* pLastPacket;
  DWORD nBytesToNextPacket;
  DWORD nFrameBitOffset;
  DWORD nFramesInLastPacket;

  XMA2DEFS_ASSERT(pXmaData);
  XMA2DEFS_ASSERT(nXmaDataBytes % XMA_BYTES_PER_PACKET == 0);
  XMA2DEFS_ASSERT(nXmaDataBytes >= XMA_BYTES_PER_PACKET * (nStreamIndex + 1));

  // Get the first XMA packet belonging to the desired stream, relying on the
  // fact that the first packets for each stream are in consecutive order at
  // the beginning of an XMA block.
  pLastPacket = pXmaData + nStreamIndex * XMA_BYTES_PER_PACKET;

  // Search for the last packet belonging to the desired stream
  for (;;)
    {
      nBytesToNextPacket = XMA_BYTES_PER_PACKET * (GetXmaPacketSkipCount(pLastPacket) + 1);
      XMA2DEFS_ASSERT(nBytesToNextPacket);
      if (pLastPacket + nBytesToNextPacket + XMA_BYTES_PER_PACKET > pXmaData + nXmaDataBytes)
    {
     break;  // The next packet would extend beyond the end of pXmaData
    }
      pLastPacket += nBytesToNextPacket;
    }

  // The last packet can sometimes have no seekable frames, in which case we
  // have to use the previous one
  if (GetXmaPacketFrameCount(pLastPacket) == 0)
    {
      pLastPacket -= nBytesToNextPacket;
    }

  // Found the last packet.  Get the bit offset of its first frame.
  nFrameBitOffset = XMA_PACKET_HEADER_BITS + GetXmaPacketFirstFrameOffsetInBits(pLastPacket);

  // Traverse frames until we reach the last one
  nFramesInLastPacket = GetXmaPacketFrameCount(pLastPacket);
  while (--nFramesInLastPacket)
    {
      nFrameBitOffset += GetXmaFrameLengthInBits(pLastPacket, nFrameBitOffset);
    }

  // The bit offset to return is the number of bits from pXmaData to
  // pLastPacket plus the offset of the last frame in this packet.
  return (DWORD)(pLastPacket - pXmaData) * 8 + nFrameBitOffset;
}


// GetXmaDecodePositionForSample: Obtains the information needed to make the
// decoder generate audio starting at a given sample position relative to the
// beginning of the given XMA block: the bit offset of the appropriate frame,
// and the right subframe within that frame.  This data can be passed directly
// to the XMAPlaybackSetDecodePosition function.

__inline HRESULT GetXmaDecodePositionForSample
  (
  const BYTE* pXmaData,  // Pointer to XMA block[s]
  DWORD nXmaDataBytes,                              // Size of pXmaData in bytes
  DWORD nStreamIndex,                               // Stream within which to seek
  DWORD nDesiredSample,                             // Sample sought
  DWORD* pnBitOffset,                         // Returns the bit offset within pXmaData of
  // the frame containing the sample sought
  DWORD* pnSubFrame                           // Returns the subframe containing the sample
)
{
  DWORD nDesiredFrame = nDesiredSample / XMA_SAMPLES_PER_FRAME;
  DWORD nSubFrame = (nDesiredSample % XMA_SAMPLES_PER_FRAME) / XMA_SAMPLES_PER_SUBFRAME;
  DWORD nBitOffset = GetXmaFrameBitPosition(pXmaData, nXmaDataBytes, nStreamIndex, nDesiredFrame);

  XMA2DEFS_ASSERT(pnBitOffset);
  XMA2DEFS_ASSERT(pnSubFrame);

  if (nBitOffset)
    {
      *pnBitOffset = nBitOffset;
      *pnSubFrame = nSubFrame;
      return S_OK;
    }
  else
    {
      return E_FAIL;
    }
}


// GetXmaSampleRate: Obtains the legal XMA sample rate (24, 32, 44.1 or 48Khz)
// corresponding to a generic sample rate.

__inline DWORD GetXmaSampleRate(DWORD dwGeneralRate)
{
  DWORD dwXmaRate = 48000; // Default XMA rate for all rates above 44100Hz

  if (dwGeneralRate <= 24000)      dwXmaRate = 24000;
  else if (dwGeneralRate <= 32000) dwXmaRate = 32000;
  else if (dwGeneralRate <= 44100) dwXmaRate = 44100;

  return dwXmaRate;
}


// Functions to convert between WAVEFORMATEXTENSIBLE channel masks (combinations
// of the SPEAKER_xxx flags defined in audiodefs.h) and XMA channel masks (which
// are limited to eight possible speaker positions: left, right, center, low
// frequency, side left, side right, back left and back right).

__inline DWORD GetStandardChannelMaskFromXmaMask(BYTE bXmaMask)
{
  DWORD dwStandardMask = 0;

  if (bXmaMask & XMA_SPEAKER_LEFT)           dwStandardMask |= SPEAKER_FRONT_LEFT;
  if (bXmaMask & XMA_SPEAKER_RIGHT)          dwStandardMask |= SPEAKER_FRONT_RIGHT;
  if (bXmaMask & XMA_SPEAKER_CENTER)         dwStandardMask |= SPEAKER_FRONT_CENTER;
  if (bXmaMask & XMA_SPEAKER_LFE)            dwStandardMask |= SPEAKER_LOW_FREQUENCY;
  if (bXmaMask & XMA_SPEAKER_LEFT_SURROUND)  dwStandardMask |= SPEAKER_SIDE_LEFT;
  if (bXmaMask & XMA_SPEAKER_RIGHT_SURROUND) dwStandardMask |= SPEAKER_SIDE_RIGHT;
  if (bXmaMask & XMA_SPEAKER_LEFT_BACK)      dwStandardMask |= SPEAKER_BACK_LEFT;
  if (bXmaMask & XMA_SPEAKER_RIGHT_BACK)     dwStandardMask |= SPEAKER_BACK_RIGHT;

  return dwStandardMask;
}

__inline BYTE GetXmaChannelMaskFromStandardMask(DWORD dwStandardMask)
{
  BYTE bXmaMask = 0;

  if (dwStandardMask & SPEAKER_FRONT_LEFT)    bXmaMask |= XMA_SPEAKER_LEFT;
  if (dwStandardMask & SPEAKER_FRONT_RIGHT)   bXmaMask |= XMA_SPEAKER_RIGHT;
  if (dwStandardMask & SPEAKER_FRONT_CENTER)  bXmaMask |= XMA_SPEAKER_CENTER;
  if (dwStandardMask & SPEAKER_LOW_FREQUENCY) bXmaMask |= XMA_SPEAKER_LFE;
  if (dwStandardMask & SPEAKER_SIDE_LEFT)     bXmaMask |= XMA_SPEAKER_LEFT_SURROUND;
  if (dwStandardMask & SPEAKER_SIDE_RIGHT)    bXmaMask |= XMA_SPEAKER_RIGHT_SURROUND;
  if (dwStandardMask & SPEAKER_BACK_LEFT)     bXmaMask |= XMA_SPEAKER_LEFT_BACK;
  if (dwStandardMask & SPEAKER_BACK_RIGHT)    bXmaMask |= XMA_SPEAKER_RIGHT_BACK;

  return bXmaMask;
}


// LocalizeXma2Format: Modifies a XMA2WAVEFORMATEX structure in place to comply
// with the current platform's byte-ordering rules (little- or big-endian).

__inline HRESULT LocalizeXma2Format(XMA2WAVEFORMATEX* pXma2Format)
{
    #define XMASWAP2BYTES(n) ((WORD)(((n) >> 8) | (((n) & 0xff) << 8)))
    #define XMASWAP4BYTES(n) ((DWORD)((n) >> 24 | (n) << 24 | ((n) & 0xff00) << 8 | ((n) & 0xff0000) >> 8))

  if (pXma2Format->wfx.wFormatTag == WAVE_FORMAT_XMA2)
    {
      return S_OK;
    }
  else if (XMASWAP2BYTES(pXma2Format->wfx.wFormatTag) == WAVE_FORMAT_XMA2)
    {
      pXma2Format->wfx.wFormatTag      = XMASWAP2BYTES(pXma2Format->wfx.wFormatTag);
      pXma2Format->wfx.nChannels       = XMASWAP2BYTES(pXma2Format->wfx.nChannels);
      pXma2Format->wfx.nSamplesPerSec  = XMASWAP4BYTES(pXma2Format->wfx.nSamplesPerSec);
      pXma2Format->wfx.nAvgBytesPerSec = XMASWAP4BYTES(pXma2Format->wfx.nAvgBytesPerSec);
      pXma2Format->wfx.nBlockAlign     = XMASWAP2BYTES(pXma2Format->wfx.nBlockAlign);
      pXma2Format->wfx.wBitsPerSample  = XMASWAP2BYTES(pXma2Format->wfx.wBitsPerSample);
      pXma2Format->wfx.cbSize          = XMASWAP2BYTES(pXma2Format->wfx.cbSize);
      pXma2Format->NumStreams          = XMASWAP2BYTES(pXma2Format->NumStreams);
      pXma2Format->ChannelMask         = XMASWAP4BYTES(pXma2Format->ChannelMask);
      pXma2Format->SamplesEncoded      = XMASWAP4BYTES(pXma2Format->SamplesEncoded);
      pXma2Format->BytesPerBlock       = XMASWAP4BYTES(pXma2Format->BytesPerBlock);
      pXma2Format->PlayBegin           = XMASWAP4BYTES(pXma2Format->PlayBegin);
      pXma2Format->PlayLength          = XMASWAP4BYTES(pXma2Format->PlayLength);
      pXma2Format->LoopBegin           = XMASWAP4BYTES(pXma2Format->LoopBegin);
      pXma2Format->LoopLength          = XMASWAP4BYTES(pXma2Format->LoopLength);
      pXma2Format->BlockCount          = XMASWAP2BYTES(pXma2Format->BlockCount);
      return S_OK;
    }
  else
    {
      return E_FAIL; // Not a recognizable XMA2 format
    }


}

猜你喜欢

转载自blog.csdn.net/adacore/article/details/83541641