From fe03981bbc20694fd6a4a61461727e02bf9192a8 Mon Sep 17 00:00:00 2001 From: "Diogo Franco (Kovensky)" Date: Thu, 6 Mar 2014 16:28:11 -0300 Subject: ao_wasapi: Slightly improve timer accuracy Use QueryPerformanceCounter to improve the accuracy of IAudioClock::GetPosition. While this is mainly for "realtime correctness" (usually the delay is a single sample or less), there are cases where IAudioClock::GetPosition takes a long time to return from its call (though the documentation doesn't define what a "long time" is), so correcting its value might be important in case the documented possible delay happens. --- audio/out/ao_wasapi.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/audio/out/ao_wasapi.c b/audio/out/ao_wasapi.c index fdca69c20c..39199159b3 100644 --- a/audio/out/ao_wasapi.c +++ b/audio/out/ao_wasapi.c @@ -121,6 +121,7 @@ typedef struct wasapi_state { IAudioClock *pAudioClock; UINT64 clock_frequency; /* scale for the "samples" returned by the clock */ UINT64 sample_count; /* the amount of samples per channel written to a GetBuffer buffer */ + LARGE_INTEGER qpc_frequency; /* frequency of windows' high resolution timer */ int opt_exclusive; int opt_list; @@ -528,6 +529,8 @@ static int init_clock(struct wasapi_state *state) { hr = IAudioClock_GetFrequency(state->pAudioClock, &state->clock_frequency); EXIT_ON_ERROR(hr); + QueryPerformanceFrequency(&state->qpc_frequency); + state->sample_count = 0; MP_VERBOSE(state, "IAudioClock::GetFrequency gave a frequency of %"PRIu64".\n", (uint64_t) state->clock_frequency); @@ -1362,19 +1365,25 @@ static int play(struct ao *ao, void **data, int samples, int flags) } static float get_device_delay(struct wasapi_state *state) { - /* where we pray that this hasn't desynced */ + /* where we pray that sample_count hasn't desynced */ mp_memory_barrier(); UINT64 sample_count = state->sample_count; - UINT64 position; + UINT64 position, qpc_position; HRESULT hr; - switch (hr = IAudioClock_GetPosition(state->pAudioClock, &position, NULL)) { + switch (hr = IAudioClock_GetPosition(state->pAudioClock, &position, &qpc_position)) { case S_OK: case S_FALSE: break; default: MP_ERR(state, "IAudioClock::GetPosition returned %s\n", explain_err(hr)); } + LARGE_INTEGER qpc_count; + QueryPerformanceCounter(&qpc_count); + UINT64 qpc_diff = (qpc_count.QuadPart * 10000000 / state->qpc_frequency.QuadPart) - qpc_position; + + position += state->clock_frequency * qpc_diff / 10000000; + /* convert position to the same base as sample_count */ position = position * state->format.Format.nSamplesPerSec / state->clock_frequency; -- cgit v1.2.3