wasapi: switched to event-driven interface.

This reduces latency and improves battery life.
This commit is contained in:
Ryan C. Gordon 2017-12-13 14:35:55 -05:00
parent 988034fcc7
commit ab4695f48f
2 changed files with 33 additions and 9 deletions

View File

@ -321,15 +321,21 @@ WASAPI_PlayDevice(_THIS)
static void static void
WASAPI_WaitDevice(_THIS) WASAPI_WaitDevice(_THIS)
{ {
while (RecoverWasapiIfLost(this) && this->hidden->client) { while (RecoverWasapiIfLost(this) && this->hidden->client && this->hidden->event) {
const UINT32 maxpadding = this->spec.samples; /*SDL_Log("WAITDEVICE");*/
UINT32 padding = 0; if (WaitForSingleObject(this->hidden->event, INFINITE) == WAIT_OBJECT_0) {
if (!WasapiFailed(this, IAudioClient_GetCurrentPadding(this->hidden->client, &padding))) { const UINT32 maxpadding = this->spec.samples;
if (padding <= maxpadding) { UINT32 padding = 0;
break; if (!WasapiFailed(this, IAudioClient_GetCurrentPadding(this->hidden->client, &padding))) {
/*SDL_Log("WASAPI EVENT! padding=%u maxpadding=%u", (unsigned int)padding, (unsigned int)maxpadding);*/
if (padding <= maxpadding) {
break;
}
} }
/* Sleep long enough for half the buffer to be free. */ } else {
SDL_Delay(((padding - maxpadding) * 1000) / this->spec.freq); /*SDL_Log("WASAPI FAILED EVENT!");*/
IAudioClient_Stop(this->hidden->client);
SDL_OpenedAudioDeviceDisconnected(this);
} }
} }
} }
@ -429,6 +435,8 @@ ReleaseWasapiDevice(_THIS)
{ {
if (this->hidden->client) { if (this->hidden->client) {
IAudioClient_Stop(this->hidden->client); IAudioClient_Stop(this->hidden->client);
IAudioClient_SetEventHandle(this->hidden->client, NULL);
IAudioClient_Release(this->hidden->client);
this->hidden->client = NULL; this->hidden->client = NULL;
} }
@ -456,6 +464,11 @@ ReleaseWasapiDevice(_THIS)
WASAPI_PlatformDeleteActivationHandler(this->hidden->activation_handler); WASAPI_PlatformDeleteActivationHandler(this->hidden->activation_handler);
this->hidden->activation_handler = NULL; this->hidden->activation_handler = NULL;
} }
if (this->hidden->event) {
CloseHandle(this->hidden->event);
this->hidden->event = NULL;
}
} }
static void static void
@ -517,6 +530,11 @@ WASAPI_PrepDevice(_THIS, const SDL_bool updatestream)
SDL_assert(client != NULL); SDL_assert(client != NULL);
this->hidden->event = CreateEventW(NULL, 0, 0, NULL);
if (this->hidden->event == NULL) {
return WIN_SetError("WASAPI can't create an event handle");
}
ret = IAudioClient_GetMixFormat(client, &waveformat); ret = IAudioClient_GetMixFormat(client, &waveformat);
if (FAILED(ret)) { if (FAILED(ret)) {
return WIN_SetErrorFromHRESULT("WASAPI can't determine mix format", ret); return WIN_SetErrorFromHRESULT("WASAPI can't determine mix format", ret);
@ -565,11 +583,16 @@ WASAPI_PrepDevice(_THIS, const SDL_bool updatestream)
return WIN_SetErrorFromHRESULT("WASAPI can't determine minimum device period", ret); return WIN_SetErrorFromHRESULT("WASAPI can't determine minimum device period", ret);
} }
ret = IAudioClient_Initialize(client, sharemode, 0, duration, sharemode == AUDCLNT_SHAREMODE_SHARED ? 0 : duration, waveformat, NULL); ret = IAudioClient_Initialize(client, sharemode, AUDCLNT_STREAMFLAGS_EVENTCALLBACK, duration, sharemode == AUDCLNT_SHAREMODE_SHARED ? 0 : duration, waveformat, NULL);
if (FAILED(ret)) { if (FAILED(ret)) {
return WIN_SetErrorFromHRESULT("WASAPI can't initialize audio client", ret); return WIN_SetErrorFromHRESULT("WASAPI can't initialize audio client", ret);
} }
ret = IAudioClient_SetEventHandle(client, this->hidden->event);
if (FAILED(ret)) {
return WIN_SetErrorFromHRESULT("WASAPI can't set event handle", ret);
}
ret = IAudioClient_GetBufferSize(client, &bufsize); ret = IAudioClient_GetBufferSize(client, &bufsize);
if (FAILED(ret)) { if (FAILED(ret)) {
return WIN_SetErrorFromHRESULT("WASAPI can't determine buffer size", ret); return WIN_SetErrorFromHRESULT("WASAPI can't determine buffer size", ret);

View File

@ -45,6 +45,7 @@ struct SDL_PrivateAudioData
IAudioRenderClient *render; IAudioRenderClient *render;
IAudioCaptureClient *capture; IAudioCaptureClient *capture;
SDL_AudioStream *capturestream; SDL_AudioStream *capturestream;
HANDLE event;
HANDLE task; HANDLE task;
SDL_bool coinitialized; SDL_bool coinitialized;
int framesize; int framesize;