Время между обратными вызовами?

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

Я рассчитал время и получил интересный результат

(при размере фрагмента 256, 44,1 КБ фс): 0,0099701;0,0000365;0,0000201;0,0201579

Этот шаблон продолжается и продолжается.

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

Если мы усредним это, мы получим желаемое время обратного вызова:

1/44100 * 256 (примерно 5,8 мс)

Вот визуализация моего измерения: введите здесь описание изображения

Так может кто-нибудь объяснить, что именно происходит здесь под капотом?


person function_store    schedule 22.04.2014    source источник


Ответы (1)


То, что происходит внутри PortAudio, зависит от ряда факторов, в том числе:

  • С каким нативным аудио API взаимодействует PortAudio
  • Какой размер буфера и параметры задержки вы передали Pa_OpenStream()
  • Возможности звукового оборудования и его драйверов, включая поддерживаемые размеры буфера, модель буферизации и временные характеристики.

В некоторых случаях PortAudio будет запрашивать буферы большего размера из собственного API аудио, а затем несколько раз быстро вызывать пользовательский обратный вызов PortAudio. Это может произойти, если вы выбрали небольшой размер буфера обратного вызова и большую задержку.

Другой сценарий заключается в том, что собственный API аудио не поддерживает размер буфера, запрошенный вами для размера обратного вызова (параметр framesPerBuffer для Pa_OpenStream()). В этом случае PortAudio будет вынужден использовать размер буфера, поддерживаемый драйвером, а затем «адаптироваться» между этим размером буфера и размером вашего буфера обратного вызова. Этот процесс адаптации может привести к нерегулярному времени.

Еще одна возможность заключается в том, что собственный аудио API использует большой кольцевой буфер. Каждый раз, когда PortAudio опрашивает собственный API хоста, он будет работать, чтобы заполнить собственный кольцевой буфер, вызывая ваш обратный вызов столько раз, сколько необходимо. В этом случае неравномерность синхронизации связана с частотой опроса.

Вышеупомянутые возможности не являются единственными.

Одним из вероятных объяснений того, что происходит в вашем случае, является то, что PortAudio вызывает ваш обратный вызов 3 раза в быстрой последовательности (можно предположить, что собственный размер буфера в 3 раза превышает размер буфера обратного вызова) по одной из причин, указанных выше.

Другая возможность заключается в том, что собственная звуковая подсистема нерегулярно передает сигнал PortAudio. Это может произойти, если системный уровень ниже PortAudio выполняет буферизацию, аналогичную описанной выше. Я видел, как это происходит, например, с DirectSound в Windows 7. Драйверы ASIO4ALL будут демонстрировать дрожание +/- 1 мс (это не то, что вы видите).

Вы можете попробовать уменьшить запрошенную задержку потока до 0 и посмотреть, изменит ли это результат. Это вызовет двойную буферизацию, которая может давать или не давать стабильный вывод. Еще одна вещь, которую можно попробовать, — это использовать параметр paFramesPerBufferUnspecified, который приведет к тому, что обратный вызов будет вызываться с собственным размером буфера — тогда вы сможете наблюдать, есть ли большая периодичность, каков этот размер буфера, а также отличается ли размер буфера от обратный звонок на обратный звонок.

Вы не сказали, на какую операционную систему и хост-API вы ориентируетесь, поэтому сложно дать более конкретные сведения, чем указано выше.

Модели внутренней буферизации, используемые различными бэкэндами хост-API PortAudio, подробно описаны на вики PortAudio. .

Чтобы ответить на связанный с этим вопрос: почему это так? Помимо случаев, когда это является функцией нижних уровней собственной звуковой подсистемы или процесса адаптации буфера, это часто является результатом указав большую рекомендуемую задержку для Pa_OpenStream(). Некоторые API-интерфейсы хоста PortAudio ослабляют периодичность буфера, если указанная задержка очень высока, чтобы уменьшить нагрузку на систему, которая может быть вызвана частыми обратными вызовами таймера.

person Ross Bencina    schedule 22.04.2014
comment
Спасибо за подробный ответ! В него вошли некоторые мысли, о которых мы подумали с моим консультантом :) Я на Win8 и использую версию, доступную на lfdi.uci.edu pythonlibs с довольно простыми настройками. Попробую предложенные варианты, еще раз спасибо! - person function_store; 23.04.2014
comment
Извините, что беспокою вас своим нубским вопросом, а как в PyAudio задать латентность или использовать параметр paFramesPerBufferUnspecified? Я использую исключительно PyAudio - person function_store; 29.04.2014
comment
@function_store Я не уверен, я никогда не использовал PyAudio. Чтобы получить paFramesPerBufferUnspecified, попробуйте передать 0 для framePerBuffer. - person Ross Bencina; 01.05.2014