6

谁能解释一下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);

   ...
}

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

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

采样率 * 延迟 =frames

?

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

我应该给予的帧数snd_pcm_writei()

采样率 * 延迟 = 帧 44100*0.5 = 22050

和for循环的迭代次数应该是?:

(int) 100000/22050 = 4; 帧数=22050

和一个额外的,但只有

100000 模 22050 = 11800

帧?

它是这样工作的吗?

路易丝

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

4

4 回答 4

9

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

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

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

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

对于使与声音驱动程序同步生成数据相对容易的设计,请查看基于向声音播放引擎注册回调函数的jack ( http://jackaudio.org/ )。事实上,如果你真的担心延迟,你可能最好使用千斤顶而不是尝试自己做。

于 2010-02-02T15:14:40.960 回答
6

I think the reason for the "premature" device closure is that you need to call snd_pcm_drain(handle); prior to snd_pcm_close(handle); to ensure that all data is played before the device is closed.

于 2013-03-07T20:26:50.297 回答
4

我做了一些测试,以确定为什么snd_pcm_writei()使用我在 ALSA 教程中找到的几个示例似乎对我不起作用,我得出的结论是,这些简单示例是snd_pcm_close ()在声音设备可以播放发送给它的完整流之前执行的。

我将速率设置为11025,使用 128 字节的随机缓冲区,并为snd_pcm_writei()每秒的声音循环 11025/128。两秒需要 86*2 次调用snd_pcm_write()才能获得两秒的声音。

为了给设备足够的时间将数据转换为音频,我在循环之后使用了一个 for 循环snd_pcm_writei()来延迟snd_pcm_close()函数的执行。

经过测试,我不得不得出结论,在调用函数之前,示例代码没有提供足够的样本来克服设备延迟,snd_pcm_close这意味着 close 函数的延迟小于snd_pcm_write()函数。

于 2012-11-18T08:15:42.267 回答
1

如果 ALSA 驱动程序的启动阈值设置不正确(如果在您的情况下约为 2s),那么您将需要在 snd_pcm_writei() 之后立即调用 snd_pcm_start() 来开始数据渲染。或者您可以在 ALSA 设备的 SW 参数中设置适当的阈值。

参考:

于 2014-09-21T17:07:59.020 回答