在 macOS 中使用 CoreAudio 切换输出音频设备

Switching output audio device with CoreAudio in macOS

提问人:Чайка 提问时间:9/26/2023 最后编辑:Чайка 更新时间:9/30/2023 访问量:100

问:

我一直在使用 CoreAudio 切换输出设备进行音频输出,但这种技术在 macOS 13 Ventura 中不再可用。

如何在 Ventura 中切换输出设备?

正确的可用输出设备是

private func availableDevices() -> Array<AudioDeviceID> {
    var property: AudioObjectPropertyAddress = AudioObjectPropertyAddress(mSelector: kAudioHardwarePropertyDevices, mScope: kAudioObjectPropertyScopeGlobal, mElement: kAudioObjectPropertyElementMaster)
    var dataSize:UInt32 = 0
    let status: OSStatus = AudioObjectGetPropertyDataSize(AudioObjectID(kAudioObjectSystemObject), &property, 0, nil, &dataSize)
    var devices:Array<AudioDeviceID> = Array()
    if status != kAudioHardwareNoError {
        devices = Array()
    } else {
        let deviceCount: Int = Int(dataSize) / MemoryLayout<AudioDeviceID>.size
        var foundDevices: Array<AudioDeviceID> = Array<AudioDeviceID>(repeating: 0, count: deviceCount)
        foundDevices.withUnsafeMutableBufferPointer { ( item: inout UnsafeMutableBufferPointer<AudioDeviceID>) -> () in
            let error: OSStatus = AudioObjectGetPropertyData(AudioObjectID(kAudioObjectSystemObject), &property, 0, nil, &dataSize, item.baseAddress!)
            if error != kAudioHardwareNoError { print("each device ID Get Error: \(error)") }
        }// end withUnsafeMutableBufferPointer
        devices = Array(foundDevices)
    }// end if

    return devices
}// end availableDevices

并将输出音频设备分配给输出节点是

internal func assignAudioDeviceTo (engine audioEngine: AVAudioEngine, selector key: SpeechPreferenceKey) {
    let output: AVAudioOutputNode = audioEngine.outputNode
    if let audioUnit: AudioUnit = output.audioUnit {
        let audioDevices: AudioDevices = AudioDevices()
        var deviceID: AudioDeviceID = AudioDevices.currentOutputtDevice().deviceID
        if let deviceName: String = key.string {
            if let device = audioDevices.outputDevices[deviceName]?.deviceID { deviceID = device }
        }// end if output device name is defined
        let error: OSStatus = AudioUnitSetProperty(audioUnit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Output, 0, &deviceID, UInt32(MemoryLayout<AudioDeviceID>.size))
        if error != noErr {
            print("output device can not assign user selected device: \(error)")
        }// end if
        audioEngine.connect(audioEngine.mainMixerNode, to: output, fromBus: 0, toBus: 0, format: nil)
    }// end if output node have audio unit

    do {
        audioEngine.prepare()
        try audioEngine.start()
    } catch let error {
        print("output device start error: \(error)")
    }// end do try - catch start output device engine
}// end func assignAudioDeviceTo
macOS Core-音频

评论

0赞 soundflix 9/26/2023
您能否分享该已弃用方法的链接/文档/说明?
0赞 Чайка 9/26/2023
未弃用,不返回错误代码,但不起作用。
0赞 Чайка 9/28/2023
@soundflix developer.apple.com/documentation/audiotoolbox/......还行?
1赞 sbooth 9/28/2023
你试过吗?audioEngine.outputNode.auAudioUnit.setDeviceID()
0赞 Чайка 9/29/2023
@sbooth谢谢你的建议,它的工作,请重新写信回答将设置为最佳答案。

答:

2赞 sbooth 9/30/2023 #1

我不确定为什么你的方法不成功,但使用

audioEngine.outputNode.auAudioUnit.setDeviceID(deviceID)

在我的测试中有效。