我在Linux上使用ALSA和音频应用程序,我发现很棒的文档解释了如何使用它:1和this one。虽然我有一些问题需要理解这部分设置:
/* Set number of periods. Periods used to be called fragments. */
if (snd_pcm_hw_params_set_periods(pcm_handle, hwparams, periods, 0) < 0) {
fprintf(stderr, "Error setting periods.\n");
return(-1);
}
当我使用播放模式时,意味着设置一段时间 并且:
/* Set buffer size (in frames). The resulting latency is given by */
/* latency = periodsize * periods / (rate * bytes_per_frame) */
if (snd_pcm_hw_params_set_buffer_size(pcm_handle, hwparams, (periodsize * periods)>>2) < 0) {
fprintf(stderr, "Error setting buffersize.\n");
return(-1);
}
以及关于延迟的相同问题,我该如何理解?
答案 0 :(得分:12)
我假设您已阅读并理解this section of linux-journal。您还可以在ALSA的上下文中找到this blog澄清有关期间大小选择(或博客中的片段)的内容。引用:
你不应该滥用声音设备的片段逻辑。它就像 这样:
延迟由缓冲区大小定义 唤醒间隔由片段大小定义。
缓冲区填充水平将在“完全缓冲区”之间振荡。并且“满了 缓冲区减去1x片段大小减去OS调度延迟&#39;设置 较小的片段大小会增加CPU负载并减少电池电量 自从强制CPU更频繁地唤醒以来的时间。 OTOH它增加了 因为你先填满了播放缓冲区,所以安全性会降低。选择 因此,片段大小是你应该做的平衡 您在功耗和辍学安全之间的需求。随着现代 处理器和一个良好的操作系统调度程序,如Linux设置 片段大小不是缓冲区大小的一半而不是 很有意义。
... (哦,ALSA使用术语&#39;期间&#39;用于我所称的&#39;片段&#39; 以上。它是同义词)
基本上,通常您会将period
设置为2(就像您引用的howto中所做的那样)。然后periodsize * period
是您的总缓冲区大小(以字节为单位)。最后,latency是由许多样本的缓冲引起的延迟,并且可以通过将缓冲区大小除以样本被回放的速率来计算(即,根据公式{{1}在代码注释中)。
例如,来自howto的参数:
对应的总缓冲区大小为latency = periodsize * periods / (rate * bytes_per_frame)
字节,延迟为16384 /(44100 * 4)~0.093秒。
另请注意,您的硬件可能对支持的期间大小有一些大小限制(请参阅this trouble shooting guide)
答案 1 :(得分:4)
当应用程序尝试将样本写入缓冲区时,如果缓冲区已满,则进程进入休眠状态。它被硬件通过中断唤醒;这个中断在每个时期结束时提出。
每个缓冲区应该至少有两个周期;否则,当唤醒发生时缓冲区已经为空,这会导致欠载。
增加周期数(即减少周期大小)会增加因调度或处理延迟而导致的欠载的安全边际。
延迟与缓冲区大小成正比:当您完全填充缓冲区时,只有在播放完所有其他样本后,硬件才会播放最后写的样本。