- Created EditorConsoleSink (implements ILogSink interface) - EditorConsoleSink stores logs in memory buffer (max 1000 entries) - Added to Debug::Logger in Application::Initialize() - ConsolePanel now reads from EditorConsoleSink via static GetInstance() - Removed separate LogSystem singleton - Removed editor/src/Core/LogEntry.h (no longer needed) Now Editor and Engine share the same Debug::Logger, with ConsolePanel displaying logs via EditorConsoleSink.
1641 lines
47 KiB
Markdown
1641 lines
47 KiB
Markdown
# XCEngine - 音频模块架构设计文档
|
||
|
||
> **借鉴 Unity 音频架构概念设计**
|
||
|
||
---
|
||
|
||
## 音频流程图
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────────────────────────────┐
|
||
│ 音频流程 │
|
||
└─────────────────────────────────────────────────────────────────────────────────────┘
|
||
|
||
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
||
│ AudioSource │────▶│ Spatialize │────▶│ EffectChain │────▶│ Output │
|
||
│ 声源组件 │ │ 3D空间化 │ │ 效果链 │ │ 音频输出 │
|
||
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
|
||
│ │ │ │
|
||
▼ ▼ ▼ ▼
|
||
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
||
│ AudioClip │ │ HRTF │ │ FFT │ │ AudioBackend│
|
||
│ 音频资源 │ │ 头部相关传输 │ │ 傅里叶变换 │ │ 音频后端 │
|
||
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
|
||
│ │
|
||
▼ ▼
|
||
┌─────────────┐ ┌─────────────┐
|
||
│ Reverbation │ │ WASAPI │
|
||
│ 混响效果 │ │ OpenAL │
|
||
└─────────────┘ │ CoreAudio │
|
||
└─────────────┘
|
||
|
||
流程说明:
|
||
1. AudioSourceComponent 负责播放 AudioClip,管理播放状态
|
||
2. AudioListenerComponent 接收声音,计算3D空间化参数
|
||
3. Spatialize 根据 Listener 位置计算 panning、distance attenuation、doppler
|
||
4. EffectChain 处理 DSP 效果链(FFT、Reverb、EQ等)
|
||
5. AudioBackend 抽象层负责与具体音频API交互
|
||
6. 最终输出到音频设备
|
||
```
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────────────────────────────┐
|
||
│ AudioBackend 抽象层架构 │
|
||
└─────────────────────────────────────────────────────────────────────────────────────┘
|
||
|
||
┌─────────────────┐
|
||
│ AudioSystem │ 音频系统入口
|
||
└────────┬────────┘
|
||
│
|
||
┌───────────────────────┼───────────────────────┐
|
||
│ │ │
|
||
┌──────▼──────┐ ┌──────▼──────┐ ┌──────▼──────┐
|
||
│ WASAPIBackend│ │OpenALBackend │ │CoreAudioBackend│
|
||
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
|
||
│ │ │
|
||
└───────────────────────┼───────────────────────┘
|
||
│
|
||
┌────────▼────────┐
|
||
│ IAudioBackend │ 抽象音频后端接口
|
||
└────────┬────────┘
|
||
│
|
||
┌──────────────────────────────────┼──────────────────────────────────┐
|
||
│ │ │ │ │ │ │
|
||
┌────▼────┐ ┌───▼────┐ ┌────▼┐ ┌──▼────┐ ┌───▼───┐ ┌───▼────┐ ┌──▼────┐
|
||
│AudioBuffer│ │AudioBus │ │Fence│ │Mixer │ │Effect │ │HRTF │ │Resampler│
|
||
│ 音频缓冲 │ │ 音频总线 │ │围栏 │ │ 混音器 │ │ 效果 │ │ 空间化 │ │ 重采样 │
|
||
└──────────┘ └────────┘ └─────┘ └────────┘ └───────┘ └────────┘ └────────┘
|
||
```
|
||
|
||
> **重要声明**:本架构借鉴 Unity 音频系统的核心概念与设计模式,包括:
|
||
> - `AudioSourceComponent` / `AudioListenerComponent` - 声源与监听器组件
|
||
> - `AudioClip` / `AudioMixer` - 音频资源与混音器
|
||
> - `EffectChain` - 效果器链
|
||
> - `Spatializer` - 3D空间化处理器
|
||
> - `AudioBackend` - 音频后端抽象
|
||
>
|
||
> **注**:Unity底层C++音频架构未公开,本设计基于公开API概念与通用音频引擎模式实现。
|
||
>
|
||
> 版本: 1.0
|
||
> 日期: 2026-03-20
|
||
> 目标: 构建专业级游戏引擎音频系统
|
||
|
||
---
|
||
|
||
## 第一章 核心类型定义
|
||
|
||
### 1.1 音频基础类型
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
namespace Audio {
|
||
|
||
// ============================================
|
||
// 前置类型定义
|
||
// ============================================
|
||
|
||
enum class AudioResourceType {
|
||
AudioClip,
|
||
AudioMixer,
|
||
AudioBank
|
||
};
|
||
|
||
enum class AudioLoadState {
|
||
Unloaded,
|
||
Loading,
|
||
Loaded,
|
||
Failed
|
||
};
|
||
|
||
enum class AudioFormat {
|
||
Unknown,
|
||
WAV,
|
||
OGG,
|
||
MP3,
|
||
FLAC,
|
||
AAC
|
||
};
|
||
|
||
enum class SpeakerMode {
|
||
Mono,
|
||
Stereo,
|
||
Surround51,
|
||
Surround71,
|
||
Surround51_2,
|
||
Surround71_2
|
||
};
|
||
|
||
enum class AudioChannel {
|
||
FrontLeft,
|
||
FrontRight,
|
||
FrontCenter,
|
||
LFE,
|
||
BackLeft,
|
||
BackRight,
|
||
SideLeft,
|
||
SideRight
|
||
};
|
||
|
||
struct AudioConfig {
|
||
uint32_t sampleRate = 48000;
|
||
uint16_t channels = 2;
|
||
uint16_t bitsPerSample = 16;
|
||
SpeakerMode speakerMode = SpeakerMode::Stereo;
|
||
uint32_t bufferSize = 8192;
|
||
uint32_t bufferCount = 2;
|
||
};
|
||
|
||
// ============================================
|
||
// 3D 音频参数
|
||
// ============================================
|
||
|
||
struct Audio3DParams {
|
||
float dopplerLevel = 1.0f;
|
||
float speedOfSound = 343.0f;
|
||
float minDistance = 1.0f;
|
||
float maxDistance = 500.0f;
|
||
float panLevel = 1.0f;
|
||
float spread = 0.0f;
|
||
float reverbZoneMix = 1.0f;
|
||
};
|
||
|
||
enum class PanMode {
|
||
Pan3D,
|
||
Pan2D
|
||
};
|
||
|
||
enum class VolumeSource {
|
||
Direct,
|
||
Path Occlusion,
|
||
Transmission,
|
||
Obstruction
|
||
};
|
||
|
||
// ============================================
|
||
// 音频缓冲区描述
|
||
// ============================================
|
||
|
||
struct AudioBufferDesc {
|
||
uint32_t size = 0;
|
||
uint32_t channels = 2;
|
||
uint32_t sampleRate = 48000;
|
||
uint16_t bitsPerSample = 16;
|
||
bool isFloat = false;
|
||
bool isCompressed = false;
|
||
AudioFormat format = AudioFormat::Unknown;
|
||
};
|
||
|
||
// ============================================
|
||
// 播放状态
|
||
// ============================================
|
||
|
||
enum class PlayState {
|
||
Stopped,
|
||
Playing,
|
||
Paused
|
||
};
|
||
|
||
enum class StopMode {
|
||
Immediate,
|
||
AllowFadeOut
|
||
};
|
||
|
||
// ============================================
|
||
// 空间化参数
|
||
// ============================================
|
||
|
||
struct SpatializerParams {
|
||
float azimuth = 0.0f;
|
||
float elevation = 0.0f;
|
||
float distance = 0.0f;
|
||
float volumeDb = 0.0f;
|
||
float panCartesianX = 0.0f;
|
||
float panCartesianY = 0.0f;
|
||
bool isOccluded = false;
|
||
bool isObstructed = false;
|
||
};
|
||
|
||
} // namespace Audio
|
||
} // namespace XCEngine
|
||
```
|
||
|
||
### 1.2 IAudioResource 基类
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
namespace Audio {
|
||
|
||
class IAudioResource {
|
||
public:
|
||
virtual ~IAudioResource() = default;
|
||
|
||
virtual void SetName(const String& name) { m_name = name; }
|
||
virtual const String& GetName() const { return m_name; }
|
||
|
||
virtual AudioResourceType GetType() const = 0;
|
||
virtual AudioLoadState GetLoadState() const { return m_loadState; }
|
||
|
||
virtual bool IsValid() const { return m_loadState == AudioLoadState::Loaded; }
|
||
virtual void Load() = 0;
|
||
virtual void Unload() = 0;
|
||
|
||
virtual int GetRefCount() const { return m_refCount.load(); }
|
||
virtual void AddRef() { m_refCount.fetch_add(1); }
|
||
virtual void Release() {
|
||
if (m_refCount.fetch_sub(1) == 1) {
|
||
delete this;
|
||
}
|
||
}
|
||
|
||
protected:
|
||
IAudioResource() : m_loadState(AudioLoadState::Unloaded), m_memoryUsage(0) {}
|
||
|
||
String m_name;
|
||
AudioLoadState m_loadState;
|
||
uint64_t m_memoryUsage;
|
||
std::atomic<int32_t> m_refCount{1};
|
||
};
|
||
|
||
} // namespace Audio
|
||
} // namespace XCEngine
|
||
```
|
||
|
||
---
|
||
|
||
## 第二章 音频资源
|
||
|
||
### 2.1 AudioClip
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
namespace Audio {
|
||
|
||
class AudioClip : public IAudioResource {
|
||
public:
|
||
AudioClip();
|
||
AudioClip(const String& filePath);
|
||
~AudioClip();
|
||
|
||
AudioResourceType GetType() const override { return AudioResourceType::AudioClip; }
|
||
|
||
void Load() override;
|
||
void Unload() override;
|
||
|
||
// 音频数据访问
|
||
const int16_t* GetData() const { return m_data.data(); }
|
||
int16_t* GetData() { return m_data.data(); }
|
||
|
||
const float* GetDataFloat() const { return m_dataFloat.data(); }
|
||
float* GetDataFloat() { return m_dataFloat.data(); }
|
||
|
||
uint32_t GetDataSize() const { return m_dataSize; }
|
||
uint32_t GetSampleCount() const { return m_sampleCount; }
|
||
uint32_t GetChannelCount() const { return m_channels; }
|
||
uint32_t GetSampleRate() const { return m_sampleRate; }
|
||
uint16_t GetBitsPerSample() const { return m_bitsPerSample; }
|
||
float GetDuration() const { return m_duration; }
|
||
|
||
AudioFormat GetFormat() const { return m_format; }
|
||
bool IsCompressed() const { return m_isCompressed; }
|
||
bool IsStreamed() const { return m_isStreamed; }
|
||
|
||
// 频谱数据查询
|
||
bool HasFrequencyData() const { return m_hasFrequencyData; }
|
||
const float* GetFrequencyData() const { return m_frequencyData.data(); }
|
||
uint32_t GetFrequencyDataSize() const { return m_frequencyData.size(); }
|
||
|
||
// 资源路径
|
||
void SetResourcePath(const String& path) { m_resourcePath = path; }
|
||
const String& GetResourcePath() const { return m_resourcePath; }
|
||
|
||
private:
|
||
void ProcessWavFile();
|
||
void DecodeCompressedData();
|
||
void GenerateFrequencyData();
|
||
void ConvertToFloat();
|
||
|
||
private:
|
||
std::vector<int16_t> m_data;
|
||
std::vector<float> m_dataFloat;
|
||
std::vector<float> m_frequencyData;
|
||
|
||
uint32_t m_dataSize = 0;
|
||
uint32_t m_sampleCount = 0;
|
||
uint16_t m_channels = 2;
|
||
uint32_t m_sampleRate = 48000;
|
||
uint16_t m_bitsPerSample = 16;
|
||
float m_duration = 0.0f;
|
||
|
||
AudioFormat m_format = AudioFormat::Unknown;
|
||
bool m_isCompressed = false;
|
||
bool m_isStreamed = false;
|
||
bool m_hasFrequencyData = false;
|
||
|
||
String m_resourcePath;
|
||
};
|
||
|
||
} // namespace Audio
|
||
} // namespace XCEngine
|
||
```
|
||
|
||
### 2.2 AudioMixer
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
namespace Audio {
|
||
|
||
class AudioMixer : public IAudioResource {
|
||
public:
|
||
AudioMixer();
|
||
~AudioMixer();
|
||
|
||
AudioResourceType GetType() const override { return AudioResourceType::AudioMixer; }
|
||
|
||
void Load() override;
|
||
void Unload() override;
|
||
|
||
// 混音器参数
|
||
float GetVolume() const { return m_volume; }
|
||
void SetVolume(float volume, float fadeTime = 0.0f);
|
||
|
||
bool IsMuted() const { return m_isMuted; }
|
||
void SetMuted(bool muted) { m_isMuted = muted; }
|
||
|
||
// 子混音器组
|
||
class MixerGroup* GetGroup(const String& name);
|
||
class MixerGroup* CreateGroup(const String& name);
|
||
void RemoveGroup(const String& name);
|
||
|
||
const std::map<String, std::unique_ptr<MixerGroup>>& GetGroups() const { return m_groups; }
|
||
|
||
// 输出混音器
|
||
void SetOutputMixer(AudioMixer* mixer);
|
||
AudioMixer* GetOutputMixer() const { return m_outputMixer; }
|
||
|
||
private:
|
||
float m_volume = 1.0f;
|
||
bool m_isMuted = false;
|
||
|
||
std::map<String, std::unique_ptr<MixerGroup>> m_groups;
|
||
AudioMixer* m_outputMixer = nullptr;
|
||
};
|
||
|
||
class MixerGroup {
|
||
public:
|
||
MixerGroup(const String& name);
|
||
~MixerGroup();
|
||
|
||
const String& GetName() const { return m_name; }
|
||
|
||
float GetVolume() const { return m_volume; }
|
||
void SetVolume(float volume, float fadeTime = 0.0f);
|
||
|
||
bool IsMuted() const { return m_isMuted; }
|
||
void SetMuted(bool muted) { m_isMuted = muted; }
|
||
|
||
bool IsSoloed() const { return m_isSoloed; }
|
||
void SetSoloed(bool soloed) { m_isSoloed = soloed; }
|
||
|
||
// 效果器
|
||
void AddEffect(IAudioEffect* effect, size_t index = SIZE_MAX);
|
||
void RemoveEffect(IAudioEffect* effect);
|
||
void SetEffectEnabled(IAudioEffect* effect, bool enabled);
|
||
|
||
const std::vector<IAudioEffect*>& GetEffects() const { return m_effects; }
|
||
|
||
// 音频处理
|
||
void Process(float* buffer, uint32_t sampleCount, uint32_t channels);
|
||
|
||
private:
|
||
String m_name;
|
||
float m_volume = 1.0f;
|
||
bool m_isMuted = false;
|
||
bool m_isSoloed = false;
|
||
|
||
std::vector<IAudioEffect*> m_effects;
|
||
};
|
||
|
||
} // namespace Audio
|
||
} // namespace XCEngine
|
||
```
|
||
|
||
### 2.3 AudioBank (用于分段加载)
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
namespace Audio {
|
||
|
||
class AudioBank : public IAudioResource {
|
||
public:
|
||
AudioBank();
|
||
~AudioBank();
|
||
|
||
AudioResourceType GetType() const override { return AudioResourceType::AudioBank; }
|
||
|
||
void Load() override;
|
||
void Unload() override;
|
||
|
||
// 事件触发
|
||
void TriggerEvent(const String& eventName);
|
||
void TriggerEvent(int eventId);
|
||
|
||
// 获取嵌入的音频片段
|
||
AudioClip* GetClip(const String& name);
|
||
AudioClip* GetClip(int id);
|
||
|
||
const std::map<String, AudioClip*>& GetAllClips() const { return m_clips; }
|
||
|
||
private:
|
||
std::map<String, AudioClip*> m_clips;
|
||
std::map<String, int> m_eventMap;
|
||
};
|
||
|
||
} // namespace Audio
|
||
} // namespace XCEngine
|
||
```
|
||
|
||
---
|
||
|
||
## 第三章 DSP 效果系统
|
||
|
||
### 3.1 IAudioEffect 接口
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
namespace Audio {
|
||
|
||
class IAudioEffect {
|
||
public:
|
||
virtual ~IAudioEffect() = default;
|
||
|
||
virtual const char* GetName() const = 0;
|
||
virtual void Process(float* buffer, uint32_t sampleCount, uint32_t channels) = 0;
|
||
|
||
virtual void SetEnabled(bool enabled) { m_enabled = enabled; }
|
||
virtual bool IsEnabled() const { return m_enabled; }
|
||
|
||
virtual void SetParameter(const char* name, float value) = 0;
|
||
virtual float GetParameter(const char* name) const = 0;
|
||
|
||
virtual size_t GetParameterCount() const = 0;
|
||
virtual const char* GetParameterName(size_t index) const = 0;
|
||
|
||
protected:
|
||
bool m_enabled = true;
|
||
};
|
||
|
||
} // namespace Audio
|
||
} // namespace XCEngine
|
||
```
|
||
|
||
### 3.2 FFTFilter (频谱分析)
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
namespace Audio {
|
||
|
||
class FFTFilter : public IAudioEffect {
|
||
public:
|
||
FFTFilter(size_t fftSize = 1024);
|
||
~FFTFilter();
|
||
|
||
const char* GetName() const override { return "FFTFilter"; }
|
||
void Process(float* buffer, uint32_t sampleCount, uint32_t channels) override;
|
||
|
||
void SetEnabled(bool enabled) override;
|
||
|
||
void SetFFTSize(size_t size);
|
||
size_t GetFFTSize() const { return m_fftSize; }
|
||
|
||
void SetParameter(const char* name, float value) override;
|
||
float GetParameter(const char* name) const override;
|
||
size_t GetParameterCount() const override;
|
||
const char* GetParameterName(size_t index) const override;
|
||
|
||
// 频谱数据访问
|
||
const float* GetMagnitudeSpectrum() const { return m_magnitudeSpectrum.data(); }
|
||
const float* GetPhaseSpectrum() const { return m_phaseSpectrum.data(); }
|
||
size_t GetSpectrumSize() const { return m_spectrumSize; }
|
||
|
||
// 设置时域核(用于滤波)
|
||
void SetTimeDomainKernel(const std::vector<float>& kernel);
|
||
void AddTimeDomainKernel(const std::vector<float>& kernel);
|
||
|
||
// 频域核
|
||
void SetFreqDomainKernel(const std::vector<float>& kernel);
|
||
void AddFreqDomainKernel(const std::vector<float>& kernel);
|
||
|
||
private:
|
||
void Init();
|
||
void ComplexVectorProduct(const std::vector<kiss_fft_cpx>& inputA,
|
||
const std::vector<kiss_fft_cpx>& inputB,
|
||
std::vector<kiss_fft_cpx>* result);
|
||
void InverseFFTScaling(std::vector<float>* signal);
|
||
|
||
private:
|
||
size_t m_fftSize;
|
||
size_t m_spectrumSize;
|
||
|
||
bool m_analysisMode = true;
|
||
|
||
std::vector<float> m_magnitudeSpectrum;
|
||
std::vector<float> m_phaseSpectrum;
|
||
|
||
std::vector<float> m_filterState;
|
||
std::vector<float> m_window;
|
||
|
||
bool m_kernelDefined = false;
|
||
std::vector<kiss_fft_scalar> m_kernelTimeDomainBuffer;
|
||
std::vector<kiss_fft_cpx> m_kernelFreqDomainBuffer;
|
||
|
||
int m_bufferSelector = 0;
|
||
std::vector<std::vector<kiss_fft_scalar>> m_signalTimeDomainBuffer;
|
||
std::vector<std::vector<kiss_fft_cpx>> m_signalFreqDomainBuffer;
|
||
std::vector<kiss_fft_cpx> m_filteredFreqDomainBuffer;
|
||
|
||
kiss_fftr_cfg m_forwardFFT = nullptr;
|
||
kiss_fftr_cfg m_inverseFFT = nullptr;
|
||
};
|
||
|
||
} // namespace Audio
|
||
} // namespace XCEngine
|
||
```
|
||
|
||
### 3.3 Reverbation (混响)
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
namespace Audio {
|
||
|
||
class Reverbation : public IAudioEffect {
|
||
public:
|
||
Reverbation(int blockSize = 1024, int samplingRate = 48000, float reverbTime = 2.0f);
|
||
~Reverbation();
|
||
|
||
const char* GetName() const override { return "Reverbation"; }
|
||
void Process(float* buffer, uint32_t sampleCount, uint32_t channels) override;
|
||
|
||
void SetParameter(const char* name, float value) override;
|
||
float GetParameter(const char* name) const override;
|
||
size_t GetParameterCount() const override;
|
||
const char* GetParameterName(size_t index) const override;
|
||
|
||
// 混响参数
|
||
void SetReverbTime(float seconds);
|
||
float GetReverbTime() const { return m_reverbTime; }
|
||
|
||
void SetDecay(float decay) { m_decay = decay; }
|
||
float GetDecay() const { return m_decay; }
|
||
|
||
void SetPreDelay(float ms);
|
||
float GetPreDelay() const { return m_preDelayMs; }
|
||
|
||
void SetHighFreqDamping(float ratio);
|
||
float GetHighFreqDamping() const { return m_highFreqDamping; }
|
||
|
||
// 脉冲响应
|
||
const std::vector<float>& GetImpulseResponseLeft() const { return m_impulseResponseLeft; }
|
||
const std::vector<float>& GetImpulseResponseRight() const { return m_impulseResponseRight; }
|
||
|
||
float GetQuietPeriod() const { return m_quietPeriodSec; }
|
||
|
||
private:
|
||
void RenderImpulseResponse(int blockSize, int samplingRate, float reverbTime);
|
||
static float FloatRand();
|
||
|
||
private:
|
||
int m_blockSize;
|
||
float m_reverbTime = 2.0f;
|
||
float m_decay = 0.7f;
|
||
float m_preDelayMs = 20.0f;
|
||
float m_highFreqDamping = 0.5f;
|
||
|
||
std::vector<float> m_impulseResponseLeft;
|
||
std::vector<float> m_impulseResponseRight;
|
||
float m_quietPeriodSec;
|
||
|
||
std::unique_ptr<FFTFilter> m_leftReverbFilter;
|
||
std::unique_ptr<FFTFilter> m_rightReverbFilter;
|
||
|
||
std::vector<float> m_reverbInput;
|
||
std::vector<float> m_reverbOutputLeft;
|
||
std::vector<float> m_reverbOutputRight;
|
||
int m_reverbOutputReadPos = 0;
|
||
};
|
||
|
||
} // namespace Audio
|
||
} // namespace XCEngine
|
||
```
|
||
|
||
### 3.4 EQ (均衡器)
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
namespace Audio {
|
||
|
||
class Equalizer : public IAudioEffect {
|
||
public:
|
||
Equalizer();
|
||
~Equalizer();
|
||
|
||
const char* GetName() const override { return "Equalizer"; }
|
||
void Process(float* buffer, uint32_t sampleCount, uint32_t channels) override;
|
||
|
||
void SetParameter(const char* name, float value) override;
|
||
float GetParameter(const char* name) const override;
|
||
size_t GetParameterCount() const override;
|
||
const char* GetParameterName(size_t index) const override;
|
||
|
||
// 频段控制
|
||
enum class Band {
|
||
LowPass,
|
||
HighPass,
|
||
BandPass,
|
||
Notch,
|
||
LowShelf,
|
||
HighShelf,
|
||
Peaking
|
||
};
|
||
|
||
void SetBand(size_t index, Band type, float frequency, float gainDb, float Q);
|
||
void SetBandEnabled(size_t index, bool enabled);
|
||
|
||
struct BandParams {
|
||
Band type = Band::Peaking;
|
||
float frequency = 1000.0f;
|
||
float gainDb = 0.0f;
|
||
float Q = 1.0f;
|
||
bool enabled = true;
|
||
};
|
||
|
||
const BandParams& GetBand(size_t index) const { return m_bands[index]; }
|
||
|
||
private:
|
||
void UpdateCoefficients(size_t index);
|
||
void ProcessBand(float* buffer, uint32_t sampleCount, size_t bandIndex);
|
||
|
||
private:
|
||
static constexpr size_t MaxBands = 10;
|
||
std::array<BandParams, MaxBands> m_bands;
|
||
std::array<std::array<float, 5>, MaxBands> m_coefficients;
|
||
|
||
std::vector<float> m_x1, m_x2, m_y1, m_y2;
|
||
};
|
||
|
||
} // namespace Audio
|
||
} // namespace XCEngine
|
||
```
|
||
|
||
### 3.5 Dynamics (动态效果器)
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
namespace Audio {
|
||
|
||
class Compressor : public IAudioEffect {
|
||
public:
|
||
Compressor();
|
||
~Compressor();
|
||
|
||
const char* GetName() const override { return "Compressor"; }
|
||
void Process(float* buffer, uint32_t sampleCount, uint32_t channels) override;
|
||
|
||
void SetParameter(const char* name, float value) override;
|
||
float GetParameter(const char* name) const override;
|
||
size_t GetParameterCount() const override;
|
||
const char* GetParameterName(size_t index) const override;
|
||
|
||
void SetThreshold(float db);
|
||
float GetThreshold() const { return m_thresholdDb; }
|
||
|
||
void SetRatio(float ratio);
|
||
float GetRatio() const { return m_ratio; }
|
||
|
||
void SetAttack(float ms);
|
||
float GetAttack() const { return m_attackMs; }
|
||
|
||
void SetRelease(float ms);
|
||
float GetRelease() const { return m_releaseMs; }
|
||
|
||
float GetGainReduction() const { return m_gainReduction; }
|
||
|
||
private:
|
||
float m_thresholdDb = -20.0f;
|
||
float m_ratio = 4.0f;
|
||
float m_attackMs = 10.0f;
|
||
float m_releaseMs = 100.0f;
|
||
|
||
float m_gainReduction = 0.0f;
|
||
float m_envelope = 0.0f;
|
||
};
|
||
|
||
class Limiter : public IAudioEffect {
|
||
public:
|
||
Limiter();
|
||
~Limiter();
|
||
|
||
const char* GetName() const override { return "Limiter"; }
|
||
void Process(float* buffer, uint32_t sampleCount, uint32_t channels) override;
|
||
|
||
void SetParameter(const char* name, float value) override;
|
||
float GetParameter(const char* name) const override;
|
||
size_t GetParameterCount() const override;
|
||
const char* GetParameterName(size_t index) const override;
|
||
|
||
void SetCeiling(float db);
|
||
float GetCeiling() const { return m_ceilingDb; }
|
||
|
||
void SetRelease(float ms);
|
||
float GetRelease() const { return m_releaseMs; }
|
||
|
||
private:
|
||
float m_ceilingDb = -0.3f;
|
||
float m_releaseMs = 50.0f;
|
||
float m_envelope = 0.0f;
|
||
};
|
||
|
||
} // namespace Audio
|
||
} // namespace XCEngine
|
||
```
|
||
|
||
---
|
||
|
||
## 第四章 3D 空间音频
|
||
|
||
### 4.1 SpatializerParams 空间化参数
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
namespace Audio {
|
||
|
||
struct SpatializerParams {
|
||
Vector3 listenerPosition;
|
||
Quaternion listenerRotation;
|
||
Vector3 listenerVelocity;
|
||
|
||
Vector3 sourcePosition;
|
||
Vector3 sourceVelocity;
|
||
Quaternion sourceRotation;
|
||
|
||
Audio3DParams params;
|
||
|
||
float GetDistanceAttenuation() const;
|
||
float GetPan() const;
|
||
float GetDopplerShift() const;
|
||
};
|
||
```
|
||
|
||
### 4.2 HRTF 空间化
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
namespace Audio {
|
||
|
||
class HRTF {
|
||
public:
|
||
HRTF();
|
||
~HRTF();
|
||
|
||
// 方向设置
|
||
void SetDirection(int elevation, int azimuth);
|
||
void GetDirection(int& elevation, int& azimuth);
|
||
|
||
// HRTF 脉冲响应
|
||
void GetLeftEarTimeHRTF(std::vector<float>& data);
|
||
void GetLeftEarFreqHRTF(std::vector<float>& data);
|
||
void GetRightEarTimeHRTF(std::vector<float>& data);
|
||
void GetRightEarFreqHRTF(std::vector<float>& data);
|
||
|
||
// 空间化处理
|
||
void Process(const float* input, float* outputLeft, float* outputRight,
|
||
size_t sampleCount, size_t channels);
|
||
|
||
// 淡入淡出处理
|
||
void ApplyFadeWindow(const std::vector<float>& blockLast,
|
||
const std::vector<float>& blockNext,
|
||
std::vector<float>* fadeResult);
|
||
|
||
// 重采样
|
||
void Resample(const float* input, float* output, size_t inputSize,
|
||
size_t outputSize, size_t channels);
|
||
|
||
private:
|
||
void BuildReacherTree();
|
||
int SearchNearestIndex(int elevation, int azimuth);
|
||
double CalculateSphereDistance(int elev1, int azim1, int elev2, int azim2);
|
||
|
||
private:
|
||
int m_realAzimuth = 0;
|
||
int m_realElevation = 0;
|
||
int m_azimuth = 0;
|
||
int m_elevation = 0;
|
||
bool m_isSwapLeftRight = false;
|
||
int m_directionIndex = 0;
|
||
|
||
using ResampledHRTFT = std::vector<float>;
|
||
using ResampledHRTFPairT = std::pair<ResampledHRTFT, ResampledHRTFT>;
|
||
|
||
std::vector<ResampledHRTFPairT> m_hrtfResampledTimeDomain;
|
||
std::vector<ResampledHRTFPairT> m_hrtfResampledFreqDomain;
|
||
|
||
std::map<int, std::pair<std::vector<int>, std::vector<int>>> m_hrtfDirections;
|
||
|
||
std::unique_ptr<FFTFilter> m_filter;
|
||
std::unique_ptr<FFTFilter> m_hrtfFilterLeft;
|
||
std::unique_ptr<FFTFilter> m_hrtfFilterRight;
|
||
|
||
std::vector<float> m_fadeWindow;
|
||
};
|
||
|
||
} // namespace Audio
|
||
} // namespace XCEngine
|
||
```
|
||
|
||
### 4.3 DopplerEffect 多普勒效应
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
namespace Audio {
|
||
|
||
class DopplerEffect {
|
||
public:
|
||
DopplerEffect();
|
||
~DopplerEffect();
|
||
|
||
void SetSpeedOfSound(float metersPerSecond);
|
||
float GetSpeedOfSound() const { return m_speedOfSound; }
|
||
|
||
void SetDopplerLevel(float level);
|
||
float GetDopplerLevel() const { return m_dopplerLevel; }
|
||
|
||
float CalculatePitchShift(const Vector3& sourceVelocity,
|
||
const Vector3& listenerVelocity,
|
||
const Vector3& sourceToListener);
|
||
|
||
private:
|
||
float m_speedOfSound = 343.0f;
|
||
float m_dopplerLevel = 1.0f;
|
||
};
|
||
|
||
} // namespace Audio
|
||
} // namespace XCEngine
|
||
```
|
||
|
||
### 4.4 OcclusionSystem 遮蔽系统
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
namespace Audio {
|
||
|
||
class OcclusionSystem {
|
||
public:
|
||
OcclusionSystem();
|
||
~OcclusionSystem();
|
||
|
||
// 遮蔽计算
|
||
float CalculateOcclusion(const Vector3& sourcePos, const Vector3& listenerPos,
|
||
const std::vector<Vector3>& obstaclePositions);
|
||
|
||
float CalculateObstruction(const Vector3& sourcePos, const Vector3& listenerPos,
|
||
const Vector3& obstaclePos);
|
||
|
||
// 遮蔽参数
|
||
void SetOcclusionHighFreqAbsorption(float value);
|
||
float GetOcclusionHighFreqAbsorption() const { return m_occlusionHighFreqAbsorb; }
|
||
|
||
void SetObstructionHighFreqDamping(float value);
|
||
float GetObstructionHighFreqDamping() const { return m_obstructionHighFreqDamp; }
|
||
|
||
private:
|
||
float m_occlusionHighFreqAbsorb = 0.5f;
|
||
float m_obstructionHighFreqDamp = 0.5f;
|
||
};
|
||
|
||
} // namespace Audio
|
||
} // namespace XCEngine
|
||
```
|
||
|
||
---
|
||
|
||
## 第五章 音频后端抽象层
|
||
|
||
### 5.1 IAudioBackend 接口
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
namespace Audio {
|
||
|
||
class IAudioBackend {
|
||
public:
|
||
virtual ~IAudioBackend() = default;
|
||
|
||
// 初始化与销毁
|
||
virtual bool Initialize(const AudioConfig& config) = 0;
|
||
virtual void Shutdown() = 0;
|
||
|
||
// 设备查询
|
||
virtual String GetDeviceName() const = 0;
|
||
virtual void GetAvailableDevices(std::vector<String>& devices) = 0;
|
||
virtual bool SetDevice(const String& deviceName) = 0;
|
||
|
||
// 混音器控制
|
||
virtual float GetMasterVolume() const = 0;
|
||
virtual void SetMasterVolume(float volume) = 0;
|
||
|
||
virtual bool IsMuted() const = 0;
|
||
virtual void SetMuted(bool muted) = 0;
|
||
|
||
// 播放控制
|
||
virtual void Start() = 0;
|
||
virtual void Stop() = 0;
|
||
virtual void Suspend() = 0;
|
||
virtual void Resume() = 0;
|
||
|
||
// 音频处理
|
||
virtual void ProcessAudio(float* buffer, uint32_t bufferSize,
|
||
uint32_t channels, uint32_t sampleRate) = 0;
|
||
|
||
// 状态查询
|
||
virtual bool IsRunning() const = 0;
|
||
virtual AudioConfig GetConfig() const = 0;
|
||
};
|
||
|
||
} // namespace Audio
|
||
} // namespace XCEngine
|
||
```
|
||
|
||
### 5.2 WASAPI 后端
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
namespace Audio {
|
||
namespace WASAPI {
|
||
|
||
class WASAPIBackend : public IAudioBackend {
|
||
public:
|
||
WASAPIBackend();
|
||
~WASAPIBackend() override;
|
||
|
||
bool Initialize(const AudioConfig& config) override;
|
||
void Shutdown() override;
|
||
|
||
String GetDeviceName() const override;
|
||
void GetAvailableDevices(std::vector<String>& devices) override;
|
||
bool SetDevice(const String& deviceName) override;
|
||
|
||
float GetMasterVolume() const override;
|
||
void SetMasterVolume(float volume) override;
|
||
|
||
bool IsMuted() const override;
|
||
void SetMuted(bool muted) override;
|
||
|
||
void Start() override;
|
||
void Stop() override;
|
||
void Suspend() override;
|
||
void Resume() override;
|
||
|
||
void ProcessAudio(float* buffer, uint32_t bufferSize,
|
||
uint32_t channels, uint32_t sampleRate) override;
|
||
|
||
bool IsRunning() const override { return m_isRunning; }
|
||
AudioConfig GetConfig() const override { return m_config; }
|
||
|
||
private:
|
||
MMRESULT InitDevice();
|
||
MMRESULT InitClient();
|
||
MMRESULT InitBuffer();
|
||
|
||
static DWORD WINAPI AudioThreadProc(LPVOID lpParameter);
|
||
void AudioThread();
|
||
|
||
void OnAudioCallback(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance,
|
||
DWORD_PTR dwParam1, DWORD_PTR dwParam2);
|
||
static void CALLBACK StaticAudioCallback(HWAVEOUT hwo, UINT uMsg,
|
||
DWORD_PTR dwInstance,
|
||
DWORD_PTR dwParam1, DWORD_PTR dwParam2);
|
||
|
||
private:
|
||
bool m_isRunning = false;
|
||
std::thread m_audioThread;
|
||
|
||
AudioConfig m_config;
|
||
|
||
WAVEFORMATEX m_waveFormat = {};
|
||
HWAVEOUT m_hWaveOut = nullptr;
|
||
HANDLE m_hEvent = nullptr;
|
||
|
||
std::vector<float> m_mixBuffer;
|
||
uint32_t m_mixBufferSize = 0;
|
||
|
||
std::vector<WAVEOUTCAPS> m_waveOutCaps;
|
||
String m_deviceName;
|
||
|
||
IAudioEffect* m_masterEffect = nullptr;
|
||
};
|
||
|
||
} // namespace WASAPI
|
||
} // namespace Audio
|
||
} // namespace XCEngine
|
||
```
|
||
|
||
### 5.3 OpenAL 后端
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
namespace Audio {
|
||
namespace OpenAL {
|
||
|
||
class OpenALBackend : public IAudioBackend {
|
||
public:
|
||
OpenALBackend();
|
||
~OpenALBackend() override;
|
||
|
||
bool Initialize(const AudioConfig& config) override;
|
||
void Shutdown() override;
|
||
|
||
String GetDeviceName() const override;
|
||
void GetAvailableDevices(std::vector<String>& devices) override;
|
||
bool SetDevice(const String& deviceName) override;
|
||
|
||
float GetMasterVolume() const override;
|
||
void SetMasterVolume(float volume) override;
|
||
|
||
bool IsMuted() const override;
|
||
void SetMuted(bool muted) override;
|
||
|
||
void Start() override;
|
||
void Stop() override;
|
||
void Suspend() override;
|
||
void Resume() override;
|
||
|
||
void ProcessAudio(float* buffer, uint32_t bufferSize,
|
||
uint32_t channels, uint32_t sampleRate) override;
|
||
|
||
bool IsRunning() const override { return m_isRunning; }
|
||
AudioConfig GetConfig() const override { return m_config; }
|
||
|
||
private:
|
||
bool m_isRunning = false;
|
||
AudioConfig m_config;
|
||
|
||
ALCdevice* m_device = nullptr;
|
||
ALCcontext* m_context = nullptr;
|
||
ALuint m_source = 0;
|
||
ALuint m_buffers[2];
|
||
|
||
std::vector<float> m_mixBuffer;
|
||
};
|
||
|
||
} // namespace OpenAL
|
||
} // namespace Audio
|
||
} // namespace XCEngine
|
||
```
|
||
|
||
---
|
||
|
||
## 第六章 音频系统核心
|
||
|
||
### 6.1 AudioSystem
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
namespace Audio {
|
||
|
||
class AudioSystem {
|
||
public:
|
||
static AudioSystem& Get();
|
||
|
||
void Initialize(const AudioConfig& config);
|
||
void Shutdown();
|
||
|
||
void Update(float deltaTime);
|
||
|
||
// 后端控制
|
||
void SetBackend(std::unique_ptr<IAudioBackend> backend);
|
||
IAudioBackend* GetBackend() const { return m_backend.get(); }
|
||
|
||
// 设备控制
|
||
String GetCurrentDevice() const;
|
||
void SetDevice(const String& deviceName);
|
||
void GetAvailableDevices(std::vector<String>& devices);
|
||
|
||
// 全局混音控制
|
||
float GetMasterVolume() const;
|
||
void SetMasterVolume(float volume);
|
||
|
||
bool IsMuted() const;
|
||
void SetMuted(bool muted);
|
||
|
||
// 音频处理
|
||
void ProcessAudio(float* buffer, uint32_t sampleCount, uint32_t channels);
|
||
|
||
// 资源管理
|
||
AudioClip* LoadAudioClip(const String& filePath);
|
||
void UnloadAudioClip(AudioClip* clip);
|
||
|
||
AudioMixer* CreateMixer(const String& name);
|
||
void DestroyMixer(AudioMixer* mixer);
|
||
|
||
// 空间化
|
||
void SetListenerTransform(const Vector3& position, const Quaternion& rotation);
|
||
void SetListenerVelocity(const Vector3& velocity);
|
||
|
||
const Vector3& GetListenerPosition() const { return m_listenerPosition; }
|
||
const Quaternion& GetListenerRotation() const { return m_listenerRotation; }
|
||
const Vector3& GetListenerVelocity() const { return m_listenerVelocity; }
|
||
|
||
// 统计信息
|
||
struct Stats {
|
||
uint32_t activeSources;
|
||
uint32_t totalSources;
|
||
uint64_t memoryUsage;
|
||
float cpuUsage;
|
||
};
|
||
const Stats& GetStats() const { return m_stats; }
|
||
|
||
private:
|
||
AudioSystem() = default;
|
||
~AudioSystem() = default;
|
||
|
||
AudioSystem(const AudioSystem&) = delete;
|
||
AudioSystem& operator=(const AudioSystem&) = delete;
|
||
|
||
void ProcessSource(AudioSourceComponent* source);
|
||
void ApplyGlobalEffects(float* buffer, uint32_t sampleCount, uint32_t channels);
|
||
|
||
private:
|
||
std::unique_ptr<IAudioBackend> m_backend;
|
||
|
||
Vector3 m_listenerPosition = Vector3::Zero();
|
||
Quaternion m_listenerRotation = Quaternion::Identity();
|
||
Vector3 m_listenerVelocity = Vector3::Zero();
|
||
|
||
std::vector<std::unique_ptr<AudioClip>> m_loadedClips;
|
||
std::map<String, std::unique_ptr<AudioMixer>> m_mixers;
|
||
|
||
std::vector<AudioSourceComponent*> m_activeSources;
|
||
|
||
Stats m_stats = {};
|
||
float m_deltaTime = 0.0f;
|
||
};
|
||
|
||
} // namespace Audio
|
||
} // namespace XCEngine
|
||
```
|
||
|
||
### 6.2 AudioSourceComponent
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
namespace Components {
|
||
|
||
class AudioSourceComponent : public Component {
|
||
public:
|
||
AudioSourceComponent();
|
||
~AudioSourceComponent();
|
||
|
||
// 播放控制
|
||
void Play();
|
||
void Pause();
|
||
void Stop(StopMode mode = StopMode::Immediate);
|
||
bool IsPlaying() const { return m_playState == Audio::PlayState::Playing; }
|
||
bool IsPaused() const { return m_playState == Audio::PlayState::Paused; }
|
||
|
||
// 音频剪辑
|
||
void SetClip(Audio::AudioClip* clip);
|
||
Audio::AudioClip* GetClip() const { return m_clip; }
|
||
|
||
// 播放参数
|
||
void SetVolume(float volume);
|
||
float GetVolume() const { return m_volume; }
|
||
|
||
void SetPitch(float pitch);
|
||
float GetPitch() const { return m_pitch; }
|
||
|
||
void SetPan(float pan);
|
||
float GetPan() const { return m_pan; }
|
||
|
||
// 循环
|
||
void SetLooping(bool loop);
|
||
bool IsLooping() const { return m_isLooping; }
|
||
|
||
// 3D 空间化
|
||
void SetSpatialize(bool spatialize);
|
||
bool IsSpatialize() const { return m_spatialize; }
|
||
|
||
void Set3DParams(const Audio::Audio3DParams& params);
|
||
const Audio::Audio3DParams& Get3DParams() const { return m_3DParams; }
|
||
|
||
void SetDopplerLevel(float level);
|
||
float GetDopplerLevel() const { return m_3DParams.dopplerLevel; }
|
||
|
||
void SetSpread(float spread);
|
||
float GetSpread() const { return m_3DParams.spread; }
|
||
|
||
void SetReverbZoneMix(float mix);
|
||
float GetReverbZoneMix() const { return m_3DParams.reverbZoneMix; }
|
||
|
||
// 混音器
|
||
void SetOutputMixer(Audio::AudioMixer* mixer);
|
||
Audio::AudioMixer* GetOutputMixer() const { return m_outputMixer; }
|
||
|
||
// 播放位置
|
||
void SetTime(float seconds);
|
||
float GetTime() const;
|
||
float GetDuration() const;
|
||
|
||
// 能量检测
|
||
float GetEnergy() const { return m_energy; }
|
||
void StartEnergyDetect();
|
||
void StopEnergyDetect();
|
||
bool IsEnergyDetecting() const { return m_isEnergyDetecting; }
|
||
|
||
// Component 虚函数
|
||
void Update(float deltaTime) override;
|
||
void OnEnable() override;
|
||
void OnDisable() override;
|
||
void OnDestroy() override;
|
||
|
||
private:
|
||
void Apply3DAttenuation();
|
||
void ProcessEffects(float* buffer, uint32_t sampleCount);
|
||
void UpdateEnergy(const float* buffer, uint32_t sampleCount);
|
||
|
||
private:
|
||
Audio::AudioClip* m_clip = nullptr;
|
||
Audio::AudioMixer* m_outputMixer = nullptr;
|
||
|
||
PlayState m_playState = PlayState::Stopped;
|
||
bool m_isLooping = false;
|
||
|
||
float m_volume = 1.0f;
|
||
float m_pitch = 1.0f;
|
||
float m_pan = 0.0f;
|
||
bool m_spatialize = true;
|
||
|
||
Audio::Audio3DParams m_3DParams;
|
||
|
||
// 播放状态
|
||
uint64_t m_samplePosition = 0;
|
||
double m_lastingTime = 0.0;
|
||
|
||
// 能量检测
|
||
bool m_isEnergyDetecting = false;
|
||
float m_energy = 0.0f;
|
||
float m_maxEnergy = 5.0f;
|
||
std::deque<float> m_energyHistory;
|
||
|
||
// 效果链
|
||
std::vector<Audio::IAudioEffect*> m_effects;
|
||
std::unique_ptr<Audio::HRTF> m_hrtf;
|
||
std::unique_ptr<Audio::DopplerEffect> m_doppler;
|
||
|
||
// 输出缓冲
|
||
static constexpr size_t BufferSize = 8192;
|
||
std::vector<float> m_outputBuffer;
|
||
};
|
||
|
||
} // namespace Components
|
||
} // namespace XCEngine
|
||
```
|
||
|
||
### 6.3 AudioListenerComponent
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
namespace Components {
|
||
|
||
class AudioListenerComponent : public Component {
|
||
public:
|
||
AudioListenerComponent();
|
||
~AudioListenerComponent();
|
||
|
||
// 能量检测
|
||
float GetEnergy() const { return m_energy; }
|
||
const float* GetFrequencyData() const { return m_frequencyData.data(); }
|
||
size_t GetFrequencyDataSize() const { return m_frequencyData.size(); }
|
||
|
||
// 全局参数
|
||
void SetMasterVolume(float volume);
|
||
float GetMasterVolume() const { return m_masterVolume; }
|
||
|
||
void SetMute(bool mute);
|
||
bool IsMute() const { return m_mute; }
|
||
|
||
// 空间化参数
|
||
void SetDopplerLevel(float level);
|
||
float GetDopplerLevel() const { return m_dopplerLevel; }
|
||
|
||
void SetSpeedOfSound(float metersPerSecond);
|
||
float GetSpeedOfSound() const { return m_speedOfSound; }
|
||
|
||
// 混响
|
||
void SetReverbLevel(float level);
|
||
float GetReverbLevel() const { return m_reverbLevel; }
|
||
|
||
void SetReverb(Audio::AudioMixer* reverb);
|
||
Audio::AudioMixer* GetReverb() const { return m_reverb; }
|
||
|
||
// Component 虚函数
|
||
void Update(float deltaTime) override;
|
||
|
||
private:
|
||
float m_masterVolume = 1.0f;
|
||
bool m_mute = false;
|
||
float m_dopplerLevel = 1.0f;
|
||
float m_speedOfSound = 343.0f;
|
||
float m_reverbLevel = 1.0f;
|
||
|
||
Audio::AudioMixer* m_reverb = nullptr;
|
||
|
||
float m_energy = 0.0f;
|
||
std::vector<float> m_frequencyData;
|
||
};
|
||
|
||
} // namespace Components
|
||
} // namespace XCEngine
|
||
```
|
||
|
||
---
|
||
|
||
## 第七章 事件系统
|
||
|
||
### 7.1 AudioEvent
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
namespace Audio {
|
||
|
||
class AudioEvent {
|
||
public:
|
||
AudioEvent() = default;
|
||
AudioEvent(const String& name) : m_name(name) {}
|
||
|
||
using Callback = std::function<void()>;
|
||
using FloatCallback = std::function<void(float)>;
|
||
|
||
uint64_t Subscribe(Callback callback);
|
||
uint64_t Subscribe(FloatCallback callback, float param);
|
||
|
||
void Unsubscribe(uint64_t id);
|
||
void ProcessUnsubscribes();
|
||
|
||
void Invoke() const;
|
||
void Invoke(float param) const;
|
||
|
||
void Clear();
|
||
|
||
const String& GetName() const { return m_name; }
|
||
void SetName(const String& name) { m_name = name; }
|
||
|
||
private:
|
||
struct ListenerBase {
|
||
virtual ~ListenerBase() = default;
|
||
virtual void Call() = 0;
|
||
virtual void CallFloat(float) = 0;
|
||
};
|
||
|
||
template<typename Func>
|
||
struct Listener : ListenerBase {
|
||
Listener(Func&& f) : func(std::move(f)) {}
|
||
void Call() override { func(); }
|
||
void CallFloat(float) override {
|
||
if constexpr (std::is_invocable_v<Func, float>) {
|
||
func(0.0f);
|
||
} else {
|
||
func();
|
||
}
|
||
}
|
||
Func func;
|
||
};
|
||
|
||
String m_name;
|
||
std::vector<std::pair<uint64_t, std::unique_ptr<ListenerBase>>> m_listeners;
|
||
std::vector<uint64_t> m_pendingUnsubscribes;
|
||
uint64_t m_nextId = 0;
|
||
};
|
||
|
||
} // namespace Audio
|
||
} // namespace XCEngine
|
||
```
|
||
|
||
### 7.2 AudioEventSystem
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
namespace Audio {
|
||
|
||
class AudioEventSystem {
|
||
public:
|
||
static AudioEventSystem& Get();
|
||
|
||
void Initialize();
|
||
void Shutdown();
|
||
|
||
// 事件创建
|
||
AudioEvent* CreateEvent(const String& name);
|
||
AudioEvent* GetEvent(const String& name);
|
||
AudioEvent* GetEvent(uint64_t id);
|
||
|
||
void DestroyEvent(const String& name);
|
||
void DestroyEvent(uint64_t id);
|
||
|
||
// 触发事件
|
||
void TriggerEvent(const String& name);
|
||
void TriggerEvent(uint64_t id);
|
||
void TriggerEvent(const String& name, float param);
|
||
void TriggerEvent(uint64_t id, float param);
|
||
|
||
// 订阅
|
||
uint64_t Subscribe(const String& eventName, AudioEvent::Callback callback);
|
||
uint64_t Subscribe(const String& eventName, AudioEvent::FloatCallback callback, float param);
|
||
|
||
// 状态
|
||
bool HasEvent(const String& name) const;
|
||
bool HasEvent(uint64_t id) const;
|
||
size_t GetEventCount() const { return m_events.size(); }
|
||
|
||
private:
|
||
AudioEventSystem() = default;
|
||
~AudioEventSystem() = default;
|
||
|
||
std::map<String, std::unique_ptr<AudioEvent>> m_events;
|
||
std::map<uint64_t, AudioEvent*> m_idToEvent;
|
||
uint64_t m_nextEventId = 0;
|
||
};
|
||
|
||
} // namespace Audio
|
||
} // namespace XCEngine
|
||
```
|
||
|
||
---
|
||
|
||
## 第八章 资源管理集成
|
||
|
||
### 8.1 AudioClipLoader
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
namespace Resources {
|
||
|
||
class AudioClipLoader : public IResourceLoader {
|
||
public:
|
||
AudioClipLoader();
|
||
~AudioClipLoader() override;
|
||
|
||
bool CanLoad(const String& extension) const override;
|
||
IResource* Load(const String& filePath) override;
|
||
bool LoadAsync(const String& filePath, std::function<void(IResource*)> callback) override;
|
||
void Unload(IResource* resource) override;
|
||
|
||
// 获取支持的文件格式
|
||
static const std::vector<String>& GetSupportedExtensions();
|
||
|
||
private:
|
||
static std::vector<String> s_supportedExtensions;
|
||
};
|
||
|
||
} // namespace Resources
|
||
} // namespace XCEngine
|
||
```
|
||
|
||
### 8.2 ResourceManager 集成
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
namespace Resources {
|
||
|
||
// 在 ResourceManager 中添加音频相关接口
|
||
|
||
template<>
|
||
class ResourceHandle<Audio::AudioClip> {
|
||
public:
|
||
ResourceHandle() = default;
|
||
explicit ResourceHandle(Audio::AudioClip* resource);
|
||
|
||
Audio::AudioClip* Get() const { return m_resource; }
|
||
Audio::AudioClip* operator->() const { return m_resource; }
|
||
|
||
explicit operator bool() const { return m_resource != nullptr; }
|
||
|
||
private:
|
||
Audio::AudioClip* m_resource = nullptr;
|
||
};
|
||
|
||
} // namespace Resources
|
||
} // namespace XCEngine
|
||
```
|
||
|
||
---
|
||
|
||
## 第九章 目录结构
|
||
|
||
```
|
||
XCEngine/
|
||
├── engine/ # 引擎核心库
|
||
│ ├── include/XCEngine/
|
||
│ │ ├── Audio/ # 音频模块
|
||
│ │ │ ├── AudioSystem.h # 音频系统入口
|
||
│ │ │ ├── AudioConfig.h # 配置结构
|
||
│ │ │ ├── AudioTypes.h # 基础类型定义
|
||
│ │ │ ├── IAudioBackend.h # 后端抽象接口
|
||
│ │ │ ├── AudioBackendFactory.h # 后端工厂
|
||
│ │ │ │
|
||
│ │ │ ├── AudioClip.h # 音频剪辑资源
|
||
│ │ │ ├── AudioMixer.h # 混音器
|
||
│ │ │ ├── AudioBank.h # 音频银行
|
||
│ │ │ │
|
||
│ │ │ ├── IAudioEffect.h # 效果器接口
|
||
│ │ │ ├── FFTFilter.h # FFT频谱分析
|
||
│ │ │ ├── Reverbation.h # 混响效果
|
||
│ │ │ ├── Equalizer.h # 均衡器
|
||
│ │ │ ├── Compressor.h # 压缩器
|
||
│ │ │ ├── Limiter.h # 限制器
|
||
│ │ │ ├── DopplerEffect.h # 多普勒效应
|
||
│ │ │ ├── OcclusionSystem.h # 遮蔽系统
|
||
│ │ │ │
|
||
│ │ │ ├── Spatializer.h # 空间化处理
|
||
│ │ │ ├── HRTF.h # HRTF实现
|
||
│ │ │ │
|
||
│ │ │ ├── AudioEvent.h # 音频事件
|
||
│ │ │ ├── AudioEventSystem.h # 事件系统
|
||
│ │ │ │
|
||
│ │ │ ├── WASAPI/
|
||
│ │ │ │ └── WASAPIBackend.h # WASAPI后端
|
||
│ │ │ └── OpenAL/
|
||
│ │ │ └── OpenALBackend.h # OpenAL后端
|
||
│ │ │ │
|
||
│ │ │ └── XCEngineAudio.h # 主头文件
|
||
│ │ │
|
||
│ │ └── Components/
|
||
│ │ ├── AudioSourceComponent.h # 声源组件
|
||
│ │ └── AudioListenerComponent.h # 监听器组件
|
||
│ │
|
||
│ └── src/Audio/
|
||
│ ├── AudioSystem.cpp
|
||
│ ├── AudioClip.cpp
|
||
│ ├── AudioMixer.cpp
|
||
│ ├── FFTFilter.cpp
|
||
│ ├── Reverbation.cpp
|
||
│ ├── Equalizer.cpp
|
||
│ ├── HRTF.cpp
|
||
│ ├── DopplerEffect.cpp
|
||
│ ├── OcclusionSystem.cpp
|
||
│ ├── AudioEventSystem.cpp
|
||
│ ├── WASAPI/
|
||
│ │ └── WASAPIBackend.cpp
|
||
│ └── OpenAL/
|
||
│ └── OpenALBackend.cpp
|
||
│
|
||
├── mvs/ # 示例应用
|
||
│ └── Music fluctuations/ # 音频示例(参考)
|
||
│ ├── source/
|
||
│ │ ├── audio/ # 基础音频
|
||
│ │ ├── audio3d/ # 3D音频
|
||
│ │ ├── kissfft/ # FFT库
|
||
│ │ └── libsamplerate/ # 重采样库
|
||
│ └── res/ # 音频资源
|
||
│
|
||
└── tests/Audio/ # 音频模块测试
|
||
├── AudioSystemTest.cpp
|
||
├── AudioClipTest.cpp
|
||
├── SpatializerTest.cpp
|
||
└── HRTFTest.cpp
|
||
```
|
||
|
||
---
|
||
|
||
## 附录:实现优先级
|
||
|
||
### 第一阶段 - 基础音频
|
||
1. AudioSystem 核心框架
|
||
2. AudioClip 资源加载(WAV格式)
|
||
3. AudioSourceComponent 播放控制
|
||
4. AudioListenerComponent 监听器
|
||
5. WASAPI 后端实现
|
||
|
||
### 第二阶段 - 3D 空间音频
|
||
1. HRTF 空间化
|
||
2. DopplerEffect 多普勒效应
|
||
3. OcclusionSystem 遮蔽系统
|
||
4. 距离衰减
|
||
|
||
### 第三阶段 - 效果系统
|
||
1. FFTFilter 频谱分析
|
||
2. Reverbation 混响
|
||
3. Equalizer 均衡器
|
||
4. Compressor/Limiter 动态效果
|
||
5. 效果链系统
|
||
|
||
### 第四阶段 - 混音与事件
|
||
1. AudioMixer 混音器
|
||
2. AudioEvent 事件系统
|
||
3. AudioBank 分段加载
|
||
4. OpenAL 后端实现
|
||
|
||
### 第五阶段 - 优化与扩展
|
||
1. 资源异步加载
|
||
2. 性能优化
|
||
3. profiler 集成
|
||
4. 更多音频格式支持
|