linux - ALSA:snd_pcm_writei 调用时缓冲区不足

标签 linux alsa

在运行我最近从 Ember 中恢复的旧程序时,我遇到了缓冲区不足的情况。

程序将原始声音文件完全加载到内存中(2100 字节长,525 帧)并准备 ALSA 进行输出(44.1khz,2 channel ,带符号 16 位):

if ((err = snd_pcm_set_params(audio_handle,
                              SND_PCM_FORMAT_S16_LE,
                              SND_PCM_ACCESS_RW_INTERLEAVED,
                              2,
                              44100,
                              1,
                              sound.playback_us)) < 0) {
  printf("E: Failed to prepare PCM: %s\n", snd_strerror(err));
  return -1;
}

首次播放声音之前,PCM 状态为PREPARED。声音第一次播放正确,但是,第二次播放时,状态为 RUNNING 并且 抛出 -EPIPE(“管道损坏”) snd_pcm_writei。播放逻辑:

frames = snd_pcm_writei(audio_handle,
                        sound.data,
                        write_size);

if(frames < 0) {
  printf("E: %s: attempting to recover\n", snd_strerror(frames));
  frames = snd_pcm_recover(audio_handle, frames, 0);

  if(frames < 0) {
    printf("E: snd_pcm_writei failed\n");
    break;
  }
} else if(frames > 0 && frames < write_size)
  printf("E: Short write (expected %li, wrote %li)\n", write_size, frames);
else
  printf("wrote %li frames\n", frames);

奇怪的是,第三次播放正确,下一次又播放失败。换句话说,它每隔一段时间就会失败并出现 -EPIPE 错误。

为了简单起见,我以 1 秒的间隔播放声音。

上面的逻辑有什么问题吗?

<小时/>

更新了代码以使用新的 ALSA API;可以在以下位置找到:http://paste.ubuntu.com/7257181/

<小时/>

编辑

刚刚发现,如果在重新发出 snd_pcm_writei 调用之前实际测试 -EPIPE 条件并重新准备 PCM 句柄,则一切都很好。那么我的(新)问题是......为什么?

if(frames == -EPIPE) {
  snd_pcm_prepare(pcm.handle);
  frames = snd_pcm_writei(pcm.handle,
                          sound.data, //sound.data + (offset << 1),
                          write_size);
}

最佳答案

如果用 525 帧(约 12 毫秒)填充缓冲区,然后等待一秒钟,则肯定会出现欠载,因为剩余的 988 毫秒没有数据。

您可以使用snd_pcm_drain等待实际数据停止播放(注意:通常,设备直到下一个周期边界才会真正停止)。 或者,继续将零个样本送入缓冲区。

关于linux - ALSA:snd_pcm_writei 调用时缓冲区不足,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23092895/

相关文章:

linux - 嵌入式 Linux 中的多个 ALSA 声音流?

C:将整数数组打印为二进制数据

linux - 阿尔萨。如何以编程方式更改设备 ID?

c - strdup 将每一行放入 char ** (数组)

c - sprintf 写入字符串\n

python - 如何以编程方式从 apt 获取软件包列表?

Yii 使用 Gii 的 Linux 权限问题

linux - 从.sh文件获取脚本代码

c++ - Debian 上的音频采样

linux - Linux 版 monogame 支持 Android 解决方案吗?当我尝试创建解决方案时出现错误