我的目标是编写一个用于在OSX上进行低延迟实时音频分析的音频应用程序。这将涉及连接到一个或多个USB接口,并从这些设备获取特定通道。
我从学习核心音频书开始,并使用C编写此书。当我沿着这条路走时,发现许多旧框架已被弃用。看来,我想实现的大部分目标都可以使用AVAudioengine并连接AVAudioUnits来编写,仅针对诸如配置硬件设备之类的较低层次而深入研究核心音频级别。
我对如何同时访问两个设备感到困惑。我不想创建聚合设备,因为我想单独对待这些设备。
使用核心音频,我可以列出所有设备的音频设备ID,并在此处更改默认系统输出设备(并可以使用类似方法来输入设备)。但是,这只允许我使用一个物理设备,并且将始终按照系统偏好设置跟踪该设备。
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)
}
但是,我对如何创建此组件的描述然后找到与该描述匹配的下一个设备感到困惑。是否可以选择音频设备ID并将AUHAL链接到该属性?
我也无法弄清楚如何将AUHAL分配给AVAudioEngine。我可以为HAL创建一个节点,但不能将此节点附加到引擎。最后,是否可以创建多个kAudioUnitSubType_HALOutput组件并将其馈入混音器?
上周我一直在尝试对此进行研究,但距离答案还很遥远。我已经阅读了有关通道映射以及所有我需要了解的内容,但是在这个级别上可以得到音频。较低级别的文件似乎没有记载,尤其是在使用swift时。