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

# Información general de una FFT/IFFT de secuencia única mediante la API XDSP

> Información general de una FFT/IFFT de secuencia única mediante la API XDSP

En este tema, se explica el flujo de código previsto sobre cómo usar el hardware para FFT/IFFT en dispositivos XBOX Series X mediante uno de los ejemplos incluidos con el Microsoft Game Development Kit (GDK).

## Conexión con el hardware e inicio

Se debe establecer una conexión con la unidad de aceleración de hardware mediante [XDspConnect](/reference/audio/xdspaudio/functions/xdspconnect). El llamador establece los requisitos de la conexión mediante los parámetros siguientes:

1. *baseBuffer*: un puntero a la memoria asignada por el usuario suficiente para contener los búferes de entrada, salida o multiplicadores de bloque que se pasarán al hardware. Esta memoria se debe asignar mediante XMemAlloc con estos atributos: *XALLOC\_MEMTYPE\_PHYSICAL\_CACHEABLE*, *XALLOC\_PAGESIZE\_64KB*, *XALLOC\_ALIGNMENT\_64K*. Estos atributos se deben establecer mediante `MAKE_XALLOC_ATTRIBUTES()`, como se muestra en el ejemplo siguiente. Esta memoria no se debe liberar hasta que la llamada a [XDspDisconnect](/reference/audio/xdspaudio/functions/xdspdisconnect) se realice correctamente. Este búfer debe tener un tamaño mínimo de 64 KB.

2. *baseBufferLength*: la longitud del *baseBuffer* en bytes. Este búfer debe tener al menos 64 KB.

3. *aggregateImpulseResponseInSeconds*: representa la duración total de todas las respuestas al impulso individuales que se activarán simultáneamente mediante [XDspActivate](/reference/audio/xdspaudio/functions/xdspactivate) con [XDspProcessType::Convolution](/reference/audio/xdspaudio/enums/xdspprocesstype). Si este valor es 0, no se puede activar ninguna secuencia con [XDspProcessType::Convolution](/reference/audio/xdspaudio/enums/xdspprocesstype).

4. handle: un puntero al [XDspClientHandle](/reference/audio/xdspaudio/handles/xdspclienthandle) que contendrá el identificador devuelto por esta llamada.

Si la llamada se realiza correctamente, el llamador puede usar el *baseBuffer* para pasar los datos de entrada y recuperar los datos de salida de las secuencias mediante los parámetros de [XDspCommand](/reference/audio/xdspaudio/structs/xdspcommand). Cualquier búfer que se pase en [XDspCommand](/reference/audio/xdspaudio/structs/xdspcommand) debe estar alineado a 16 bytes. El siguiente ejemplo de un administrador de búferes sencillo se puede usar para administrar los búferes de entrada y salida.

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

A continuación se muestra el ejemplo de código del primer paso para asignar memoria y establecer una conexión.

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

Donde XMemAllocAttributes representa los atributos mencionados anteriormente. El código siguiente establece *aggregateImpulseResponse* en 32 segundos.

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

## Activación y desactivación de secuencias

Una vez establecida la conexión con el dispositivo, el llamador debe enviar un comando de activación de secuencia para iniciar una convolución, FFT o IFFT. El llamador debe especificar el [XDspProcessType](/reference/audio/xdspaudio/enums/xdspprocesstype), el número de tramas por bloque, el número de canales, la longitud de la respuesta al impulso en floats y un puntero a los datos de la respuesta al impulso en el dominio de la frecuencia en [XDspActivationParameters](/reference/audio/xdspaudio/structs/xdspactivationparameters). Solo se permiten secuencias mono o estéreo. Para [XDspProcessType::ForwardFourierTransform](/reference/audio/xdspaudio/enums/xdspprocesstype) y [XDspProcessType::inverseFourierTransform](/reference/audio/xdspaudio/enums/xdspprocesstype), [XDspActivationParameters::impulseResponse](/reference/audio/xdspaudio/structs/xdspactivationparameters) debe ser nullptr y [XDspActivationParameters::impulseResponseLengthInFloats](/reference/audio/xdspaudio/structs/xdspactivationparameters) = 0. [XDspActivationOptions](/reference/audio/xdspaudio/enums/xdspactivationoptions) se debe establecer adecuadamente.

A continuación se muestra el código para activar una secuencia para la transformada de Fourier directa; el código es similar para la transformada de Fourier inversa.

```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) devuelve un búfer [XDspStatus](/reference/audio/xdspaudio/structs/xdspstatus) como uno de sus parámetros. Este búfer [XDspStatus](/reference/audio/xdspaudio/structs/xdspstatus) se debe usar para conocer el estado de los comandos procesados por el hardware para esta secuencia. Una vez recibido el resultado de la activación, el llamador puede empezar a enviar datos para la convolución, la FFT o la IFFT. Esto se debe hacer mediante la API [XDspSubmitCommand](/reference/audio/xdspaudio/functions/xdspsubmitcommand). Para cada [XDspSubmitCommand](/reference/audio/xdspaudio/functions/xdspsubmitcommand), el llamador debe hacer lo siguiente:

1. Rellenar el búfer de entrada con exactamente *blockFrameCount* de datos.
2. Rellenar el [XDspCommand](/reference/audio/xdspaudio/structs/xdspcommand) con los valores adecuados y con búferes de entrada y salida alineados a 16 bytes.
3. Llamar a [XDspSubmitCommand](/reference/audio/xdspaudio/functions/xdspsubmitcommand) para enviar el comando al hardware. Esta función devuelve un número de secuencia de comando que se puede usar para hacer un seguimiento del número de comandos enviados al 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++; 
 } 
```

A continuación, se puede comprobar [XDspStatus](/reference/audio/xdspaudio/structs/xdspstatus) para conocer el estado de los comandos enviados al hardware de la siguiente manera:

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

Cuando se procesan los paquetes de la secuencia o el hardware devuelve un error en el resultado de [XDspStatus](/reference/audio/xdspaudio/structs/xdspstatus), se debe llamar a [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) devuelve *XDSP\_E\_PENDING\_RESULTS* si el hardware no ha terminado de procesar todos los comandos enviados para esta secuencia.

## Finalización

Después de que [XDspDeactivate](/reference/audio/xdspaudio/functions/xdspdeactivate) se realice correctamente, el llamador debe llamar a [XDspDisconnect](/reference/audio/xdspaudio/functions/xdspdisconnect) para desconectarse de la unidad de aceleración de hardware de audio y liberar todos los recursos asignados. Si no se han desactivado todas las secuencias, [XDspDisconnect](/reference/audio/xdspaudio/functions/xdspdisconnect) devolverá el error *XDSP\_E\_NOT\_ALL\_HANDLES\_DEACTIVATED*.

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