#swift #core-audio #avaudioengine
#быстрый #core-audio #avaudioengine
Вопрос:
Я довольно новичок в этом и пытаюсь учиться, поэтому, пожалуйста, извините, если следующее неверно, но я думаю, что это должно быть:
- инициализировать узел ввода и вывода
- создайте аудиоустройство для каждого узла
- назначьте «currentDevice» определенного идентификатора устройства для каждого аудиоустройства
- подключите вход и выход
func start() {
let engine = AVAudioEngine()
let inputNode = engine.inputNode
let outputNode = engine.outputNode
guard let inputUnit: AudioUnit = inputNode.audioUnit else { return }
guard let outputUnit: AudioUnit = outputNode.audioUnit else { return }
var inputDeviceID: AudioDeviceID = 46 // External input device
var outputDeviceID: AudioDeviceID = 57 // Mac mini speakers
AudioUnitSetProperty(inputUnit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, amp;inputDeviceID, UInt32(MemoryLayout<AudioDeviceID>.size))
AudioUnitSetProperty(outputUnit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, amp;outputDeviceID, UInt32(MemoryLayout<AudioDeviceID>.size))
let bus = 0
engine.connect(inputNode, to: outputNode, fromBus: bus, toBus: bus, format: nil)
engine.prepare()
do {
try engine.start()
} catch {
print("error")
}
}
Когда я запускаю это, журналы заполняются:
AudioObjectGetPropertyDataSize: no object with given ID 0
AudioObjectGetPropertyData: no object with given ID 0
AudioObjectGetPropertyDataSize: no object with given ID 0
AudioObjectGetPropertyData: no object with given ID 0
AudioObjectGetPropertyDataSize: no object with given ID 0
AudioObjectGetPropertyData: no object with given ID 0
...
Откуда берется этот идентификатор 0?
Если я закомментирую либо AudioUnitSetProperty(...)
то, либо другое, ошибки не произойдет.
Что я здесь делаю не так?
Ответ №1:
То, что вы делаете, выглядит для меня правильно, хотя я обычно делаю это с помощью AUAudioUnit
:
try inputNode.AUAudioUnit.setDeviceID(inputDeviceID)
try outputNode.AUAudioUnit.setDeviceID(outputDeviceID)
Однако я не знаю, что в этом случае это будет иметь значение.
Ранее существовало недокументированное ограничение на AVAudioEngine
ограничение одновременного ввода и вывода на системное устройство по умолчанию (https://www.mail-archive.com/coreaudio-api@lists.apple.com/msg01663.html ). Я не уверен, что это ограничение все еще присутствует в Big Sur.
Один из возможных обходных путей (у меня еще не было возможности попробовать) — создать агрегированное устройство, содержащее устройства ввода и вывода, которые вы хотите, и использовать с этим устройством AVAudioEngine
.
AudioObjectID
0 kAudioObjectUnknown
. Я подозреваю, что ваша попытка установить устройство привела к сбою движка в состояние ошибки.
Комментарии:
1. Спасибо за быстрый ответ. Это полезно, особенно для чтения, что я на правильном пути. Два вопроса: 1) Об этом ограничении AVEngine, ограничивающем одновременный ввод и вывод, как работают такие приложения, как GarageBand? На панели настроек GarageBand есть возможность выбрать устройство вывода и устройство ввода, которые вообще не связаны с системными устройствами. Я в основном пытаюсь сделать это без остальной части GarageBand. Я подумал, что это будет возможно , потому что GarageBand может это сделать.
2. 2) Когда вы предлагаете создать агрегатное устройство, это то, что я бы сделал программно? Или вы имеете в виду включить в утилите Audio Midi?
3. Просто чтобы было ясно, что я пытаюсь сделать: существует приложение под названием BlackHole, которое создает программное аудиоустройство, которое можно выбрать в качестве устройства вывода в качестве средства передачи звука в приложения в качестве устройства ввода. Я хочу взять этот звук и отправить его обратно на реальное устройство вывода. Преимущество этого в том, что он предоставит системе доступ к регулятору громкости. Я использую этот проект как предлог, чтобы узнать больше об AVAudioEngine, так что это вторичная цель этого. Опять же, я ценю ваш ответ. Трудно найти информацию о чем-либо из этого.
4. GarageBand может использовать или не использовать
AVAudioEngine
under the hood; если это так, он может использовать private API. Вы можете создавать агрегированные устройства программно, используяAudioHardwareCreateAggregateDevice
, хотя я бы сначала попробовал AMS, чтобы посмотреть, действительно ли это будет работать для вас.5. Ага. Есть ли у вас какие-либо идеи, почему существует такое ограничение? Кажется странным иметь библиотеку, предназначенную для подключения разных узлов, представляющих аудиоустройства, а затем сделать невозможным подключение этих устройств.