То, что происходит внутри 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