ALSA backend determines channel layout of devices

This commit is contained in:
Andrew Kelley 2015-07-09 23:35:58 -07:00
parent c760bc4df7
commit fe2040da7c
8 changed files with 319 additions and 115 deletions

View file

@ -137,6 +137,7 @@ view `coverage/index.html` in a browser.
- pulseaudio has peek() drop() which sucks, but what if libsoundio lets you
specify how much to peek() and if you don't peek all of it, save the
unused to a buffer for you.
0. add len arguments to APIs that have char *
## Planned Uses for libsoundio

View file

@ -15,6 +15,8 @@
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;
@ -81,6 +83,169 @@ static char * str_partition_on_char(char *str, char c) {
return nullptr;
}
static snd_pcm_stream_t purpose_to_stream(SoundIoDevicePurpose purpose) {
switch (purpose) {
case SoundIoDevicePurposeOutput: return SND_PCM_STREAM_PLAYBACK;
case SoundIoDevicePurposeInput: return SND_PCM_STREAM_CAPTURE;
}
soundio_panic("invalid purpose");
}
static SoundIoChannelId from_alsa_chmap_pos(unsigned int pos) {
switch ((snd_pcm_chmap_position)pos) {
case SND_CHMAP_UNKNOWN: return SoundIoChannelIdInvalid;
case SND_CHMAP_NA: return SoundIoChannelIdInvalid;
case SND_CHMAP_MONO: return SoundIoChannelIdFrontCenter;
case SND_CHMAP_FL: return SoundIoChannelIdFrontLeft; // front left
case SND_CHMAP_FR: return SoundIoChannelIdFrontRight; // front right
case SND_CHMAP_RL: return SoundIoChannelIdBackLeft; // rear left
case SND_CHMAP_RR: return SoundIoChannelIdBackRight; // rear right
case SND_CHMAP_FC: return SoundIoChannelIdFrontCenter; // front center
case SND_CHMAP_LFE: return SoundIoChannelIdLfe; // LFE
case SND_CHMAP_SL: return SoundIoChannelIdSideLeft; // side left
case SND_CHMAP_SR: return SoundIoChannelIdSideRight; // side right
case SND_CHMAP_RC: return SoundIoChannelIdBackCenter; // rear center
case SND_CHMAP_FLC: return SoundIoChannelIdFrontLeftCenter; // front left center
case SND_CHMAP_FRC: return SoundIoChannelIdFrontRightCenter; // front right center
case SND_CHMAP_RLC: return SoundIoChannelIdBackLeftCenter; // rear left center
case SND_CHMAP_RRC: return SoundIoChannelIdBackRightCenter; // rear right center
case SND_CHMAP_FLW: return SoundIoChannelIdFrontLeftWide; // front left wide
case SND_CHMAP_FRW: return SoundIoChannelIdFrontRightWide; // front right wide
case SND_CHMAP_FLH: return SoundIoChannelIdFrontLeftHigh; // front left high
case SND_CHMAP_FCH: return SoundIoChannelIdFrontCenterHigh; // front center high
case SND_CHMAP_FRH: return SoundIoChannelIdFrontRightHigh; // front right high
case SND_CHMAP_TC: return SoundIoChannelIdTopCenter; // top center
case SND_CHMAP_TFL: return SoundIoChannelIdTopFrontLeft; // top front left
case SND_CHMAP_TFR: return SoundIoChannelIdTopFrontRight; // top front right
case SND_CHMAP_TFC: return SoundIoChannelIdTopFrontCenter; // top front center
case SND_CHMAP_TRL: return SoundIoChannelIdTopBackLeft; // top rear left
case SND_CHMAP_TRR: return SoundIoChannelIdTopBackRight; // top rear right
case SND_CHMAP_TRC: return SoundIoChannelIdTopBackCenter; // top rear center
case SND_CHMAP_TFLC: return SoundIoChannelIdTopFrontLeftCenter; // top front left center
case SND_CHMAP_TFRC: return SoundIoChannelIdTopFrontRightCenter; // top front right center
case SND_CHMAP_TSL: return SoundIoChannelIdTopSideLeft; // top side left
case SND_CHMAP_TSR: return SoundIoChannelIdTopSideRight; // top side right
case SND_CHMAP_LLFE: return SoundIoChannelIdLeftLfe; // left LFE
case SND_CHMAP_RLFE: return SoundIoChannelIdRightLfe; // right LFE
case SND_CHMAP_BC: return SoundIoChannelIdBottomCenter; // bottom center
case SND_CHMAP_BLC: return SoundIoChannelIdBottomLeftCenter; // bottom left center
case SND_CHMAP_BRC: return SoundIoChannelIdBottomRightCenter; // bottom right center
}
return SoundIoChannelIdInvalid;
}
static void get_channel_layout(SoundIoDevice *device, snd_pcm_chmap_t *chmap) {
int channel_count = min((unsigned int)SOUNDIO_MAX_CHANNELS, chmap->channels);
device->channel_layout.channel_count = channel_count;
device->channel_layout.name = nullptr;
for (int i = 0; i < channel_count; i += 1) {
device->channel_layout.channels[i] = from_alsa_chmap_pos(chmap->pos[i]);
}
soundio_channel_layout_detect_builtin(&device->channel_layout);
}
static void handle_channel_maps(SoundIoDevice *device, snd_pcm_chmap_query_t **maps) {
if (!maps)
return;
snd_pcm_chmap_query_t **p;
snd_pcm_chmap_query_t *v;
snd_pcm_chmap_t *best = nullptr;
for (p = maps; (v = *p); p += 1) {
if (!best || v->map.channels > best->channels)
best = &v->map;
}
get_channel_layout(device, best);
snd_pcm_free_chmaps(maps);
}
static int probe_device(SoundIoDevice *device, snd_pcm_chmap_query_t **maps) {
int err;
snd_pcm_t *handle;
snd_pcm_hw_params_t *hwparams;
snd_pcm_sw_params_t *swparams;
snd_pcm_hw_params_alloca(&hwparams);
snd_pcm_sw_params_alloca(&swparams);
snd_pcm_stream_t stream = purpose_to_stream(device->purpose);
if ((err = snd_pcm_open(&handle, device->name, stream, 0)) < 0) {
handle_channel_maps(device, maps);
return SoundIoErrorOpeningDevice;
}
if ((err = snd_pcm_hw_params_any(handle, hwparams)) < 0) {
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) {
snd_pcm_close(handle);
return SoundIoErrorOpeningDevice;
}
if ((err = snd_pcm_hw_params_set_access(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
snd_pcm_close(handle);
return SoundIoErrorOpeningDevice;
}
unsigned int channel_count;
if ((err = snd_pcm_hw_params_set_channels_last(handle, hwparams, &channel_count)) < 0) {
snd_pcm_close(handle);
return SoundIoErrorOpeningDevice;
}
unsigned int min_sample_rate;
unsigned int max_sample_rate;
int min_dir;
int max_dir;
if ((err = snd_pcm_hw_params_get_rate_max(hwparams, &max_sample_rate, &max_dir)) < 0) {
snd_pcm_close(handle);
return SoundIoErrorOpeningDevice;
}
if (max_dir < 0)
max_sample_rate -= 1;
if ((err = snd_pcm_hw_params_get_rate_min(hwparams, &min_sample_rate, &min_dir)) < 0) {
snd_pcm_close(handle);
return SoundIoErrorOpeningDevice;
}
if (min_dir > 0)
min_sample_rate += 1;
snd_pcm_chmap_t *chmap = snd_pcm_get_chmap(handle);
if (chmap) {
get_channel_layout(device, chmap);
free(chmap);
} else if (!maps) {
maps = snd_pcm_query_chmaps(handle);
}
handle_channel_maps(device, 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;
snd_pcm_close(handle);
return 0;
// TODO: device->default_sample_format
// TODO: device->default_latency
}
static inline bool str_has_prefix(const char *big_str, const char *prefix) {
return strncmp(big_str, prefix, strlen(prefix)) == 0;
}
static int refresh_devices(SoundIo *soundio) {
SoundIoAlsa *sia = (SoundIoAlsa *)soundio->backend_data;
@ -173,12 +338,6 @@ static int refresh_devices(SoundIo *soundio) {
return SoundIoErrorNoMem;
}
// TODO: device->channel_layout
// TODO: device->default_sample_format
// TODO: device->default_latency
// TODO: device->default_sample_rate
SoundIoList<SoundIoDevice *> *device_list;
if (stream == SND_PCM_STREAM_PLAYBACK) {
device->purpose = SoundIoDevicePurposeOutput;
@ -193,6 +352,8 @@ static int refresh_devices(SoundIo *soundio) {
devices_info->default_input_index = device_list->length;
}
probe_device(device, nullptr);
if (device_list->append(device)) {
soundio_device_unref(device);
free(name);
@ -289,11 +450,6 @@ static int refresh_devices(SoundIo *soundio) {
return SoundIoErrorNoMem;
}
// TODO: device->channel_layout
// TODO: device->default_sample_format
// TODO: device->default_latency
// TODO: device->default_sample_rate
SoundIoList<SoundIoDevice *> *device_list;
if (stream == SND_PCM_STREAM_PLAYBACK) {
device->purpose = SoundIoDevicePurposeOutput;
@ -304,6 +460,9 @@ static int refresh_devices(SoundIo *soundio) {
device_list = &devices_info->input_devices;
}
snd_pcm_chmap_query_t **maps = snd_pcm_query_chmaps_from_hw(card_index, device_index, -1, stream);
probe_device(device, maps);
if (device_list->append(device)) {
soundio_device_unref(device);
destroy(devices_info);

View file

@ -31,7 +31,7 @@ static struct SoundIoChannelLayout builtin_channel_layouts[] = {
{
SoundIoChannelIdFrontLeft,
SoundIoChannelIdFrontRight,
SoundIoChannelIdLowFrequency,
SoundIoChannelIdLfe,
},
},
{
@ -59,7 +59,7 @@ static struct SoundIoChannelLayout builtin_channel_layouts[] = {
SoundIoChannelIdFrontLeft,
SoundIoChannelIdFrontRight,
SoundIoChannelIdFrontCenter,
SoundIoChannelIdLowFrequency,
SoundIoChannelIdLfe,
}
},
{
@ -79,7 +79,7 @@ static struct SoundIoChannelLayout builtin_channel_layouts[] = {
SoundIoChannelIdFrontLeft,
SoundIoChannelIdFrontRight,
SoundIoChannelIdFrontCenter,
SoundIoChannelIdLowFrequency,
SoundIoChannelIdLfe,
}
},
{
@ -133,7 +133,7 @@ static struct SoundIoChannelLayout builtin_channel_layouts[] = {
SoundIoChannelIdFrontCenter,
SoundIoChannelIdSideLeft,
SoundIoChannelIdSideRight,
SoundIoChannelIdLowFrequency,
SoundIoChannelIdLfe,
}
},
{
@ -145,7 +145,7 @@ static struct SoundIoChannelLayout builtin_channel_layouts[] = {
SoundIoChannelIdFrontCenter,
SoundIoChannelIdBackLeft,
SoundIoChannelIdBackRight,
SoundIoChannelIdLowFrequency,
SoundIoChannelIdLfe,
}
},
{
@ -168,8 +168,8 @@ static struct SoundIoChannelLayout builtin_channel_layouts[] = {
SoundIoChannelIdFrontRight,
SoundIoChannelIdSideLeft,
SoundIoChannelIdSideRight,
SoundIoChannelIdFrontLeftOfCenter,
SoundIoChannelIdFrontRightOfCenter,
SoundIoChannelIdFrontLeftCenter,
SoundIoChannelIdFrontRightCenter,
}
},
{
@ -194,7 +194,7 @@ static struct SoundIoChannelLayout builtin_channel_layouts[] = {
SoundIoChannelIdSideLeft,
SoundIoChannelIdSideRight,
SoundIoChannelIdBackCenter,
SoundIoChannelIdLowFrequency,
SoundIoChannelIdLfe,
}
},
{
@ -207,7 +207,7 @@ static struct SoundIoChannelLayout builtin_channel_layouts[] = {
SoundIoChannelIdBackLeft,
SoundIoChannelIdBackRight,
SoundIoChannelIdBackCenter,
SoundIoChannelIdLowFrequency,
SoundIoChannelIdLfe,
}
},
{
@ -218,9 +218,9 @@ static struct SoundIoChannelLayout builtin_channel_layouts[] = {
SoundIoChannelIdFrontRight,
SoundIoChannelIdSideLeft,
SoundIoChannelIdSideRight,
SoundIoChannelIdFrontLeftOfCenter,
SoundIoChannelIdFrontRightOfCenter,
SoundIoChannelIdLowFrequency,
SoundIoChannelIdFrontLeftCenter,
SoundIoChannelIdFrontRightCenter,
SoundIoChannelIdLfe,
}
},
{
@ -245,8 +245,8 @@ static struct SoundIoChannelLayout builtin_channel_layouts[] = {
SoundIoChannelIdFrontCenter,
SoundIoChannelIdSideLeft,
SoundIoChannelIdSideRight,
SoundIoChannelIdFrontLeftOfCenter,
SoundIoChannelIdFrontRightOfCenter,
SoundIoChannelIdFrontLeftCenter,
SoundIoChannelIdFrontRightCenter,
}
},
{
@ -260,7 +260,7 @@ static struct SoundIoChannelLayout builtin_channel_layouts[] = {
SoundIoChannelIdSideRight,
SoundIoChannelIdBackLeft,
SoundIoChannelIdBackRight,
SoundIoChannelIdLowFrequency,
SoundIoChannelIdLfe,
}
},
{
@ -272,9 +272,9 @@ static struct SoundIoChannelLayout builtin_channel_layouts[] = {
SoundIoChannelIdFrontCenter,
SoundIoChannelIdSideLeft,
SoundIoChannelIdSideRight,
SoundIoChannelIdFrontLeftOfCenter,
SoundIoChannelIdFrontRightOfCenter,
SoundIoChannelIdLowFrequency,
SoundIoChannelIdFrontLeftCenter,
SoundIoChannelIdFrontRightCenter,
SoundIoChannelIdLfe,
}
},
{
@ -286,9 +286,9 @@ static struct SoundIoChannelLayout builtin_channel_layouts[] = {
SoundIoChannelIdFrontCenter,
SoundIoChannelIdBackLeft,
SoundIoChannelIdBackRight,
SoundIoChannelIdFrontLeftOfCenter,
SoundIoChannelIdFrontRightOfCenter,
SoundIoChannelIdLowFrequency,
SoundIoChannelIdFrontLeftCenter,
SoundIoChannelIdFrontRightCenter,
SoundIoChannelIdLfe,
}
},
{
@ -307,6 +307,49 @@ static struct SoundIoChannelLayout builtin_channel_layouts[] = {
},
};
const char *soundio_get_channel_name(enum SoundIoChannelId id) {
switch (id) {
case SoundIoChannelIdInvalid: return "(Invalid Channel)";
case SoundIoChannelIdCount: return "(Invalid Channel)";
case SoundIoChannelIdFrontLeft: return "Front Left";
case SoundIoChannelIdFrontRight: return "Front Right";
case SoundIoChannelIdFrontCenter: return "Front Center";
case SoundIoChannelIdLfe: return "LFE";
case SoundIoChannelIdBackLeft: return "Back Left";
case SoundIoChannelIdBackRight: return "Back Right";
case SoundIoChannelIdFrontLeftCenter: return "Front Left Center";
case SoundIoChannelIdFrontRightCenter: return "Front Right Center";
case SoundIoChannelIdBackCenter: return "Back Center";
case SoundIoChannelIdSideLeft: return "Side Left";
case SoundIoChannelIdSideRight: return "Side Right";
case SoundIoChannelIdTopCenter: return "Top Center";
case SoundIoChannelIdTopFrontLeft: return "Top Front Left";
case SoundIoChannelIdTopFrontCenter: return "Top Front Center";
case SoundIoChannelIdTopFrontRight: return "Top Front Right";
case SoundIoChannelIdTopBackLeft: return "Top Back Left";
case SoundIoChannelIdTopBackCenter: return "Top Back Center";
case SoundIoChannelIdTopBackRight: return "Top Back Right";
case SoundIoChannelIdBackLeftCenter: return "Back Left Center";
case SoundIoChannelIdBackRightCenter: return "Back Right Center";
case SoundIoChannelIdFrontLeftWide: return "Front Left Wide";
case SoundIoChannelIdFrontRightWide: return "Front Right Wide";
case SoundIoChannelIdFrontLeftHigh: return "Front Left High";
case SoundIoChannelIdFrontCenterHigh: return "Front Center High";
case SoundIoChannelIdFrontRightHigh: return "Front Right High";
case SoundIoChannelIdTopFrontLeftCenter: return "Top Front Left Center";
case SoundIoChannelIdTopFrontRightCenter: return "Top Front Right Center";
case SoundIoChannelIdTopSideLeft: return "Top Side Left";
case SoundIoChannelIdTopSideRight: return "Top Side Right";
case SoundIoChannelIdLeftLfe: return "Left LFE";
case SoundIoChannelIdRightLfe: return "Right LFE";
case SoundIoChannelIdBottomCenter: return "Bottom Center";
case SoundIoChannelIdBottomLeftCenter: return "Bottom Left Center";
case SoundIoChannelIdBottomRightCenter: return "Bottom Right Center";
}
return "(Invalid Channel)";
}
bool soundio_channel_layout_equal(
const struct SoundIoChannelLayout *a,
const struct SoundIoChannelLayout *b)
@ -322,33 +365,6 @@ bool soundio_channel_layout_equal(
return true;
}
const char *soundio_get_channel_name(enum SoundIoChannelId id) {
switch (id) {
case SoundIoChannelIdInvalid: return "(Invalid Channel)";
case SoundIoChannelIdCount: return "(Invalid Channel)";
case SoundIoChannelIdFrontLeft: return "Front Left";
case SoundIoChannelIdFrontRight: return "Front Right";
case SoundIoChannelIdFrontCenter: return "Front Center";
case SoundIoChannelIdLowFrequency: return "Low Frequency";
case SoundIoChannelIdBackLeft: return "Back Left";
case SoundIoChannelIdBackRight: return "Back Right";
case SoundIoChannelIdFrontLeftOfCenter: return "Front Left of Center";
case SoundIoChannelIdFrontRightOfCenter: return "Front Right of Center";
case SoundIoChannelIdBackCenter: return "Back Center";
case SoundIoChannelIdSideLeft: return "Side Left";
case SoundIoChannelIdSideRight: return "Side Right";
case SoundIoChannelIdTopCenter: return "Top Center";
case SoundIoChannelIdTopFrontLeft: return "Top Front Left";
case SoundIoChannelIdTopFrontCenter: return "Top Front Center";
case SoundIoChannelIdTopFrontRight: return "Top Front Right";
case SoundIoChannelIdTopBackLeft: return "Top Back Left";
case SoundIoChannelIdTopBackCenter: return "Top Back Center";
case SoundIoChannelIdTopBackRight: return "Top Back Right";
}
return "(Invalid Channel)";
}
int soundio_channel_layout_builtin_count(void) {
return array_length(builtin_channel_layouts);
}
@ -381,3 +397,13 @@ int soundio_channel_layout_find_channel(
return -1;
}
bool soundio_channel_layout_detect_builtin(struct SoundIoChannelLayout *layout) {
for (int i = 0; i < array_length(builtin_channel_layouts); i += 1) {
const struct SoundIoChannelLayout *builtin_layout = &builtin_channel_layouts[i];
if (soundio_channel_layout_equal(builtin_layout, layout)) {
layout->name = builtin_layout->name;
return true;
}
}
return false;
}

View file

@ -297,7 +297,7 @@ int soundio_dummy_init(SoundIo *soundio) {
device->channel_layout = *soundio_channel_layout_get_builtin(SoundIoChannelLayoutIdMono);
device->default_sample_format = SoundIoSampleFormatFloat;
device->default_latency = 0.01;
device->default_sample_rate = 48000;
device->sample_rate_default = 48000;
device->purpose = SoundIoDevicePurposeOutput;
if (soundio->safe_devices_info->output_devices.append(device)) {
@ -327,7 +327,7 @@ int soundio_dummy_init(SoundIo *soundio) {
device->channel_layout = *soundio_channel_layout_get_builtin(SoundIoChannelLayoutIdMono);
device->default_sample_format = SoundIoSampleFormatFloat;
device->default_latency = 0.01;
device->default_sample_rate = 48000;
device->sample_rate_default = 48000;
device->purpose = SoundIoDevicePurposeInput;
if (soundio->safe_devices_info->input_devices.append(device)) {

View file

@ -161,9 +161,9 @@ static SoundIoChannelId from_pulseaudio_channel_pos(pa_channel_position_t pos) {
case PA_CHANNEL_POSITION_REAR_CENTER: return SoundIoChannelIdBackCenter;
case PA_CHANNEL_POSITION_REAR_LEFT: return SoundIoChannelIdBackLeft;
case PA_CHANNEL_POSITION_REAR_RIGHT: return SoundIoChannelIdBackRight;
case PA_CHANNEL_POSITION_LFE: return SoundIoChannelIdLowFrequency;
case PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER: return SoundIoChannelIdFrontLeftOfCenter;
case PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER: return SoundIoChannelIdFrontRightOfCenter;
case PA_CHANNEL_POSITION_LFE: return SoundIoChannelIdLfe;
case PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER: return SoundIoChannelIdFrontLeftCenter;
case PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER: return SoundIoChannelIdFrontRightCenter;
case PA_CHANNEL_POSITION_SIDE_LEFT: return SoundIoChannelIdSideLeft;
case PA_CHANNEL_POSITION_SIDE_RIGHT: return SoundIoChannelIdSideRight;
case PA_CHANNEL_POSITION_TOP_CENTER: return SoundIoChannelIdTopCenter;
@ -268,7 +268,7 @@ static void sink_info_callback(pa_context *pulse_context, const pa_sink_info *in
set_from_pulseaudio_channel_map(info->channel_map, &device->channel_layout);
device->default_sample_format = sample_format_from_pulseaudio(info->sample_spec);
device->default_latency = usec_to_sec(info->configured_latency);
device->default_sample_rate = sample_rate_from_pulseaudio(info->sample_spec);
device->sample_rate_default = sample_rate_from_pulseaudio(info->sample_spec);
device->purpose = SoundIoDevicePurposeOutput;
if (sipa->current_devices_info->output_devices.append(device))
@ -297,7 +297,7 @@ static void source_info_callback(pa_context *pulse_context, const pa_source_info
set_from_pulseaudio_channel_map(info->channel_map, &device->channel_layout);
device->default_sample_format = sample_format_from_pulseaudio(info->sample_spec);
device->default_latency = usec_to_sec(info->configured_latency);
device->default_sample_rate = sample_rate_from_pulseaudio(info->sample_spec);
device->sample_rate_default = sample_rate_from_pulseaudio(info->sample_spec);
device->purpose = SoundIoDevicePurposeInput;
if (sipa->current_devices_info->input_devices.append(device))
@ -445,47 +445,46 @@ static pa_sample_format_t to_pulseaudio_sample_format(SoundIoSampleFormat sample
static pa_channel_position_t to_pulseaudio_channel_pos(SoundIoChannelId channel_id) {
switch (channel_id) {
case SoundIoChannelIdInvalid:
case SoundIoChannelIdFrontLeft: return PA_CHANNEL_POSITION_FRONT_LEFT;
case SoundIoChannelIdFrontRight: return PA_CHANNEL_POSITION_FRONT_RIGHT;
case SoundIoChannelIdFrontCenter: return PA_CHANNEL_POSITION_FRONT_CENTER;
case SoundIoChannelIdLfe: return PA_CHANNEL_POSITION_LFE;
case SoundIoChannelIdBackLeft: return PA_CHANNEL_POSITION_REAR_LEFT;
case SoundIoChannelIdBackRight: return PA_CHANNEL_POSITION_REAR_RIGHT;
case SoundIoChannelIdFrontLeftCenter: return PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER;
case SoundIoChannelIdFrontRightCenter: return PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER;
case SoundIoChannelIdBackCenter: return PA_CHANNEL_POSITION_REAR_CENTER;
case SoundIoChannelIdSideLeft: return PA_CHANNEL_POSITION_SIDE_LEFT;
case SoundIoChannelIdSideRight: return PA_CHANNEL_POSITION_SIDE_RIGHT;
case SoundIoChannelIdTopCenter: return PA_CHANNEL_POSITION_TOP_CENTER;
case SoundIoChannelIdTopFrontLeft: return PA_CHANNEL_POSITION_TOP_FRONT_LEFT;
case SoundIoChannelIdTopFrontCenter: return PA_CHANNEL_POSITION_TOP_FRONT_CENTER;
case SoundIoChannelIdTopFrontRight: return PA_CHANNEL_POSITION_TOP_FRONT_RIGHT;
case SoundIoChannelIdTopBackLeft: return PA_CHANNEL_POSITION_TOP_REAR_LEFT;
case SoundIoChannelIdTopBackCenter: return PA_CHANNEL_POSITION_TOP_REAR_CENTER;
case SoundIoChannelIdTopBackRight: return PA_CHANNEL_POSITION_TOP_REAR_RIGHT;
case SoundIoChannelIdCount:
soundio_panic("invalid channel id");
case SoundIoChannelIdFrontLeft:
return PA_CHANNEL_POSITION_FRONT_LEFT;
case SoundIoChannelIdFrontRight:
return PA_CHANNEL_POSITION_FRONT_RIGHT;
case SoundIoChannelIdFrontCenter:
return PA_CHANNEL_POSITION_FRONT_CENTER;
case SoundIoChannelIdLowFrequency:
return PA_CHANNEL_POSITION_LFE;
case SoundIoChannelIdBackLeft:
return PA_CHANNEL_POSITION_REAR_LEFT;
case SoundIoChannelIdBackRight:
return PA_CHANNEL_POSITION_REAR_RIGHT;
case SoundIoChannelIdFrontLeftOfCenter:
return PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER;
case SoundIoChannelIdFrontRightOfCenter:
return PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER;
case SoundIoChannelIdBackCenter:
return PA_CHANNEL_POSITION_REAR_CENTER;
case SoundIoChannelIdSideLeft:
return PA_CHANNEL_POSITION_SIDE_LEFT;
case SoundIoChannelIdSideRight:
return PA_CHANNEL_POSITION_SIDE_RIGHT;
case SoundIoChannelIdTopCenter:
return PA_CHANNEL_POSITION_TOP_CENTER;
case SoundIoChannelIdTopFrontLeft:
return PA_CHANNEL_POSITION_TOP_FRONT_LEFT;
case SoundIoChannelIdTopFrontCenter:
return PA_CHANNEL_POSITION_TOP_FRONT_CENTER;
case SoundIoChannelIdTopFrontRight:
return PA_CHANNEL_POSITION_TOP_FRONT_RIGHT;
case SoundIoChannelIdTopBackLeft:
return PA_CHANNEL_POSITION_TOP_REAR_LEFT;
case SoundIoChannelIdTopBackCenter:
return PA_CHANNEL_POSITION_TOP_REAR_CENTER;
case SoundIoChannelIdTopBackRight:
return PA_CHANNEL_POSITION_TOP_REAR_RIGHT;
case SoundIoChannelIdInvalid:
case SoundIoChannelIdBackLeftCenter:
case SoundIoChannelIdBackRightCenter:
case SoundIoChannelIdFrontLeftWide:
case SoundIoChannelIdFrontRightWide:
case SoundIoChannelIdFrontLeftHigh:
case SoundIoChannelIdFrontCenterHigh:
case SoundIoChannelIdFrontRightHigh:
case SoundIoChannelIdTopFrontLeftCenter:
case SoundIoChannelIdTopFrontRightCenter:
case SoundIoChannelIdTopSideLeft:
case SoundIoChannelIdTopSideRight:
case SoundIoChannelIdLeftLfe:
case SoundIoChannelIdRightLfe:
case SoundIoChannelIdBottomCenter:
case SoundIoChannelIdBottomLeftCenter:
case SoundIoChannelIdBottomRightCenter:
return PA_CHANNEL_POSITION_INVALID;
}
soundio_panic("invalid channel id");
return PA_CHANNEL_POSITION_INVALID;
}
static pa_channel_map to_pulseaudio_channel_map(const SoundIoChannelLayout *channel_layout) {

View file

@ -228,7 +228,7 @@ const struct SoundIoChannelLayout *soundio_device_channel_layout(const struct So
}
int soundio_device_sample_rate(const struct SoundIoDevice *device) {
return device->default_sample_rate;
return device->sample_rate_default;
}
void soundio_device_unref(struct SoundIoDevice *device) {

View file

@ -32,11 +32,11 @@ enum SoundIoChannelId {
SoundIoChannelIdFrontLeft,
SoundIoChannelIdFrontRight,
SoundIoChannelIdFrontCenter,
SoundIoChannelIdLowFrequency,
SoundIoChannelIdLfe,
SoundIoChannelIdBackLeft,
SoundIoChannelIdBackRight,
SoundIoChannelIdFrontLeftOfCenter,
SoundIoChannelIdFrontRightOfCenter,
SoundIoChannelIdFrontLeftCenter,
SoundIoChannelIdFrontRightCenter,
SoundIoChannelIdBackCenter,
SoundIoChannelIdSideLeft,
SoundIoChannelIdSideRight,
@ -48,6 +48,23 @@ enum SoundIoChannelId {
SoundIoChannelIdTopBackCenter,
SoundIoChannelIdTopBackRight,
SoundIoChannelIdBackLeftCenter,
SoundIoChannelIdBackRightCenter,
SoundIoChannelIdFrontLeftWide,
SoundIoChannelIdFrontRightWide,
SoundIoChannelIdFrontLeftHigh,
SoundIoChannelIdFrontCenterHigh,
SoundIoChannelIdFrontRightHigh,
SoundIoChannelIdTopFrontLeftCenter,
SoundIoChannelIdTopFrontRightCenter,
SoundIoChannelIdTopSideLeft,
SoundIoChannelIdTopSideRight,
SoundIoChannelIdLeftLfe,
SoundIoChannelIdRightLfe,
SoundIoChannelIdBottomCenter,
SoundIoChannelIdBottomLeftCenter,
SoundIoChannelIdBottomRightCenter,
SoundIoChannelIdCount,
};
@ -121,7 +138,10 @@ struct SoundIoDevice {
// whether something worked until you try it.
// these values can be unknown
enum SoundIoSampleFormat default_sample_format;
int default_sample_rate;
int sample_rate_min;
int sample_rate_max;
int sample_rate_default;
double default_latency;
enum SoundIoDevicePurpose purpose;
@ -232,6 +252,10 @@ void soundio_debug_print_channel_layout(const struct SoundIoChannelLayout *layou
int soundio_channel_layout_find_channel(
const struct SoundIoChannelLayout *layout, enum SoundIoChannelId channel);
// merely populates the name field of layout if it matches a builtin one.
// returns whether it found a match
bool soundio_channel_layout_detect_builtin(struct SoundIoChannelLayout *layout);
// Sample Formats

View file

@ -103,9 +103,4 @@ template <typename T>
static inline T min(T a, T b) {
return (a <= b) ? a : b;
}
static inline bool str_has_prefix(const char *big_str, const char *prefix) {
return strncmp(big_str, prefix, strlen(prefix)) == 0;
}
#endif