PulseAudio не может считывать буферы с постоянной скоростью

Я хочу записать свой микрофон и обработать в режиме реального времени, например. покажите осциллограмму сигнала микрофона.

Я пробовал 3 способа получить данные из PulseAudio, и все они работают одинаково. Я ожидаю гладкого потока двоичных файлов, но вместо этого есть шаблон примерно такой: зависание ~ 300 мс, печать тонны вывода, повтор.
3 разных способа, 2 разных машины, одинаковые результаты.

Первый способ был parec.

2-й и 3-й способ — привет миры на C и Haskell, оба используют библиотеку pulse-simple.

C: https://freedesktop.org/software/pulseaudio/doxygen/parec-simple_8c-example.html#a7

Хаскелл:

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 волюметр делает это правильно. Что мне не хватает?

РЕДАКТИРОВАТЬ: я обнаружил, что во время работы pavucontrol я получаю отличные результаты как в моих примерах программ, так и с parec. Почему??

Кроме того, я посмотрел на источник pavucontrol и parec, и оказалось, что они оба используют asynchronous API, а мои 2 примера программ используют simple API. Таким образом, проблема не полностью связана с использованием 1 API или другого, поскольку parec ведет себя как программы-примеры.


person PizzaBeer    schedule 19.05.2019    source источник
comment
попробуйте отправить сообщение на dsp.stackexchange.com . Удачи.   -  person shellter    schedule 20.05.2019


Ответы (1)


При вызове pa_simple_new установите в поле fragsize аргумента pa_buffer_attr желаемую задержку в байтах. PulseAudio попытается достичь этой задержки, но может не достичь ее в зависимости от возможностей оборудования.

(pavucontrol, вероятно, запрашивает низкую задержку. PulseAudio пытается достичь минимальной задержки, запрашиваемой всеми запущенными в данный момент программами, поэтому задержка записи при работе pavucontrol низкая).

In 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 для неблокирующего чтения.

person Pulse    schedule 15.12.2019