Developer Tools 入门 8m
天鹅任务第一章:黑暗中的声音
Swan's Quest, Chapter 1: Voices in the dark
2020年6月22日
一句话判断
Swan’s Quest 是苹果为 WWDC 2020 设计的交互式编程挑战——第一章用 AVFoundation 让你的设备「听懂」特定频率的声音,是一个巧妙地引导你学习音频编程的解谜游戏。
这场 Session 讲了什么
Swan’s Quest 是 WWDC 2020 的特殊活动,一个横跨四天的编程冒险游戏。玩家需要在 Swift Playgrounds 中完成一系列编程挑战,每个挑战对应一个 iOS 技术领域。
第一章「黑暗中的声音」的挑战是:用 AVAudioEngine 监听麦克风输入,检测特定频率的声音,然后用检测到的频率作为「密码」来解锁下一关。你需要理解音频频谱分析的基本概念,使用 AVAudioEngine 的 installTap 来捕获音频缓冲区,然后分析频率分量。
整个体验设计得很有趣——你写的代码会响应外部世界的声音(甚至可以对着手机吹口哨),这种交互感是传统教程做不到的。
值得深挖的点
音频频率检测的实现思路
核心是用 AVAudioEngine 的输入节点采集音频,通过 FFT(快速傅里叶变换)将时域信号转换为频域信号,找到能量最集中的频率分量。苹果在 Playground 中提供了部分辅助代码,但核心的频率检测逻辑需要你自己实现。
代码片段
import AVFoundation
// 基础的音频频率检测
class AudioDetector {
let engine = AVAudioEngine()
func startListening() {
let inputNode = engine.inputNode
let format = inputNode.outputFormat(forBus: 0)
// 安装音频采集节点
inputNode.installTap(onBus: 0, bufferSize: 1024, format: format) { buffer, time in
// 获取音频数据
let channelData = buffer.floatChannelData?[0]
let frameLength = Int(buffer.frameLength)
// 分析频率(简化版本)
// 实际需要用 FFT 或 vDSP 进行频谱分析
self.analyzeFrequency(data: channelData!, frameLength: frameLength)
}
try? engine.start()
}
func analyzeFrequency(data: UnsafePointer<Float>, frameLength: Int) {
// 计算音频信号的频率分量
// 简化示例:计算 RMS 能量来判断是否有声音
var sum: Float = 0
for i in 0..<frameLength {
sum += data[i] * data[i]
}
let rms = sqrt(sum / Float(frameLength))
if rms > 0.1 {
print("检测到声音,音量: \(rms)")
}
}
}
最佳实践
- 先跑通 Playground 再研究原理。Swan’s Quest 的乐趣在于动手,不要一开始就深究 FFT 的数学原理。先把代码跑起来,看到结果后再回头看为什么。
- 用真实的乐器或声音源测试。手机播放一个纯音(可以用在线频率发生器),比吹口哨更容易触发检测。
还有什么值得关注
- 完成第一章后会在 Swift Playgrounds 中解锁第二章的内容。
- 苹果在 Playground 的提示系统中嵌入了教学链接,点击可以跳转到相关的 WWDC Session。
- 这个系列的四章分别覆盖了:音频、UI、绘图和序列化,每一章都是独立的编程挑战。
WWDC 2020