mirror of
https://github.com/Ryujinx/libsoundio.git
synced 2024-12-23 08:45:37 +00:00
sample rate is exposed as a list of min/max pairs
This commit is contained in:
parent
eb7308d992
commit
7238d29666
10
README.md
10
README.md
|
@ -249,16 +249,10 @@ view `coverage/index.html` in a browser.
|
||||||
|
|
||||||
## Roadmap
|
## Roadmap
|
||||||
|
|
||||||
0. ALSA backend for microphone example is broken
|
|
||||||
0. Add some builtin channel layouts from
|
|
||||||
https://developer.apple.com/library/mac/documentation/MusicAudio/Reference/CoreAudioDataTypesRef/#//apple_ref/doc/constant_group/Audio_Channel_Layout_Tags
|
|
||||||
0. Make sure sending bogus device id results in "SoundIoErrorNoSuchDevice" on each backend
|
|
||||||
0. Make sure PulseAudio can handle refresh devices crashing before
|
|
||||||
block_until_have_devices
|
|
||||||
0. CoreAudio exposes a list of min/max pairs of supported sample rates. libsoundio
|
|
||||||
should do the same.
|
|
||||||
0. implement WASAPI (Windows) backend, get examples working
|
0. implement WASAPI (Windows) backend, get examples working
|
||||||
0. implement ASIO (Windows) backend, get examples working
|
0. implement ASIO (Windows) backend, get examples working
|
||||||
|
0. Make sure PulseAudio can handle refresh devices crashing before
|
||||||
|
block_until_have_devices
|
||||||
0. Do we really want `period_duration` in the API?
|
0. Do we really want `period_duration` in the API?
|
||||||
0. Integrate into libgroove and test with Groove Basin
|
0. Integrate into libgroove and test with Groove Basin
|
||||||
0. clear buffer maybe could take an argument to say how many frames to not clear
|
0. clear buffer maybe could take an argument to say how many frames to not clear
|
||||||
|
|
|
@ -50,8 +50,12 @@ static void print_device(struct SoundIoDevice *device, bool is_default) {
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stderr, " min sample rate: %d\n", device->sample_rate_min);
|
fprintf(stderr, " sample rates:\n");
|
||||||
fprintf(stderr, " max sample rate: %d\n", device->sample_rate_max);
|
for (int i = 0; i < device->sample_rate_count; i += 1) {
|
||||||
|
struct SoundIoSampleRateRange *range = &device->sample_rates[i];
|
||||||
|
fprintf(stderr, " %d - %d\n", range->min, range->max);
|
||||||
|
|
||||||
|
}
|
||||||
if (device->sample_rate_current)
|
if (device->sample_rate_current)
|
||||||
fprintf(stderr, " current sample rate: %d\n", device->sample_rate_current);
|
fprintf(stderr, " current sample rate: %d\n", device->sample_rate_current);
|
||||||
fprintf(stderr, " formats: ");
|
fprintf(stderr, " formats: ");
|
||||||
|
|
|
@ -39,6 +39,14 @@ static enum SoundIoFormat prioritized_formats[] = {
|
||||||
SoundIoFormatInvalid,
|
SoundIoFormatInvalid,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int prioritized_sample_rates[] = {
|
||||||
|
48000,
|
||||||
|
44100,
|
||||||
|
96000,
|
||||||
|
24000,
|
||||||
|
0,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
__attribute__ ((cold))
|
__attribute__ ((cold))
|
||||||
__attribute__ ((noreturn))
|
__attribute__ ((noreturn))
|
||||||
|
@ -274,11 +282,15 @@ int main(int argc, char **argv) {
|
||||||
if (!layout)
|
if (!layout)
|
||||||
panic("channel layouts not compatible");
|
panic("channel layouts not compatible");
|
||||||
|
|
||||||
|
int *sample_rate;
|
||||||
int sample_rate = 48000;
|
for (sample_rate = prioritized_sample_rates; *sample_rate; sample_rate += 1) {
|
||||||
if (in_device->sample_rate_max < sample_rate) sample_rate = in_device->sample_rate_max;
|
if (soundio_device_supports_sample_rate(in_device, *sample_rate) &&
|
||||||
if (out_device->sample_rate_max < sample_rate) sample_rate = out_device->sample_rate_max;
|
soundio_device_supports_sample_rate(out_device, *sample_rate))
|
||||||
if (in_device->sample_rate_min > sample_rate || out_device->sample_rate_min > sample_rate)
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!*sample_rate)
|
||||||
panic("incompatible sample rates");
|
panic("incompatible sample rates");
|
||||||
|
|
||||||
enum SoundIoFormat *fmt;
|
enum SoundIoFormat *fmt;
|
||||||
|
@ -296,7 +308,7 @@ int main(int argc, char **argv) {
|
||||||
if (!instream)
|
if (!instream)
|
||||||
panic("out of memory");
|
panic("out of memory");
|
||||||
instream->format = *fmt;
|
instream->format = *fmt;
|
||||||
instream->sample_rate = sample_rate;
|
instream->sample_rate = *sample_rate;
|
||||||
instream->layout = *layout;
|
instream->layout = *layout;
|
||||||
instream->period_duration = microphone_latency / 4.0;
|
instream->period_duration = microphone_latency / 4.0;
|
||||||
instream->read_callback = read_callback;
|
instream->read_callback = read_callback;
|
||||||
|
@ -308,7 +320,7 @@ int main(int argc, char **argv) {
|
||||||
if (!outstream)
|
if (!outstream)
|
||||||
panic("out of memory");
|
panic("out of memory");
|
||||||
outstream->format = *fmt;
|
outstream->format = *fmt;
|
||||||
outstream->sample_rate = sample_rate;
|
outstream->sample_rate = *sample_rate;
|
||||||
outstream->layout = *layout;
|
outstream->layout = *layout;
|
||||||
outstream->buffer_duration = microphone_latency;
|
outstream->buffer_duration = microphone_latency;
|
||||||
outstream->write_callback = write_callback;
|
outstream->write_callback = write_callback;
|
||||||
|
|
|
@ -238,7 +238,13 @@ struct SoundIoChannelLayout {
|
||||||
enum SoundIoChannelId channels[SOUNDIO_MAX_CHANNELS];
|
enum SoundIoChannelId channels[SOUNDIO_MAX_CHANNELS];
|
||||||
};
|
};
|
||||||
|
|
||||||
// The size of this struct is not part of the API or ABI.
|
// The size of this struct is OK to use.
|
||||||
|
struct SoundIoSampleRateRange {
|
||||||
|
int min;
|
||||||
|
int max;
|
||||||
|
};
|
||||||
|
|
||||||
|
// The size of this struct is OK to use.
|
||||||
struct SoundIoChannelArea {
|
struct SoundIoChannelArea {
|
||||||
// Base address of buffer.
|
// Base address of buffer.
|
||||||
char *ptr;
|
char *ptr;
|
||||||
|
@ -336,10 +342,11 @@ struct SoundIoDevice {
|
||||||
// Sample rate is the number of frames per second.
|
// Sample rate is the number of frames per second.
|
||||||
// Sample rate is handled very similar to sample format; see those docs.
|
// Sample rate is handled very similar to sample format; see those docs.
|
||||||
// If sample rate information is missing due to a probe error, the field
|
// If sample rate information is missing due to a probe error, the field
|
||||||
// will be set to zero.
|
// will be set to 0 or NULL.
|
||||||
// Devices are guaranteed to have at least 1 sample rate available.
|
// Devices which have `probe_error` set to `SoundIoErrorNone` are
|
||||||
int sample_rate_min;
|
// guaranteed to have at least 1 sample rate available.
|
||||||
int sample_rate_max;
|
struct SoundIoSampleRateRange *sample_rates;
|
||||||
|
int sample_rate_count;
|
||||||
int sample_rate_current;
|
int sample_rate_current;
|
||||||
|
|
||||||
// Buffer duration in seconds. If `buffer_duration_current` is unknown or
|
// Buffer duration in seconds. If `buffer_duration_current` is unknown or
|
||||||
|
@ -705,6 +712,16 @@ bool soundio_device_supports_format(struct SoundIoDevice *device,
|
||||||
bool soundio_device_supports_layout(struct SoundIoDevice *device,
|
bool soundio_device_supports_layout(struct SoundIoDevice *device,
|
||||||
const struct SoundIoChannelLayout *layout);
|
const struct SoundIoChannelLayout *layout);
|
||||||
|
|
||||||
|
// Convenience function. Returns whether `sample_rate` is included in the
|
||||||
|
// device's supported sample rates.
|
||||||
|
bool soundio_device_supports_sample_rate(struct SoundIoDevice *device,
|
||||||
|
int sample_rate);
|
||||||
|
|
||||||
|
// Convenience function. Returns the available sample rate nearest to
|
||||||
|
// `sample_rate`, rounding up.
|
||||||
|
int soundio_device_nearest_sample_rate(struct SoundIoDevice *device,
|
||||||
|
int sample_rate);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Output Streams
|
// Output Streams
|
||||||
|
|
11
src/alsa.cpp
11
src/alsa.cpp
|
@ -252,6 +252,7 @@ static int set_access(snd_pcm_t *handle, snd_pcm_hw_params_t *hwparams, snd_pcm_
|
||||||
static int probe_open_device(SoundIoDevice *device, snd_pcm_t *handle, int resample,
|
static int probe_open_device(SoundIoDevice *device, snd_pcm_t *handle, int resample,
|
||||||
int *out_channels_min, int *out_channels_max)
|
int *out_channels_min, int *out_channels_max)
|
||||||
{
|
{
|
||||||
|
SoundIoDevicePrivate *dev = (SoundIoDevicePrivate *)device;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
snd_pcm_hw_params_t *hwparams;
|
snd_pcm_hw_params_t *hwparams;
|
||||||
|
@ -286,8 +287,10 @@ static int probe_open_device(SoundIoDevice *device, snd_pcm_t *handle, int resam
|
||||||
if ((err = snd_pcm_hw_params_set_rate_last(handle, hwparams, &rate_max, nullptr)) < 0)
|
if ((err = snd_pcm_hw_params_set_rate_last(handle, hwparams, &rate_max, nullptr)) < 0)
|
||||||
return SoundIoErrorOpeningDevice;
|
return SoundIoErrorOpeningDevice;
|
||||||
|
|
||||||
device->sample_rate_min = rate_min;
|
device->sample_rate_count = 1;
|
||||||
device->sample_rate_max = rate_max;
|
device->sample_rates = &dev->prealloc_sample_rate_range;
|
||||||
|
device->sample_rates[0].min = rate_min;
|
||||||
|
device->sample_rates[0].max = rate_max;
|
||||||
|
|
||||||
double one_over_actual_rate = 1.0 / (double)rate_max;
|
double one_over_actual_rate = 1.0 / (double)rate_max;
|
||||||
|
|
||||||
|
@ -437,8 +440,8 @@ static int probe_device(SoundIoDevice *device, snd_pcm_chmap_query_t **maps) {
|
||||||
maps = nullptr;
|
maps = nullptr;
|
||||||
|
|
||||||
if (!device->is_raw) {
|
if (!device->is_raw) {
|
||||||
if (device->sample_rate_min == device->sample_rate_max)
|
if (device->sample_rates[0].min == device->sample_rates[0].max)
|
||||||
device->sample_rate_current = device->sample_rate_min;
|
device->sample_rate_current = device->sample_rates[0].min;
|
||||||
|
|
||||||
if (device->buffer_duration_min == device->buffer_duration_max)
|
if (device->buffer_duration_min == device->buffer_duration_max)
|
||||||
device->buffer_duration_current = device->buffer_duration_min;
|
device->buffer_duration_current = device->buffer_duration_min;
|
||||||
|
|
|
@ -642,6 +642,14 @@ static int refresh_devices(struct SoundIoPrivate *si) {
|
||||||
}
|
}
|
||||||
rd.device->sample_rate_current = (int)floored_value;
|
rd.device->sample_rate_current = (int)floored_value;
|
||||||
|
|
||||||
|
// If you try to open an input stream with anything but the current
|
||||||
|
// nominal sample rate, AudioUnitRender returns an error.
|
||||||
|
if (aim == SoundIoDeviceAimInput) {
|
||||||
|
device->sample_rate_count = 1;
|
||||||
|
device->sample_rates = &dev->prealloc_sample_rate_range;
|
||||||
|
device->sample_rates[0].min = rd.device->sample_rate_current;
|
||||||
|
device->sample_rates[0].max = rd.device->sample_rate_current;
|
||||||
|
} else {
|
||||||
prop_address.mSelector = kAudioDevicePropertyAvailableNominalSampleRates;
|
prop_address.mSelector = kAudioDevicePropertyAvailableNominalSampleRates;
|
||||||
prop_address.mScope = aim_to_scope(aim);
|
prop_address.mScope = aim_to_scope(aim);
|
||||||
prop_address.mElement = kAudioObjectPropertyElementMaster;
|
prop_address.mElement = kAudioObjectPropertyElementMaster;
|
||||||
|
@ -666,20 +674,26 @@ static int refresh_devices(struct SoundIoPrivate *si) {
|
||||||
return SoundIoErrorOpeningDevice;
|
return SoundIoErrorOpeningDevice;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (avr_array_len == 1) {
|
||||||
|
device->sample_rate_count = 1;
|
||||||
|
device->sample_rates = &dev->prealloc_sample_rate_range;
|
||||||
|
device->sample_rates[0].min = ceil(avr->mMinimum);
|
||||||
|
device->sample_rates[0].max = floor(avr->mMaximum);
|
||||||
|
} else {
|
||||||
|
device->sample_rate_count = avr_array_len;
|
||||||
|
device->sample_rates = allocate<SoundIoSampleRateRange>(avr_array_len);
|
||||||
|
if (!device->sample_rates) {
|
||||||
|
deinit_refresh_devices(&rd);
|
||||||
|
return SoundIoErrorNoMem;
|
||||||
|
}
|
||||||
for (int i = 0; i < avr_array_len; i += 1) {
|
for (int i = 0; i < avr_array_len; i += 1) {
|
||||||
AudioValueRange *avr = &rd.avr_array[i];
|
AudioValueRange *avr = &rd.avr_array[i];
|
||||||
int min_val = ceil(avr->mMinimum);
|
int min_val = ceil(avr->mMinimum);
|
||||||
int max_val = floor(avr->mMaximum);
|
int max_val = floor(avr->mMaximum);
|
||||||
if (rd.device->sample_rate_min == 0 || min_val < rd.device->sample_rate_min)
|
device->sample_rates[i].min = min_val;
|
||||||
rd.device->sample_rate_min = min_val;
|
device->sample_rates[i].max = max_val;
|
||||||
if (rd.device->sample_rate_max == 0 || max_val > rd.device->sample_rate_max)
|
}
|
||||||
rd.device->sample_rate_max = max_val;
|
|
||||||
}
|
}
|
||||||
// If you try to open an input stream with anything but the current
|
|
||||||
// nominal sample rate, AudioUnitRender returns an error.
|
|
||||||
if (aim == SoundIoDeviceAimInput) {
|
|
||||||
rd.device->sample_rate_min = rd.device->sample_rate_current;
|
|
||||||
rd.device->sample_rate_max = rd.device->sample_rate_current;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
prop_address.mSelector = kAudioDevicePropertyBufferFrameSize;
|
prop_address.mSelector = kAudioDevicePropertyBufferFrameSize;
|
||||||
|
|
|
@ -363,6 +363,14 @@ static int set_all_device_formats(SoundIoDevice *device) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void set_all_device_sample_rates(SoundIoDevice *device) {
|
||||||
|
SoundIoDevicePrivate *dev = (SoundIoDevicePrivate *)device;
|
||||||
|
device->sample_rate_count = 1;
|
||||||
|
device->sample_rates = &dev->prealloc_sample_rate_range;
|
||||||
|
device->sample_rates[0].min = 8000;
|
||||||
|
device->sample_rates[0].max = 5644800;
|
||||||
|
}
|
||||||
|
|
||||||
static int set_all_device_channel_layouts(SoundIoDevice *device) {
|
static int set_all_device_channel_layouts(SoundIoDevice *device) {
|
||||||
device->layout_count = soundio_channel_layout_builtin_count();
|
device->layout_count = soundio_channel_layout_builtin_count();
|
||||||
device->layouts = allocate<SoundIoChannelLayout>(device->layout_count);
|
device->layouts = allocate<SoundIoChannelLayout>(device->layout_count);
|
||||||
|
@ -429,12 +437,11 @@ int soundio_dummy_init(SoundIoPrivate *si) {
|
||||||
destroy_dummy(si);
|
destroy_dummy(si);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
set_all_device_sample_rates(device);
|
||||||
|
|
||||||
device->buffer_duration_min = 0.01;
|
device->buffer_duration_min = 0.01;
|
||||||
device->buffer_duration_max = 4;
|
device->buffer_duration_max = 4;
|
||||||
device->buffer_duration_current = 0.1;
|
device->buffer_duration_current = 0.1;
|
||||||
device->sample_rate_min = 2;
|
|
||||||
device->sample_rate_max = 5644800;
|
|
||||||
device->sample_rate_current = 48000;
|
device->sample_rate_current = 48000;
|
||||||
device->period_duration_min = 0.01;
|
device->period_duration_min = 0.01;
|
||||||
device->period_duration_max = 2;
|
device->period_duration_max = 2;
|
||||||
|
@ -479,11 +486,10 @@ int soundio_dummy_init(SoundIoPrivate *si) {
|
||||||
destroy_dummy(si);
|
destroy_dummy(si);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
set_all_device_sample_rates(device);
|
||||||
device->buffer_duration_min = 0.01;
|
device->buffer_duration_min = 0.01;
|
||||||
device->buffer_duration_max = 4;
|
device->buffer_duration_max = 4;
|
||||||
device->buffer_duration_current = 0.1;
|
device->buffer_duration_current = 0.1;
|
||||||
device->sample_rate_min = 2;
|
|
||||||
device->sample_rate_max = 5644800;
|
|
||||||
device->sample_rate_current = 48000;
|
device->sample_rate_current = 48000;
|
||||||
device->period_duration_min = 0.01;
|
device->period_duration_min = 0.01;
|
||||||
device->period_duration_max = 2;
|
device->period_duration_max = 2;
|
||||||
|
|
|
@ -192,8 +192,10 @@ static int refresh_devices_bare(SoundIoPrivate *si) {
|
||||||
device->format_count = 1;
|
device->format_count = 1;
|
||||||
device->formats = allocate<SoundIoFormat>(1);
|
device->formats = allocate<SoundIoFormat>(1);
|
||||||
device->current_format = SoundIoFormatFloat32NE;
|
device->current_format = SoundIoFormatFloat32NE;
|
||||||
device->sample_rate_min = sij->sample_rate;
|
device->sample_rate_count = 1;
|
||||||
device->sample_rate_max = sij->sample_rate;
|
device->sample_rates = &dev->prealloc_sample_rate_range;
|
||||||
|
device->sample_rates[0].min = sij->sample_rate;
|
||||||
|
device->sample_rates[0].max = sij->sample_rate;
|
||||||
device->sample_rate_current = sij->sample_rate;
|
device->sample_rate_current = sij->sample_rate;
|
||||||
device->period_duration_min = sij->period_size / (double) sij->sample_rate;
|
device->period_duration_min = sij->period_size / (double) sij->sample_rate;
|
||||||
device->period_duration_max = device->period_duration_min;
|
device->period_duration_max = device->period_duration_min;
|
||||||
|
|
|
@ -294,8 +294,10 @@ static void sink_info_callback(pa_context *pulse_context, const pa_sink_info *in
|
||||||
device->sample_rate_current = info->sample_spec.rate;
|
device->sample_rate_current = info->sample_spec.rate;
|
||||||
// PulseAudio performs resampling, so any value is valid. Let's pick
|
// PulseAudio performs resampling, so any value is valid. Let's pick
|
||||||
// some reasonable min and max values.
|
// some reasonable min and max values.
|
||||||
device->sample_rate_min = min(8000, device->sample_rate_current);
|
device->sample_rate_count = 1;
|
||||||
device->sample_rate_max = max(5644800, device->sample_rate_current);
|
device->sample_rates = &dev->prealloc_sample_rate_range;
|
||||||
|
device->sample_rates[0].min = min(8000, device->sample_rate_current);
|
||||||
|
device->sample_rates[0].max = max(5644800, device->sample_rate_current);
|
||||||
|
|
||||||
device->current_format = from_pulseaudio_format(info->sample_spec);
|
device->current_format = from_pulseaudio_format(info->sample_spec);
|
||||||
// PulseAudio performs sample format conversion, so any PulseAudio
|
// PulseAudio performs sample format conversion, so any PulseAudio
|
||||||
|
@ -364,8 +366,10 @@ static void source_info_callback(pa_context *pulse_context, const pa_source_info
|
||||||
device->sample_rate_current = info->sample_spec.rate;
|
device->sample_rate_current = info->sample_spec.rate;
|
||||||
// PulseAudio performs resampling, so any value is valid. Let's pick
|
// PulseAudio performs resampling, so any value is valid. Let's pick
|
||||||
// some reasonable min and max values.
|
// some reasonable min and max values.
|
||||||
device->sample_rate_min = min(8000, device->sample_rate_current);
|
device->sample_rate_count = 1;
|
||||||
device->sample_rate_max = max(5644800, device->sample_rate_current);
|
device->sample_rates = &dev->prealloc_sample_rate_range;
|
||||||
|
device->sample_rates[0].min = min(8000, device->sample_rate_current);
|
||||||
|
device->sample_rates[0].max = max(5644800, device->sample_rate_current);
|
||||||
|
|
||||||
device->current_format = from_pulseaudio_format(info->sample_spec);
|
device->current_format = from_pulseaudio_format(info->sample_spec);
|
||||||
// PulseAudio performs sample format conversion, so any PulseAudio
|
// PulseAudio performs sample format conversion, so any PulseAudio
|
||||||
|
|
|
@ -368,6 +368,9 @@ void soundio_device_unref(struct SoundIoDevice *device) {
|
||||||
free(device->formats);
|
free(device->formats);
|
||||||
free(device->layouts);
|
free(device->layouts);
|
||||||
|
|
||||||
|
if (device->sample_rates != &dev->prealloc_sample_rate_range)
|
||||||
|
free(device->sample_rates);
|
||||||
|
|
||||||
free(dev);
|
free(dev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -451,7 +454,7 @@ int soundio_outstream_open(struct SoundIoOutStream *outstream) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!outstream->sample_rate)
|
if (!outstream->sample_rate)
|
||||||
outstream->sample_rate = clamp(device->sample_rate_min, 48000, device->sample_rate_max);
|
outstream->sample_rate = soundio_device_nearest_sample_rate(device, 48000);
|
||||||
|
|
||||||
if (!outstream->name)
|
if (!outstream->name)
|
||||||
outstream->name = "SoundIoOutStream";
|
outstream->name = "SoundIoOutStream";
|
||||||
|
@ -537,7 +540,7 @@ int soundio_instream_open(struct SoundIoInStream *instream) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!instream->sample_rate)
|
if (!instream->sample_rate)
|
||||||
instream->sample_rate = clamp(device->sample_rate_min, 48000, device->sample_rate_max);
|
instream->sample_rate = soundio_device_nearest_sample_rate(device, 48000);
|
||||||
|
|
||||||
if (!instream->name)
|
if (!instream->name)
|
||||||
instream->name = "SoundIoInStream";
|
instream->name = "SoundIoInStream";
|
||||||
|
@ -687,3 +690,32 @@ bool soundio_device_supports_layout(struct SoundIoDevice *device,
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool soundio_device_supports_sample_rate(struct SoundIoDevice *device, int sample_rate) {
|
||||||
|
for (int i = 0; i < device->sample_rate_count; i += 1) {
|
||||||
|
SoundIoSampleRateRange *range = &device->sample_rates[i];
|
||||||
|
if (sample_rate >= range->min && sample_rate <= range->max)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int soundio_device_nearest_sample_rate(struct SoundIoDevice *device, int sample_rate) {
|
||||||
|
int best_rate = -1;
|
||||||
|
int best_delta = -1;
|
||||||
|
for (int i = 0; i < device->sample_rate_count; i += 1) {
|
||||||
|
SoundIoSampleRateRange *range = &device->sample_rates[i];
|
||||||
|
if (sample_rate < range->min) {
|
||||||
|
int delta = range->min - sample_rate;
|
||||||
|
if (best_delta == -1 || delta < best_delta) {
|
||||||
|
best_delta = delta;
|
||||||
|
best_rate = range->min;
|
||||||
|
}
|
||||||
|
} else if (best_rate == -1 && sample_rate > range->max) {
|
||||||
|
best_rate = range->max;
|
||||||
|
} else {
|
||||||
|
return sample_rate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return best_rate;
|
||||||
|
}
|
||||||
|
|
|
@ -147,6 +147,7 @@ struct SoundIoDevicePrivate {
|
||||||
SoundIoDevice pub;
|
SoundIoDevice pub;
|
||||||
SoundIoDeviceBackendData backend_data;
|
SoundIoDeviceBackendData backend_data;
|
||||||
void (*destruct)(SoundIoDevicePrivate *);
|
void (*destruct)(SoundIoDevicePrivate *);
|
||||||
|
SoundIoSampleRateRange prealloc_sample_rate_range;
|
||||||
};
|
};
|
||||||
|
|
||||||
void soundio_destroy_devices_info(struct SoundIoDevicesInfo *devices_info);
|
void soundio_destroy_devices_info(struct SoundIoDevicesInfo *devices_info);
|
||||||
|
|
Loading…
Reference in a new issue