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,尽管我尝试更改为 paFloat32defaultHighInputLatency/defaultHighOutputLatency,其中没有任何改善)。

在每次调用回调时,它通过memcpysizeof(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_InitializePa_OpenStreamPa_StartStreamPa_StopStreamPa_CloseStreamPa_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 不可靠:表达式“...”失败的主要内容,如果未能解决你的问题,请参考以下文章

c ++和portaudio,输出严重失真

PortAudio-19 for mac

PortAudio 回调和 ASIO sdk 的输入延迟

在 portaudio 中打开原始数据流(例如 tcpdump)

如何修复 PyAudio、PortAudio 的安装问题:“致命错误 C1083:无法打开包含文件:'portaudio.h':没有这样的文件或目录”

pyaudio安装缺少文件问题error: portaudio.h: 没有那个文件或目录