Audio met lage latentie
In dit artikel worden wijzigingen in de audiolatentie in Windows 10 besproken. Het behandelt API-opties voor toepassingsontwikkelaars en wijzigingen in stuurprogramma's die kunnen worden aangebracht ter ondersteuning van audio met lage latentie. Audiolatentie is de vertraging tussen die tijd dat geluid wordt gemaakt en wanneer het wordt gehoord. Lage audiolatentie is belangrijk voor verschillende belangrijke scenario's, zoals:
- Pro-audio
- Muziek maken
- Communicatie
- Virtual reality
- Games
De doelstellingen van dit document zijn:
- Beschrijf de bronnen van audiolatentie in Windows.
- Leg de wijzigingen uit die de audiolatentie in de Windows 10-audiostack verminderen.
- Geef een referentie over hoe ontwikkelaars van toepassingen en hardwarefabrikanten kunnen profiteren van de nieuwe infrastructuur om toepassingen en stuurprogramma's met een lage audiolatentie te ontwikkelen.
In dit artikel wordt het volgende behandeld:
- De AudioGraph-API voor interactieve scenario's en het maken van media.
- Wijzigingen in WASAPI ter ondersteuning van lage latentie.
- Verbeteringen in de DDIs van het stuurprogramma.
Terminologie
Term | Beschrijving |
---|---|
Latentie weergeven | Vertraging tussen de tijd dat een toepassing een buffer met audiogegevens naar de render-API's verzendt, tot het tijdstip waarop deze van de luidsprekers wordt gehoord. |
Latentie vastleggen | Vertraging tussen de tijd dat een geluid wordt vastgelegd vanaf de microfoon, totdat het wordt verzonden naar de capture-API's die door de toepassing worden gebruikt. |
Retourlatentie | Vertraging tussen de tijd dat een geluid wordt vastgelegd vanaf de microfoon, verwerkt door de toepassing en door de toepassing verzonden voor rendering naar de luidsprekers. Het is ongeveer gelijk aan renderlatentie plus capturerlatentie. |
Aanraakvertraging naar app | Vertraging tussen de tijd waarop een gebruiker op het scherm tikt totdat het signaal naar de toepassing wordt verzonden. |
Latentie van aanraak naar geluid | Vertraging tussen het moment waarop een gebruiker op het scherm tikt, de gebeurtenis naar de toepassing gaat, en er een geluid via de luidsprekers wordt gehoord. Het is gelijk aan de weergavelatentie + touch-to-app-latentie. |
Windows-audiostack
In het volgende diagram ziet u een vereenvoudigde versie van de Windows-audiostack.
Hier volgt een samenvatting van de latenties in het renderpad: audioverwerkingsobjecten
De toepassing schrijft de gegevens naar een buffer
De audio-engine leest de gegevens uit de buffer en verwerkt deze. Het laadt ook audio-effecten in de vorm van audioverwerkingsobjecten (API's). Zie Windows-audioverwerkingsobjectenvoor meer informatie over API's.
De latentie van de API's varieert op basis van de signaalverwerking binnen de API's.
Vóór Windows 10 was de latentie van de audio-engine gelijk aan ~12 ms voor toepassingen die drijvendekommagegegevens gebruiken en ~6 ms voor toepassingen die gehele getallen gebruiken
In Windows 10 en hoger is de latentie gereduceerd tot 1,3 ms voor alle toepassingen
De audio-engine schrijft de verwerkte gegevens naar een buffer.
Voor Windows 10 is de buffer altijd ingesteld op ~10 ms.
Vanaf Windows 10 wordt de buffergrootte gedefinieerd door het audiostuurprogramma (meer informatie over de buffer wordt verderop in dit artikel beschreven).
Het audiostuurprogramma leest de gegevens uit de buffer en schrijft ze naar de hardware.
De hardware kan de gegevens ook opnieuw verwerken in de vorm van meer audio-effecten.
De gebruiker hoort audio van de luidspreker.
Hier volgt een samenvatting van de latentie in het opnamepad:
Audio wordt vastgelegd vanaf de microfoon.
De hardware kan de gegevens verwerken. Als u bijvoorbeeld audio-effecten wilt toevoegen.
Het stuurprogramma leest de gegevens van de hardware en schrijft de gegevens naar een buffer.
Voor Windows 10 is deze buffer altijd ingesteld op 10 ms.
Vanaf Windows 10 wordt de buffergrootte gedefinieerd door het audiostuurprogramma (hieronder vindt u meer informatie).
De audio-engine leest de gegevens uit de buffer en verwerkt deze. Het laadt ook audio-effecten in de vorm van audioverwerkingsobjecten (API's).
De latentie van de API's varieert op basis van de signaalverwerking binnen de API's.
Vóór Windows 10 was de latentie van de audio-engine gelijk aan ~6 ms voor toepassingen die drijvendekommagegevens en ~0 ms gebruiken voor toepassingen die gehele getallen gebruiken.
In Windows 10 en hoger is de latentie beperkt tot ~0 ms voor alle toepassingen.
De toepassing wordt gesignaleerd dat er gegevens beschikbaar zijn om te worden gelezen zodra de audio-engine klaar is met de verwerking. De audiostack biedt ook de optie van exclusieve modus. In dat geval slaat de data de audio-engine over en gaat het rechtstreeks van de toepassing naar de buffer waar het stuurprogramma het leest. Als een toepassing echter een eindpunt opent in de exclusieve modus, is er geen andere toepassing die dat eindpunt kan gebruiken om audio weer te geven of vast te leggen.
Een ander populair alternatief voor toepassingen die lage latentie nodig hebben, is het ASIO-model (Audio Stream Input/Output), dat gebruikmaakt van de exclusieve modus. Nadat een gebruiker een ASIO-stuurprogramma van derden heeft geïnstalleerd, kunnen toepassingen gegevens rechtstreeks vanuit de toepassing verzenden naar het ASIO-stuurprogramma. De toepassing moet echter zodanig worden geschreven dat deze rechtstreeks met het ASIO-stuurprogramma praat.
Beide alternatieven (exclusieve modus en ASIO) hebben hun eigen beperkingen. Ze bieden lage latentie, maar ze hebben hun eigen beperkingen (waarvan sommige hierboven zijn beschreven). Als gevolg hiervan is de audio-engine gewijzigd om de latentie te verlagen, terwijl de flexibiliteit behouden blijft.
Verbeteringen in audiostack
Windows 10 en hoger zijn in drie gebieden verbeterd om de latentie te verminderen:
- Alle toepassingen die audio gebruiken, zien een vermindering van 4,5-16 ms in retourlatentie (zoals beschreven in de bovenstaande sectie) zonder codewijzigingen of stuurprogramma-updates, vergeleken met Windows 8.1.
- Toepassingen die gegevens met drijvende komma gebruiken, hebben een latentie die met 16 ms lager is.
- Toepassingen die gehele getallen gebruiken, hebben een lagere latentie van 4,5 ms.
- Systemen met bijgewerkte stuurprogramma's bieden nog lagere retourlatentie:
- Stuurprogramma's kunnen de DDIS's met lage latentie gebruiken om de ondersteunde grootten van de buffer te rapporteren die wordt gebruikt om gegevens over te dragen tussen Windows en de hardware. Gegevensoverdrachten hoeven niet altijd buffers van 10 ms te gebruiken, zoals in eerdere Windows-versies. In plaats daarvan kan het stuurprogramma opgeven of het kleine buffers kan gebruiken, bijvoorbeeld 5 ms, 3 ms, 1 ms, enzovoort.
- Toepassingen waarvoor lage latentie is vereist, kunnen gebruikmaken van de audio-API's met lage latentie (AudioGraph of WASAPI), om een query uit te voeren op de buffergrootten die door het stuurprogramma worden ondersteund en het te selecteren dat wordt gebruikt voor de gegevensoverdracht naar/van de hardware.
- Wanneer een toepassing buffergrootten onder een bepaalde drempelwaarde gebruikt om audio weer te geven en vast te leggen, wordt in Windows een speciale modus geactiveerd, waarbij de resources worden beheerd op een manier die interferentie tussen de audiostreaming en andere subsystemen voorkomt. Dit vermindert de onderbrekingen in de uitvoering van het audiosubsysteem en minimaliseert de kans op audiostoringen. Wanneer de toepassing stopt met streamen, keert Windows terug naar de normale uitvoeringsmodus. Het audiosubsysteem bestaat uit de volgende resources:
- De audio engine-thread die audio met lage latentie verwerkt.
- Alle threads en interrupts die zijn geregistreerd door het stuurprogramma (met behulp van de DDIS's met lage latentie die worden beschreven in de sectie over de registratie van stuurprogrammaresources).
- Sommige of alle audiothreads van de toepassingen die kleine buffers aanvragen, en van alle toepassingen die dezelfde audioapparaatgrafiek delen (bijvoorbeeld dezelfde signaalverwerkingsmodus) met elke toepassing waarvoor kleine buffers zijn aangevraagd:
- AudioGraph-callbacks op het streamingpad.
- Als de toepassing WASAPI gebruikt, worden alleen de werkitems die zijn verzonden naar de Real-Time Werkwachtrij-API of MFCreateMFByteStreamOnStreamEx en gelabeld als 'Audio' of 'ProAudio'.
API-verbeteringen
De volgende twee Windows 10-API's bieden mogelijkheden voor lage latentie:
Ga als volgt te werk om te bepalen welke van de twee API's u wilt gebruiken:
- Geef de voorkeur aan AudioGraph, waar mogelijk, voor de ontwikkeling van nieuwe toepassingen.
- Gebruik alleen WASAPI als:
- U hebt meer controle nodig dan die van AudioGraph.
- U hebt een lagere latentie nodig dan die van AudioGraph.
In de meethulpmiddelen sectie van dit artikel ziet u specifieke metingen van een Haswell-systeem met behulp van het POSTVAK HDAudio-stuurprogramma.
In de volgende secties worden de mogelijkheden voor lage latentie in elke API uitgelegd. Zoals in de vorige sectie is opgemerkt, moet het systeem bijgewerkte stuurprogramma's hebben die ondersteuning bieden voor kleine buffergrootten om de minimale latentie te bereiken.
AudioGraph
AudioGraph is een Universal Windows Platform API in Windows 10 en hoger die is gericht op het realiseren van interactieve en muziek creatie scenario's met gemak. AudioGraph is beschikbaar in verschillende programmeertalen (C++, C#, JavaScript) en heeft een eenvoudig en functierijk programmeermodel.
AudioGraph biedt de eigenschap AudioGraphSettings::QuantumSizeSelectionMode om scenario's met lage latentie te bereiken. Deze eigenschap kan een van de waarden zijn die worden weergegeven in de onderstaande tabel:
Waarde | Beschrijving |
---|---|
Systeemstandaard | Hiermee stelt u de buffer in op de standaardbuffergrootte (~10 ms) |
Laagste Latentie | Hiermee stelt u de buffer in op de minimumwaarde die wordt ondersteund door het stuurprogramma |
DichtstBijGewenst | Hiermee stelt u in dat de buffergrootte gelijk is aan de waarde die is gedefinieerd door de eigenschap DesiredSamplesPerQuantum of op een waarde die net zo dicht bij DesiredSamplesPerQuantum staat als wordt ondersteund door het stuurprogramma. |
Het AudioCreation-voorbeeld laat zien hoe u AudioGraph gebruikt voor lage latentie. In het volgende codefragment ziet u hoe u de minimale buffergrootte instelt:
AudioGraphSettings settings = new AudioGraphSettings(AudioRenderCategory.Media);
settings.QuantumSizeSelectionMode = QuantumSizeSelectionMode.LowestLatency;
CreateAudioGraphResult result = await AudioGraph.CreateAsync(settings);
Windows-audiosessie-API (WASAPI)
Vanaf Windows 10 is WASAPI uitgebreid tot:
- Sta een toepassing toe om het bereik van buffergrootten (dat wil gezegd, periodiciteitswaarden) te detecteren die worden ondersteund door het audiostuurprogramma van een bepaald audioapparaat. Hierdoor kan een toepassing kiezen tussen de standaardbuffergrootte (10 ms) of een kleine buffer (minder dan 10 ms) bij het openen van een stream in de gedeelde modus. Als een toepassing geen buffergrootte opgeeft, wordt de standaardbuffergrootte gebruikt.
- Hiermee kan een toepassing de huidige indeling en de periodiciteit van de audio-engine detecteren. Hierdoor kunnen toepassingen zich aanpassen aan de huidige instellingen van de audio-engine.
- Toestaan dat een app aangeeft dat deze wil weergeven of vastleggen in de opgegeven indeling, zonder dat de audio-engine een herbemonstering uitvoert.
De bovenstaande functies zijn beschikbaar op alle Windows-apparaten. Bepaalde apparaten met voldoende resources en bijgewerkte stuurprogramma's bieden echter een betere gebruikerservaring dan andere.
De bovenstaande functionaliteit wordt geleverd door een interface, genaamd IAudioClient3, die is afgeleid van IAudioClient2.
IAudioClient3 definieert de volgende drie methoden:
Methode | Beschrijving |
---|---|
HuidigeGedeeldeModusEnginePeriodeVerkrijgen | Retourneert de huidige indeling en de periodiciteit van de audio-engine |
GetSharedModeEnginePeriod | Retourneert het bereik van periodieke gebeurtenissen die door de engine worden ondersteund voor de opgegeven stroomindeling |
InitializeSharedAudioStream (Initialiseer Gedeelde Audiostream) | Initialiseert een gedeelde stream met de opgegeven periodiciteit |
Het WASAPIAudio-voorbeeld laat zien hoe u IAudioClient3 gebruikt voor lage latentie.
In het volgende codefragment ziet u hoe een app voor het maken van muziek kan werken in de laagste latentie-instelling die wordt ondersteund door het systeem.
// 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)) {
...
}
Voor toepassingen die WASAPI gebruiken, raadt Microsoft aan om de Real-Time Work Queue-API of de MFCreateMFByteStreamOnStreamEx- te gebruiken om werkitems te maken en te taggen als Audio of Pro Audio, in plaats van hun eigen threads. Hierdoor kan Windows deze op een manier beheren waardoor interferentie tegen niet-audio-subsystemen wordt voorkomen. Alle AudioGraph-threads worden daarentegen automatisch correct beheerd door Windows. Het volgende codefragment uit het WASAPIAudio-voorbeeld laat zien hoe u de MF Work Queue-API's gebruikt.
// 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 );
Het volgende codefragment laat ook zien hoe u de RT Work Queue-API's gebruikt.
#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;
}
Ten slotte moeten toepassingsontwikkelaars die GEBRUIKMAKEN van WASAPI hun streams taggen met de audiocategorie en of ze de modus voor onbewerkte signaalverwerking moeten gebruiken, op basis van de functionaliteit van elke stream. Microsoft raadt aan dat alle audiostreams niet gebruikmaken van de onbewerkte signaalverwerkingsmodus, tenzij de implicaties worden begrepen. De onbewerkte modus omzeilt alle signaalverwerking die is gekozen door de OEM, dus:
- Het rendersignaal voor een bepaald eindpunt kan suboptimaal zijn.
- Het opnamesignaal kan een indeling hebben die de toepassing niet begrijpt.
- De latentie kan worden verbeterd.
Verbeteringen van stuurprogramma's
Om ervoor te zorgen dat audiostuurprogramma's ondersteuning bieden voor lage latentie, bieden Windows 10 en hoger de volgende functies:
- [Verplicht] Declareer de minimale buffergrootte die in elke modus wordt ondersteund.
- [Optioneel, maar aanbevolen] Verbeter de coördinatie voor de gegevensstroom tussen het stuurprogramma en Windows.
- [Optioneel, maar aanbevolen] Registreer de stuurprogrammabronnen (interrupts, threads), zodat ze kunnen worden beveiligd door Windows in scenario's met lage latentie. HDAudio miniport-functiestuurprogramma's die zijn geïnventariseerd door de inbox HDAudio-busstuurprogramma hdaudbus.sys hoeven de HDAudio-interrupts niet te registreren, aangezien dit al wordt gedaan door hdaudbus.sys. Als het minipoortstuurprogramma echter zijn eigen threads maakt, moet het deze registreren.
In de volgende drie secties wordt elke functie uitgebreider uitgelegd.
De minimale buffergrootte declareren
Een stuurprogramma werkt onder verschillende beperkingen bij het verplaatsen van audiogegevens tussen Windows, het stuurprogramma en de hardware. Deze beperkingen kunnen worden veroorzaakt door het fysieke hardwaretransport dat gegevens verplaatst tussen het geheugen en de hardware, of vanwege de signaalverwerkingsmodules binnen de hardware of gekoppelde DSP.
Vanaf Windows 10 versie 1607 kan het stuurprogramma zijn mogelijkheden voor buffergrootte uitdrukken met behulp van de apparateigenschap DEVPKEY_KsAudio_PacketSize_Constraints2. Met deze eigenschap kan de gebruiker de absolute minimale buffergrootte definiëren die wordt ondersteund door het stuurprogramma en specifieke buffergroottebeperkingen voor elke signaalverwerkingsmodus. De modusspecifieke beperkingen moeten hoger zijn dan de minimale buffergrootte van de stuurprogramma's, anders worden ze genegeerd door de audiostack.
In het volgende codefragment ziet u bijvoorbeeld hoe een stuurprogramma kan declareren dat de absolute minimaal ondersteunde buffergrootte 2 ms is, maar dat de standaardmodus 128 frames ondersteunt, wat overeenkomt met 3 ms als we uitgaan van een samplefrequentie van 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
},
}
};
Zie de volgende artikelen voor uitgebreidere informatie over deze structuren:
- KSAUDIO_PACKETSIZE_CONSTRAINTS structuur
- KSAUDIO_PACKETSIZE_CONSTRAINTS2 structuur
- KSAUDIO_PACKETSIZE_PROCESSINGMODE_CONSTRAINT structuur
Het sysvad-voorbeeld laat ook zien hoe u deze eigenschappen kunt gebruiken, zodat een stuurprogramma de minimale buffer voor elke modus kan declareren.
De coördinatie tussen stuurprogramma en besturingssysteem verbeteren
Met de DDIS's die in deze sectie worden beschreven, kan het stuurprogramma het volgende doen:
- Geef duidelijk aan welke helft (pakket) van de buffer beschikbaar is voor Windows, in plaats van het besturingssysteem te raden op basis van een codeckoppelingspositie. Dit helpt Windows om sneller te herstellen van audiofoutjes.
- U kunt eventueel de gegevensoverdracht in en uit de WaveRT-buffer optimaliseren of vereenvoudigen. De mate van voordeel hier is afhankelijk van het ontwerp van de DMA-engine of een ander mechanisme voor gegevensoverdracht tussen de WaveRT-buffer en (mogelijk DSP)-hardware.
- 'Burst' legt gegevens sneller vast dan in realtime, als het stuurprogramma intern gegevens heeft verzameld. Dit is voornamelijk bedoeld voor spraakactiveringsscenario's, maar kan ook worden toegepast tijdens normale streaming.
- Geef tijdstempelinformatie op over de huidige stroompositie in plaats van Windows-schattingen, waardoor mogelijk nauwkeurige positiegegevens kunnen worden gebruikt.
Deze DDI is handig in het geval dat een DSP wordt gebruikt. Een standaard HD Audio-stuurprogramma of andere eenvoudige ronde DMA-bufferontwerpen kunnen echter niet veel voordeel vinden in deze DDIS's die hier worden vermeld.
Verschillende van de stuurprogrammaroutines retourneren tijdstempels van Windows-prestatiemeteritems die de tijd weerspiegelen waarop steekproeven worden vastgelegd of gepresenteerd door het apparaat.
Bij apparaten met complexe DSP-pijplijnen en signaalverwerking kan het berekenen van een nauwkeurige tijdstempel lastig zijn en moet het zorgvuldig gebeuren. De tijdstempels mogen niet overeenkomen met het tijdstip waarop steekproeven zijn overgebracht naar of van Windows naar de DSP.
Als u de prestatiemeteritems wilt berekenen, kunnen het stuurprogramma en de DSP een aantal van de volgende methoden gebruiken.
- In de DSP kunt u voorbeeldtijdstempels bijhouden met behulp van een interne DSP-wandklok.
- Bereken tussen het stuurprogramma en DSP een correlatie tussen het Windows-prestatiemeteritem en de DSP-wandklok. Procedures hiervoor kunnen variëren van eenvoudig (maar minder nauwkeurig) tot redelijk complex of nieuw (maar nauwkeuriger).
- Houd rekening met eventuele constante vertragingen als gevolg van signaalverwerkingsalgoritmen of pijplijn- of hardwaretransporten, tenzij deze vertragingen anders worden gerekend.
In het sysvad-voorbeeld ziet u hoe u de bovenstaande DDIS's gebruikt.
Stuurprogrammabronnen registreren
Audiostuurprogramma's moeten hun streaming-resources registreren bij Portcls om te zorgen voor een foutloze werking. Hierdoor kan Windows resources beheren om interferentie tussen audiostreaming en andere subsystemen te voorkomen.
Stream-resources zijn resources die door het audiostuurprogramma worden gebruikt om audiostreams te verwerken of ervoor te zorgen dat de audiogegevensstroom verloopt. Er worden slechts twee typen streambronnen ondersteund: interrupts en threads die eigendom zijn van het stuurprogramma. Audiostuurprogramma's moeten een resource registreren nadat de resource is gemaakt en de registratie van de resource ongedaan maken voordat deze is verwijderd.
Audiostuurprogramma's kunnen resources registreren tijdens de initialisatie wanneer het stuurprogramma wordt geladen of tijdens runtime, bijvoorbeeld wanneer er een I/O-resource opnieuw wordt verdeeld. Portcls gebruikt een globale status om alle audiostreamingresources bij te houden.
In sommige gebruiksscenario's, zoals degenen die zeer lage latentieaudio vereisen, probeert Windows de geregistreerde bronnen van het audiostuurprogramma te isoleren van interferentie van andere besturingssysteem-, toepassings- en hardwareactiviteit. Het besturingssysteem en het audiosubsysteem doen dit wanneer het nodig is zonder interactie met het audiostuurprogramma, behalve voor de registratie van de resources door het audiostuurprogramma.
Deze vereiste voor het registreren van streamresources impliceert dat alle stuurprogramma's die zich in het pad voor de streamingpijplijn bevinden, hun resources direct of indirect moeten registreren bij Portcls. Het stuurprogramma voor de audio miniport heeft de volgende opties:
- Het audio-minipoortstuurprogramma is het onderste stuurprogramma van de stack (rechtstreeks aan de h/w koppelen), in dit geval kent het stuurprogramma de streambronnen en kan het deze registreren bij Portcls.
- Het minipoort-audiostuurprogramma streamt audio met behulp van andere stuurprogramma's (bijvoorbeeld audiobusstuurprogramma's). Deze andere stuurprogramma's gebruiken ook resources die moeten worden geregistreerd bij Portcls. Deze parallelle/busstuurprogrammastapels kunnen een openbare (of privé-)interface beschikbaar stellen, indien één leverancier eigenaar is van alle stuurprogramma's, die door audio-minipoortstuurprogramma's wordt gebruikt om deze informatie te verzamelen.
- Het audio-minipoortstuurprogramma streamt audio met behulp van andere stuurprogramma's (bijvoorbeeld hdaudbus). Deze andere stuurprogramma's gebruiken ook resources die moeten worden geregistreerd bij Portcls. Deze parallelle/busstuurprogramma's kunnen worden gekoppeld aan Portcls en hun resources rechtstreeks registreren. De audio-minipoortstuurprogramma's moeten Portcls laten weten dat ze afhankelijk zijn van de resources van deze andere parallelle/busappara(a)ten (PDO's). De HD-audio-infrastructuur maakt gebruik van deze optie: het HD-audiobusstuurprogramma is gekoppeld aan Portcls en voert automatisch de volgende stappen uit:
- registreert de middelen van de buschauffeur en
- Geeft Portcls een bericht dat de resources van de onderliggende items afhankelijk zijn van de resources van het bovenliggende item. In de HD-audioarchitectuur hoeft het audio-minipoortstuurprogramma alleen maar zijn eigen, aan het stuurprogramma toebehorende threadbronnen te registreren.
Notities:
- HDAudio miniport-functiestuurprogramma's die door het ingebouwde HDAudio-busstuurprogramma hdaudbus.sys zijn geïdentificeerd, hoeven de HDAudio-interrupts niet te registreren, omdat dit al wordt gedaan door hdaudbus.sys. Als het minipoortstuurprogramma echter zijn eigen threads maakt, moeten deze worden geregistreerd.
- Stuurprogramma's die alleen aan Portcls zijn gekoppeld voor het registreren van streaming-resources, moeten hun INFs bijwerken om wdmaudio.inf op te nemen en portcls.sys (en afhankelijke bestanden) te kopiëren. Er wordt een nieuwe INF-kopieersectie gedefinieerd in wdmaudio.inf om alleen die bestanden te kopiëren.
- Audiostuurprogramma's die alleen draaien in Windows 10 en hoger, kunnen hard-links maken naar:
- Audiostuurprogramma's die op een lager besturingssysteem moeten worden uitgevoerd, kunnen de volgende interface gebruiken (de minipoort kan QueryInterface aanroepen voor de IID_IPortClsStreamResourceManager-interface en de bijbehorende resources alleen registreren wanneer PortCls de interface ondersteunt).
- Deze DDIs's gebruiken deze opsomming en structuur:
Ten slotte moeten stuurprogramma's die PortCls koppelen voor het uitsluitende doel van het registreren van resources, de volgende twee regels toevoegen in de DDInstall-sectie van hun inf. Stuurprogramma's voor audio-miniports hebben dit niet nodig omdat ze al in wdmaudio.inf zijn opgenomen.
[<install-section-name>]
Include=wdmaudio.inf
Needs=WDMPORTCLS.CopyFilesOnly
De bovenstaande regels zorgen ervoor dat PortCls en de bijbehorende afhankelijke bestanden zijn geïnstalleerd.
Meethulpmiddelen
Om de rondreislatentie te meten, kan een gebruiker tools gebruiken die pulsen via de luidsprekers afspelen en deze via de microfoon vastleggen. Ze meten de vertraging van het volgende pad:
- De toepassing roept de render-API (AudioGraph of WASAPI) aan om de pulse af te spelen
- De audio wordt afgespeeld via de luidsprekers
- De audio wordt vastgelegd vanaf de microfoon
- De puls wordt gedetecteerd door de capture-API (AudioGraph of WASAPI) om de retourlatentie voor verschillende buffergrootten te meten, moeten gebruikers een stuurprogramma installeren dat kleine buffers ondersteunt. Het inbox HDAudio-stuurprogramma is bijgewerkt ter ondersteuning van buffergrootten tussen 128 samples (2.66ms@48kHz) en 480 samples (10ms@48kHz). De volgende stappen laten zien hoe u het ingebouwde HDAudio-stuurprogramma installeert (dat deel uitmaakt van alle Windows 10-SKU's en later):
- Apparaatbeheer starten.
- Dubbelklik onder Geluidsvideo- en gamecontrollersop het apparaat dat overeenkomt met uw interne luidsprekers.
- Ga in het volgende venster naar het tabblad Stuurprogramma.
- Selecteer Stuurprogramma bijwerken ->Blader op mijn computer naar stuurprogrammasoftware ->Laat ik kiezen uit een lijst met apparaatstuurprogramma's op deze computer ->Selecteer High Definition Audio Device en selecteer Volgende.
- Als er een venster met de titel Waarschuwing stuurprogramma bijwerken wordt weergegeven, selecteert u Ja.
- Selecteer sluiten.
- Als u wordt gevraagd het systeem opnieuw op te starten, selecteert u Ja om opnieuw op te starten.
- Na het herstarten van de computer gebruikt het systeem het ingebouwde Microsoft HDAudio-stuurprogramma en niet het codec-stuurprogramma van een derde partij. Onthoud welk stuurprogramma u eerder gebruikte, zodat u terug kunt vallen op dat stuurprogramma als u de optimale instellingen voor uw audiocodec wilt gebruiken.
De verschillen in de latentie tussen WASAPI en AudioGraph hebben de volgende oorzaken:
- AudioGraph voegt één buffer van latentie toe aan de opnamezijde om render en capture te synchroniseren, die niet wordt geleverd door WASAPI. Deze toevoeging vereenvoudigt de code voor toepassingen die zijn geschreven met Behulp van AudioGraph.
- Er is een andere buffer van latentie in de renderzijde van AudioGraph wanneer het systeem meer dan 6 ms buffers gebruikt.
- AudioGraph heeft niet de mogelijkheid om audio-effecten voor vastleggen uit te schakelen.
Monsters
FAQ
Zou het niet beter zijn als alle toepassingen gebruikmaken van de nieuwe API's voor lage latentie? Garandeert lage latentie altijd een betere gebruikerservaring?
Niet noodzakelijkerwijs. Lage latentie heeft zijn compromissen:
- Lage latentie betekent een hoger energieverbruik. Als het systeem buffers van 10 ms gebruikt, betekent dit dat de CPU elke 10 ms wakker wordt, de gegevensbuffer vult en naar de slaapstand gaat. Als het systeem echter buffers van 1 ms gebruikt, betekent dit dat de CPU elke 1 ms wakker wordt. In het tweede scenario betekent dit dat de CPU vaker wakker wordt en dat het energieverbruik toeneemt. Dit vermindert de levensduur van de batterij.
- De meeste toepassingen zijn afhankelijk van audio-effecten om de beste gebruikerservaring te bieden. Mediaspelers willen bijvoorbeeld hoogwaardige audio leveren. Communicatietoepassingen willen minimaal echo en ruis. Door deze typen audio-effecten toe te voegen aan een stream, wordt de latentie verhoogd. Deze toepassingen zijn meer geïnteresseerd in audiokwaliteit dan in audiolatentie.
Kortom, elk toepassingstype heeft verschillende behoeften met betrekking tot de audiolatentie. Als een toepassing geen lage latentie nodig heeft, moet deze de nieuwe API's niet gebruiken voor lage latentie.
Worden alle systemen die worden bijgewerkt naar Windows 10 en hoger automatisch bijgewerkt om kleine buffers te ondersteunen? Ondersteunen alle systemen dezelfde minimale buffergrootte?
Nee, om ervoor te zorgen dat een systeem ondersteuning biedt voor kleine buffers, moet het bijgewerkte stuurprogramma's hebben. Het is aan de OEM's om te bepalen welke systemen worden bijgewerkt ter ondersteuning van kleine buffers. Bovendien bieden nieuwere systemen meer kans om kleinere buffers te ondersteunen dan oudere systemen. De latentie in nieuwe systemen is waarschijnlijk lager dan oudere systemen.
Als een stuurprogramma kleine buffergrootten ondersteunt, gebruiken alle toepassingen in Windows 10 en hoger automatisch kleine buffers om audio weer te geven en vast te leggen?
Nee, standaard gebruiken alle toepassingen in Windows 10 en hoger buffers van 10 ms om audio weer te geven en vast te leggen. Als een toepassing kleine buffers moet gebruiken, moet deze de nieuwe AudioGraph-instellingen of de INTERFACE WASAPI IAudioClient3 gebruiken om dit te doen. Als één toepassing echter het gebruik van kleine buffers aanvraagt, wordt de audio-engine gestart met het overbrengen van audio met behulp van die specifieke buffergrootte. In dat geval schakelen alle toepassingen die gebruikmaken van hetzelfde eindpunt en dezelfde modus automatisch over naar die kleine buffergrootte. Wanneer de toepassing met lage latentie wordt afgesloten, wordt de audio-engine weer overgeschakeld naar buffers van 10 ms.