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

# 使用 XDSP API 進行單一串流摺積概觀

> 使用 XDSP API 進行單一串流摺積概觀

在本主題中，我們將使用 Microsoft Game Development Kit (GDK) 隨附的其中一個範例，逐步說明如何在 XBOX Series X 裝置上使用硬體摺積殘響的預期程式碼流程。

## 硬體連線和啟動

必須透過 [XDspConnect](/zh-TW/reference/audio/xdspaudio/functions/xdspconnect) 或 [XDspConnectWithMaximumStreamLimit](/zh-TW/reference/audio/xdspaudio/functions/xdspconnectwithmaximumstreamlimit) 與硬體加速單元建立連線。呼叫端會使用下列參數設定連線的需求：

1. *baseBuffer* - 指向使用者配置記憶體的指標，此記憶體必須足以容納將傳遞給硬體的輸入、輸出、包絡緩衝區和/或區塊乘數緩衝區。此記憶體應透過 XMemAlloc 以下列屬性配置：*XALLOC\_MEMTYPE\_PHYSICAL\_CACHEABLE*、*XALLOC\_PAGESIZE\_64KB*、*XALLOC\_ALIGNMENT\_64K*。這些屬性應使用 `MAKE_XALLOC_ATTRIBUTES()` 設定，如下列範例所示。在 [XDspDisconnect](/zh-TW/reference/audio/xdspaudio/functions/xdspdisconnect) 呼叫成功之前，不應釋放此記憶體。此緩衝區的大小應至少為 64KB。

2. *baseBufferLength* - *baseBuffer* 的長度 (以位元組為單位)。此緩衝區應至少為 64KB，且不超過 500 MB。

3. *aggregateImpulseResponseInSeconds* - 代表將使用 [XDspActivate](/zh-TW/reference/audio/xdspaudio/functions/xdspactivate) 搭配 [XDspProcessType::Convolution](/zh-TW/reference/audio/xdspaudio/enums/xdspprocesstype) 同時啟用的所有個別脈衝回應的總持續時間。如果此值為 0，則無法啟用任何使用 [XDspProcessType::Convolution](/zh-TW/reference/audio/xdspaudio/enums/xdspprocesstype) 的串流。

4. handle - 指向 [XDspClientHandle](/zh-TW/reference/audio/xdspaudio/handles/xdspclienthandle) 的指標，用來保存此呼叫所傳回的控制代碼。

如果呼叫成功，呼叫端就可以使用 *baseBuffer*，透過 [XDspCommand](/zh-TW/reference/audio/xdspaudio/structs/xdspcommand) 參數傳遞輸入資料並擷取串流的輸出資料。在 [XDspCommand](/zh-TW/reference/audio/xdspaudio/structs/xdspcommand) 中傳遞的任何緩衝區都應以 16 位元組對齊。下列簡單緩衝區管理員範例可用於管理輸入和輸出緩衝區。

```cpp theme={null}
class ConvolveOneBufferManager
{
private:
    float const* _outputBuffer = nullptr;
    uint32_t _maxBufferFrameCount = 0;
    uint32_t _bufferStride = 0;
    uint32_t _maxBufferCount = 0;
    uint32_t _acquiredBufferCount = 0;
    uint32_t _channelCount = 1;

public:
    void Reset(float const* outputBuffer, uint32_t maxBufferCount, uint32_t maxBufferFrameCount, uint32_t channelCount) {
        _outputBuffer = outputBuffer;
        _maxBufferCount = maxBufferCount;
        _maxBufferFrameCount = maxBufferFrameCount;
        _channelCount = channelCount;
    }

    uint32_t GetMaxBufferFrameCount() const {
        return _maxBufferFrameCount;
    }

    bool IsFull() const {
        return _acquiredBufferCount >= _maxBufferCount;
    }

    void Acquire() {
        if (_acquiredBufferCount < _maxBufferCount) {
            _acquiredBufferCount++;
        }
    }

    void Release() {
        if (_acquiredBufferCount > 0) {
            _acquiredBufferCount--;
        }
    }

    float* GetOutputBuffer(uint32_t index) {
        return const_cast<float*>(_outputBuffer) + (((index % _maxBufferCount) * _maxBufferFrameCount * _channelCount));
    }

};
```

以下是配置記憶體並建立連線之第一個步驟的程式碼範例。

```cpp theme={null}
static const ULONGLONG XMemAllocAttributes = MAKE_XALLOC_ATTRIBUTES(allocatorId,
                      0,
                      XALLOC_MEMTYPE_PHYSICAL_CACHEABLE,
                      XALLOC_PAGESIZE_64KB,
                      XALLOC_ALIGNMENT_64K,
                      FALSE);

float* baseBuffer = (float *)XMemAlloc(baseBufferLength, XMemAllocAttributes);
```

其中 XMemAllocAttributes 代表上述的屬性。下列程式碼會將 *aggregateImpulseResponse* 設定為 32 秒。

```cpp theme={null}
hr = XDspConnect(baseBuffer, baseBufferLength, 32 /*aggregateImpulseResponseInSeconds*/, &clientHandle);
```

## 串流的啟用和停用

與裝置建立連線之後，呼叫端應傳送串流啟用命令以進行摺積、FFT 或 IFFT。呼叫端必須在 [XDspActivationParameters](/zh-TW/reference/audio/xdspaudio/structs/xdspactivationparameters) 中指定 [XDspProcessType](/zh-TW/reference/audio/xdspaudio/enums/xdspprocesstype)、區塊框架計數、聲道計數、以浮點數為單位的脈衝回應長度，以及指向頻域中脈衝回應資料的指標。只允許單聲道或立體聲串流。對於 [XDspProcessType::ForwardFourierTransform](/zh-TW/reference/audio/xdspaudio/enums/xdspprocesstype) 和 [XDspProcessType::inverseFourierTransform](/zh-TW/reference/audio/xdspaudio/enums/xdspprocesstype)，[XDspActivationParameters::impulseResponse](/zh-TW/reference/audio/xdspaudio/structs/xdspactivationparameters) 應為 nullptr，且 [XDspActivationParameters::impulseResponseLengthInFloats](/zh-TW/reference/audio/xdspaudio/structs/xdspactivationparameters) = 0。應適當地設定 [XDspActivationOptions](/zh-TW/reference/audio/xdspaudio/enums/xdspactivationoptions)。

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

```cpp theme={null}
XDspActivationParameters params;
XDspStatus* status;
XDspStreamHandle* streamHandle;
params.type = XDspProcessType::Convolution;
params.blockFrameCount = maxBufferFrameCount;
params.channelCount = channelCount; // mono or stereo
params.impulseResponseLengthInFloats = filterFrameCount;
params.impulseResponse = filterBuffer;

if (channelCount == 2 && deinterleaved)
{
    params.options |= XDspActivationOptions::Deinterleaved;
}
if (stereoImpulseResponse)
{
    params.options |= XDspActivationOptions::StereoImpulseResponse;
}
hr = XDspActivate(clientHandle, &params, &status, &streamHandle); 
```

[XDspActivate](/zh-TW/reference/audio/xdspaudio/functions/xdspactivate) 會以其中一個參數傳回 [XDspStatus](/zh-TW/reference/audio/xdspaudio/structs/xdspstatus) 緩衝區。此 [XDspStatus](/zh-TW/reference/audio/xdspaudio/structs/xdspstatus) 緩衝區應用來尋找硬體為此串流所處理之命令的狀態。收到啟用結果之後，呼叫端就可以開始提交資料以進行摺積/FFT/IFFT。這應使用 [XDspSubmitCommand](/zh-TW/reference/audio/xdspaudio/functions/xdspsubmitcommand) API 來完成。對於每個 [XDspSubmitCommand](/zh-TW/reference/audio/xdspaudio/functions/xdspsubmitcommand)，呼叫端都必須執行下列動作：

1. 以剛好 *blockFrameCount* 的資料填入輸入緩衝區。
2. 以適當的值以及 16 位元組對齊的輸入和輸出緩衝區填入 [XDspCommand](/zh-TW/reference/audio/xdspaudio/structs/xdspcommand)。
3. 呼叫 [XDspSubmitCommand](/zh-TW/reference/audio/xdspaudio/functions/xdspsubmitcommand) 將命令提交至硬體。此函式會傳回命令序號，可用來追蹤傳送至硬體的命令數目。

```cpp theme={null}
XDspCommand command;

command.beginScale = 1.0f;
command.endScale = 1.0f;
command.inputBlockBuffer = inputDataBuffer;
command.outputBlockBuffer =  bufferManager.GetOutputBuffer(_totalCommandsSubmitted + 1);
command.blockBufferMultiplier = nullptr;

uint32_t sequence = 0;
hr = XDspSubmitCommand(streamHandle, &command, &sequence);

if (SUCCEEDED(hr))
{
    totalCommandsSubmitted++;
}
```

接下來，可以依下列方式檢查 [XDspStatus](/zh-TW/reference/audio/xdspaudio/structs/xdspstatus)，以尋找提交至硬體之命令的狀態：

```cpp theme={null}
while (status->lastProcessedCommandSequence > totalResponsesReceived)
{
    totalResponsesReceived++;
 
    // Hardware status is only updated when there is a hardware fault and the
    // error is going to persist for the duration of the stream. But, all the
    // commands that have already been submitted will still be processed by
    // the hardware and we have to wait for these commands to be processed 
    // before calling XDspDeactivate.
    hr = status->result; 
     
    float* outBuffer = bufferManager.GetOutputBuffer(totalResponsesReceived);
    // The output will be in the outBuffer
    // Do something with the outBuffer
    bufferManager.Release();
}
```

當串流中的封包已處理完畢，或硬體在 [XDspStatus](/zh-TW/reference/audio/xdspaudio/structs/xdspstatus) 結果中傳回錯誤時，應呼叫 [XDspDeactivate](/zh-TW/reference/audio/xdspaudio/functions/xdspdeactivate)。

```cpp theme={null}
while (totalResponsesReceived < totalCommandsSubmitted)
{
    // run the above code in the while loop to obtain all the responses
}
hr = XDspDeactivate(streamHandle);
```

如果硬體尚未處理完為此串流提交的所有命令，[XDspDeactivate](/zh-TW/reference/audio/xdspaudio/functions/xdspdeactivate) 會傳回 *XDSP\_E\_PENDING\_RESULTS*。

## 終止

[XDspDeactivate](/zh-TW/reference/audio/xdspaudio/functions/xdspdeactivate) 成功之後，呼叫端必須呼叫 [XDspDisconnect](/zh-TW/reference/audio/xdspaudio/functions/xdspdisconnect) 以中斷與音訊硬體加速單元的連線，以釋放所有已配置的資源。如果並非所有串流都已停用，[XDspDisconnect](/zh-TW/reference/audio/xdspaudio/functions/xdspdisconnect) 將傳回 *XDSP\_E\_NOT\_ALL\_HANDLES\_DEACTIVATED* 錯誤。

```cpp theme={null}
hr = XDspDisconnect(clientHandle);
XMemFree(baseBuffer, XMemAllocAttributes);
```

## 參考 API 文件

* [XDspAudio (API 內容)](/zh-TW/reference/audio/xdspaudio/xdspaudio_members)
  * 函式
    * [XDspConnect](/zh-TW/reference/audio/xdspaudio/functions/xdspconnect)
    * [XDspConnectWithMaximumStreamLimit](/zh-TW/reference/audio/xdspaudio/functions/xdspconnectwithmaximumstreamlimit)
    * [XDspDisconnect](/zh-TW/reference/audio/xdspaudio/functions/xdspdisconnect)
    * [XDspActivate](/zh-TW/reference/audio/xdspaudio/functions/xdspactivate)
    * [XDspSubmitCommand](/zh-TW/reference/audio/xdspaudio/functions/xdspsubmitcommand)
    * [XDspDeactivate](/zh-TW/reference/audio/xdspaudio/functions/xdspdeactivate)
  * 結構
    * [XDspCommand](/zh-TW/reference/audio/xdspaudio/structs/xdspcommand)
    * [XDspActivationParameters](/zh-TW/reference/audio/xdspaudio/structs/xdspactivationparameters)
    * [XDspStatus](/zh-TW/reference/audio/xdspaudio/structs/xdspstatus)

## 另請參閱

[XDSP 概觀](/zh-TW/build/console-features/audio/overviews/xdsp-overview)


## Related topics

- [XBOX 主機遊戲的認證測試 XBOX 需求](/zh-TW/publishing/certification/console-cert-tested-requirements.md)
- [XR-015 管理玩家通訊](/zh-TW/publishing/certification/xr/xr-015.md)
- [使用 PlayFab 加入後端服務](/zh-TW/home/build-first-title/add-backend-services.md)
- [服務 C API 概觀 - PFPushNotifications.h](/zh-TW/services/playfab/api-references/c/pfpushnotifications/pfpushnotifications_members.md)
- [游戏串流简介](/zh-CN/build/core-features/common/game-streaming/game-streaming-overview.md)
