> ## 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 장치에서 하드웨어 Convolution reverb를 사용하는 예상 코드 흐름을 안내합니다.

## 하드웨어 연결 및 시작

[XDspConnect](/reference/audio/xdspaudio/functions/xdspconnect) 또는 [XDspConnectWithMaximumStreamLimit](/reference/audio/xdspaudio/functions/xdspconnectwithmaximumstreamlimit)를 통해 하드웨어 가속 유닛과 연결을 설정해야 합니다. 호출자는 다음 매개변수를 사용하여 연결 요구사항을 설정합니다:

1. *baseBuffer* - 하드웨어에 전달될 입력, 출력, 엔벨로프 버퍼 및/또는 블록 승수 버퍼를 담을 수 있는 사용자 할당 메모리를 가리키는 포인터입니다. 이 메모리는 *XALLOC\_MEMTYPE\_PHYSICAL\_CACHEABLE*, *XALLOC\_PAGESIZE\_64KB*, *XALLOC\_ALIGNMENT\_64K* 속성으로 XMemAlloc를 통해 할당되어야 합니다. 이러한 속성은 아래 예시와 같이 `MAKE_XALLOC_ATTRIBUTES()`를 사용하여 설정해야 합니다. 이 메모리는 [XDspDisconnect](/reference/audio/xdspaudio/functions/xdspdisconnect) 호출이 성공할 때까지 해제되어서는 안 됩니다. 이 버퍼는 최소 64KB 크기여야 합니다.

2. *baseBufferLength* - *baseBuffer* 의 바이트 단위 길이. 이 버퍼는 최소 64KB이고 500MB 이하여야 합니다.

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 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](/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)는 적절히 설정되어야 합니다.

다음은 컨볼루션을 위한 하나의 스트림을 활성화하는 코드입니다.

```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](/reference/audio/xdspaudio/functions/xdspactivate)는 매개변수 중 하나로 [XDspStatus](/reference/audio/xdspaudio/structs/xdspstatus) 버퍼를 반환합니다. 이 [XDspStatus](/reference/audio/xdspaudio/structs/xdspstatus) 버퍼는 이 스트림에 대해 하드웨어에서 처리된 명령의 상태를 찾는 데 사용해야 합니다. 활성화 결과가 수신된 후, 호출자는 컨볼루션/FFT/IFFT를 위한 데이터 제출을 시작할 수 있습니다. 이는 [XDspSubmitCommand](/reference/audio/xdspaudio/functions/xdspsubmitcommand) API를 사용하여 수행해야 합니다. 각 [XDspSubmitCommand](/reference/audio/xdspaudio/functions/xdspsubmitcommand)에 대해 호출자는 다음을 수행해야 합니다:

1. 정확히 *blockFrameCount* 만큼의 데이터로 입력 버퍼를 채웁니다.
2. 적절한 값과 16바이트 정렬된 입력 및 출력 버퍼로 [XDspCommand](/reference/audio/xdspaudio/structs/xdspcommand)를 채웁니다.
3. [XDspSubmitCommand](/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](/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);
```

## 참조 API 문서

* [XDspAudio (API contents)](/reference/audio/xdspaudio/xdspaudio_members)
  * Functions
    * [XDspConnect](/reference/audio/xdspaudio/functions/xdspconnect)
    * [XDspConnectWithMaximumStreamLimit](/reference/audio/xdspaudio/functions/xdspconnectwithmaximumstreamlimit)
    * [XDspDisconnect](/reference/audio/xdspaudio/functions/xdspdisconnect)
    * [XDspActivate](/reference/audio/xdspaudio/functions/xdspactivate)
    * [XDspSubmitCommand](/reference/audio/xdspaudio/functions/xdspsubmitcommand)
    * [XDspDeactivate](/reference/audio/xdspaudio/functions/xdspdeactivate)
  * Structures
    * [XDspCommand](/reference/audio/xdspaudio/structs/xdspcommand)
    * [XDspActivationParameters](/reference/audio/xdspaudio/structs/xdspactivationparameters)
    * [XDspStatus](/reference/audio/xdspaudio/structs/xdspstatus)

## 함께 보기

[XDSP 개요](/build/console-features/audio/overviews/xdsp-overview)


## Related topics

- [XDSP API를 사용한 엔벨로프가 있는 싱글 스트림 컨볼루션](/ko/build/console-features/audio/overviews/xdsp-overview-single-stream-convolution-with-envelope.md)
- [XDSP API를 사용한 싱글 스트림 FFT/IFFT 개요](/ko/build/console-features/audio/overviews/xdsp-overview-single-stream-fft-ifft.md)
- [XAPU API를 사용한 싱글 스트림 Opus 오디오 디코딩](/ko/build/console-features/audio/overviews/xapu-overview-single-stream-audio-decode.md)
- [XDSP 인벨로핑 개요](/ko/build/console-features/audio/overviews/xdsp-overview-enveloping.md)
- [XDspActivate](/ko/reference/audio/xdspaudio/functions/xdspactivate.md)
