WASAPI: get the period duration of devices

This commit is contained in:
Andrew Kelley 2015-08-12 15:32:44 -07:00
parent 20b0515582
commit f4ad630769
3 changed files with 37 additions and 4 deletions

View file

@ -251,11 +251,10 @@ view `coverage/index.html` in a browser.
0. implement WASAPI (Windows) backend, get examples working 0. implement WASAPI (Windows) backend, get examples working
- list devices - list devices
- period duration - formats
- buffer duration - buffer duration
- raw mode - raw mode
- channel layout - channel layout
- formats
- watching - watching
- sine wave - sine wave
- microphone - microphone

View file

@ -11,6 +11,7 @@
#include <mmdeviceapi.h> #include <mmdeviceapi.h>
#include <functiondiscoverykeys_devpkey.h> #include <functiondiscoverykeys_devpkey.h>
#include <mmreg.h> #include <mmreg.h>
#include <audioclient.h>
// Attempting to use the Windows-supplied versions of these constants resulted // Attempting to use the Windows-supplied versions of these constants resulted
// in `undefined reference` linker errors. // in `undefined reference` linker errors.
@ -50,6 +51,11 @@ static SoundIoDeviceAim data_flow_to_aim(EDataFlow data_flow) {
return (data_flow == eRender) ? SoundIoDeviceAimOutput : SoundIoDeviceAimInput; return (data_flow == eRender) ? SoundIoDeviceAimOutput : SoundIoDeviceAimInput;
} }
static double from_reference_time(REFERENCE_TIME rt) {
return ((double)rt) / 10000000.0;
}
struct RefreshDevices { struct RefreshDevices {
IMMDeviceCollection *collection; IMMDeviceCollection *collection;
IMMDevice *mm_device; IMMDevice *mm_device;
@ -89,6 +95,12 @@ static void deinit_refresh_devices(RefreshDevices *rd) {
PropVariantClear(&rd->prop_variant_value); 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) { static int refresh_devices(SoundIoPrivate *si) {
SoundIo *soundio = &si->pub; SoundIo *soundio = &si->pub;
SoundIoWasapi *siw = &si->backend_data.wasapi; SoundIoWasapi *siw = &si->backend_data.wasapi;
@ -172,24 +184,45 @@ static int refresh_devices(SoundIoPrivate *si) {
} }
SoundIoDevicePrivate *dev = allocate<SoundIoDevicePrivate>(1); SoundIoDevicePrivate *dev = allocate<SoundIoDevicePrivate>(1);
if (!dev) { if (!dev) {
deinit_refresh_devices(&rd); deinit_refresh_devices(&rd);
return SoundIoErrorNoMem; return SoundIoErrorNoMem;
} }
SoundIoDeviceWasapi *dw = &dev->backend_data.wasapi;
dev->destruct = destruct_device;
assert(!rd.device); assert(!rd.device);
rd.device = &dev->pub; rd.device = &dev->pub;
rd.device->ref_count = 1; rd.device->ref_count = 1;
rd.device->soundio = soundio; rd.device->soundio = soundio;
rd.device->is_raw = false; // TODO rd.device->is_raw = false; // TODO
int device_id_len; int device_id_len;
if ((err = from_lpwstr(rd.lpwstr, &rd.device->id, &device_id_len))) { if ((err = from_lpwstr(rd.lpwstr, &rd.device->id, &device_id_len))) {
deinit_refresh_devices(&rd); deinit_refresh_devices(&rd);
return err; 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) if (rd.endpoint)
IMMEndpoint_Release(rd.endpoint); IMMEndpoint_Release(rd.endpoint);
if (FAILED(hr = IMMDevice_QueryInterface(rd.mm_device, IID_IMMEndpoint, (void**)&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); fprintf(stderr, "bits per sample: %d\n", (int)wave_format->Format.wBitsPerSample);
SoundIoList<SoundIoDevice *> *device_list; SoundIoList<SoundIoDevice *> *device_list;
if (rd.device->aim == SoundIoDeviceAimOutput) { if (rd.device->aim == SoundIoDeviceAimOutput) {
device_list = &rd.devices_info->output_devices; device_list = &rd.devices_info->output_devices;

View file

@ -12,10 +12,12 @@
#include "soundio/os.h" #include "soundio/os.h"
#include "atomics.hpp" #include "atomics.hpp"
struct IMMDeviceEnumerator; struct IMMDeviceEnumerator;
struct IAudioClient;
int soundio_wasapi_init(struct SoundIoPrivate *si); int soundio_wasapi_init(struct SoundIoPrivate *si);
struct SoundIoDeviceWasapi { struct SoundIoDeviceWasapi {
IAudioClient *audio_client;
}; };
struct SoundIoWasapi { struct SoundIoWasapi {