Я пытаюсь подключиться к выбранному в данный момент выходному аудиоустройству в macOS, поэтому у меня в основном есть сквозной прослушиватель, который может отслеживать аудиопоток, который в данный момент выводится, не затрагивая его.
Я хочу скопировать эти данные в кольцевой буфер в режиме реального времени, чтобы иметь возможность работать с ними отдельно.
Сочетание документов Apple и (устаревших?) ответов SO сбивает с толку относительно того, нужно ли мне писать хакерское расширение ядра, могу ли я использовать для этого CoreAudio или нужно взаимодействовать с HAL?
Я хотел бы работать в Swift, если это возможно.
Большое спасибо
(ps. Я смотрел на это и это)
Я не знаю о расширениях ядра - их использование специальных сертификатов подписи «позвоните нам» или необходимость отключения SIP препятствует случайному исследованию.
Однако вы можете использовать комбинацию плагинов CoreAudio и HAL AudioServer, чтобы делать то, что вы хотите, и вам даже не нужно писать плагин самостоятельно, есть несколько версий с открытым исходным кодом на выбор.
CoreAudio не дает вам возможности записывать с устройств вывода (или «касаться») — вы можете записывать только с устройств ввода, поэтому способ обойти это — создать виртуальное «сквозное» устройство (AudioServerPlugin), а не связанный с любым оборудованием, которое копирует вывод на вход, а затем устанавливает это сквозное устройство в качестве вывода по умолчанию и записывает с его входа. Я сделал это, используя плагины AudioServer с открытым исходным кодом, такие как BackgroundMusic и BlackHole [СДЕЛАТЬ: добавить больше].
Чтобы коснуться / записать с полученного устройства, вы можете просто добавить к нему обратный вызов AudioDeviceIOProc
или установить устройство в качестве kAudioOutputUnitProperty_CurrentDevice
для kAudioUnitSubType_HALOutput
AudioUnit
Есть две проблемы с описанным выше подходом к виртуальному сквозному устройству:
Если 1. является проблемой, то просто создать устройство с несколькими выходами, содержащее сквозное устройство и реальное устройство вывода (см. снимок экрана), и установить его в качестве устройства вывода по умолчанию. Регуляторы громкости перестают работать, но вы все еще можете изменить реальную громкость устройства вывода в Audio MIDI Setup.app
.
Для 2. вы можете добавить прослушиватель к устройству вывода по умолчанию и обновить устройство с несколькими выходами выше, когда оно изменится.
Вы можете сделать большую часть вышеперечисленного в быстром режиме, хотя для хранения кольцевого буфера из обратных вызовов доставки буфера вам придется использовать C или какой-либо другой язык, который может соблюдать правила аудио в реальном времени (без блокировок, без выделения памяти и т. д. ). Возможно, вы могли бы попробовать AVAudioEngine
сделать тап, но смена устройства ввода IIRC — это юдоль слез.
Точно. Вы уверены, что Blackhole может перенаправлять звук из отдельных приложений? Это больше похоже на петлю RA.
Да, честно говоря, у меня установлен Loopback, поэтому я объединил их в своем уме!
Если у вас есть петля, вы настраиваете свое устройство так, чтобы оно имело только один источник: приложение, и вы записываете с устройства, используя методы, описанные в ответе. Я не упомянул петлю в ответе. Я считаю, что он использует совсем другой метод.
да, причина, по которой я не могу использовать Loopback в решении, в первую очередь заключается в том, что я хочу распространять это приложение среди других пользователей и не могу гарантировать, что у них будет Loopback или ноу-хау для его настройки. Я все еще обдумываю то, что вы написали, потому что, я думаю, будет хороший компромисс с использованием устройства с несколькими выходами.
это действительно всеобъемлющий обзор, спасибо. Что насчет этого: 1. при запуске программы я определяю текущее устройство вывода по умолчанию. 2. программно изменить текущее устройство вывода по умолчанию на виртуальный AU, который является просто прокси для исходного устройства вывода по умолчанию. 3. привяжите прослушиватель к событию изменения устройства вывода и измените то, что делегирует прокси-сервер 4. всегда заставляйте устройство вывода быть прокси-сервером во время работы программы (при любом изменении). Моя другая альтернатива — использовать Blackhole и попросить пользователя выбрать конкретное приложение в качестве источника звука, например Spotify или Skype и т. д.?