alsa:每次欠载都会增加延迟 [英] alsa: latency increases at every underrun

查看:704
本文介绍了alsa:每次欠载都会增加延迟的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个典型的捕获过程回放循环。使用 snd_pcm_readi(),一些廉价的音频处理进行捕获,然后通过 snd_pcm_writei()进行回放。单线程。
在128个周期大小和96000KHz的频率下,我看不到任何延迟。很好。

I'm writing a tipical capture-process-playback loop. Capture using snd_pcm_readi(), some cheap audio process and then playback through snd_pcm_writei(). Single threaded. At 128 period size and 96000KHz I cannot perceive any latency. Good.

我偶尔会遇到缓冲区不足( snd_pcm_writei()返回-EPIPE);没关系,我正在运行未配置低音频延迟的常规Ubuntu 16.04桌面。

Periodically I get a buffer underrun (snd_pcm_writei() returns -EPIPE); It's ok, I'm running a regular Ubuntu 16.04 desktop not configured for low audio latency.

在运行不足后,延迟就可以被察觉了。我不明白为什么。

After some underruns the latency becomes perceivable. I don't understand why.

这是我的捕获设备配置:

this is my capture device configuration:

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()时播放,并且我将再次处于低延迟循环中。但这是错误的,延迟会增加。

when the underrun occurs I run snd_pcm_recover() and forget about the audio period that was just refused by snd_pcm_writei(). In my mind the next audio period will be played as soon I run snd_pcm_writei() and I will be again in a low-latency loop. But this is wrong, the latency increases.

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

No errors from the capture side of my loop.

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

What's happening? What Am I doing wrong?

谢谢。

推荐答案

捕获缓冲区大于回放缓冲区缓冲。这是一个降低捕获溢出风险的好主意(如果硬件支持,您可能希望将其扩大甚至更大),但是当播放设备停止一小段时间时,捕获中将堆积更多数据

The capture buffer is larger than the playback buffer. This is a good idea to reduce the risk of capture overruns (and you migth want to make it even larger, if supported by the hardware), but when the playback device stops for a short time, more data will have piled up in the capture buffer and does not go away faster than you can play it.

为确保捕获和回放设备不会丢失同步,

To ensure that the capture and playback devices do not lose synchronization, either


  • 停止两个设备,然后再次正确启动它们,或者

  • 配置播放设备以禁用欠载检测(设置停止阈值到边界值);这意味着即使缓冲区中没有 valid 样本,回放也将继续进行,然后您的代码必须编写样本,直到被捕获为止。 (使用默认设置,在欠载期间将再次播放环形缓冲区中的旧样本;如果将静音阈值/大小设置为零/边界,则改为播放静音。)

  • stop both devices, and then start them again properly, or
  • configure the playback device to disable underrun detection (set the stop threshold to the boundary value); this means that playback will just continue, even if there are no valid samples in the buffer, and your code then has to write samples until is has caught up. (With the default settings, the old samples in the ring buffer are played again during an underrun; if you've set the silence threshold/size to zero/boundary, silence is played instead.)

这篇关于alsa:每次欠载都会增加延迟的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆