gpt4 book ai didi

c - 使用 snd_pcm_writei() 播放音频时,如何在 ALSA 编程中正确处理 xrun?

转载 作者:行者123 更新时间:2023-12-04 15:36:57 49 4
gpt4 key购买 nike

我已经尝试了多个示例程序,它们似乎有代码来处理播放时的 xruns:

https://albertlockett.wordpress.com/2013/11/06/creating-digital-audio-with-alsa/

https://www.linuxjournal.com/article/6735 ( list 3)

当使用 snd_pcm_writei() 时,似乎当返回值为 -EPIPE(即 xrun/underrun)时,它们会:

if (rc == -EPIPE) {
/* EPIPE means underrun */
fprintf(stderr, "underrun occurred\n");
snd_pcm_prepare(handle);
}

即在句柄上调用 snd_pcm_prepare()。

但是,当我尝试运行这些程序时,我仍然会口吃。通常,我会得到至少几个,可能是六个 xrun,然后它会流畅地连续播放而无需进一步的 xrun。但是,如果我有其他东西使用声卡,比如 Firefox,我会得到更多的 xruns,有时只有 xruns。但同样,即使我杀死了任何其他使用声卡的程序,我仍然会遇到一些初始 xrun 和扬声器实际卡顿的问题。

这对我来说是 Not Acceptable ,我如何修改这种类型的 xrun 处理以防止卡顿?

我自己尝试解决这个问题:

从 ALSA API 中,我看到 snd_pcm_prepare() 做了:

Prepare PCM for use.

这对像我这样的 ALSA 初学者帮助不大。没有解释如何使用它来恢复 xrun 问题。

我还注意到,来自:https://www.alsa-project.org/alsa-doc/alsa-lib/pcm.html

SND_PCM_STATE_XRUN The PCM device reached overrun (capture) or underrun (playback). You can use the -EPIPE return code from I/O functions (snd_pcm_writei(), snd_pcm_writen(), snd_pcm_readi(), snd_pcm_readn()) to determine this state without checking the actual state via snd_pcm_state() call. It is recommended to use the helper function snd_pcm_recover() to recover from this state, but you can also use snd_pcm_prepare(), snd_pcm_drop() or snd_pcm_drain() calls.

同样,我也不清楚。我可以使用 snd_pcm_prepare() 或者我可以使用这些其他调用?有什么不同?我应该使用什么?

最佳答案

处理欠载的最佳方法是通过防止它们来避免处理它们。这可以通过在缓冲区为空之前足够早地写入样本来完成。为此,

  • 重组您的程序,以便在您需要调用 snd_pcm_write*() 和/或
  • 时可以编写新示例
  • 增加您的进程/线程的优先级(如果可能;如果其他程序干扰您的磁盘 OI/O,这可能没有帮助),和/或
  • 增加缓冲区大小(这也会增加延迟)。

当发生欠载时,您必须决定应该如何处理本应播放但未在正确时间写入缓冲区的样本。

  • 要稍后播放这些示例(即,将所有 后面的示例移到稍后的时间),请配置设备,以便欠载停止它。 (这是默认设置。)您的程序必须在有新样本时重新启动设备。
  • 要同时继续播放以下示例,就好像丢失的示例已实际播放一样,请配置设备,以便欠载运行不会停止它。这可以通过将停止阈值¹设置为边界值²来完成。 (其他错误,如拔出 USB 设备,仍会停止设备。)

    当确实发生数据不足时,设备将播放恰好在环形缓冲区中的那些样本。默认情况下,这些是一段时间前的旧样本,听起来不正确。要改为播放静音(这听起来也不正确,但以不同的方式),请告诉设备在播放后立即清除缓冲区的每个部分,方法是将静音阈值³设置为零并将静音大小⁴设置为边界值.

要(尝试)在错误(xrun 或其他错误)后重新初始化设备,您可以调用 snd_pcm_prepare()snd_pcm_recover()。后者调用前者,并处理挂起的设备(通过等待它恢复)。

¹停止阈值:snd_pcm_sw_params_set_stop_threshold()
²边界值:snd_pcm_sw_params_get_boundary()
³静音阈值:snd_pcm_sw_params_set_silence_threshold()
⁴静音大小:snd_pcm_sw_params_set_silence_size()

关于c - 使用 snd_pcm_writei() 播放音频时,如何在 ALSA 编程中正确处理 xrun?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59396728/

49 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com