From 8fbabc4dfc23d593c964b257782ec62a1e0ca4a6 Mon Sep 17 00:00:00 2001 From: Ruurd Adema Date: Fri, 19 Aug 2016 21:18:06 +0200 Subject: [PATCH 1/8] Fixed issue with CoreAudio stereo stream being mono --- src/coreaudio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreaudio.c b/src/coreaudio.c index a483b53..39f16a7 100644 --- a/src/coreaudio.c +++ b/src/coreaudio.c @@ -1169,7 +1169,7 @@ static OSStatus read_callback_ca(void *userdata, AudioUnitRenderActionFlags *io_ assert(audio_buffer->mNumberChannels == instream->layout.channel_count); assert(audio_buffer->mDataByteSize == in_number_frames * instream->bytes_per_frame); for (int ch = 0; ch < instream->layout.channel_count; ch += 1) { - isca->areas[ch].ptr = ((char*)audio_buffer->mData) + instream->bytes_per_sample; + isca->areas[ch].ptr = ((char*)audio_buffer->mData) + (instream->bytes_per_sample * ch); isca->areas[ch].step = instream->bytes_per_frame; } } else { From a8201986a0846808be0d5d1fdb8161168f0b0df3 Mon Sep 17 00:00:00 2001 From: Jacques Heunis Date: Fri, 16 Sep 2016 10:12:35 +0200 Subject: [PATCH 2/8] Return slightly more descriptive soundio errors when RefreshDevices fails for WASAPI. --- src/wasapi.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/wasapi.c b/src/wasapi.c index 84bc695..49709d9 100644 --- a/src/wasapi.c +++ b/src/wasapi.c @@ -671,6 +671,9 @@ static int refresh_devices(struct SoundIoPrivate *si) { { if(hr != E_NOTFOUND) { deinit_refresh_devices(&rd); + if(hr == E_OUTOFMEMORY) { + return SoundIoErrorNoMem; + } return SoundIoErrorOpeningDevice; } } @@ -681,7 +684,9 @@ static int refresh_devices(struct SoundIoPrivate *si) { } if (FAILED(hr = IMMDevice_GetId(rd.default_render_device, &rd.lpwstr))) { deinit_refresh_devices(&rd); - return SoundIoErrorOpeningDevice; + // MSDN states the IMMDevice_GetId can fail if the device is NULL, or if we're out of memory + // We know the device point isn't NULL so we're necessarily out of memory + return SoundIoErrorNoMem; } if ((err = from_lpwstr(rd.lpwstr, &rd.default_render_id, &rd.default_render_id_len))) { deinit_refresh_devices(&rd); @@ -695,6 +700,9 @@ static int refresh_devices(struct SoundIoPrivate *si) { { if(hr != E_NOTFOUND) { deinit_refresh_devices(&rd); + if(hr == E_OUTOFMEMORY) { + return SoundIoErrorNoMem; + } return SoundIoErrorOpeningDevice; } } @@ -705,7 +713,9 @@ static int refresh_devices(struct SoundIoPrivate *si) { } if (FAILED(hr = IMMDevice_GetId(rd.default_capture_device, &rd.lpwstr))) { deinit_refresh_devices(&rd); - return SoundIoErrorOpeningDevice; + // MSDN states the IMMDevice_GetId can fail if the device is NULL, or if we're out of memory + // We know the device point isn't NULL so we're necessarily out of memory. + return SoundIoErrorNoMem; } if ((err = from_lpwstr(rd.lpwstr, &rd.default_capture_id, &rd.default_capture_id_len))) { deinit_refresh_devices(&rd); @@ -718,11 +728,16 @@ static int refresh_devices(struct SoundIoPrivate *si) { eAll, DEVICE_STATE_ACTIVE, &rd.collection))) { deinit_refresh_devices(&rd); + if(hr == E_OUTOFMEMORY) { + return SoundIoErrorNoMem; + } return SoundIoErrorOpeningDevice; } UINT unsigned_count; if (FAILED(hr = IMMDeviceCollection_GetCount(rd.collection, &unsigned_count))) { + // In theory this shouldn't happen since the only documented failure case is that + // rd.collection is NULL, but then EnumAudioEndpoints should have failed. deinit_refresh_devices(&rd); return SoundIoErrorOpeningDevice; } From 61c04c373082ef1e74d95f4181479e9097705c5f Mon Sep 17 00:00:00 2001 From: Jacques Heunis Date: Fri, 16 Sep 2016 10:22:54 +0200 Subject: [PATCH 3/8] Fix WASAPI disconnecting if just one device cannot be opened. --- src/wasapi.c | 357 ++++++++++++++++++++++++++++----------------------- 1 file changed, 194 insertions(+), 163 deletions(-) diff --git a/src/wasapi.c b/src/wasapi.c index 49709d9..ab478c8 100644 --- a/src/wasapi.c +++ b/src/wasapi.c @@ -762,16 +762,14 @@ static int refresh_devices(struct SoundIoPrivate *si) { rd.mm_device = NULL; } if (FAILED(hr = IMMDeviceCollection_Item(rd.collection, device_i, &rd.mm_device))) { - deinit_refresh_devices(&rd); - return SoundIoErrorOpeningDevice; + continue; } if (rd.lpwstr) { CoTaskMemFree(rd.lpwstr); rd.lpwstr = NULL; } if (FAILED(hr = IMMDevice_GetId(rd.mm_device, &rd.lpwstr))) { - deinit_refresh_devices(&rd); - return SoundIoErrorOpeningDevice; + continue; } @@ -816,177 +814,30 @@ static int refresh_devices(struct SoundIoPrivate *si) { return SoundIoErrorNoMem; } - if (rd.audio_client) { - IUnknown_Release(rd.audio_client); - rd.audio_client = NULL; - } - if (FAILED(hr = IMMDevice_Activate(rd.mm_device, IID_IAUDIOCLIENT, - CLSCTX_ALL, NULL, (void**)&rd.audio_client))) - { - deinit_refresh_devices(&rd); - return SoundIoErrorOpeningDevice; - } - - REFERENCE_TIME default_device_period; - REFERENCE_TIME min_device_period; - if (FAILED(hr = IAudioClient_GetDevicePeriod(rd.audio_client, - &default_device_period, &min_device_period))) - { - deinit_refresh_devices(&rd); - return SoundIoErrorOpeningDevice; - } - dev_w_shared->period_duration = from_reference_time(default_device_period); - rd.device_shared->software_latency_current = dev_w_shared->period_duration; - - dev_w_raw->period_duration = from_reference_time(min_device_period); - rd.device_raw->software_latency_min = dev_w_raw->period_duration * 2; - - if (rd.endpoint) { IMMEndpoint_Release(rd.endpoint); rd.endpoint = NULL; } if (FAILED(hr = IMMDevice_QueryInterface(rd.mm_device, IID_IMMENDPOINT, (void**)&rd.endpoint))) { - deinit_refresh_devices(&rd); - return SoundIoErrorOpeningDevice; + rd.device_shared->probe_error = SoundIoErrorOpeningDevice; + rd.device_raw->probe_error = SoundIoErrorOpeningDevice; + rd.device_shared = NULL; + rd.device_raw = NULL; + continue; } EDataFlow data_flow; if (FAILED(hr = IMMEndpoint_GetDataFlow(rd.endpoint, &data_flow))) { - deinit_refresh_devices(&rd); - return SoundIoErrorOpeningDevice; + rd.device_shared->probe_error = SoundIoErrorOpeningDevice; + rd.device_raw->probe_error = SoundIoErrorOpeningDevice; + rd.device_shared = NULL; + rd.device_raw = NULL; + continue; } rd.device_shared->aim = data_flow_to_aim(data_flow); rd.device_raw->aim = rd.device_shared->aim; - if (rd.prop_store) { - IPropertyStore_Release(rd.prop_store); - rd.prop_store = NULL; - } - if (FAILED(hr = IMMDevice_OpenPropertyStore(rd.mm_device, STGM_READ, &rd.prop_store))) { - deinit_refresh_devices(&rd); - return SoundIoErrorOpeningDevice; - } - - if (rd.prop_variant_value_inited) { - PropVariantClear(&rd.prop_variant_value); - rd.prop_variant_value_inited = false; - } - PropVariantInit(&rd.prop_variant_value); - rd.prop_variant_value_inited = true; - if (FAILED(hr = IPropertyStore_GetValue(rd.prop_store, - PKEY_DEVICE_FRIENDLYNAME, &rd.prop_variant_value))) - { - deinit_refresh_devices(&rd); - return SoundIoErrorOpeningDevice; - } - if (!rd.prop_variant_value.pwszVal) { - deinit_refresh_devices(&rd); - return SoundIoErrorOpeningDevice; - } - int device_name_len; - if ((err = from_lpwstr(rd.prop_variant_value.pwszVal, &rd.device_shared->name, &device_name_len))) { - deinit_refresh_devices(&rd); - return SoundIoErrorOpeningDevice; - } - - rd.device_raw->name = soundio_str_dupe(rd.device_shared->name, device_name_len); - if (!rd.device_raw->name) { - deinit_refresh_devices(&rd); - return SoundIoErrorNoMem; - } - - // Get the format that WASAPI opens the device with for shared streams. - // This is guaranteed to work, so we use this to modulate the sample - // rate while holding the format constant and vice versa. - if (rd.prop_variant_value_inited) { - PropVariantClear(&rd.prop_variant_value); - rd.prop_variant_value_inited = false; - } - 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))) - { - deinit_refresh_devices(&rd); - return SoundIoErrorOpeningDevice; - } - WAVEFORMATEXTENSIBLE *valid_wave_format = (WAVEFORMATEXTENSIBLE *)rd.prop_variant_value.blob.pBlobData; - if (valid_wave_format->Format.wFormatTag != WAVE_FORMAT_EXTENSIBLE) { - deinit_refresh_devices(&rd); - return SoundIoErrorOpeningDevice; - } - if ((err = detect_valid_sample_rates(&rd, valid_wave_format, dev_raw, - AUDCLNT_SHAREMODE_EXCLUSIVE))) - { - deinit_refresh_devices(&rd); - return err; - } - if ((err = detect_valid_formats(&rd, valid_wave_format, dev_raw, - AUDCLNT_SHAREMODE_EXCLUSIVE))) - { - deinit_refresh_devices(&rd); - return err; - } - - if (rd.wave_format) { - CoTaskMemFree(rd.wave_format); - rd.wave_format = NULL; - } - if (FAILED(hr = IAudioClient_GetMixFormat(rd.audio_client, (WAVEFORMATEX**)&rd.wave_format))) { - deinit_refresh_devices(&rd); - return SoundIoErrorOpeningDevice; - } - if (rd.wave_format->Format.wFormatTag != WAVE_FORMAT_EXTENSIBLE) { - deinit_refresh_devices(&rd); - return SoundIoErrorOpeningDevice; - } - rd.device_shared->sample_rate_current = rd.wave_format->Format.nSamplesPerSec; - rd.device_shared->current_format = from_wave_format_format(rd.wave_format); - - - if (rd.device_shared->aim == SoundIoDeviceAimOutput) { - // For output streams in shared mode, - // WASAPI performs resampling, so any value is valid. - // Let's pick some reasonable min and max values. - rd.device_shared->sample_rate_count = 1; - rd.device_shared->sample_rates = &dev_shared->prealloc_sample_rate_range; - rd.device_shared->sample_rates[0].min = soundio_int_min(SOUNDIO_MIN_SAMPLE_RATE, - rd.device_shared->sample_rate_current); - rd.device_shared->sample_rates[0].max = soundio_int_max(SOUNDIO_MAX_SAMPLE_RATE, - rd.device_shared->sample_rate_current); - } else { - // Shared mode input stream: mix format is all we can do. - rd.device_shared->sample_rate_count = 1; - rd.device_shared->sample_rates = &dev_shared->prealloc_sample_rate_range; - rd.device_shared->sample_rates[0].min = rd.device_shared->sample_rate_current; - rd.device_shared->sample_rates[0].max = rd.device_shared->sample_rate_current; - } - - if ((err = detect_valid_formats(&rd, rd.wave_format, dev_shared, - AUDCLNT_SHAREMODE_SHARED))) - { - deinit_refresh_devices(&rd); - return err; - } - - from_wave_format_layout(rd.wave_format, &rd.device_shared->current_layout); - rd.device_shared->layout_count = 1; - rd.device_shared->layouts = &rd.device_shared->current_layout; - - if ((err = detect_valid_layouts(&rd, valid_wave_format, dev_raw, - AUDCLNT_SHAREMODE_EXCLUSIVE))) - { - deinit_refresh_devices(&rd); - return err; - } - - IMMDevice_AddRef(rd.mm_device); - dev_w_shared->mm_device = rd.mm_device; - dev_w_raw->mm_device = rd.mm_device; - rd.mm_device = NULL; - struct SoundIoListDevicePtr *device_list; if (rd.device_shared->aim == SoundIoDeviceAimOutput) { device_list = &rd.devices_info->output_devices; @@ -1009,12 +860,192 @@ static int refresh_devices(struct SoundIoPrivate *si) { deinit_refresh_devices(&rd); return err; } - rd.device_shared = NULL; - if ((err = SoundIoListDevicePtr_append(device_list, rd.device_raw))) { deinit_refresh_devices(&rd); return err; } + + if (rd.audio_client) { + IUnknown_Release(rd.audio_client); + rd.audio_client = NULL; + } + if (FAILED(hr = IMMDevice_Activate(rd.mm_device, IID_IAUDIOCLIENT, + CLSCTX_ALL, NULL, (void**)&rd.audio_client))) + { + rd.device_shared->probe_error = SoundIoErrorOpeningDevice; + rd.device_raw->probe_error = SoundIoErrorOpeningDevice; + rd.device_shared = NULL; + rd.device_raw = NULL; + continue; + } + + REFERENCE_TIME default_device_period; + REFERENCE_TIME min_device_period; + if (FAILED(hr = IAudioClient_GetDevicePeriod(rd.audio_client, + &default_device_period, &min_device_period))) + { + rd.device_shared->probe_error = SoundIoErrorOpeningDevice; + rd.device_raw->probe_error = SoundIoErrorOpeningDevice; + rd.device_shared = NULL; + rd.device_raw = NULL; + continue; + } + dev_w_shared->period_duration = from_reference_time(default_device_period); + rd.device_shared->software_latency_current = dev_w_shared->period_duration; + + dev_w_raw->period_duration = from_reference_time(min_device_period); + rd.device_raw->software_latency_min = dev_w_raw->period_duration * 2; + + if (rd.prop_store) { + IPropertyStore_Release(rd.prop_store); + rd.prop_store = NULL; + } + if (FAILED(hr = IMMDevice_OpenPropertyStore(rd.mm_device, STGM_READ, &rd.prop_store))) { + rd.device_shared->probe_error = SoundIoErrorOpeningDevice; + rd.device_raw->probe_error = SoundIoErrorOpeningDevice; + rd.device_shared = NULL; + rd.device_raw = NULL; + continue; + } + + if (rd.prop_variant_value_inited) { + PropVariantClear(&rd.prop_variant_value); + rd.prop_variant_value_inited = false; + } + PropVariantInit(&rd.prop_variant_value); + rd.prop_variant_value_inited = true; + if (FAILED(hr = IPropertyStore_GetValue(rd.prop_store, + PKEY_DEVICE_FRIENDLYNAME, &rd.prop_variant_value))) + { + rd.device_shared->probe_error = SoundIoErrorOpeningDevice; + rd.device_raw->probe_error = SoundIoErrorOpeningDevice; + rd.device_shared = NULL; + rd.device_raw = NULL; + continue; + } + if (!rd.prop_variant_value.pwszVal) { + rd.device_shared->probe_error = SoundIoErrorOpeningDevice; + rd.device_raw->probe_error = SoundIoErrorOpeningDevice; + rd.device_shared = NULL; + rd.device_raw = NULL; + continue; + } + int device_name_len; + if ((err = from_lpwstr(rd.prop_variant_value.pwszVal, &rd.device_shared->name, &device_name_len))) { + rd.device_shared->probe_error = SoundIoErrorOpeningDevice; + rd.device_raw->probe_error = SoundIoErrorOpeningDevice; + rd.device_shared = NULL; + rd.device_raw = NULL; + continue; + } + + rd.device_raw->name = soundio_str_dupe(rd.device_shared->name, device_name_len); + if (!rd.device_raw->name) { + deinit_refresh_devices(&rd); + return SoundIoErrorNoMem; + } + + // Get the format that WASAPI opens the device with for shared streams. + // This is guaranteed to work, so we use this to modulate the sample + // rate while holding the format constant and vice versa. + if (rd.prop_variant_value_inited) { + PropVariantClear(&rd.prop_variant_value); + rd.prop_variant_value_inited = false; + } + 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))) + { + rd.device_shared->probe_error = SoundIoErrorOpeningDevice; + rd.device_raw->probe_error = SoundIoErrorOpeningDevice; + rd.device_shared = NULL; + rd.device_raw = NULL; + continue; + } + WAVEFORMATEXTENSIBLE *valid_wave_format = (WAVEFORMATEXTENSIBLE *)rd.prop_variant_value.blob.pBlobData; + if (valid_wave_format->Format.wFormatTag != WAVE_FORMAT_EXTENSIBLE) { + rd.device_shared->probe_error = SoundIoErrorOpeningDevice; + rd.device_raw->probe_error = SoundIoErrorOpeningDevice; + rd.device_shared = NULL; + rd.device_raw = NULL; + continue; + } + if ((err = detect_valid_sample_rates(&rd, valid_wave_format, dev_raw, + AUDCLNT_SHAREMODE_EXCLUSIVE))) + { + rd.device_raw->probe_error = SoundIoErrorOpeningDevice; + rd.device_raw = NULL; + } + if (rd.device_raw && (err = detect_valid_formats(&rd, valid_wave_format, dev_raw, + AUDCLNT_SHAREMODE_EXCLUSIVE))) + { + rd.device_raw->probe_error = SoundIoErrorOpeningDevice; + rd.device_raw = NULL; + } + if (rd.device_raw && (err = detect_valid_layouts(&rd, valid_wave_format, dev_raw, + AUDCLNT_SHAREMODE_EXCLUSIVE))) + { + rd.device_raw->probe_error = SoundIoErrorOpeningDevice; + rd.device_raw = NULL; + } + + if (rd.wave_format) { + CoTaskMemFree(rd.wave_format); + rd.wave_format = NULL; + } + if (FAILED(hr = IAudioClient_GetMixFormat(rd.audio_client, (WAVEFORMATEX**)&rd.wave_format))) { + // According to MSDN GetMixFormat only applies to shared-mode devices. + rd.device_shared->probe_error = SoundIoErrorOpeningDevice; + rd.device_shared = NULL; + } + else if(rd.wave_format && (rd.wave_format->Format.wFormatTag != WAVE_FORMAT_EXTENSIBLE)) { + rd.device_shared->probe_error = SoundIoErrorOpeningDevice; + rd.device_shared = NULL; + } + + if(rd.device_shared) { + rd.device_shared->sample_rate_current = rd.wave_format->Format.nSamplesPerSec; + rd.device_shared->current_format = from_wave_format_format(rd.wave_format); + + if (rd.device_shared->aim == SoundIoDeviceAimOutput) { + // For output streams in shared mode, + // WASAPI performs resampling, so any value is valid. + // Let's pick some reasonable min and max values. + rd.device_shared->sample_rate_count = 1; + rd.device_shared->sample_rates = &dev_shared->prealloc_sample_rate_range; + rd.device_shared->sample_rates[0].min = soundio_int_min(SOUNDIO_MIN_SAMPLE_RATE, + rd.device_shared->sample_rate_current); + rd.device_shared->sample_rates[0].max = soundio_int_max(SOUNDIO_MAX_SAMPLE_RATE, + rd.device_shared->sample_rate_current); + } + else { + // Shared mode input stream: mix format is all we can do. + rd.device_shared->sample_rate_count = 1; + rd.device_shared->sample_rates = &dev_shared->prealloc_sample_rate_range; + rd.device_shared->sample_rates[0].min = rd.device_shared->sample_rate_current; + rd.device_shared->sample_rates[0].max = rd.device_shared->sample_rate_current; + } + + if ((err = detect_valid_formats(&rd, rd.wave_format, dev_shared, + AUDCLNT_SHAREMODE_SHARED))) + { + rd.device_shared->probe_error = SoundIoErrorOpeningDevice; + rd.device_shared = NULL; + } + else { + from_wave_format_layout(rd.wave_format, &rd.device_shared->current_layout); + rd.device_shared->layout_count = 1; + rd.device_shared->layouts = &rd.device_shared->current_layout; + } + } + + IMMDevice_AddRef(rd.mm_device); + dev_w_shared->mm_device = rd.mm_device; + dev_w_raw->mm_device = rd.mm_device; + rd.mm_device = NULL; + + rd.device_shared = NULL; rd.device_raw = NULL; } From b88355eaaf2f891c47f81ce5b2a568f1715e497d Mon Sep 17 00:00:00 2001 From: Jacques Heunis Date: Fri, 16 Sep 2016 21:47:00 +0200 Subject: [PATCH 4/8] Return more descriptive/exact errors when available in WASAPI. --- src/wasapi.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/wasapi.c b/src/wasapi.c index ab478c8..1ea0761 100644 --- a/src/wasapi.c +++ b/src/wasapi.c @@ -713,8 +713,9 @@ static int refresh_devices(struct SoundIoPrivate *si) { } if (FAILED(hr = IMMDevice_GetId(rd.default_capture_device, &rd.lpwstr))) { deinit_refresh_devices(&rd); - // MSDN states the IMMDevice_GetId can fail if the device is NULL, or if we're out of memory - // We know the device point isn't NULL so we're necessarily out of memory. + if(hr == E_OUTOFMEMORY) { + return SoundIoErrorNoMem; + } return SoundIoErrorNoMem; } if ((err = from_lpwstr(rd.lpwstr, &rd.default_capture_id, &rd.default_capture_id_len))) { @@ -932,8 +933,8 @@ static int refresh_devices(struct SoundIoPrivate *si) { } int device_name_len; if ((err = from_lpwstr(rd.prop_variant_value.pwszVal, &rd.device_shared->name, &device_name_len))) { - rd.device_shared->probe_error = SoundIoErrorOpeningDevice; - rd.device_raw->probe_error = SoundIoErrorOpeningDevice; + rd.device_shared->probe_error = err; + rd.device_raw->probe_error = err; rd.device_shared = NULL; rd.device_raw = NULL; continue; @@ -974,19 +975,19 @@ static int refresh_devices(struct SoundIoPrivate *si) { if ((err = detect_valid_sample_rates(&rd, valid_wave_format, dev_raw, AUDCLNT_SHAREMODE_EXCLUSIVE))) { - rd.device_raw->probe_error = SoundIoErrorOpeningDevice; + rd.device_raw->probe_error = err; rd.device_raw = NULL; } if (rd.device_raw && (err = detect_valid_formats(&rd, valid_wave_format, dev_raw, AUDCLNT_SHAREMODE_EXCLUSIVE))) { - rd.device_raw->probe_error = SoundIoErrorOpeningDevice; + rd.device_raw->probe_error = err; rd.device_raw = NULL; } if (rd.device_raw && (err = detect_valid_layouts(&rd, valid_wave_format, dev_raw, AUDCLNT_SHAREMODE_EXCLUSIVE))) { - rd.device_raw->probe_error = SoundIoErrorOpeningDevice; + rd.device_raw->probe_error = err; rd.device_raw = NULL; } @@ -1030,7 +1031,7 @@ static int refresh_devices(struct SoundIoPrivate *si) { if ((err = detect_valid_formats(&rd, rd.wave_format, dev_shared, AUDCLNT_SHAREMODE_SHARED))) { - rd.device_shared->probe_error = SoundIoErrorOpeningDevice; + rd.device_shared->probe_error = err; rd.device_shared = NULL; } else { From f9444b089bf2bfa8cb6eee2b53c826534528d7c8 Mon Sep 17 00:00:00 2001 From: Jacques Heunis Date: Fri, 16 Sep 2016 22:46:14 +0200 Subject: [PATCH 5/8] Fix incorrectly returning the same error in multiple error cases --- src/wasapi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wasapi.c b/src/wasapi.c index 1ea0761..c2940a8 100644 --- a/src/wasapi.c +++ b/src/wasapi.c @@ -716,7 +716,7 @@ static int refresh_devices(struct SoundIoPrivate *si) { if(hr == E_OUTOFMEMORY) { return SoundIoErrorNoMem; } - return SoundIoErrorNoMem; + return SoundIoErrorOpeningDevice; } if ((err = from_lpwstr(rd.lpwstr, &rd.default_capture_id, &rd.default_capture_id_len))) { deinit_refresh_devices(&rd); From 6703021eba894a60695ac0dd76a0f2929a751484 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 23 Oct 2016 16:11:58 -0400 Subject: [PATCH 6/8] sio_sine: add phase wrap around closes #110 Thanks to @iskunk for the fix. --- README.md | 3 ++- example/sio_sine.c | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index e18bb4e..e08f3cc 100644 --- a/README.md +++ b/README.md @@ -95,7 +95,8 @@ static void write_callback(struct SoundIoOutStream *outstream, *ptr = sample; } } - seconds_offset += seconds_per_frame * frame_count; + seconds_offset = fmodf(seconds_offset + + seconds_per_frame * frame_count, 1.0f); if ((err = soundio_outstream_end_write(outstream))) { fprintf(stderr, "%s\n", soundio_strerror(err)); diff --git a/example/sio_sine.c b/example/sio_sine.c index 75fe613..cc70c67 100644 --- a/example/sio_sine.c +++ b/example/sio_sine.c @@ -77,13 +77,13 @@ static void write_callback(struct SoundIoOutStream *outstream, int frame_count_m double pitch = 440.0; double radians_per_second = pitch * 2.0 * PI; for (int frame = 0; frame < frame_count; frame += 1) { - double sample = sinf((seconds_offset + frame * seconds_per_frame) * radians_per_second); + double sample = sin((seconds_offset + frame * seconds_per_frame) * radians_per_second); for (int channel = 0; channel < layout->channel_count; channel += 1) { write_sample(areas[channel].ptr, sample); areas[channel].ptr += areas[channel].step; } } - seconds_offset += seconds_per_frame * frame_count; + seconds_offset = fmod(seconds_offset + seconds_per_frame * frame_count, 1.0); if ((err = soundio_outstream_end_write(outstream))) { if (err == SoundIoErrorUnderflow) From 9557eb7b60e16964ef3f48e4a77587030e901859 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 23 Oct 2016 16:38:21 -0400 Subject: [PATCH 7/8] docs: move ring buffer docs to work around doxygen limitation closes #113 --- soundio/soundio.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/soundio/soundio.h b/soundio/soundio.h index 6aa8359..e5b8c8d 100644 --- a/soundio/soundio.h +++ b/soundio/soundio.h @@ -1163,11 +1163,12 @@ SOUNDIO_EXPORT int soundio_instream_get_latency(struct SoundIoInStream *instream double *out_latency); +struct SoundIoRingBuffer; + /// A ring buffer is a single-reader single-writer lock-free fixed-size queue. /// libsoundio ring buffers use memory mapping techniques to enable a /// contiguous buffer when reading or writing across the boundary of the ring /// buffer's capacity. -struct SoundIoRingBuffer; /// `requested_capacity` in bytes. /// Returns `NULL` if and only if memory could not be allocated. /// Use ::soundio_ring_buffer_capacity to get the actual capacity, which might From 25a35c3dab3884bda597384b3db221ad7a5cbcc5 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 23 Oct 2016 16:48:52 -0400 Subject: [PATCH 8/8] build: examples and tests work when building statically closes #106 --- CMakeLists.txt | 42 +++++++++++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e47a46d..f70bbd7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -257,28 +257,44 @@ if(BUILD_EXAMPLE_PROGRAMS) set_target_properties(sio_sine PROPERTIES LINKER_LANGUAGE C COMPILE_FLAGS ${EXAMPLE_CFLAGS}) - target_link_libraries(sio_sine libsoundio_shared ${LIBM}) + if(BUILD_DYNAMIC_LIBS) + target_link_libraries(sio_sine libsoundio_shared ${LIBM}) + else() + target_link_libraries(sio_sine libsoundio_static ${LIBSOUNDIO_LIBS} ${LIBM}) + endif() install(TARGETS sio_sine DESTINATION ${CMAKE_INSTALL_BINDIR}) add_executable(sio_list_devices example/sio_list_devices.c) set_target_properties(sio_list_devices PROPERTIES LINKER_LANGUAGE C COMPILE_FLAGS ${EXAMPLE_CFLAGS}) - target_link_libraries(sio_list_devices libsoundio_shared) + if(BUILD_DYNAMIC_LIBS) + target_link_libraries(sio_list_devices libsoundio_shared) + else() + target_link_libraries(sio_list_devices libsoundio_static ${LIBSOUNDIO_LIBS}) + endif() install(TARGETS sio_list_devices DESTINATION ${CMAKE_INSTALL_BINDIR}) add_executable(sio_microphone example/sio_microphone.c) set_target_properties(sio_microphone PROPERTIES LINKER_LANGUAGE C COMPILE_FLAGS ${EXAMPLE_CFLAGS}) - target_link_libraries(sio_microphone libsoundio_shared) + if(BUILD_DYNAMIC_LIBS) + target_link_libraries(sio_microphone libsoundio_shared) + else() + target_link_libraries(sio_microphone libsoundio_static ${LIBSOUNDIO_LIBS}) + endif() install(TARGETS sio_microphone DESTINATION ${CMAKE_INSTALL_BINDIR}) add_executable(sio_record example/sio_record.c) set_target_properties(sio_record PROPERTIES LINKER_LANGUAGE C COMPILE_FLAGS ${EXAMPLE_CFLAGS}) - target_link_libraries(sio_record libsoundio_shared) + if(BUILD_DYNAMIC_LIBS) + target_link_libraries(sio_record libsoundio_shared) + else() + target_link_libraries(sio_record libsoundio_static ${LIBSOUNDIO_LIBS}) + endif() install(TARGETS sio_record DESTINATION ${CMAKE_INSTALL_BINDIR}) endif() @@ -302,19 +318,31 @@ if(BUILD_TESTS) set_target_properties(underflow PROPERTIES LINKER_LANGUAGE C COMPILE_FLAGS ${EXAMPLE_CFLAGS}) - target_link_libraries(underflow libsoundio_shared ${LIBM}) + if(BUILD_DYNAMIC_LIBS) + target_link_libraries(underflow libsoundio_shared ${LIBM}) + else() + target_link_libraries(underflow libsoundio_static ${LIBSOUNDIO_LIBS} ${LIBM}) + endif() add_executable(backend_disconnect_recover test/backend_disconnect_recover.c) set_target_properties(backend_disconnect_recover PROPERTIES LINKER_LANGUAGE C COMPILE_FLAGS ${EXAMPLE_CFLAGS}) - target_link_libraries(backend_disconnect_recover libsoundio_shared) + if(BUILD_DYNAMIC_LIBS) + target_link_libraries(backend_disconnect_recover libsoundio_shared) + else() + target_link_libraries(backend_disconnect_recover libsoundio_static ${LIBSOUNDIO_LIBS}) + endif() add_executable(overflow test/overflow.c) set_target_properties(overflow PROPERTIES LINKER_LANGUAGE C COMPILE_FLAGS ${EXAMPLE_CFLAGS}) - target_link_libraries(overflow libsoundio_shared) + if(BUILD_DYNAMIC_LIBS) + target_link_libraries(overflow libsoundio_shared) + else() + target_link_libraries(overflow libsoundio_static ${LIBSOUNDIO_LIBS}) + endif()