PulseAudio无法以一致的速率读取缓冲区

问题描述 投票:2回答:1

例如,我想实时记录我的麦克风并进行处理。显示麦克风信号的示波器视图。

我已经尝试了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都得到了不错的结果。为什么?

[另外,我查看了pavucontrolparec的来源,事实证明它们都使用asynchronous API,而我的两个示例程序都使用simple API。因此,问题并不完全是由于使用1个API或其他API,因为parec的行为类似于示例程序。

linux audio pulseaudio
1个回答
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。 (请注意,使用简单API时会自动设置PA_STREAM_ADJUST_LATENCY标志。)>

这应该使采样流更加流畅,但是由于pa_simple_read正在阻塞(等待直到整个缓冲区被填满),即使您使用较小的缓冲区进行读取,您仍然会增加延迟。要摆脱这种额外的延迟,您需要使用异步API进行非阻塞读取。

© www.soinside.com 2019 - 2024. All rights reserved.