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
- list devices
- period duration
- formats
- buffer duration
- raw mode
- channel layout
- formats
- watching
- sine wave
- microphone

View file

@ -11,6 +11,7 @@
#include <mmdeviceapi.h>
#include <functiondiscoverykeys_devpkey.h>
#include <mmreg.h>
#include <audioclient.h>
// 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<SoundIoDevicePrivate>(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<SoundIoDevice *> *device_list;
if (rd.device->aim == SoundIoDeviceAimOutput) {
device_list = &rd.devices_info->output_devices;

View file

@ -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 {