【问题标题】:alsa: latency increases at every underrunalsa:每次运行时延迟都会增加
【发布时间】:2018-11-04 05:50:45
【问题描述】:

我正在编写一个典型的捕获过程回放循环。使用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(),就会播放下一个音频时段,我将再次进入低延迟循环。但这是错误的,延迟会增加。

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

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

谢谢。

【问题讨论】:

    标签: linux alsa


    【解决方案1】:

    捕获缓冲区大于播放缓冲区。这是降低捕获溢出风险的好主意(如果硬件支持,您可能希望使其更大),但是当播放设备短时间停止时,捕获中会堆积更多数据缓冲并且不会比您播放它的速度更快。

    为确保采集和播放设备不会失去同步,

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

    【讨论】:

    • 谢谢。我会尝试你的两种解决方案。但是我不明白为什么数据会堆积在捕获缓冲区中;由于欠载而无法播放的音频周期不再像我正确播放的任何其他数据块一样在捕获缓冲区中。据我了解,播放和捕捉设备是完全分开的,从捕捉的角度来看,无论播放与否,数据块都会以恒定的速度被拉出。我的错在哪里?
    • 只要停止播放,您也不会从捕获缓冲区中读取数据。如果播放缓冲区和捕获缓冲区的大小相同,您可能会得到两者的 xruns。
    • 有谁知道如何使用“aplay”命令行工具将阈值设置为边界值?如果我使用 -T 标志将 stop_threshold 设置为边界值,则它不起作用。 stop_threshold 设置为比我输入的值更小的值,并且我仍然看到欠载后延迟增加。不理解这种行为。
    • @ProjectileFish aplay 在样本中没有设置停止阈值的参数。
    猜你喜欢
    • 2023-02-16
    • 2022-06-09
    • 1970-01-01
    • 2023-03-29
    • 2019-05-12
    • 1970-01-01
    • 1970-01-01
    • 2014-10-31
    • 2016-12-24
    相关资源
    最近更新 更多