Skip to content

Instantly share code, notes, and snippets.

@SpotlightKid
Created April 29, 2019 15:49
Show Gist options
  • Save SpotlightKid/50986b65db32f6e93e86530bd2b90559 to your computer and use it in GitHub Desktop.
Save SpotlightKid/50986b65db32f6e93e86530bd2b90559 to your computer and use it in GitHub Desktop.
Print hardware capabilities of ALSA device
/*
* alsa-query.c - print hardware capabilities of ALSA device
*
* compile with: gcc -o alsa-query alsa-query.c -lasound
*/
#include <stdio.h>
#include <alsa/asoundlib.h>
#define ARRAY_SIZE(a) (sizeof(a) / sizeof *(a))
static const snd_pcm_access_t accesses[] = {
SND_PCM_ACCESS_MMAP_INTERLEAVED,
SND_PCM_ACCESS_MMAP_NONINTERLEAVED,
SND_PCM_ACCESS_MMAP_COMPLEX,
SND_PCM_ACCESS_RW_INTERLEAVED,
SND_PCM_ACCESS_RW_NONINTERLEAVED,
};
static const snd_pcm_format_t formats[] = {
SND_PCM_FORMAT_S8,
SND_PCM_FORMAT_U8,
SND_PCM_FORMAT_S16_LE,
SND_PCM_FORMAT_S16_BE,
SND_PCM_FORMAT_U16_LE,
SND_PCM_FORMAT_U16_BE,
SND_PCM_FORMAT_S24_LE,
SND_PCM_FORMAT_S24_BE,
SND_PCM_FORMAT_U24_LE,
SND_PCM_FORMAT_U24_BE,
SND_PCM_FORMAT_S32_LE,
SND_PCM_FORMAT_S32_BE,
SND_PCM_FORMAT_U32_LE,
SND_PCM_FORMAT_U32_BE,
SND_PCM_FORMAT_FLOAT_LE,
SND_PCM_FORMAT_FLOAT_BE,
SND_PCM_FORMAT_FLOAT64_LE,
SND_PCM_FORMAT_FLOAT64_BE,
SND_PCM_FORMAT_IEC958_SUBFRAME_LE,
SND_PCM_FORMAT_IEC958_SUBFRAME_BE,
SND_PCM_FORMAT_MU_LAW,
SND_PCM_FORMAT_A_LAW,
SND_PCM_FORMAT_IMA_ADPCM,
SND_PCM_FORMAT_MPEG,
SND_PCM_FORMAT_GSM,
SND_PCM_FORMAT_SPECIAL,
SND_PCM_FORMAT_S24_3LE,
SND_PCM_FORMAT_S24_3BE,
SND_PCM_FORMAT_U24_3LE,
SND_PCM_FORMAT_U24_3BE,
SND_PCM_FORMAT_S20_3LE,
SND_PCM_FORMAT_S20_3BE,
SND_PCM_FORMAT_U20_3LE,
SND_PCM_FORMAT_U20_3BE,
SND_PCM_FORMAT_S18_3LE,
SND_PCM_FORMAT_S18_3BE,
SND_PCM_FORMAT_U18_3LE,
SND_PCM_FORMAT_U18_3BE,
};
static const unsigned int rates[] = {
5512,
8000,
11025,
16000,
22050,
32000,
44100,
48000,
64000,
88200,
96000,
176400,
192000,
};
int main(int argc, char *argv[])
{
const char *device_name = "hw";
snd_pcm_t *pcm;
snd_pcm_hw_params_t *hw_params;
unsigned int i;
unsigned int min, max;
int any_rate;
int err;
if (argc > 1)
device_name = argv[1];
err = snd_pcm_open(&pcm, device_name, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
if (err < 0) {
fprintf(stderr, "cannot open device '%s': %s\n", device_name, snd_strerror(err));
return 1;
}
snd_pcm_hw_params_alloca(&hw_params);
err = snd_pcm_hw_params_any(pcm, hw_params);
if (err < 0) {
fprintf(stderr, "cannot get hardware parameters: %s\n", snd_strerror(err));
snd_pcm_close(pcm);
return 1;
}
printf("Device: %s (type: %s)\n", device_name, snd_pcm_type_name(snd_pcm_type(pcm)));
printf("Access types:");
for (i = 0; i < ARRAY_SIZE(accesses); ++i) {
if (!snd_pcm_hw_params_test_access(pcm, hw_params, accesses[i]))
printf(" %s", snd_pcm_access_name(accesses[i]));
}
putchar('\n');
printf("Formats:");
for (i = 0; i < ARRAY_SIZE(formats); ++i) {
if (!snd_pcm_hw_params_test_format(pcm, hw_params, formats[i]))
printf(" %s", snd_pcm_format_name(formats[i]));
}
putchar('\n');
err = snd_pcm_hw_params_get_channels_min(hw_params, &min);
if (err < 0) {
fprintf(stderr, "cannot get minimum channels count: %s\n", snd_strerror(err));
snd_pcm_close(pcm);
return 1;
}
err = snd_pcm_hw_params_get_channels_max(hw_params, &max);
if (err < 0) {
fprintf(stderr, "cannot get maximum channels count: %s\n", snd_strerror(err));
snd_pcm_close(pcm);
return 1;
}
printf("Channels:");
for (i = min; i <= max; ++i) {
if (!snd_pcm_hw_params_test_channels(pcm, hw_params, i))
printf(" %u", i);
}
putchar('\n');
err = snd_pcm_hw_params_get_rate_min(hw_params, &min, NULL);
if (err < 0) {
fprintf(stderr, "cannot get minimum rate: %s\n", snd_strerror(err));
snd_pcm_close(pcm);
return 1;
}
err = snd_pcm_hw_params_get_rate_max(hw_params, &max, NULL);
if (err < 0) {
fprintf(stderr, "cannot get maximum rate: %s\n", snd_strerror(err));
snd_pcm_close(pcm);
return 1;
}
printf("Sample rates:");
if (min == max)
printf(" %u", min);
else if (!snd_pcm_hw_params_test_rate(pcm, hw_params, min + 1, 0))
printf(" %u-%u", min, max);
else {
any_rate = 0;
for (i = 0; i < ARRAY_SIZE(rates); ++i) {
if (!snd_pcm_hw_params_test_rate(pcm, hw_params, rates[i], 0)) {
any_rate = 1;
printf(" %u", rates[i]);
}
}
if (!any_rate)
printf(" %u-%u", min, max);
}
putchar('\n');
err = snd_pcm_hw_params_get_period_time_min(hw_params, &min, NULL);
if (err < 0) {
fprintf(stderr, "cannot get minimum period time: %s\n", snd_strerror(err));
snd_pcm_close(pcm);
return 1;
}
err = snd_pcm_hw_params_get_period_time_max(hw_params, &max, NULL);
if (err < 0) {
fprintf(stderr, "cannot get maximum period time: %s\n", snd_strerror(err));
snd_pcm_close(pcm);
return 1;
}
printf("Interrupt interval: %u-%u us\n", min, max);
err = snd_pcm_hw_params_get_buffer_time_min(hw_params, &min, NULL);
if (err < 0) {
fprintf(stderr, "cannot get minimum buffer time: %s\n", snd_strerror(err));
snd_pcm_close(pcm);
return 1;
}
err = snd_pcm_hw_params_get_buffer_time_max(hw_params, &max, NULL);
if (err < 0) {
fprintf(stderr, "cannot get maximum buffer time: %s\n", snd_strerror(err));
snd_pcm_close(pcm);
return 1;
}
printf("Buffer size: %u-%u us\n", min, max);
snd_pcm_close(pcm);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment