我想实时记录我的麦克风并进行处理,例如显示示波器视图的麦克风信号。
我尝试了3种方法从PulseAudio中获取数据,并且它们都执行相同的操作。我期望二进制流平稳,但是会有一种大致类似的模式:挂起〜300ms,打印一吨输出,重复。
3种不同的方式,2种不同的机器,相同的结果。
第一种方法是parec
。
第二种方法和第三种方法都是使用pulse-simple
库的C和Haskell中的hello世界。
C: https://freedesktop.org/software/pulseaudio/doxygen/parec-simple_8c-example.html#a7
Haskell:
import Sound.Pulse.Simple
import Control.Monad
import System.IO
main = do
s <- simpleNew Nothing "example" Record Nothing
"this is an example application"
(SampleSpec (F32 LittleEndian) 44100 1) Nothing Nothing
forever $ do
let numSamples = 4410
xs <- simpleRead s $ numSamples :: IO [Float]
putStrLn $ "hello"
hFlush stdout
在循环主体中刷新标准输出没有影响。
在循环中添加延迟会改变性能,但并不能达到我想要的效果。
以某种方式pavucontrol
VU计量器正确无误。我想念什么?
编辑:我发现在运行pavucontrol
时,无论是在示例程序中还是在parec
上,都能得到很好的结果。为什么?
我还查看了pavucontrol
和parec
的来源,结果发现它们都使用asynchronous
API,而我的2个示例程序都使用了simple
API。因此,问题并不完全是由于使用了1个API或其他API,因为parec
的行为类似于示例程序。
答案 0 :(得分:1)
调用pa_simple_new
时,请将fragsize
参数的pa_buffer_attr
字段设置为所需的等待时间(以字节为单位)。 PulseAudio将尝试实现该延迟,但可能无法达到该延迟,具体取决于硬件功能。
(pavucontrol可能要求较低的延迟。PulseAudio尝试达到所有当前正在运行的程序所要求的最低延迟,因此这就是在运行pavucontrol时记录延迟较低的原因。
在C中:
pa_buffer_attr attr;
attr.maxlength = (uint32_t) -1;
attr.tlength = (uint32_t) -1;
attr.prebuf = (uint32_t) -1;
attr.minreq = (uint32_t) -1;
attr.fragsize = 1600;
pa = pa_simple_new(NULL,
argv[0],
PA_STREAM_RECORD,
NULL,
"record",
&ss,
NULL,
&attr,
&error);
有关更多信息,请参见LatencyControl。 (请注意,PA_STREAM_ADJUST_LATENCY
标志是在使用简单API时自动设置的。)
这应该使采样流更加流畅,但是由于pa_simple_read
正在阻塞(等待直到整个缓冲区被填满),即使您使用较小的缓冲区进行读取,您仍然会增加延迟。为了消除这种额外的延迟,您需要使用异步API进行非阻塞读取。