Meet Audio Workgroups
Audio & Video 高级 20m

认识 Audio Workgroups

Meet Audio Workgroups

2020年6月25日

在 Apple 官方观看视频

一句话判断

如果你在开发专业音频应用(DAW、音频处理器),Audio Workgroups 是你降低端到端延迟、提升多线程音频处理性能的关键新 API。

这场 Session 讲了什么

这场 Session 介绍了 macOS Big Sur 和 iOS 14 中全新的 Audio Workgroups 机制。在专业音频场景中,低延迟是核心需求——音乐人按下琴键到听到声音,延迟必须控制在几毫秒以内。传统做法是用单一的 Audio Unit 在实时音频线程中处理所有工作,但这对 CPU 的利用效率很低。

Audio Workgroups 允许开发者将多个 Audio Unit 组织成一个工作组,系统会以协调的方式调度这些 Audio Unit 的渲染。这意味着你可以将音频处理流水线拆分成多个阶段,每个阶段在不同的线程上执行,而系统保证整体渲染的时序一致性。演讲者用一个虚拟乐器插件的实际案例展示了从单个复杂 Audio Unit 拆分成多个轻量 Workgroup Member 的过程。

Session 还讨论了 Workgroup 与 Core Audio 底层调度器的交互方式,以及如何利用这个机制在不增加延迟的前提下充分利用多核 CPU。对于插件开发者来说,这意味着同一个插件在 8 核 Mac 上的性能可以接近线性提升。

值得深挖的点

  • Workgroup 调度器的时序保证:普通的多线程音频处理最大的问题是无法保证线程间的同步——如果上游线程还没渲染完,下游线程就必须等待,导致 buffer underrun。Audio Workgroups 的调度器会追踪整个渲染图的数据依赖,确保所有渲染操作在音频硬件需要数据之前完成。
  • 从 AUv2 到 AUv3 的迁移考量:Audio Workgroups 主要在 AUv3(App Extension 模型)中工作。如果你还在用 AUv2(传统 Component Manager 模型),迁移到 AUv3 不仅能获得 Workgroup 支持,还能获得更好的进程隔离和稳定性。

代码片段

// 创建 Audio Workgroup 并添加成员
import AVFoundation

// 获取当前 Audio Unit 的 Workgroup
func createRenderContext() -> AUAudioUnit {
    let audioUnit = MyCustomAudioUnit(
        componentDescription: AudioComponentDescription(
            componentType: kAudioUnitType_MusicDevice,
            componentSubType: 0x736e7468  // 'snth'
        )
    )

    // 在渲染回调中使用 Workgroup 信息
    audioUnit.renderBlock = { [weak self] actionFlags, timestamp, frameCount, outputData in
        guard let self = self else { return noErr }
        // 在 Workgroup 上下文中执行渲染
        return self.render(frames: frameCount, to: outputData)
    }
    return audioUnit
}
// Audio Unit Extension 中的 Workgroup 实现
class WorkgroupManagedAudioUnit: AUAudioUnit {
    private var workgroup: AUScheduleWorkgroup?

    override func allocateRenderResources() throws {
        try super.allocateRenderResources()
        // 创建 Workgroup 用于非实时音频任务
        workgroup = AUScheduleWorkgroup(name: "AudioProcessing")
    }

    func scheduleProcessing(
        block: @escaping () -> Void
    ) {
        // 在 Workgroup 线程池中调度非实时任务
        workgroup?.schedule(block)
    }
}
// C API 层面的 Workgroup 使用(适用于基于 C 的音频插件)
#include <AudioToolbox/AudioWorkgroup.h>

void setupWorkgroup(AudioUnit au) {
    AudioWorkgroupRef workgroup;
    OSStatus status = AudioWorkgroupCreate(&workgroup);

    // 将渲染线程加入 Workgroup
    AudioWorkgroupAddMember(workgroup, pthread_self());

    // 在渲染循环中协调多线程
    AudioWorkgroupStart(workgroup);
    // ... 执行渲染 ...
    AudioWorkgroupEnd(workgroup);
}

最佳实践

  • 实时音频线程中绝不分配内存、不使用锁、不调用可能阻塞的系统函数——这条铁律在 Workgroup 时代依然适用
  • 将 CPU 密集型处理(如 FFT、卷积混响)拆分到 Workgroup 的非实时线程中,实时线程只做最小化的数据搬运
  • 使用 Instruments 的 Audio模板来测量 Workgroup 调度效率,确认你的拆分策略是否真的减少了延迟
  • 测试时使用不同的 buffer size(64、128、256 samples)验证 Workgroup 在各种延迟要求下的表现

还有什么值得关注

  • Audio Workgroups 与 macOS 的 Power Management 有深度交互,会影响 CPU 的频率调度策略
  • 如果你在做 AUv3 插件,关注一下 Xcode 12 中 Audio Unit 模板的变化
  • 搭配 “Record stereo audio with AVAudioSession” 和 “What’s new in streaming audio for Apple Watch” 一起看,可以全面了解 2020 年 Apple 音频生态的更新
WWDC 2020