如何使用ALSA的snd_pcm_writei()?

Lou*_*ise 5 c c++ alsa

有人可以解释一下snd_pcm_writei

snd_pcm_sframes_t snd_pcm_writei(snd_pcm_t *pcm, const void *buffer,
                                 snd_pcm_uframes_t size)
Run Code Online (Sandbox Code Playgroud)

作品?

我像这样使用它:

for (int i = 0; i < 1; i++) {
   f = snd_pcm_writei(handle, buffer, frames);

   ...
}
Run Code Online (Sandbox Code Playgroud)

http://pastebin.com/m2f28b578上的完整源代码

这是否意味着,我不应该给出snd_pcm_writei()所有帧的数量buffer,而只是

sample_rate*latency = frames

因此,如果我有例如:sample_rate = 44100 latency = 0.5 [s] all_frames = 100000

帧的,我应该给的数目snd_pcm_writei()

sample_rate*latency = frames 44100*0.5 = 22050

以及for循环的迭代次数应该是多少?

(int)100000/22050 = 4; 框架= 22050

还有一个,但只有

100000 mod 22050 = 11800

帧?

它是如何工作的?

路易丝

http://www.alsa-project.org/alsa-doc/alsa-lib/group___p_c_m.html#gf13067c0ebde29118ca05af76e5b17a9

Ori*_*ach 7

frames应该是您想要从缓冲区写入的帧数(样本).系统的声音驱动程序将立即开始将这些样本传输到声卡,它们将以恒定速率播放.

延迟是在几个地方引入的.在等待传输到卡时,驱动程序缓冲的数据存在延迟.至少有一个缓冲区充满了在任何给定时刻传输到卡上的数据,并且在应用程序端有缓冲,这就是您似乎关注的问题.

要减少应用程序端的延迟,您需要编写适合您的最小缓冲区.如果您的应用程序执行DSP任务,那通常是一个窗口的数据.

在循环中编写小缓冲区没有任何优势 - 只需继续编写所有内容 - 但有一点需要理解:为了最大限度地减少延迟,应用程序应该写入驱动程序的速度不会快于驱动程序将数据写入声卡,或者你最终会堆积更多数据并累积越来越多的延迟.

对于使声音驱动程序与之相对容易生成数据的设计,请查看jack(http://jackaudio.org/),它基于在声音播放引擎中注册回调函数.事实上,如果你真的担心延迟,你可能最好不要使用插孔而不是自己动手.

  • 17000个样本不到一秒的播放时间.通过反复写入缓冲区到声音驱动程序,你基本上是一次又一次地播放它,但是根据你的描述,它听起来好像系统中的某些东西阻止了声音的开始播放.首先,踩过缓冲区是正确的做法; 你不需要多次写一个样本.其次,要查看您的声音驱动程序或声卡是否无法播放声音的开头,请尝试在开始时使用大约一秒钟的0个样本填充缓冲区,并查看它是否有所作为. (2认同)

小智 6

我认为对于“早熟”设备关闭的原因是,你需要调用snd_pcm_drain(handle);之前snd_pcm_close(handle);,以确保设备关闭之前所有数据被播放。