I want to record my microphone and process in real time, eg. show an oscilloscope view of the microphone signal.
I've tried 3 ways to get the data out of PulseAudio and they all perform the same. I expect a smooth stream of binary but instead there's a pattern roughly like: Hang for ~300ms, print a ton of output, repeat.
3 different ways, 2 different machines, same results.
The 1st way was parec
.
The 2nd and 3rd way are hello worlds in C and Haskell, both using the pulse-simple
library.
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
Flushing stdout in the loop body does not make a difference.
Adding a delay in the loop changes the performance but not to what I want.
Somehow the pavucontrol
VU meter gets it right. What am I missing?
EDIT: I discovered that while pavucontrol
is running, I get great results, both in my example programs and with parec
. Why??
Also, I looked at the source of pavucontrol
and parec
, and it turns out they both use the asynchronous
API, and my 2 example programs use the simple
API. So, the issue is not entirely due to the use of 1 API or the other, since parec
behaves like the example programs.