Skip to content

08 · 音频系统 ​

本章讲解 BGM、SE、Voice 和 Ambient 四类音频的控制。

音频类型 ​

类型全称用途特点
bgmBackground Music背景音乐循环播放,唯一
seSound Effect音效单次播放,可多个同时
voiceVoice语音单次播放,与对话同步
ambientAmbient环境音循环播放,可多个

BGM 背景音乐 ​

播放 ​

dsl
bgm "Media/bgm_main.wav" volume=0.7
参数说明
路径相对于项目根目录
volume音量(0~1,默认 1)

停止 ​

DSL 中没有专门的停止 BGM 命令。停止 BGM 需使用 C# API:

csharp
// 在 C# 场景脚本中
gameController.StopBgm();       // 同步
await gameController.StopBgmAsync();  // 异步

或者在场景切换时,引擎会根据 DefaultAutoStopBgm 配置自动停止 BGM。

切换 ​

直接播放新的 BGM 会自动停止旧的:

dsl
bgm "Media/bgm_town.wav" volume=0.7
// ... 小镇场景
bgm "Media/bgm_battle.wav" volume=0.9   // 自动停止 bgm_town

BGM 是唯一的

同一时间只能播放一首 BGM。播放新的会自动停止旧的。

BGM 交叉淡入 ​

在 StoryScript 子类内,可通过受保护的 _pipeline 字段发送命令实现 BGM 交叉淡入(渐出旧曲 + 渐入新曲):

csharp
await _pipeline.SendAsync(new BgmQueueCommand 
{ 
    Path = "Media/bgm_part2.wav", 
    Volume = 0.7f, 
    CrossFadeDuration = 2.0 
});

DSL 限制

bgm 命令只支持播放。队列、停止、交叉淡入等高级功能需要通过 C# API 调用。

SE 音效 ​

dsl
se "Media/se_click.wav" volume=0.5

SE 是单次播放的,可以多个同时播放(如点击声 + 提示音):

dsl
se "Media/se_select.wav"
say "你选择了攻击!" speaker="系统"
se "Media/se_hit.wav"
shake duration=0.3 intensity=10

Voice 语音 ​

Voice(角色语音)走独立的语音通道(单轨):同一时间只播放一句语音,新的会原子替换旧的。

方式一:独立语句 ​

dsl
voice "Media/Voice/zhang_hello.wav" volume=0.9
参数说明
路径相对于项目根目录
volume音量(0~1,默认 1)
auto_stop前进时是否自动停止(true/false,默认跟随 DefaultAutoStopVoice)

方式二:随 say 行内播放(推荐) ​

对话展示的同时播放该句语音,无需手动对齐:

dsl
say "你好!我是老张。" speaker="老张" voice="Media/Voice/zhang_hello.wav"

单轨原子替换

语音通道只有一条。下一句 say voice= 或独立 voice 会顶替当前正在播放的语音——天然实现「翻到下一句就换语音」。

停止语音 ​

当 say 之后没有下一句(例如对话结束、跳转场景前),语音不会自动被顶替,可用 stop_voice 主动中断:

dsl
say "再见了。" speaker="老张" voice="Media/Voice/zhang_bye.wav"
stop_voice        // 立即中断当前语音
navigate "chapter2"

回顾重播也会播放语音

say voice= 在回溯/前进重看一句时同样会重播该句语音(符合直觉:重看应听到同一句)。若重放场景不希望出声,可在 C# 侧控制。

C# API ​

csharp
// StoryScript 子类中,Ctrl 即 IGameController
Ctrl.PlayVoice("Media/Voice/zhang_hello.wav");                  // 同步触发
await Ctrl.PlayVoiceAsync("Media/Voice/zhang_hello.wav");       // 异步
Ctrl.StopVoice();                                              // 停止当前语音

// 或在 SayAsync 中直接带语音
await Ctrl.SayAsync("你好!我是老张。", "老张", voice: "Media/Voice/zhang_hello.wav");

Ambient 环境音 ​

dsl
ambient "Media/amb_rain.wav" volume=0.4

Ambient 是循环播放的,可以多个同时存在(如雨声 + 风声 + 篝火声):

dsl
ambient "Media/amb_rain.wav" volume=0.5
ambient "Media/amb_wind.wav" volume=0.3
ambient "Media/amb_fire.wav" volume=0.4
say "雨夜,你在壁炉旁取暖。" speaker="旁白"

停止环境音 ​

dsl
stop_ambient            // 停止所有环境音
stop_ambient "amb_rain" // 停止指定环境音

音频格式 ​

格式推荐说明
WAV✅无损,引擎原生支持,加载快
MP3✅压缩,体积小
Ogg✅压缩,开源

WAV vs MP3

  • WAV——音质最好,加载最快,但文件大。适合短音效(SE/Voice)。
  • MP3——文件小,适合长 BGM。

音频目录结构 ​

Media/
├── Audio/
│   ├── BGM/
│   │   ├── bgm_main.wav
│   │   ├── bgm_town.wav
│   │   └── bgm_battle.wav
│   ├── SE/
│   │   ├── se_click.wav
│   │   ├── se_hit.wav
│   │   └── se_select.wav
│   ├── Voice/
│   │   ├── zhang_hello.wav
│   │   └── zhang_bye.wav
│   └── Ambient/
│       ├── amb_rain.wav
│       └── amb_wind.wav

路径

音频路径相对于项目根目录,通常以 Media/ 开头。也可以放在 Media/Audio/BGM/ 等子目录中。

自动停止 ​

引擎配置中有两个自动停止选项:

配置默认值说明
DefaultAutoStopBgmtrue场景切换时自动停止 BGM
DefaultAutoStopVoicetrue对话切换时自动停止 Voice

动手练习 ​

给灯塔场景配上完整音频:

dsl
label lighthouse:
  bgm "Media/bgm_main.wav" volume=0.6
  ambient "Media/amb_rain.wav" volume=0.5
  ambient "Media/amb_wind.wav" volume=0.3

  se "Media/se_door.wav"
  say "你推开了灯塔的门。" speaker="旁白"
  say "风声和雨声渐渐远去。" speaker="旁白"

  ambient "Media/amb_fire.wav" volume=0.4
  say "壁炉里的火噼啪作响。" speaker="旁白"

  // 战斗或事件
  se "Media/se_hit.wav"
  shake duration=0.3 intensity=10

  // 离开时
  stop_ambient
  // BGM 会在场景切换时自动停止(DefaultAutoStopBgm=true)
  transition "fade" duration=1.5

下一步 ​

音频掌握了!下一章学习 NVL 模式——让文本累积显示。

基于 .NET 10 + Avalonia 12 · Apache-2.0 License