Я видел аудио архитектуры, которые основаны на push и pull, и у обоих есть свои плюсы и минусы.
В системе на основе push, где каждый фильтр направляет данные вниз по потоку в фильтр downstream, вам нужно некоторое представление о синхронизации запросов push, чтобы у вас были данные в конце цепочки блоков обработки звука, когда звуковая карта готова для данных. Обычно это происходит в виде внешних часов, которые время прокачки вашего графика. DirectShow работает таким образом.
В системе, основанной на извлечении, вы можете использовать запросы ввода-вывода со звуковой карты, чтобы управлять прокачкой графика, что позволяет синхронизировать ваше устройство. В этой системе вам все равно понадобится буферизация в начале вашего графика (источники данных).
Я бы порекомендовал не делать систему, основанную на двухтактном режиме, а использовать архитектуру в стиле исполнителя Представьте, что у вас есть набор блоков обработки звука (APU), которые управляются объектом AudioGraph, который знает, как они связаны. Теперь вы можете использовать звуковые обратные вызовы со звуковой карты и передавать любые аудиовходы на ваш AudioGraph, и позволить AudioGraph управлять обработкой данных через каждый из блоков обработки звука. Это полностью отделяет поток данных от запросов ввода-вывода и позволяет вашему AudioGraph выполнять такие вещи, как распараллеливание запросов на обработку, запускать запросы для обработки каждого из фильтров не по порядку и т. Д. Кроме того, каждому APU не нужно знать о своих соседях. и они только «связаны вместе» на уровне AudioGraph. Это AudioUnits на OS X работает.