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