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

# Décodage audio Opus à flux unique avec l'API XAPU

> Vue d'ensemble du décodage audio Opus à flux unique à l'aide de l'API XAPU

Dans cette rubrique, nous passerons en revue le déroulement attendu du code pour utiliser le décodage Opus accéléré par le matériel sur les appareils XBOX Series X à l'aide de l'un des exemples inclus avec le Microsoft Game Development Kit (GDK). Cet exemple s'appelle `DecodeOne.cpp` et couvre un scénario de décodage à flux unique avec un client.

## Connexion au matériel audio et démarrage

Le décodage commence par l'établissement d'une connexion avec l'unité d'accélération matérielle au moyen de [XApuConnect](/fr-CA/reference/audio/xapu/functions/xapuconnect). L'appelant définit les exigences de la connexion à l'aide de [XApuConnectInputParameters](/fr-CA/reference/audio/xapu/structs/xapuconnectinputparameters) pour configurer les éléments suivants :

1. Le type de traitement (dans ce cas, [XApuProcessType::DecodeOpus](/fr-CA/reference/audio/xapu/enums/xapuprocesstype)).
2. Le nombre de flux (dans ce cas, 1).
3. La mémoire totale requise pour transmettre et récupérer les données d'entrée et de sortie, dans ce cas 1024 pour `MaxInputBufferLength` (doit être égal ou supérieur au plus gros paquet Opus du flux). Le nombre doit également être un multiple de 16, et 7680. Cela correspond à 20 ms de données à 48 K, soit 960 × 2 × sizeof(float) = 7680 pour `MaxOutputBufferLength`. La sortie doit également être un multiple de 16.

Si cet appel réussit, le paramètre [XApuConnectOutputParameters::baseData](/fr-CA/reference/audio/xapu/structs/xapuconnectoutputparameters) pointe vers un emplacement mémoire alloué par le système d'exploitation de manière à ce que l'unité d'accélération matérielle puisse y accéder directement sans marshaling ni copie supplémentaire. L'appelant doit utiliser cette mémoire pour transmettre les données d'entrée et récupérer les données de sortie. L'exemple suivant d'un gestionnaire de mémoire simple peut servir à définir [XApuConnectInputParameters](/fr-CA/reference/audio/xapu/structs/xapuconnectinputparameters) et à partitionner [XApuConnectOutputParameters::baseData](/fr-CA/reference/audio/xapu/structs/xapuconnectoutputparameters) en deux pointeurs : l'un pour les données d'entrée et l'autre pour les données de sortie.

```cpp theme={null}
class DecodeOneSimpleMemoryManager
{
public:
    static const uint32_t MaxStreamCount = 1;
    const uint32_t MaxInputBufferLength = 1024; // Must be equal to or greater than the largest Opus packet in the stream. The number must also be a multiple of 16.
    const uint32_t MaxOutputBufferLength = 7680; // This is 20 ms of data at 48 K, which is 960 x 2 x sizeof(float) = 7680 for MaxOutputBufferLength. The output also needs to be multiple of 16.

private:
    XApuConnectInputParameters _inParam = {
        XApuProcessType::DecodeOpus,
        MaxStreamCount,
        1,
        MaxStreamCount * (MaxInputBufferLength + MaxOutputBufferLength),
        0,
        XApuConnectOptions::None };

    XApuConnectOutputParameters _outParam = {};

public:
    XApuConnectInputParameters * const GetConnectParametersRef() {
        return &_inputParam;
    }

    XApuConnectOutputParameters * const GetConnectionDataRef() {
        return &_outParam;
    }

    uint8_t* GetRawInputBuffer(uint32_t& maxByteCount) {
        maxByteCount = MaxInputBufferLength;
        return reinterpret_cast<uint8_t*>(_outParam.baseData);
    }

    uint8_t* GetRawOutputBuffer(uint32_t& maxByteCount) {
        maxByteCount = MaxOutputBufferLength;
        return reinterpret_cast<uint8_t*>(_outParam.baseData) + MaxInputBufferLength;
    }
};
```

Voici l'exemple de code de la première étape pour établir une connexion.

```cpp theme={null}
XApuConnectInputParameters * const connectParameters = memoryManager.GetConnectParametersRef();
XApuConnectOutputParameters * const connectionData = memoryManager.GetConnectionDataRef();
hr = XApuConnect(connectParameters, connectionData, &xapuHandle);
```

## Activation et désactivation des flux

Une fois la connexion établie avec le périphérique, l'appelant doit envoyer une commande d'activation de flux pour engager un seul moteur de décodage. L'appelant doit indiquer l'index du flux et le nombre de canaux. Seuls les flux mono ou stéréo sont autorisés.

L'appelant doit appeler [XApuDequeueResult](/fr-CA/reference/audio/xapu/functions/xapudequeueresult) pour obtenir le résultat de l'activation. Comme [XApuConnectInputParameters::maxQueuedCommandsPerStream](/fr-CA/reference/audio/xapu/structs/xapuconnectinputparameters) est défini à 1 dans cet exemple, l'appelant doit attendre chaque résultat avant de soumettre la commande suivante. Cela inclut les commandes `Activate`, `Process` et `Deactivate` (pour plus de détails, consultez [XApuCommandType](/fr-CA/reference/audio/xapu/enums/xapucommandtype)).

Voici le code pour activer un flux.

```cpp theme={null}
XApuDecodeConvertActivateCommand command = {};
command.id.type = XApuCommandType::Activate;
command.id.streamIndex = 0;
command.id.sequence = 0;
command.channelCount = channelCount;

hr = XApuEnqueueCommand(xapuHandle, &command.id, nullptr);
XApuResult result = {};

do {
    hr = XApuDequeueResult(handle, &result);
} while (hr == XAPU_E_PENDING_RESULTS);
```

Une fois le résultat de l'activation reçu, l'appelant peut commencer à soumettre des paquets Opus pour décodage. Cela doit se faire à l'aide de la commande [XApuCommandType::Process](/fr-CA/reference/audio/xapu/enums/xapucommandtype). Pour chaque commande `Process`, l'appelant doit effectuer les opérations suivantes :

1. Remplir la mémoire tampon d'entrée avec exactement un paquet Opus.
2. Indiquer la longueur du paquet.
3. Fournir l'emplacement de la mémoire tampon de sortie qui sera remplie de données décodées par l'unité d'accélération matérielle audio.
4. Indiquer la longueur maximale de la mémoire tampon de sortie.

L'appelant doit également indiquer les valeurs `streamIndex` et `frameCount`. Si toutes les données décodées doivent être copiées dans la mémoire tampon de sortie, la valeur `frameCount` peut être définie à n'importe quelle valeur égale ou supérieure au nombre de trames encodées dans le paquet (par exemple, pour un paquet de 20 ms, `frameCount` peut être défini entre 960 et 0xFFFFFFFF).

```cpp theme={null}
XApuDecodeConvertCommand command = {};
command.id.streamIndex = 0;
command.id.type = XApuCommandType::Process;
command.id.sequence = packetIndex;
command.frameCount = 0xFFFFFFFF;
command.inputData = memoryManager.GetRawInputBuffer(inputMaxByteCount);
command.inputDataLength = packetLength;
command.outputData = memoryManager.GetRawOutputBuffer(outputMaxByteCount);
command.maxOutputDataLength = outputMaxByteCount;

hr = XApuEnqueueCommand(xapuHandle, &command.id, nullptr);
```

Ensuite, [XApuDequeueResult](/fr-CA/reference/audio/xapu/functions/xapudequeueresult) doit être appelé pour obtenir la sortie décodée du paquet. Une fois [XApuResult](/fr-CA/reference/audio/xapu/structs/xapuresult) récupéré avec succès, les données de sortie seront stockées dans `result.outputData`. Après leur traitement, le paquet suivant doit être soumis pour décodage au moyen d'un nouvel appel à [XApuEnqueueCommand](/fr-CA/reference/audio/xapu/functions/xapuenqueuecommand) avec la commande [XApuCommandType::Process](/fr-CA/reference/audio/xapu/enums/xapucommandtype).

```cpp theme={null}
XApuResult result = {};

do {
    hr = XApuDequeueResult(handle, &result);
    if (SUCCEEDED(hr))
    {
         if (result.id.type == XApuCommandType::Process)
         {
              fwrite(result.outputData, 1, result.outputDataLength, fileOutput);
         }
    }
    
} while (hr == XAPU_E_PENDING_RESULTS);
```

Une fois tous les paquets du flux décodés, une commande [XApuCommandType::Deactivate](/fr-CA/reference/audio/xapu/enums/xapucommandtype) doit être soumise.

```cpp theme={null}
XApuCommandId id;
id.type = XApuCommandType::Deactivate;
id.streamIndex = 0;
id.sequence = 0;

hr = XApuEnqueueCommand(xapuHandle, &id, nullptr);

do {
    hr = XApuDequeueResult(handle, &result);
} while (hr == XAPU_E_PENDING_RESULTS);
```

## Terminaison

Une fois le résultat de la désactivation reçu, l'appelant doit appeler [XApuDisconnect](/fr-CA/reference/audio/xapu/functions/xapudisconnect) pour se déconnecter de l'unité d'accélération matérielle audio afin de libérer toutes les ressources allouées.

```cpp theme={null}
hr = XApuDisconnect(xapuHandle);
```


## Related topics

- [XAPU overview](/build/console-features/audio/overviews/xapu-overview.md)
- [XAPU 概述](/zh-CN/build/console-features/audio/overviews/xapu-overview.md)
- [XAPU 개요](/ko/build/console-features/audio/overviews/xapu-overview.md)
- [Single-stream Opus audio decoding with the XAPU API](/build/console-features/audio/overviews/xapu-overview-single-stream-audio-decode.md)
- [XAPU の概要](/ja-jp/build/console-features/audio/overviews/xapu-overview.md)
