wasapi: switched to event-driven interface.
authorRyan C. Gordon <icculus@icculus.org>
Wed, 13 Dec 2017 14:35:55 -0500
changeset 11776b4b29ae66d10
parent 11775 c5ecf88a2ddc
child 11777 5b29597e48b6
wasapi: switched to event-driven interface.

This reduces latency and improves battery life.
src/audio/wasapi/SDL_wasapi.c
src/audio/wasapi/SDL_wasapi.h
     1.1 --- a/src/audio/wasapi/SDL_wasapi.c	Tue Dec 12 22:25:39 2017 -0500
     1.2 +++ b/src/audio/wasapi/SDL_wasapi.c	Wed Dec 13 14:35:55 2017 -0500
     1.3 @@ -321,15 +321,21 @@
     1.4  static void
     1.5  WASAPI_WaitDevice(_THIS)
     1.6  {
     1.7 -    while (RecoverWasapiIfLost(this) && this->hidden->client) {
     1.8 -        const UINT32 maxpadding = this->spec.samples;
     1.9 -        UINT32 padding = 0;
    1.10 -        if (!WasapiFailed(this, IAudioClient_GetCurrentPadding(this->hidden->client, &padding))) {
    1.11 -            if (padding <= maxpadding) {
    1.12 -                break;
    1.13 +    while (RecoverWasapiIfLost(this) && this->hidden->client && this->hidden->event) {
    1.14 +        /*SDL_Log("WAITDEVICE");*/
    1.15 +        if (WaitForSingleObject(this->hidden->event, INFINITE) == WAIT_OBJECT_0) {
    1.16 +            const UINT32 maxpadding = this->spec.samples;
    1.17 +            UINT32 padding = 0;
    1.18 +            if (!WasapiFailed(this, IAudioClient_GetCurrentPadding(this->hidden->client, &padding))) {
    1.19 +                /*SDL_Log("WASAPI EVENT! padding=%u maxpadding=%u", (unsigned int)padding, (unsigned int)maxpadding);*/
    1.20 +                if (padding <= maxpadding) {
    1.21 +                    break;
    1.22 +                }
    1.23              }
    1.24 -            /* Sleep long enough for half the buffer to be free. */
    1.25 -            SDL_Delay(((padding - maxpadding) * 1000) / this->spec.freq);
    1.26 +        } else {
    1.27 +            /*SDL_Log("WASAPI FAILED EVENT!");*/
    1.28 +            IAudioClient_Stop(this->hidden->client);
    1.29 +            SDL_OpenedAudioDeviceDisconnected(this);
    1.30          }
    1.31      }
    1.32  }
    1.33 @@ -429,6 +435,8 @@
    1.34  {
    1.35      if (this->hidden->client) {
    1.36          IAudioClient_Stop(this->hidden->client);
    1.37 +        IAudioClient_SetEventHandle(this->hidden->client, NULL);
    1.38 +        IAudioClient_Release(this->hidden->client);
    1.39          this->hidden->client = NULL;
    1.40      }
    1.41  
    1.42 @@ -456,6 +464,11 @@
    1.43          WASAPI_PlatformDeleteActivationHandler(this->hidden->activation_handler);
    1.44          this->hidden->activation_handler = NULL;
    1.45      }
    1.46 +
    1.47 +    if (this->hidden->event) {
    1.48 +        CloseHandle(this->hidden->event);
    1.49 +        this->hidden->event = NULL;
    1.50 +    }
    1.51  }
    1.52  
    1.53  static void
    1.54 @@ -517,6 +530,11 @@
    1.55  
    1.56      SDL_assert(client != NULL);
    1.57  
    1.58 +    this->hidden->event = CreateEventW(NULL, 0, 0, NULL);
    1.59 +    if (this->hidden->event == NULL) {
    1.60 +        return WIN_SetError("WASAPI can't create an event handle");
    1.61 +    }
    1.62 +
    1.63      ret = IAudioClient_GetMixFormat(client, &waveformat);
    1.64      if (FAILED(ret)) {
    1.65          return WIN_SetErrorFromHRESULT("WASAPI can't determine mix format", ret);
    1.66 @@ -565,11 +583,16 @@
    1.67          return WIN_SetErrorFromHRESULT("WASAPI can't determine minimum device period", ret);
    1.68      }
    1.69  
    1.70 -    ret = IAudioClient_Initialize(client, sharemode, 0, duration, sharemode == AUDCLNT_SHAREMODE_SHARED ? 0 : duration, waveformat, NULL);
    1.71 +    ret = IAudioClient_Initialize(client, sharemode, AUDCLNT_STREAMFLAGS_EVENTCALLBACK, duration, sharemode == AUDCLNT_SHAREMODE_SHARED ? 0 : duration, waveformat, NULL);
    1.72      if (FAILED(ret)) {
    1.73          return WIN_SetErrorFromHRESULT("WASAPI can't initialize audio client", ret);
    1.74      }
    1.75  
    1.76 +    ret = IAudioClient_SetEventHandle(client, this->hidden->event);
    1.77 +    if (FAILED(ret)) {
    1.78 +        return WIN_SetErrorFromHRESULT("WASAPI can't set event handle", ret);
    1.79 +    }
    1.80 +
    1.81      ret = IAudioClient_GetBufferSize(client, &bufsize);
    1.82      if (FAILED(ret)) {
    1.83          return WIN_SetErrorFromHRESULT("WASAPI can't determine buffer size", ret);
     2.1 --- a/src/audio/wasapi/SDL_wasapi.h	Tue Dec 12 22:25:39 2017 -0500
     2.2 +++ b/src/audio/wasapi/SDL_wasapi.h	Wed Dec 13 14:35:55 2017 -0500
     2.3 @@ -45,6 +45,7 @@
     2.4      IAudioRenderClient *render;
     2.5      IAudioCaptureClient *capture;
     2.6      SDL_AudioStream *capturestream;
     2.7 +    HANDLE event;
     2.8      HANDLE task;
     2.9      SDL_bool coinitialized;
    2.10      int framesize;