Created
April 29, 2019 15:49
-
-
Save SpotlightKid/50986b65db32f6e93e86530bd2b90559 to your computer and use it in GitHub Desktop.
Print hardware capabilities of ALSA device
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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