PortAudio 不可靠:表达式“...”失败
Posted
技术标签:
【中文标题】PortAudio 不可靠:表达式“...”失败【英文标题】:PortAudio unreliable: Expression '...' failed 【发布时间】:2016-05-20 01:53:54 【问题描述】:我目前正在试验实时信号处理,所以我尝试了 PortAudio(来自 C)。
我的电脑上有两个音频接口,板载声音(英特尔高清音频)和一个 USB 音频接口。两者通常在 Linux 上的 ALSA 下都能正常工作。我也试过Linux下JACK下的USB音频接口,效果也很好。
我的工作:
我的代码只是初始化 PortAudio,打开并启动一个流(一个通道,paInt32
样本格式,defaultLowInputLatency
/defaultLowOutputLatency
,尽管我尝试更改为 paFloat32
或 defaultHighInputLatency
/defaultHighOutputLatency
,其中没有任何改善)。
在每次调用回调时,它通过memcpy
将sizeof(int32_t) * frameCount
字节从输入缓冲区复制到输出缓冲区,然后返回paContinue
。它在回调中什么也不做。没有内存分配,没有系统调用,没有任何东西可以阻塞。它只是输出它读取的内容。代码很简单,还是不能运行。
将memcpy
替换为循环将int32_t
类型的frameCount
元素从输入缓冲区复制到输出缓冲区并没有改变任何内容。
我的尝试:
使用 PortAudio 尝试了以下场景。
-
通过 USB 音频接口输入和输出,PortAudio 上的回调机制,ALSA 后端。
通过 USB 音频接口输入和输出,在具有 1024 个样本缓冲区大小的 PortAudio 上阻塞 I/O,ALSA 后端。
通过 USB 音频接口输入,通过板载声音输出,PortAudio 上的回调机制,ALSA 后端。
通过 USB 音频接口输入,通过板载声音输出,在具有 1024 个样本缓冲区大小的 PortAudio 上阻塞 I/O,ALSA 后端。
通过 USB 音频接口输入和输出,PortAudio 上的回调机制,JACK 后端。
通过 USB 音频接口输入和输出,在具有 1024 个样本缓冲区大小的 PortAudio 上阻塞 I/O,JACK 后端。
我遇到的问题:
结果如下。 (数字代表上述场景。)
-
设备无输出。
设备输出不稳定(中断)。一直以来都有大量缓冲区不足。
设备无输出。
设备的输出不可靠。有时有效,有时无效。 (无需更改任何内容,只需多次运行可执行文件。)当它工作时,延迟开始时很低,但随着时间的推移会增加并且变得非常明显。
设备无输出。
设备无输出。
在每次尝试之间,ALSA 已经过测试,如果它仍然响应(有时它完全“锁定”,因此没有应用程序可以再输出声音)并重新启动系统以防 ALSA 被“锁定”,然后继续测试。
更多细节,在追踪问题时可能有用:
在完全没有输出的情况下,使用 ALSA 作为后端时会收到以下错误消息。
Expression 'err' failed in 'src/hostapi/alsa/pa_linux_alsa.c', line: 3350
Expression 'ContinuePoll( self, StreamDirection_In, &pollTimeout, &pollCapture )' failed in 'src/hostapi/alsa/pa_linux_alsa.c', line: 3876
Expression 'PaAlsaStream_WaitForFrames( stream, &framesAvail, &xrun )' failed in 'src/hostapi/alsa/pa_linux_alsa.c', line: 4248
使用 JACK 作为后端时,我收到以下错误消息。
Cannot lock down 42435354 byte memory area (Cannot allocate memory)
另外,无论我使用什么方法,我总是会收到这些警告。
ALSA lib pcm.c:2267:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.rear
ALSA lib pcm.c:2267:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.center_lfe
ALSA lib pcm.c:2267:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.side
ALSA lib pcm_route.c:867:(find_matching_chmap) Found no matching channel map
ALSA lib pcm_route.c:867:(find_matching_chmap) Found no matching channel map
在使用 ALSA 时,我也会收到一两个关于欠载的投诉。
ALSA lib pcm.c:7905:(snd_pcm_recover) underrun occurred
我调用的 PortAudio 函数(Pa_Initialize
、Pa_OpenStream
、Pa_StartStream
、Pa_StopStream
、Pa_CloseStream
、Pa_Terminate
,按此顺序)都返回 paNoError
。
PortAudio 附带的paex_read_write_wire.c
(阻塞 I/O)示例通常可以访问设备,但也会遇到很多欠载(例如我的测试用例 2)。
无论哪种情况,dmesg
中都没有任何有趣的内容。 (刚刚检查过,因为 ALSA 有一个内核级组件。)
我的问题:
任何人都知道这里有什么问题以及我该如何解决它?或者至少,我怎样才能把范围缩小一点?
【问题讨论】:
请出示您的代码。 给你!非常感谢您的时间和努力! /// PortAudio(基于回调):pastebin.com/MrHpkXEA /// PortAudio(阻塞 I/O):pastebin.com/MDdUZ8W3 /// RtAudio(基于回调):pastebin.com/YCQ0JpSR FWIW,我在 Ubuntu 16.04.1 上使用简单的 PortAudio 应用程序遇到了同样的问题。我间歇性地收到此错误。确实非常令人沮丧! 我在 rasberian 上的 pyaudio 也有类似的问题。使用添加空帧的建议答案进行测试。 【参考方案1】:当您只写入一个样本块时,播放设备将在您即将写入下一个块时耗尽样本。
在开始读/写循环之前,您应该用零样本填充播放设备的缓冲区。
【讨论】:
谢谢!你确定这就是它与 PortAudio 的工作方式吗?这是一个实时 API。回调为您提供了一个输入和一个输出缓冲区以及一些帧,并且(据我所知)希望您从一个中读取该数量的帧并将该数量的帧写入另一个。我希望 API 在每个块上调用我,然后在我返回后将我写入的内容输出到输出缓冲区。 (所以调用每个块和 1 个块“延迟”,因为我处理的块总是在下一次迭代中输出。)这也是它在示例中的完成方式。我认为不涉及缓冲区。 理论上,实时 API 应该可以解决这个问题。 PortAudio 的示例程序有效吗? 就像我说的,我尝试了paex_read_write_wire.c
示例(因为,就像我的应用程序一样,它同时进行输入和输出,但它使用阻塞 I/O)。它不像我的那样“退出”,但它一直处于低速运行状态,并且输出严重失真。 paex_saw.c
中有示例代码,它使用回调机制输出锯齿波(但没有输入),这适用于板载声音(但也输出有关“无通道映射”的 ALSA 警告),但会导致大量欠载(和USB 接口上的失真)。请注意,USB 接口可以很好地与 ALSA 下的“普通”应用程序配合使用。
如果 PA 一开始就不起作用,那么您的程序将无能为力。
所以库本身坏了? (考虑到它很常见,这不是不太可能吗?)我该怎么办?尝试另一个库?我刚来自“普通 ALSA”,我遇到了严重的延迟问题,所以人们告诉我使用基于回调的 API。 (此外,ALSA 包含错误。已经偶然发现它们,但“解决了”。;-))我做了一些研究,发现 PortAudio 似乎被广泛使用,并且是为实时处理而设计的(这适合我的需要)。我想开发一些音频处理算法,但我正在处理的只是损坏的 API。 :-(【参考方案2】:
我不清楚细节,但对我来说,从默认的低输入/输出延迟切换到默认的高输入/输出延迟可以解决这个问题,而且我无法感知延迟的变化。
【讨论】:
以上是关于PortAudio 不可靠:表达式“...”失败的主要内容,如果未能解决你的问题,请参考以下文章
在 portaudio 中打开原始数据流(例如 tcpdump)
如何修复 PyAudio、PortAudio 的安装问题:“致命错误 C1083:无法打开包含文件:'portaudio.h':没有这样的文件或目录”