ALSA:不支持非交错访问? [英] ALSA: non-interleaved access not supported?
问题描述
ALSA 的 title="nofollow noreferrer"a> 函数在使用 调用时失败SND_PCM_ACCESS_RW_NONINTERLEAVED 访问类型,报告存在无效参数.相同的代码适用于
ALSA's snd_pcm_hw_params_set_access function fails when called with SND_PCM_ACCESS_RW_NONINTERLEAVED access type, reporting that there was an invalid argument. The same code works fine with SND_PCM_ACCESS_RW_INTERLEAVED access.
我尝试更改对 snd_pcm_hw_params_* 函数的调用顺序,但没有任何效果.
I tried to change the order of calls to snd_pcm_hw_params_* functions with no effect.
接下来我以为我的硬件可能不支持非交错播放,但根据这篇文章 ALSA 子系统将在将非交错数据发送到硬件之前对其进行交错,如果它本身不支持非交错播放.因此,非交错访问应该始终可用.
Next I thought that my hardware might not support non-interleaved playback, but according to this post ALSA subsystem will interleave non-interleaved data before sending it to the hardware if it does not support non-interleaved playback itself. Thus, non-interleaved access should always be available.
那么,为什么非交错访问似乎不受支持?
Why is it then, that non-interleaved access seems not be unsupported?
以下代码适用于交错播放,但对于非交错播放会产生此问题:
Following is the code that works fine for interleaved playback, but produces this problem for non-interleaved playback:
int err;
if ((err = snd_pcm_hw_params_malloc(&hw_params)) < 0) {
fprintf(stderr, "ALSA: allocate hw_params error: %s
", snd_strerror(err));
throw 5;
}
if ((err = snd_pcm_hw_params_any(pb_dev, hw_params)) < 0) {
fprintf(stderr, "ALSA: hw_params_any error: %s
", snd_strerror(err));
throw 5;
}
if ((err = snd_pcm_hw_params_set_access(pb_dev, hw_params, (pAudioCtx->sample_fmt < AV_SAMPLE_FMT_U8P) ? SND_PCM_ACCESS_RW_INTERLEAVED : SND_PCM_ACCESS_RW_NONINTERLEAVED)) < 0) {
fprintf(stderr, "ALSA: set access type error: %s
", snd_strerror(err));
throw 5;
}
if ((err = snd_pcm_hw_params_set_channels(pb_dev, hw_params, pAudioCtx->channels)) < 0) {
fprintf(stderr, "ALSA: set channel count error: %s
", snd_strerror(err));
throw 5;
}
snd_pcm_format_t sample_format;
switch (pAudioCtx->sample_fmt) {
case AV_SAMPLE_FMT_U8: case AV_SAMPLE_FMT_U8P: sample_format = SND_PCM_FORMAT_U8; break;
case AV_SAMPLE_FMT_S16: case AV_SAMPLE_FMT_S16P: sample_format = SND_PCM_FORMAT_S16; break;
case AV_SAMPLE_FMT_S32: case AV_SAMPLE_FMT_S32P: sample_format = SND_PCM_FORMAT_S32; break;
case AV_SAMPLE_FMT_FLT: case AV_SAMPLE_FMT_FLTP: sample_format = SND_PCM_FORMAT_FLOAT; break;
case AV_SAMPLE_FMT_DBL: case AV_SAMPLE_FMT_DBLP: sample_format = SND_PCM_FORMAT_FLOAT64; break;
default: fprintf(stderr, "sampleformat %d is not supported
", pAudioCtx->sample_fmt);
throw 5;
}
if ((err = snd_pcm_hw_params_set_format(pb_dev, hw_params, sample_format)) < 0) {
fprintf(stderr, "ALSA: set sample format error: %s
", snd_strerror(err));
throw 5;
}
if ((err = snd_pcm_hw_params_set_rate_near(pb_dev, hw_params, (unsigned int*)&pAudioCtx->sample_rate, 0)) < 0) {
fprintf(stderr, "ALSA: set sample rate error: %s
", snd_strerror(err));
throw 5;
}
if ((err = snd_pcm_hw_params(pb_dev, hw_params)) < 0) {
fprintf(stderr, "ALSA: set parameters error: %s
", snd_strerror(err));
throw 5;
}
执行此操作会产生以下输出:
Executing this yields following output:
ALSA: set access type error: Invalid argument
推荐答案
hw_params_set_*
函数只接受设备支持的那些值.
The hw_params_set_*
functions accept only those values that are supported by the device.
大多数默认设备(plughw
、default
等)都支持自动转换,因此接受所有格式.hw
设备没有.
Most of the default devices (plughw
, default
, etc.) support automatic conversions, and thus accept all formats.
hw
devices do not.
这篇关于ALSA:不支持非交错访问?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!