环境
iOS 18
Xcode 16.3
swift-driver version: 1.120.5 Apple Swift version 6.1 (swiftlang-6.1.0.110.21 clang-1700.0.13.3)
Target: x86_64-apple-macosx15.0
Core Audio 的架构
声音数据的描述
sample: 一个声道采样的值,采样率定义了每秒从连续信号中提取并组成离散信号的采样个数,它用赫兹(Hz)来表示。
frame: 一个时间常量内的sample的集合
packet: 一个或多个连续的帧
AudioStreamBasicDescription
1 | // CoreAudioBaseTypes.h |
1 | CF_ENUM(AudioFormatID) |
1 | CF_ENUM(AudioFormatFlags) |
About the name: Although this data type has “stream” in its name, you use it in every instance where you need to represent an audio data format in Core Audio—including in non-streamed, standard files. You could think of it as the “audio format basic description” data type. The “stream” in the name refers to the fact that audio formats come into play whenever you need to move (that is, stream) audio data around in hardware or software.
类型中的stream只是表示播放的概念,这里定义的就是iOS音频格式的描述
获取声音的格式信息
1 | public func audioFormat() -> AudioStreamBasicDescription? { |
我加载的是一个44.1kHz,双声道的mp3文件
778924083 = 0x2E6D7033 => “.mp3”
AudioStreamPacketDescription
1 | // CoreAudioBaseTypes.h |
Proxy Objects,Properties, Scopes, Elements
名称 | 说明 |
---|---|
Proxy Objects | 音频文件,流的代码抽象 |
Properties | 管理对象的状态或行为 |
Scopes | 作用域:输入/输出 |
Elements | 具体的设备,比如蓝牙,有线… |
Properties的key一般是个常量值,比如 kAudioFilePropertyFileFormat或者kAudioQueueDeviceProperty_NumberChannels.
回调函数: 与Core Audio交互
Core Audio接口通过回调函数与应用交互,一般有下面几种场景
- 音频数据传送到应用程序(例如用于录制;然后通过回调将新数据写入磁盘)
- 从应用程序请求音频数据(例如用于播放;回调从磁盘/内存读取并提供数据)。
- 通知应用程序音频对象已更改状态(回调会执行适当操作,比如更新界面)。
回调函数实现分两步: 注册 && 回调
相关框架
名称 | 说明 |
---|---|
AVFoundation | 提供AVAudioPlayer类,这是一个用于音频播放的简化的原生接口,还提供AVAudioEngine类,用于更复杂的音频处理 |
AudioToolbox | 为Core Audio中的高级服务提供接口,包括Audio Session服务,用于在iOS管理应用程序的音频行为,允许应用程序使用音频插件,包括音频单元和编解码器 |
OpenAL | 提供了与OpenAL配合使用的接口 |
CoreAudioTypes | 提供Core Audio使用的数据类型以及低级服务的接口。 |
示例
播放音乐
使用AudioToolbox.framework
1 | func play() { |
在回调方法中读取音频文件并将数据入队供系统的队列播放
1 | private let playbackCallback: AudioQueueOutputCallback = { |
1 | public func audioQueueOutput(audioQueue: AudioQueueRef, queueBuffer audioQueueBuffer: AudioQueueBufferRef) { |