CoreAudio:如何检测RemoteIO后面没有设备而不启动它?

Posted

技术标签:

【中文标题】CoreAudio:如何检测RemoteIO后面没有设备而不启动它?【英文标题】:CoreAudio: How to detect there's no device behind RemoteIO without starting it? 【发布时间】:2020-06-25 14:10:47 【问题描述】:

我正在尝试在没有麦克风的 Mac 上的 Catalyst 上使用 kAudioUnitSubType_RemoteIO 单元。

问题是,总线 1(即输入)的整个初始化都很好,包括设置格式,甚至启用总线,但随后它在 AudioOutputUnitStart(unit) 失败,出现一些模糊的错误 -66628,甚至没有列出osstatus.com.

但是,如果我仅使用输出总线 0 启动设备,则它运行良好并播放我的音频。

那么,有没有一种简单的方法可以在没有枚举所有设备的情况下检测 RemoteIO 后面没有设备的情况?只需尝试一些肯定会失败的功能(设置或获取参数?)。

这是我的代码:

    // Instantiate the unit
    var desc = AudioComponentDescription(componentType: kAudioUnitType_Output, componentSubType: kAudioUnitSubType_RemoteIO, componentManufacturer: kAudioUnitManufacturer_Apple, componentFlags: 0, componentFlagsMask: 0)
    let comp = AudioComponentFindNext(nil, &desc)!
    var unit: AudioUnit!
    NotError(AudioComponentInstanceNew(comp, &unit), 51000)

    // Set maximum buffer size as recommended by Apple
    var maxFramesPerSlice = UInt32(Self.maxFramesPerSlice)
    NotError(AudioUnitSetProperty(unit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 1, &maxFramesPerSlice, SizeOf(maxFramesPerSlice)), 51003)

    // Set format and sample rate to the same as hardware output
    var descr = AudiostreamBasicDescription.canonical(isStereo: true, sampleRate: hardwareSampleRate)
    NotError(AudioUnitSetProperty(unit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &descr, SizeOf(descr)), 51022)

    // Set render callback
    var callback = AURenderCallbackStruct(inputProc: stereoInputRenderCallback, inputProcRefCon: Bridge(obj: self))
    NotError(AudioUnitSetProperty(unit, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Output, 1, &callback, SizeOf(callback)), 51008)

    // Enable input - required as it's disabled by default
    var enable: UInt32 = 1
    NotError(AudioUnitSetProperty(unit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &enable, SizeOf(enable)), 51021)

    NotError(AudioUnitInitialize(unit), 51007)

所以它通过了所有这些并且只在OSStatus(-66628)这里失败:

    NotError(AudioOutputUnitStart(unit), 51009)

我认为在尝试启动设备之前必须有某种方法来检测设备的缺失。

编辑:理想情况下我正在寻找一种跨平台的方式(ioS/macOS)

【问题讨论】:

也许 kAudioDevicePropertyStreamConfigurationkAudioObjectPropertyScopeInput 并检查 mBuffers > 0? @sbooth 已经做了类似的事情。我在 RemoteIO 的两条总线的硬件端获得了格式描述符。如果总线后面没有设备,则格式结构全为零。例如,在 Mac Pro 和 Catalyst 下,我的麦克风全为零,因此似乎可以正常工作。 太好了,很高兴你能成功。我发布了我的建议作为答案,这样它就不会丢失。 【参考方案1】:

我相信检查为kAudioDevicePropertyStreamConfiguration, kAudioObjectPropertyScopeInput 返回的AudioStreamBasicDescription 是否具有mBuffers > 0 将表明设备是否存在。

【讨论】:

谢谢。虽然这需要一个 deviceID,但我不知道在 iOS、Catalyst 和 macOS 上获取当前输入 deviceID 的任何跨平台方法。有什么建议么?找了一阵子。 您说得对,这需要设备 ID。我不确定如何在 iOS 上获得一个。我知道您可以从 AVAudioSessionPortDescription 获得 UID,但我不确定是否可以转换为设备 ID(通常在 macOS 上我会使用 kAudioHardwarePropertyTranslateUIDToDevice),但我不知道 UID 是否相同。

以上是关于CoreAudio:如何检测RemoteIO后面没有设备而不启动它?的主要内容,如果未能解决你的问题,请参考以下文章

iphone 的音频单元代码错误 -remoteIO

Core Audio - 远程 IO 混乱

如何在 iPhone 的 Core Audio (Audio Unit/ Remote IO) 中将录制的声音更改为男人的声音

Core Audio - 多样本播放/录音

Core Audio(音频单元)音频会话和 MPVolumeView

如何在 AudioGraph 中将 RemoteIO、Mixer 和 Filter 连接在一起?