实时获取 macOS 输出设备音频缓冲区

Get macOS Output Device Audio Buffers in Realtime

我正在尝试 点击 当前在 macOS 上选择的输出音频设备,所以我基本上有一个直通监听器可以监视当前正在输出的音频流而不影响它.

我想把这个数据实时复制到一个环形缓冲区,这样我就可以单独对其进行操作了。

Apple 文档和(过时的?)SO 答案的组合让我感到困惑,我是否需要编写一个 hacky 内核扩展,可以为此使用 CoreAudio,还是需要与 HAL 接口?

如果可能,我想在Swift工作。

非常感谢

(ps。我一直在看this and this)

我不知道内核扩展 - 它们使用特殊的“呼叫我们”签名证书或关闭 SIP 的必要性阻碍了随意探索。

但是你可以使用CoreAudio和HAL AudioServer插件的组合来做你想做的事情,你甚至不需要自己写插件,有几个开源版本可供选择。

CoreAudio 没有为您提供从(或“点击”)输出设备进行录音的方法 - 您只能从输入设备进行录音,因此解决此问题的方法是创建一个虚拟的“直通”设备(AudioServerPlugin),不与任何硬件关联,将输出复制到输入,然后将此传递设备设置为默认输出并从其输入记录。我已经使用 BackgroundMusic and BlackHole [TODO: add more].

等开源 AudioServer 插件完成了此操作

从生成的设备tap/record,您可以简单地向它添加一个AudioDeviceIOProc回调或将设备设置为kAudioUnitSubType_HALOutput[=13=的kAudioOutputUnitProperty_CurrentDevice ]

上述虚拟直通设备方法存在两个问题:

  1. 你不能再听到输出了,因为它正在被直通设备消耗掉
  2. 更改默认输出设备会从您的设备切换开,并且点击会停止。

如果 1. 有问题,那么一个简单的方法就是创建一个包含直通设备和一个真实输出设备的多输出设备(见屏幕截图)并将其设置为默认输出设备。音量控制停止工作,但您仍然可以在 Audio MIDI Setup.app.

中更改实际输出设备的音量

对于2.你可以在默认输出设备上添加一个监听器,当它发生变化时更新上面的多输出设备。

您可以在 swift 中执行上述大部分操作,但对于从缓冲区传送回调中装载环形缓冲区,您必须使用 C 或其他一些可以 respect the realtime audio rules (no locks, no memory allocation, etc). You could maybe try AVAudioEngine to do the tap, but IIRC changing input device is a 的语言。