关于C#:ALSA中句号的含义

 2021-04-09 

The meaning of period in ALSA

我在Linux上使用ALSA和音频应用程序,我发现很棒的文档解释了如何使用它:1和这个。尽管我有一些问题需要了解设置的这一部分:

1
2
3
4
5
6
 /* 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.\
"
);
  return(-1);
}

当我使用PLAYBACK模式时,这意味着设置多个时间段
和:

1
2
3
4
5
6
7
/* 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.\
"
);
  return(-1);
}

这里还有关于延迟的相同问题,我应该如何理解?


我认为您已经阅读并理解了Linux-journal的这一部分。您可能还会发现,此博客在ALSA的上下文中阐明了有关时段大小选择(或博客中的片段)的信息。引用:

You shouldn't misuse the fragments logic of sound devices. It's like
this:

The latency is defined by the buffer size.
The wakeup interval is defined by the fragment size.

缓冲区填充水平将在" full buffer"和" full"之间振荡
缓冲区减去1x片段大小减去OS调度延迟"。环境
较小的片段大小会增加CPU负载并减少电池
时间,因为您迫使CPU更频繁地唤醒。 OTOH增加
退出安全性,因为您较早填充了播放缓冲区。选择
因此,片段大小是您应该平衡的内容
您在功耗和跌落安全性之间的需求。与现代
处理器和良好的操作系统调度程序(如Linux)来设置
片段大小不等于缓冲区大小的一半不会
很有道理。

...
(哦,ALSA用"期间"一词来形容我所说的"碎片"
以上。是同义词)

因此,从本质上讲,通常您会将period设置为2(就像在您所参考的howto中所做的那样)。然后periodsize * period是您的缓冲区总大小(以字节为单位)。最后,延迟是由许多样本的缓冲引起的延迟,可以通过将缓冲区大小除以回放样本的速率来计算(即,根据代码注释中的公式latency = periodsize * periods / (rate * bytes_per_frame)) )。

例如,howto中的参数:

  • 期间= 2
  • periodsize = 8192字节
  • 频率= 44100Hz
  • 16位立体声数据(每帧4个字节)

对应于period * periodsize = 2 * 8192 = 16384个字节的总缓冲区大小,并且延迟为16384 /(44100 * 4)?0.093`秒。

还请注意,您的硬件可能会对支持的周期大小有一些大小限制(请参阅此故障排除指南)


当应用程序尝试将样本写入缓冲区时,如果缓冲区已满,则过程进入睡眠状态。它通过中断被硬件唤醒。在每个周期结束时都会引发此中断。

每个缓冲区至少应有两个句点;否则,唤醒时缓冲区已经为空,从而导致欠载。

增加周期数(即减小周期大小)会增加针对因调度或处理延迟而导致的不足量的安全裕度。

等待时间与缓冲区大小成正比:当完全填满缓冲区时,只有在所有其他采样都播放完之后,硬件才会播放最后写入的采样。