> ## 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) に含まれているサンプルの 1 つを使用して、XBOX Series X デバイスでハードウェア アクセラレーションによる Opus デコードを使用する方法についての想定されるコード フローを説明します。このサンプルは `DecodeOne.cpp` と呼ばれ、1 つのクライアントによるシングル ストリーム デコード シナリオを扱います。

## オーディオ ハードウェアの接続と起動

デコードは、[XApuConnect](/reference/audio/xapu/functions/xapuconnect) を介したハードウェア アクセラレーション ユニットとの接続の確立から始まります。呼び出し元は、[XApuConnectInputParameters](/reference/audio/xapu/structs/xapuconnectinputparameters) を使用して接続の要件を設定し、以下を設定します。

1. 処理タイプ (この場合、[XApuProcessType::DecodeOpus](/reference/audio/xapu/enums/xapuprocesstype))。
2. ストリームの数 (この場合、1)。
3. 入力および出力データを渡したり取得したりするために必要な合計メモリ。この場合、`MaxInputBufferLength` に 1024 (ストリーム内の最大の Opus パケット以上である必要があり、16 の倍数である必要があります) と 7680 を指定します。これは、48 K での 20 ms のデータで、`MaxOutputBufferLength` の場合は 960 × 2 × sizeof(float) = 7680 です。出力も 16 の倍数である必要があります。

この呼び出しが成功すると、[XApuConnectOutputParameters::baseData](/reference/audio/xapu/structs/xapuconnectoutputparameters) パラメーターは、ハードウェア アクセラレーション ユニットが追加のマーシャリングまたはコピーなしで直接アクセスできるようにオペレーティング システムによって割り当てられたメモリ位置を指します。このメモリは、呼び出し元が入力データを渡し、出力データを取得するために使用するべきです。次の単純なメモリ マネージャーの例を使用して、[XApuConnectInputParameters](/reference/audio/xapu/structs/xapuconnectinputparameters) を設定し、[XApuConnectOutputParameters::baseData](/reference/audio/xapu/structs/xapuconnectoutputparameters) を 2 つのポインター (入力データ用と出力データ用) に分割できます。

```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](/reference/audio/xapu/functions/xapudequeueresult) を呼び出してアクティブ化の結果を取得する必要があります。このサンプルでは [XApuConnectInputParameters::maxQueuedCommandsPerStream](/reference/audio/xapu/structs/xapuconnectinputparameters) が 1 に設定されているため、呼び出し元は次のコマンドを送信する前に各結果を待つ必要があります。これには、`Activate`、`Process`、および `Deactivate` コマンドが含まれます (詳細については、[XApuCommandType](/reference/audio/xapu/enums/xapucommandtype) を参照してください)。

1 つのストリームをアクティブ化するコードを以下に示します。

```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](/reference/audio/xapu/enums/xapucommandtype) コマンドを使用して行う必要があります。各 `Process` コマンドに対して、呼び出し元は以下を行う必要があります。

1. 入力バッファーに正確に 1 つの Opus パケットを埋めます。
2. パケットの長さを指定します。
3. オーディオ ハードウェア アクセラレーション ユニットによってデコードされたデータで埋められる出力バッファーの場所を提供します。
4. 出力バッファーの最大長を指定します。

また、呼び出し元は `streamIndex` および `frameCount` の値を指定する必要があります。デコードされたすべてのデータを出力バッファーにコピーする必要がある場合、`frameCount` 値は、パケットにエンコードされているフレーム数以上の任意の値に設定できます (たとえば、20 ms パケットの場合、`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](/reference/audio/xapu/functions/xapudequeueresult) を呼び出してパケットのデコード出力を取得する必要があります。[XApuResult](/reference/audio/xapu/structs/xapuresult) が正常に取得された後、出力データは `result.outputData` に格納されます。処理された後、次のパケットは [XApuEnqueueCommand](/reference/audio/xapu/functions/xapuenqueuecommand) の [XApuCommandType::Process](/reference/audio/xapu/enums/xapucommandtype) コマンドへの新しい呼び出しでデコード用に送信する必要があります。

```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](/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](/reference/audio/xapu/functions/xapudisconnect) を呼び出してオーディオ ハードウェア アクセラレーション ユニットから切断する必要があります。

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