1

我有一个不断输出 PCM 数据的设备。在某些情况下,我想记录此输出。为此,我有一个等待信号记录的进程,当它收到信号时,它启动一个线程(通过pthread_create)。此线程打开 PCM 设备并使用snd_async_add_pcm_handler. 此处理程序 fn 用于pcm_readi获取 PCM 流中的任何可用信息并将其写入磁盘。

一切都很好 - 除了

一旦它开始运行,我的调用进程就会停止任何循环。它应该继续监听下一个发出停止录制信号的事件。看着执行,我发现它很慢,然后在 PCM 录制开始后停止。如果我不开始录制,应用程序会正常运行并继续响应。

所以看起来我有两条途径:

  1. 发现录制过程中的差距和usleep(或类似的)给调用应用程序时间响应
  2. 尝试使用其他方式退出录制

我没有使用#1 取得任何进展,所以我正在研究#2。众所周知,音频样本将以低幅度开始,然后变高一两秒钟,然后再变低。我正在使用滚动平均值来捕获这个低-高-低,并试图关闭异步 IO。

它的位置:一旦 IO 应该停止,我尝试调用snd_async_del_handler,但这会使应用程序崩溃,并显示一个简单的“IO 可能”消息。我也尝试过调用snd_pcm_drop,但这不会关闭异步 io,因此它会在下次尝试读取时崩溃。以任一顺序组合两者都会给出相似的响应。

我错过了哪些步骤?

4

1 回答 1

3

* 函数被snd_async_强烈弃用,因为它们不适用于所有类型的设备,难以使用,并且在实践中没有任何优势。

请注意,ALSA API不是线程安全的,即对一个 PCM 设备的调用必须全部来自一个线程,或者是同步的。

你应该做的是poll在你的线程中有一个事件循环(使用)来处理 PCM 设备和来自主线程的退出消息。为此,PCM 设备应该在非阻塞模式下运行(使用snd_pcm_poll_descriptors* 函数)。要向线程发送消息,请使用任何具有poll文件句柄的机制,例如管道或eventfd.

于 2013-02-14T20:12:25.540 回答