Skip to main content
In this topic, we will walk through the expected code flow about how to use hardware Convolution reverb on XBOX Series X devices by using one of the samples included with the Microsoft Game Development Kit (GDK).

Hardware connection and startup

A connection has to be established with the hardware acceleration unit via XDspConnect or XDspConnectWithMaximumStreamLimit. The caller sets the requirements for the connection by using the following parameters:
  1. baseBuffer - A pointer to the user allocated memory enough to hold input, output, envelope buffer and/or block multiplier buffers that will be passed to the hardware. This memory should be allocated via XMemAlloc with these attributes: XALLOC_MEMTYPE_PHYSICAL_CACHEABLE, XALLOC_PAGESIZE_64KB, XALLOC_ALIGNMENT_64K. These attributes should be set using MAKE_XALLOC_ATTRIBUTES(), as shown in the example below. This memory should not be freed until XDspDisconnect call succeeds. This buffer should be at least 64KB in size.
  2. baseBufferLength - The length of the baseBuffer in bytes. This buffer should be at least 64KB and no more than 500 MB.
  3. aggregateImpulseResponseInSeconds - It represents the overall duration of all the individual impulse responses that will be activated simultaneously using XDspActivate with XDspProcessType::Convolution. If this value is 0, no streams with XDspProcessType::Convolution can be activated.
  4. handle - a pointer to the XDspClientHandle to hold the handle returned by this call.
If the call succeeds, the baseBuffer can be used by the caller to pass input data and retrieve the output data of the streams via XDspCommand parameters. Any buffer that is passed in the XDspCommand should be 16 byte aligned. The following example of a simple buffer manager can be used for managing the input and output buffers.
The envelope buffers for each stream should be part of the baseBuffer that is passed to XDspConnect or XDspConnectWithMaximumStreamLimit similar to the input and output buffers. The length of each envelope buffer can be calculated as follows.
Following is the code example for the first step to allocate memory and establish a connection. Note that XDspConnectWithMaximumStreamLimit can be used in place of XDspConnect to reduce the internal memory usage if the number of streams that can be active is below 256.
Where XMemAllocAttributes represents the attributes mentioned above. The following code sets the aggregateImpulseResponse to 32 seconds.

Activation and deactivation of streams

After the connection is established with the device, the caller should send a stream activation command to engage a convolution, FFT or IFFT. The caller must specify the XDspProcessType, block frame count, channel count, impulse response length in floats and a pointer to the impulse response data in frequency domain in the XDspActivationParameters. Only mono or stereo streams are allowed. For XDspProcessType::ForwardFourierTransform and XDspProcessType::inverseFourierTransform, XDspActivationParameters::impulseResponse should be nullptr and XDspActivationParameters::impulseResponseLengthInFloats = 0. XDspActivationOptions should be set appropriately. Following is the code to activate one stream for convolution.
XDspActivate returns a XDspStatus buffer as one of its parameters. This XDspStatus buffer should be used to find the status of the commands processed by the hardware for this stream. After the activation result is received, the caller can start submitting data for Convolution/FFT/IFFT. This should be done by using the XDspSubmitCommand or XDspSubmitCommandWithEnvelope API. On each call, the caller must do the following:
  1. Fill the input buffer with exactly blockFrameCount of data.
  2. Fill in the XDspCommand with appropriate values and input and output buffers that are 16 byte aligned.
  3. Call XDspSubmitCommand to submit the command to the hardware. This function returns a command sequence number that can be used to track the number of commands sent to the hardware.
  4. To apply an envelope, fill the envelope buffer with gain values for each block of the impulse response filter and call XDspSubmitCommandWithEnvelope and continue making this call with the same envelope buffer until enveloping is no longer needed or the envelope needs to be changed.
  5. When enveloping is no longer required, call XDspSubmitCommand or XDspSubmitCommandWithEnvelope with a nullptr for envelopeBuffer. Note that XDspSubmitCommandWithEnvelope with a nullptr for envelopeBuffer is equivalent to XDspSubmitCommand.
  6. When switching the envelope, the current envelopeBuffer can only be updated for the next envelope if the hardware processed all the commands using that envelope and the results have been picked up. If not, please use a different envelope buffer.
The following code snippet shows an example of filling the envelope buffer with gain values for each block of the impulse response filter. Here it shows how to use only the first half of the impulse response filter with the gain values for the first half of the impulse response blocks starting with 1.0f, linearly decreasing and the second half filled with a gain value of 0.0f. For a stereo impulse response filter, the entire filter for the left channel is followed by that of the right channel - the envelope buffer for the stereo impulse response filter follows the same pattern with the gain values for the entire left channel followed by the gain values for the entire right channel. Please see Overview of Enveloping using XDSP API for information on calculating the size of the envelope buffer.
The following code snippet shows applying the envelope by calling XDspSubmitCommandWithEnvelope with a valid envelopeBuffer. This is same as the snippet that shows how to submit a command using XDspSubmitCommand except passing in the additional envelopeBuffer parameter. This should be repeated until envelope is no longer needed at which point either XDspSubmitCommand or XDspSubmitCommandWithEnvelope with a nullptr for envelopeBuffer should be called.
Next, XDspStatus can be checked to find the status of the commands submitted to the hardware as follows:
The packets in the stream are processed or the hardware returns an error in XDspStatus result, XDspDeactivate should be called.
XDspDeactivate returns XDSP_E_PENDING_RESULTS if the hardware is not done processing all commands submitted for this stream.

Termination

After XDspDeactivate succeeds, the caller must call XDspDisconnect to disconnect from the audio hardware acceleration unit to free all the allocated resources. If all streams are not deactivated, XDspDisconnect will return XDSP_E_NOT_ALL_HANDLES_DEACTIVATED error.

Reference API documentation

See also

XDSP Overview Overview of Enveloping using XDSP API
Last modified on August 20, 2026