> ## Documentation Index
> Fetch the complete documentation index at: https://docs.xbox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Visão geral de uma FFT/IFFT de fluxo único usando a API XDSP

> Visão geral de uma FFT/IFFT de fluxo único usando a API XDSP

Neste tópico, vamos explicar o fluxo de código esperado sobre como usar o hardware para FFT/IFFT em dispositivos XBOX Series X usando um dos exemplos incluídos no Microsoft Game Development Kit (GDK).

## Conexão e inicialização do hardware

É necessário estabelecer uma conexão com a unidade de aceleração de hardware por meio de [XDspConnect](https://docs.xbox.com/pt-BR/reference/audio/xdspaudio/functions/xdspconnect.md). O chamador define os requisitos da conexão usando os seguintes parâmetros:

1. *baseBuffer* - Um ponteiro para a memória alocada pelo usuário, suficiente para armazenar os buffers de entrada, de saída e/ou de multiplicador de bloco que serão passados ao hardware. Essa memória deve ser alocada por meio de XMemAlloc com estes atributos: *XALLOC\_MEMTYPE\_PHYSICAL\_CACHEABLE*, *XALLOC\_PAGESIZE\_64KB*, *XALLOC\_ALIGNMENT\_64K*. Esses atributos devem ser definidos usando `MAKE_XALLOC_ATTRIBUTES()`, conforme mostrado no exemplo abaixo. Essa memória não deve ser liberada até que a chamada de [XDspDisconnect](https://docs.xbox.com/pt-BR/reference/audio/xdspaudio/functions/xdspdisconnect.md) seja bem-sucedida. Esse buffer deve ter pelo menos 64KB de tamanho.

2. *baseBufferLength* - O comprimento do *baseBuffer* em bytes. Esse buffer deve ter pelo menos 64KB.

3. *aggregateImpulseResponseInSeconds* - Representa a duração total de todas as respostas ao impulso individuais que serão ativadas simultaneamente usando [XDspActivate](https://docs.xbox.com/pt-BR/reference/audio/xdspaudio/functions/xdspactivate.md) com [XDspProcessType::Convolution](https://docs.xbox.com/pt-BR/reference/audio/xdspaudio/enums/xdspprocesstype.md). Se esse valor for 0, nenhum fluxo com [XDspProcessType::Convolution](https://docs.xbox.com/pt-BR/reference/audio/xdspaudio/enums/xdspprocesstype.md) poderá ser ativado.

4. handle - um ponteiro para o [XDspClientHandle](https://docs.xbox.com/pt-BR/reference/audio/xdspaudio/handles/xdspclienthandle.md) que armazenará o identificador retornado por esta chamada.

Se a chamada for bem-sucedida, o *baseBuffer* poderá ser usado pelo chamador para passar dados de entrada e recuperar os dados de saída dos fluxos por meio dos parâmetros de [XDspCommand](https://docs.xbox.com/pt-BR/reference/audio/xdspaudio/structs/xdspcommand.md). Qualquer buffer passado no [XDspCommand](https://docs.xbox.com/pt-BR/reference/audio/xdspaudio/structs/xdspcommand.md) deve estar alinhado em 16 bytes. O exemplo a seguir de um gerenciador de buffers simples pode ser usado para gerenciar os buffers de entrada e saída.

```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)); 
    } 
 
}; 
```

Veja a seguir o exemplo de código da primeira etapa para alocar memória e estabelecer uma conexão.

```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);
```

Em que XMemAllocAttributes representa os atributos mencionados acima. O código a seguir define *aggregateImpulseResponse* como 32 segundos.

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

## Ativação e desativação de fluxos

Depois que a conexão com o dispositivo for estabelecida, o chamador deverá enviar um comando de ativação de fluxo para iniciar uma convolução, FFT ou IFFT. O chamador deve especificar o [XDspProcessType](https://docs.xbox.com/pt-BR/reference/audio/xdspaudio/enums/xdspprocesstype.md), a contagem de quadros do bloco, a contagem de canais, o comprimento da resposta ao impulso em floats e um ponteiro para os dados da resposta ao impulso no domínio da frequência em [XDspActivationParameters](https://docs.xbox.com/pt-BR/reference/audio/xdspaudio/structs/xdspactivationparameters.md). Somente fluxos mono ou estéreo são permitidos. Para [XDspProcessType::ForwardFourierTransform](https://docs.xbox.com/pt-BR/reference/audio/xdspaudio/enums/xdspprocesstype.md) e [XDspProcessType::inverseFourierTransform](https://docs.xbox.com/pt-BR/reference/audio/xdspaudio/enums/xdspprocesstype.md), [XDspActivationParameters::impulseResponse](https://docs.xbox.com/pt-BR/reference/audio/xdspaudio/structs/xdspactivationparameters.md) deve ser nullptr e [XDspActivationParameters::impulseResponseLengthInFloats](https://docs.xbox.com/pt-BR/reference/audio/xdspaudio/structs/xdspactivationparameters.md) = 0. [XDspActivationOptions](https://docs.xbox.com/pt-BR/reference/audio/xdspaudio/enums/xdspactivationoptions.md) deve ser definido adequadamente.

Veja a seguir o código para ativar um fluxo para a Forward Fourier Transform; o código é semelhante para a Inverse Fourier Transform.

```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](https://docs.xbox.com/pt-BR/reference/audio/xdspaudio/functions/xdspactivate.md) retorna um buffer [XDspStatus](https://docs.xbox.com/pt-BR/reference/audio/xdspaudio/structs/xdspstatus.md) como um de seus parâmetros. Esse buffer [XDspStatus](https://docs.xbox.com/pt-BR/reference/audio/xdspaudio/structs/xdspstatus.md) deve ser usado para obter o status dos comandos processados pelo hardware para esse fluxo. Depois que o resultado da ativação for recebido, o chamador poderá começar a enviar dados para convolução/FFT/IFFT. Isso deve ser feito usando a API [XDspSubmitCommand](https://docs.xbox.com/pt-BR/reference/audio/xdspaudio/functions/xdspsubmitcommand.md). Para cada [XDspSubmitCommand](https://docs.xbox.com/pt-BR/reference/audio/xdspaudio/functions/xdspsubmitcommand.md), o chamador deve fazer o seguinte:

1. Preencha o buffer de entrada com exatamente *blockFrameCount* de dados.
2. Preencha o [XDspCommand](https://docs.xbox.com/pt-BR/reference/audio/xdspaudio/structs/xdspcommand.md) com os valores apropriados e com buffers de entrada e saída alinhados em 16 bytes.
3. Chame [XDspSubmitCommand](https://docs.xbox.com/pt-BR/reference/audio/xdspaudio/functions/xdspsubmitcommand.md) para enviar o comando ao hardware. Essa função retorna um número de sequência de comando que pode ser usado para acompanhar o número de comandos enviados ao hardware.

```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++; 
 } 
```

Em seguida, [XDspStatus](https://docs.xbox.com/pt-BR/reference/audio/xdspaudio/structs/xdspstatus.md) pode ser verificado para obter o status dos comandos enviados ao hardware, da seguinte forma:

```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();
}
```

Quando os pacotes do fluxo forem processados ou o hardware retornar um erro no resultado de [XDspStatus](https://docs.xbox.com/pt-BR/reference/audio/xdspaudio/structs/xdspstatus.md), [XDspDeactivate](https://docs.xbox.com/pt-BR/reference/audio/xdspaudio/functions/xdspdeactivate.md) deverá ser chamado.

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

[XDspDeactivate](https://docs.xbox.com/pt-BR/reference/audio/xdspaudio/functions/xdspdeactivate.md) retornará *XDSP\_E\_PENDING\_RESULTS* se o hardware não tiver terminado de processar todos os comandos enviados para esse fluxo.

## Encerramento

Depois que [XDspDeactivate](https://docs.xbox.com/pt-BR/reference/audio/xdspaudio/functions/xdspdeactivate.md) for bem-sucedido, o chamador deverá chamar [XDspDisconnect](https://docs.xbox.com/pt-BR/reference/audio/xdspaudio/functions/xdspdisconnect.md) para se desconectar da unidade de aceleração de hardware de áudio e liberar todos os recursos alocados. Se nem todos os fluxos forem desativados, [XDspDisconnect](https://docs.xbox.com/pt-BR/reference/audio/xdspaudio/functions/xdspdisconnect.md) retornará o erro *XDSP\_E\_NOT\_ALL\_HANDLES\_DEACTIVATED*.

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


## Related topics

- [Visão geral de uma convolução de fluxo único usando a API XDSP](https://docs.xbox.com/pt-BR/build/console-features/audio/overviews/xdsp-overview-single-stream-convolution.md)
- [Convolução de fluxo único com envelope usando a API XDSP](https://docs.xbox.com/pt-BR/build/console-features/audio/overviews/xdsp-overview-single-stream-convolution-with-envelope.md)
- [XDspActivate](https://docs.xbox.com/pt-BR/reference/audio/xdspaudio/functions/xdspactivate.md)
- [XDspDeactivate](https://docs.xbox.com/pt-BR/reference/audio/xdspaudio/functions/xdspdeactivate.md)
- [XDspDisconnect](https://docs.xbox.com/pt-BR/reference/audio/xdspaudio/functions/xdspdisconnect.md)
