2016-05-26 4 views
19

Laut Microsoft können Anwendungen, die WASAPI im gemeinsam genutzten Modus verwenden, ab Windows 10 Puffergrößen unter 10 ms anfordern (siehe https://msdn.microsoft.com/en-us/library/windows/hardware/mt298187%28v=vs.85%29.aspx).Wie erreicht man unter Verwendung des gemeinsamen WASAPI-Modus die 10-ms-Latenzzeit?

Laut dem Artikel erfordert das Erreichen solcher niedrigen Latenzen einige Treiberaktualisierungen, was ich getan habe. Mit einem Rendering- und Capture-Stream im exklusiven Modus habe ich eine Gesamt-Round-Trip-Latenz (mit einem Hardware-Loopback-Kabel) von etwa 13 ms gemessen. Dies deutet darauf hin, dass mindestens einer der Endpunkte erfolgreich eine Latenz von < 10ms erreicht. (Ist diese Annahme korrekt?)

Der Artikel erwähnt, dass Anwendungen die neue IAudioClient3-Schnittstelle verwenden können, um die Mindestpuffergröße abzufragen, die von der Windows-Audioengine unter Verwendung von IAudioClient3::GetSharedModeEnginePeriod() unterstützt wird. Diese Funktion gibt jedoch immer 10 ms auf meinem System zurück, und jeder Versuch, einen Audiostream unter Verwendung entweder IAudioClient::Initialize() oder IAudioClient3::InitializeSharedAudioStream() mit einer Periode unter 10ms zu initialisieren, führt immer zu AUDCLNT_E_INVALID_DEVICE_PERIOD.

Nur um sicher zu gehen, deaktivierte ich auch alle Effekte in den Audiotreibern. Was fehlt mir? Ist es überhaupt möglich, eine niedrige Latenz aus dem gemeinsam genutzten Modus zu erhalten? Siehe unten für einen Beispielcode.

#include <windows.h> 
#include <atlbase.h> 
#include <mmdeviceapi.h> 
#include <audioclient.h> 
#include <iostream> 

#define VERIFY(hr) do {         \ 
    auto temp = (hr);          \ 
    if(FAILED(temp)) {          \ 
    std::cout << "Error: " << #hr << ": " << temp << "\n"; \ 
    goto error;           \ 
    }              \ 
} while(0) 


int main(int argc, char** argv) { 

    HRESULT hr; 
    CComPtr<IMMDevice> device; 
    AudioClientProperties props; 
    CComPtr<IAudioClient> client; 
    CComPtr<IAudioClient2> client2; 
    CComPtr<IAudioClient3> client3; 
    CComHeapPtr<WAVEFORMATEX> format; 
    CComPtr<IMMDeviceEnumerator> enumerator; 

    REFERENCE_TIME minTime, maxTime, engineTime; 
    UINT32 min, max, fundamental, default_, current; 

    VERIFY(CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED)); 
    VERIFY(enumerator.CoCreateInstance(__uuidof(MMDeviceEnumerator))); 
    VERIFY(enumerator->GetDefaultAudioEndpoint(eRender, eMultimedia, &device)); 
    VERIFY(device->Activate(__uuidof(IAudioClient), CLSCTX_ALL, nullptr, reinterpret_cast<void**>(&client))); 
    VERIFY(client->QueryInterface(&client2)); 
    VERIFY(client->QueryInterface(&client3)); 

    VERIFY(client3->GetCurrentSharedModeEnginePeriod(&format, &current)); 

    // Always fails with AUDCLNT_E_OFFLOAD_MODE_ONLY. 
    hr = client2->GetBufferSizeLimits(format, TRUE, &minTime, &maxTime); 
    if(hr == AUDCLNT_E_OFFLOAD_MODE_ONLY) 
    std::cout << "GetBufferSizeLimits returned AUDCLNT_E_OFFLOAD_MODE_ONLY.\n"; 
    else if(SUCCEEDED(hr)) 
    std::cout << "hw min = " << (minTime/10000.0) << " hw max = " << (maxTime/10000.0) << "\n"; 
    else 
    VERIFY(hr); 

    // Correctly? reports a minimum hardware period of 3ms and audio engine period of 10ms. 
    VERIFY(client->GetDevicePeriod(&engineTime, &minTime)); 
    std::cout << "hw min = " << (minTime/10000.0) << " engine = " << (engineTime/10000.0) << "\n"; 

    // All values are set to a number of frames corresponding to 10ms. 
    // This does not change if i change the device's sampling rate in the control panel. 
    VERIFY(client3->GetSharedModeEnginePeriod(format, &default_, &fundamental, &min, &max)); 
    std::cout << "default = " << default_ 
      << " fundamental = " << fundamental 
      << " min = " << min 
      << " max = " << max 
      << " current = " << current << "\n"; 

    props.bIsOffload = FALSE; 
    props.cbSize = sizeof(props); 
    props.eCategory = AudioCategory_ForegroundOnlyMedia; 
    props.Options = AUDCLNT_STREAMOPTIONS_RAW | AUDCLNT_STREAMOPTIONS_MATCH_FORMAT; 

    // Doesn't seem to have any effect regardless of category/options values. 
    VERIFY(client2->SetClientProperties(&props)); 

    format.Free(); 
    VERIFY(client3->GetCurrentSharedModeEnginePeriod(&format, &current)); 
    VERIFY(client3->GetSharedModeEnginePeriod(format, &default_, &fundamental, &min, &max)); 
    std::cout << "default = " << default_ 
      << " fundamental = " << fundamental 
      << " min = " << min 
      << " max = " << max 
      << " current = " << current << "\n"; 

error: 
    CoUninitialize(); 
    return 0; 
} 
+0

Sicherlich ist dies ein Treiberproblem, nie ein Problem in Audio. Ich bekomme die gleichen grundlegenden Ergebnisse, Cirrus Logic CS4208 Treiberversion 6.6001.3.24 und Windows 10.0.10586. Du solltest deine nennen. –

+0

Getestet mit Onboard-HD-Audio mit "aktualisierten Treibern" wie im Artikel erwähnt. Ich werde wieder versuchen, eine andere Schnittstelle zu verwenden, auch scheint ich nicht zu finden, wo ich diese aktualisierten Treiber bekomme (aber ich weiß, dass es Windows-spezifische Treiber für niedrige Latenz war), also wäre es seltsam, wenn es wirklich ist eine Treibersache). Ich schaue hinein, um zu sehen, was genau auf meinem System ist. –

+0

Verstanden. Ich habe die Treiber wie hier erklärt verwendet: https://msdn.microsoft.com/en-us/library/windows/hardware/mt298187(v=vs.85).aspx#Measurement_Tools. Zitat: "Um die Roundtrip-Latenz für verschiedene Puffergrößen zu messen, müssen Benutzer einen Treiber installieren, der kleine Puffer unterstützt. Der HDAudio-Inbox-Treiber wurde aktualisiert, um Puffergrößen zwischen 128 Samples ([email protected]) und 480 Samples (10ms @ 48kHz) ". Werde versuchen, heute Abend ein anderes Gerät zu benutzen. –

Antwort

0

Per Hans im Kommentar oben, überprüfen Sie, dass Sie habe die Anweisungen für Low Latency Audio here gefolgt.

Ich würde die Maschine nur neu starten, um sicher zu sein; Windows kann mit dieser Art von Sache ein bisschen knifflig sein.

Verwandte Themen