我稍微修改了从ALSA Project website获取的演示,以便在我的笔记本电脑的声卡(Intel PCH ALC3227 Analog,Ubuntu 18.04)上进行测试,该声卡需要2个通道和16位整数。我还将延迟时间加倍(1秒),关闭重新采样并使演示持续时间更长。这是代码(为了合成而不粘贴运行时错误检查)
#include <alsa/asoundlib.h>
#include <stdlib.h>
static char *device = "hw:1,0"; /* playback device */
snd_output_t *output = NULL;
unsigned char buffer[16*1024]; /* some random data */
int main(void) {
int err;
unsigned int i;
snd_pcm_t *handle;
snd_pcm_sframes_t frames;
for (i = 0; i < sizeof(buffer); i++)
buffer[i] = (unsigned char) (rand() & 0xff);
snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK, 0)
snd_pcm_set_params(handle, SND_PCM_FORMAT_S16_LE,
SND_PCM_ACCESS_RW_INTERLEAVED, 2, 48000, 0, 1E6);
// Print actual buffer size
snd_pcm_hw_params_t *hw_params;
snd_pcm_hw_params_malloc(&hw_params);
snd_pcm_hw_params_current(handle, hw_params);
snd_pcm_uframes_t bufferSize;
snd_pcm_hw_params_get_buffer_size(hw_params, &bufferSize);
printf("ALSA buffer size = %li\n", bufferSize);
// playback
for (i = 0; i < 256; ++i) {
frames = snd_pcm_writei(handle, buffer, sizeof(buffer) / 4);
if (frames < 0)
frames = snd_pcm_recover(handle, (int) frames, 0);
if (frames < 0) {
printf("snd_pcm_writei failed: %s\n", snd_strerror((int) frames));
break;
}
if (frames > 0 && frames < (long) sizeof(buffer) / 4)
printf("Short write (expected %li, wrote %li)\n",
(long) sizeof(buffer) / 4, frames);
}
snd_pcm_hw_params_free(hw_params);
snd_pcm_close(handle);
return (0);
}
音频工作,但有人可以解释我为什么有时会得到如下输出
ALSA buffer size = 16384
Short write (expected 4096, wrote 9)
Short write (expected 4096, wrote 4080)
表明snd_pcm_writei
写的帧少于预期?根据ALSA docs,我知道必须发生信号,但我没有得到原因和信号。
我也尝试将buffer
的大小减半,但结果却大致相同。
发生错误时会报告短读取,但某些帧已成功写入。
您应该使用剩余的缓冲区再次调用相同的函数;如果错误不是短暂的,那么它将被报告。 (这个示例代码是错误的;它只是忽略了没有写入缓冲区的剩余部分。)