Моя цель - написать аудио приложение для анализа аудио в реальном времени с малой задержкой в OSX. Это потребует подключения к одному или нескольким интерфейсам USB и получения определенных каналов от этих устройств.
Я начал с учебной аудиокниги и написал ее, используя C. Когда я шел по этому пути, выяснилось, что многие старые фреймворки устарели. Похоже, что большинство из того, чего я хотел бы достичь, может быть написано с использованием AVAudioengine и подключением AVAudioUnits, углубляясь в уровень звука ядра только для более низких вещей, таких как настройка аппаратных устройств.
Я не совсем понимаю, как получить доступ к двум устройствам одновременно. Я не хочу создавать агрегатное устройство, поскольку я хотел бы рассматривать устройства индивидуально.
Используя базовое аудио, я могу перечислить идентификатор аудиоустройства для всех устройств и изменить системное устройство вывода по умолчанию здесь (и могу сделать устройство ввода аналогичными способами). Однако это позволяет мне использовать только одно физическое устройство и всегда будет отслеживать устройство в системных настройках.
static func setOutputDevice(newDeviceID: AudioDeviceID) {
let propertySize = UInt32(MemoryLayout<UInt32>.size)
var deviceID = newDeviceID
var propertyAddress = AudioObjectPropertyAddress(
mSelector: AudioObjectPropertySelector(kAudioHardwarePropertyDefaultOutputDevice),
mScope: AudioObjectPropertyScope(kAudioObjectPropertyScopeGlobal),
mElement: AudioObjectPropertyElement(kAudioObjectPropertyElementMaster))
AudioObjectSetPropertyData(AudioObjectID(kAudioObjectSystemObject), &propertyAddress, 0, nil, propertySize, &deviceID)
}
Затем я обнаружил, что kAudioUnitSubType_HALOutput - это способ указать статическое устройство, доступное только через это свойство. Я могу создать компонент этого типа, используя:
var outputHAL = AudioComponentDescription(componentType: kAudioUnitType_Output, componentSubType: kAudioUnitSubType_HALOutput, componentManufacturer: kAudioUnitManufacturer_Apple, componentFlags: 0, componentFlagsMask: 0)
let component = AudioComponentFindNext(nil, &outputHAL)
guard component != nil else {
print("Can't get input unit")
exit(-1)
}
Однако я не совсем понимаю, как создать описание этого компонента, а затем найти следующее устройство, соответствующее описанию. Есть ли свойство, где я могу выбрать идентификатор аудиоустройства и связать AUHAL с этим?
Я также не могу понять, как назначить AUHAL для AVAudioEngine. Я могу создать узел для HAL, но не могу прикрепить это к движку. Наконец, возможно ли создать несколько компонентов kAudioUnitSubType_HALOutput и подать их в микшер?
Я пытался исследовать это на прошлой неделе, но нигде не приблизился к ответу. Я прочитал о картировании каналов и обо всем, что мне нужно знать, но на этом уровне получаю звук. нижний уровень кажется довольно недокументированным, особенно при использовании swift.