c++ - usuarios - ¿Cómo obtener una latencia inferior a 10 ms mediante el modo compartido WASAPI?
compartir libro excel 2016 en red local (1)
De acuerdo con Microsoft, a partir de Windows 10, las aplicaciones que usan WASAPI de modo compartido pueden solicitar tamaños de búfer de menos de 10 ms (consulte https://msdn.microsoft.com/en-us/library/windows/hardware/mt298187%28v=vs. 85% 29.aspx ).
Según el artículo, lograr tan bajas latencias requiere algunas actualizaciones de controladores, lo cual hice. Utilizando una secuencia de captura y captura en modo exclusivo, medí una latencia total de ida y vuelta (utilizando un cable de bucle invertido de hardware) de alrededor de 13 ms. Esto me sugiere que al menos uno de los puntos finales logra con éxito una latencia de <10ms. (¿Es correcta esta suposición?)
El artículo menciona que las aplicaciones pueden usar la nueva interfaz IAudioClient3
para consultar el tamaño mínimo de búfer admitido por el motor de audio de Windows utilizando IAudioClient3::GetSharedModeEnginePeriod()
. Sin embargo, esta función siempre devuelve 10 ms en mi sistema, y cualquier intento de inicializar una secuencia de audio utilizando IAudioClient::Initialize()
o IAudioClient3::InitializeSharedAudioStream()
con un período inferior a 10 ms siempre da como resultado AUDCLNT_E_INVALID_DEVICE_PERIOD
.
Solo para estar seguro, también deshabilité el procesamiento de efectos en los controladores de audio. ¿Qué me estoy perdiendo? ¿Es posible obtener baja latencia desde el modo compartido? Vea a continuación un código de muestra.
#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, ¤t));
// 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, ¤t));
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;
}
Per Hans en el comentario anterior, verifica que hayas seguido las instrucciones para el audio de baja latencia aquí .
Reiniciaría la máquina solo para estar seguro; Windows puede ser un poco quisquilloso con ese tipo de cosas.