Откуда берется идентификатор объекта 0 в этом быстром коде, который должен передавать аудио с устройства ввода на устройство вывода? См. Сообщение об ошибке

#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. Ага. Есть ли у вас какие-либо идеи, почему существует такое ограничение? Кажется странным иметь библиотеку, предназначенную для подключения разных узлов, представляющих аудиоустройства, а затем сделать невозможным подключение этих устройств.