实时获取macOS输出设备音频缓冲区 [英] Get macOS Output Device Audio Buffers in Realtime

查看:100
本文介绍了实时获取macOS输出设备音频缓冲区的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在MacOS上点击当前选择的输出音频设备,因此我基本上有一个通过监听器,可以监听当前正在输出的音频流而不会对其造成影响.

我想将此数据实时复制到环形缓冲区,以便可以分别对其进行操作.

Apple文档和(过时的?)SO答案的组合对于我是否需要编写hacky的内核扩展,可以利用CoreAudio进行扩展还是需要与HAL进行接口而感到困惑?

如果可能的话,我想在Swift中工作.

非常感谢

(ps.我一直在查看

I'm trying to tap the currently selected output audio device on macOS, so I basically have a pass through listener that can monitor the audio stream currently being output without affecting it.

I want to copy this data to a ring buffer in real time so I can operate on it separately.

The combination of Apple docs and (outdated?) SO answers are confusing as to whether I need to write a hacky kernel extension, can utilise CoreAudio for this, or need to interface with the HAL?

I would like to work in Swift if possible.

Many thanks

(ps. I had been looking at this and this)

解决方案

I don't know about kernel extensions - their use of special "call us" signing certificates or the necessity of turning off SIP discourages casual exploration.

However you can use a combination of CoreAudio and HAL AudioServer plugins to do what you want, and you don't even need to write the plugin yourself, there are several open source versions to choose from.

CoreAudio doesn't give you a way to record from (or "tap") output devices - you can only record from input devices, so the way to get around this is to create a virtual "pass through" device (AudioServerPlugin), not associated with any hardware, that copies output through to input and then set this pass through device as default output and record from its input. I've done this using open source AudioServer Plugins like BackgroundMusic and BlackHole [TODO: add more].

To tap/record from the resulting device you can simply add an AudioDeviceIOProc callback to it or set the device as the kAudioOutputUnitProperty_CurrentDevice of an kAudioUnitSubType_HALOutput AudioUnit

There are two problems with the above virtual pass through device approach:

  1. you can't your hear output anymore, because it's being consumed by the pass through device
  2. changing default output device will switch away from your device and the tap will fall silent.

If 1. is a problem, then a simple is to create a Multi-Output device containing the pass through device and a real output device (see screenshot) & set this as the default output device. Volume controls stop working, but you can still change the real output device's volume in Audio MIDI Setup.app.

For 2. you can add a listener to the default output device and update the multi-output device above when it changes.

You can do most of the above in swift, although for ringbuffer-stowing from the buffer delivery callbacks you'll have to use C or some other language that can 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 vale of tears.

这篇关于实时获取macOS输出设备音频缓冲区的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆