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

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

Я рассчитал это, и получил интересный результат

(При размере фрагмента 256, 44,1 тыс. Фс): 0,0099701;0,0000365;0,0000201;0,0201579

Эта модель продолжается и продолжается.

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

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

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

Вот мое измерение визуализируется:

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

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 уменьшают периодичность буфера, если заданная задержка очень высока, чтобы уменьшить нагрузку на систему, которая может быть вызвана высокочастотными обратными вызовами таймера.

Другие вопросы по тегам