mirror of
https://github.com/Ryujinx/libsoundio.git
synced 2025-01-03 15:15:32 +00:00
ALSA backend determines what formats a device supports
This commit is contained in:
parent
8887a528ef
commit
3b8d896c8e
|
@ -43,10 +43,15 @@ static void print_device(struct SoundIoDevice *device, bool is_default) {
|
|||
}
|
||||
raw_str = device->is_raw ? "(raw) " : "";
|
||||
const char *description = soundio_device_description(device);
|
||||
int sample_rate = soundio_device_sample_rate(device);
|
||||
int sample_rate = device->sample_rate_max;
|
||||
fprintf(stderr, "%s%s device: ", raw_str, purpose_str);
|
||||
print_channel_layout(soundio_device_channel_layout(device));
|
||||
fprintf(stderr, " %d Hz %s%s\n", sample_rate, description, default_str);
|
||||
if (device->probe_error) {
|
||||
fprintf(stderr, "[%s] %s%s\n", soundio_strerror(device->probe_error),
|
||||
description, default_str);
|
||||
} else {
|
||||
print_channel_layout(soundio_device_channel_layout(device));
|
||||
fprintf(stderr, " %d Hz %s%s\n", sample_rate, description, default_str);
|
||||
}
|
||||
}
|
||||
|
||||
static int list_devices(struct SoundIo *soundio) {
|
||||
|
@ -97,7 +102,7 @@ int main(int argc, char **argv) {
|
|||
|
||||
int err;
|
||||
if ((err = soundio_connect(soundio))) {
|
||||
fprintf(stderr, "%s\n", soundio_error_string(err));
|
||||
fprintf(stderr, "%s\n", soundio_strerror(err));
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ int main(int argc, char **argv) {
|
|||
|
||||
int err;
|
||||
if ((err = soundio_connect(soundio)))
|
||||
panic("error connecting: %s", soundio_error_string(err));
|
||||
panic("error connecting: %s", soundio_strerror(err));
|
||||
|
||||
int default_out_device_index = soundio_get_default_output_device_index(soundio);
|
||||
if (default_out_device_index < 0)
|
||||
|
@ -73,24 +73,21 @@ int main(int argc, char **argv) {
|
|||
if (!soundio_channel_layout_equal(in_layout, out_layout))
|
||||
panic("channel layouts not compatible");
|
||||
|
||||
if (soundio_device_sample_rate(in_device) != soundio_device_sample_rate(out_device))
|
||||
panic("sample rates not compatible");
|
||||
|
||||
double latency = 0.1;
|
||||
|
||||
struct SoundIoInputDevice *input_device;
|
||||
soundio_input_device_create(in_device, SoundIoSampleFormatFloat32NE, 48000, latency, NULL,
|
||||
soundio_input_device_create(in_device, SoundIoFormatFloat32NE, 48000, latency, NULL,
|
||||
read_callback, &input_device);
|
||||
|
||||
struct SoundIoOutputDevice *output_device;
|
||||
soundio_output_device_create(out_device, SoundIoSampleFormatFloat32NE, 48000, latency, NULL,
|
||||
soundio_output_device_create(out_device, SoundIoFormatFloat32NE, 48000, latency, NULL,
|
||||
write_callback, underrun_callback, &output_device);
|
||||
|
||||
if ((err = soundio_input_device_start(input_device)))
|
||||
panic("unable to start input device: %s", soundio_error_string(err));
|
||||
panic("unable to start input device: %s", soundio_strerror(err));
|
||||
|
||||
if ((err = soundio_output_device_start(output_device)))
|
||||
panic("unable to start output device: %s", soundio_error_string(err));
|
||||
panic("unable to start output device: %s", soundio_strerror(err));
|
||||
|
||||
for (;;)
|
||||
soundio_wait_events(soundio);
|
||||
|
|
|
@ -75,7 +75,7 @@ int main(int argc, char **argv) {
|
|||
|
||||
int err;
|
||||
if ((err = soundio_connect(soundio)))
|
||||
panic("error connecting: %s", soundio_error_string(err));
|
||||
panic("error connecting: %s", soundio_strerror(err));
|
||||
|
||||
int default_out_device_index = soundio_get_default_output_device_index(soundio);
|
||||
if (default_out_device_index < 0)
|
||||
|
@ -90,11 +90,11 @@ int main(int argc, char **argv) {
|
|||
soundio_device_description(device));
|
||||
|
||||
struct SoundIoOutputDevice *output_device;
|
||||
soundio_output_device_create(device, SoundIoSampleFormatFloat32NE, 48000,
|
||||
soundio_output_device_create(device, SoundIoFormatFloat32NE, 48000,
|
||||
0.1, NULL, write_callback, underrun_callback, &output_device);
|
||||
|
||||
if ((err = soundio_output_device_start(output_device)))
|
||||
panic("unable to start device: %s", soundio_error_string(err));
|
||||
panic("unable to start device: %s", soundio_strerror(err));
|
||||
|
||||
for (;;)
|
||||
soundio_wait_events(soundio);
|
||||
|
|
113
src/alsa.cpp
113
src/alsa.cpp
|
@ -15,8 +15,6 @@
|
|||
|
||||
static snd_pcm_stream_t stream_types[] = {SND_PCM_STREAM_PLAYBACK, SND_PCM_STREAM_CAPTURE};
|
||||
|
||||
static const int MAX_SAMPLE_RATE = 48000;
|
||||
|
||||
struct SoundIoAlsa {
|
||||
SoundIoOsMutex *mutex;
|
||||
SoundIoOsCond *cond;
|
||||
|
@ -158,6 +156,40 @@ static void handle_channel_maps(SoundIoDevice *device, snd_pcm_chmap_query_t **m
|
|||
snd_pcm_free_chmaps(maps);
|
||||
}
|
||||
|
||||
static snd_pcm_format_t to_alsa_fmt(SoundIoFormat fmt) {
|
||||
switch (fmt) {
|
||||
case SoundIoFormatS8: return SND_PCM_FORMAT_S8;
|
||||
case SoundIoFormatU8: return SND_PCM_FORMAT_U8;
|
||||
case SoundIoFormatS16LE: return SND_PCM_FORMAT_S16_LE;
|
||||
case SoundIoFormatS16BE: return SND_PCM_FORMAT_S16_BE;
|
||||
case SoundIoFormatU16LE: return SND_PCM_FORMAT_U16_LE;
|
||||
case SoundIoFormatU16BE: return SND_PCM_FORMAT_U16_BE;
|
||||
case SoundIoFormatS24LE: return SND_PCM_FORMAT_S24_LE;
|
||||
case SoundIoFormatS24BE: return SND_PCM_FORMAT_S24_BE;
|
||||
case SoundIoFormatU24LE: return SND_PCM_FORMAT_U24_LE;
|
||||
case SoundIoFormatU24BE: return SND_PCM_FORMAT_U24_BE;
|
||||
case SoundIoFormatS32LE: return SND_PCM_FORMAT_S32_LE;
|
||||
case SoundIoFormatS32BE: return SND_PCM_FORMAT_S32_BE;
|
||||
case SoundIoFormatU32LE: return SND_PCM_FORMAT_U32_LE;
|
||||
case SoundIoFormatU32BE: return SND_PCM_FORMAT_U32_BE;
|
||||
case SoundIoFormatFloat32LE: return SND_PCM_FORMAT_FLOAT_LE;
|
||||
case SoundIoFormatFloat32BE: return SND_PCM_FORMAT_FLOAT_BE;
|
||||
case SoundIoFormatFloat64LE: return SND_PCM_FORMAT_FLOAT64_LE;
|
||||
case SoundIoFormatFloat64BE: return SND_PCM_FORMAT_FLOAT64_BE;
|
||||
|
||||
case SoundIoFormatInvalid:
|
||||
return SND_PCM_FORMAT_UNKNOWN;
|
||||
}
|
||||
return SND_PCM_FORMAT_UNKNOWN;
|
||||
}
|
||||
|
||||
static void test_fmt_mask(SoundIoDevice *device, const snd_pcm_format_mask_t *fmt_mask, SoundIoFormat fmt) {
|
||||
if (snd_pcm_format_mask_test(fmt_mask, to_alsa_fmt(fmt))) {
|
||||
device->formats[device->format_count] = fmt;
|
||||
device->format_count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
static int probe_device(SoundIoDevice *device, snd_pcm_chmap_query_t **maps) {
|
||||
int err;
|
||||
snd_pcm_t *handle;
|
||||
|
@ -176,23 +208,27 @@ static int probe_device(SoundIoDevice *device, snd_pcm_chmap_query_t **maps) {
|
|||
}
|
||||
|
||||
if ((err = snd_pcm_hw_params_any(handle, hwparams)) < 0) {
|
||||
handle_channel_maps(device, maps);
|
||||
snd_pcm_close(handle);
|
||||
return SoundIoErrorOpeningDevice;
|
||||
}
|
||||
|
||||
// disable hardware resampling because we're trying to probe
|
||||
if ((err = snd_pcm_hw_params_set_rate_resample(handle, hwparams, 0)) < 0) {
|
||||
handle_channel_maps(device, maps);
|
||||
snd_pcm_close(handle);
|
||||
return SoundIoErrorOpeningDevice;
|
||||
}
|
||||
|
||||
if ((err = snd_pcm_hw_params_set_access(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
|
||||
handle_channel_maps(device, maps);
|
||||
snd_pcm_close(handle);
|
||||
return SoundIoErrorOpeningDevice;
|
||||
}
|
||||
|
||||
unsigned int channel_count;
|
||||
if ((err = snd_pcm_hw_params_set_channels_last(handle, hwparams, &channel_count)) < 0) {
|
||||
handle_channel_maps(device, maps);
|
||||
snd_pcm_close(handle);
|
||||
return SoundIoErrorOpeningDevice;
|
||||
}
|
||||
|
@ -203,6 +239,7 @@ static int probe_device(SoundIoDevice *device, snd_pcm_chmap_query_t **maps) {
|
|||
int max_dir;
|
||||
|
||||
if ((err = snd_pcm_hw_params_get_rate_max(hwparams, &max_sample_rate, &max_dir)) < 0) {
|
||||
handle_channel_maps(device, maps);
|
||||
snd_pcm_close(handle);
|
||||
return SoundIoErrorOpeningDevice;
|
||||
}
|
||||
|
@ -210,12 +247,68 @@ static int probe_device(SoundIoDevice *device, snd_pcm_chmap_query_t **maps) {
|
|||
max_sample_rate -= 1;
|
||||
|
||||
if ((err = snd_pcm_hw_params_get_rate_min(hwparams, &min_sample_rate, &min_dir)) < 0) {
|
||||
handle_channel_maps(device, maps);
|
||||
snd_pcm_close(handle);
|
||||
return SoundIoErrorOpeningDevice;
|
||||
}
|
||||
if (min_dir > 0)
|
||||
min_sample_rate += 1;
|
||||
|
||||
snd_pcm_format_mask_t *fmt_mask;
|
||||
snd_pcm_format_mask_alloca(&fmt_mask);
|
||||
snd_pcm_format_mask_none(fmt_mask);
|
||||
snd_pcm_format_mask_set(fmt_mask, SND_PCM_FORMAT_S8);
|
||||
snd_pcm_format_mask_set(fmt_mask, SND_PCM_FORMAT_U8);
|
||||
snd_pcm_format_mask_set(fmt_mask, SND_PCM_FORMAT_S16_LE);
|
||||
snd_pcm_format_mask_set(fmt_mask, SND_PCM_FORMAT_S16_BE);
|
||||
snd_pcm_format_mask_set(fmt_mask, SND_PCM_FORMAT_U16_LE);
|
||||
snd_pcm_format_mask_set(fmt_mask, SND_PCM_FORMAT_U16_BE);
|
||||
snd_pcm_format_mask_set(fmt_mask, SND_PCM_FORMAT_S24_LE);
|
||||
snd_pcm_format_mask_set(fmt_mask, SND_PCM_FORMAT_S24_BE);
|
||||
snd_pcm_format_mask_set(fmt_mask, SND_PCM_FORMAT_U24_LE);
|
||||
snd_pcm_format_mask_set(fmt_mask, SND_PCM_FORMAT_U24_BE);
|
||||
snd_pcm_format_mask_set(fmt_mask, SND_PCM_FORMAT_S32_LE);
|
||||
snd_pcm_format_mask_set(fmt_mask, SND_PCM_FORMAT_S32_BE);
|
||||
snd_pcm_format_mask_set(fmt_mask, SND_PCM_FORMAT_U32_LE);
|
||||
snd_pcm_format_mask_set(fmt_mask, SND_PCM_FORMAT_U32_BE);
|
||||
snd_pcm_format_mask_set(fmt_mask, SND_PCM_FORMAT_FLOAT_LE);
|
||||
snd_pcm_format_mask_set(fmt_mask, SND_PCM_FORMAT_FLOAT_BE);
|
||||
snd_pcm_format_mask_set(fmt_mask, SND_PCM_FORMAT_FLOAT64_LE);
|
||||
snd_pcm_format_mask_set(fmt_mask, SND_PCM_FORMAT_FLOAT64_BE);
|
||||
|
||||
if ((err = snd_pcm_hw_params_set_format_mask(handle, hwparams, fmt_mask)) < 0) {
|
||||
handle_channel_maps(device, maps);
|
||||
snd_pcm_close(handle);
|
||||
return SoundIoErrorOpeningDevice;
|
||||
}
|
||||
|
||||
snd_pcm_hw_params_get_format_mask(hwparams, fmt_mask);
|
||||
device->formats = allocate<SoundIoFormat>(18);
|
||||
if (!device->formats) {
|
||||
handle_channel_maps(device, maps);
|
||||
snd_pcm_close(handle);
|
||||
return SoundIoErrorNoMem;
|
||||
}
|
||||
|
||||
device->format_count = 0;
|
||||
test_fmt_mask(device, fmt_mask, SoundIoFormatS8);
|
||||
test_fmt_mask(device, fmt_mask, SoundIoFormatU8);
|
||||
test_fmt_mask(device, fmt_mask, SoundIoFormatS16LE);
|
||||
test_fmt_mask(device, fmt_mask, SoundIoFormatS16BE);
|
||||
test_fmt_mask(device, fmt_mask, SoundIoFormatU16LE);
|
||||
test_fmt_mask(device, fmt_mask, SoundIoFormatU16BE);
|
||||
test_fmt_mask(device, fmt_mask, SoundIoFormatS24LE);
|
||||
test_fmt_mask(device, fmt_mask, SoundIoFormatS24BE);
|
||||
test_fmt_mask(device, fmt_mask, SoundIoFormatU24LE);
|
||||
test_fmt_mask(device, fmt_mask, SoundIoFormatU24BE);
|
||||
test_fmt_mask(device, fmt_mask, SoundIoFormatS32LE);
|
||||
test_fmt_mask(device, fmt_mask, SoundIoFormatS32BE);
|
||||
test_fmt_mask(device, fmt_mask, SoundIoFormatU32LE);
|
||||
test_fmt_mask(device, fmt_mask, SoundIoFormatU32BE);
|
||||
test_fmt_mask(device, fmt_mask, SoundIoFormatFloat32LE);
|
||||
test_fmt_mask(device, fmt_mask, SoundIoFormatFloat32BE);
|
||||
test_fmt_mask(device, fmt_mask, SoundIoFormatFloat64LE);
|
||||
test_fmt_mask(device, fmt_mask, SoundIoFormatFloat64BE);
|
||||
|
||||
|
||||
snd_pcm_chmap_t *chmap = snd_pcm_get_chmap(handle);
|
||||
|
@ -229,16 +322,14 @@ static int probe_device(SoundIoDevice *device, snd_pcm_chmap_query_t **maps) {
|
|||
|
||||
|
||||
device->sample_rate_min = min_sample_rate;
|
||||
device->sample_rate_min = max_sample_rate;
|
||||
device->sample_rate_default =
|
||||
(min_sample_rate <= MAX_SAMPLE_RATE &&
|
||||
MAX_SAMPLE_RATE <= max_sample_rate) ? MAX_SAMPLE_RATE : max_sample_rate;
|
||||
|
||||
device->sample_rate_max = max_sample_rate;
|
||||
// TODO can we figure out what sample rate dmix is currently playing at,
|
||||
// if dmix applies to this device?
|
||||
device->sample_rate_current = 0;
|
||||
|
||||
snd_pcm_close(handle);
|
||||
return 0;
|
||||
|
||||
// TODO: device->default_sample_format
|
||||
// TODO: device->default_latency
|
||||
}
|
||||
|
||||
|
@ -352,7 +443,7 @@ static int refresh_devices(SoundIo *soundio) {
|
|||
devices_info->default_input_index = device_list->length;
|
||||
}
|
||||
|
||||
probe_device(device, nullptr);
|
||||
device->probe_error = probe_device(device, nullptr);
|
||||
|
||||
if (device_list->append(device)) {
|
||||
soundio_device_unref(device);
|
||||
|
@ -461,7 +552,7 @@ static int refresh_devices(SoundIo *soundio) {
|
|||
}
|
||||
|
||||
snd_pcm_chmap_query_t **maps = snd_pcm_query_chmaps_from_hw(card_index, device_index, -1, stream);
|
||||
probe_device(device, maps);
|
||||
device->probe_error = probe_device(device, maps);
|
||||
|
||||
if (device_list->append(device)) {
|
||||
soundio_device_unref(device);
|
||||
|
@ -575,7 +666,7 @@ static void device_thread_run(void *arg) {
|
|||
}
|
||||
if (got_rescan_event) {
|
||||
if ((err = refresh_devices(soundio)))
|
||||
soundio_panic("error refreshing devices: %s", soundio_error_string(err));
|
||||
soundio_panic("error refreshing devices: %s", soundio_strerror(err));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -245,6 +245,34 @@ static void input_device_clear_buffer_dummy(SoundIo *soundio,
|
|||
soundio_panic("TODO");
|
||||
}
|
||||
|
||||
static int set_all_device_formats(SoundIoDevice *device) {
|
||||
device->format_count = 18;
|
||||
device->formats = allocate<SoundIoFormat>(device->format_count);
|
||||
if (!device->formats)
|
||||
return SoundIoErrorNoMem;
|
||||
|
||||
device->formats[0] = SoundIoFormatS8;
|
||||
device->formats[1] = SoundIoFormatU8;
|
||||
device->formats[2] = SoundIoFormatS16LE;
|
||||
device->formats[3] = SoundIoFormatS16BE;
|
||||
device->formats[4] = SoundIoFormatU16LE;
|
||||
device->formats[5] = SoundIoFormatU16BE;
|
||||
device->formats[6] = SoundIoFormatS24LE;
|
||||
device->formats[7] = SoundIoFormatS24BE;
|
||||
device->formats[8] = SoundIoFormatU24LE;
|
||||
device->formats[9] = SoundIoFormatU24BE;
|
||||
device->formats[10] = SoundIoFormatS32LE;
|
||||
device->formats[11] = SoundIoFormatS32BE;
|
||||
device->formats[12] = SoundIoFormatU32LE;
|
||||
device->formats[13] = SoundIoFormatU32BE;
|
||||
device->formats[14] = SoundIoFormatFloat32LE;
|
||||
device->formats[15] = SoundIoFormatFloat32BE;
|
||||
device->formats[16] = SoundIoFormatFloat64LE;
|
||||
device->formats[17] = SoundIoFormatFloat64BE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int soundio_dummy_init(SoundIo *soundio) {
|
||||
assert(!soundio->backend_data);
|
||||
SoundIoDummy *sid = create<SoundIoDummy>();
|
||||
|
@ -287,17 +315,24 @@ int soundio_dummy_init(SoundIo *soundio) {
|
|||
device->ref_count = 1;
|
||||
device->soundio = soundio;
|
||||
device->name = strdup("dummy-out");
|
||||
device->description = strdup("Dummy output device");
|
||||
device->description = strdup("Dummy Output Device");
|
||||
if (!device->name || !device->description) {
|
||||
free(device->name);
|
||||
free(device->description);
|
||||
soundio_device_unref(device);
|
||||
destroy_dummy(soundio);
|
||||
return SoundIoErrorNoMem;
|
||||
}
|
||||
device->channel_layout = *soundio_channel_layout_get_builtin(SoundIoChannelLayoutIdMono);
|
||||
device->default_sample_format = SoundIoSampleFormatFloat32NE;
|
||||
int err;
|
||||
if ((err = set_all_device_formats(device))) {
|
||||
soundio_device_unref(device);
|
||||
destroy_dummy(soundio);
|
||||
return err;
|
||||
}
|
||||
|
||||
device->default_latency = 0.01;
|
||||
device->sample_rate_default = 48000;
|
||||
device->sample_rate_min = 2;
|
||||
device->sample_rate_max = 5644800;
|
||||
device->sample_rate_current = 48000;
|
||||
device->purpose = SoundIoDevicePurposeOutput;
|
||||
|
||||
if (soundio->safe_devices_info->output_devices.append(device)) {
|
||||
|
@ -325,9 +360,16 @@ int soundio_dummy_init(SoundIo *soundio) {
|
|||
return SoundIoErrorNoMem;
|
||||
}
|
||||
device->channel_layout = *soundio_channel_layout_get_builtin(SoundIoChannelLayoutIdMono);
|
||||
device->default_sample_format = SoundIoSampleFormatFloat32NE;
|
||||
int err;
|
||||
if ((err = set_all_device_formats(device))) {
|
||||
soundio_device_unref(device);
|
||||
destroy_dummy(soundio);
|
||||
return err;
|
||||
}
|
||||
device->default_latency = 0.01;
|
||||
device->sample_rate_default = 48000;
|
||||
device->sample_rate_min = 2;
|
||||
device->sample_rate_max = 5644800;
|
||||
device->sample_rate_current = 48000;
|
||||
device->purpose = SoundIoDevicePurposeInput;
|
||||
|
||||
if (soundio->safe_devices_info->input_devices.append(device)) {
|
||||
|
|
|
@ -139,17 +139,17 @@ static double usec_to_sec(pa_usec_t usec) {
|
|||
}
|
||||
|
||||
|
||||
static SoundIoSampleFormat sample_format_from_pulseaudio(pa_sample_spec sample_spec) {
|
||||
static SoundIoFormat format_from_pulseaudio(pa_sample_spec sample_spec) {
|
||||
switch (sample_spec.format) {
|
||||
case PA_SAMPLE_U8: return SoundIoSampleFormatU8;
|
||||
case PA_SAMPLE_S16LE: return SoundIoSampleFormatS16LE;
|
||||
case PA_SAMPLE_S16BE: return SoundIoSampleFormatS16BE;
|
||||
case PA_SAMPLE_FLOAT32LE: return SoundIoSampleFormatFloat32LE;
|
||||
case PA_SAMPLE_FLOAT32BE: return SoundIoSampleFormatFloat32BE;
|
||||
case PA_SAMPLE_S32LE: return SoundIoSampleFormatS32LE;
|
||||
case PA_SAMPLE_S32BE: return SoundIoSampleFormatS32BE;
|
||||
case PA_SAMPLE_S24_32LE: return SoundIoSampleFormatS24LE;
|
||||
case PA_SAMPLE_S24_32BE: return SoundIoSampleFormatS24BE;
|
||||
case PA_SAMPLE_U8: return SoundIoFormatU8;
|
||||
case PA_SAMPLE_S16LE: return SoundIoFormatS16LE;
|
||||
case PA_SAMPLE_S16BE: return SoundIoFormatS16BE;
|
||||
case PA_SAMPLE_FLOAT32LE: return SoundIoFormatFloat32LE;
|
||||
case PA_SAMPLE_FLOAT32BE: return SoundIoFormatFloat32BE;
|
||||
case PA_SAMPLE_S32LE: return SoundIoFormatS32LE;
|
||||
case PA_SAMPLE_S32BE: return SoundIoFormatS32BE;
|
||||
case PA_SAMPLE_S24_32LE: return SoundIoFormatS24LE;
|
||||
case PA_SAMPLE_S24_32BE: return SoundIoFormatS24BE;
|
||||
|
||||
case PA_SAMPLE_MAX:
|
||||
case PA_SAMPLE_INVALID:
|
||||
|
@ -157,9 +157,9 @@ static SoundIoSampleFormat sample_format_from_pulseaudio(pa_sample_spec sample_s
|
|||
case PA_SAMPLE_ULAW:
|
||||
case PA_SAMPLE_S24LE:
|
||||
case PA_SAMPLE_S24BE:
|
||||
return SoundIoSampleFormatInvalid;
|
||||
return SoundIoFormatInvalid;
|
||||
}
|
||||
return SoundIoSampleFormatInvalid;
|
||||
return SoundIoFormatInvalid;
|
||||
}
|
||||
|
||||
static int sample_rate_from_pulseaudio(pa_sample_spec sample_spec) {
|
||||
|
@ -280,9 +280,10 @@ static void sink_info_callback(pa_context *pulse_context, const pa_sink_info *in
|
|||
if (!device->name || !device->description)
|
||||
soundio_panic("out of memory");
|
||||
set_from_pulseaudio_channel_map(info->channel_map, &device->channel_layout);
|
||||
device->default_sample_format = sample_format_from_pulseaudio(info->sample_spec);
|
||||
// TODO determine the list of supported formats and the min and max sample rate
|
||||
device->current_format = format_from_pulseaudio(info->sample_spec);
|
||||
device->default_latency = usec_to_sec(info->configured_latency);
|
||||
device->sample_rate_default = sample_rate_from_pulseaudio(info->sample_spec);
|
||||
device->sample_rate_current = sample_rate_from_pulseaudio(info->sample_spec);
|
||||
device->purpose = SoundIoDevicePurposeOutput;
|
||||
|
||||
if (sipa->current_devices_info->output_devices.append(device))
|
||||
|
@ -309,9 +310,10 @@ static void source_info_callback(pa_context *pulse_context, const pa_source_info
|
|||
if (!device->name || !device->description)
|
||||
soundio_panic("out of memory");
|
||||
set_from_pulseaudio_channel_map(info->channel_map, &device->channel_layout);
|
||||
device->default_sample_format = sample_format_from_pulseaudio(info->sample_spec);
|
||||
// TODO determine the list of supported formats and the min and max sample rate
|
||||
device->current_format = format_from_pulseaudio(info->sample_spec);
|
||||
device->default_latency = usec_to_sec(info->configured_latency);
|
||||
device->sample_rate_default = sample_rate_from_pulseaudio(info->sample_spec);
|
||||
device->sample_rate_current = sample_rate_from_pulseaudio(info->sample_spec);
|
||||
device->purpose = SoundIoDevicePurposeInput;
|
||||
|
||||
if (sipa->current_devices_info->input_devices.append(device))
|
||||
|
@ -437,28 +439,28 @@ static void wakeup(SoundIo *soundio) {
|
|||
pa_threaded_mainloop_signal(sipa->main_loop, 0);
|
||||
}
|
||||
|
||||
static pa_sample_format_t to_pulseaudio_sample_format(SoundIoSampleFormat sample_format) {
|
||||
switch (sample_format) {
|
||||
case SoundIoSampleFormatU8: return PA_SAMPLE_U8;
|
||||
case SoundIoSampleFormatS16LE: return PA_SAMPLE_S16LE;
|
||||
case SoundIoSampleFormatS16BE: return PA_SAMPLE_S16BE;
|
||||
case SoundIoSampleFormatS24LE: return PA_SAMPLE_S24_32LE;
|
||||
case SoundIoSampleFormatS24BE: return PA_SAMPLE_S24_32BE;
|
||||
case SoundIoSampleFormatS32LE: return PA_SAMPLE_S32LE;
|
||||
case SoundIoSampleFormatS32BE: return PA_SAMPLE_S32BE;
|
||||
case SoundIoSampleFormatFloat32LE: return PA_SAMPLE_FLOAT32LE;
|
||||
case SoundIoSampleFormatFloat32BE: return PA_SAMPLE_FLOAT32BE;
|
||||
static pa_sample_format_t to_pulseaudio_format(SoundIoFormat format) {
|
||||
switch (format) {
|
||||
case SoundIoFormatU8: return PA_SAMPLE_U8;
|
||||
case SoundIoFormatS16LE: return PA_SAMPLE_S16LE;
|
||||
case SoundIoFormatS16BE: return PA_SAMPLE_S16BE;
|
||||
case SoundIoFormatS24LE: return PA_SAMPLE_S24_32LE;
|
||||
case SoundIoFormatS24BE: return PA_SAMPLE_S24_32BE;
|
||||
case SoundIoFormatS32LE: return PA_SAMPLE_S32LE;
|
||||
case SoundIoFormatS32BE: return PA_SAMPLE_S32BE;
|
||||
case SoundIoFormatFloat32LE: return PA_SAMPLE_FLOAT32LE;
|
||||
case SoundIoFormatFloat32BE: return PA_SAMPLE_FLOAT32BE;
|
||||
|
||||
case SoundIoSampleFormatInvalid:
|
||||
case SoundIoSampleFormatS8:
|
||||
case SoundIoSampleFormatU16LE:
|
||||
case SoundIoSampleFormatU16BE:
|
||||
case SoundIoSampleFormatU24LE:
|
||||
case SoundIoSampleFormatU24BE:
|
||||
case SoundIoSampleFormatU32LE:
|
||||
case SoundIoSampleFormatU32BE:
|
||||
case SoundIoSampleFormatFloat64LE:
|
||||
case SoundIoSampleFormatFloat64BE:
|
||||
case SoundIoFormatInvalid:
|
||||
case SoundIoFormatS8:
|
||||
case SoundIoFormatU16LE:
|
||||
case SoundIoFormatU16BE:
|
||||
case SoundIoFormatU24LE:
|
||||
case SoundIoFormatU24BE:
|
||||
case SoundIoFormatU32LE:
|
||||
case SoundIoFormatU32BE:
|
||||
case SoundIoFormatFloat64LE:
|
||||
case SoundIoFormatFloat64BE:
|
||||
return PA_SAMPLE_INVALID;
|
||||
}
|
||||
return PA_SAMPLE_INVALID;
|
||||
|
@ -600,7 +602,7 @@ static int output_device_init_pa(SoundIo *soundio,
|
|||
pa_threaded_mainloop_lock(sipa->main_loop);
|
||||
|
||||
pa_sample_spec sample_spec;
|
||||
sample_spec.format = to_pulseaudio_sample_format(output_device->sample_format);
|
||||
sample_spec.format = to_pulseaudio_format(output_device->format);
|
||||
sample_spec.rate = output_device->sample_rate;
|
||||
sample_spec.channels = device->channel_layout.channel_count;
|
||||
pa_channel_map channel_map = to_pulseaudio_channel_map(&device->channel_layout);
|
||||
|
@ -766,7 +768,7 @@ static int input_device_init_pa(SoundIo *soundio,
|
|||
pa_threaded_mainloop_lock(sipa->main_loop);
|
||||
|
||||
pa_sample_spec sample_spec;
|
||||
sample_spec.format = to_pulseaudio_sample_format(input_device->sample_format);
|
||||
sample_spec.format = to_pulseaudio_format(input_device->format);
|
||||
sample_spec.rate = input_device->sample_rate;
|
||||
sample_spec.channels = device->channel_layout.channel_count;
|
||||
|
||||
|
|
107
src/soundio.cpp
107
src/soundio.cpp
|
@ -22,7 +22,7 @@
|
|||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
const char *soundio_error_string(int error) {
|
||||
const char *soundio_strerror(int error) {
|
||||
switch ((enum SoundIoError)error) {
|
||||
case SoundIoErrorNone: return "(no error)";
|
||||
case SoundIoErrorNoMem: return "out of memory";
|
||||
|
@ -33,52 +33,56 @@ const char *soundio_error_string(int error) {
|
|||
soundio_panic("invalid error enum value: %d", error);
|
||||
}
|
||||
|
||||
int soundio_get_bytes_per_sample(enum SoundIoSampleFormat sample_format) {
|
||||
switch (sample_format) {
|
||||
case SoundIoSampleFormatInvalid: soundio_panic("invalid sample format");
|
||||
case SoundIoSampleFormatU8: return 1;
|
||||
case SoundIoSampleFormatS8: return 1;
|
||||
case SoundIoSampleFormatS16LE: return 2;
|
||||
case SoundIoSampleFormatS16BE: return 2;
|
||||
case SoundIoSampleFormatU16LE: return 2;
|
||||
case SoundIoSampleFormatU16BE: return 2;
|
||||
case SoundIoSampleFormatS24LE: return 4;
|
||||
case SoundIoSampleFormatS24BE: return 4;
|
||||
case SoundIoSampleFormatU24LE: return 4;
|
||||
case SoundIoSampleFormatU24BE: return 4;
|
||||
case SoundIoSampleFormatS32LE: return 4;
|
||||
case SoundIoSampleFormatS32BE: return 4;
|
||||
case SoundIoSampleFormatU32LE: return 4;
|
||||
case SoundIoSampleFormatU32BE: return 4;
|
||||
case SoundIoSampleFormatFloat32LE: return 4;
|
||||
case SoundIoSampleFormatFloat32BE: return 4;
|
||||
case SoundIoSampleFormatFloat64LE: return 8;
|
||||
case SoundIoSampleFormatFloat64BE: return 8;
|
||||
int soundio_get_bytes_per_sample(enum SoundIoFormat format) {
|
||||
switch (format) {
|
||||
case SoundIoFormatU8: return 1;
|
||||
case SoundIoFormatS8: return 1;
|
||||
case SoundIoFormatS16LE: return 2;
|
||||
case SoundIoFormatS16BE: return 2;
|
||||
case SoundIoFormatU16LE: return 2;
|
||||
case SoundIoFormatU16BE: return 2;
|
||||
case SoundIoFormatS24LE: return 4;
|
||||
case SoundIoFormatS24BE: return 4;
|
||||
case SoundIoFormatU24LE: return 4;
|
||||
case SoundIoFormatU24BE: return 4;
|
||||
case SoundIoFormatS32LE: return 4;
|
||||
case SoundIoFormatS32BE: return 4;
|
||||
case SoundIoFormatU32LE: return 4;
|
||||
case SoundIoFormatU32BE: return 4;
|
||||
case SoundIoFormatFloat32LE: return 4;
|
||||
case SoundIoFormatFloat32BE: return 4;
|
||||
case SoundIoFormatFloat64LE: return 8;
|
||||
case SoundIoFormatFloat64BE: return 8;
|
||||
|
||||
case SoundIoFormatInvalid:
|
||||
soundio_panic("invalid sample format");
|
||||
}
|
||||
soundio_panic("invalid sample format");
|
||||
}
|
||||
|
||||
const char * soundio_sample_format_string(enum SoundIoSampleFormat sample_format) {
|
||||
switch (sample_format) {
|
||||
case SoundIoSampleFormatInvalid: return "(invalid sample format)";
|
||||
case SoundIoSampleFormatU8: return "signed 8-bit";
|
||||
case SoundIoSampleFormatS8: return "unsigned 8-bit";
|
||||
case SoundIoSampleFormatS16LE: return "signed 16-bit LE";
|
||||
case SoundIoSampleFormatS16BE: return "signed 16-bit BE";
|
||||
case SoundIoSampleFormatU16LE: return "unsigned 16-bit LE";
|
||||
case SoundIoSampleFormatU16BE: return "unsigned 16-bit LE";
|
||||
case SoundIoSampleFormatS24LE: return "signed 24-bit LE";
|
||||
case SoundIoSampleFormatS24BE: return "signed 24-bit BE";
|
||||
case SoundIoSampleFormatU24LE: return "unsigned 24-bit LE";
|
||||
case SoundIoSampleFormatU24BE: return "unsigned 24-bit BE";
|
||||
case SoundIoSampleFormatS32LE: return "signed 32-bit LE";
|
||||
case SoundIoSampleFormatS32BE: return "signed 32-bit BE";
|
||||
case SoundIoSampleFormatU32LE: return "unsigned 32-bit LE";
|
||||
case SoundIoSampleFormatU32BE: return "unsigned 32-bit BE";
|
||||
case SoundIoSampleFormatFloat32LE: return "float 32-bit LE";
|
||||
case SoundIoSampleFormatFloat32BE: return "float 32-bit BE";
|
||||
case SoundIoSampleFormatFloat64LE: return "float 64-bit LE";
|
||||
case SoundIoSampleFormatFloat64BE: return "float 64-bit BE";
|
||||
const char * soundio_format_string(enum SoundIoFormat format) {
|
||||
switch (format) {
|
||||
case SoundIoFormatU8: return "signed 8-bit";
|
||||
case SoundIoFormatS8: return "unsigned 8-bit";
|
||||
case SoundIoFormatS16LE: return "signed 16-bit LE";
|
||||
case SoundIoFormatS16BE: return "signed 16-bit BE";
|
||||
case SoundIoFormatU16LE: return "unsigned 16-bit LE";
|
||||
case SoundIoFormatU16BE: return "unsigned 16-bit LE";
|
||||
case SoundIoFormatS24LE: return "signed 24-bit LE";
|
||||
case SoundIoFormatS24BE: return "signed 24-bit BE";
|
||||
case SoundIoFormatU24LE: return "unsigned 24-bit LE";
|
||||
case SoundIoFormatU24BE: return "unsigned 24-bit BE";
|
||||
case SoundIoFormatS32LE: return "signed 32-bit LE";
|
||||
case SoundIoFormatS32BE: return "signed 32-bit BE";
|
||||
case SoundIoFormatU32LE: return "unsigned 32-bit LE";
|
||||
case SoundIoFormatU32BE: return "unsigned 32-bit BE";
|
||||
case SoundIoFormatFloat32LE: return "float 32-bit LE";
|
||||
case SoundIoFormatFloat32BE: return "float 32-bit BE";
|
||||
case SoundIoFormatFloat64LE: return "float 64-bit LE";
|
||||
case SoundIoFormatFloat64BE: return "float 64-bit BE";
|
||||
|
||||
case SoundIoFormatInvalid:
|
||||
return "(invalid sample format)";
|
||||
}
|
||||
return "(invalid sample format)";
|
||||
}
|
||||
|
@ -250,10 +254,6 @@ const struct SoundIoChannelLayout *soundio_device_channel_layout(const struct So
|
|||
return &device->channel_layout;
|
||||
}
|
||||
|
||||
int soundio_device_sample_rate(const struct SoundIoDevice *device) {
|
||||
return device->sample_rate_default;
|
||||
}
|
||||
|
||||
void soundio_device_unref(struct SoundIoDevice *device) {
|
||||
if (!device)
|
||||
return;
|
||||
|
@ -264,6 +264,7 @@ void soundio_device_unref(struct SoundIoDevice *device) {
|
|||
if (device->ref_count == 0) {
|
||||
free(device->name);
|
||||
free(device->description);
|
||||
deallocate(device->formats, device->format_count);
|
||||
destroy(device);
|
||||
}
|
||||
}
|
||||
|
@ -313,7 +314,7 @@ void soundio_output_device_write(struct SoundIoOutputDevice *output_device,
|
|||
|
||||
|
||||
int soundio_output_device_create(struct SoundIoDevice *device,
|
||||
enum SoundIoSampleFormat sample_format, int sample_rate,
|
||||
enum SoundIoFormat format, int sample_rate,
|
||||
double latency, void *userdata,
|
||||
void (*write_callback)(struct SoundIoOutputDevice *, int frame_count),
|
||||
void (*underrun_callback)(struct SoundIoOutputDevice *),
|
||||
|
@ -332,10 +333,10 @@ int soundio_output_device_create(struct SoundIoDevice *device,
|
|||
output_device->userdata = userdata;
|
||||
output_device->write_callback = write_callback;
|
||||
output_device->underrun_callback = underrun_callback;
|
||||
output_device->sample_format = sample_format;
|
||||
output_device->format = format;
|
||||
output_device->sample_rate = sample_rate;
|
||||
output_device->latency = latency;
|
||||
output_device->bytes_per_frame = soundio_get_bytes_per_frame(sample_format,
|
||||
output_device->bytes_per_frame = soundio_get_bytes_per_frame(format,
|
||||
device->channel_layout.channel_count);
|
||||
|
||||
SoundIo *soundio = device->soundio;
|
||||
|
@ -368,7 +369,7 @@ int soundio_output_device_start(struct SoundIoOutputDevice *output_device) {
|
|||
}
|
||||
|
||||
int soundio_input_device_create(struct SoundIoDevice *device,
|
||||
enum SoundIoSampleFormat sample_format, int sample_rate,
|
||||
enum SoundIoFormat format, int sample_rate,
|
||||
double latency, void *userdata,
|
||||
void (*read_callback)(struct SoundIoInputDevice *),
|
||||
struct SoundIoInputDevice **out_input_device)
|
||||
|
@ -385,10 +386,10 @@ int soundio_input_device_create(struct SoundIoDevice *device,
|
|||
sid->device = device;
|
||||
sid->userdata = userdata;
|
||||
sid->read_callback = read_callback;
|
||||
sid->sample_format = sample_format;
|
||||
sid->format = format;
|
||||
sid->latency = latency;
|
||||
sid->sample_rate = sample_rate;
|
||||
sid->bytes_per_frame = soundio_get_bytes_per_frame(sample_format,
|
||||
sid->bytes_per_frame = soundio_get_bytes_per_frame(format,
|
||||
device->channel_layout.channel_count);
|
||||
|
||||
SoundIo *soundio = device->soundio;
|
||||
|
|
151
src/soundio.h
151
src/soundio.h
|
@ -140,74 +140,115 @@ enum SoundIoDevicePurpose {
|
|||
SoundIoDevicePurposeOutput,
|
||||
};
|
||||
|
||||
enum SoundIoSampleFormat {
|
||||
SoundIoSampleFormatInvalid,
|
||||
SoundIoSampleFormatU8, // Signed 8 bit
|
||||
SoundIoSampleFormatS8, // Unsigned 8 bit
|
||||
SoundIoSampleFormatS16LE, // Signed 16 bit Little Endian
|
||||
SoundIoSampleFormatS16BE, // Signed 16 bit Big Endian
|
||||
SoundIoSampleFormatU16LE, // Unsigned 16 bit Little Endian
|
||||
SoundIoSampleFormatU16BE, // Unsigned 16 bit Little Endian
|
||||
SoundIoSampleFormatS24LE, // Signed 24 bit Little Endian using low three bytes in 32-bit word
|
||||
SoundIoSampleFormatS24BE, // Signed 24 bit Big Endian using low three bytes in 32-bit word
|
||||
SoundIoSampleFormatU24LE, // Unsigned 24 bit Little Endian using low three bytes in 32-bit word
|
||||
SoundIoSampleFormatU24BE, // Unsigned 24 bit Big Endian using low three bytes in 32-bit word
|
||||
SoundIoSampleFormatS32LE, // Signed 32 bit Little Endian
|
||||
SoundIoSampleFormatS32BE, // Signed 32 bit Big Endian
|
||||
SoundIoSampleFormatU32LE, // Unsigned 32 bit Little Endian
|
||||
SoundIoSampleFormatU32BE, // Unsigned 32 bit Big Endian
|
||||
SoundIoSampleFormatFloat32LE, // Float 32 bit Little Endian, Range -1.0 to 1.0
|
||||
SoundIoSampleFormatFloat32BE, // Float 32 bit Big Endian, Range -1.0 to 1.0
|
||||
SoundIoSampleFormatFloat64LE, // Float 64 bit Little Endian, Range -1.0 to 1.0
|
||||
SoundIoSampleFormatFloat64BE, // Float 64 bit Big Endian, Range -1.0 to 1.0
|
||||
enum SoundIoFormat {
|
||||
SoundIoFormatInvalid,
|
||||
SoundIoFormatS8, // Signed 8 bit
|
||||
SoundIoFormatU8, // Unsigned 8 bit
|
||||
SoundIoFormatS16LE, // Signed 16 bit Little Endian
|
||||
SoundIoFormatS16BE, // Signed 16 bit Big Endian
|
||||
SoundIoFormatU16LE, // Unsigned 16 bit Little Endian
|
||||
SoundIoFormatU16BE, // Unsigned 16 bit Little Endian
|
||||
SoundIoFormatS24LE, // Signed 24 bit Little Endian using low three bytes in 32-bit word
|
||||
SoundIoFormatS24BE, // Signed 24 bit Big Endian using low three bytes in 32-bit word
|
||||
SoundIoFormatU24LE, // Unsigned 24 bit Little Endian using low three bytes in 32-bit word
|
||||
SoundIoFormatU24BE, // Unsigned 24 bit Big Endian using low three bytes in 32-bit word
|
||||
SoundIoFormatS32LE, // Signed 32 bit Little Endian
|
||||
SoundIoFormatS32BE, // Signed 32 bit Big Endian
|
||||
SoundIoFormatU32LE, // Unsigned 32 bit Little Endian
|
||||
SoundIoFormatU32BE, // Unsigned 32 bit Big Endian
|
||||
SoundIoFormatFloat32LE, // Float 32 bit Little Endian, Range -1.0 to 1.0
|
||||
SoundIoFormatFloat32BE, // Float 32 bit Big Endian, Range -1.0 to 1.0
|
||||
SoundIoFormatFloat64LE, // Float 64 bit Little Endian, Range -1.0 to 1.0
|
||||
SoundIoFormatFloat64BE, // Float 64 bit Big Endian, Range -1.0 to 1.0
|
||||
};
|
||||
|
||||
#if defined(SOUNDIO_OS_BIG_ENDIAN)
|
||||
#define SoundIoSampleFormatS16NE SoundIoSampleFormatS16BE
|
||||
#define SoundIoSampleFormatU16NE SoundIoSampleFormatU16BE
|
||||
#define SoundIoSampleFormatS24NE SoundIoSampleFormatS24BE
|
||||
#define SoundIoSampleFormatU24NE SoundIoSampleFormatU24BE
|
||||
#define SoundIoSampleFormatS32NE SoundIoSampleFormatS32BE
|
||||
#define SoundIoSampleFormatU32NE SoundIoSampleFormatU32BE
|
||||
#define SoundIoSampleFormatFloat32NE SoundIoSampleFormatFloat32BE
|
||||
#define SoundIoSampleFormatFloat64NE SoundIoSampleFormatFloat64BE
|
||||
#define SoundIoFormatS16NE SoundIoFormatS16BE
|
||||
#define SoundIoFormatU16NE SoundIoFormatU16BE
|
||||
#define SoundIoFormatS24NE SoundIoFormatS24BE
|
||||
#define SoundIoFormatU24NE SoundIoFormatU24BE
|
||||
#define SoundIoFormatS32NE SoundIoFormatS32BE
|
||||
#define SoundIoFormatU32NE SoundIoFormatU32BE
|
||||
#define SoundIoFormatFloat32NE SoundIoFormatFloat32BE
|
||||
#define SoundIoFormatFloat64NE SoundIoFormatFloat64BE
|
||||
#elif defined(SOUNDIO_OS_LITTLE_ENDIAN)
|
||||
#define SoundIoSampleFormatS16NE SoundIoSampleFormatS16LE
|
||||
#define SoundIoSampleFormatU16NE SoundIoSampleFormatU16LE
|
||||
#define SoundIoSampleFormatS24NE SoundIoSampleFormatS24LE
|
||||
#define SoundIoSampleFormatU24NE SoundIoSampleFormatU24LE
|
||||
#define SoundIoSampleFormatS32NE SoundIoSampleFormatS32LE
|
||||
#define SoundIoSampleFormatU32NE SoundIoSampleFormatU32LE
|
||||
#define SoundIoSampleFormatFloat32NE SoundIoSampleFormatFloat32LE
|
||||
#define SoundIoSampleFormatFloat64NE SoundIoSampleFormatFloat64LE
|
||||
#define SoundIoFormatS16NE SoundIoFormatS16LE
|
||||
#define SoundIoFormatU16NE SoundIoFormatU16LE
|
||||
#define SoundIoFormatS24NE SoundIoFormatS24LE
|
||||
#define SoundIoFormatU24NE SoundIoFormatU24LE
|
||||
#define SoundIoFormatS32NE SoundIoFormatS32LE
|
||||
#define SoundIoFormatU32NE SoundIoFormatU32LE
|
||||
#define SoundIoFormatFloat32NE SoundIoFormatFloat32LE
|
||||
#define SoundIoFormatFloat64NE SoundIoFormatFloat64LE
|
||||
#endif
|
||||
|
||||
struct SoundIoDevice {
|
||||
struct SoundIo *soundio;
|
||||
|
||||
// `name` uniquely identifies this device. `description` is user-friendly
|
||||
// text to describe the device.
|
||||
char *name;
|
||||
char *description;
|
||||
|
||||
// If this information is missing due to a `probe_error`, the number of
|
||||
// channels will be zero.
|
||||
struct SoundIoChannelLayout channel_layout;
|
||||
|
||||
// these values might not actually matter. audio hardware has a set of
|
||||
// {sample format, sample rate} that they support. you can't know
|
||||
// whether something worked until you try it.
|
||||
// these values can be unknown
|
||||
enum SoundIoSampleFormat default_sample_format;
|
||||
// A device is either a raw device or it is a virtual device that is
|
||||
// provided by a software mixing service such as dmix or PulseAudio (see
|
||||
// `is_raw`). If it is a raw device, `current_format` is meaningless;
|
||||
// the device has no current format until you open it. On the other hand,
|
||||
// if it is a virtual device, `current_format` describes the destination
|
||||
// sample format that your audio will be converted to. Or, if you're the
|
||||
// lucky first application to open the device, you might cause the
|
||||
// `current_format` to change to your format. Generally, you want to
|
||||
// ignore `current_format` and use whatever format is most convenient
|
||||
// for you which is supported by the device, because when you are the only
|
||||
// application left, the mixer might decide to switch `current_format` to
|
||||
// yours. You can learn the supported formats via `formats` and
|
||||
// `format_count`. If this information is missing due to a probe error,
|
||||
// `formats` will be `NULL`. If `current_format` is unavailable, it will be
|
||||
// set to `SoundIoFormatInvalid`.
|
||||
enum SoundIoFormat *formats;
|
||||
int format_count;
|
||||
enum SoundIoFormat current_format;
|
||||
|
||||
// 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
|
||||
// will be set to zero.
|
||||
int sample_rate_min;
|
||||
int sample_rate_max;
|
||||
int sample_rate_default;
|
||||
int sample_rate_current;
|
||||
|
||||
double default_latency;
|
||||
|
||||
// Tells whether this device is an input device or an output device.
|
||||
enum SoundIoDevicePurpose purpose;
|
||||
int ref_count;
|
||||
|
||||
// raw means that you are directly opening the hardware device and not
|
||||
// going through a proxy such as dmix or PulseAudio. When you open a raw
|
||||
// device, other applications on the computer are not able to
|
||||
// simultaneously access the device. Raw devices do not perform automatic
|
||||
// resampling and thus tend to have fewer formats available.
|
||||
bool is_raw;
|
||||
|
||||
// Devices are reference counted. See `soundio_device_ref` and
|
||||
// `soundio_device_unref`.
|
||||
int ref_count;
|
||||
|
||||
// This is set to a SoundIoError representing the result of the device
|
||||
// probe. Ideally this will be SoundIoErrorNone in which case all the
|
||||
// fields of the device will be populated. If there is an error code here
|
||||
// then information about formats, sample rates, and channel layouts might
|
||||
// be missing.
|
||||
int probe_error;
|
||||
};
|
||||
|
||||
// TODO rename this to SoundIoOutStream
|
||||
struct SoundIoOutputDevice {
|
||||
void *backend_data;
|
||||
struct SoundIoDevice *device;
|
||||
enum SoundIoSampleFormat sample_format;
|
||||
enum SoundIoFormat format;
|
||||
int sample_rate;
|
||||
double latency;
|
||||
int bytes_per_frame;
|
||||
|
@ -217,10 +258,11 @@ struct SoundIoOutputDevice {
|
|||
void (*write_callback)(struct SoundIoOutputDevice *, int frame_count);
|
||||
};
|
||||
|
||||
// TODO rename this to SoundIoInStream
|
||||
struct SoundIoInputDevice {
|
||||
void *backend_data;
|
||||
struct SoundIoDevice *device;
|
||||
enum SoundIoSampleFormat sample_format;
|
||||
enum SoundIoFormat format;
|
||||
int sample_rate;
|
||||
double latency;
|
||||
int bytes_per_frame;
|
||||
|
@ -276,7 +318,7 @@ void soundio_destroy(struct SoundIo *soundio);
|
|||
int soundio_connect(struct SoundIo *soundio);
|
||||
void soundio_disconnect(struct SoundIo *soundio);
|
||||
|
||||
const char *soundio_error_string(int error);
|
||||
const char *soundio_strerror(int error);
|
||||
const char *soundio_backend_name(enum SoundIoBackend backend);
|
||||
|
||||
// when you call this, the on_devices_change and on_events_signal callbacks
|
||||
|
@ -315,19 +357,19 @@ bool soundio_channel_layout_detect_builtin(struct SoundIoChannelLayout *layout);
|
|||
|
||||
// Sample Formats
|
||||
|
||||
int soundio_get_bytes_per_sample(enum SoundIoSampleFormat sample_format);
|
||||
int soundio_get_bytes_per_sample(enum SoundIoFormat format);
|
||||
|
||||
static inline int soundio_get_bytes_per_frame(enum SoundIoSampleFormat sample_format, int channel_count) {
|
||||
return soundio_get_bytes_per_sample(sample_format) * channel_count;
|
||||
static inline int soundio_get_bytes_per_frame(enum SoundIoFormat format, int channel_count) {
|
||||
return soundio_get_bytes_per_sample(format) * channel_count;
|
||||
}
|
||||
|
||||
static inline int soundio_get_bytes_per_second(enum SoundIoSampleFormat sample_format,
|
||||
static inline int soundio_get_bytes_per_second(enum SoundIoFormat format,
|
||||
int channel_count, int sample_rate)
|
||||
{
|
||||
return soundio_get_bytes_per_frame(sample_format, channel_count) * sample_rate;
|
||||
return soundio_get_bytes_per_frame(format, channel_count) * sample_rate;
|
||||
}
|
||||
|
||||
const char * soundio_sample_format_string(enum SoundIoSampleFormat sample_format);
|
||||
const char * soundio_format_string(enum SoundIoFormat format);
|
||||
|
||||
|
||||
|
||||
|
@ -359,7 +401,6 @@ const char *soundio_device_name(const struct SoundIoDevice *device);
|
|||
const char *soundio_device_description(const struct SoundIoDevice *device);
|
||||
|
||||
const struct SoundIoChannelLayout *soundio_device_channel_layout(const struct SoundIoDevice *device);
|
||||
int soundio_device_sample_rate(const struct SoundIoDevice *device);
|
||||
|
||||
bool soundio_device_equal(
|
||||
const struct SoundIoDevice *a,
|
||||
|
@ -371,7 +412,7 @@ enum SoundIoDevicePurpose soundio_device_purpose(const struct SoundIoDevice *dev
|
|||
// Output Devices
|
||||
|
||||
int soundio_output_device_create(struct SoundIoDevice *device,
|
||||
enum SoundIoSampleFormat sample_format, int sample_rate,
|
||||
enum SoundIoFormat format, int sample_rate,
|
||||
double latency, void *userdata,
|
||||
void (*write_callback)(struct SoundIoOutputDevice *, int frame_count),
|
||||
void (*underrun_callback)(struct SoundIoOutputDevice *),
|
||||
|
@ -397,7 +438,7 @@ void soundio_output_device_clear_buffer(struct SoundIoOutputDevice *output_devic
|
|||
// Input Devices
|
||||
|
||||
int soundio_input_device_create(struct SoundIoDevice *device,
|
||||
enum SoundIoSampleFormat sample_format, int sample_rate,
|
||||
enum SoundIoFormat format, int sample_rate,
|
||||
double latency, void *userdata,
|
||||
void (*read_callback)(struct SoundIoInputDevice *),
|
||||
struct SoundIoInputDevice **out_input_device);
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
static inline void ok_or_panic(int err) {
|
||||
if (err)
|
||||
soundio_panic("%s", soundio_error_string(err));
|
||||
soundio_panic("%s", soundio_strerror(err));
|
||||
}
|
||||
|
||||
static void test_os_get_time(void) {
|
||||
|
@ -37,7 +37,7 @@ static void test_create_output_device(void) {
|
|||
soundio_device_name(device);
|
||||
soundio_device_description(device);
|
||||
struct SoundIoOutputDevice *output_device;
|
||||
soundio_output_device_create(device, SoundIoSampleFormatFloat32NE, 48000, 0.1, NULL,
|
||||
soundio_output_device_create(device, SoundIoFormatFloat32NE, 48000, 0.1, NULL,
|
||||
write_callback, underrun_callback, &output_device);
|
||||
soundio_output_device_destroy(output_device);
|
||||
soundio_device_unref(device);
|
||||
|
|
Loading…
Reference in a new issue