linux – ALSA:snd_pcm_writei调用的缓冲区欠载

weixin_38048892 2019-09-12 12:17:32
在运行我最近从灰烬中带回来的旧程序时,我得到缓冲区欠载. 程序将原始声音文件完全加载到内存中(2100字节长,525帧)并准备ALSA输出(44.1khz,2个通道,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,并且snd_pcm_writei会抛出-EPIPE(“Broken pipe”).播放逻辑: 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/ 编辑 刚刚发现如果一个人实际测试-EPIPE条件并在重新发出snd_pcm_writei调用之前重新准备PCM句柄,那么一切都很好.我的(新)问题是……为什么? if(frames == -EPIPE) { snd_pcm_prepare(pcm.handle); frames = snd_pcm_writei(pcm.handle, sound.data, //sound.data + (offset << 1), write_size); }
...全文
1981 1 打赏 收藏 转发到动态 举报
写回复
用AI写文章
1 条回复
切换为时间正序
请发表友善的回复…
发表回复
weixin_38054276 2019-09-12
  • 打赏
  • 举报
回复
如果用525帧(大约12 ms)填充缓冲区然后等待一秒钟,则可以保证得到欠载,因为剩余的988 ms没有数据. 你可以使用snd_pcm_drain等到实际数据停止播放(注意:通常情况下,设备实际上不会停止,直到下一个周期边界).或者,继续将零样品送入缓冲液.

476

社区成员

发帖
与我相关
我的任务
社区描述
其他技术讨论专区
其他 技术论坛(原bbs)
社区管理员
  • 其他技术讨论专区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧