----------------------------------------
-- 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
}
}