feat(audio): 使用 oto/v3 重构音频播放系统,移除 beep/v2 依赖

核心变更:
- 实现全局 oto.Context 单例管理(sync.Once)
- 实现一次性播放:PlayWav/PlayMP3(支持 context 取消)
- 实现 BGM 循环播放:PlayMP3Loop(atomic.Bool + WaitGroup)
- 迁移所有业务层到新 API(TTS/BGM/待机音频)
- 添加完整的单元测试(6/6 通过)

技术栈:
- oto/v3 v3.3.2(低级音频播放)
- hajimehoshi/go-mp3 v0.3.4(MP3 解码)
- youpy/go-wav v0.3.2(WAV 解码)

移除依赖:
- gopxl/beep/v2 及所有相关依赖

优化:
- 流式播放,无需预先加载
- 并发安全,无竞态条件
- 资源管理清晰(defer cleanup)
- Sleep 间隔优化(1ms → 10ms,降低 CPU 占用)
This commit is contained in:
2026-04-08 19:21:48 +08:00
parent b5f7c823c8
commit 788327047c
15 changed files with 396 additions and 149 deletions

View File

@@ -7,7 +7,6 @@ import (
"game-driver/pkg/utils"
"sync"
"github.com/gopxl/beep/v2/speaker"
"go.uber.org/zap"
)
@@ -22,13 +21,10 @@ func PlayBgm() leaf.HandlerFunc {
}
if bgm != nil {
zap.S().Infoln("背景音乐解析成功")
// 等待组
var wait sync.WaitGroup
defer wait.Wait()
// 结束信号通道
a := make(chan struct{})
// 发送结束信号
defer close(a)
wait.Add(1)
@@ -38,18 +34,14 @@ func PlayBgm() leaf.HandlerFunc {
zap.S().Infoln("开始播放背景音乐")
defer zap.S().Infoln("结束背景音乐播放")
ctrl, closer, e := audio.PlayBgmMP3(bgm)
defer closer()
if e != nil {
zap.S().Errorln("播放背景音乐异常:", e)
_, cleanup, err := audio.PlayMP3Loop(bgm)
if err != nil {
zap.S().Errorln("播放背景音乐异常:", err)
return
}
defer cleanup()
<-a
speaker.Lock()
ctrl.Streamer = nil
speaker.Unlock()
}()
} else {
zap.S().Infoln("未解析到背景音乐")