On Xbox One XMA2 audio decompression is implemented in hardware, xWMA is not and requires software decoding. Both use the same compression algorithms but xWMA may provide a broader range of encoding formats. Generally speaking we would recommend encoding for XMA2 for performance and compression benefits, though perhaps some high fidelity music might sound better if rendered through xWMA - this would require some listening tests. Coding XMA2 through XAudio2 should be the simplest approach, though it can be coded directly to the hardware using the ACP commands.
Historically, both xWMA and XMA2 are based on the codecs developed for Windows Media Audio (WMA). Both xWMA and XMA2 have been developed specifically for Xbox games. XMA2 uses a smaller subset of the available codecs and parameters than does xWMA. Although they have both been developed for Xbox, they are not interchangeable - the headers for each file format are different. Nor are the formats compatible with PC versions of Windows. The codecs used for XMA2 and xWMA are slightly different, so each will have its own artifacts from the compression system used.
Encode audio data to XMA2 using XMA2 Encoder Tool, supplied as part of the XDK.
XMA2 files are .WAV files with the XMA2WAVEFORMATEX format header, and that contain an additional seek chunk within the seek location table.
The XMA2 format is Xbox 360 compatible, and the seek table needs to be ULONG byte-swapped for Xbox One. If the input is a WAVE file the output can be used without alteration.
To byte-swap the seek table use the following lines of code.
for(UINT32 i = 0;(i < xmaformat->BlockCount);i++)
{
rgpXMASeekTable[i] = _byteswap_ulong(rgpXMASeekTable[i]);
}
Consider adding the lines of code to your app to test the functionality, then perhaps writing a separate tool to perform the swap so no pre-processing is required of your app.
For Xbox One, all DMA input and output buffers used with flowgraphs, and all XMA content submitted to a source buffer, must be allocated using the ApuAlloc method, and freed using the ApuFree method, as shown in the following code. Note the use of the SHAPE_XMA_INPUT_BUFFER_ALIGNMENT flag to ensure correct block alignment.
HRESULT ApuVirtualAllocate(void** virtualAddress,UINT32 sizeInBytes)
{
DWORD dwsize = sizeInBytes;
DWORD change = 0;
if(FixBlockAlign((DWORD*)&sizeInBytes,SHAPE_XMA_INPUT_BUFFER_SIZE_ALIGNMENT,&change)) // returns TRUE if alignemt was needed else FALSE
{
return E_INVALIDARG;
}
return ApuAlloc(virtualAddress,NULL,sizeInBytes,SHAPE_XMA_INPUT_BUFFER_ALIGNMENT);
}
void ApuVirtualFree(void* virtualAddress)
{
if(virtualAddress)
{
ApuFree(virtualAddress);
}
}
BOOL FixBlockAlign(DWORD* pBYTES,DWORD BLOCKALIGN,DWORD* pChange)
{
if(pBYTES && (BLOCKALIGN > 1))
{
DWORD bytes = (*pBYTES);
(*pBYTES) /= BLOCKALIGN;
(*pBYTES) *= BLOCKALIGN;
if(pChange)
{
(*pChange) = bytes - (*pBYTES);
if((*pChange) > 0)
{
return TRUE;
}
}
}
return FALSE;
}
Refer to the documentation for the XMA2WAVEFORMATEX structure for details on how the fields of the structure are used with an XMA2 encoded file.
There is a long standing bug in the XMA hardware decoder (present also on the Xbox 360) that will require titles to provide a workaround if they use the AcpHal directly. XAudio2 does already provide the workaround. Until the XMA2Encoder tool is updated, take note of the following.
When decoding XMA bitstreams, if you are only using a single XMA input buffer, you can trigger an AXI bus error if the last 64 bytes XMA buffer contains encoded data.
Though it is rare an XMA bitstream to contain encoded data within the last 64 bytes, it needs to be handled to prevent the AXI bus error. Until the XMA2Encoder tool is updated to ensure that no encoded files contain encoded data in the last 64 bytes of the bitstream, you have several options to avoid this problem.
context->ptrRead1 = context->ptrRead0
Any one of the methods above will prevent the XMA prefetcher from reading an invalid address.