131 lines
5.6 KiB
Markdown
131 lines
5.6 KiB
Markdown
|
|
# Audio System And Effect Chain
|
|||
|
|
|
|||
|
|
## 这篇指南解决什么问题
|
|||
|
|
|
|||
|
|
只看 `Audio` 模块的单个 API 页,很容易知道“有哪些类”,但不容易知道:
|
|||
|
|
|
|||
|
|
- 当前真正的播放主链路是什么
|
|||
|
|
- `AudioMixer` 和各种效果器现在到底有没有接入
|
|||
|
|
- `AudioSourceComponent`、`AudioListenerComponent` 和 `AudioSystem` 分别该怎么理解
|
|||
|
|
- 这个设计和 Unity 风格音频体系的关系是什么
|
|||
|
|
|
|||
|
|
这篇指南专门解释这些问题。
|
|||
|
|
|
|||
|
|
## 先建立正确心智模型
|
|||
|
|
|
|||
|
|
当前引擎音频系统更适合理解成:
|
|||
|
|
|
|||
|
|
**场景组件层 + 全局混音系统层 + 平台输出后端层**
|
|||
|
|
|
|||
|
|
其中:
|
|||
|
|
|
|||
|
|
- [AudioSourceComponent](../../XCEngine/Components/AudioSourceComponent/AudioSourceComponent.md) 负责每个声源的播放状态和样本生成。
|
|||
|
|
- [AudioListenerComponent](../../XCEngine/Components/AudioListenerComponent/AudioListenerComponent.md) 负责把监听器 transform 推送到系统。
|
|||
|
|
- [AudioSystem](../../XCEngine/Audio/AudioSystem/AudioSystem.md) 负责收集活跃声源、混音并提交给输出后端。
|
|||
|
|
- [IAudioBackend](../../XCEngine/Audio/IAudioBackend/IAudioBackend.md) 负责真正的设备和平台输出。
|
|||
|
|
|
|||
|
|
这和 Unity 的 `AudioSource + AudioListener + AudioMixer` 心智模型有明显对应关系,但当前版本还没有 Unity 那种完整的 mixer graph、bus、snapshot 和 effect routing 体系。
|
|||
|
|
|
|||
|
|
## 当前真实播放链路
|
|||
|
|
|
|||
|
|
按当前代码,主链路可以简化成:
|
|||
|
|
|
|||
|
|
1. `AudioSourceComponent::Play()` 把自己注册到 `AudioSystem`
|
|||
|
|
2. `Scene` 更新期间,`AudioListenerComponent` 更新监听器 transform
|
|||
|
|
3. `AudioSystem::Update()` 为当前帧分配一个浮点混音 buffer
|
|||
|
|
4. `AudioSystem` 遍历活跃 `AudioSourceComponent`
|
|||
|
|
5. 每个 `AudioSourceComponent::ProcessAudio()` 直接把自己的样本叠加到同一个 buffer
|
|||
|
|
6. `AudioSystem` 调用后端 `ProcessAudio()`
|
|||
|
|
7. Windows 后端把浮点样本转成 `int16` 并交给系统播放
|
|||
|
|
|
|||
|
|
这条链路已经能支撑基础声音播放,但它仍然是比较直接的“源混到总线,再送后端”模型。
|
|||
|
|
|
|||
|
|
## 为什么 `AudioMixer` 现在不能按 Unity AudioMixer 理解
|
|||
|
|
|
|||
|
|
从接口形状上看,[AudioMixer](../../XCEngine/Audio/AudioMixer/AudioMixer.md) 很像未来会成长为完整路由中枢的类型:
|
|||
|
|
|
|||
|
|
- 有效果器槽
|
|||
|
|
- 有输出 mixer
|
|||
|
|
- 有 3D 参数
|
|||
|
|
- 有每声道音量
|
|||
|
|
|
|||
|
|
但按当前实现,它真正处理的只有总音量和静音。效果器数组、输出 mixer、3D 参数和每声道音量现在都只是被记录,没有自动进入主链路。
|
|||
|
|
|
|||
|
|
所以最准确的理解方式是:
|
|||
|
|
|
|||
|
|
- 它是架构方向正确的扩展点
|
|||
|
|
- 但还不是完整 mixer graph
|
|||
|
|
|
|||
|
|
## 效果器链当前的现实状态
|
|||
|
|
|
|||
|
|
### 已有类型
|
|||
|
|
|
|||
|
|
- [Equalizer](../../XCEngine/Audio/Equalizer/Equalizer.md)
|
|||
|
|
- [FFTFilter](../../XCEngine/Audio/FFTFilter/FFTFilter.md)
|
|||
|
|
- [Reverbation](../../XCEngine/Audio/Reverbation/Reverbation.md)
|
|||
|
|
- [HRTF](../../XCEngine/Audio/HRTF/HRTF.md)
|
|||
|
|
|
|||
|
|
### 当前成熟度差异
|
|||
|
|
|
|||
|
|
- `Equalizer` 和 `Reverbation` 会真实改写音频样本。
|
|||
|
|
- `FFTFilter` 当前更像 analyzer,不会回写处理结果。
|
|||
|
|
- `HRTF` 是独立空间化处理器,不是 `IAudioEffect` 派生效果器。
|
|||
|
|
|
|||
|
|
### 当前没接上的地方
|
|||
|
|
|
|||
|
|
- `AudioMixer` 不会自动遍历 effect slots
|
|||
|
|
- `AudioSystem` 也不会自动经过 `AudioMixer`
|
|||
|
|
- `AudioSourceComponent::outputMixer` 当前没有形成实际路由
|
|||
|
|
|
|||
|
|
这就是为什么文档会一再强调“接口存在”和“主链路已生效”不是一回事。
|
|||
|
|
|
|||
|
|
## 当前 Windows 后端到底是什么
|
|||
|
|
|
|||
|
|
类名叫 `WASAPIBackend`,但当前实现实际上依赖的是 `waveOut*` 这套 WinMM API,而不是 Core Audio WASAPI COM 接口。
|
|||
|
|
|
|||
|
|
为什么要特别说明这点?
|
|||
|
|
|
|||
|
|
- 因为名字会让人以为这是现代 Windows 音频栈的标准 WASAPI 后端
|
|||
|
|
- 但当前实现的设备模型、线程模型和缓冲策略其实更接近传统 waveOut 风格
|
|||
|
|
|
|||
|
|
这不一定是问题,但文档必须准确。
|
|||
|
|
|
|||
|
|
## 为什么要保留这些“还没完全接上”的接口
|
|||
|
|
|
|||
|
|
从引擎设计角度看,这其实是合理的演进路径:
|
|||
|
|
|
|||
|
|
1. 先打通最基础的播放链路
|
|||
|
|
2. 再把 mixer、effects、spatialization 的抽象搭出来
|
|||
|
|
3. 之后逐步把这些节点正式接入主混音图
|
|||
|
|
|
|||
|
|
这样做的好处是 API 方向能尽早稳定,编辑器和脚本层也能先围绕目标架构设计。代价是文档必须明确当前成熟度,否则用户会把“未来形状”误读成“当前能力”。
|
|||
|
|
|
|||
|
|
## 你现在最该注意的限制
|
|||
|
|
|
|||
|
|
### 1. `AudioSourceComponent` 不是完整商用级 AudioSource
|
|||
|
|
|
|||
|
|
它已经能解码、播放和基础混音,但 pause/resume、3D 参数、output mixer 和序列化都还不完整。
|
|||
|
|
|
|||
|
|
### 2. `AudioListenerComponent` 主要只做监听器 transform 和 master volume / mute
|
|||
|
|
|
|||
|
|
其他高级参数现在大多是存值或预留位。
|
|||
|
|
|
|||
|
|
### 3. `AudioMixer` 还没有成为主链路中枢
|
|||
|
|
|
|||
|
|
不要把它当成已经具备完整 bus routing 的 Unity AudioMixer 替代品。
|
|||
|
|
|
|||
|
|
### 4. `AudioSystem` 和内建后端之间的 buffer size 语义还需要收敛
|
|||
|
|
|
|||
|
|
当前调用方和实现方对 `bufferSize` 的理解并不完全一致。
|
|||
|
|
|
|||
|
|
### 5. 这个模块当前缺少足够的直接单元测试
|
|||
|
|
|
|||
|
|
很多行为需要以源码而不是测试保证为准。
|
|||
|
|
|
|||
|
|
## 推荐阅读顺序
|
|||
|
|
|
|||
|
|
1. 先读 [Audio](../../XCEngine/Audio/Audio.md)
|
|||
|
|
2. 再读 [AudioSystem](../../XCEngine/Audio/AudioSystem/AudioSystem.md) 和 [IAudioBackend](../../XCEngine/Audio/IAudioBackend/IAudioBackend.md)
|
|||
|
|
3. 然后对照 [AudioSourceComponent](../../XCEngine/Components/AudioSourceComponent/AudioSourceComponent.md) 与 [AudioListenerComponent](../../XCEngine/Components/AudioListenerComponent/AudioListenerComponent.md)
|
|||
|
|
4. 最后再看 [AudioMixer](../../XCEngine/Audio/AudioMixer/AudioMixer.md) 和各个效果器页,理解哪些能力已经落地、哪些还在预留阶段
|