How to query ALSA channels, period and buffer on Raspberry Pi?

荒凉一梦 提交于 2021-01-28 05:39:26

问题


I'm writing an audio decoding program for ALSA, which among others detects audio capabilities. It uses the snd_pcm_hw_params_get_XXX() functions for that. This works well on my Ubuntu PC but on Raspberry Pi 3 these calls return no information. They return success but the min and max values are meaningless.

For instance the period:

int err;
snd_pcm_t *pcm;
snd_pcm_hw_params_t *hw_params;
const char* device_name = "hw:0,0";

// open audio device
err = snd_pcm_open(&pcm, device_name, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
if (err < 0) {
    LOG(LOG_ERROR, LOG_OBJ "Failed to open audio device '%s': %s\n", device_name, snd_strerror(err));
    return false;
}

// initialize
snd_pcm_hw_params_alloca(&hw_params);
err = snd_pcm_hw_params_any(pcm, hw_params);
if (err < 0) {
    LOG(LOG_ERROR, LOG_OBJ "Failed to get hardware parameters: %s\n", snd_strerror(err));
    goto fail;
}

// query period size
snd_pcm_uframes_t period_min;
snd_pcm_uframes_t period_max;
unsigned period_min_us;
unsigned period_max_us;

err = snd_pcm_hw_params_get_period_size_min(hw_params, &period_min, NULL);
if (err < 0) {
    LOG(LOG_ERROR, LOG_OBJ "Failed to get minimum period time: %s\n", snd_strerror(err));
    goto fail;
}
err = snd_pcm_hw_params_get_period_size_max(hw_params, &period_max, NULL);
if (err < 0) {
    LOG(LOG_ERROR, LOG_OBJ "Failed to get maximum period time: %s\n", snd_strerror(err));
    goto fail;
}
err = snd_pcm_hw_params_get_period_time_min(hw_params, &period_min_us, NULL);
if (err < 0) {
    LOG(LOG_ERROR, LOG_OBJ "Failed to get minimum period time: %s\n", snd_strerror(err));
    goto fail;
}
err = snd_pcm_hw_params_get_period_time_max(hw_params, &period_max_us, NULL);
if (err < 0) {
    LOG(LOG_ERROR, LOG_OBJ "Failed to get maximum period time: %s\n", snd_strerror(err));
    goto fail;
}
LOG(LOG_DEBUG, LOG_OBJ "Supported period: %lu to %lu frames (%u to %u us)\n",
        (unsigned long)period_min, (unsigned long)period_max,
        period_min_us, period_max_us);

This prints:

Supported period: 0 to 0 frames (1 to 0 us)

Or the buffer size:

snd_pcm_uframes_t buffer_min;
snd_pcm_uframes_t buffer_max;
unsigned buffer_min_us;
unsigned buffer_max_us;
err = snd_pcm_hw_params_get_buffer_size_min(hw_params, &buffer_min);
if (err < 0) {
    LOG(LOG_ERROR, LOG_OBJ "Failed get minimum buffer time: %s\n", snd_strerror(err));
    goto fail;
}
err = snd_pcm_hw_params_get_buffer_size_max(hw_params, &buffer_max);
if (err < 0) {
    LOG(LOG_ERROR, LOG_OBJ "Failed get maximum buffer time: %s\n", snd_strerror(err));
    goto fail;
}
err = snd_pcm_hw_params_get_buffer_time_min(hw_params, &buffer_min_us, NULL);
if (err < 0) {
    LOG(LOG_ERROR, LOG_OBJ "Failed get minimum buffer time: %s\n", snd_strerror(err));
    goto fail;
}
err = snd_pcm_hw_params_get_buffer_time_max(hw_params, &buffer_max_us, NULL);
if (err < 0) {
    LOG(LOG_ERROR, LOG_OBJ "Failed get maximum buffer time: %s\n", snd_strerror(err));
    goto fail;
}
LOG(LOG_DEBUG, LOG_OBJ "Supported buffer size: %lu to %lu frames (%u to %u us)\n",
        (unsigned long)buffer_min, (unsigned long)buffer_max,
        buffer_min_us, buffer_max_us);

This prints:

Supported buffer size: 0 to 0 frames (1 to 0 us)

And so on. Same for the number of periods and channels. On the other hand the snd_pcm_hw_params_test_XXX() calls do work and that way I can detect the rates, formats, accesses.

Why do the get functions return no meaningful information? Am I doing something wrong? And more importantly, how can I get the buffering and channel information also on Raspberry Pi?

来源:https://stackoverflow.com/questions/46035886/how-to-query-alsa-channels-period-and-buffer-on-raspberry-pi

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!