mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-03-22 10:34:30 +08:00
feat(audio): 实现音频管理系统基础功能
- 添加音频管理器抽象基类和接口定义 - 支持背景音乐、音效和3D音效播放 - 实现音量控制和音频淡入淡出效果 - 提供音频播放器池化管理机制 - 支持通过资源ID或路径播放音频 - 实现主音量、音乐音量和音效音量独立控制 - 添加音频播放状态检测功能 - 支持低通滤波器和混响效果设置 - 实现系统资源自动清理机制
This commit is contained in:
parent
7da12c05ce
commit
506c26f945
447
GFramework.Core.Godot/system/AbstractAudioManagerSystem.cs
Normal file
447
GFramework.Core.Godot/system/AbstractAudioManagerSystem.cs
Normal file
@ -0,0 +1,447 @@
|
||||
using GFramework.Core.extensions;
|
||||
using GFramework.Core.system;
|
||||
using Godot;
|
||||
|
||||
namespace GFramework.Core.Godot.system;
|
||||
|
||||
/// <summary>
|
||||
/// 音频管理器抽象基类,提供音频播放的基础实现
|
||||
/// </summary>
|
||||
public abstract class AbstractAudioManagerSystem : AbstractSystem, IAudioManagerSystem
|
||||
{
|
||||
/// <summary>
|
||||
/// 音频资源加载系统依赖
|
||||
/// </summary>
|
||||
protected IResourceLoadSystem? ResourceLoadSystem;
|
||||
|
||||
/// <summary>
|
||||
/// 资源目录系统依赖
|
||||
/// </summary>
|
||||
protected IAssetCatalogSystem? AssetCatalogSystem;
|
||||
|
||||
/// <summary>
|
||||
/// 背景音乐播放器
|
||||
/// </summary>
|
||||
protected AudioStreamPlayer? MusicPlayer;
|
||||
|
||||
/// <summary>
|
||||
/// 音效播放器列表
|
||||
/// </summary>
|
||||
protected readonly List<AudioStreamPlayer> SoundPlayers = [];
|
||||
|
||||
/// <summary>
|
||||
/// 可用音效播放器队列
|
||||
/// </summary>
|
||||
protected readonly Queue<AudioStreamPlayer> AvailableSoundPlayers = new();
|
||||
|
||||
/// <summary>
|
||||
/// 3D音效播放器列表
|
||||
/// </summary>
|
||||
protected readonly List<AudioStreamPlayer3D> Sound3DPlayers = [];
|
||||
|
||||
/// <summary>
|
||||
/// 可用3D音效播放器队列
|
||||
/// </summary>
|
||||
protected readonly Queue<AudioStreamPlayer3D> AvailableSound3DPlayers = new();
|
||||
|
||||
/// <summary>
|
||||
/// 资源工厂系统依赖
|
||||
/// </summary>
|
||||
protected IResourceFactorySystem? ResourceFactorySystem;
|
||||
|
||||
/// <summary>
|
||||
/// 背景音乐音量
|
||||
/// </summary>
|
||||
protected float MusicVolume = 1.0f;
|
||||
|
||||
/// <summary>
|
||||
/// 音效音量
|
||||
/// </summary>
|
||||
protected float SoundVolume = 1.0f;
|
||||
|
||||
/// <summary>
|
||||
/// 主音量
|
||||
/// </summary>
|
||||
protected float MasterVolume = 1.0f;
|
||||
|
||||
/// <summary>
|
||||
/// 特效音量
|
||||
/// </summary>
|
||||
protected float SfxVolume = 1.0f;
|
||||
|
||||
/// <summary>
|
||||
/// 语音音量
|
||||
/// </summary>
|
||||
protected float VoiceVolume = 1.0f;
|
||||
|
||||
/// <summary>
|
||||
/// 环境音量
|
||||
/// </summary>
|
||||
protected float AmbientVolume = 1.0f;
|
||||
|
||||
/// <summary>
|
||||
/// 音乐淡入淡出动画
|
||||
/// </summary>
|
||||
protected Tween? MusicFadeTween;
|
||||
|
||||
/// <summary>
|
||||
/// 最大同时播放的音效数量
|
||||
/// </summary>
|
||||
protected const int MaxSoundPlayers = 10;
|
||||
|
||||
/// <summary>
|
||||
/// 最大同时播放的3D音效数量
|
||||
/// </summary>
|
||||
protected const int MaxSound3DPlayers = 5;
|
||||
|
||||
/// <summary>
|
||||
/// 所有者节点的抽象属性
|
||||
/// </summary>
|
||||
protected abstract Node Owner { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 系统初始化方法
|
||||
/// </summary>
|
||||
protected override void OnInit()
|
||||
{
|
||||
// 获取依赖的系统
|
||||
ResourceLoadSystem = this.GetSystem<IResourceLoadSystem>();
|
||||
AssetCatalogSystem = this.GetSystem<IAssetCatalogSystem>();
|
||||
ResourceFactorySystem = this.GetSystem<IResourceFactorySystem>();
|
||||
|
||||
// 初始化背景音乐播放器
|
||||
MusicPlayer = new AudioStreamPlayer();
|
||||
Owner.AddChild(MusicPlayer);
|
||||
|
||||
// 预创建音效播放器池
|
||||
for (var i = 0; i < MaxSoundPlayers; i++)
|
||||
{
|
||||
var soundPlayer = new AudioStreamPlayer();
|
||||
Owner.AddChild(soundPlayer);
|
||||
soundPlayer.Finished += () => OnSoundFinished(soundPlayer);
|
||||
SoundPlayers.Add(soundPlayer);
|
||||
AvailableSoundPlayers.Enqueue(soundPlayer);
|
||||
}
|
||||
|
||||
// 预创建3D音效播放器池
|
||||
for (var i = 0; i < MaxSound3DPlayers; i++)
|
||||
{
|
||||
var sound3DPlayer = new AudioStreamPlayer3D();
|
||||
Owner.AddChild(sound3DPlayer);
|
||||
sound3DPlayer.Finished += () => OnSound3DFinished(sound3DPlayer);
|
||||
Sound3DPlayers.Add(sound3DPlayer);
|
||||
AvailableSound3DPlayers.Enqueue(sound3DPlayer);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 当音效播放完成时的回调
|
||||
/// </summary>
|
||||
/// <param name="player">完成播放的音频播放器</param>
|
||||
private void OnSoundFinished(AudioStreamPlayer player)
|
||||
{
|
||||
// 将播放器放回可用队列
|
||||
AvailableSoundPlayers.Enqueue(player);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 当3D音效播放完成时的回调
|
||||
/// </summary>
|
||||
/// <param name="player">完成播放的3D音频播放器</param>
|
||||
private void OnSound3DFinished(AudioStreamPlayer3D player)
|
||||
{
|
||||
// 将播放器放回可用队列
|
||||
AvailableSound3DPlayers.Enqueue(player);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 播放背景音乐
|
||||
/// </summary>
|
||||
/// <param name="audioPath">音频文件路径</param>
|
||||
/// <param name="volume">音量大小,范围0-1</param>
|
||||
/// <param name="loop">是否循环播放</param>
|
||||
public virtual void PlayMusic(string audioPath, float volume = 1.0f, bool loop = true)
|
||||
{
|
||||
var audioStream = ResourceLoadSystem?.LoadResource<AudioStream>(audioPath);
|
||||
if (audioStream == null || MusicPlayer == null) return;
|
||||
|
||||
// 停止当前正在进行的淡入淡出效果
|
||||
MusicFadeTween?.Kill();
|
||||
|
||||
MusicPlayer.Stream = audioStream;
|
||||
MusicPlayer.VolumeDb = LinearToDb(volume * MusicVolume * MasterVolume);
|
||||
MusicPlayer.Play();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 通过资源ID播放背景音乐
|
||||
/// </summary>
|
||||
/// <param name="musicId">音乐资源ID</param>
|
||||
/// <param name="volume">音量大小,范围0-1</param>
|
||||
/// <param name="loop">是否循环播放</param>
|
||||
public virtual void PlayMusic(AssetCatalog.ResourceId musicId, float volume = 1.0f, bool loop = true)
|
||||
{
|
||||
PlayMusic(musicId.Path, volume, loop);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 播放音效
|
||||
/// </summary>
|
||||
/// <param name="audioPath">音频文件路径</param>
|
||||
/// <param name="volume">音量大小,范围0-1</param>
|
||||
/// <param name="pitch">音调调整</param>
|
||||
public virtual void PlaySound(string audioPath, float volume = 1.0f, float pitch = 1.0f)
|
||||
{
|
||||
if (AvailableSoundPlayers.Count == 0) return;
|
||||
|
||||
var audioStream = ResourceLoadSystem?.LoadResource<AudioStream>(audioPath);
|
||||
if (audioStream == null) return;
|
||||
|
||||
var player = AvailableSoundPlayers.Dequeue();
|
||||
player.Stream = audioStream;
|
||||
player.VolumeDb = LinearToDb(volume * SoundVolume * MasterVolume);
|
||||
player.Play();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 通过资源ID播放音效
|
||||
/// </summary>
|
||||
/// <param name="soundId">音效资源ID</param>
|
||||
/// <param name="volume">音量大小,范围0-1</param>
|
||||
/// <param name="pitch">音调调整</param>
|
||||
public virtual void PlaySound(AssetCatalog.ResourceId soundId, float volume = 1.0f, float pitch = 1.0f)
|
||||
{
|
||||
PlaySound(soundId.Path, volume, pitch);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 播放3D音效
|
||||
/// </summary>
|
||||
/// <param name="audioPath">音频文件路径</param>
|
||||
/// <param name="position">3D空间中的位置</param>
|
||||
/// <param name="volume">音量大小,范围0-1</param>
|
||||
public virtual void PlaySound3D(string audioPath, Vector3 position, float volume = 1.0f)
|
||||
{
|
||||
if (AvailableSound3DPlayers.Count == 0) return;
|
||||
|
||||
var audioStream = ResourceLoadSystem?.LoadResource<AudioStream>(audioPath);
|
||||
if (audioStream == null) return;
|
||||
|
||||
var player = AvailableSound3DPlayers.Dequeue();
|
||||
player.Stream = audioStream;
|
||||
player.VolumeDb = LinearToDb(volume * SoundVolume * MasterVolume);
|
||||
player.Position = position;
|
||||
player.Play();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 停止背景音乐
|
||||
/// </summary>
|
||||
public virtual void StopMusic()
|
||||
{
|
||||
MusicFadeTween?.Kill();
|
||||
MusicPlayer?.Stop();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 暂停背景音乐
|
||||
/// </summary>
|
||||
public virtual void PauseMusic()
|
||||
{
|
||||
MusicFadeTween?.Kill();
|
||||
// todo 需要记录音乐播放位置,以便恢复播放时从正确位置开始
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 恢复背景音乐播放
|
||||
/// </summary>
|
||||
public virtual void ResumeMusic()
|
||||
{
|
||||
MusicPlayer?.Play();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置背景音乐音量
|
||||
/// </summary>
|
||||
/// <param name="volume">音量大小,范围0-1</param>
|
||||
public virtual void SetMusicVolume(float volume)
|
||||
{
|
||||
MusicVolume = volume;
|
||||
if (MusicPlayer != null)
|
||||
{
|
||||
MusicPlayer.VolumeDb = LinearToDb(MusicVolume * MasterVolume);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置音效音量
|
||||
/// </summary>
|
||||
/// <param name="volume">音量大小,范围0-1</param>
|
||||
public virtual void SetSoundVolume(float volume)
|
||||
{
|
||||
SoundVolume = volume;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置主音量
|
||||
/// </summary>
|
||||
/// <param name="volume">音量大小,范围0-1</param>
|
||||
public virtual void SetMasterVolume(float volume)
|
||||
{
|
||||
MasterVolume = volume;
|
||||
|
||||
// 更新音乐音量
|
||||
if (MusicPlayer != null)
|
||||
{
|
||||
MusicPlayer.VolumeDb = LinearToDb(MusicVolume * MasterVolume);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置SFX音量
|
||||
/// </summary>
|
||||
/// <param name="volume">音量大小,范围0-1</param>
|
||||
public virtual void SetSfxVolume(float volume)
|
||||
{
|
||||
SfxVolume = volume;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置语音音量
|
||||
/// </summary>
|
||||
/// <param name="volume">音量大小,范围0-1</param>
|
||||
public virtual void SetVoiceVolume(float volume)
|
||||
{
|
||||
VoiceVolume = volume;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置环境音量
|
||||
/// </summary>
|
||||
/// <param name="volume">音量大小,范围0-1</param>
|
||||
public virtual void SetAmbientVolume(float volume)
|
||||
{
|
||||
AmbientVolume = volume;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查背景音乐是否正在播放
|
||||
/// </summary>
|
||||
/// <returns>正在播放返回true,否则返回false</returns>
|
||||
public virtual bool IsMusicPlaying()
|
||||
{
|
||||
return MusicPlayer?.Playing ?? false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 淡入背景音乐
|
||||
/// </summary>
|
||||
/// <param name="audioPath">音频文件路径</param>
|
||||
/// <param name="duration">淡入持续时间(秒)</param>
|
||||
/// <param name="volume">目标音量</param>
|
||||
public virtual void FadeInMusic(string audioPath, float duration, float volume = 1.0f)
|
||||
{
|
||||
var audioStream = ResourceLoadSystem?.LoadResource<AudioStream>(audioPath);
|
||||
if (audioStream == null || MusicPlayer == null) return;
|
||||
|
||||
// 停止当前正在进行的淡入淡出效果
|
||||
MusicFadeTween?.Kill();
|
||||
|
||||
MusicPlayer.Stream = audioStream;
|
||||
MusicPlayer.VolumeDb = LinearToDb(0.0f); // 初始音量为0
|
||||
MusicPlayer.Play();
|
||||
|
||||
// 创建淡入动画
|
||||
MusicFadeTween = Owner.CreateTween();
|
||||
MusicFadeTween.TweenProperty(MusicPlayer, "volume_db", LinearToDb(volume * MusicVolume * MasterVolume),
|
||||
duration);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 淡出背景音乐
|
||||
/// </summary>
|
||||
/// <param name="duration">淡出持续时间(秒)</param>
|
||||
public virtual void FadeOutMusic(float duration)
|
||||
{
|
||||
if (MusicPlayer == null) return;
|
||||
|
||||
// 停止当前正在进行的淡入淡出效果
|
||||
MusicFadeTween?.Kill();
|
||||
|
||||
// 创建淡出动画
|
||||
MusicFadeTween = Owner.CreateTween();
|
||||
MusicFadeTween.TweenProperty(MusicPlayer, "volume_db", LinearToDb(0.0f), duration);
|
||||
MusicFadeTween.TweenCallback(Callable.From(() => MusicPlayer.Stop()));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置低通滤波器强度
|
||||
/// </summary>
|
||||
/// <param name="amount">滤波器强度,范围0-1</param>
|
||||
public virtual void SetLowPassFilter(float amount)
|
||||
{
|
||||
// TODO: 实现低通滤波器效果
|
||||
// 可以通过AudioEffectLowPassFilter实现
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置音频混响效果
|
||||
/// </summary>
|
||||
/// <param name="roomSize">房间大小</param>
|
||||
/// <param name="damping">阻尼</param>
|
||||
/// <param name="wetLevel">湿声级别</param>
|
||||
public virtual void SetReverb(float roomSize, float damping, float wetLevel)
|
||||
{
|
||||
// TODO: 实现音频混响效果
|
||||
// 可以通过AudioEffectReverb实现
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将线性音量值转换为分贝值
|
||||
/// </summary>
|
||||
/// <param name="linear">线性音量值(0-1)</param>
|
||||
/// <returns>分贝值</returns>
|
||||
protected static float LinearToDb(float linear)
|
||||
{
|
||||
return linear > 0 ? 20 * Mathf.Log(linear) : -100;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将分贝值转换为线性音量值
|
||||
/// </summary>
|
||||
/// <param name="db">分贝值</param>
|
||||
/// <returns>线性音量值(0-1)</returns>
|
||||
protected static float DbToLinear(float db)
|
||||
{
|
||||
return db > -100 ? Mathf.Exp(db / 20) : 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 系统销毁时清理资源
|
||||
/// </summary>
|
||||
protected void OnDestroy()
|
||||
{
|
||||
// 停止并清理淡入淡出动画
|
||||
MusicFadeTween?.Kill();
|
||||
|
||||
// 清理音乐播放器
|
||||
MusicPlayer?.QueueFree();
|
||||
|
||||
// 清理音效播放器池
|
||||
foreach (var player in SoundPlayers)
|
||||
{
|
||||
player.QueueFree();
|
||||
}
|
||||
|
||||
// 清理3D音效播放器池
|
||||
foreach (var player in Sound3DPlayers)
|
||||
{
|
||||
player.QueueFree();
|
||||
}
|
||||
|
||||
SoundPlayers.Clear();
|
||||
AvailableSoundPlayers.Clear();
|
||||
Sound3DPlayers.Clear();
|
||||
AvailableSound3DPlayers.Clear();
|
||||
}
|
||||
}
|
||||
101
GFramework.Core.Godot/system/IAudioManagerSystem.cs
Normal file
101
GFramework.Core.Godot/system/IAudioManagerSystem.cs
Normal file
@ -0,0 +1,101 @@
|
||||
using GFramework.Core.system;
|
||||
using Godot;
|
||||
|
||||
namespace GFramework.Core.Godot.system;
|
||||
|
||||
/// <summary>
|
||||
/// 音频管理器系统接口,用于统一管理背景音乐和音效的播放
|
||||
/// </summary>
|
||||
public interface IAudioManagerSystem : ISystem
|
||||
{
|
||||
/// <summary>
|
||||
/// 播放背景音乐
|
||||
/// </summary>
|
||||
/// <param name="audioPath">音频文件路径</param>
|
||||
/// <param name="volume">音量大小,范围0-1</param>
|
||||
/// <param name="loop">是否循环播放</param>
|
||||
void PlayMusic(string audioPath, float volume = 1.0f, bool loop = true);
|
||||
|
||||
/// <summary>
|
||||
/// 播放音效
|
||||
/// </summary>
|
||||
/// <param name="audioPath">音频文件路径</param>
|
||||
/// <param name="volume">音量大小,范围0-1</param>
|
||||
/// <param name="pitch">音调调整</param>
|
||||
void PlaySound(string audioPath, float volume = 1.0f, float pitch = 1.0f);
|
||||
|
||||
/// <summary>
|
||||
/// 停止背景音乐
|
||||
/// </summary>
|
||||
void StopMusic();
|
||||
|
||||
/// <summary>
|
||||
/// 暂停背景音乐
|
||||
/// </summary>
|
||||
void PauseMusic();
|
||||
|
||||
/// <summary>
|
||||
/// 恢复背景音乐播放
|
||||
/// </summary>
|
||||
void ResumeMusic();
|
||||
|
||||
/// <summary>
|
||||
/// 设置背景音乐音量
|
||||
/// </summary>
|
||||
/// <param name="volume">音量大小,范围0-1</param>
|
||||
void SetMusicVolume(float volume);
|
||||
|
||||
/// <summary>
|
||||
/// 设置音效音量
|
||||
/// </summary>
|
||||
/// <param name="volume">音量大小,范围0-1</param>
|
||||
void SetSoundVolume(float volume);
|
||||
|
||||
/// <summary>
|
||||
/// 设置主音量
|
||||
/// </summary>
|
||||
/// <param name="volume">音量大小,范围0-1</param>
|
||||
void SetMasterVolume(float volume);
|
||||
|
||||
/// <summary>
|
||||
/// 检查背景音乐是否正在播放
|
||||
/// </summary>
|
||||
/// <returns>正在播放返回true,否则返回false</returns>
|
||||
bool IsMusicPlaying();
|
||||
|
||||
/// <summary>
|
||||
/// 淡入背景音乐
|
||||
/// </summary>
|
||||
/// <param name="audioPath">音频文件路径</param>
|
||||
/// <param name="duration">淡入持续时间(秒)</param>
|
||||
/// <param name="volume">目标音量</param>
|
||||
void FadeInMusic(string audioPath, float duration, float volume = 1.0f);
|
||||
|
||||
/// <summary>
|
||||
/// 淡出背景音乐
|
||||
/// </summary>
|
||||
/// <param name="duration">淡出持续时间(秒)</param>
|
||||
void FadeOutMusic(float duration);
|
||||
|
||||
/// <summary>
|
||||
/// 播放3D音效
|
||||
/// </summary>
|
||||
/// <param name="audioPath">音频文件路径</param>
|
||||
/// <param name="position">3D空间中的位置</param>
|
||||
/// <param name="volume">音量大小,范围0-1</param>
|
||||
void PlaySound3D(string audioPath, Vector3 position, float volume = 1.0f);
|
||||
|
||||
/// <summary>
|
||||
/// 设置低通滤波器强度
|
||||
/// </summary>
|
||||
/// <param name="amount">滤波器强度,范围0-1</param>
|
||||
void SetLowPassFilter(float amount);
|
||||
|
||||
/// <summary>
|
||||
/// 设置音频混响效果
|
||||
/// </summary>
|
||||
/// <param name="roomSize">房间大小</param>
|
||||
/// <param name="damping">阻尼</param>
|
||||
/// <param name="wetLevel">湿声级别</param>
|
||||
void SetReverb(float roomSize, float damping, float wetLevel);
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user