alsa:每个欠载时延迟增加

时间:2018-05-24 22:08:49

标签: linux alsa

我正在编写一个典型的捕获过程回放循环。使用snd_pcm_readi()捕获,一些廉价的音频处理,然后通过snd_pcm_writei()播放。单线程。 在128周期大小和96000KHz我无法察觉任何延迟。好。

我定期得到缓冲区欠载(snd_pcm_writei()返回-EPIPE);没关系,我正在运行一个没有配置低音频延迟的常规Ubuntu 16.04桌面。

在一些不足之后,延迟变得可感知。我不明白为什么。

这是我的捕获设备配置:

Plug PCM: Linear Integer <-> Linear Float conversion PCM (S32_LE)
Its setup is:
  stream       : CAPTURE
  access       : RW_INTERLEAVED
  format       : FLOAT_LE
  subformat    : STD
  channels     : 1
  rate         : 96000
  exact rate   : 96000 (96000/1)
  msbits       : 32
  buffer_size  : 4096
  period_size  : 128
  period_time  : 1333
  tstamp_mode  : NONE
  tstamp_type  : MONOTONIC
  period_step  : 1
  avail_min    : 128
  period_event : 0
  start_threshold  : 0
  stop_threshold   : 4096
  silence_threshold: 0
  silence_size : 0

这是播放设备配置:

Plug PCM: Linear Integer <-> Linear Float conversion PCM (S32_LE)
Its setup is:
  stream       : PLAYBACK
  access       : RW_INTERLEAVED
  format       : FLOAT_LE
  subformat    : STD
  channels     : 1
  rate         : 96000
  exact rate   : 96000 (96000/1)
  msbits       : 32
  buffer_size  : 384
  period_size  : 128
  period_time  : 1333
  tstamp_mode  : NONE
  tstamp_type  : MONOTONIC
  period_step  : 1
  avail_min    : 128
  period_event : 0
  start_threshold  : 384
  stop_threshold   : 384
  silence_threshold: 0
  silence_size : 0
  boundary     : 6917529027641081856

当发生欠载时,我运行snd_pcm_recover()并忘记snd_pcm_writei()拒绝的音频时段。在我看来,我会在snd_pcm_writei()运行后立即播放下一个音频周期,我将再次处于低延迟循环中。但这是错误的,延迟会增加。

我的循环捕获方没有错误。

发生了什么?我究竟做错了什么?

感谢。

1 个答案:

答案 0 :(得分:1)

捕获缓冲区大于回放缓冲区。这是一个好主意,可以降低捕获溢出的风险(如果硬件支持,你想让它变得更大),但是当播放设备停止一小段时间时,捕获中会堆积更多数据缓冲并且不会比你播放的速度快。

要确保捕获和回放设备不会失去同步,

  • 停止两个设备,然后再次正确启动它们,或
  • 配置播放设备禁用欠载检测(将停止阈值设置为边界值);这意味着即使缓冲区中没有有效的样本,回放也会继续,然后您的代码必须写入样本,直到找到它为止。 (使用默认设置,环形缓冲区中的旧样本在欠载期间再次播放;如果您将静音阈值/大小设置为零/边界,则会播放静音。)