Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用snd_pcm_writei()播放音频时,如何正确处理ALSA编程中的xrun?_C_Alsa - Fatal编程技术网

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

使用snd_pcm_writei()播放音频时,如何正确处理ALSA编程中的xrun?,c,alsa,C,Alsa,我尝试了多个示例程序,这些程序似乎都有代码来处理回放下的xruns: (清单3) 使用snd_pcm_writei()时,当返回值为-eppe(即xrun/underrun)时,它们会执行以下操作: if (rc == -EPIPE) { /* EPIPE means underrun */ fprintf(stderr, "underrun occurred\n"); snd_pcm_prepare(handle); } 即调用手柄上的snd_pcm_prepare() 然而,

我尝试了多个示例程序,这些程序似乎都有代码来处理回放下的xruns:

(清单3)

使用snd_pcm_writei()时,当返回值为-eppe(即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和扬声器上的实际口吃问题

这对我来说是不可接受的,我如何修改这种类型的xrun处理以防止口吃

我自己试图弄明白这一点:

从ALSA API中,我看到snd_pcm_prepare()可以:

准备PCM以备使用

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

我还注意到:

SND_PCM_状态_XRUN PCM设备达到超限(捕获)或欠载(播放)。您可以使用I/O函数中的-eppe返回代码 (snd_pcm_writei()、snd_pcm_writen()、snd_pcm_readi()、snd_pcm_readn()) 在不通过检查实际状态的情况下确定此状态 snd_pcm_state()调用。建议使用helper函数 snd_pcm_recover()从该状态恢复,但也可以使用 snd_pcm_prepare()、snd_pcm_drop()或snd_pcm_drain()调用


我也不清楚。我可以使用snd_pcm_prepare()或其他调用?有什么区别?我应该使用什么?

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

  • 重新组织您的程序,以便在需要调用
    snd\u pcm\u write*()
    ,和/或
  • 增加进程/线程的优先级(如果可能;如果其他程序干扰磁盘OI/O,这可能没有帮助),和/或
  • 增加缓冲区大小(这也会增加延迟)
当发生欠运行时,您必须决定应播放但未在正确时间写入缓冲区的样本的情况

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

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

要在发生错误(xrun或其他错误)后(尝试)重新初始化设备,可以调用
snd\u pcm\u prepare()
snd\u pcm\u recover()
。后者调用前者,并处理挂起的设备(通过等待设备恢复)

\\停止阈值:
snd\u pcm\u sw\u params\u set\u stop\u threshold()

²边界值:
snd\u pcm\u sw\u params\u get\u boundary()

静音阈值:
snd\u pcm\u sw\u params\u set\u静音阈值()
⁴静音大小:
snd\u pcm\u sw\u params\u set\u静音大小()