Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/25.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
Linux ALSA:播放音频的正确方法-阻塞模式和线程_Linux_Alsa - Fatal编程技术网

Linux ALSA:播放音频的正确方法-阻塞模式和线程

Linux ALSA:播放音频的正确方法-阻塞模式和线程,linux,alsa,Linux,Alsa,我无法以正确的方式编写循环以播放音频和/或我无法正确理解Alsa的start_阈值、stop_阈值和avail_min参数的含义。我希望达到最低的延迟,并知道要修改的正确参数,以便使我的捕获过程播放链能够容忍音频处理时间的变化。在本例中,我从文件中读取示例,以关注播放部分 这是我的输出设备配置,在阻塞模式下打开(Ubuntu 16.04,PulseAudio存在,defaultdevice): 一开始我不知道这些EPIPE错误的原因;我所期望的是,snd_pcm_writei要么立即返回,要么在

我无法以正确的方式编写循环以播放音频和/或我无法正确理解Alsa的start_阈值、stop_阈值和avail_min参数的含义。我希望达到最低的延迟,并知道要修改的正确参数,以便使我的捕获过程播放链能够容忍音频处理时间的变化。在本例中,我从文件中读取示例,以关注播放部分

这是我的输出设备配置,在阻塞模式下打开(Ubuntu 16.04,PulseAudio存在,
default
device):

一开始我不知道这些EPIPE错误的原因;我所期望的是,
snd_pcm_writei
要么立即返回,要么在返回之前等待(或多或少)一段时间,因为我处于阻塞模式,并且我提供样本的速度比回放采样率要求的要快。 错误序列结束时,播放正常。此外,如果我将实时优先级设置为我的线程(
pthread_setschedparam()
),我将得到一个无限的OK 2048/ERR-32列表,我只听到噪音。这对我来说真的很奇怪

我的错在哪里


谢谢。

开始时,缓冲区是空的,因此您应该尽快填充,不要等待

要减少延迟,请减小缓冲区大小。
要降低欠载的风险,请增加缓冲区大小。
你不能同时做这两件事。您必须为您的特定情况选择一个平衡这两个目标的缓冲区大小

开始阈值指定当缓冲区中有那么多帧时,设备自动开始播放。您应该将其设置为缓冲区大小

停止阈值指定设备在可用(空闲)帧数达到此值时停止。您应该将其保留为默认值,即缓冲区大小


avail_min参数指定在中断导致应用程序实际被唤醒之前必须有多少帧可用。

在开始时,缓冲区是空的,因此您应该尽快填充它,而不必等待

要减少延迟,请减小缓冲区大小。
要降低欠载的风险,请增加缓冲区大小。
你不能同时做这两件事。您必须为您的特定情况选择一个平衡这两个目标的缓冲区大小

开始阈值指定当缓冲区中有那么多帧时,设备自动开始播放。您应该将其设置为缓冲区大小

停止阈值指定设备在可用(空闲)帧数达到此值时停止。您应该将其保留为默认值,即缓冲区大小

avail_min参数指定在中断导致应用程序实际被唤醒之前必须有多少帧可用。

编辑:

原来凶手是PulseAudio。通过
pasuspender
把它放在一边,一切都按照我的预期进行。 我向前迈出了一步。我能够获得更稳定的声音输出设置
buffer\u size
start\u threshold
stop\u threshold
为周期大小的3倍,而
avail\u min
为周期大小。我仍然没有得到avail_min和start_threshold之间的区别,但是这工作得更好,即使是使用如下所示的小周期大小:

ALSA <-> PulseAudio PCM I/O Plugin
Its setup is:
  stream       : PLAYBACK
  access       : RW_INTERLEAVED
  format       : FLOAT_LE
  subformat    : STD
  channels     : 1
  rate         : 44100
  exact rate   : 44100 (44100/1)
  msbits       : 32
  buffer_size  : 192
  period_size  : 64
  period_time  : 1451
  tstamp_mode  : NONE
  tstamp_type  : GETTIMEOFDAY
  period_step  : 1
  avail_min    : 64
  period_event : 0
  start_threshold  : 192
  stop_threshold   : 192
  silence_threshold: 0
  silence_size : 0
  boundary     : 6917529027641081856
但我仍然有实时显示的问题。如果我将实时调度设置为我的线程,有时我会得到一个干净的输出,没有EPIPE错误,但大多数时候,我会得到一个无休止的错误序列,我只听到噪音:

[1525158709952740 /     30] snd_pcm_writei: OK 64
[1525158709952781 /     14] snd_pcm_writei: OK 64
[1525158709952809 /   2163] snd_pcm_writei: OK 64
[1525158709954994 /      4] snd_pcm_writei: ERR -32 [Broken pipe]
snd_pcm_prepare: 0
[1525158709956346 /     29] snd_pcm_writei: OK 64
[1525158709956385 /     15] snd_pcm_writei: OK 64
[1525158709956405 /   2250] snd_pcm_writei: OK 64
[1525158709958673 /      3] snd_pcm_writei: ERR -32 [Broken pipe]
snd_pcm_prepare: 0
[1525158709959930 /     31] snd_pcm_writei: OK 64
[1525158709959971 /     15] snd_pcm_writei: OK 64
[1525158709959998 /   2334] snd_pcm_writei: OK 64
[1525158709962355 /      3] snd_pcm_writei: ERR -32 [Broken pipe]
snd_pcm_prepare: 0
使用更大的周期大小,我有更多的机会获得干净的音频流,但仍然不是100%可靠

有什么提示吗

谢谢。

编辑:

原来凶手是PulseAudio。通过
pasuspender
把它放在一边,一切都按照我的预期进行。 我向前迈出了一步。我能够获得更稳定的声音输出设置
buffer\u size
start\u threshold
stop\u threshold
为周期大小的3倍,而
avail\u min
为周期大小。我仍然没有得到avail_min和start_threshold之间的区别,但是这工作得更好,即使是使用如下所示的小周期大小:

ALSA <-> PulseAudio PCM I/O Plugin
Its setup is:
  stream       : PLAYBACK
  access       : RW_INTERLEAVED
  format       : FLOAT_LE
  subformat    : STD
  channels     : 1
  rate         : 44100
  exact rate   : 44100 (44100/1)
  msbits       : 32
  buffer_size  : 192
  period_size  : 64
  period_time  : 1451
  tstamp_mode  : NONE
  tstamp_type  : GETTIMEOFDAY
  period_step  : 1
  avail_min    : 64
  period_event : 0
  start_threshold  : 192
  stop_threshold   : 192
  silence_threshold: 0
  silence_size : 0
  boundary     : 6917529027641081856
但我仍然有实时显示的问题。如果我将实时调度设置为我的线程,有时我会得到一个干净的输出,没有EPIPE错误,但大多数时候,我会得到一个无休止的错误序列,我只听到噪音:

[1525158709952740 /     30] snd_pcm_writei: OK 64
[1525158709952781 /     14] snd_pcm_writei: OK 64
[1525158709952809 /   2163] snd_pcm_writei: OK 64
[1525158709954994 /      4] snd_pcm_writei: ERR -32 [Broken pipe]
snd_pcm_prepare: 0
[1525158709956346 /     29] snd_pcm_writei: OK 64
[1525158709956385 /     15] snd_pcm_writei: OK 64
[1525158709956405 /   2250] snd_pcm_writei: OK 64
[1525158709958673 /      3] snd_pcm_writei: ERR -32 [Broken pipe]
snd_pcm_prepare: 0
[1525158709959930 /     31] snd_pcm_writei: OK 64
[1525158709959971 /     15] snd_pcm_writei: OK 64
[1525158709959998 /   2334] snd_pcm_writei: OK 64
[1525158709962355 /      3] snd_pcm_writei: ERR -32 [Broken pipe]
snd_pcm_prepare: 0
使用更大的周期大小,我有更多的机会获得干净的音频流,但仍然不是100%可靠

有什么提示吗


谢谢。

我明白这一点。但是我的第二个snd_pcm_writei()是在(成功的)第一个snd_pcm_writei()之后的2.5毫秒,而这段时间是46毫秒。我认为它足够快了。为什么会出现错误?因为您已将停止阈值设置得太低。确定。我开始明白了。谢谢但是,如果我推送的数据太多,或者等到我确定下一个snd_pcm_writei()会成功时,我如何才能使snd_pcm_writei()阻塞?启动阈值和可用最小参数之间有什么区别?我理解这一点。但是我的第二个snd_pcm_writei()是在(成功的)第一个snd_pcm_writei()之后的2.5毫秒,而这段时间是46毫秒。我认为它足够快了。为什么会出现错误?因为您已将停止阈值设置得太低。确定。我开始明白了。谢谢但是,如果我推送的数据太多,或者等到我确定下一个snd_pcm_writei()会成功时,我如何才能使snd_pcm_writei()阻塞?启动阈值和可用最小参数之间有什么区别?
[1525158345182486 /     64] snd_pcm_writei: OK 64
[1525158345182609 /     23] snd_pcm_writei: OK 64
[1525158345182833 /    862] snd_pcm_writei: OK 64
[1525158345183718 /      3] snd_pcm_writei: ERR -32 [Broken pipe]
snd_pcm_prepare: 0
[1525158345184915 /     38] snd_pcm_writei: OK 64
[1525158345184962 /     46] snd_pcm_writei: OK 64
[1525158345185018 /   1240] snd_pcm_writei: OK 64
[1525158345186281 /     33] snd_pcm_writei: OK 64
[1525158709952740 /     30] snd_pcm_writei: OK 64
[1525158709952781 /     14] snd_pcm_writei: OK 64
[1525158709952809 /   2163] snd_pcm_writei: OK 64
[1525158709954994 /      4] snd_pcm_writei: ERR -32 [Broken pipe]
snd_pcm_prepare: 0
[1525158709956346 /     29] snd_pcm_writei: OK 64
[1525158709956385 /     15] snd_pcm_writei: OK 64
[1525158709956405 /   2250] snd_pcm_writei: OK 64
[1525158709958673 /      3] snd_pcm_writei: ERR -32 [Broken pipe]
snd_pcm_prepare: 0
[1525158709959930 /     31] snd_pcm_writei: OK 64
[1525158709959971 /     15] snd_pcm_writei: OK 64
[1525158709959998 /   2334] snd_pcm_writei: OK 64
[1525158709962355 /      3] snd_pcm_writei: ERR -32 [Broken pipe]
snd_pcm_prepare: 0