Время go Я играл с концептуальным игровым аудиомиксером в C. Ничего из этого не закончено, но вещи действительно работают. Библиотека использует самый низкий из доступных Core Audio API, таким образом, действительно, с такими вещами, как AudioDeviceCreateIOProcID
и AudioObjectAddPropertyListener
.
Короче говоря, эта игровая площадка позволяет мне использовать несколько аудиоустройств, известных MacOS, и маршрутизировать один или несколько аудио потоки между ними, проходя через различные виды «узлов» на этом пути (например, представьте себе узел матричного микшера).
Сначала, в ответ на ваши вопросы
AudioDeviceStart()
инициированные обратные вызовы будет запускать каждый из другого (случайного) потока. Кроме того, обратные вызовы не будут вызываться в определенном порядке c. Я также обнаружил, что разница между обратными вызовами может сильно различаться (по-видимому, в зависимости от аудиоустройства, предоставляющего / запрашивающего данные). Чтобы решить эту проблему, я использовал безблокировочный (то есть, использующий счетчики Atomi c) кольцевой буфер.
Ваша озабоченность по поводу различных часовых доменов очень реальна. Два устройства, работающие на частоте 96 кГц, будут работать на разных скоростях. Это может go хорошо в течение долгого времени, но в конечном итоге у одного из них закончатся данные и начнется сбой. Если внешние устройства не синхронизируются друг с другом, например, с помощью слова или ptp, они будут работать в своем собственном временном домене. Для передачи аудио между разными временными областями вам нужно будет asyn c -sample-rate-преобразовать аудиоданные. И SR C должен будет иметь возможность конвертировать в очень маленьких крыс ios и корректировать по пути. Одним из тех, кто делает это очень хорошо, является Soxr . В мире Core Audio есть VarispeedNode, который позволяет вам делать в основном то же самое. Большим недостатком решения asyn c -sr c является задержка, которую он вводит, однако, возможно, вы могли бы указать «низкую задержку».
В вашем случае синхронизация различных аудиоустройств будет самая большая проблема В моем случае я обнаружил, что обратные вызовы различных аудиоустройств слишком сильно различаются, чтобы выбрать один из них для «синхронизации часов», поэтому в итоге я создал автономную временную область, тщательно рассчитав время выполнения цикла обработки. Для этого я использовал низкоуровневые механизмы синхронизации, такие как mach_wait_until()
и mach_absolute_time()
(документации по этому вопросу немного).
Агрегированные устройства
Однако может быть другое решение. Глядя на документацию в AudioHardware.h
от платформы CoreAudio, кажется, что есть способ создать агрегатное устройство программно с использованием AudioHardwareCreateAggregateDevice()
. Это позволяет MacOS управлять синхронизацией различных аудиоустройств. Также обратите внимание на ключ kAudioAggregateDeviceIsPrivateKey
, который позволяет вам создавать агрегатное устройство, не публикуя его во всей системе. Таким образом, устройство не будет отображаться в Audio MIDI Setup (я думаю). Также обратите внимание, что этот ключ приводит к исчезновению агрегата, когда процесс, который его создал, останавливается. Это может или не может быть то, что вам нужно, но это будет очень надежный способ реализации с использованием нескольких аудиоустройств. Если бы мне снова пришлось писать программное обеспечение, я бы определенно изучил этот способ синхронизации.
Прочие полезные советы и подсказки
В целом при работе с аудио с низкой задержкой вы хотите достичь максимально детерминированное поведение c. Но я уверен, что вы знаете об этом.
Другой недостаток заключается в том, что документация API Core Audio недоступна на сайте разработчика Apple (https://developer.apple.com/documentation/coreaudio/core_audio_functions?language=objc). Для этого вам нужно погрузиться в заголовки платформы Core Audio, где вы найдете много полезной документации по использованию API.
На моей машине заголовки расположены по адресу: /Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/CoreAudio.framework/Versions/A/Headers
Дополнительное чтение:
http://atastypixel.com/blog/four-common-mistakes-in-audio-development http://www.rossbencina.com/code/real-time-audio-programming-101-time-waits-for-nothing https://developer.apple.com/library/archive/qa/qa1467/_index.html