2026-03-26 16:45:24 +08:00
|
|
|
# AudioSystem
|
|
|
|
|
|
|
|
|
|
**命名空间**: `XCEngine::Audio`
|
|
|
|
|
|
|
|
|
|
**类型**: `class (singleton)`
|
|
|
|
|
|
|
|
|
|
**头文件**: `XCEngine/Audio/AudioSystem.h`
|
|
|
|
|
|
2026-03-27 19:18:53 +08:00
|
|
|
**描述**: 全局音频系统入口,负责音频后端生命周期、监听器状态、活跃音频源列表和每帧混音调度。
|
|
|
|
|
|
|
|
|
|
## 角色概述
|
|
|
|
|
|
|
|
|
|
`AudioSystem` 是当前引擎音频主链路的中心。它的定位类似于一个轻量级全局运行时服务:
|
|
|
|
|
|
|
|
|
|
- 管理一个当前后端 `IAudioBackend`
|
|
|
|
|
- 持有监听器位置、旋转和速度
|
|
|
|
|
- 持有活跃 `AudioSourceComponent` 列表
|
|
|
|
|
- 在 `Update()` 中把各音频源混到输出 buffer
|
|
|
|
|
|
|
|
|
|
如果从 Unity 风格心智模型来理解,它更接近“底层音频 runtime + 设备桥接层”,而不是 Unity Audio Mixer 那样完整的音频图形系统。
|
|
|
|
|
|
|
|
|
|
## 生命周期
|
|
|
|
|
|
|
|
|
|
### 初始化
|
|
|
|
|
|
|
|
|
|
`Initialize(const AudioConfig&)` 当前会:
|
|
|
|
|
|
|
|
|
|
1. 如果已有后端,先 `Shutdown()`
|
|
|
|
|
2. 直接创建 `WASAPI::WASAPIBackend`
|
|
|
|
|
3. 调用后端 `Initialize(config)`
|
|
|
|
|
4. 成功后调用 `Start()`
|
|
|
|
|
5. 失败时打印日志并清空后端
|
|
|
|
|
|
|
|
|
|
这说明当前默认后端策略是写死的,不是从插件表或平台抽象层动态选择。
|
|
|
|
|
|
|
|
|
|
### 关闭
|
|
|
|
|
|
|
|
|
|
`Shutdown()` 会:
|
|
|
|
|
|
|
|
|
|
- 停止并销毁当前后端
|
|
|
|
|
- 清空 `m_activeSources`
|
|
|
|
|
|
|
|
|
|
它不会额外遍历场景组件做状态回填,因此组件侧的播放状态和系统侧活跃源列表可能需要上层逻辑保持一致。
|
|
|
|
|
|
|
|
|
|
## 当前混音路径
|
|
|
|
|
|
|
|
|
|
`Update(float deltaTime)` 是当前主路径:
|
|
|
|
|
|
|
|
|
|
1. 保存 `m_deltaTime`
|
|
|
|
|
2. 检查后端是否存在且正在运行
|
|
|
|
|
3. 根据后端配置分配一个浮点 `mixBuffer`
|
|
|
|
|
4. 遍历 `m_activeSources`
|
|
|
|
|
5. 对每个“已启用且正在播放”的源调用 `ProcessSource()`
|
|
|
|
|
6. 把最终混音结果交给后端 `ProcessAudio()`
|
|
|
|
|
7. 更新 `Stats.activeSources` 和 `Stats.totalSources`
|
|
|
|
|
|
|
|
|
|
`ProcessSource()` 当前只是简单转发到 `AudioSourceComponent::ProcessAudio()`。这意味着:
|
|
|
|
|
|
|
|
|
|
- `AudioSystem` 本身不做复杂路由
|
|
|
|
|
- 不会自动经过 `AudioMixer`
|
|
|
|
|
- 不会自动挂任何效果器链
|
|
|
|
|
|
|
|
|
|
## 监听器语义
|
|
|
|
|
|
|
|
|
|
当前系统只维护一份全局监听器状态:
|
|
|
|
|
|
|
|
|
|
- `SetListenerTransform()`
|
|
|
|
|
- `SetListenerVelocity()`
|
|
|
|
|
- `GetListenerPosition()`
|
|
|
|
|
- `GetListenerRotation()`
|
|
|
|
|
- `GetListenerVelocity()`
|
|
|
|
|
|
|
|
|
|
[AudioListenerComponent](../../Components/AudioListenerComponent/AudioListenerComponent.md) 的作用,就是在 `Update()` 时把宿主对象的 `Transform` 推进到这里。
|
|
|
|
|
|
|
|
|
|
## 设备控制
|
|
|
|
|
|
|
|
|
|
当前提供:
|
|
|
|
|
|
|
|
|
|
- `GetCurrentDevice()`
|
|
|
|
|
- `SetDevice()`
|
|
|
|
|
- `GetAvailableDevices()`
|
|
|
|
|
- `GetMasterVolume()`
|
|
|
|
|
- `SetMasterVolume()`
|
|
|
|
|
- `IsMuted()`
|
|
|
|
|
- `SetMuted()`
|
|
|
|
|
|
|
|
|
|
这些能力本质上都是对当前后端的转发。没有后端时,它们会返回空字符串、默认值或直接 no-op。
|
|
|
|
|
|
|
|
|
|
## Stats 语义
|
|
|
|
|
|
|
|
|
|
`Stats` 结构当前公开:
|
|
|
|
|
|
|
|
|
|
- `activeSources`
|
|
|
|
|
- `totalSources`
|
|
|
|
|
- `memoryUsage`
|
|
|
|
|
- `cpuUsage`
|
|
|
|
|
|
|
|
|
|
但当前实现里实际更新的只有前两个字段。`memoryUsage` 和 `cpuUsage` 仍是占位值。
|
|
|
|
|
|
|
|
|
|
## 线程语义
|
|
|
|
|
|
|
|
|
|
- 当前实现没有为 `m_activeSources` 做加锁保护。
|
|
|
|
|
- `RegisterSource()` 和 `UnregisterSource()` 只是直接改 `std::vector`。
|
|
|
|
|
- 后端可能有自己的线程,但 `AudioSystem` 文档本身不提供并发安全保证。
|
|
|
|
|
|
|
|
|
|
默认应按主线程驱动 `Update()`,并谨慎看待与后端线程的交互边界。
|
|
|
|
|
|
|
|
|
|
## 当前实现限制
|
|
|
|
|
|
|
|
|
|
- `RegisterSource()` 没有去重保护,同一 source 可能被重复注册。
|
|
|
|
|
- 没有自动接入 [AudioMixer](../AudioMixer/AudioMixer.md) 或效果器链。
|
|
|
|
|
- `ProcessAudio()` 这个直接转发接口当前硬编码把 sample rate 传成 `48000`。
|
|
|
|
|
- `IAudioBackend::ProcessAudio()` 的 `bufferSize` 语义在当前调用方与内建 Windows 后端之间并不完全一致:`AudioSystem` 传的是样本数量,而后端按字节大小解释。
|
|
|
|
|
- `Stats.memoryUsage` / `Stats.cpuUsage` 当前没有真实采集逻辑。
|
|
|
|
|
- 没有看到直接覆盖该类型的单元测试。
|
|
|
|
|
|
|
|
|
|
## 相关方法
|
|
|
|
|
|
|
|
|
|
- [Get](Get.md)
|
|
|
|
|
- [Initialize](Initialize.md)
|
|
|
|
|
- [Shutdown](Shutdown.md)
|
|
|
|
|
- [Update](Update.md)
|
|
|
|
|
- [SetBackend](SetBackend.md)
|
|
|
|
|
- [GetBackend](GetBackend.md)
|
|
|
|
|
- [GetCurrentDevice](GetCurrentDevice.md)
|
|
|
|
|
- [SetDevice](SetDevice.md)
|
|
|
|
|
- [GetAvailableDevices](GetAvailableDevices.md)
|
|
|
|
|
- [GetMasterVolume](GetMasterVolume.md)
|
|
|
|
|
- [SetMasterVolume](SetMasterVolume.md)
|
|
|
|
|
- [IsMuted](IsMuted.md)
|
|
|
|
|
- [SetMuted](SetMuted.md)
|
|
|
|
|
- [ProcessAudio](ProcessAudio.md)
|
|
|
|
|
- [SetListenerTransform](SetListenerTransform.md)
|
|
|
|
|
- [SetListenerVelocity](SetListenerVelocity.md)
|
|
|
|
|
- [GetListenerPosition](GetListenerPosition.md)
|
|
|
|
|
- [GetListenerRotation](GetListenerRotation.md)
|
|
|
|
|
- [GetListenerVelocity](GetListenerVelocity.md)
|
|
|
|
|
- [RegisterSource](RegisterSource.md)
|
|
|
|
|
- [UnregisterSource](UnregisterSource.md)
|
|
|
|
|
- [GetStats](GetStats.md)
|
|
|
|
|
|
|
|
|
|
## 相关指南
|
|
|
|
|
|
|
|
|
|
- [Audio System And Effect Chain](../../../_guides/Audio/Audio-System-And-Effect-Chain.md)
|
2026-03-26 16:45:24 +08:00
|
|
|
|
|
|
|
|
## 相关文档
|
|
|
|
|
|
2026-03-27 19:18:53 +08:00
|
|
|
- [当前模块](../Audio.md)
|
|
|
|
|
- [IAudioBackend](../IAudioBackend/IAudioBackend.md)
|
|
|
|
|
- [WASAPIBackend](../WindowsAudioBackend/WindowsAudioBackend.md)
|
|
|
|
|
- [AudioSourceComponent](../../Components/AudioSourceComponent/AudioSourceComponent.md)
|
|
|
|
|
- [AudioListenerComponent](../../Components/AudioListenerComponent/AudioListenerComponent.md)
|
|
|
|
|
- [API 总索引](../../../main.md)
|