> ## 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.

# 使用 XAPU API 進行單一串流 Opus 音訊解碼

> 使用 XAPU API 進行單一串流 Opus 音訊解碼的概觀

在本主題中，我們將使用 Microsoft Game Development Kit (GDK) 隨附的其中一個範例，逐步說明如何在 XBOX Series X 裝置上使用 Opus 硬體加速解碼的預期程式碼流程。此範例名為 `DecodeOne.cpp`，涵蓋單一用戶端的單一串流解碼案例。

## 音訊硬體連線與啟動

解碼一開始會透過 [XApuConnect](/zh-TW/reference/audio/xapu/functions/xapuconnect) 與硬體加速單元建立連線。呼叫端會使用 [XApuConnectInputParameters](/zh-TW/reference/audio/xapu/structs/xapuconnectinputparameters) 設定連線需求，以設定下列項目：

1. 處理類型 (在此例中為 [XApuProcessType::DecodeOpus](/zh-TW/reference/audio/xapu/enums/xapuprocesstype))。
2. 串流數目 (在此例中為 1)。
3. 傳遞和擷取輸入與輸出資料所需的記憶體總量，在此例中，`MaxInputBufferLength` 為 1024 (必須等於或大於串流中最大的 Opus 封包)。此數字也必須是 16 的倍數，以及 7680。這是 48 K 下 20 毫秒的資料，即 `MaxOutputBufferLength` 為 960 × 2 × sizeof(float) = 7680。輸出也必須是 16 的倍數。

如果此呼叫成功，[XApuConnectOutputParameters::baseData](/zh-TW/reference/audio/xapu/structs/xapuconnectoutputparameters) 參數會指向由作業系統配置的記憶體位置，其配置方式讓硬體加速單元可以直接存取，而無須額外封送處理或複製。呼叫端應使用此記憶體來傳遞輸入資料並擷取輸出資料。下列簡易記憶體管理員範例可用來設定 [XApuConnectInputParameters](/zh-TW/reference/audio/xapu/structs/xapuconnectinputparameters)，並將 [XApuConnectOutputParameters::baseData](/zh-TW/reference/audio/xapu/structs/xapuconnectoutputparameters) 分割成兩個指標：一個用於輸入資料，另一個用於輸出資料。

```cpp theme={null}
class DecodeOneSimpleMemoryManager
{
public:
    static const uint32_t MaxStreamCount = 1;
    const uint32_t MaxInputBufferLength = 1024; // Must be equal to or greater than the largest Opus packet in the stream. The number must also be a multiple of 16.
    const uint32_t MaxOutputBufferLength = 7680; // This is 20 ms of data at 48 K, which is 960 x 2 x sizeof(float) = 7680 for MaxOutputBufferLength. The output also needs to be multiple of 16.

private:
    XApuConnectInputParameters _inParam = {
        XApuProcessType::DecodeOpus,
        MaxStreamCount,
        1,
        MaxStreamCount * (MaxInputBufferLength + MaxOutputBufferLength),
        0,
        XApuConnectOptions::None };

    XApuConnectOutputParameters _outParam = {};

public:
    XApuConnectInputParameters * const GetConnectParametersRef() {
        return &_inputParam;
    }

    XApuConnectOutputParameters * const GetConnectionDataRef() {
        return &_outParam;
    }

    uint8_t* GetRawInputBuffer(uint32_t& maxByteCount) {
        maxByteCount = MaxInputBufferLength;
        return reinterpret_cast<uint8_t*>(_outParam.baseData);
    }

    uint8_t* GetRawOutputBuffer(uint32_t& maxByteCount) {
        maxByteCount = MaxOutputBufferLength;
        return reinterpret_cast<uint8_t*>(_outParam.baseData) + MaxInputBufferLength;
    }
};
```

以下是建立連線第一個步驟的程式碼範例。

```cpp theme={null}
XApuConnectInputParameters * const connectParameters = memoryManager.GetConnectParametersRef();
XApuConnectOutputParameters * const connectionData = memoryManager.GetConnectionDataRef();
hr = XApuConnect(connectParameters, connectionData, &xapuHandle);
```

## 啟用與停用串流

與裝置建立連線之後，呼叫端應傳送串流啟用命令以啟用單一解碼引擎。呼叫端必須指定串流索引與聲道數。僅允許單聲道或立體聲串流。

呼叫端應呼叫 [XApuDequeueResult](/zh-TW/reference/audio/xapu/functions/xapudequeueresult) 以取得啟用結果。由於此範例中的 [XApuConnectInputParameters::maxQueuedCommandsPerStream](/zh-TW/reference/audio/xapu/structs/xapuconnectinputparameters) 設為 1，呼叫端必須等候每個結果後才能提交下一個命令。這包括 `Activate`、`Process` 與 `Deactivate` 命令 (如需詳細資料，請參閱 [XApuCommandType](/zh-TW/reference/audio/xapu/enums/xapucommandtype))。

以下是啟用一個串流的程式碼。

```cpp theme={null}
XApuDecodeConvertActivateCommand command = {};
command.id.type = XApuCommandType::Activate;
command.id.streamIndex = 0;
command.id.sequence = 0;
command.channelCount = channelCount;

hr = XApuEnqueueCommand(xapuHandle, &command.id, nullptr);
XApuResult result = {};

do {
    hr = XApuDequeueResult(handle, &result);
} while (hr == XAPU_E_PENDING_RESULTS);
```

收到啟用結果之後，呼叫端就可以開始提交 Opus 封包進行解碼。這應透過 [XApuCommandType::Process](/zh-TW/reference/audio/xapu/enums/xapucommandtype) 命令來完成。針對每個 `Process` 命令，呼叫端必須執行下列動作：

1. 在輸入緩衝區中填入剛好一個 Opus 封包。
2. 指定封包的長度。
3. 提供輸出緩衝區的位置，音訊硬體加速單元會在該緩衝區中填入解碼後的資料。
4. 指定輸出緩衝區的最大長度。

此外，呼叫端必須指定 `streamIndex` 與 `frameCount` 值。如果需要將所有解碼資料複製到輸出緩衝區，可以將 `frameCount` 值設為等於或大於封包中所編碼畫面數的任何值 (例如，對於 20 毫秒的封包，`frameCount` 可設定在 960 與 0xFFFFFFFF 之間)。

```cpp theme={null}
XApuDecodeConvertCommand command = {};
command.id.streamIndex = 0;
command.id.type = XApuCommandType::Process;
command.id.sequence = packetIndex;
command.frameCount = 0xFFFFFFFF;
command.inputData = memoryManager.GetRawInputBuffer(inputMaxByteCount);
command.inputDataLength = packetLength;
command.outputData = memoryManager.GetRawOutputBuffer(outputMaxByteCount);
command.maxOutputDataLength = outputMaxByteCount;

hr = XApuEnqueueCommand(xapuHandle, &command.id, nullptr);
```

接下來，應呼叫 [XApuDequeueResult](/zh-TW/reference/audio/xapu/functions/xapudequeueresult) 以取得封包的解碼輸出。成功擷取 [XApuResult](/zh-TW/reference/audio/xapu/structs/xapuresult) 之後，輸出資料會儲存在 `result.outputData` 中。處理完畢後，應以 [XApuCommandType::Process](/zh-TW/reference/audio/xapu/enums/xapucommandtype) 命令再次呼叫 [XApuEnqueueCommand](/zh-TW/reference/audio/xapu/functions/xapuenqueuecommand)，提交下一個封包進行解碼。

```cpp theme={null}
XApuResult result = {};

do {
    hr = XApuDequeueResult(handle, &result);
    if (SUCCEEDED(hr))
    {
         if (result.id.type == XApuCommandType::Process)
         {
              fwrite(result.outputData, 1, result.outputDataLength, fileOutput);
         }
    }
    
} while (hr == XAPU_E_PENDING_RESULTS);
```

串流中的所有封包都解碼完成後，應提交 [XApuCommandType::Deactivate](/zh-TW/reference/audio/xapu/enums/xapucommandtype) 命令。

```cpp theme={null}
XApuCommandId id;
id.type = XApuCommandType::Deactivate;
id.streamIndex = 0;
id.sequence = 0;

hr = XApuEnqueueCommand(xapuHandle, &id, nullptr);

do {
    hr = XApuDequeueResult(handle, &result);
} while (hr == XAPU_E_PENDING_RESULTS);
```

## 終止

收到停用的結果之後，呼叫端必須呼叫 [XApuDisconnect](/zh-TW/reference/audio/xapu/functions/xapudisconnect) 以中斷與音訊硬體加速單元的連線，進而釋放所有已配置的資源。

```cpp theme={null}
hr = XApuDisconnect(xapuHandle);
```


## Related topics

- [使用 XDSP API 進行單一串流 FFT/IFFT 概觀](/zh-TW/build/console-features/audio/overviews/xdsp-overview-single-stream-fft-ifft.md)
- [使用 XDSP API 進行單一串流摺積概觀](/zh-TW/build/console-features/audio/overviews/xdsp-overview-single-stream-convolution.md)
- [XBOX Series X|S 音訊硬體概觀](/zh-TW/build/console-features/audio/overviews/scarlett-audio.md)
- [概觀](/zh-TW/build/console-features/audio/overviews/index.md)
- [XApuCommandType](/zh-TW/reference/audio/xapu/enums/xapucommandtype.md)
