Partager via


Audio à faible latence

Cet article décrit les changements de latence audio dans Windows 10. Il couvre les options d’API pour les développeurs d’applications et les modifications apportées aux pilotes qui peuvent être apportées pour prendre en charge l’audio à faible latence. La latence audio est le délai entre le moment où le son est créé et le moment où il est entendu. Une faible latence audio est importante pour plusieurs scénarios clés, tels que :

  • Audio Professionnel
  • Création de musique
  • Communications
  • Réalité virtuelle
  • Jeux

Les objectifs de ce document sont les suivants :

  1. Décrire les sources de latence audio dans Windows.
  2. Expliquer les modifications qui réduisent la latence audio dans la pile audio Windows 10.
  3. Fournissez une référence sur la façon dont les développeurs d’applications et les fabricants de matériel peuvent tirer parti de la nouvelle infrastructure afin de développer des applications et des pilotes avec une faible latence audio.

Cet article couvre les points suivants :

  1. Nouvelle API AudioGraph pour les scénarios interactifs et de création de médias.
  2. Modifications apportées à WASAPI pour prendre en charge une faible latence.
  3. Améliorations apportées aux DDIs du pilote.

Terminologie

Terme Description
Latence de rendu Délai entre le moment où une application envoie une mémoire tampon de données audio aux API de rendu, jusqu’au moment où elle est entendue par les haut-parleurs.
Capturer la latence Délai entre le moment où un son est capturé à partir du microphone et celui où il est envoyé aux API de capture utilisées par l’application.
Latence aller-retour Délai entre le moment où un son est capturé à partir du microphone, traité par l’application et soumis par l’application pour le rendu aux haut-parleurs. Elle est à peu près égale à la latence de rendu + latence de capture.
Latence tactile à l’application Délai entre le moment où un utilisateur appuie sur l’écran et le moment où le signal est envoyé à l’application.
Latence tactile-son Délai entre le moment où un utilisateur appuie sur l’écran, l’événement est envoyé à l’application et un son est entendu via les haut-parleurs. Elle est égale à la latence de rendu + latence tactile à l’application.

Pile audio Windows

Le diagramme suivant montre une version simplifiée de la pile audio Windows.

Diagramme montrant la pile audio à faible latence avec des applications, un pilote de moteur audio et du matériel.

Voici un résumé des latences dans le chemin de rendu : objets de traitement audio

  1. L’application écrit les données dans une mémoire tampon

  2. Le moteur audio lit les données de la mémoire tampon et les traite. Il charge également des effets audio sous la forme d’objets de traitement audio (APO). Pour plus d’informations sur les API, consultez Objets de traitement audio Windows.

  3. La latence des API varie en fonction du traitement du signal au sein des API.

  4. Avant Windows 10, la latence du moteur audio était égale à ~12 ms pour les applications qui utilisent des données à virgule flottante et ~6 ms pour les applications qui utilisent des données entières

  5. Dans Windows 10 et versions ultérieures, la latence a été réduite à 1,3 ms pour toutes les applications

  6. Le moteur audio écrit les données traitées dans une mémoire tampon.

  7. Avant Windows 10, la mémoire tampon était toujours définie sur ~10 ms.

  8. À compter de Windows 10, la taille de la mémoire tampon est définie par le pilote audio (plus d’informations sur la mémoire tampon sont décrites plus loin dans cet article).

  9. Le pilote Audio lit les données de la mémoire tampon et les écrit dans le matériel.

  10. Le matériel peut également traiter à nouveau les données sous la forme d’effets audio supplémentaires.

  11. L’utilisateur entend l’audio du haut-parleur.

Voici un résumé de la latence dans le chemin de capture :

  1. L’audio est capturé à partir du microphone.

  2. Le matériel peut traiter les données. Par exemple, pour ajouter des effets audio.

  3. Le pilote lit les données du matériel et écrit les données dans une mémoire tampon.

  4. Avant Windows 10, cette mémoire tampon était toujours définie sur 10 ms.

  5. À compter de Windows 10, la taille de la mémoire tampon est définie par le pilote audio (plus d’informations ci-dessous).

  6. Le moteur audio lit les données de la mémoire tampon et les traite. Il charge également des effets audio sous la forme d’objets de traitement audio (APO).

  7. La latence des API varie en fonction du traitement du signal au sein des API.

  8. Avant Windows 10, la latence du moteur audio était égale à ~6 ms pour les applications qui utilisent des données à virgule flottante et à ~0 ms pour les applications qui utilisent des données entières.

  9. Dans Windows 10 et versions ultérieures, la latence a été réduite à environ 0 ms pour toutes les applications.

  10. L’application est signalée que les données peuvent être lues dès que le moteur audio a terminé son traitement. La pile audio offre également l’option de mode exclusif. Dans ce cas, les données contournent le moteur audio et passent directement de l’application à la mémoire tampon à partir de laquelle le pilote les lit. Toutefois, si une application ouvre un point de terminaison en mode exclusif, aucune autre application ne peut utiliser ce point de terminaison pour afficher ou capturer l’audio.

Une autre alternative populaire pour les applications qui ont besoin d’une faible latence consiste à utiliser le modèle ASIO (Audio Stream Input/Output), qui utilise le mode exclusif. Une fois qu’un utilisateur a installé un pilote ASIO tiers, les applications peuvent envoyer des données directement de l’application au pilote ASIO. Toutefois, l’application doit être écrite de telle sorte qu’elle communique directement avec le pilote ASIO.

Les deux alternatives (mode exclusif et ASIO) ont leurs propres limitations. Ils fournissent une faible latence, mais ils ont leurs propres limitations (dont certaines ont été décrites ci-dessus). Par conséquent, le moteur audio a été modifié afin de réduire la latence, tout en conservant la flexibilité.

Améliorations apportées à la pile audio

Windows 10 et les versions ultérieures ont été améliorées dans trois domaines pour réduire la latence :

  1. Toutes les applications qui utilisent l’audio verront une réduction de 4,5 à 16 ms de la latence aller-retour (comme expliqué dans la section ci-dessus) sans aucune modification du code ni mise à jour du pilote, par rapport à Windows 8.1.
    1. Les applications qui utilisent des données à virgule flottante auront une latence inférieure de 16 ms.
    2. Les applications qui utilisent des données entières auront une latence inférieure de 4,5 ms.
  2. Les systèmes avec des pilotes mis à jour offrent une latence aller-retour encore plus faible :
    1. Les pilotes peuvent utiliser de nouvelles DDIs pour signaler les tailles prises en charge de la mémoire tampon utilisée pour transférer des données entre Windows et le matériel. Les transferts de données n’ont pas besoin d’utiliser toujours des mémoires tampons de 10 ms, comme dans les versions précédentes de Windows. Au lieu de cela, le pilote peut spécifier s’il peut utiliser de petites mémoires tampons, par exemple, 5 ms, 3 ms, 1 ms, etc.
    2. Les applications qui nécessitent une faible latence peuvent utiliser de nouvelles API audio (AudioGraph ou WASAPI) pour interroger les tailles de mémoire tampon prises en charge par le pilote et sélectionner celle qui sera utilisée pour le transfert de données vers/depuis le matériel.
  3. Lorsqu’une application utilise des tailles de mémoire tampon inférieures à un certain seuil pour afficher et capturer l’audio, Windows passe en mode spécial, où il gère ses ressources de manière à éviter les interférences entre le streaming audio et d’autres sous-systèmes. Cela permet de réduire les interruptions dans l’exécution du sous-système audio et de réduire la probabilité de problèmes audio. Lorsque l’application arrête la diffusion en continu, Windows revient à son mode d’exécution normal. Le sous-système audio se compose des ressources suivantes :
    1. Thread du moteur audio qui traite l’audio à faible latence.
    2. Tous les threads et interruptions qui ont été inscrits par le pilote (à l’aide des nouvelles DDIS décrites dans la section sur l’inscription des ressources de pilote).
    3. Une partie ou la totalité des threads audio des applications qui demandent de petites mémoires tampons, et de toutes les applications qui partagent le même graphique d’appareil audio (par exemple, le même mode de traitement du signal) avec toute application qui a demandé de petites mémoires tampons :
  4. Rappels AudioGraph sur le chemin de diffusion en continu.
  5. Si l’application utilise WASAPI, seuls les éléments de travail qui ont été soumis à l’API file d’attente de travail en temps réel ou à MFCreateMFByteStreamOnStreamEx et qui ont été étiquetés comme « Audio » ou « ProAudio ».

Améliorations d’API

Les deux API Windows 10 suivantes fournissent des fonctionnalités à faible latence :

Pour déterminer les deux API à utiliser :

  • Privilégiez AudioGraph, dans la mesure du possible pour le développement de nouvelles applications.
  • Utilisez UNIQUEMENT WASAPI si :
    • Vous avez besoin de plus de contrôle que celui fourni par AudioGraph.
    • Vous avez besoin d’une latence inférieure à celle fournie par AudioGraph.

La section Outils de mesure de cet article montre des mesures spécifiques d’un système Haswell à l’aide du pilote HDAudio de boîte de réception.

Les sections suivantes expliquent les fonctionnalités de faible latence dans chaque API. Comme indiqué dans la section précédente, pour que le système atteigne la latence minimale, il doit disposer de pilotes mis à jour qui prennent en charge de petites tailles de mémoire tampon.

AudioGraph

AudioGraph est une nouvelle API plateforme Windows universelle dans Windows 10 et versions ultérieures qui vise à réaliser facilement des scénarios interactifs et de création de musique. AudioGraph est disponible dans plusieurs langages de programmation (C++, C#, JavaScript) et dispose d’un modèle de programmation simple et riche en fonctionnalités.

Pour cibler les scénarios de faible latence, AudioGraph fournit la propriété AudioGraphSettings ::QuantumSizeSelectionMode . Cette propriété peut être l’une des valeurs indiquées dans le tableau ci-dessous :

Valeur Description
SystemDefault Définit la mémoire tampon sur la taille de mémoire tampon par défaut (~10 ms)
La latence la plus faible Définit la mémoire tampon sur la valeur minimale prise en charge par le pilote
ClosestToDesired Définit la taille de la mémoire tampon pour qu’elle soit égale à la valeur définie par la propriété DesiredSamplesPerQuantum ou à une valeur aussi proche de DesiredSamplesPerQuantum que celle prise en charge par le pilote.

L’exemple AudioCreation montre comment utiliser AudioGraph pour une faible latence. L’extrait de code suivant montre comment définir la taille minimale de la mémoire tampon :

AudioGraphSettings settings = new AudioGraphSettings(AudioRenderCategory.Media);
settings.QuantumSizeSelectionMode = QuantumSizeSelectionMode.LowestLatency;
CreateAudioGraphResult result = await AudioGraph.CreateAsync(settings);

API de session audio Windows (WASAPI)

À partir de Windows 10, WASAPI a été amélioré pour :

  • Autoriser une application à découvrir la plage de tailles de mémoire tampon (c’est-à-dire les valeurs de périodicité) prises en charge par le pilote audio d’un périphérique audio donné. Cela permet à une application de choisir entre la taille de mémoire tampon par défaut (10 ms) ou une petite mémoire tampon (inférieure à 10 ms) lors de l’ouverture d’un flux en mode partagé. Si une application ne spécifie pas de taille de mémoire tampon, elle utilise la taille de mémoire tampon par défaut.
  • Autoriser une application à découvrir le format actuel et la périodicité du moteur audio. Cela permet aux applications de s’aligner sur les paramètres actuels du moteur audio.
  • Autoriser une application à spécifier qu’elle souhaite afficher/capturer dans le format qu’elle spécifie sans rééchantillonnage par le moteur audio

Les fonctionnalités ci-dessus seront disponibles sur tous les appareils Windows. Toutefois, certains appareils disposant de suffisamment de ressources et de pilotes mis à jour offrent une meilleure expérience utilisateur que d’autres.

La fonctionnalité ci-dessus est fournie par une nouvelle interface, appelée IAudioClient3, qui dérive de IAudioClient2.

IAudioClient3 définit les 3 méthodes suivantes :

Méthode Description
GetCurrentSharedModeEnginePeriod Retourne le format actuel et la périodicité du moteur audio
GetSharedModeEnginePeriod Retourne la plage de périodicités prises en charge par le moteur pour le format de flux spécifié
InitializeSharedAudioStream Initialise un flux partagé avec la périodicité spécifiée

L’exemple WASAPIAudio montre comment utiliser IAudioClient3 pour une faible latence.

L’extrait de code suivant montre comment une application de création de musique peut fonctionner dans le paramètre de latence la plus faible pris en charge par le système.

// 1. Activation

// Get a string representing the Default Audio (Render|Capture) Device
m_DeviceIdString = MediaDevice::GetDefaultAudio(Render|Capture)Id(
Windows::Media::Devices::AudioDeviceRole::Default );

// This call must be made on the main UI thread.  Async operation will call back to
// IActivateAudioInterfaceCompletionHandler::ActivateCompleted, which must be an agile // interface implementation
hr = ActivateAudioInterfaceAsync( m_DeviceIdString->Data(), __uuidof(IAudioClient3),
nullptr, this, &asyncOp );

// 2. Setting the audio client properties – note that low latency offload is not supported

AudioClientProperties audioProps = {0};
audioProps.cbSize = sizeof( AudioClientProperties );
audioProps.eCategory = AudioCategory_Media;

// if the device has System.Devices.AudioDevice.RawProcessingSupported set to true and you want to use raw mode
// audioProps.Options |= AUDCLNT_STREAMOPTIONS_RAW;
//
// if it is important to avoid resampling in the audio engine, set this flag
// audioProps.Options |= AUDCLNT_STREAMOPTIONS_MATCH_FORMAT;


hr = m_AudioClient->SetClientProperties( &audioProps ); if (FAILED(hr)) { ... }

// 3. Querying the legal periods

hr = m_AudioClient->GetMixFormat( &mixFormat ); if (FAILED(hr)) { ... }

hr = m_AudioClient->GetSharedModeEnginePeriod(wfx, &defaultPeriodInFrames, &fundamentalPeriodInFrames, &minPeriodInFrames, &maxPeriodInFrames); if (FAILED(hr)) { ... }

// legal periods are any multiple of fundamentalPeriodInFrames between
// minPeriodInFrames and maxPeriodInFrames, inclusive
// the Windows shared-mode engine uses defaultPeriodInFrames unless an audio client // has specifically requested otherwise

// 4. Initializing a low-latency client

hr = m_AudioClient->InitializeSharedAudioStream(
         AUDCLNT_STREAMFLAGS_EVENTCALLBACK,
         desiredPeriodInFrames,
         mixFormat,
         nullptr); // audio session GUID
         if (AUDCLNT_E_ENGINE_PERIODICITY_LOCKED == hr) {
         /* engine is already running at a different period; call m_AudioClient->GetSharedModeEnginePeriod to see what it is */
         } else if (FAILED(hr)) {
             ...
         }

// 5. Initializing a client with a specific format (if the format needs to be different than the default format)

AudioClientProperties audioProps = {0};
audioProps.cbSize = sizeof( AudioClientProperties );
audioProps.eCategory = AudioCategory_Media;
audioProps.Options |= AUDCLNT_STREAMOPTIONS_MATCH_FORMAT;

hr = m_AudioClient->SetClientProperties( &audioProps );
if (FAILED(hr)) { ... }

hr = m_AudioClient->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED, appFormat, &closest);
if (S_OK == hr) {
       /* device supports the app format */
} else if (S_FALSE == hr) {
       /* device DOES NOT support the app format; closest supported format is in the "closest" output variable */
} else {
       /* device DOES NOT support the app format, and Windows could not find a close supported format */
}

hr = m_AudioClient->InitializeSharedAudioStream(
       AUDCLNT_STREAMFLAGS_EVENTCALLBACK,
       defaultPeriodInFrames,
       appFormat,
       nullptr); // audio session GUID
if (AUDCLNT_E_ENGINE_FORMAT_LOCKED == hr) {
       /* engine is already running at a different format */
} else if (FAILED(hr)) {
       ...
}

En outre, Microsoft recommande aux applications qui utilisent WASAPI d’utiliser également l’API file d’attente de travail en temps réel ou mfCreateMFByteStreamOnStreamEx pour créer des éléments de travail et les étiqueter comme Audio ou Audio Pro, au lieu de leurs propres threads. Cela permettra à Windows de les gérer de manière à éviter les interférences des sous-systèmes non audio. En revanche, tous les threads AudioGraph sont automatiquement gérés correctement par Windows. L’extrait de code suivant de l’exemple WASAPIAudio montre comment utiliser les API de file d’attente de travail MF.

// Specify Source Reader Attributes
Attributes->SetUnknown( MF_SOURCE_READER_ASYNC_CALLBACK, static_cast<IMFSourceReaderCallback *>(this) );
    if (FAILED( hr ))
    {
        goto exit;
    }
    Attributes->SetString( MF_READWRITE_MMCSS_CLASS_AUDIO, L"Audio" );
    if (FAILED( hr ))
    {
        goto exit;
    }
    Attributes->SetUINT32( MF_READWRITE_MMCSS_PRIORITY_AUDIO, 0 );
    if (FAILED( hr ))
    {
        goto exit;
    }
    // Create a stream from IRandomAccessStream
    hr = MFCreateMFByteStreamOnStreamEx (reinterpret_cast<IUnknown*>(m_ContentStream), &ByteStream );
    if ( FAILED( hr ) )
    {
        goto exit;
    }
    // Create source reader
    hr = MFCreateSourceReaderFromByteStream( ByteStream, Attributes, &m_MFSourceReader );

L’extrait de code suivant montre également comment utiliser les API de file d’attente de travail RT.

#define INVALID_WORK_QUEUE_ID 0xffffffff
DWORD g_WorkQueueId = INVALID_WORK_QUEUE_ID;
//#define MMCSS_AUDIO_CLASS    L"Audio"
//#define MMCSS_PROAUDIO_CLASS L"ProAudio"

STDMETHODIMP TestClass::GetParameters(DWORD* pdwFlags, DWORD* pdwQueue)
{
       HRESULT hr = S_OK;
       *pdwFlags = 0;
       *pdwQueue = g_WorkQueueId;
       return hr;
}

//-------------------------------------------------------
STDMETHODIMP TestClass::Invoke(IRtwqAsyncResult* pAsyncResult)
{
       HRESULT hr = S_OK;
       IUnknown *pState = NULL;
       WCHAR className[20];
       DWORD  bufferLength = 20;
       DWORD taskID = 0;
       LONG priority = 0;

       printf("Callback is invoked pAsyncResult(0x%0x)  Current process id :0x%0x Current thread id :0x%0x\n", (INT64)pAsyncResult, GetCurrentProcessId(), GetCurrentThreadId());

       hr = RtwqGetWorkQueueMMCSSClass(g_WorkQueueId, className, &bufferLength);
       IF_FAIL_EXIT(hr, Exit);

       if (className[0])
       {
              hr = RtwqGetWorkQueueMMCSSTaskId(g_WorkQueueId, &taskID);
              IF_FAIL_EXIT(hr, Exit);

              hr = RtwqGetWorkQueueMMCSSPriority(g_WorkQueueId, &priority);
              IF_FAIL_EXIT(hr, Exit);
              printf("MMCSS: [%ws] taskID (%d) priority(%d)\n", className, taskID, priority);
       }
       else
       {
              printf("non-MMCSS\n");
       }
       hr = pAsyncResult->GetState(&pState);
       IF_FAIL_EXIT(hr, Exit);

Exit:
       return S_OK;
}
//-------------------------------------------------------

int _tmain(int argc, _TCHAR* argv[])
{
       HRESULT hr = S_OK;
       HANDLE signalEvent;
       LONG Priority = 1;
       IRtwqAsyncResult *pAsyncResult = NULL;
       RTWQWORKITEM_KEY workItemKey = NULL;;
       IRtwqAsyncCallback *callback = NULL;
       IUnknown *appObject = NULL;
       IUnknown *appState = NULL;
       DWORD taskId = 0;
       TestClass cbClass;
       NTSTATUS status;

       hr = RtwqStartup();
       IF_FAIL_EXIT(hr, Exit);

       signalEvent = CreateEvent(NULL, true, FALSE, NULL);
       IF_TRUE_ACTION_EXIT(signalEvent == NULL, hr = E_OUTOFMEMORY, Exit);

       g_WorkQueueId = RTWQ_MULTITHREADED_WORKQUEUE;

       hr = RtwqLockSharedWorkQueue(L"Audio", 0, &taskId, &g_WorkQueueId);
       IF_FAIL_EXIT(hr, Exit);

       hr = RtwqCreateAsyncResult(NULL, reinterpret_cast<IRtwqAsyncCallback*>(&cbClass), NULL, &pAsyncResult);
       IF_FAIL_EXIT(hr, Exit);

       hr = RtwqPutWaitingWorkItem(signalEvent, Priority, pAsyncResult, &workItemKey);
       IF_FAIL_EXIT(hr, Exit);

       for (int i = 0; i < 5; i++)
       {
              SetEvent(signalEvent);
              Sleep(30);
              hr = RtwqPutWaitingWorkItem(signalEvent, Priority, pAsyncResult, &workItemKey);
              IF_FAIL_EXIT(hr, Exit);
    }

Exit:
       if (pAsyncResult)
       {
              pAsyncResult->Release();
       }

      if (INVALID_WORK_QUEUE_ID != g_WorkQueueId)
      {
        hr = RtwqUnlockWorkQueue(g_WorkQueueId);
        if (FAILED(hr))
        {
            printf("Failed with RtwqUnlockWorkQueue 0x%x\n", hr);
        }

        hr = RtwqShutdown();
        if (FAILED(hr))
        {
            printf("Failed with RtwqShutdown 0x%x\n", hr);
        }
      }

       if (FAILED(hr))
       {
          printf("Failed with error code 0x%x\n", hr);
       }
       return 0;
}

Enfin, les développeurs d’applications qui utilisent WASAPI doivent étiqueter leurs flux avec la catégorie audio et s’ils utilisent le mode de traitement du signal brut, en fonction des fonctionnalités de chaque flux. Microsoft recommande que tous les flux audio n’utilisent pas le mode de traitement du signal brut, sauf si les implications sont comprises. Le mode brut contourne tout le traitement du signal qui a été choisi par l’OEM, de sorte que :

  • Le signal de rendu d’un point de terminaison particulier peut ne pas être optimal.
  • Le signal de capture peut être dans un format que l’application ne peut pas comprendre.
  • La latence peut être améliorée.

Améliorations apportées aux pilotes

Pour que les pilotes audio prennent en charge une faible latence, Windows 10 et les versions ultérieures fournissent les fonctionnalités suivantes :

  1. [Obligatoire] Déclarez la taille de mémoire tampon minimale prise en charge dans chaque mode.
  2. [Facultatif, mais recommandé] Améliorez la coordination du flux de données entre le pilote et Windows.
  3. [Facultatif, mais recommandé] Inscrivez les ressources de pilote (interruptions, threads) afin qu’elles puissent être protégées par Windows dans les scénarios de faible latence. Les pilotes de fonction miniport HDAudio énumérés par le pilote de bus HDAudio de boîte de réception hdaudbus.sys n’ont pas besoin d’enregistrer les interruptions HDAudio, car cela est déjà fait par hdaudbus.sys. Toutefois, si le pilote miniport crée ses propres threads, il doit les inscrire.

Les trois sections suivantes expliquent plus en détail chaque nouvelle fonctionnalité.

Déclarer la taille de mémoire tampon minimale

Un pilote fonctionne sous diverses contraintes lors du déplacement de données audio entre Windows, le pilote et le matériel. Ces contraintes peuvent être dues au transport matériel physique qui déplace les données entre la mémoire et le matériel, ou en raison des modules de traitement du signal au sein du matériel ou du DSP associé.

À compter de Windows 10, version 1607, le pilote peut exprimer ses fonctionnalités de taille de mémoire tampon à l’aide de la propriété de périphérique DEVPKEY_KsAudio_PacketSize_Constraints2. Cette propriété permet à l’utilisateur de définir la taille de mémoire tampon minimale absolue prise en charge par le pilote, ainsi que des contraintes de taille de mémoire tampon spécifiques pour chaque mode de traitement du signal. Les contraintes spécifiques au mode doivent être supérieures à la taille de mémoire tampon minimale des pilotes, sinon elles sont ignorées par la pile audio.

Par exemple, l’extrait de code suivant montre comment un pilote peut déclarer que la taille de mémoire tampon minimale absolue prise en charge est de 2 ms, mais que le mode par défaut prend en charge 128 images, ce qui correspond à 3 ms si nous supposons un taux d’échantillonnage de 48 kHz.

 
//
// Describe buffer size constraints for WaveRT buffers
//
static struct
{
    KSAUDIO_PACKETSIZE_CONSTRAINTS2 TransportPacketConstraints;
    KSAUDIO_PACKETSIZE_PROCESSINGMODE_CONSTRAINT AdditionalProcessingConstraints[1];
} SysvadWaveRtPacketSizeConstraintsRender =
{
    {
        2 * HNSTIME_PER_MILLISECOND,                // 2 ms minimum processing interval
        FILE_BYTE_ALIGNMENT,                        // 1 byte packet size alignment
        0,                                          // no maximum packet size constraint
        2,                                          // 2 processing constraints follow
        {
            STATIC_AUDIO_SIGNALPROCESSINGMODE_DEFAULT,          // constraint for default processing mode
            128,                                                // 128 samples per processing frame
            0,                                                  // NA hns per processing frame
        },
    },
    {
        {
            STATIC_AUDIO_SIGNALPROCESSINGMODE_MOVIE,            // constraint for movie processing mode
            1024,                                               // 1024 samples per processing frame
            0,                                                  // NA hns per processing frame
        },
    }
};

Pour plus d’informations détaillées sur ces structures, consultez les articles suivants :

En outre, l’exemple sysvad montre comment utiliser ces propriétés, afin qu’un pilote déclare la mémoire tampon minimale pour chaque mode.

Améliorer la coordination entre le pilote et le système d’exploitation

Les DDIs décrits dans cette section permettent au pilote de :

  • Indiquez clairement la moitié (paquet) de la mémoire tampon disponible pour Windows, plutôt que le système d’exploitation en fonction d’une position de liaison de codec. Cela permet à Windows de récupérer plus rapidement des problèmes audio.
  • Vous pouvez éventuellement optimiser ou simplifier ses transferts de données à l’entrée et à l’extérieur de la mémoire tampon WaveRT. L’avantage ici dépend de la conception du moteur DMA ou d’un autre mécanisme de transfert de données entre la mémoire tampon WaveRT et le matériel (éventuellement DSP).
  • Les données capturées en rafale sont plus rapides que le temps réel si le pilote a accumulé des données capturées en interne. Cela est principalement destiné aux scénarios d’activation vocale, mais peut également s’appliquer pendant la diffusion en continu normale.
  • Fournissez des informations d’horodatage sur la position actuelle du flux plutôt que sur les estimations windows, ce qui permet potentiellement d’obtenir des informations de position précises.

Cette DDI est utile dans le cas où un DSP est utilisé. Toutefois, un pilote Audio HD standard ou d’autres conceptions de mémoire tampon DMA circulaires simples peuvent ne pas trouver beaucoup d’avantages dans ces nouvelles DDIs répertoriées ici.

Plusieurs routines de pilote retournent des horodatages du compteur de performances Windows qui reflètent l’heure à laquelle les exemples sont capturés ou présentés par l’appareil.

Dans les appareils qui ont des pipelines DSP et un traitement de signal complexes, le calcul d’un horodatage précis peut être difficile et doit être effectué de manière réfléchie. Les horodatages ne doivent pas refléter l’heure à laquelle les échantillons ont été transférés vers ou depuis Windows vers le DSP.

Pour calculer les valeurs du compteur de performances, le pilote et le DSP peuvent utiliser certaines des méthodes suivantes.

  • Dans le DSP, suivez les exemples d’horodatages à l’aide d’une horloge murale DSP interne.
  • Entre le pilote et le DSP, calculez une corrélation entre le compteur de performances Windows et l’horloge murale DSP. Les procédures peuvent aller de simples (mais moins précises) à assez complexes ou nouvelles (mais plus précises).
  • Tenez compte des retards constants dus aux algorithmes de traitement du signal ou aux transports de pipeline ou matériels, sauf si ces retards sont pris en compte.

L’exemple sysvad montre comment utiliser les DDIs ci-dessus.

Inscrire des ressources de pilote

Pour garantir un fonctionnement sans problème, les pilotes audio doivent inscrire leurs ressources de streaming auprès de Portcls. Cela permet à Windows de gérer les ressources afin d’éviter les interférences entre la diffusion en continu audio et d’autres sous-systèmes.

Les ressources de flux sont toutes les ressources utilisées par le pilote audio pour traiter les flux audio ou garantir le flux de données audio. Seuls deux types de ressources de flux sont pris en charge : les interruptions et les threads appartenant au pilote. Les pilotes audio doivent inscrire une ressource après avoir créé la ressource et annuler l’inscription de la ressource avant de la supprimer.

Les pilotes audio peuvent inscrire des ressources au moment de l’initialisation au moment du chargement du pilote, ou au moment de l’exécution, par exemple en cas de rééquilibrage des ressources d’E/S. Portcls utilise un état global pour effectuer le suivi de toutes les ressources de streaming audio.

Dans certains cas d’usage, tels que ceux nécessitant une très faible latence audio, Windows tente d’isoler les ressources inscrites du pilote audio des interférences d’autres activités de système d’exploitation, d’application et de matériel. Le système d’exploitation et le sous-système audio effectuent cette opération en fonction des besoins sans interagir avec le pilote audio, à l’exception de l’inscription des ressources par le pilote audio.

Cette exigence d’inscription des ressources de flux implique que tous les pilotes qui se trouvent dans le chemin du pipeline de streaming doivent inscrire leurs ressources directement ou indirectement auprès de Portcls. Le pilote de miniport audio dispose des options suivantes :

  • Le pilote de miniport audio est le pilote inférieur de sa pile (interfaçage direct du h/w). Dans ce cas, le pilote connaît ses ressources de flux et peut les inscrire auprès de Portcls.
  • Le pilote de miniport audio diffuse de l’audio avec l’aide d’autres pilotes (par exemple, les pilotes de bus audio). Ces autres pilotes utilisent également des ressources qui doivent être inscrites auprès de Portcls. Ces piles de pilotes parallèles/bus peuvent exposer une interface publique (ou privée, si un seul fournisseur possède tous les pilotes) que les pilotes de miniport audio utilisent pour collecter ces informations.
  • Le pilote de miniport audio diffuse de l’audio avec l’aide d’autres pilotes (par exemple hdaudbus). Ces autres pilotes utilisent également des ressources qui doivent être inscrites auprès de Portcls. Ces pilotes parallèles/bus peuvent établir une liaison avec Portcls et inscrire directement leurs ressources. Les pilotes de miniport audio doivent informer Portcls qu’ils dépendent des ressources de ces autres périphériques parallèles/bus (PPO). L’infrastructure audio HD utilise cette option, c’est-à-dire que le pilote de bus audio HD est lié à Portcls et effectue automatiquement les étapes suivantes :
    • enregistre les ressources de son pilote de bus, et
    • avertit Portcls que les ressources des enfants dépendent des ressources du parent. Dans l’architecture audio HD, le pilote de miniport audio doit simplement inscrire ses propres ressources de thread appartenant au pilote.

Remarques :

  • Les pilotes de fonction miniport HDAudio énumérés par le pilote de bus HDAudio de boîte de réception hdaudbus.sys n’ont pas besoin d’enregistrer les interruptions HDAudio, car cela est déjà fait par hdaudbus.sys. Toutefois, si le pilote miniport crée ses propres threads, il doit les inscrire.
  • Les pilotes qui sont liés à Portcls uniquement pour l’inscription des ressources de streaming doivent mettre à jour leurs infs pour inclure wdmaudio.inf et copier les portcls.sys (et les fichiers dépendants). Une nouvelle section de copie INF est définie dans wdmaudio.inf pour copier uniquement ces fichiers.
  • Les pilotes audio qui s’exécutent uniquement dans Windows 10 et versions ultérieures peuvent être liés en dur à :
  • Les pilotes audio qui doivent s’exécuter sur un système d’exploitation de bas niveau peuvent utiliser l’interface suivante (le miniport peut appeler QueryInterface pour l’interface IID_IPortClsStreamResourceManager et inscrire ses ressources uniquement lorsque PortCls prend en charge l’interface).
  • Ces DDIs utilisent cette énumération et cette structure :

Enfin, les pilotes qui lient des PortCls dans le seul but d’inscrire des ressources doivent ajouter les deux lignes suivantes dans la section DDInstall de leur inf. Les pilotes de miniport audio n’en ont pas besoin, car ils ont déjà include/needs dans wdmaudio.inf.

[<install-section-name>]
Include=wdmaudio.inf
Needs=WDMPORTCLS.CopyFilesOnly

Les lignes ci-dessus vérifient que PortCls et ses fichiers dépendants sont installés.

Outils de mesure

Pour mesurer la latence d’aller-retour, l’utilisateur peut utiliser des outils qui jouent des impulsions via les haut-parleurs et les capturent via le microphone. Ils mesurent le délai du chemin d’accès suivant :

  1. L’application appelle l’API de rendu (AudioGraph ou WASAPI) pour lire l’impulsion
  2. L’audio est lu via les haut-parleurs
  3. L’audio est capturé à partir du microphone
  4. L’impulsion est détectée par l’API de capture (AudioGraph ou WASAPI) Afin de mesurer la latence d’aller-retour pour différentes tailles de mémoire tampon, les utilisateurs doivent installer un pilote qui prend en charge les petites mémoires tampons. Le pilote HDAudio de boîte de réception a été mis à jour pour prendre en charge des tailles de mémoire tampon comprises entre 128 échantillons (2.66ms@48kHz) et 480 échantillons (10ms@48kHz). Les étapes suivantes montrent comment installer le pilote HDAudio de boîte de réception (qui fait partie de toutes les références SKU Windows 10 et ultérieures) :
  • Démarrez le Gestionnaire de périphériques.
  • Sous Contrôleurs vidéo et de jeu audio, double-cliquez sur l’appareil correspondant à vos haut-parleurs internes.
  • Dans la fenêtre suivante, accédez à l’onglet Pilote .
  • Sélectionnez Mettre à jour le pilote ->Parcourir mon ordinateur à la recherche de logiciels pilotes ->Permettez-moi de choisir dans une liste de pilotes de périphérique sur cet ordinateur ->Sélectionnez Périphérique audio haute définition , puis sélectionnez Suivant.
  • Si une fenêtre intitulée « Avertissement de mise à jour du pilote » s’affiche, sélectionnez Oui.
  • Sélectionnez Fermer.
  • Si vous êtes invité à redémarrer le système, sélectionnez Oui pour redémarrer.
  • Après le redémarrage, le système utilise le pilote Microsoft HDAudio de boîte de réception et non le pilote de codec tiers. N’oubliez pas le pilote que vous utilisiez précédemment afin de pouvoir revenir à ce pilote si vous souhaitez utiliser les paramètres optimaux pour votre codec audio.

Graphique illustrant les différences de latence d’aller-retour entre WASAPI et AudioGraph pour différentes tailles de mémoire tampon.

Les différences de latence entre WASAPI et AudioGraph sont dues aux raisons suivantes :

  • AudioGraph ajoute une mémoire tampon de latence côté capture, afin de synchroniser le rendu et la capture, ce qui n’est pas fourni par WASAPI. Cet ajout simplifie le code des applications écrites à l’aide d’AudioGraph.
  • Il existe une autre mémoire tampon de latence dans le côté de rendu d’AudioGraph lorsque le système utilise des mémoires tampons supérieures à 6 ms.
  • AudioGraph n’a pas la possibilité de désactiver les effets audio de capture.

Exemples

Forum aux questions

Ne serait-il pas préférable que toutes les applications utilisent les nouvelles API pour une faible latence ? Une faible latence ne garantit-elle pas toujours une meilleure expérience utilisateur ?

Pas nécessairement. La faible latence a ses inconvénients :

  • Une faible latence signifie une consommation d’énergie plus élevée. Si le système utilise des mémoires tampons de 10 ms, cela signifie que le processeur se réveille toutes les 10 ms, remplit la mémoire tampon de données et se met en veille. Toutefois, si le système utilise des mémoires tampons de 1 ms, cela signifie que le processeur se réveille toutes les 1 ms. Dans le deuxième scénario, cela signifie que le processeur se réveille plus souvent et que la consommation d’énergie augmente. Cela diminuera l’autonomie de la batterie.
  • La plupart des applications s’appuient sur des effets audio pour offrir la meilleure expérience utilisateur. Par exemple, les lecteurs multimédias veulent fournir un audio haute fidélité. Les applications de communication veulent un minimum d’écho et de bruit. L’ajout de ces types d’effets audio à un flux augmente sa latence. Ces applications s’intéressent davantage à la qualité audio qu’à la latence audio.

En résumé, chaque type d’application a des besoins différents en ce qui concerne la latence audio. Si une application n’a pas besoin d’une faible latence, elle ne doit pas utiliser les nouvelles API pour une faible latence.

Tous les systèmes qui sont mis à jour vers Windows 10 et ultérieurement seront-ils automatiquement mis à jour pour prendre en charge les petites mémoires tampons ? Tous les systèmes prendront-ils en charge la même taille de mémoire tampon minimale ?

Non, pour qu’un système prend en charge de petites mémoires tampons, il doit disposer de pilotes mis à jour. Il appartient aux fabricants OEM de décider quels systèmes seront mis à jour pour prendre en charge les petites mémoires tampons. En outre, les systèmes plus récents sont plus susceptibles de prendre en charge des mémoires tampons plus petites que les systèmes plus anciens. La latence dans les nouveaux systèmes sera probablement inférieure à celle des systèmes plus anciens.

Si un pilote prend en charge de petites tailles de mémoire tampon, toutes les applications de Windows 10 et ultérieures utilisent-elles automatiquement de petites mémoires tampons pour afficher et capturer l’audio ?

Non, par défaut, toutes les applications dans Windows 10 et versions ultérieures utilisent des mémoires tampons de 10 ms pour afficher et capturer l’audio. Si une application doit utiliser de petites mémoires tampons, elle doit utiliser les nouveaux paramètres AudioGraph ou l’interface WASAPI IAudioClient3 pour ce faire. Toutefois, si une application demande l’utilisation de petites mémoires tampons, le moteur audio commence à transférer l’audio à l’aide de cette taille de mémoire tampon particulière. Dans ce cas, toutes les applications qui utilisent le même point de terminaison et le même mode basculeront automatiquement vers cette petite taille de mémoire tampon. Lorsque l’application à faible latence se ferme, le moteur audio bascule à nouveau vers des mémoires tampons de 10 ms.