mirror of
https://github.com/Ryujinx/libsoundio.git
synced 2024-12-22 22:45:28 +00:00
WASAPI: get the list of supported formats from devices
This commit is contained in:
parent
f4ad630769
commit
75185d17d7
|
@ -251,10 +251,9 @@ view `coverage/index.html` in a browser.
|
|||
|
||||
0. implement WASAPI (Windows) backend, get examples working
|
||||
- list devices
|
||||
- formats
|
||||
- channel layout
|
||||
- buffer duration
|
||||
- raw mode
|
||||
- channel layout
|
||||
- watching
|
||||
- sine wave
|
||||
- microphone
|
||||
|
|
|
@ -304,7 +304,9 @@ struct SoundIoDevice {
|
|||
// If the same physical device supports both input and output, that makes
|
||||
// one SoundIoDevice for the input and one SoundIoDevice for the output.
|
||||
// In this case, the `id` of each SoundIoDevice will be the same, and the
|
||||
// `aim` field will be different.
|
||||
// `aim` field will be different. Additionally, if the device supports raw
|
||||
// mode, there may be up to four devices with the same id: one for each
|
||||
// value of `is_raw` and one for each value of `aim`.
|
||||
char *id;
|
||||
char *name;
|
||||
|
||||
|
|
|
@ -584,10 +584,8 @@ static int refresh_devices(struct SoundIoPrivate *si) {
|
|||
rd.device->name = soundio_str_dupe(rd.device_name, rd.device_name_len);
|
||||
rd.device->layout_count = 1;
|
||||
rd.device->layouts = allocate<SoundIoChannelLayout>(1);
|
||||
rd.device->format_count = 1;
|
||||
rd.device->formats = allocate<SoundIoFormat>(1);
|
||||
|
||||
if (!rd.device->id || !rd.device->name || !rd.device->layouts || !rd.device->formats) {
|
||||
if (!rd.device->id || !rd.device->name || !rd.device->layouts) {
|
||||
deinit_refresh_devices(&rd);
|
||||
return SoundIoErrorNoMem;
|
||||
}
|
||||
|
@ -622,6 +620,8 @@ static int refresh_devices(struct SoundIoPrivate *si) {
|
|||
|
||||
rd.device->layouts[0] = rd.device->current_layout;
|
||||
// in CoreAudio, format is always 32-bit native endian float
|
||||
rd.device->format_count = 1;
|
||||
rd.device->formats = &dev->prealloc_format;
|
||||
rd.device->formats[0] = SoundIoFormatFloat32NE;
|
||||
|
||||
prop_address.mSelector = kAudioDevicePropertyNominalSampleRate;
|
||||
|
|
|
@ -189,8 +189,6 @@ static int refresh_devices_bare(SoundIoPrivate *si) {
|
|||
device->name = allocate<char>(description_len);
|
||||
device->layout_count = 1;
|
||||
device->layouts = allocate<SoundIoChannelLayout>(1);
|
||||
device->format_count = 1;
|
||||
device->formats = allocate<SoundIoFormat>(1);
|
||||
device->current_format = SoundIoFormatFloat32NE;
|
||||
device->sample_rate_count = 1;
|
||||
device->sample_rates = &dev->prealloc_sample_rate_range;
|
||||
|
@ -206,7 +204,7 @@ static int refresh_devices_bare(SoundIoPrivate *si) {
|
|||
dj->port_count = client->port_count;
|
||||
dj->ports = allocate<SoundIoDeviceJackPort>(dj->port_count);
|
||||
|
||||
if (!device->id || !device->name || !device->layouts || !device->formats || !dj->ports) {
|
||||
if (!device->id || !device->name || !device->layouts || !dj->ports) {
|
||||
jack_free(port_names);
|
||||
soundio_device_unref(device);
|
||||
soundio_destroy_devices_info(devices_info);
|
||||
|
@ -257,6 +255,8 @@ static int refresh_devices_bare(SoundIoPrivate *si) {
|
|||
}
|
||||
|
||||
device->layouts[0] = device->current_layout;
|
||||
device->format_count = 1;
|
||||
device->formats = &dev->prealloc_format;
|
||||
device->formats[0] = device->current_format;
|
||||
|
||||
SoundIoList<SoundIoDevice *> *device_list;
|
||||
|
|
|
@ -374,12 +374,14 @@ void soundio_device_unref(struct SoundIoDevice *device) {
|
|||
|
||||
free(device->id);
|
||||
free(device->name);
|
||||
free(device->formats);
|
||||
free(device->layouts);
|
||||
|
||||
if (device->sample_rates != &dev->prealloc_sample_rate_range)
|
||||
free(device->sample_rates);
|
||||
|
||||
if (device->formats != &dev->prealloc_format)
|
||||
free(device->formats);
|
||||
|
||||
free(dev);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -164,6 +164,7 @@ struct SoundIoDevicePrivate {
|
|||
SoundIoDeviceBackendData backend_data;
|
||||
void (*destruct)(SoundIoDevicePrivate *);
|
||||
SoundIoSampleRateRange prealloc_sample_rate_range;
|
||||
SoundIoFormat prealloc_format;
|
||||
};
|
||||
|
||||
void soundio_destroy_devices_info(struct SoundIoDevicesInfo *devices_info);
|
||||
|
|
|
@ -47,6 +47,36 @@ static int from_lpwstr(LPWSTR lpwstr, char **out_str, int *out_str_len) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static SoundIoFormat from_wave_format(WAVEFORMATEXTENSIBLE *wave_format) {
|
||||
assert(wave_format->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE);
|
||||
bool is_pcm = IsEqualGUID(wave_format->SubFormat, SOUNDIO_KSDATAFORMAT_SUBTYPE_PCM);
|
||||
bool is_float = IsEqualGUID(wave_format->SubFormat, SOUNDIO_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT);
|
||||
|
||||
if (wave_format->Samples.wValidBitsPerSample == wave_format->Format.wBitsPerSample) {
|
||||
if (wave_format->Format.wBitsPerSample == 8) {
|
||||
if (is_pcm)
|
||||
return SoundIoFormatU8;
|
||||
} else if (wave_format->Format.wBitsPerSample == 16) {
|
||||
if (is_pcm)
|
||||
return SoundIoFormatS16LE;
|
||||
} else if (wave_format->Format.wBitsPerSample == 32) {
|
||||
if (is_pcm)
|
||||
return SoundIoFormatS32LE;
|
||||
else if (is_float)
|
||||
return SoundIoFormatFloat32LE;
|
||||
} else if (wave_format->Format.wBitsPerSample == 64) {
|
||||
if (is_float)
|
||||
return SoundIoFormatFloat64LE;
|
||||
}
|
||||
} else if (wave_format->Format.wBitsPerSample == 32 &&
|
||||
wave_format->Samples.wValidBitsPerSample == 24)
|
||||
{
|
||||
return SoundIoFormatS24LE;
|
||||
}
|
||||
|
||||
return SoundIoFormatInvalid;
|
||||
}
|
||||
|
||||
static SoundIoDeviceAim data_flow_to_aim(EDataFlow data_flow) {
|
||||
return (data_flow == eRender) ? SoundIoDeviceAimOutput : SoundIoDeviceAimInput;
|
||||
}
|
||||
|
@ -65,6 +95,7 @@ struct RefreshDevices {
|
|||
IPropertyStore *prop_store;
|
||||
LPWSTR lpwstr;
|
||||
PROPVARIANT prop_variant_value;
|
||||
WAVEFORMATEXTENSIBLE *wave_format;
|
||||
bool prop_variant_value_inited;
|
||||
SoundIoDevicesInfo *devices_info;
|
||||
SoundIoDevice *device;
|
||||
|
@ -93,6 +124,8 @@ static void deinit_refresh_devices(RefreshDevices *rd) {
|
|||
IPropertyStore_Release(rd->prop_store);
|
||||
if (rd->prop_variant_value_inited)
|
||||
PropVariantClear(&rd->prop_variant_value);
|
||||
if (rd->wave_format)
|
||||
CoTaskMemFree(rd->wave_format);
|
||||
}
|
||||
|
||||
static void destruct_device(SoundIoDevicePrivate *dev) {
|
||||
|
@ -265,39 +298,29 @@ static int refresh_devices(SoundIoPrivate *si) {
|
|||
return SoundIoErrorOpeningDevice;
|
||||
}
|
||||
|
||||
if (rd.prop_variant_value_inited)
|
||||
PropVariantClear(&rd.prop_variant_value);
|
||||
PropVariantInit(&rd.prop_variant_value);
|
||||
rd.prop_variant_value_inited = true;
|
||||
if ((FAILED(hr = IPropertyStore_GetValue(rd.prop_store,
|
||||
PKEY_AudioEngine_DeviceFormat, &rd.prop_variant_value))))
|
||||
{
|
||||
if (rd.wave_format)
|
||||
CoTaskMemFree(rd.wave_format);
|
||||
if (FAILED(hr = IAudioClient_GetMixFormat(dw->audio_client, (WAVEFORMATEX**)&rd.wave_format))) {
|
||||
deinit_refresh_devices(&rd);
|
||||
return SoundIoErrorOpeningDevice;
|
||||
}
|
||||
|
||||
WAVEFORMATEXTENSIBLE *wave_format = (WAVEFORMATEXTENSIBLE *)rd.prop_variant_value.blob.pBlobData;
|
||||
if (wave_format->Format.wFormatTag != WAVE_FORMAT_EXTENSIBLE) {
|
||||
if (rd.wave_format->Format.wFormatTag != WAVE_FORMAT_EXTENSIBLE) {
|
||||
deinit_refresh_devices(&rd);
|
||||
return SoundIoErrorOpeningDevice;
|
||||
}
|
||||
|
||||
/*
|
||||
if (IsEqualGUID(wave_format->SubFormat, SOUNDIO_KSDATAFORMAT_SUBTYPE_PCM)) {
|
||||
} else if (IsEqualGUID(wave_format->SubFormat, SOUNDIO_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)) {
|
||||
} else {
|
||||
deinit_refresh_devices(&rd);
|
||||
return SoundIoErrorOpeningDevice;
|
||||
}
|
||||
*/
|
||||
|
||||
rd.device->sample_rate_count = 1;
|
||||
rd.device->sample_rates = &dev->prealloc_sample_rate_range;
|
||||
rd.device->sample_rate_current = wave_format->Format.nSamplesPerSec;
|
||||
rd.device->sample_rate_current = rd.wave_format->Format.nSamplesPerSec;
|
||||
rd.device->sample_rates[0].min = rd.device->sample_rate_current;
|
||||
rd.device->sample_rates[0].max = rd.device->sample_rate_current;
|
||||
|
||||
fprintf(stderr, "bits per sample: %d\n", (int)wave_format->Format.wBitsPerSample);
|
||||
rd.device->current_format = from_wave_format(rd.wave_format);
|
||||
rd.device->format_count = 1;
|
||||
rd.device->formats = &dev->prealloc_format;
|
||||
rd.device->formats[0] = rd.device->current_format;
|
||||
|
||||
|
||||
|
||||
|
||||
SoundIoList<SoundIoDevice *> *device_list;
|
||||
if (rd.device->aim == SoundIoDeviceAimOutput) {
|
||||
|
|
Loading…
Reference in a new issue