From f4ad63076983e6983e867149c0b23c7a8e3f4832 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 12 Aug 2015 15:32:44 -0700 Subject: [PATCH] WASAPI: get the period duration of devices --- README.md | 3 +-- src/wasapi.cpp | 36 ++++++++++++++++++++++++++++++++++-- src/wasapi.hpp | 2 ++ 3 files changed, 37 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index b38d4d4..a5e8520 100644 --- a/README.md +++ b/README.md @@ -251,11 +251,10 @@ view `coverage/index.html` in a browser. 0. implement WASAPI (Windows) backend, get examples working - list devices - - period duration + - formats - buffer duration - raw mode - channel layout - - formats - watching - sine wave - microphone diff --git a/src/wasapi.cpp b/src/wasapi.cpp index 72a7697..792dd97 100644 --- a/src/wasapi.cpp +++ b/src/wasapi.cpp @@ -11,6 +11,7 @@ #include #include #include +#include // Attempting to use the Windows-supplied versions of these constants resulted // in `undefined reference` linker errors. @@ -50,6 +51,11 @@ static SoundIoDeviceAim data_flow_to_aim(EDataFlow data_flow) { return (data_flow == eRender) ? SoundIoDeviceAimOutput : SoundIoDeviceAimInput; } + +static double from_reference_time(REFERENCE_TIME rt) { + return ((double)rt) / 10000000.0; +} + struct RefreshDevices { IMMDeviceCollection *collection; IMMDevice *mm_device; @@ -89,6 +95,12 @@ static void deinit_refresh_devices(RefreshDevices *rd) { PropVariantClear(&rd->prop_variant_value); } +static void destruct_device(SoundIoDevicePrivate *dev) { + SoundIoDeviceWasapi *dw = &dev->backend_data.wasapi; + if (dw->audio_client) + IUnknown_Release(dw->audio_client); +} + static int refresh_devices(SoundIoPrivate *si) { SoundIo *soundio = &si->pub; SoundIoWasapi *siw = &si->backend_data.wasapi; @@ -172,24 +184,45 @@ static int refresh_devices(SoundIoPrivate *si) { } + SoundIoDevicePrivate *dev = allocate(1); if (!dev) { deinit_refresh_devices(&rd); return SoundIoErrorNoMem; } + SoundIoDeviceWasapi *dw = &dev->backend_data.wasapi; + dev->destruct = destruct_device; assert(!rd.device); rd.device = &dev->pub; rd.device->ref_count = 1; rd.device->soundio = soundio; rd.device->is_raw = false; // TODO - int device_id_len; if ((err = from_lpwstr(rd.lpwstr, &rd.device->id, &device_id_len))) { deinit_refresh_devices(&rd); return err; } + if (FAILED(hr = IMMDevice_Activate(rd.mm_device, IID_IAudioClient, + CLSCTX_ALL, nullptr, (void**)&dw->audio_client))) + { + deinit_refresh_devices(&rd); + return SoundIoErrorOpeningDevice; + } + + REFERENCE_TIME default_device_period; + REFERENCE_TIME min_device_period; + if (FAILED(hr = IAudioClient_GetDevicePeriod(dw->audio_client, + &default_device_period, &min_device_period))) + { + deinit_refresh_devices(&rd); + return SoundIoErrorOpeningDevice; + } + rd.device->period_duration_current = from_reference_time(default_device_period); + rd.device->period_duration_min = from_reference_time(min_device_period); + + if (rd.endpoint) IMMEndpoint_Release(rd.endpoint); if (FAILED(hr = IMMDevice_QueryInterface(rd.mm_device, IID_IMMEndpoint, (void**)&rd.endpoint))) { @@ -266,7 +299,6 @@ static int refresh_devices(SoundIoPrivate *si) { fprintf(stderr, "bits per sample: %d\n", (int)wave_format->Format.wBitsPerSample); - SoundIoList *device_list; if (rd.device->aim == SoundIoDeviceAimOutput) { device_list = &rd.devices_info->output_devices; diff --git a/src/wasapi.hpp b/src/wasapi.hpp index 717036c..707db1b 100644 --- a/src/wasapi.hpp +++ b/src/wasapi.hpp @@ -12,10 +12,12 @@ #include "soundio/os.h" #include "atomics.hpp" struct IMMDeviceEnumerator; +struct IAudioClient; int soundio_wasapi_init(struct SoundIoPrivate *si); struct SoundIoDeviceWasapi { + IAudioClient *audio_client; }; struct SoundIoWasapi {