> ## 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 を使用したシングル ストリーム FFT/IFFT の概要

> XDSP API を使用したシングル ストリーム FFT/IFFT の概要

このトピックでは、Microsoft Game Development Kit (GDK) に含まれているサンプルの 1 つを使用して、XBOX Series X デバイス上で FFT/IFFT をハードウェアで実行する方法についての想定されるコード フローを説明します。

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

[XDspConnect](/reference/audio/xdspaudio/functions/xdspconnect) を介して、ハードウェア アクセラレーション ユニットとの接続を確立する必要があります。呼び出し元は、次のパラメーターを使用して接続の要件を設定します。

1. *baseBuffer* - ハードウェアに渡される入力、出力、および/またはブロック マルチプライヤー バッファーを保持するのに十分なユーザー割り当てメモリへのポインター。このメモリは、次の属性で XMemAlloc を介して割り当てる必要があります。*XALLOC\_MEMTYPE\_PHYSICAL\_CACHEABLE*、*XALLOC\_PAGESIZE\_64KB*、*XALLOC\_ALIGNMENT\_64K*。これらの属性は、以下の例に示すように `MAKE_XALLOC_ATTRIBUTES()` を使用して設定する必要があります。このメモリは、[XDspDisconnect](/reference/audio/xdspaudio/functions/xdspdisconnect) の呼び出しが成功するまで解放してはなりません。このバッファーのサイズは少なくとも 64KB である必要があります。

2. *baseBufferLength* - *baseBuffer* の長さ (バイト単位)。このバッファーは少なくとも 64KB である必要があります。

3. *aggregateImpulseResponseInSeconds* - [XDspProcessType::Convolution](/reference/audio/xdspaudio/enums/xdspprocesstype) で [XDspActivate](/reference/audio/xdspaudio/functions/xdspactivate) を使用して同時にアクティブ化されるすべての個別のインパルス応答の全体的な持続時間を表します。この値が 0 の場合、[XDspProcessType::Convolution](/reference/audio/xdspaudio/enums/xdspprocesstype) を持つストリームをアクティブ化することはできません。

4. handle - この呼び出しによって返されるハンドルを保持する [XDspClientHandle](/reference/audio/xdspaudio/handles/xdspclienthandle) へのポインター。

呼び出しが成功すると、*baseBuffer* を呼び出し元が使用して、[XDspCommand](/reference/audio/xdspaudio/structs/xdspcommand) パラメーターを介してストリームの入力データを渡し、出力データを取得できます。[XDspCommand](/reference/audio/xdspaudio/structs/xdspcommand) で渡されるすべてのバッファーは 16 バイトにアラインされている必要があります。以下の簡単なバッファー マネージャーの例を、入力および出力バッファーの管理に使用できます。

```cpp theme={null}
class TransformOneBufferManager 
{ 
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](/reference/audio/xdspaudio/structs/xdspactivationparameters) で [XDspProcessType](/reference/audio/xdspaudio/enums/xdspprocesstype)、ブロック フレーム カウント、チャネル カウント、float 単位のインパルス応答の長さ、および周波数領域のインパルス応答データへのポインターを指定する必要があります。モノラルまたはステレオのストリームのみが許可されます。[XDspProcessType::ForwardFourierTransform](/reference/audio/xdspaudio/enums/xdspprocesstype) および [XDspProcessType::inverseFourierTransform](/reference/audio/xdspaudio/enums/xdspprocesstype) の場合、[XDspActivationParameters::impulseResponse](/reference/audio/xdspaudio/structs/xdspactivationparameters) は nullptr で、[XDspActivationParameters::impulseResponseLengthInFloats](/reference/audio/xdspaudio/structs/xdspactivationparameters) = 0 である必要があります。[XDspActivationOptions](/reference/audio/xdspaudio/enums/xdspactivationoptions) は適切に設定してください。

順フーリエ変換用に 1 つのストリームをアクティブ化するコードを以下に示します。逆フーリエ変換のコードも同様です。

```cpp theme={null}
XDspActivationParameters params; 
XDspStatus* status; 
XDspStreamHandle* streamHandle; 
params.type = isForward ? XDspProcessType::ForwardFourierTransform : XDspProcessType::InverseFourierTransform;  // choose FFT vs IFFT
params.blockFrameCount = maxBufferFrameCount; 
params.channelCount = 1; // only mono is supported 
params.impulseResponseLengthInFloats = 0; // should be 0 for FFT/IFFT
params.impulseResponse = nullptr;  // should be nullptr for FFT/IFFT
params.options |= isPolar ? XDspActivationOptions::EnablePolarFormat : XDspActivationOptions::None;  // specifies whether the output should be in Polar format or Cartesian format and for IFFT this specifies whether the input is in Polar or Cartesian format.
 
hr = XDspActivate(clientHandle, &params, &status, &streamHandle);
```

[XDspActivate](/reference/audio/xdspaudio/functions/xdspactivate) は、パラメーターの 1 つとして [XDspStatus](/reference/audio/xdspaudio/structs/xdspstatus) バッファーを返します。この [XDspStatus](/reference/audio/xdspaudio/structs/xdspstatus) バッファーを使用して、このストリームに対してハードウェアによって処理されたコマンドの状態を確認してください。アクティブ化の結果を受け取った後、呼び出し元は Convolution/FFT/IFFT 用にデータを送信できます。これは、[XDspSubmitCommand](/reference/audio/xdspaudio/functions/xdspsubmitcommand) API を使用して行う必要があります。各 [XDspSubmitCommand](/reference/audio/xdspaudio/functions/xdspsubmitcommand) で、呼び出し元は以下を行う必要があります。

1. 入力バッファーに正確に *blockFrameCount* のデータを入れます。
2. [XDspCommand](/reference/audio/xdspaudio/structs/xdspcommand) に適切な値と、16 バイトにアラインされた入力および出力バッファーを入れます。
3. [XDspSubmitCommand](/reference/audio/xdspaudio/functions/xdspsubmitcommand) を呼び出して、ハードウェアにコマンドを送信します。この関数は、ハードウェアに送信されたコマンドの数を追跡するために使用できるコマンド シーケンス番号を返します。

```cpp theme={null}
XDspCommand command;  
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](/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](/reference/audio/xdspaudio/structs/xdspstatus) の結果にエラーを返すと、[XDspDeactivate](/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](/reference/audio/xdspaudio/functions/xdspdeactivate) は *XDSP\_E\_PENDING\_RESULTS* を返します。

## 終了

[XDspDeactivate](/reference/audio/xdspaudio/functions/xdspdeactivate) が成功した後、呼び出し元は割り当てられたすべてのリソースを解放するために [XDspDisconnect](/reference/audio/xdspaudio/functions/xdspdisconnect) を呼び出してオーディオ ハードウェア アクセラレーション ユニットから切断する必要があります。すべてのストリームが非アクティブ化されていない場合、[XDspDisconnect](/reference/audio/xdspaudio/functions/xdspdisconnect) は *XDSP\_E\_NOT\_ALL\_HANDLES\_DEACTIVATED* エラーを返します。

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


## Related topics

- [XDSP API を使用したシングル ストリーム コンボリューションの概要](/ja-jp/build/console-features/audio/overviews/xdsp-overview-single-stream-convolution.md)
- [XAPU API を使用したシングル ストリーム Opus オーディオ デコード](/ja-jp/build/console-features/audio/overviews/xapu-overview-single-stream-audio-decode.md)
- [XDSP API を使用したエンベロープ付きシングル ストリーム コンボリューション](/ja-jp/build/console-features/audio/overviews/xdsp-overview-single-stream-convolution-with-envelope.md)
- [XDspActivate](/ja-jp/reference/audio/xdspaudio/functions/xdspactivate.md)
- [XDspStatus](/ja-jp/reference/audio/xdspaudio/structs/xdspstatus.md)
