【问题标题】:How to set AVAudioEngine input and output devices (swift/macos)如何设置AVAudioEngine输入输出设备(swift/macos)
【发布时间】:2020-09-01 18:58:08
【问题描述】:

我到处寻找,找不到解决这个问题的方法。我正在寻找一种方法来更改 AVAudioEngine 将在 macOS 上使用的输入/输出设备。

当简单地播放音频文件时,以下工作按预期工作:

var outputDeviceID:AudioDeviceID = xxx 
let result:OSStatus = AudioUnitSetProperty(outputUnit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &outputDeviceID, UInt32(MemoryLayout<AudioObjectPropertyAddress>.size))
if result != 0  {
   print("error setting output device \(result)")
   return
}

但是,如果我初始化音频输入(使用let input = engine.inputNode),那么一旦我尝试启动引擎就会出现错误:

AVAEInternal.h:88 所需条件为假:[AVAudioEngine.mm:1055:CheckCanPerformIO: (canPerformIO)]

我知道我的播放代码没问题,因为如果我避免更改输出设备,那么我可以听到麦克风和音频文件,如果我更改输出设备但不初始化 inputNode 文件播放到指定的目的地。

除此之外,我一直在尝试更改输入设备,我从各个地方了解到以下应该这样做:

let result1:OSStatus = AudioUnitSetProperty(inputUnit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Output, 0, &inputDeviceID, UInt32(MemoryLayout<AudioObjectPropertyAddress>.size))
if result1 != 0  {
    print("failed with error \(result1)")
    return
}

但是,这不起作用 - 在大多数情况下,它会引发错误 (10853),尽管如果我选择一个同时具有输入和输出的声卡,它会成功 - 当我尝试设置输出或输入节点它实际上是为两者设置设备。

我认为这意味着AVAudioEngine 实例只能处理一个设备,但是它很高兴使用默认设备(麦克风和扬声器/耳机),所以我相信这不是问题。查看一些解决方案,我在网上看到人们只是更改了默认输入,但这并不是一个非常好的解决方案。

有人对这是否可能有任何想法吗?

值得注意的是kAudioOutputUnitProperty_CurrentDevice 是唯一可用的属性,没有等效的kAudioInputUnitProperty_CurrentDevice 键,因为据我了解inputNodeoutputNode 都被归类为“输出单元” "(因为它们都在某处发出声音)。

任何想法都将不胜感激,因为这非常令人沮丧!

谢谢

【问题讨论】:

  • 我也用 inputNode.auAudioUnit.setDeviceID(xxx) 试过这个,似乎有同样的问题。据我所知,您只能在以下情况下离开默认音频设备:a)您只输出音频,或 b)您使用一个设备进行输入和输出..
  • 您找到解决方案了吗?我遇到了完全相同的问题...
  • 收到了苹果的回复 - 会回答的..

标签: swift macos core-audio avaudioengine


【解决方案1】:

所以我就这个问题和另一个问题向苹果提交了支持请求,响应确认 AVAudioEngine 只能分配给单个聚合设备(即具有输入和输出通道的设备)-系统默认单位在内部有效地创建一个聚合设备,这就是它们工作的原因,尽管我发现了一个额外的问题,即如果输入设备也具有输出功能(并且您激活了 inputNode),那么该设备必须既是输入设备又是输出设备否则输出似乎不起作用。

所以答案是我认为没有答案..

【讨论】:

  • 我想知道是否可以将输入设备的AUAudioUnit 包装在AVAudioSourceNode 中并用它来代替inputNode。我写了一些看起来很有希望但不能正常工作的代码,但这种方法是可行的。
  • 我试过了,但您似乎无法通过这种方式将硬件输入到音频引擎中。我认为解决方案是创建一个单独的 AudioUnit,将其写入缓冲区并使用播放器节点在缓冲区中读取,但我还没有机会尝试这个。 Apple 的 CoreAudio “Play Through” 示例可以做到这一点,但没有引擎,而且延迟似乎非常低。我尝试在 inputNode 上点击,但延迟至少为 100 毫秒
  • 感谢您记录您发现的所有内容。我也在为此苦苦挣扎,尝试使用输入设备 A 并通过输出设备 B 播放它,并尝试了您描述的许多事情。您对此有进一步了解吗?你知道像 GarageBand 这样的应用程序是如何做到的吗?我将尝试找到 CoreAudio“播放”示例...
  • 我相信大多数人都在做 Play Through 示例所做的事情,即写入缓冲区,然后从缓冲区读取到另一个设备 - 这就是我最终不得不做的事情
猜你喜欢
  • 2015-05-01
  • 2019-03-19
  • 1970-01-01
  • 2016-05-02
  • 1970-01-01
  • 2021-06-29
  • 1970-01-01
  • 1970-01-01
  • 2022-11-18
相关资源
最近更新 更多