> ## Documentation Index
> Fetch the complete documentation index at: https://devdocs.xbox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# XMA2 概述

> XMA2 硬件音频解压在 XBOX One 上的工作方式，以及在 XAudio2 游戏音频内容中与 xWMA 软件解码的对比。

在 XBOX One 上，XMA2 音频解压由硬件实现。而 xWMA 不是，需要软件解码。XMA2 和 xWMA 使用相同的压缩算法，但 xWMA 提供了更广的编码格式选择。出于性能和压缩率的考虑，建议编码为 XMA2；但请注意，某些高保真音乐通过 xWMA 渲染可能听感更好——这需要进行主观听测试。通过 `XAudio2` 编写 XMA2 应该是最简单的方式，但也可以直接使用音频控制处理器 (Audio Control Processor, ACP) 命令为硬件编写 XMA2 代码。

<Note>xWMA 和 XMA2 都源自为 Windows Media Audio (WMA) 开发的编解码器，且都专为 XBOX 游戏开发。XMA2 使用的可用编解码器与参数子集比 xWMA 使用的更小。虽然二者都为 XBOX 开发，但并不可互换：它们的文件头不同，格式与 PC 版 Windows 不兼容。XMA2 与 xWMA 所用的编解码器也略有差异，因此各自会有各自所用压缩系统带来的伪影。</Note>

本主题涵盖以下内容：

* [XMA2 编码](#ID4E3)
* [XMA2 AXI 总线错误](#ID4ENC)

<a id="ID4E3" />

## XMA2 编码

使用作为 Microsoft Game Development Kit (GDK) 一部分提供的 [XMA2 编码器工具](/build/console-features/audio/tools/xma2encodertool) 将音频数据编码为 XMA2。XMA2 文件是带有 [XMA2WAVEFORMATEX](/reference/audio/xma2defs/structs/xma2waveformatex) 格式头以及 `Seek` 位置表中额外 `seek` 块的 .wav 文件。

XMA2 格式与 XBOX 360 兼容，但对 XBOX One，`Seek` 表需要按 `ULONG` 进行字节交换。如果输入本身就是 .wav 文件，输出可以直接使用无需修改。

要对 `Seek` 表进行字节交换，请使用以下代码。

```cpp theme={null}
      for(UINT32 i = 0;(i < xmaformat->BlockCount);i++)
      {
      rgpXMASeekTable[i] = _byteswap_ulong(rgpXMASeekTable[i]);
      }  
```

可以先把这段代码加到你的应用中以验证功能，然后再考虑单独写一个工具来完成交换，让你的应用不必进行预处理。

对于 XBOX One，用于流程图的所有直接内存访问 (DMA) 输入输出缓冲区，以及提交给源缓冲区的所有 XMA 内容，都必须使用 [ApuAlloc](/reference/audio/apu/functions/apualloc) 方法分配，并使用 [ApuFree](/reference/audio/apu/functions/apufree) 方法释放，如下所示。注意 `SHAPE_XMA_INPUT_BUFFER_ALIGNMENT` 标志用于确保块正确对齐。

```cpp theme={null}
      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 an alignment was needed; else, returns 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&mdash;(*pBYTES);
            if((*pChange) > 0)
            {
              return TRUE;
            }
          }
        }
        return FALSE;
      }  
```

有关在 XMA2 编码文件中使用该结构字段的详细信息，请参见 [XMA2WAVEFORMATEX](/reference/audio/xma2defs/structs/xma2waveformatex) 结构。

<a id="ID4ENC" />

## XMA2 AXI 总线错误

XMA 硬件解码器（以及 XBOX 360）中长期存在一个 bug：如果游戏直接使用 `AcpHal`，则必须自行采取变通措施。`XAudio2` 已经内置了变通方案。不过，在 XMA2 编码器工具更新之前，请注意以下信息。

当解码 XMA 位流且只使用单个 XMA 输入缓冲区时，如果 XMA 缓冲区末尾的 64 字节中含有已编码数据，就有可能触发 AXI 总线错误。XMA 位流很少在末尾 64 字节内包含已编码数据，但仍必须处理这种情况以防止 AXI 总线错误。在 XMA2 编码器工具更新以确保不再有任何已编码文件在位流末尾 64 字节内包含已编码数据之前，你可以通过以下方法之一避免此问题。

* 始终使用两个 XMA 输入缓冲区，且永远不要将任一输入缓冲区的指针设置为无效值。

* 将未使用的输入缓冲区的指针设为与另一个输入缓冲区的指针相同，即使你不启用另一个缓冲区。示例如下。

```cpp theme={null}
      context->ptrRead1 = context->ptrRead0  
```

* 在生成内容时使用一个离线工具扫描你的 XMA 文件。如果已编码 XMA 位流末尾的 64 字节中有任何一个字节不是 0xFF，则重新编码该文件。

以上任何一种方法都可防止 XMA 预取器读取无效地址。

<a id="ID4EFD" />

## 参考 API 文档

* [APU (API 内容)](/reference/audio/apu/apu_members)
  * Functions
    * [ApuAlloc](/reference/audio/apu/functions/apualloc)
    * [ApuFree](/reference/audio/apu/functions/apufree)
* [XMA2Defs (API 内容)](/reference/audio/xma2defs/xma2defs_members)
  * Structures
    * [XMA2WAVEFORMATEX](/reference/audio/xma2defs/structs/xma2waveformatex)

## 另请参阅

[XMA2 编码器工具](/build/console-features/audio/tools/xma2encodertool)


## Related topics

- [XMA2WAVEFORMATEX](/zh-CN/reference/audio/xma2defs/structs/xma2waveformatex.md)
- [XMA2STREAMFORMAT](/zh-CN/reference/audio/xma2defs/structs/xma2streamformat.md)
- [XMA2WAVEFORMAT](/zh-CN/reference/audio/xma2defs/structs/xma2waveformat.md)
- [XMA2PACKET](/zh-CN/reference/audio/xma2defs/structs/xma2packet.md)
- [XMA2Defs](/zh-CN/reference/audio/xma2defs/xma2defs_members.md)
