有人可以解释snd_pcm_writei
的方式snd_pcm_sframes_t snd_pcm_writei(snd_pcm_t *pcm, const void *buffer,
snd_pcm_uframes_t size)
作品?
我这样使用过它:
for (int i = 0; i < 1; i++) {
f = snd_pcm_writei(handle, buffer, frames);
...
}
的完整源代码
这是否意味着我不应该给snd_pcm_writei()
数字
buffer
中的所有帧,但只有
sample_rate * latency = frames
所以,如果我,例如有: sample_rate = 44100 潜伏期= 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
答案 0 :(得分:6)
frames 应该是您想要从缓冲区写入的帧数(样本)。系统的声音驱动程序将立即开始将这些样本传输到声卡,它们将以恒定速率播放。
延迟是在几个地方引入的。在等待传输到卡上时,驱动程序缓冲的数据存在延迟。至少有一个缓冲区充满了在任何给定时刻传输到卡上的数据,并且在应用程序端有缓冲,这是你似乎关注的。
要减少应用程序端的延迟,您需要编写适合您的最小缓冲区。如果您的应用程序执行DSP任务,那通常就是一个窗口的数据。
在循环中编写小缓冲区没有任何优势 - 只需继续编写所有内容 - 但有一点需要理解:为了最大限度地减少延迟,应用程序应该写入驱动程序不会比驱动程序写入更快数据到声卡,或者你最终堆积更多数据并累积越来越多的延迟。
对于使声音驱动程序与锁定步骤相对容易生成数据的设计,请查看基于向声音播放引擎注册回调函数的jack(http://jackaudio.org/)。事实上,如果你真的担心延迟,你可能最好不要使用插孔而不是自己动手。
答案 1 :(得分:3)
我做了一些测试,以确定为什么snd_pcm_writei()
似乎不适合我,使用我在ALSA教程中找到的几个示例,我得出的结论是,简单示例之前正在执行snd_pcm_close ()
声音设备可以播放发送给它的完整流。
我将速率设置为11025
,使用128字节的随机缓冲区,并将循环snd_pcm_writei()
设置为每秒声音的11025/128。两秒钟需要86 * 2个电话snd_pcm_write()
才能获得两秒钟的声音。
为了给设备足够的时间将数据转换为音频,我在snd_pcm_writei()
循环之后使用了for循环来延迟执行snd_pcm_close()
函数。
经过测试,我必须得出结论,在调用snd_pcm_close
函数之前,示例代码没有提供足够的样本来克服设备延迟,这意味着close函数的延迟小于{{1}功能。
答案 2 :(得分:3)
我认为设备关闭“过早”的原因是您需要在snd_pcm_drain(handle);
之前调用snd_pcm_close(handle);
,以确保在设备关闭之前播放所有数据。
答案 3 :(得分:0)
如果未正确设置ALSA驱动程序的启动阈值(如果是大约2秒),则需要调用snd_pcm_start()以在snd_pcm_writei()之后立即启动数据呈现。 或者您可以在ALSA设备的SW参数中设置适当的阈值。
REF: