diff --git a/docs/design/13-playtest-criteria.md b/docs/design/13-playtest-criteria.md
index 5ddca539..6d9c82e9 100644
--- a/docs/design/13-playtest-criteria.md
+++ b/docs/design/13-playtest-criteria.md
@@ -108,3 +108,29 @@
3. 设置边界:settings.voice 切换后下一句起用对应目录(voice 缓存键含性别);settings.bgm=0 时无 bgm 层加载;speed=1.7 时下一句 playbackRate 生效。
4. 双击=重听在其声明可用的阶段生效(escape 检查/simon 规则/rpg 场景 desc 等)。
5. 菜单约定(裁决②):适用游戏的模态菜单 = 单击循环 / 双击确认 / 上滑帮助 / 下滑关闭(RPG 豁免)。
+
+---
+
+## 8. round3 变更记录(simon 手势映射例外)
+
+> round3 G5(research/04-playtests/round2/synthesis.md §2)改变了 simon 的**玩法**
+> 手势映射(不是向导层断言):input 阶段双击永远=作答(第 6 音色),主动重听改绑
+> 上滑。按本研究「playtest 断言零改动」红线的例外流程,本节只做追加记录 §3 受影响
+> 断言的替换口径;§3 既有文字不回改,其余 5 个游戏断言零改动。
+
+- §3 关键路径 4「主动重听:input 阶段且期望输入非 doubletap 时双击 → 断言 chances
+ 减少、inputIdx 清零、序列重播」→ 替换为:**input 阶段上滑(且期望输入非 up)=
+ 主动重听**,断言目标不变(chances 减少、inputIdx 清零、序列重播)。
+- §3 边界「双击冲突(裁定①):期望输入恰为 doubletap 时双击 = 答题(inputIdx 前进),
+ 不触发重听」→ 保留并强化为:**input 阶段双击永远=作答**——期望非 doubletap 时
+ 照常判错(耗机会/死亡),不再触发重听。
+- §3 边界「chances=0 时双击非期望手势:不判错(round 不变、inputIdx 不变)、播
+ chances_out」→ 替换为:**chances=0 时上滑非期望手势**,断言目标不变。
+- 新增边界断言:期望输入恰为 up 时上滑=作答(六手势全是答题输入,00 号文档 §5.3
+ 豁免同款);非输入阶段(gameover/菜单)上滑行为不变。
+- 随上述改口的测试脚手架微调(非断言变更):两处「错手势注入」的取值从
+ `GESTURES.find(g => g !== exp && g !== 'doubletap')` 增加排除 `up`(round3 后
+ up=重听键,注入 up 会触发重听而非判错,与旧版注入 doubletap 需避开是同一道理)。
+- 依据:docs/design/14-guide-layer.md「round3 v1.2」§8/G5;simon playtest 断言仅
+ 上述 3 处改口(108 条总数不变),其余断言(含教学、复活、结算、菜单、序列约束、
+ 速度下限)零改动。
diff --git a/docs/design/14-guide-layer.md b/docs/design/14-guide-layer.md
index 38d15df8..b48b1af3 100644
--- a/docs/design/14-guide-layer.md
+++ b/docs/design/14-guide-layer.md
@@ -114,3 +114,73 @@
`tools/extract_voice_text.py` 已刷新 `web/harness/voice_text.json`(428 句)。
- 转写渲染适配:实际播出的 `voice/gd_*` 由 play 捕获照常渲染;被 idle-skip 的
向导句单独标注「本句按 idle-only 跳过未播」。
+
+---
+
+# 14 · 向导交互层设计裁定(round3 v1.2 增补)
+
+> 依据:research/04-playtests/round2/synthesis.md(G1~G8 + §3 新语音表,唯一事实源)。
+> 本文只做**追加**,上文 v1 / round2 裁定不回改;实现载体同前(`web/engine/guide.js`
+> + 各游戏 game.js 接线),全部改动已落地。G8(不做项)照裁定书记录,不再列。
+
+## 8. round3 裁定落地摘要(G1~G7)
+
+| # | 裁定 | 落地 |
+|---|---|---|
+| G1 | rhythm「轮到你」迟到 bug | **根因诊断**:round2 F3 把 gd_answer 排在 `leadBarT0 + 4*spb`——那是首个应答窗口**起点本身**(领奏小节的末尾),不是窗口前;P4 转写(窗口 t+79~95、gd_answer t+93.7)即窗口开后才响,起不到预警作用。**修复**:排程点改到 `leadBarT0`(窗口前整整 1 小节 = 领奏小节头);`_armAnswerCue`/`_fireAnswerCue` 承接——菜单恢复也是一次「进 main」,旧标记已消费时对恢复后首个未判定窗口重排同款标记(已迫近则 0.15s 内尽早补上);上一句结束后的下一句不适用(裁定原文)。gd_answer 语音 full 档经曲谱定时队列直达(不走 guide queue),turn earcon **standard 也发**(off 全静不变)。guide.test 增转写级断言:真实跑 90BPM 一曲,gd_answer 时刻 < 首窗口起点,且窗口起点 − gd_answer ≈ 4×spb。 |
+| G2 | rhythm 教学降难 DDA | 同一步连续 2 次失败 → 该步领奏**降速 25% 重演**(`_tutRate=0.75`:该步领奏与应答网格间隔 ×1/0.75,领奏小节头仍对齐 BGM 小节,BGM 不变速;排程照走 `_sched` 绝对时间 + 40ms 泵,泵与判定零改动)+ full 档先播 `gd_slow`「我放慢一些,跟着试试。」(经 `_speakGuarded` 串行,播完才重演);每教学局 1 次封顶(`_tutSlowUsed`);该步做对或离开(跳步)恢复正常速度;降速重演后该步重新给两次机会。**off 档维持 round2 的 retry_skip 跳步原路径**(6 playtest 断言零改动红线)。 |
+| G3 | rhythm 恢复 count-in 可感知化 | **根因诊断**:round2 F3.2 的 count-in 排了但**从未按时响过**——底鼓 push 进 `_sched` 后没有重排,队头是数秒外的领奏音符,40ms 泵的 `LOOKAHEAD(0.6s)` 前瞻窗口永远轮不到队尾的 count-in(复现实测:恢复后 4 记底鼓与 beat 震全部迟到聚堆),P3 听到的正是「恢复后 5 秒死寂」。**修复**:push 后 `_sortSched()`;底鼓音量 0.7→**1.0**(sfx 层独立于 BGM,每拍 beat 震保持);full 档恢复时先经 `_speakGuarded` 播 `gd_count`「四拍之后,继续。」(每局恢复限 1 次,`_gdCountUsed`;链完/缺失兜底后才开始数拍);恢复用令牌 `_resumeSeq` 防 count-in 语音期间再开菜单的旧恢复串场。**off 档保持 v1 即时续播**(playtest 断言零改动红线)。 |
+| G4 | escape 保险丝→新目标断链 | 拾取保险丝的 `unlock_cabinet`(关键获得不可跳)播完后接 `gd_next_fuse`「保险丝到手。接下来,去找电箱。」——游戏反馈层**全档位**(走游戏语音链不走向导通道,gd_economy 先例)。 |
+| G5 | simon 双击双义根治 | **改全局规则**:input 阶段**双击永远=作答(第 6 音色)**——期望恰为 doubletap 判对,否则照常判错,不再承担重听;主动重听改绑**上滑**(期望输入恰为 up 时上滑=作答,六手势全是答题输入的 00 §5.3 豁免同款);非输入阶段行为不变。`gd_economy` 按裁定书新文案**重录**(记不住就向上滑…);教学第 6 音色步资产 `t6_double`「双击,是这个声音。」不含重听语义、无需改动,教学步与新文案不矛盾。**超出裁定书 §3 清单的同口径修正(2 句,见 §9 注)**:`gd_relisten`(input 看门狗提示)与 `t7_retry`(教学收尾链)旧文案都在教「双击重听」,不清掉等于保留 P0,随 G5 一并重录为上滑口径,台词改动仅「双击→向上滑」机械替换。 |
+| G6 | simon 局尾反馈轻量化 | 每轮成功在既有轮结算链(`_roundClear` 的 correct/chance_plus 链)尾追加 `gd_clear`「漂亮,过了。」(每局 1 次);本轮完成数超过历史最佳且确有旧纪录(`best>0`)时追加 `gd_record`「破纪录了。」(每局 1 次;结算另有 new_record,此处是局中破纪录的即时一刻)。游戏反馈层全档位。 |
+| G7 | space 方向呼喊第二通道 | loud 警报档(撞击前 500ms)回调里同窗直达播 `voice/dir_
`「左!/右!/上!/下!」——与 sfx/alarm 分属 voice/sfx 两通道天然同时不互顶(引擎对白 duck 压 BGM 保证可闻);**直达式播放不排队**(呼喊必须赶在撞击前,宁可顶掉里程/充能类短句也不排到链尾迟到);游戏反馈层全档位。 |
+
+## 9. round3 新增语音资产台词表(11 句 ×2 性别 = 22 文件;其中 G5 为重录 3 句)
+
+全文与 synthesis §3 逐字一致(speaker/instruct 沿用各游戏旁白 pair 常量,dir_* 按表注
+用 space 旁白 pair);另 2 句为 G5 手势映射的同口径机械修正(裁定书 §3 未列,落地
+原因见 §8/G5——不清掉「双击重听」旧文案,input 看门狗与教学收尾仍在教已废除的手势):
+
+| 游戏 | id | 全文 | 触发 |
+|---|---|---|---|
+| rhythm | `gd_slow` | 我放慢一些,跟着试试。 | 教学连 2 失败降速重演前(G2,full 档,每教学局 1 次) |
+| rhythm | `gd_count` | 四拍之后,继续。 | 菜单恢复 count-in 前(G3,full 档,每局恢复限 1 次) |
+| escape | `gd_next_fuse` | 保险丝到手。接下来,去找电箱。 | 拾取保险丝链尾(G4,全档位) |
+| simon | `gd_economy`(重录) | 记不住就向上滑,重新听一遍。免费机会有两次,用完要扣一次机会。 | 开局教学末尾(G5,全档位) |
+| simon | `gd_clear` | 漂亮,过了。 | 每轮成功链尾(G6,全档位,每局 1 次) |
+| simon | `gd_record` | 破纪录了。 | 局中破个人纪录(G6,全档位,每局 1 次) |
+| space | `dir_left` / `dir_right` / `dir_up` / `dir_down` | 左!/ 右!/ 上!/ 下! | loud 警报档方向呼喊(G7,全档位) |
+| simon | `gd_relisten`(同口径修正) | 需要的话,向上滑可以重新听一遍序列。 | input 10s 看门狗(原「双击可以重新听」,G5) |
+| simon | `t7_retry`(同口径修正) | 答错可以消耗机会重听。向上滑,可以随时重听。 | 教学收尾链(原「双击,可以随时重听」,G5) |
+
+资产落位与管线同前:`web//audio/voice/{female,male}/.{ogg,m4a}`
+(`tools/gen_voice_dual.py --game --only ` 生成 → `--convert` 落盘 →
+`tools/check_all_assets.py` 终检)。
+
+## 10. round3 验证记录
+
+- 6 playtest(guide=off):除 simon 按 13 号文档 round3 变更记录改口 3 处断言
+ (input 双击=作答、上滑=重听;108 条总数与 round2 基线一致)外,**断言零改动
+ 全绿**:storyline 54 / escape 103 / simon 108 / rhythm 81 / space 113 / rpg 139。
+- `web/harness/guide.test.mjs` **93 条断言全绿**(round2 基线 52 条既有断言零改动,
+ 其余为新增):G1(gd_answer 时间窗=窗口前整整 1 小节、恢复后重排仍在窗前)、
+ G2(连 2 失败降速 ×1/0.75 + gd_slow + 做对恢复 + 每局封顶后回退 retry_skip)、
+ G3(恢复先 gd_count 后 count-in、底鼓重排入队头、beat 震、每局限 1 次)、
+ G5(双击作答/上滑重听/期望恰为 up 时上滑=作答,full 与 off 双档)、
+ G6(gd_clear 每局 1 次 + 破纪录 gd_record)、G7(dir_* 与 loud 警报同窗 ≤50ms)。
+ 为此给 harness mock 补了 setInterval/虚拟 ctx.currentTime/用例间 localStorage 隔离。
+- 转写 harness 修复(`web/harness/mock.mjs`,工具层非玩法):decodeAudioData 原来
+ 按「最近一次 fetch 的 url」估时长,prewarm 并发下 voice 会随机继承 bgm 的 90s
+ 时长,语音结束定时器形同虚设(链全靠兜底看门狗推进、教学 tap 被滞留语音当跳过
+ 吃掉)——改为按 ArrayBuffer 自身 `__url` 估算,与各 playtest mock 对齐。
+- `tools/check_all_assets.py` 全绿(双格式配对、无 0 字节、全可解码、双性别集合
+ 一致);`tools/extract_voice_text.py` 已刷新 `web/harness/voice_text.json`
+ (437 句)。`gen_voice_dual.py --check` 中 rpg/tut_b0 等 4 句「缺 staging」为
+ R5 既有已知项(资产已先行落盘、staging 无 wav),非本轮引入。
+- 转写抽查(research/04-playtests/transcripts/,6 份全部重跑、零资产缺失):
+ rhythm gd_answer 落在首窗口前整整 1 小节(t+67.0 vs 窗口 t+69.7)、教学第 2 句
+ 连 2 失败触发「我放慢一些」+ 慢速领奏(拍距 ×1/0.75)+ 做对恢复、菜单恢复
+ 「四拍之后,继续」+ 4 记底鼓 count-in 在;escape 保险丝后紧接 gd_next_fuse、
+ 其后再走两步;simon 看门狗提示上滑重听 + 期望恰为 up 时上滑作答 + 双击音
+ 双击作答,全程无双击歧义时刻;space 每次撞击前 500ms 警报与「左!/右!/上!/
+ 下!」同窗到达。
diff --git a/research/04-playtests/transcripts/escape.md b/research/04-playtests/transcripts/escape.md
index 5ea7aa4c..43689af7 100644
--- a/research/04-playtests/transcripts/escape.md
+++ b/research/04-playtests/transcripts/escape.md
@@ -13,98 +13,111 @@ t+ 0.0s 【状态】引导第 1/8 步 引导第 1/8 步,等我做手势(
#### 【玩家动作】照引导单击了一下
t+ 0.0s ▶ 语音:「先活动一下。朝任意方向滑一下,走一小步。」
-t+ 20.0s ♪ 向导音:turn(轮到你)
-t+ 20.0s 【状态】引导第 2/8 步 引导第 2/8 步,等我做手势(语音播放中,语速1)
+t+ 2.1s ▶ 语音:「单击可跳过旁白。」
+t+ 4.2s ♪ 向导音:turn(轮到你)
+t+ 4.2s 【状态】引导第 2/8 步 引导第 2/8 步,等我做手势(BGM=bgm/drone,语速1)
#### 【玩家动作】随便滑了一步,有脚步声
-t+ 20.0s ♪ 音效 sfx/step
-t+ 20.0s ▶ 语音:「很好,你迈出了第一步。」
-t+ 22.1s ▶ 语音:「这个房间不大,四面都是墙。再滑两下,试试碰碰墙。」
-t+ 24.2s ♪ 向导音:turn(轮到你)
-t+ 24.2s 【状态】引导第 3/8 步 引导第 3/8 步,等我做手势(BGM=bgm/drone,语速1)
-t+ 24.2s ♪ 音效 sfx/wall
-t+ 24.2s ▶ 语音:「那边是墙,换个方向。」
-t+ 24.2s 〰 震动:error(做错了:两连短震)
+t+ 4.2s ♪ 音效 sfx/step
+t+ 4.2s ▶ 语音:「很好,你迈出了第一步。」
+t+ 6.4s ▶ 语音:「这个房间不大,四面都是墙。再滑两下,试试碰碰墙。」
+t+ 8.5s ♪ 向导音:turn(轮到你)
+t+ 8.5s 【状态】引导第 3/8 步 引导第 3/8 步,等我做手势(BGM=bgm/drone,语速1)
+t+ 8.5s ♪ 音效 sfx/wall
+t+ 8.5s ▶ 语音:「那边是墙,换个方向。」
+t+ 8.5s 〰 震动:error(做错了:两连短震)
#### 【玩家动作】又滑一步,又撞墙了——墙的方位听出来了
-t+ 26.4s ♪ 音效 sfx/wall
-t+ 26.4s ▶ 语音:「那边是墙,换个方向。」
-t+ 26.4s 〰 震动:error(做错了:两连短震)
-t+ 28.5s ▶ 语音:「跟着我指的路走。向左滑。」
-t+ 30.6s ♪ 向导音:turn(轮到你)
-t+ 30.6s 【状态】引导第 4/8 步 引导第 4/8 步,等我做手势(BGM=bgm/drone,语速1)
+t+ 10.6s ♪ 音效 sfx/wall
+t+ 10.6s ▶ 语音:「那边是墙,换个方向。」
+t+ 10.6s 〰 震动:error(做错了:两连短震)
+t+ 12.7s ▶ 语音:「跟着我指的路走。向左滑。」
+t+ 14.8s ♪ 向导音:turn(轮到你)
+t+ 14.8s 【状态】引导第 4/8 步 引导第 4/8 步,等我做手势(BGM=bgm/drone,语速1)
#### 【玩家动作】这回往左,走通了一步
-t+ 30.6s ♪ 音效 sfx/step
-t+ 30.6s ▶ 语音:「对。再向下滑。」
-t+ 32.7s ♪ 向导音:turn(轮到你)
-t+ 32.7s 【状态】引导第 5/8 步 引导第 5/8 步,等我做手势(BGM=bgm/drone,语速1)
+t+ 14.8s ♪ 音效 sfx/step
+t+ 14.8s ▶ 语音:「对。再向下滑。」
+t+ 17.0s ♪ 向导音:turn(轮到你)
+t+ 17.0s 【状态】引导第 5/8 步 引导第 5/8 步,等我做手势(BGM=bgm/drone,语速1)
#### 【玩家动作】往下滑,进了储物间
-t+ 32.7s ♪ 音效 sfx/step
-t+ 32.7s ♪ 音效 sfx/amb_storage
-t+ 32.7s ▶ 语音:「听到水声了吗?单击一下,仔细检查这个房间。」
-t+ 34.8s ♪ 向导音:turn(轮到你)
-t+ 34.8s 【状态】引导第 6/8 步 引导第 6/8 步,等我做手势(BGM=bgm/drone,语速1)
+t+ 17.0s ♪ 音效 sfx/step
+t+ 17.0s ♪ 音效 sfx/amb_storage
+t+ 17.0s ▶ 语音:「听到水声了吗?单击一下,仔细检查这个房间。」
+t+ 19.1s ♪ 向导音:turn(轮到你)
+t+ 19.1s 【状态】引导第 6/8 步 引导第 6/8 步,等我做手势(BGM=bgm/drone,语速1)
#### 【玩家动作】单击摸一遍房间,摸到钥匙了
-t+ 34.8s ♪ 音效 sfx/pickup
-t+ 34.8s ▶ 语音:「你摸到了一把钥匙!」
-t+ 34.8s 〰 震动:pickup(获得)
-t+ 37.0s ▶ 语音:「钥匙能开锁。双击,是把物品用出去的用法。现在,双击试试。」
-t+ 39.1s ♪ 向导音:turn(轮到你)
-t+ 39.1s 【状态】引导第 7/8 步 引导第 7/8 步,等我做手势(BGM=bgm/drone,语速1)
+t+ 19.1s ♪ 音效 sfx/pickup
+t+ 19.1s ▶ 语音:「你摸到了一把钥匙!」
+t+ 19.1s 〰 震动:pickup(获得)
+t+ 21.2s ▶ 语音:「钥匙能开锁。双击,是把物品用出去的用法。现在,双击试试。」
+t+ 23.3s ♪ 向导音:turn(轮到你)
+t+ 23.3s 【状态】引导第 7/8 步 引导第 7/8 步,等我做手势(BGM=bgm/drone,语速1)
#### 【玩家动作】双击看了看背包
-t+ 39.1s ▶ 语音:「你身上带着一把钥匙。」
-t+ 41.2s ▶ 语音:「对,就是这样。接下来,靠你自己了。」
-t+ 43.3s ▶ 语音:「找到能用这把钥匙打开的东西。需要帮助时,在原地双击。」
-t+ 45.4s ♪ 向导音:turn(轮到你)
-t+ 45.4s ♪ 音效 sfx/amb_storage
-t+ 45.4s 【状态】引导完毕,正式开始。我在储物间 探索中,我在 (0,2)。四向滑挪步,单击摸一遍房间,双击用物品(BGM=bgm/drone,语速1)
-t+ 45.4s ……… 静默 3s(辨了辨方向) ………
-t+ 45.4s ♪ 音效 sfx/step
-t+ 45.4s ♪ 音效 sfx/amb_hum
-t+ 50.0s ♪ 音效 sfx/step
-t+ 50.0s ♪ 音效 sfx/amb_power
-t+ 50.0s ▶ 语音:「这个房间的墙上,有一只电箱。」
-t+ 52.1s ♪ 音效 sfx/wall
-t+ 52.1s ▶ 语音:「那边是墙,换个方向。」
-t+ 52.1s 〰 震动:error(做错了:两连短震)
-t+ 54.2s ▶ 语音:「手指贴着屏幕,向上推一下。」
+t+ 23.3s ▶ 语音:「你身上带着一把钥匙。」
+t+ 25.4s ▶ 语音:「对,就是这样。接下来,靠你自己了。」
+t+ 27.6s ▶ 语音:「找到能用这把钥匙打开的东西。需要帮助时,在原地双击。」
+t+ 29.7s ♪ 向导音:turn(轮到你)
+t+ 29.7s ♪ 音效 sfx/amb_storage
+t+ 29.7s 【状态】引导完毕,正式开始。我在储物间 探索中,我在 (0,2)。四向滑挪步,单击摸一遍房间,双击用物品(BGM=bgm/drone,语速1)
+t+ 29.7s ……… 静默 3s(辨了辨方向) ………
+t+ 29.7s ♪ 音效 sfx/step
+t+ 29.7s ♪ 音效 sfx/amb_hum
+t+ 35.0s ♪ 音效 sfx/step
+t+ 35.0s ♪ 音效 sfx/amb_power
+t+ 35.0s ▶ 语音:「这个房间的墙上,有一只电箱。」
+t+ 37.1s ♪ 音效 sfx/wall
+t+ 37.1s ▶ 语音:「那边是墙,换个方向。」
+t+ 37.1s 〰 震动:error(做错了:两连短震)
+t+ 39.2s ▶ 语音:「手指贴着屏幕,向上推一下。」
#### 【玩家动作】北边是墙,撞了一下——「那边是墙」后面还跟了句方向(向上推的是北墙)
-t+ 54.2s ♪ 音效 sfx/wall
-t+ 54.2s ▶ 语音:「那边是墙,换个方向。」
-t+ 54.2s 〰 震动:error(做错了:两连短震)
-t+ 55.0s ▶ 语音:「需要帮助吗?」
-t+ 55.0s 〰 震动:warning(警告三连震)
-t+ 57.1s ▶ 语音:「钥匙就在你身上。它能打开某一把锁。」
+t+ 39.2s ♪ 音效 sfx/wall
+t+ 39.2s ▶ 语音:「那边是墙,换个方向。」
+t+ 39.2s 〰 震动:error(做错了:两连短震)
+t+ 40.0s ▶ 语音:「需要帮助吗?」
+t+ 40.0s 〰 震动:warning(警告三连震)
+t+ 42.1s ▶ 语音:「钥匙就在你身上。它能打开某一把锁。」
#### 【玩家动作】又撞了一下——听到游戏主动来问我了
-t+ 65.0s ♪ 音效 sfx/step
-t+ 65.0s ♪ 音效 sfx/amb_wind
+t+ 50.0s ♪ 音效 sfx/step
+t+ 50.0s ♪ 音效 sfx/amb_wind
#### 【玩家动作】往东走,风声换了个方向
-t+ 70.0s ♪ 音效 sfx/step
-t+ 70.0s ♪ 音效 sfx/amb_hum
-t+ 75.0s ♪ 音效 sfx/step
-t+ 75.0s ♪ 音效 sfx/amb_cabinet
-t+ 75.0s ▶ 语音:「这个房间里,立着一个铁柜。」
+t+ 55.0s ♪ 音效 sfx/step
+t+ 55.0s ♪ 音效 sfx/amb_hum
+t+ 60.0s ♪ 音效 sfx/step
+t+ 60.0s ♪ 音效 sfx/amb_cabinet
+t+ 60.0s ▶ 语音:「这个房间里,立着一个铁柜。」
#### 【玩家动作】到了铁柜房,柜子锁着
-t+ 77.1s ♪ 音效 sfx/unlock
-t+ 77.1s ♪ 音效 sfx/door_creak
-t+ 77.1s ▶ 语音:「钥匙插进锁孔,缓缓转动。咔哒一声,柜门开了。柜子深处,躺着一枚保险丝。保险丝到手了。」
-t+ 77.1s 〰 震动:success(成功长震)
-t+ 85.0s 【状态】柜子开了,拿到保险丝——解到第二间,收工 探索中,我在 (2,1)。四向滑挪步,单击摸一遍房间,双击用物品(BGM=bgm/drone,语速1)
+t+ 62.1s ♪ 音效 sfx/unlock
+t+ 62.1s ♪ 音效 sfx/door_creak
+t+ 62.1s ▶ 语音:「钥匙插进锁孔,缓缓转动。咔哒一声,柜门开了。柜子深处,躺着一枚保险丝。保险丝到手了。」
+t+ 62.1s 〰 震动:success(成功长震)
+t+ 64.2s ▶ 向导语音:「保险丝到手。接下来,去找电箱。」
+t+ 66.4s 【状态】柜子开了,听到「保险丝到手。接下来,去找电箱」——目标又有了 探索中,我在 (2,1)。四向滑挪步,单击摸一遍房间,双击用物品(BGM=bgm/drone,语速1)
+t+ 66.4s ♪ 音效 sfx/step
+t+ 66.4s ♪ 音效 sfx/amb_drip
+
+#### 【玩家动作】照新目标往西摸
+
+t+ 70.0s ♪ 音效 sfx/step
+t+ 70.0s ♪ 音效 sfx/amb_hum
+
+#### 【玩家动作】再走一步,西边隐隐有电流声——电箱在那边
+
+t+ 75.0s 【状态】解到第二间、照下一目标句又摸了两步,收工 探索中,我在 (0,1)。四向滑挪步,单击摸一遍房间,双击用物品(BGM=bgm/drone,语速1)
diff --git a/research/04-playtests/transcripts/rhythm.md b/research/04-playtests/transcripts/rhythm.md
index 14fcd399..b646ff66 100644
--- a/research/04-playtests/transcripts/rhythm.md
+++ b/research/04-playtests/transcripts/rhythm.md
@@ -5,173 +5,168 @@
> 非最优操作:包含犹豫、误操作与乱试。语音时长按语速估算(±20%),仅供节奏参考。
t+ 0.0s (玩家点开游戏,轻触屏幕开始)
t+ 0.0s ▶ 语音:「欢迎来到节拍行者。跟着音乐,我奏一句,你跟一句。」
-t+ 8.0s ▶ 语音:「听,底鼓。在下一小节的同一个位置,单击。」
-t+ 18.0s 【状态】教学开始了,先听领奏 教学:听领奏,下一小节照样打(tap)(语音播放中,语速1)
-t+ 18.0s 【状态】教学第 1/3 句 教学:听领奏,下一小节照样打(tap)(语音播放中,语速1)
-t+ 19.3s 〰 震动:beat(节拍点)
-t+ 23.0s ▶ 语音:「再听一遍,跟着来。」
-t+ 23.0s 〰 震动:error(做错了:两连短震)
-t+ 25.1s ▶ 语音:「再听一遍,跟着来。」
-t+ 27.2s ▶ 向导语音:「慢了半拍。跟着节拍走。」
-t+ 30.0s 〰 震动:beat(节拍点)
-t+ 33.6s ▶ 语音:「没关系,我们先走下一句。」
-t+ 33.6s 〰 震动:error(做错了:两连短震)
-t+ 35.8s ▶ 语音:「这次是左和右。跟着打,左滑,右滑。」
-t+ 35.8s 【状态】教学第 2/3 句 教学:听领奏,下一小节照样打(tap)(语音播放中,语速1)
-t+ 38.0s 〰 震动:beat(节拍点)
-t+ 39.3s 〰 震动:beat(节拍点)
-t+ 43.0s ▶ 语音:「再听一遍,跟着来。」
-t+ 43.0s 〰 震动:error(做错了:两连短震)
-t+ 45.1s ▶ 语音:「再听一遍,跟着来。」
-t+ 47.2s ▶ 向导语音:「慢了半拍。跟着节拍走。」
-t+ 48.7s 〰 震动:beat(节拍点)
-t+ 50.0s 〰 震动:beat(节拍点)
-t+ 53.6s ▶ 语音:「没关系,我们先走下一句。」
-t+ 53.6s 〰 震动:error(做错了:两连短震)
-t+ 55.8s ▶ 语音:「最后一句,三个音,中间是双击。」
-t+ 55.8s 【状态】教学第 3/3 句 教学:听领奏,下一小节照样打(left→right)(语音播放中,语速1)
-t+ 55.8s ♪ 音效 sfx/inst_hat_l
-t+ 55.8s ♪ 音效 sfx/inst_hat_r
-t+ 59.3s 〰 震动:beat(节拍点)
-t+ 60.0s 〰 震动:beat(节拍点)
-t+ 60.7s 〰 震动:beat(节拍点)
-t+ 64.3s ▶ 语音:「再听一遍,跟着来。」
-t+ 64.3s 〰 震动:error(做错了:两连短震)
-t+ 66.4s ▶ 语音:「再听一遍,跟着来。」
-t+ 68.6s ▶ 向导语音:「慢了半拍。跟着节拍走。」
-t+ 70.0s 〰 震动:beat(节拍点)
-t+ 70.7s 〰 震动:beat(节拍点)
-t+ 71.3s 〰 震动:beat(节拍点)
-t+ 75.0s ▶ 语音:「没关系,我们先走下一句。」
-t+ 75.0s 〰 震动:error(做错了:两连短震)
-t+ 77.1s ▶ 语音:「很好,演出开始。」
-t+ 79.2s ♪ 向导音:battle(战斗/对抗)
-t+ 79.2s 【状态】教学完毕,曲目一《启程》90 拍开始 演奏中(启程):还剩 31 个应答音。领奏停了、轮到空拍,就该我出手了(无 BGM,语速1)
-t+ 81.7s ♪ 向导音:menu(系统界面)
-t+ 81.7s ▶ 语音:「菜单。单击切换选项,双击确认。」
-t+ 81.7s 【状态】曲中暂停,进了菜单 暂停菜单:单击切选项,双击确认,上滑帮助,下滑恢复演奏(语音播放中,语速1)
-t+ 81.7s ▶ 语音:「回大厅。」
+t+ 2.1s ▶ 语音:「听,底鼓。在下一小节的同一个位置,单击。」
+t+ 4.2s 【状态】教学开始了,先听领奏 教学:听领奏,下一小节照样打(tap)(无 BGM,语速1)
+t+ 4.2s 【状态】教学第 1/3 句 教学:听领奏,下一小节照样打(tap)(无 BGM,语速1)
+t+ 6.0s 〰 震动:beat(节拍点)
+t+ 9.0s ♪ 音效 sfx/inst_kick
+t+ 9.6s ▶ 语音:「这次是左和右。跟着打,左滑,右滑。」
+t+ 11.8s 【状态】教学第 2/3 句 教学:听领奏,下一小节照样打(left→right)(无 BGM,语速1)
+t+ 14.0s 〰 震动:beat(节拍点)
+t+ 15.3s 〰 震动:beat(节拍点)
+t+ 19.0s ▶ 语音:「再听一遍,跟着来。」
+t+ 19.0s 〰 震动:error(做错了:两连短震)
+t+ 19.0s 【状态】第一遍没敢出手,先听它归因 教学:听领奏,下一小节照样打(left→right)(语音播放中,语速1)
+t+ 21.1s ▶ 语音:「再听一遍,跟着来。」
+t+ 23.2s ▶ 向导语音:「慢了半拍。跟着节拍走。」
+t+ 23.2s 【状态】又重新领奏了一遍,还是没敢出手 教学:听领奏,下一小节照样打(left→right)(语音播放中,语速1)
+t+ 24.7s 〰 震动:beat(节拍点)
+t+ 26.0s 〰 震动:beat(节拍点)
+t+ 29.6s ▶ 向导语音:「我放慢一些,跟着试试。」
+t+ 29.6s 〰 震动:error(做错了:两连短震)
+t+ 31.8s 【状态】听到「我放慢一些,跟着试试」——领奏降速 25% 重演,这回跟着慢拍打 教学:听领奏,下一小节照样打(left→right)(领奏已放慢 25%)(无 BGM,语速1)
+t+ 35.3s 〰 震动:beat(节拍点)
+t+ 37.1s 〰 震动:beat(节拍点)
+t+ 38.9s ♪ 音效 sfx/inst_hat_l
+t+ 40.6s ♪ 音效 sfx/inst_hat_r
+t+ 41.6s ▶ 语音:「最后一句,三个音,中间是双击。」
+t+ 43.8s 【状态】教学第 3/3 句 教学:听领奏,下一小节照样打(tap→doubletap→tap)(无 BGM,语速1)
+t+ 46.0s 〰 震动:beat(节拍点)
+t+ 46.7s 〰 震动:beat(节拍点)
+t+ 47.3s 〰 震动:beat(节拍点)
+t+ 49.0s ♪ 音效 sfx/inst_kick
+t+ 49.3s ♪ 音效 sfx/inst_snare
+t+ 50.3s ♪ 音效 sfx/inst_kick
+t+ 51.0s ▶ 语音:「很好,演出开始。」
+t+ 53.1s ♪ 向导音:battle(战斗/对抗)
+t+ 53.1s 【状态】教学完毕,曲目一《启程》90 拍开始。领奏响之前先听到「现在跟着我打」 演奏中(启程):还剩 31 个应答音。领奏停了、轮到空拍,就该我出手了(无 BGM,语速1)
+t+ 55.6s ♪ 向导音:menu(系统界面)
+t+ 55.6s ▶ 语音:「菜单。单击切换选项,双击确认。」
+t+ 55.6s 【状态】曲中暂停,进了菜单 暂停菜单:单击切选项,双击确认,上滑帮助,下滑恢复演奏(语音播放中,语速1)
+t+ 55.6s ▶ 语音:「回大厅。」
#### 【玩家动作】还是想打完这首,下滑回去
-t+ 87.1s ……… 静默 5s(还在数拍子,第一句没敢出手) ………
+t+ 61.0s ▶ 向导语音:「四拍之后,继续。」
+t+ 61.0s 【状态】听到「四拍之后,继续」,跟着四下底鼓数拍进来了 演奏中(启程):还剩 31 个应答音。领奏停了、轮到空拍,就该我出手了(语音播放中,语速1)
+t+ 61.0s ……… 静默 5s(还在数拍子,第一句没敢出手) ………
+t+ 63.2s 〰 震动:beat(节拍点)
+t+ 63.8s 〰 震动:beat(节拍点)
+t+ 64.5s 〰 震动:beat(节拍点)
+t+ 65.2s 〰 震动:beat(节拍点)
+t+ 67.0s ▶ 向导语音:「现在跟着我打。」
+t+ 67.0s ♪ 向导音:turn(轮到你)
+t+ 67.0s 〰 震动:beat(节拍点)
+t+ 68.3s 〰 震动:beat(节拍点)
+t+ 70.3s 〰 震动:error(做错了:两连短震)
+t+ 71.6s ▶ 向导语音:「慢了半拍,下一小节跟上我就行。」
+t+ 71.6s 〰 震动:error(做错了:两连短震)
+t+ 71.6s 【状态】第一句全漏了,听到「慢了半拍,下一小节跟上我就行」 演奏中(启程):还剩 29 个应答音。领奏停了、轮到空拍,就该我出手了(语音播放中,语速1)
+t+ 75.0s 〰 震动:beat(节拍点)
+t+ 76.3s 〰 震动:beat(节拍点)
+t+ 77.6s ♪ 音效 sfx/inst_hat_l
+t+ 77.6s ♪ 音效 sfx/inst_accent
+t+ 79.0s ♪ 音效 sfx/inst_hat_r
+t+ 79.0s ♪ 音效 sfx/inst_accent
+t+ 79.0s 〰 震动:自定义震型 [20,40,20]
+t+ 83.0s 〰 震动:beat(节拍点)
+t+ 83.7s 〰 震动:beat(节拍点)
+t+ 84.3s 〰 震动:beat(节拍点)
+t+ 86.0s ♪ 音效 sfx/inst_kick
+t+ 86.0s ♪ 音效 sfx/inst_accent
+t+ 86.3s ♪ 音效 sfx/inst_snare
+t+ 86.3s ♪ 音效 sfx/inst_accent
+t+ 87.3s ♪ 音效 sfx/inst_kick
+t+ 87.3s ♪ 音效 sfx/inst_accent
+t+ 87.3s 〰 震动:自定义震型 [20,40,20]
t+ 91.0s 〰 震动:beat(节拍点)
+t+ 91.7s 〰 震动:beat(节拍点)
t+ 92.3s 〰 震动:beat(节拍点)
-t+ 93.7s ▶ 向导语音:「现在跟着我打。」
-t+ 93.7s ♪ 向导音:turn(轮到你)
-t+ 94.3s 〰 震动:error(做错了:两连短震)
-t+ 95.6s ▶ 向导语音(对白在播,本句按 idle-only 跳过未播):「慢了半拍,下一小节跟上我就行。」
-t+ 95.6s 〰 震动:error(做错了:两连短震)
-t+ 95.6s 【状态】第一句全漏了,听到「慢了半拍,下一小节跟上我就行」 演奏中(启程):还剩 29 个应答音。领奏停了、轮到空拍,就该我出手了(语音播放中,语速1)
+t+ 93.6s ♪ 音效 sfx/inst_hat_l
+t+ 93.6s ♪ 音效 sfx/inst_accent
+t+ 94.3s ♪ 音效 sfx/inst_snare
+t+ 94.3s ♪ 音效 sfx/inst_accent
+t+ 95.0s ♪ 音效 sfx/inst_hat_r
+t+ 95.0s ♪ 音效 sfx/inst_accent
+t+ 95.0s 〰 震动:自定义震型 [20,40,20]
t+ 99.0s 〰 震动:beat(节拍点)
t+ 100.3s 〰 震动:beat(节拍点)
-t+ 101.6s ♪ 音效 sfx/inst_hat_l
-t+ 101.6s ♪ 音效 sfx/inst_accent
-t+ 103.0s ♪ 音效 sfx/inst_hat_r
+t+ 101.0s 〰 震动:beat(节拍点)
+t+ 102.0s ♪ 音效 sfx/inst_kick
+t+ 102.0s ♪ 音效 sfx/inst_accent
+t+ 103.0s ♪ 音效 sfx/inst_hat_l
t+ 103.0s ♪ 音效 sfx/inst_accent
-t+ 103.0s 〰 震动:自定义震型 [20,40,20]
-t+ 107.0s 〰 震动:beat(节拍点)
-t+ 107.7s 〰 震动:beat(节拍点)
-t+ 108.3s 〰 震动:beat(节拍点)
-t+ 110.0s ♪ 音效 sfx/inst_kick
-t+ 110.0s ♪ 音效 sfx/inst_accent
-t+ 110.3s ♪ 音效 sfx/inst_snare
-t+ 110.3s ♪ 音效 sfx/inst_accent
-t+ 111.3s ♪ 音效 sfx/inst_kick
-t+ 111.3s ♪ 音效 sfx/inst_accent
-t+ 111.3s 〰 震动:自定义震型 [20,40,20]
+t+ 103.6s ♪ 音效 sfx/inst_snare
+t+ 103.6s ♪ 音效 sfx/inst_accent
+t+ 103.6s 〰 震动:自定义震型 [20,40,20]
+t+ 104.4s ▶ 语音:「过半了,保持。」
+t+ 104.3s 〰 震动:beat(节拍点)
+t+ 105.7s 〰 震动:beat(节拍点)
+t+ 106.3s 〰 震动:beat(节拍点)
+t+ 107.0s ♪ 音效 sfx/inst_hat_r
+t+ 107.0s ♪ 音效 sfx/inst_accent
+t+ 108.6s ♪ 音效 sfx/inst_kick
+t+ 108.6s ♪ 音效 sfx/inst_accent
+t+ 109.0s ♪ 音效 sfx/inst_snare
+t+ 109.0s ♪ 音效 sfx/inst_accent
+t+ 109.0s 〰 震动:自定义震型 [20,40,20]
+t+ 109.7s 〰 震动:beat(节拍点)
+t+ 111.0s 〰 震动:beat(节拍点)
+t+ 111.7s 〰 震动:beat(节拍点)
+t+ 112.3s ♪ 音效 sfx/inst_tom_hi
+t+ 112.3s ♪ 音效 sfx/inst_accent
+t+ 113.6s ♪ 音效 sfx/inst_tom_lo
+t+ 113.6s ♪ 音效 sfx/inst_accent
+t+ 113.6s 〰 震动:success(成功长震)
+t+ 114.3s ♪ 音效 sfx/inst_snare
+t+ 114.3s ♪ 音效 sfx/inst_accent
+t+ 114.3s 〰 震动:自定义震型 [20,40,20]
t+ 115.0s 〰 震动:beat(节拍点)
t+ 115.7s 〰 震动:beat(节拍点)
t+ 116.3s 〰 震动:beat(节拍点)
-t+ 117.6s ♪ 音效 sfx/inst_hat_l
-t+ 117.6s ♪ 音效 sfx/inst_accent
-t+ 118.3s ♪ 音效 sfx/inst_snare
+t+ 117.0s 〰 震动:beat(节拍点)
+t+ 118.0s ♪ 音效 sfx/inst_kick
+t+ 118.0s ♪ 音效 sfx/inst_accent
+t+ 118.3s ♪ 音效 sfx/inst_tom_hi
t+ 118.3s ♪ 音效 sfx/inst_accent
t+ 119.0s ♪ 音效 sfx/inst_hat_r
t+ 119.0s ♪ 音效 sfx/inst_accent
-t+ 119.0s 〰 震动:自定义震型 [20,40,20]
-t+ 123.0s 〰 震动:beat(节拍点)
-t+ 124.3s 〰 震动:beat(节拍点)
-t+ 125.0s 〰 震动:beat(节拍点)
-t+ 126.0s ♪ 音效 sfx/inst_kick
-t+ 126.0s ♪ 音效 sfx/inst_accent
-t+ 127.0s ♪ 音效 sfx/inst_hat_l
-t+ 127.0s ♪ 音效 sfx/inst_accent
-t+ 127.6s ♪ 音效 sfx/inst_snare
-t+ 127.6s ♪ 音效 sfx/inst_accent
-t+ 127.6s 〰 震动:自定义震型 [20,40,20]
-t+ 128.4s ▶ 语音:「过半了,保持。」
-t+ 128.3s 〰 震动:beat(节拍点)
-t+ 129.7s 〰 震动:beat(节拍点)
-t+ 130.3s 〰 震动:beat(节拍点)
-t+ 131.0s ♪ 音效 sfx/inst_hat_r
-t+ 131.0s ♪ 音效 sfx/inst_accent
-t+ 132.6s ♪ 音效 sfx/inst_kick
-t+ 132.6s ♪ 音效 sfx/inst_accent
-t+ 133.0s ♪ 音效 sfx/inst_snare
-t+ 133.0s ♪ 音效 sfx/inst_accent
-t+ 133.0s 〰 震动:自定义震型 [20,40,20]
-t+ 133.7s 〰 震动:beat(节拍点)
-t+ 135.0s 〰 震动:beat(节拍点)
-t+ 135.7s 〰 震动:beat(节拍点)
-t+ 136.3s ♪ 音效 sfx/inst_tom_hi
-t+ 136.3s ♪ 音效 sfx/inst_accent
-t+ 137.6s ♪ 音效 sfx/inst_tom_lo
-t+ 137.6s ♪ 音效 sfx/inst_accent
-t+ 137.6s 〰 震动:success(成功长震)
-t+ 138.3s ♪ 音效 sfx/inst_snare
-t+ 138.3s ♪ 音效 sfx/inst_accent
-t+ 138.3s 〰 震动:自定义震型 [20,40,20]
-t+ 139.0s 〰 震动:beat(节拍点)
-t+ 139.7s 〰 震动:beat(节拍点)
-t+ 140.3s 〰 震动:beat(节拍点)
-t+ 141.0s 〰 震动:beat(节拍点)
-t+ 142.0s ♪ 音效 sfx/inst_kick
-t+ 142.0s ♪ 音效 sfx/inst_accent
-t+ 142.3s ♪ 音效 sfx/inst_tom_hi
-t+ 142.3s ♪ 音效 sfx/inst_accent
-t+ 143.0s ♪ 音效 sfx/inst_hat_r
-t+ 143.0s ♪ 音效 sfx/inst_accent
-t+ 143.6s ♪ 音效 sfx/inst_snare
-t+ 143.6s ♪ 音效 sfx/inst_accent
-t+ 143.6s 〰 震动:自定义震型 [20,40,20]
-t+ 144.3s 〰 震动:beat(节拍点)
-t+ 145.0s 〰 震动:beat(节拍点)
-t+ 145.7s 〰 震动:beat(节拍点)
-t+ 146.3s 〰 震动:beat(节拍点)
-t+ 147.0s ♪ 音效 sfx/inst_hat_l
-t+ 147.0s ♪ 音效 sfx/inst_accent
-t+ 147.6s ♪ 音效 sfx/inst_hat_r
-t+ 147.6s ♪ 音效 sfx/inst_accent
-t+ 148.6s ♪ 音效 sfx/inst_kick
-t+ 148.6s ♪ 音效 sfx/inst_accent
-t+ 149.0s ♪ 音效 sfx/inst_snare
-t+ 149.0s ♪ 音效 sfx/inst_accent
-t+ 149.0s 〰 震动:自定义震型 [20,40,20]
-t+ 149.7s 〰 震动:beat(节拍点)
-t+ 150.3s 〰 震动:beat(节拍点)
-t+ 151.0s 〰 震动:beat(节拍点)
-t+ 151.1s 〰 震动:beat(节拍点)
-t+ 151.1s 〰 震动:beat(节拍点)
-t+ 151.1s 〰 震动:beat(节拍点)
-t+ 151.1s 〰 震动:beat(节拍点)
-t+ 151.7s 〰 震动:beat(节拍点)
-t+ 152.6s ♪ 音效 sfx/inst_kick
-t+ 152.6s ♪ 音效 sfx/inst_accent
-t+ 153.0s ♪ 音效 sfx/inst_snare
-t+ 153.0s ♪ 音效 sfx/inst_accent
-t+ 154.0s ♪ 音效 sfx/inst_kick
-t+ 154.0s ♪ 音效 sfx/inst_accent
-t+ 154.3s ♪ 音效 sfx/inst_snare
-t+ 154.3s ♪ 音效 sfx/inst_accent
-t+ 154.3s 〰 震动:自定义震型 [20,40,20]
-t+ 155.4s ♪ 向导音:settle(结算)
-t+ 155.4s ▶ 语音:「A 级!准确率超过八成五,非常出色。」
-t+ 155.4s 〰 震动:success(成功长震)
-t+ 155.4s 〰 震动:success(成功长震)
-t+ 155.4s 〰 震动:自定义震型 [20,40,20]
-t+ 157.5s ▶ 语音:「新连击纪录!」
-t+ 159.6s ▶ 语音:「新曲目解锁,追风!」
-t+ 161.8s ▶ 语音:「单击再来一遍,右滑下一首,下滑回大厅。」
-t+ 163.9s ♫ BGM 切换 → bgm/menu(淡入 800ms)
-t+ 165.4s 【状态】曲子打完了,结算播报中 结算播报中:听完单击再来一遍,右滑下一首,下滑回大厅(BGM=bgm/menu,语速1)
+t+ 119.6s ♪ 音效 sfx/inst_snare
+t+ 119.6s ♪ 音效 sfx/inst_accent
+t+ 119.6s 〰 震动:自定义震型 [20,40,20]
+t+ 120.3s 〰 震动:beat(节拍点)
+t+ 121.0s 〰 震动:beat(节拍点)
+t+ 121.7s 〰 震动:beat(节拍点)
+t+ 122.3s 〰 震动:beat(节拍点)
+t+ 123.0s ♪ 音效 sfx/inst_hat_l
+t+ 123.0s ♪ 音效 sfx/inst_accent
+t+ 123.6s ♪ 音效 sfx/inst_hat_r
+t+ 123.6s ♪ 音效 sfx/inst_accent
+t+ 124.6s ♪ 音效 sfx/inst_kick
+t+ 124.6s ♪ 音效 sfx/inst_accent
+t+ 125.0s ♪ 音效 sfx/inst_snare
+t+ 125.0s ♪ 音效 sfx/inst_accent
+t+ 125.0s 〰 震动:自定义震型 [20,40,20]
+t+ 125.7s 〰 震动:beat(节拍点)
+t+ 126.3s 〰 震动:beat(节拍点)
+t+ 127.0s 〰 震动:beat(节拍点)
+t+ 127.7s 〰 震动:beat(节拍点)
+t+ 128.6s ♪ 音效 sfx/inst_kick
+t+ 128.6s ♪ 音效 sfx/inst_accent
+t+ 129.0s ♪ 音效 sfx/inst_snare
+t+ 129.0s ♪ 音效 sfx/inst_accent
+t+ 130.0s ♪ 音效 sfx/inst_kick
+t+ 130.0s ♪ 音效 sfx/inst_accent
+t+ 130.3s ♪ 音效 sfx/inst_snare
+t+ 130.3s ♪ 音效 sfx/inst_accent
+t+ 130.3s 〰 震动:自定义震型 [20,40,20]
+t+ 131.4s ♪ 向导音:settle(结算)
+t+ 131.4s ▶ 语音:「A 级!准确率超过八成五,非常出色。」
+t+ 131.4s 〰 震动:success(成功长震)
+t+ 131.4s 〰 震动:success(成功长震)
+t+ 131.4s 〰 震动:自定义震型 [20,40,20]
+t+ 133.5s ▶ 语音:「新连击纪录!」
+t+ 135.6s ▶ 语音:「新曲目解锁,追风!」
+t+ 137.8s ▶ 语音:「单击再来一遍,右滑下一首,下滑回大厅。」
+t+ 139.9s ♫ BGM 切换 → bgm/menu(淡入 800ms)
+t+ 141.4s 【状态】曲子打完了,结算播报中 结算播报中:听完单击再来一遍,右滑下一首,下滑回大厅(BGM=bgm/menu,语速1)
diff --git a/research/04-playtests/transcripts/simon.md b/research/04-playtests/transcripts/simon.md
index f899069e..3c0ecfca 100644
--- a/research/04-playtests/transcripts/simon.md
+++ b/research/04-playtests/transcripts/simon.md
@@ -49,75 +49,75 @@ t+ 47.7s 【状态】教学第 6/6 个音色 教学:该做「双击」了(
t+ 47.7s ♪ 音效 sfx/tone_doubletap
t+ 47.7s ▶ 语音:「对了。」
t+ 49.8s ▶ 语音:「六种声音都记住了。后面的序列,会越来越长。」
-t+ 51.9s ▶ 语音:「答错可以消耗机会重听。双击,可以随时重听。」
-t+ 54.0s ▶ 向导语音:「记不住就双击重新听,免费机会有两次,用完要扣一次机会。」
+t+ 51.9s ▶ 语音:「答错可以消耗机会重听。向上滑,可以随时重听。」
+t+ 54.0s ▶ 向导语音:「记不住就向上滑,重新听一遍。免费机会有两次,用完要扣一次机会。」
t+ 56.2s ▶ 语音:「第一轮,听好了。」
-t+ 58.3s ♪ 音效 sfx/tone_doubletap
+t+ 58.3s ♪ 音效 sfx/tone_tap
t+ 58.3s 〰 震动:beat(节拍点)
-t+ 58.3s 【状态】教学讲完了,机会经济也交代清楚了:免费重听两次,用完要扣机会 第 1 轮序列演奏中(2 个音),记住顺序,先别动手(无 BGM,语速1)
-t+ 59.0s ♪ 音效 sfx/tone_up
+t+ 58.3s 【状态】教学讲完了:免费重听两次、用完扣机会,想重听就向上滑 第 1 轮序列演奏中(2 个音),记住顺序,先别动手(无 BGM,语速1)
+t+ 59.0s ♪ 音效 sfx/tone_doubletap
t+ 59.0s 〰 震动:beat(节拍点)
t+ 60.1s ♪ 向导音:turn(轮到你)
t+ 60.1s ▶ 语音:「轮到你了。」
t+ 60.1s 〰 震动:confirm(轻点确认)
-t+ 62.2s 【状态】轮到我复现了 第 1 轮轮到你了:已对上 0/2,照原顺序做手势(无 BGM,语速1)
-t+ 62.2s ♪ 音效 sfx/tone_doubletap
-t+ 62.2s 【状态】轮到我复现了 第 1 轮轮到你了:已对上 1/2,照原顺序做手势(无 BGM,语速1)
-t+ 62.2s ♪ 音效 sfx/tone_up
-t+ 62.2s 〰 震动:success(成功长震)
-t+ 62.5s ▶ 语音:「第二轮,听好了。」
-t+ 64.6s ♪ 音效 sfx/tone_doubletap
-t+ 64.6s 〰 震动:beat(节拍点)
-t+ 65.3s ♪ 音效 sfx/tone_up
-t+ 65.3s 〰 震动:beat(节拍点)
-t+ 66.0s ♪ 音效 sfx/tone_doubletap
-t+ 66.0s 〰 震动:beat(节拍点)
-t+ 67.0s ♪ 向导音:turn(轮到你)
-t+ 67.0s 〰 震动:confirm(轻点确认)
-t+ 67.0s 【状态】轮到我复现了 第 2 轮轮到你了:已对上 0/3,照原顺序做手势(无 BGM,语速1)
-t+ 67.0s ♪ 音效 sfx/tone_doubletap
-t+ 67.0s 【状态】序列有点长,先僵一会儿 第 2 轮轮到你了:已对上 1/3,照原顺序做手势(无 BGM,语速1)
-t+ 67.0s ……… 静默 10s(想不起来序列了) ………
-t+ 72.2s 【状态】听到提示:需要的话,双击可以重新听一遍序列 第 2 轮轮到你了:已对上 1/3,照原顺序做手势(无 BGM,语速1)
+t+ 62.2s 【状态】第 1 轮有点懵,先僵一会儿 第 1 轮轮到你了:已对上 0/2,照原顺序做手势(双击就是双击那个音,要重听就向上滑)(无 BGM,语速1)
+t+ 62.2s ……… 静默 10s(想不起来序列了) ………
+t+ 72.2s ♪ 向导音:nudge(看门狗轻提醒)
+t+ 72.2s ▶ 向导语音:「需要的话,向上滑可以重新听一遍序列。」
+t+ 72.2s 【状态】听到提示:需要的话,向上滑可以重新听一遍序列 第 1 轮轮到你了:已对上 0/2,照原顺序做手势(双击就是双击那个音,要重听就向上滑)(语音播放中,语速1)
-#### 【玩家动作】照提示双击,用掉一次免费重听
+#### 【玩家动作】照提示向上滑,用掉一次免费重听
t+ 72.2s ▶ 语音:「再听一遍。」
t+ 72.2s 〰 震动:pickup(获得)
t+ 74.3s ▶ 语音:「重听机会用完了,小心。」
-t+ 76.4s ♪ 音效 sfx/tone_doubletap
+t+ 76.4s ♪ 音效 sfx/tone_tap
t+ 76.4s 〰 震动:beat(节拍点)
-t+ 77.1s ♪ 音效 sfx/tone_up
-t+ 77.8s ♪ 音效 sfx/tone_doubletap
+t+ 77.1s ♪ 音效 sfx/tone_doubletap
t+ 77.1s 〰 震动:beat(节拍点)
-t+ 77.8s 〰 震动:beat(节拍点)
-t+ 78.9s ♪ 向导音:turn(轮到你)
-t+ 78.9s 〰 震动:confirm(轻点确认)
-t+ 78.9s 【状态】轮到我复现了 第 2 轮轮到你了:已对上 0/3,照原顺序做手势(无 BGM,语速1)
-t+ 78.9s ♪ 音效 sfx/tone_doubletap
-t+ 78.9s 【状态】轮到我复现了 第 2 轮轮到你了:已对上 1/3,照原顺序做手势(无 BGM,语速1)
-t+ 78.9s ♪ 音效 sfx/tone_up
-t+ 78.9s 【状态】轮到我复现了 第 2 轮轮到你了:已对上 2/3,照原顺序做手势(无 BGM,语速1)
-t+ 78.9s ♪ 音效 sfx/tone_doubletap
-t+ 78.9s 〰 震动:success(成功长震)
-t+ 79.2s ▶ 语音:「第三轮,听好了。」
-t+ 81.3s ♪ 音效 sfx/tone_doubletap
-t+ 81.3s 〰 震动:beat(节拍点)
-t+ 81.9s ♪ 音效 sfx/tone_up
-t+ 81.9s 〰 震动:beat(节拍点)
-t+ 82.6s ♪ 音效 sfx/tone_doubletap
-t+ 82.6s 〰 震动:beat(节拍点)
-t+ 83.2s ♪ 音效 sfx/tone_up
-t+ 83.2s 〰 震动:beat(节拍点)
-t+ 84.3s ♪ 向导音:turn(轮到你)
-t+ 84.3s 〰 震动:confirm(轻点确认)
-t+ 84.3s 【状态】轮到我复现了 第 3 轮轮到你了:已对上 0/4,照原顺序做手势(无 BGM,语速1)
-t+ 84.3s ♪ 音效 sfx/tone_doubletap
-t+ 84.3s 【状态】轮到我复现了 第 3 轮轮到你了:已对上 1/4,照原顺序做手势(无 BGM,语速1)
-t+ 84.3s ♪ 音效 sfx/tone_up
-t+ 84.3s 【状态】轮到我复现了 第 3 轮轮到你了:已对上 2/4,照原顺序做手势(无 BGM,语速1)
-t+ 84.3s ♪ 音效 sfx/tone_doubletap
-t+ 84.3s 【状态】最后一轮最后一个音,打完这轮就收 第 3 轮轮到你了:已对上 3/4,照原顺序做手势(无 BGM,语速1)
-t+ 84.3s ♪ 音效 sfx/tone_up
-t+ 84.3s 〰 震动:success(成功长震)
-t+ 84.3s 【状态】收工:完整打完 3 轮,在轮与轮的边界停手(免费重听剩 0 次) 刚答完一轮,播报中(无 BGM,语速1)
+t+ 78.2s ♪ 向导音:turn(轮到你)
+t+ 78.2s ▶ 语音:「轮到你了。」
+t+ 78.2s 〰 震动:confirm(轻点确认)
+t+ 80.4s 【状态】轮到我复现了 第 1 轮轮到你了:已对上 0/2,照原顺序做手势(双击就是双击那个音,要重听就向上滑)(无 BGM,语速1)
+t+ 80.4s ♪ 音效 sfx/tone_tap
+t+ 80.4s 【状态】轮到我复现了 第 1 轮轮到你了:已对上 1/2,照原顺序做手势(双击就是双击那个音,要重听就向上滑)(无 BGM,语速1)
+t+ 80.4s ♪ 音效 sfx/tone_doubletap
+t+ 80.4s ▶ 向导语音:「漂亮,过了。」
+t+ 80.4s 〰 震动:success(成功长震)
+t+ 82.8s ▶ 语音:「第二轮,听好了。」
+t+ 84.9s ♪ 音效 sfx/tone_tap
+t+ 84.9s 〰 震动:beat(节拍点)
+t+ 85.6s ♪ 音效 sfx/tone_doubletap
+t+ 85.6s 〰 震动:beat(节拍点)
+t+ 86.2s ♪ 音效 sfx/tone_up
+t+ 86.2s 〰 震动:beat(节拍点)
+t+ 87.3s ♪ 向导音:turn(轮到你)
+t+ 87.3s 〰 震动:confirm(轻点确认)
+t+ 87.3s 【状态】这个是上行音——上滑作答(期望恰为 up 时上滑=作答) 第 2 轮轮到你了:已对上 0/3,照原顺序做手势(双击就是双击那个音,要重听就向上滑)(无 BGM,语速1)
+t+ 87.3s ♪ 音效 sfx/tone_up
+t+ 87.3s 【状态】轮到我复现了 第 2 轮轮到你了:已对上 1/3,照原顺序做手势(双击就是双击那个音,要重听就向上滑)(无 BGM,语速1)
+t+ 87.3s ♪ 音效 sfx/tone_doubletap
+t+ 87.3s 【状态】轮到我复现了 第 2 轮轮到你了:已对上 2/3,照原顺序做手势(双击就是双击那个音,要重听就向上滑)(无 BGM,语速1)
+t+ 87.3s ♪ 音效 sfx/tone_up
+t+ 87.3s 〰 震动:success(成功长震)
+t+ 87.6s ▶ 语音:「第三轮,听好了。」
+t+ 89.7s ♪ 音效 sfx/tone_up
+t+ 89.7s 〰 震动:beat(节拍点)
+t+ 90.4s ♪ 音效 sfx/tone_doubletap
+t+ 90.4s 〰 震动:beat(节拍点)
+t+ 91.0s ♪ 音效 sfx/tone_up
+t+ 91.7s ♪ 音效 sfx/tone_right
+t+ 91.0s 〰 震动:beat(节拍点)
+t+ 91.7s 〰 震动:beat(节拍点)
+t+ 92.7s ♪ 向导音:turn(轮到你)
+t+ 92.7s 〰 震动:confirm(轻点确认)
+t+ 92.7s 【状态】轮到我复现了 第 3 轮轮到你了:已对上 0/4,照原顺序做手势(双击就是双击那个音,要重听就向上滑)(无 BGM,语速1)
+t+ 92.7s ♪ 音效 sfx/tone_up
+t+ 92.7s 【状态】轮到我复现了 第 3 轮轮到你了:已对上 1/4,照原顺序做手势(双击就是双击那个音,要重听就向上滑)(无 BGM,语速1)
+t+ 92.7s ♪ 音效 sfx/tone_doubletap
+t+ 92.7s 【状态】轮到我复现了 第 3 轮轮到你了:已对上 2/4,照原顺序做手势(双击就是双击那个音,要重听就向上滑)(无 BGM,语速1)
+t+ 92.7s ♪ 音效 sfx/tone_up
+t+ 92.7s 【状态】这个是双击音——双击作答(round3:input 双击永远=作答) 第 3 轮轮到你了:已对上 3/4,照原顺序做手势(双击就是双击那个音,要重听就向上滑)(无 BGM,语速1)
+t+ 92.7s ♪ 音效 sfx/tone_doubletap
+t+ 92.7s 〰 震动:success(成功长震)
+t+ 92.7s 【状态】收工:完整打完 3 轮,在轮与轮的边界停手(免费重听剩 0 次) 刚答完一轮,播报中(无 BGM,语速1)
diff --git a/research/04-playtests/transcripts/space.md b/research/04-playtests/transcripts/space.md
index 01e4976e..0e400397 100644
--- a/research/04-playtests/transcripts/space.md
+++ b/research/04-playtests/transcripts/space.md
@@ -48,31 +48,47 @@ t+ 25.7s 【状态】演练做完了,要出发了 演练旁白在播,先
t+ 27.8s ♫ BGM 切换 → bgm/engine
t+ 27.8s ♪ 向导音:battle(战斗/对抗)
t+ 27.8s 【状态】出发。引擎声起来了,保护期里先练手 对局中:引擎声平稳,等下一颗(保护期)(BGM=bgm/engine,语速1)
-t+ 29.3s ♪ 音效 sfx/whoosh_left
+t+ 29.3s ♪ 音效 sfx/whoosh_up
t+ 32.3s ♪ 音效 sfx/alarm
-t+ 32.3s 〰 震动:danger(危险逼近)
t+ 32.8s ♪ 音效 sfx/alarm
+t+ 32.8s ▶ 语音:「上!」
+t+ 32.3s 〰 震动:danger(危险逼近)
t+ 32.8s 〰 震动:danger(危险逼近)
+
+#### 【玩家动作】听到第二段警报和方向呼喊,同向滑开
+
t+ 33.3s ♪ 音效 sfx/dodge
-t+ 33.3s ♪ 音效 sfx/whoosh_up
+t+ 33.3s ♪ 音效 sfx/whoosh_down
t+ 36.3s ♪ 音效 sfx/alarm
-t+ 36.3s 〰 震动:danger(危险逼近)
t+ 36.8s ♪ 音效 sfx/alarm
+t+ 36.8s ▶ 语音:「下!」
+t+ 36.3s 〰 震动:danger(危险逼近)
t+ 36.8s 〰 震动:danger(危险逼近)
+
+#### 【玩家动作】听到第二段警报和方向呼喊,同向滑开
+
t+ 37.3s ♪ 音效 sfx/dodge
-t+ 37.3s ♪ 音效 sfx/whoosh_right
+t+ 37.3s ♪ 音效 sfx/whoosh_left
t+ 40.3s ♪ 音效 sfx/alarm
-t+ 40.3s 〰 震动:danger(危险逼近)
t+ 40.8s ♪ 音效 sfx/alarm
+t+ 40.8s ▶ 语音:「左!」
+t+ 40.3s 〰 震动:danger(危险逼近)
t+ 40.8s 〰 震动:danger(危险逼近)
+
+#### 【玩家动作】听到第二段警报和方向呼喊,同向滑开
+
t+ 41.3s ♪ 音效 sfx/dodge
-t+ 41.3s ♪ 音效 sfx/whoosh_down
+t+ 41.3s ♪ 音效 sfx/whoosh_right
t+ 44.3s ♪ 音效 sfx/alarm
-t+ 44.3s 〰 震动:danger(危险逼近)
t+ 44.8s ♪ 音效 sfx/alarm
+t+ 44.8s ▶ 语音:「右!」
+t+ 44.3s 〰 震动:danger(危险逼近)
t+ 44.8s 〰 震动:danger(危险逼近)
+
+#### 【玩家动作】听到第二段警报和方向呼喊,同向滑开
+
t+ 45.3s ♪ 音效 sfx/dodge
-t+ 45.3s ♪ 音效 sfx/whoosh_up
+t+ 45.3s ♪ 音效 sfx/whoosh_left
t+ 47.8s ▶ 语音:「试试单击,引擎会短促加速,直接冲过空隙。」
t+ 47.8s 【状态】游戏停下来教新功能 暂停了刷怪教新功能:单击试试加速(语音播放中,语速1)
@@ -80,37 +96,57 @@ t+ 47.8s 【状态】游戏停下来教新功能 暂停了刷怪教新功能
t+ 49.9s ♪ 音效 sfx/boost
t+ 49.9s ▶ 语音:「感觉到了吗?加速的时候,陨石撞不上你。」
-t+ 52.4s ♪ 音效 sfx/whoosh_left
+t+ 52.4s ♪ 音效 sfx/whoosh_up
t+ 55.4s ♪ 音效 sfx/alarm
-t+ 55.4s 〰 震动:danger(危险逼近)
t+ 55.9s ♪ 音效 sfx/alarm
+t+ 55.9s ▶ 语音:「上!」
+t+ 55.4s 〰 震动:danger(危险逼近)
t+ 55.9s 〰 震动:danger(危险逼近)
+
+#### 【玩家动作】听到第二段警报和方向呼喊,同向滑开
+
t+ 56.4s ♪ 音效 sfx/dodge
-t+ 56.4s ♪ 音效 sfx/whoosh_left
+t+ 56.4s ♪ 音效 sfx/whoosh_right
t+ 59.4s ♪ 音效 sfx/alarm
-t+ 59.4s 〰 震动:danger(危险逼近)
t+ 59.9s ♪ 音效 sfx/alarm
+t+ 59.9s ▶ 语音:「右!」
+t+ 59.4s 〰 震动:danger(危险逼近)
t+ 59.9s 〰 震动:danger(危险逼近)
+
+#### 【玩家动作】听到第二段警报和方向呼喊,同向滑开
+
t+ 60.4s ♪ 音效 sfx/dodge
-t+ 60.4s ♪ 音效 sfx/whoosh_left
+t+ 60.4s ♪ 音效 sfx/whoosh_down
t+ 63.4s ♪ 音效 sfx/alarm
-t+ 63.4s 〰 震动:danger(危险逼近)
t+ 63.9s ♪ 音效 sfx/alarm
+t+ 63.9s ▶ 语音:「下!」
+t+ 63.4s 〰 震动:danger(危险逼近)
t+ 63.9s 〰 震动:danger(危险逼近)
+
+#### 【玩家动作】听到第二段警报和方向呼喊,同向滑开
+
t+ 64.4s ♪ 音效 sfx/dodge
-t+ 64.4s ♪ 音效 sfx/whoosh_left
+t+ 64.4s ♪ 音效 sfx/whoosh_down
t+ 67.4s ♪ 音效 sfx/alarm
-t+ 67.4s 〰 震动:danger(危险逼近)
t+ 67.9s ♪ 音效 sfx/alarm
+t+ 67.9s ▶ 语音:「下!」
+t+ 67.4s 〰 震动:danger(危险逼近)
t+ 67.9s 〰 震动:danger(危险逼近)
+
+#### 【玩家动作】听到第二段警报和方向呼喊,同向滑开
+
t+ 68.4s ♪ 音效 sfx/dodge
t+ 68.4s ♪ 音效 sfx/whoosh_up
t+ 71.4s ♪ 音效 sfx/alarm
-t+ 71.4s 〰 震动:danger(危险逼近)
t+ 71.9s ♪ 音效 sfx/alarm
+t+ 71.9s ▶ 语音:「上!」
+t+ 71.4s 〰 震动:danger(危险逼近)
t+ 71.9s 〰 震动:danger(危险逼近)
+
+#### 【玩家动作】听到第二段警报和方向呼喊,同向滑开
+
t+ 72.4s ♪ 音效 sfx/dodge
-t+ 72.4s ♪ 音效 sfx/whoosh_down
+t+ 72.4s ♪ 音效 sfx/whoosh_left
t+ 72.8s ▶ 语音:「双击展开护盾,能挡下一次撞击。」
t+ 72.8s 【状态】游戏停下来教新功能 暂停了刷怪教新功能:双击展开护盾(语音播放中,语速1)
@@ -120,26 +156,35 @@ t+ 74.9s ♪ 音效 sfx/shield
t+ 74.9s ▶ 语音:「护盾展开后会自动充能,好了我会告诉你。」
t+ 77.4s ♪ 音效 sfx/whoosh_right
t+ 80.4s ♪ 音效 sfx/alarm
-t+ 80.4s 〰 震动:danger(危险逼近)
t+ 80.9s ♪ 音效 sfx/alarm
+t+ 80.9s ▶ 语音:「右!」
+t+ 80.4s 〰 震动:danger(危险逼近)
t+ 80.9s 〰 震动:danger(危险逼近)
+
+#### 【玩家动作】听到第二段警报和方向呼喊,同向滑开
+
t+ 81.4s ♪ 音效 sfx/dodge
t+ 81.4s ▶ 语音:「十颗了,稳。」
-t+ 81.4s ♪ 音效 sfx/whoosh_down
+t+ 81.4s ♪ 音效 sfx/whoosh_right
t+ 81.4s 〰 震动:confirm(轻点确认)
t+ 84.4s ♪ 音效 sfx/alarm
-t+ 84.4s 〰 震动:danger(危险逼近)
t+ 84.9s ♪ 音效 sfx/alarm
+t+ 84.9s ▶ 语音:「右!」
+t+ 84.4s 〰 震动:danger(危险逼近)
t+ 84.9s 〰 震动:danger(危险逼近)
+
+#### 【玩家动作】听到第二段警报和方向呼喊,同向滑开
+
t+ 85.4s ♪ 音效 sfx/dodge
t+ 85.4s ♪ 音效 sfx/whoosh_right
t+ 87.8s ▶ 语音:「训练护盾关闭。接下来,靠你自己了。」
t+ 87.8s 〰 震动:warning(警告三连震)
t+ 88.4s ♪ 音效 sfx/alarm
-t+ 88.4s 〰 震动:danger(危险逼近)
-t+ 88.4s 【状态】保护期结束了,这颗我故意没动 对局中:1 颗陨石在逼近,听方位同向滑开(语音播放中,语速1)
t+ 88.9s ♪ 音效 sfx/alarm
+t+ 88.9s ▶ 语音:「右!」
+t+ 88.4s 〰 震动:danger(危险逼近)
t+ 88.9s 〰 震动:danger(危险逼近)
+t+ 88.9s 【状态】保护期结束了,这颗我故意没动 对局中:1 颗陨石在逼近,听方位同向滑开(语音播放中,语速1)
t+ 89.4s ♪ 音效 sfx/hit
t+ 89.4s ▶ 语音:「右边撞上的。听到右边的呼啸,向右滑。」
t+ 89.4s 〰 震动:hit(受击重震)
@@ -148,52 +193,75 @@ t+ 89.4s 〰 震动:hit(受击重震)
t+ 89.4s ♪ 音效 sfx/whoosh_up
t+ 91.2s ♪ 音效 sfx/alarm
-t+ 91.2s 〰 震动:danger(危险逼近)
-t+ 91.2s 【状态】又有一颗,也故意不躲——想听听第二次被撞会说什么 对局中:1 颗陨石在逼近,听方位同向滑开(语音播放中,语速1)
t+ 91.6s ▶ 向导语音:「被撞了。听方位,同向滑动就能拨开。」
t+ 91.7s ♪ 音效 sfx/alarm
+t+ 91.7s ▶ 语音:「上!」
+t+ 91.2s 〰 震动:danger(危险逼近)
t+ 91.7s 〰 震动:danger(危险逼近)
+t+ 91.7s 【状态】又有一颗,也故意不躲——想听听第二次被撞会说什么 对局中:1 颗陨石在逼近,听方位同向滑开(语音播放中,语速1)
t+ 92.2s ♪ 音效 sfx/hit
t+ 92.2s ▶ 语音:「上面撞上的。听到高高的呼啸,向上滑。」
t+ 92.2s 〰 震动:hit(受击重震)
#### 【玩家动作】第二次被撞:先听方位归因,又听到「这是最后一次机会,撑住」——这就是全部家底了
-t+ 92.6s ♪ 音效 sfx/whoosh_right
+t+ 92.6s ♪ 音效 sfx/whoosh_left
t+ 94.3s ▶ 语音:「船体只剩最后一次了,小心!」
t+ 94.4s ♪ 音效 sfx/alarm
t+ 94.9s ♪ 音效 sfx/alarm
+t+ 94.9s ▶ 语音:「左!」
t+ 94.4s 〰 震动:danger(危险逼近)
t+ 94.9s 〰 震动:danger(危险逼近)
+
+#### 【玩家动作】听到第二段警报和方向呼喊,同向滑开
+
t+ 95.4s ♪ 音效 sfx/dodge
-t+ 95.7s ♪ 音效 sfx/whoosh_down
-t+ 96.5s ▶ 向导语音:「这是最后一次机会,撑住。」
+t+ 95.7s ♪ 音效 sfx/whoosh_right
t+ 97.5s ♪ 音效 sfx/alarm
t+ 97.5s 〰 震动:danger(危险逼近)
t+ 98.0s ♪ 音效 sfx/alarm
+t+ 98.0s ▶ 语音:「右!」
+t+ 98.0s 〰 震动:danger(危险逼近)
+
+#### 【玩家动作】听到第二段警报和方向呼喊,同向滑开
+
t+ 98.5s ♪ 音效 sfx/dodge
t+ 98.8s ♪ 音效 sfx/whoosh_left
-t+ 98.0s 〰 震动:danger(危险逼近)
t+ 100.5s ♪ 音效 sfx/alarm
t+ 100.5s 〰 震动:danger(危险逼近)
t+ 101.0s ♪ 音效 sfx/alarm
-t+ 101.5s ♪ 音效 sfx/dodge
-t+ 101.8s ♪ 音效 sfx/whoosh_up
+t+ 101.0s ▶ 语音:「左!」
t+ 101.0s 〰 震动:danger(危险逼近)
+
+#### 【玩家动作】听到第二段警报和方向呼喊,同向滑开
+
+t+ 101.5s ♪ 音效 sfx/dodge
+t+ 101.8s ♪ 音效 sfx/whoosh_left
t+ 103.5s ♪ 音效 sfx/alarm
t+ 103.5s 〰 震动:danger(危险逼近)
t+ 104.0s ♪ 音效 sfx/alarm
-t+ 104.5s ♪ 音效 sfx/dodge
-t+ 104.8s ♪ 音效 sfx/whoosh_right
-t+ 104.9s ▶ 语音:「护盾充能完毕。」
+t+ 104.0s ▶ 语音:「左!」
t+ 104.0s 〰 震动:danger(危险逼近)
+
+#### 【玩家动作】听到第二段警报和方向呼喊,同向滑开
+
+t+ 104.5s ♪ 音效 sfx/dodge
+t+ 104.8s ♪ 音效 sfx/whoosh_up
+t+ 104.9s ▶ 语音:「护盾充能完毕。」
t+ 104.9s 〰 震动:pickup(获得)
t+ 106.4s ♪ 音效 sfx/alarm
-t+ 106.4s 〰 震动:danger(危险逼近)
t+ 106.9s ♪ 音效 sfx/alarm
+t+ 106.9s ▶ 语音:「上!」
+t+ 106.4s 〰 震动:danger(危险逼近)
t+ 106.9s 〰 震动:danger(危险逼近)
+
+#### 【玩家动作】听到第二段警报和方向呼喊,同向滑开
+
t+ 107.4s ♪ 音效 sfx/dodge
-t+ 107.7s ♪ 音效 sfx/whoosh_down
+t+ 107.7s ♪ 音效 sfx/whoosh_right
t+ 109.3s ♪ 音效 sfx/alarm
+t+ 109.8s ♪ 音效 sfx/alarm
+t+ 109.8s ▶ 语音:「右!」
t+ 109.3s 〰 震动:danger(危险逼近)
-t+ 109.3s 【状态】保护期结束后撑了 22 秒、挨了两下还活着(警报也只起一波了),先到这 对局中:1 颗陨石在逼近,听方位同向滑开(BGM=bgm/engine,语速1)
+t+ 109.8s 〰 震动:danger(危险逼近)
+t+ 109.8s 【状态】保护期结束后撑了 22 秒、挨了两下还活着;每回撞击前半秒都能听到方向呼喊,先到这 对局中:1 颗陨石在逼近,听方位同向滑开(语音播放中,语速1)
diff --git a/tools/gen_voice_dual.py b/tools/gen_voice_dual.py
index 5cc12484..ae18bf07 100644
--- a/tools/gen_voice_dual.py
+++ b/tools/gen_voice_dual.py
@@ -207,6 +207,8 @@ ESCAPE_LINES = [
("menu_home", _ESC, "回大厅。"),
("menu_back", _ESC, "返回游戏。"),
("skip_hint", _ESC, "单击可跳过旁白。"),
+ # ---- 向导层 round3(docs/design/14-guide-layer.md「round3 v1.2」,synthesis §3 定稿全文)----
+ ("gd_next_fuse", _ESC, "保险丝到手。接下来,去找电箱。"),
]
@@ -240,7 +242,7 @@ SIMON_LINES = [
("t_blunt_tap", _SIMON, "用指尖,轻轻点一下屏幕。"),
("t_blunt_double", _SIMON, "用指尖,快速点两下屏幕。"),
("t7_ready", _SIMON, "六种声音都记住了。后面的序列,会越来越长。"),
- ("t7_retry", _SIMON, "答错可以消耗机会重听。双击,可以随时重听。"),
+ ("t7_retry", _SIMON, "答错可以消耗机会重听。向上滑,可以随时重听。"),
("t_skip", _SIMON, "跳过教学,直接开始。"),
# ---- 轮次播报(整句,round_01..round_20 + 兜底) ----
*[(f"round_{i + 1:02d}", _SIMON, f"{w}轮,听好了。") for i, w in enumerate(_SIMON_ROUNDS)],
@@ -273,9 +275,14 @@ SIMON_LINES = [
("menu_back", _SIMON, "返回游戏。"),
("skip_hint", _SIMON, "单击可跳过旁白。"),
# ---- 向导层(docs/design/14-guide-layer.md,schemes §1.5 定稿全文)----
- ("gd_relisten", _SIMON, "需要的话,双击可以重新听一遍序列。"),
+ ("gd_relisten", _SIMON, "需要的话,向上滑可以重新听一遍序列。"),
# ---- 向导层 round2(docs/design/14-guide-layer.md「round2 v1.1」,synthesis §3 定稿全文)----
- ("gd_economy", _SIMON, "记不住就双击重新听,免费机会有两次,用完要扣一次机会。"),
+ # round3 G5 重录(14 号文档「round3 v1.2」):双击改回纯音色、重听改绑上滑,
+ # 机会经济句按裁定书新文案一字不改重录;教学链 t7_retry 同步手势口径。
+ ("gd_economy", _SIMON, "记不住就向上滑,重新听一遍。免费机会有两次,用完要扣一次机会。"),
+ # ---- 向导层 round3(docs/design/14-guide-layer.md「round3 v1.2」,synthesis §3 定稿全文)----
+ ("gd_clear", _SIMON, "漂亮,过了。"),
+ ("gd_record", _SIMON, "破纪录了。"),
]
@@ -329,6 +336,9 @@ RHYTHM_LINES = [
("gd_miss_early", _RHY, "抢拍了。等声音落下再滑。"),
("gd_miss_late", _RHY, "慢了半拍。跟着节拍走。"),
("gd_miss_wrong", _RHY, "方向不对。跟着音色滑。"),
+ # ---- 向导层 round3(docs/design/14-guide-layer.md「round3 v1.2」,synthesis §3 定稿全文)----
+ ("gd_slow", _RHY, "我放慢一些,跟着试试。"),
+ ("gd_count", _RHY, "四拍之后,继续。"),
]
@@ -401,6 +411,12 @@ SPACE_LINES = [
("gd_hit_hint", _SPC, "被撞了。听方位,同向滑动就能拨开。"),
# ---- 向导层 round2(docs/design/14-guide-layer.md「round2 v1.1」,synthesis §3 定稿全文)----
("gd_last_life", _SPC, "这是最后一次机会,撑住。"),
+ # ---- 向导层 round3(docs/design/14-guide-layer.md「round3 v1.2」,synthesis §3 定稿全文)----
+ # dir_* 为角色音风格超短呼喊,speaker 用本游戏旁白 pair(synthesis §3 表注)。
+ ("dir_left", _SPC, "左!"),
+ ("dir_right", _SPC, "右!"),
+ ("dir_up", _SPC, "上!"),
+ ("dir_down", _SPC, "下!"),
]
diff --git a/web/escape/audio/voice/female/again.ogg b/web/escape/audio/voice/female/again.ogg
index 609d84f7..bbc34f60 100644
Binary files a/web/escape/audio/voice/female/again.ogg and b/web/escape/audio/voice/female/again.ogg differ
diff --git a/web/escape/audio/voice/female/box_fixed.ogg b/web/escape/audio/voice/female/box_fixed.ogg
index 6678f3df..ccf115cf 100644
Binary files a/web/escape/audio/voice/female/box_fixed.ogg and b/web/escape/audio/voice/female/box_fixed.ogg differ
diff --git a/web/escape/audio/voice/female/empty_1.ogg b/web/escape/audio/voice/female/empty_1.ogg
index 71f27087..9d0f0229 100644
Binary files a/web/escape/audio/voice/female/empty_1.ogg and b/web/escape/audio/voice/female/empty_1.ogg differ
diff --git a/web/escape/audio/voice/female/empty_2.ogg b/web/escape/audio/voice/female/empty_2.ogg
index 6f2ea5ff..3a2b0e76 100644
Binary files a/web/escape/audio/voice/female/empty_2.ogg and b/web/escape/audio/voice/female/empty_2.ogg differ
diff --git a/web/escape/audio/voice/female/empty_3.ogg b/web/escape/audio/voice/female/empty_3.ogg
index fcde5b6a..ad6ef599 100644
Binary files a/web/escape/audio/voice/female/empty_3.ogg and b/web/escape/audio/voice/female/empty_3.ogg differ
diff --git a/web/escape/audio/voice/female/escape.ogg b/web/escape/audio/voice/female/escape.ogg
index 343fcd29..73dd4b47 100644
Binary files a/web/escape/audio/voice/female/escape.ogg and b/web/escape/audio/voice/female/escape.ogg differ
diff --git a/web/escape/audio/voice/female/fix_box.ogg b/web/escape/audio/voice/female/fix_box.ogg
index 64cd849a..b6684966 100644
Binary files a/web/escape/audio/voice/female/fix_box.ogg and b/web/escape/audio/voice/female/fix_box.ogg differ
diff --git a/web/escape/audio/voice/female/found_key.ogg b/web/escape/audio/voice/female/found_key.ogg
index c1e8cda1..be441555 100644
Binary files a/web/escape/audio/voice/female/found_key.ogg and b/web/escape/audio/voice/female/found_key.ogg differ
diff --git a/web/escape/audio/voice/female/g0_intro.ogg b/web/escape/audio/voice/female/g0_intro.ogg
index ee5763f8..e7798988 100644
Binary files a/web/escape/audio/voice/female/g0_intro.ogg and b/web/escape/audio/voice/female/g0_intro.ogg differ
diff --git a/web/escape/audio/voice/female/g1_done.ogg b/web/escape/audio/voice/female/g1_done.ogg
index a079c0e6..28d24e46 100644
Binary files a/web/escape/audio/voice/female/g1_done.ogg and b/web/escape/audio/voice/female/g1_done.ogg differ
diff --git a/web/escape/audio/voice/female/g1_move.ogg b/web/escape/audio/voice/female/g1_move.ogg
index bcd0db3f..cd525590 100644
Binary files a/web/escape/audio/voice/female/g1_move.ogg and b/web/escape/audio/voice/female/g1_move.ogg differ
diff --git a/web/escape/audio/voice/female/g2_wall.ogg b/web/escape/audio/voice/female/g2_wall.ogg
index bf43aa72..45608111 100644
Binary files a/web/escape/audio/voice/female/g2_wall.ogg and b/web/escape/audio/voice/female/g2_wall.ogg differ
diff --git a/web/escape/audio/voice/female/g3_left.ogg b/web/escape/audio/voice/female/g3_left.ogg
index fc9dc87d..6b08522d 100644
Binary files a/web/escape/audio/voice/female/g3_left.ogg and b/web/escape/audio/voice/female/g3_left.ogg differ
diff --git a/web/escape/audio/voice/female/g4_down.ogg b/web/escape/audio/voice/female/g4_down.ogg
index 0f7e944f..4c6e6df1 100644
Binary files a/web/escape/audio/voice/female/g4_down.ogg and b/web/escape/audio/voice/female/g4_down.ogg differ
diff --git a/web/escape/audio/voice/female/g5_inspect.ogg b/web/escape/audio/voice/female/g5_inspect.ogg
index 91c723b9..9d8762eb 100644
Binary files a/web/escape/audio/voice/female/g5_inspect.ogg and b/web/escape/audio/voice/female/g5_inspect.ogg differ
diff --git a/web/escape/audio/voice/female/g5_key.ogg b/web/escape/audio/voice/female/g5_key.ogg
index a88e1eda..7ed26752 100644
Binary files a/web/escape/audio/voice/female/g5_key.ogg and b/web/escape/audio/voice/female/g5_key.ogg differ
diff --git a/web/escape/audio/voice/female/g6_done.ogg b/web/escape/audio/voice/female/g6_done.ogg
index 3f3936c4..b2bff63b 100644
Binary files a/web/escape/audio/voice/female/g6_done.ogg and b/web/escape/audio/voice/female/g6_done.ogg differ
diff --git a/web/escape/audio/voice/female/g6_doubletap.ogg b/web/escape/audio/voice/female/g6_doubletap.ogg
index 9cc0c8f9..19565a23 100644
Binary files a/web/escape/audio/voice/female/g6_doubletap.ogg and b/web/escape/audio/voice/female/g6_doubletap.ogg differ
diff --git a/web/escape/audio/voice/female/g7_goal.ogg b/web/escape/audio/voice/female/g7_goal.ogg
index 62adc106..d1efb62b 100644
Binary files a/web/escape/audio/voice/female/g7_goal.ogg and b/web/escape/audio/voice/female/g7_goal.ogg differ
diff --git a/web/escape/audio/voice/female/gd_next_fuse.m4a b/web/escape/audio/voice/female/gd_next_fuse.m4a
new file mode 100644
index 00000000..97a2c887
Binary files /dev/null and b/web/escape/audio/voice/female/gd_next_fuse.m4a differ
diff --git a/web/escape/audio/voice/female/gd_next_fuse.ogg b/web/escape/audio/voice/female/gd_next_fuse.ogg
new file mode 100644
index 00000000..9db16340
Binary files /dev/null and b/web/escape/audio/voice/female/gd_next_fuse.ogg differ
diff --git a/web/escape/audio/voice/female/guide_blunt_down.ogg b/web/escape/audio/voice/female/guide_blunt_down.ogg
index 4b385f63..fe851706 100644
Binary files a/web/escape/audio/voice/female/guide_blunt_down.ogg and b/web/escape/audio/voice/female/guide_blunt_down.ogg differ
diff --git a/web/escape/audio/voice/female/guide_blunt_left.ogg b/web/escape/audio/voice/female/guide_blunt_left.ogg
index 08b12501..71f32791 100644
Binary files a/web/escape/audio/voice/female/guide_blunt_left.ogg and b/web/escape/audio/voice/female/guide_blunt_left.ogg differ
diff --git a/web/escape/audio/voice/female/guide_blunt_right.ogg b/web/escape/audio/voice/female/guide_blunt_right.ogg
index 8618ef46..735cb907 100644
Binary files a/web/escape/audio/voice/female/guide_blunt_right.ogg and b/web/escape/audio/voice/female/guide_blunt_right.ogg differ
diff --git a/web/escape/audio/voice/female/guide_blunt_up.ogg b/web/escape/audio/voice/female/guide_blunt_up.ogg
index df9db5d9..5e240137 100644
Binary files a/web/escape/audio/voice/female/guide_blunt_up.ogg and b/web/escape/audio/voice/female/guide_blunt_up.ogg differ
diff --git a/web/escape/audio/voice/female/guide_offpath.ogg b/web/escape/audio/voice/female/guide_offpath.ogg
index 68f83c4b..5d1ecd5c 100644
Binary files a/web/escape/audio/voice/female/guide_offpath.ogg and b/web/escape/audio/voice/female/guide_offpath.ogg differ
diff --git a/web/escape/audio/voice/female/guide_skip.ogg b/web/escape/audio/voice/female/guide_skip.ogg
index 4e3e88c0..04c90a94 100644
Binary files a/web/escape/audio/voice/female/guide_skip.ogg and b/web/escape/audio/voice/female/guide_skip.ogg differ
diff --git a/web/escape/audio/voice/female/guide_wrong_down.ogg b/web/escape/audio/voice/female/guide_wrong_down.ogg
index 5bb9acbe..1a525bbe 100644
Binary files a/web/escape/audio/voice/female/guide_wrong_down.ogg and b/web/escape/audio/voice/female/guide_wrong_down.ogg differ
diff --git a/web/escape/audio/voice/female/guide_wrong_gesture.ogg b/web/escape/audio/voice/female/guide_wrong_gesture.ogg
index 5f1eafad..d9f69cfd 100644
Binary files a/web/escape/audio/voice/female/guide_wrong_gesture.ogg and b/web/escape/audio/voice/female/guide_wrong_gesture.ogg differ
diff --git a/web/escape/audio/voice/female/guide_wrong_left.ogg b/web/escape/audio/voice/female/guide_wrong_left.ogg
index ee9ed70d..20c076ea 100644
Binary files a/web/escape/audio/voice/female/guide_wrong_left.ogg and b/web/escape/audio/voice/female/guide_wrong_left.ogg differ
diff --git a/web/escape/audio/voice/female/guide_wrong_right.ogg b/web/escape/audio/voice/female/guide_wrong_right.ogg
index b02f24fb..1614ad38 100644
Binary files a/web/escape/audio/voice/female/guide_wrong_right.ogg and b/web/escape/audio/voice/female/guide_wrong_right.ogg differ
diff --git a/web/escape/audio/voice/female/guide_wrong_up.ogg b/web/escape/audio/voice/female/guide_wrong_up.ogg
index 6ca95de7..a272bbca 100644
Binary files a/web/escape/audio/voice/female/guide_wrong_up.ogg and b/web/escape/audio/voice/female/guide_wrong_up.ogg differ
diff --git a/web/escape/audio/voice/female/help_ops.ogg b/web/escape/audio/voice/female/help_ops.ogg
index d488ba72..01ab7c60 100644
Binary files a/web/escape/audio/voice/female/help_ops.ogg and b/web/escape/audio/voice/female/help_ops.ogg differ
diff --git a/web/escape/audio/voice/female/inspect_box_dead.ogg b/web/escape/audio/voice/female/inspect_box_dead.ogg
index 582d05c2..1b63a368 100644
Binary files a/web/escape/audio/voice/female/inspect_box_dead.ogg and b/web/escape/audio/voice/female/inspect_box_dead.ogg differ
diff --git a/web/escape/audio/voice/female/inspect_cabinet_locked.ogg b/web/escape/audio/voice/female/inspect_cabinet_locked.ogg
index ed0d138a..ba820158 100644
Binary files a/web/escape/audio/voice/female/inspect_cabinet_locked.ogg and b/web/escape/audio/voice/female/inspect_cabinet_locked.ogg differ
diff --git a/web/escape/audio/voice/female/inspect_gate.ogg b/web/escape/audio/voice/female/inspect_gate.ogg
index d360711c..9776ca59 100644
Binary files a/web/escape/audio/voice/female/inspect_gate.ogg and b/web/escape/audio/voice/female/inspect_gate.ogg differ
diff --git a/web/escape/audio/voice/female/inspect_gate_ready.ogg b/web/escape/audio/voice/female/inspect_gate_ready.ogg
index d5371b31..2050f9c6 100644
Binary files a/web/escape/audio/voice/female/inspect_gate_ready.ogg and b/web/escape/audio/voice/female/inspect_gate_ready.ogg differ
diff --git a/web/escape/audio/voice/female/inv_both.ogg b/web/escape/audio/voice/female/inv_both.ogg
index 7519b4f0..55931220 100644
Binary files a/web/escape/audio/voice/female/inv_both.ogg and b/web/escape/audio/voice/female/inv_both.ogg differ
diff --git a/web/escape/audio/voice/female/inv_empty.ogg b/web/escape/audio/voice/female/inv_empty.ogg
index 8de6f3c5..b9d3b711 100644
Binary files a/web/escape/audio/voice/female/inv_empty.ogg and b/web/escape/audio/voice/female/inv_empty.ogg differ
diff --git a/web/escape/audio/voice/female/inv_fuse.ogg b/web/escape/audio/voice/female/inv_fuse.ogg
index 16cef413..b7fe3115 100644
Binary files a/web/escape/audio/voice/female/inv_fuse.ogg and b/web/escape/audio/voice/female/inv_fuse.ogg differ
diff --git a/web/escape/audio/voice/female/inv_key.ogg b/web/escape/audio/voice/female/inv_key.ogg
index 144a272b..e0ce950c 100644
Binary files a/web/escape/audio/voice/female/inv_key.ogg and b/web/escape/audio/voice/female/inv_key.ogg differ
diff --git a/web/escape/audio/voice/female/menu_back.ogg b/web/escape/audio/voice/female/menu_back.ogg
index ea0cc6c5..963406cc 100644
Binary files a/web/escape/audio/voice/female/menu_back.ogg and b/web/escape/audio/voice/female/menu_back.ogg differ
diff --git a/web/escape/audio/voice/female/menu_home.ogg b/web/escape/audio/voice/female/menu_home.ogg
index 61b0e3c5..c04e5924 100644
Binary files a/web/escape/audio/voice/female/menu_home.ogg and b/web/escape/audio/voice/female/menu_home.ogg differ
diff --git a/web/escape/audio/voice/female/menu_open.ogg b/web/escape/audio/voice/female/menu_open.ogg
index 788420b7..d0540b46 100644
Binary files a/web/escape/audio/voice/female/menu_open.ogg and b/web/escape/audio/voice/female/menu_open.ogg differ
diff --git a/web/escape/audio/voice/female/menu_restart.ogg b/web/escape/audio/voice/female/menu_restart.ogg
index e3e4c860..2dd0c0c5 100644
Binary files a/web/escape/audio/voice/female/menu_restart.ogg and b/web/escape/audio/voice/female/menu_restart.ogg differ
diff --git a/web/escape/audio/voice/female/nav_down.ogg b/web/escape/audio/voice/female/nav_down.ogg
index c0e475bb..eef5ed96 100644
Binary files a/web/escape/audio/voice/female/nav_down.ogg and b/web/escape/audio/voice/female/nav_down.ogg differ
diff --git a/web/escape/audio/voice/female/nav_left.ogg b/web/escape/audio/voice/female/nav_left.ogg
index b220388d..ab0f4421 100644
Binary files a/web/escape/audio/voice/female/nav_left.ogg and b/web/escape/audio/voice/female/nav_left.ogg differ
diff --git a/web/escape/audio/voice/female/nav_right.ogg b/web/escape/audio/voice/female/nav_right.ogg
index 6f1cf5f2..f85f0d33 100644
Binary files a/web/escape/audio/voice/female/nav_right.ogg and b/web/escape/audio/voice/female/nav_right.ogg differ
diff --git a/web/escape/audio/voice/female/nav_up.ogg b/web/escape/audio/voice/female/nav_up.ogg
index f3969f7e..8e75a7e1 100644
Binary files a/web/escape/audio/voice/female/nav_up.ogg and b/web/escape/audio/voice/female/nav_up.ogg differ
diff --git a/web/escape/audio/voice/female/reopen_prompt.ogg b/web/escape/audio/voice/female/reopen_prompt.ogg
index 81231a8f..3e020cf1 100644
Binary files a/web/escape/audio/voice/female/reopen_prompt.ogg and b/web/escape/audio/voice/female/reopen_prompt.ogg differ
diff --git a/web/escape/audio/voice/female/replay.ogg b/web/escape/audio/voice/female/replay.ogg
index 03fdb348..a31a75e9 100644
Binary files a/web/escape/audio/voice/female/replay.ogg and b/web/escape/audio/voice/female/replay.ogg differ
diff --git a/web/escape/audio/voice/female/room_cabinet.ogg b/web/escape/audio/voice/female/room_cabinet.ogg
index c91eb324..3257312c 100644
Binary files a/web/escape/audio/voice/female/room_cabinet.ogg and b/web/escape/audio/voice/female/room_cabinet.ogg differ
diff --git a/web/escape/audio/voice/female/room_gate.ogg b/web/escape/audio/voice/female/room_gate.ogg
index 04a901c6..c4275c7e 100644
Binary files a/web/escape/audio/voice/female/room_gate.ogg and b/web/escape/audio/voice/female/room_gate.ogg differ
diff --git a/web/escape/audio/voice/female/room_power.ogg b/web/escape/audio/voice/female/room_power.ogg
index d6c5e9d0..974af2f2 100644
Binary files a/web/escape/audio/voice/female/room_power.ogg and b/web/escape/audio/voice/female/room_power.ogg differ
diff --git a/web/escape/audio/voice/female/room_storage.ogg b/web/escape/audio/voice/female/room_storage.ogg
index cff23bb8..a3f59dc7 100644
Binary files a/web/escape/audio/voice/female/room_storage.ogg and b/web/escape/audio/voice/female/room_storage.ogg differ
diff --git a/web/escape/audio/voice/female/skip_hint.ogg b/web/escape/audio/voice/female/skip_hint.ogg
index da6649d5..f9dd4c8f 100644
Binary files a/web/escape/audio/voice/female/skip_hint.ogg and b/web/escape/audio/voice/female/skip_hint.ogg differ
diff --git a/web/escape/audio/voice/female/start_room.ogg b/web/escape/audio/voice/female/start_room.ogg
index 5911043e..02e665e3 100644
Binary files a/web/escape/audio/voice/female/start_room.ogg and b/web/escape/audio/voice/female/start_room.ogg differ
diff --git a/web/escape/audio/voice/female/stuck_ask.ogg b/web/escape/audio/voice/female/stuck_ask.ogg
index e66f19d0..ef45d505 100644
Binary files a/web/escape/audio/voice/female/stuck_ask.ogg and b/web/escape/audio/voice/female/stuck_ask.ogg differ
diff --git a/web/escape/audio/voice/female/stuck_box_1.ogg b/web/escape/audio/voice/female/stuck_box_1.ogg
index 428ab0b3..1d02109e 100644
Binary files a/web/escape/audio/voice/female/stuck_box_1.ogg and b/web/escape/audio/voice/female/stuck_box_1.ogg differ
diff --git a/web/escape/audio/voice/female/stuck_box_2.ogg b/web/escape/audio/voice/female/stuck_box_2.ogg
index 490acfda..365802ff 100644
Binary files a/web/escape/audio/voice/female/stuck_box_2.ogg and b/web/escape/audio/voice/female/stuck_box_2.ogg differ
diff --git a/web/escape/audio/voice/female/stuck_box_3.ogg b/web/escape/audio/voice/female/stuck_box_3.ogg
index 4176157e..dc2c1bc2 100644
Binary files a/web/escape/audio/voice/female/stuck_box_3.ogg and b/web/escape/audio/voice/female/stuck_box_3.ogg differ
diff --git a/web/escape/audio/voice/female/stuck_cabinet_1.ogg b/web/escape/audio/voice/female/stuck_cabinet_1.ogg
index 4d3c5b08..656d1738 100644
Binary files a/web/escape/audio/voice/female/stuck_cabinet_1.ogg and b/web/escape/audio/voice/female/stuck_cabinet_1.ogg differ
diff --git a/web/escape/audio/voice/female/stuck_cabinet_2.ogg b/web/escape/audio/voice/female/stuck_cabinet_2.ogg
index 95037edd..68079fba 100644
Binary files a/web/escape/audio/voice/female/stuck_cabinet_2.ogg and b/web/escape/audio/voice/female/stuck_cabinet_2.ogg differ
diff --git a/web/escape/audio/voice/female/stuck_cabinet_3.ogg b/web/escape/audio/voice/female/stuck_cabinet_3.ogg
index a71ca6e8..fc407d4a 100644
Binary files a/web/escape/audio/voice/female/stuck_cabinet_3.ogg and b/web/escape/audio/voice/female/stuck_cabinet_3.ogg differ
diff --git a/web/escape/audio/voice/female/stuck_gate_1.ogg b/web/escape/audio/voice/female/stuck_gate_1.ogg
index e0bb89dc..4d076316 100644
Binary files a/web/escape/audio/voice/female/stuck_gate_1.ogg and b/web/escape/audio/voice/female/stuck_gate_1.ogg differ
diff --git a/web/escape/audio/voice/female/stuck_gate_2.ogg b/web/escape/audio/voice/female/stuck_gate_2.ogg
index bcc16a8b..c742fd18 100644
Binary files a/web/escape/audio/voice/female/stuck_gate_2.ogg and b/web/escape/audio/voice/female/stuck_gate_2.ogg differ
diff --git a/web/escape/audio/voice/female/stuck_gate_3.ogg b/web/escape/audio/voice/female/stuck_gate_3.ogg
index d49c6c0d..aa3a39ef 100644
Binary files a/web/escape/audio/voice/female/stuck_gate_3.ogg and b/web/escape/audio/voice/female/stuck_gate_3.ogg differ
diff --git a/web/escape/audio/voice/female/stuck_key_1.ogg b/web/escape/audio/voice/female/stuck_key_1.ogg
index dfbbaa7b..1a696c16 100644
Binary files a/web/escape/audio/voice/female/stuck_key_1.ogg and b/web/escape/audio/voice/female/stuck_key_1.ogg differ
diff --git a/web/escape/audio/voice/female/stuck_key_2.ogg b/web/escape/audio/voice/female/stuck_key_2.ogg
index 178896d8..b6d03e46 100644
Binary files a/web/escape/audio/voice/female/stuck_key_2.ogg and b/web/escape/audio/voice/female/stuck_key_2.ogg differ
diff --git a/web/escape/audio/voice/female/stuck_key_3.ogg b/web/escape/audio/voice/female/stuck_key_3.ogg
index 4df2fdd7..e4fd84a6 100644
Binary files a/web/escape/audio/voice/female/stuck_key_3.ogg and b/web/escape/audio/voice/female/stuck_key_3.ogg differ
diff --git a/web/escape/audio/voice/female/time_band1.ogg b/web/escape/audio/voice/female/time_band1.ogg
index 676f8b6d..e1700705 100644
Binary files a/web/escape/audio/voice/female/time_band1.ogg and b/web/escape/audio/voice/female/time_band1.ogg differ
diff --git a/web/escape/audio/voice/female/time_band2.ogg b/web/escape/audio/voice/female/time_band2.ogg
index de205328..de7fd78e 100644
Binary files a/web/escape/audio/voice/female/time_band2.ogg and b/web/escape/audio/voice/female/time_band2.ogg differ
diff --git a/web/escape/audio/voice/female/time_band3.ogg b/web/escape/audio/voice/female/time_band3.ogg
index 334f97f4..3ed99989 100644
Binary files a/web/escape/audio/voice/female/time_band3.ogg and b/web/escape/audio/voice/female/time_band3.ogg differ
diff --git a/web/escape/audio/voice/female/time_band4.ogg b/web/escape/audio/voice/female/time_band4.ogg
index a1534c54..8a518358 100644
Binary files a/web/escape/audio/voice/female/time_band4.ogg and b/web/escape/audio/voice/female/time_band4.ogg differ
diff --git a/web/escape/audio/voice/female/unlock_cabinet.ogg b/web/escape/audio/voice/female/unlock_cabinet.ogg
index 199aead4..99228bf8 100644
Binary files a/web/escape/audio/voice/female/unlock_cabinet.ogg and b/web/escape/audio/voice/female/unlock_cabinet.ogg differ
diff --git a/web/escape/audio/voice/female/use_fail.ogg b/web/escape/audio/voice/female/use_fail.ogg
index 958fc860..deec5ab6 100644
Binary files a/web/escape/audio/voice/female/use_fail.ogg and b/web/escape/audio/voice/female/use_fail.ogg differ
diff --git a/web/escape/audio/voice/female/wall.ogg b/web/escape/audio/voice/female/wall.ogg
index 7db3a657..029184aa 100644
Binary files a/web/escape/audio/voice/female/wall.ogg and b/web/escape/audio/voice/female/wall.ogg differ
diff --git a/web/escape/audio/voice/male/again.ogg b/web/escape/audio/voice/male/again.ogg
index d53508e1..9a41eeab 100644
Binary files a/web/escape/audio/voice/male/again.ogg and b/web/escape/audio/voice/male/again.ogg differ
diff --git a/web/escape/audio/voice/male/box_fixed.ogg b/web/escape/audio/voice/male/box_fixed.ogg
index 01da1ab7..c8964569 100644
Binary files a/web/escape/audio/voice/male/box_fixed.ogg and b/web/escape/audio/voice/male/box_fixed.ogg differ
diff --git a/web/escape/audio/voice/male/empty_1.ogg b/web/escape/audio/voice/male/empty_1.ogg
index e6ec2517..656239c7 100644
Binary files a/web/escape/audio/voice/male/empty_1.ogg and b/web/escape/audio/voice/male/empty_1.ogg differ
diff --git a/web/escape/audio/voice/male/empty_2.ogg b/web/escape/audio/voice/male/empty_2.ogg
index 67fc5bfb..0f4112b1 100644
Binary files a/web/escape/audio/voice/male/empty_2.ogg and b/web/escape/audio/voice/male/empty_2.ogg differ
diff --git a/web/escape/audio/voice/male/empty_3.ogg b/web/escape/audio/voice/male/empty_3.ogg
index 9b1a3535..21f8bbbb 100644
Binary files a/web/escape/audio/voice/male/empty_3.ogg and b/web/escape/audio/voice/male/empty_3.ogg differ
diff --git a/web/escape/audio/voice/male/escape.ogg b/web/escape/audio/voice/male/escape.ogg
index 2cb9418a..93096015 100644
Binary files a/web/escape/audio/voice/male/escape.ogg and b/web/escape/audio/voice/male/escape.ogg differ
diff --git a/web/escape/audio/voice/male/fix_box.ogg b/web/escape/audio/voice/male/fix_box.ogg
index 2b401a6b..46c2511f 100644
Binary files a/web/escape/audio/voice/male/fix_box.ogg and b/web/escape/audio/voice/male/fix_box.ogg differ
diff --git a/web/escape/audio/voice/male/found_key.ogg b/web/escape/audio/voice/male/found_key.ogg
index 608a1865..8dd2856a 100644
Binary files a/web/escape/audio/voice/male/found_key.ogg and b/web/escape/audio/voice/male/found_key.ogg differ
diff --git a/web/escape/audio/voice/male/g0_intro.ogg b/web/escape/audio/voice/male/g0_intro.ogg
index 3703a082..51422225 100644
Binary files a/web/escape/audio/voice/male/g0_intro.ogg and b/web/escape/audio/voice/male/g0_intro.ogg differ
diff --git a/web/escape/audio/voice/male/g1_done.ogg b/web/escape/audio/voice/male/g1_done.ogg
index cfbcab04..163557c8 100644
Binary files a/web/escape/audio/voice/male/g1_done.ogg and b/web/escape/audio/voice/male/g1_done.ogg differ
diff --git a/web/escape/audio/voice/male/g1_move.ogg b/web/escape/audio/voice/male/g1_move.ogg
index 56e7a2ba..45322853 100644
Binary files a/web/escape/audio/voice/male/g1_move.ogg and b/web/escape/audio/voice/male/g1_move.ogg differ
diff --git a/web/escape/audio/voice/male/g2_wall.ogg b/web/escape/audio/voice/male/g2_wall.ogg
index a1ef9c9e..71c1d21f 100644
Binary files a/web/escape/audio/voice/male/g2_wall.ogg and b/web/escape/audio/voice/male/g2_wall.ogg differ
diff --git a/web/escape/audio/voice/male/g3_left.ogg b/web/escape/audio/voice/male/g3_left.ogg
index 4a81dc51..7c528ab1 100644
Binary files a/web/escape/audio/voice/male/g3_left.ogg and b/web/escape/audio/voice/male/g3_left.ogg differ
diff --git a/web/escape/audio/voice/male/g4_down.ogg b/web/escape/audio/voice/male/g4_down.ogg
index 3e7151bd..4e1ff6a5 100644
Binary files a/web/escape/audio/voice/male/g4_down.ogg and b/web/escape/audio/voice/male/g4_down.ogg differ
diff --git a/web/escape/audio/voice/male/g5_inspect.ogg b/web/escape/audio/voice/male/g5_inspect.ogg
index 9bc0eb2d..c68e135c 100644
Binary files a/web/escape/audio/voice/male/g5_inspect.ogg and b/web/escape/audio/voice/male/g5_inspect.ogg differ
diff --git a/web/escape/audio/voice/male/g5_key.ogg b/web/escape/audio/voice/male/g5_key.ogg
index 26771e8f..0be3eb0f 100644
Binary files a/web/escape/audio/voice/male/g5_key.ogg and b/web/escape/audio/voice/male/g5_key.ogg differ
diff --git a/web/escape/audio/voice/male/g6_done.ogg b/web/escape/audio/voice/male/g6_done.ogg
index 307f9e8d..97bb42a8 100644
Binary files a/web/escape/audio/voice/male/g6_done.ogg and b/web/escape/audio/voice/male/g6_done.ogg differ
diff --git a/web/escape/audio/voice/male/g6_doubletap.ogg b/web/escape/audio/voice/male/g6_doubletap.ogg
index 50047043..aaa58fa5 100644
Binary files a/web/escape/audio/voice/male/g6_doubletap.ogg and b/web/escape/audio/voice/male/g6_doubletap.ogg differ
diff --git a/web/escape/audio/voice/male/g7_goal.ogg b/web/escape/audio/voice/male/g7_goal.ogg
index 6487e3f6..5c13ee50 100644
Binary files a/web/escape/audio/voice/male/g7_goal.ogg and b/web/escape/audio/voice/male/g7_goal.ogg differ
diff --git a/web/escape/audio/voice/male/gd_next_fuse.m4a b/web/escape/audio/voice/male/gd_next_fuse.m4a
new file mode 100644
index 00000000..a7aa85f8
Binary files /dev/null and b/web/escape/audio/voice/male/gd_next_fuse.m4a differ
diff --git a/web/escape/audio/voice/male/gd_next_fuse.ogg b/web/escape/audio/voice/male/gd_next_fuse.ogg
new file mode 100644
index 00000000..e30c6156
Binary files /dev/null and b/web/escape/audio/voice/male/gd_next_fuse.ogg differ
diff --git a/web/escape/audio/voice/male/guide_blunt_down.ogg b/web/escape/audio/voice/male/guide_blunt_down.ogg
index 87dced83..72000e5b 100644
Binary files a/web/escape/audio/voice/male/guide_blunt_down.ogg and b/web/escape/audio/voice/male/guide_blunt_down.ogg differ
diff --git a/web/escape/audio/voice/male/guide_blunt_left.ogg b/web/escape/audio/voice/male/guide_blunt_left.ogg
index 91b973c1..b893da18 100644
Binary files a/web/escape/audio/voice/male/guide_blunt_left.ogg and b/web/escape/audio/voice/male/guide_blunt_left.ogg differ
diff --git a/web/escape/audio/voice/male/guide_blunt_right.ogg b/web/escape/audio/voice/male/guide_blunt_right.ogg
index abd6ff4f..bb91fafa 100644
Binary files a/web/escape/audio/voice/male/guide_blunt_right.ogg and b/web/escape/audio/voice/male/guide_blunt_right.ogg differ
diff --git a/web/escape/audio/voice/male/guide_blunt_up.ogg b/web/escape/audio/voice/male/guide_blunt_up.ogg
index 5d898958..17771966 100644
Binary files a/web/escape/audio/voice/male/guide_blunt_up.ogg and b/web/escape/audio/voice/male/guide_blunt_up.ogg differ
diff --git a/web/escape/audio/voice/male/guide_offpath.ogg b/web/escape/audio/voice/male/guide_offpath.ogg
index 821b3d6b..769c9cf4 100644
Binary files a/web/escape/audio/voice/male/guide_offpath.ogg and b/web/escape/audio/voice/male/guide_offpath.ogg differ
diff --git a/web/escape/audio/voice/male/guide_skip.ogg b/web/escape/audio/voice/male/guide_skip.ogg
index 14e68690..33256485 100644
Binary files a/web/escape/audio/voice/male/guide_skip.ogg and b/web/escape/audio/voice/male/guide_skip.ogg differ
diff --git a/web/escape/audio/voice/male/guide_wrong_down.ogg b/web/escape/audio/voice/male/guide_wrong_down.ogg
index 509acb96..44f9dcbf 100644
Binary files a/web/escape/audio/voice/male/guide_wrong_down.ogg and b/web/escape/audio/voice/male/guide_wrong_down.ogg differ
diff --git a/web/escape/audio/voice/male/guide_wrong_gesture.ogg b/web/escape/audio/voice/male/guide_wrong_gesture.ogg
index b8f264a0..c53e8e51 100644
Binary files a/web/escape/audio/voice/male/guide_wrong_gesture.ogg and b/web/escape/audio/voice/male/guide_wrong_gesture.ogg differ
diff --git a/web/escape/audio/voice/male/guide_wrong_left.ogg b/web/escape/audio/voice/male/guide_wrong_left.ogg
index a94ff9a6..c8ba89a0 100644
Binary files a/web/escape/audio/voice/male/guide_wrong_left.ogg and b/web/escape/audio/voice/male/guide_wrong_left.ogg differ
diff --git a/web/escape/audio/voice/male/guide_wrong_right.ogg b/web/escape/audio/voice/male/guide_wrong_right.ogg
index dc8fa1f6..9afbe249 100644
Binary files a/web/escape/audio/voice/male/guide_wrong_right.ogg and b/web/escape/audio/voice/male/guide_wrong_right.ogg differ
diff --git a/web/escape/audio/voice/male/guide_wrong_up.ogg b/web/escape/audio/voice/male/guide_wrong_up.ogg
index 3694ab17..88b96706 100644
Binary files a/web/escape/audio/voice/male/guide_wrong_up.ogg and b/web/escape/audio/voice/male/guide_wrong_up.ogg differ
diff --git a/web/escape/audio/voice/male/help_ops.ogg b/web/escape/audio/voice/male/help_ops.ogg
index ba0ca485..b1452442 100644
Binary files a/web/escape/audio/voice/male/help_ops.ogg and b/web/escape/audio/voice/male/help_ops.ogg differ
diff --git a/web/escape/audio/voice/male/inspect_box_dead.ogg b/web/escape/audio/voice/male/inspect_box_dead.ogg
index be932d51..dce7cd15 100644
Binary files a/web/escape/audio/voice/male/inspect_box_dead.ogg and b/web/escape/audio/voice/male/inspect_box_dead.ogg differ
diff --git a/web/escape/audio/voice/male/inspect_cabinet_locked.ogg b/web/escape/audio/voice/male/inspect_cabinet_locked.ogg
index 6a584fec..528f7865 100644
Binary files a/web/escape/audio/voice/male/inspect_cabinet_locked.ogg and b/web/escape/audio/voice/male/inspect_cabinet_locked.ogg differ
diff --git a/web/escape/audio/voice/male/inspect_gate.ogg b/web/escape/audio/voice/male/inspect_gate.ogg
index 26b18301..2db97401 100644
Binary files a/web/escape/audio/voice/male/inspect_gate.ogg and b/web/escape/audio/voice/male/inspect_gate.ogg differ
diff --git a/web/escape/audio/voice/male/inspect_gate_ready.ogg b/web/escape/audio/voice/male/inspect_gate_ready.ogg
index 827bbf69..1526a069 100644
Binary files a/web/escape/audio/voice/male/inspect_gate_ready.ogg and b/web/escape/audio/voice/male/inspect_gate_ready.ogg differ
diff --git a/web/escape/audio/voice/male/inv_both.ogg b/web/escape/audio/voice/male/inv_both.ogg
index 1f52c985..5cb8cddf 100644
Binary files a/web/escape/audio/voice/male/inv_both.ogg and b/web/escape/audio/voice/male/inv_both.ogg differ
diff --git a/web/escape/audio/voice/male/inv_empty.ogg b/web/escape/audio/voice/male/inv_empty.ogg
index 0829c381..49d4cdc2 100644
Binary files a/web/escape/audio/voice/male/inv_empty.ogg and b/web/escape/audio/voice/male/inv_empty.ogg differ
diff --git a/web/escape/audio/voice/male/inv_fuse.ogg b/web/escape/audio/voice/male/inv_fuse.ogg
index cd0d6286..06ad2981 100644
Binary files a/web/escape/audio/voice/male/inv_fuse.ogg and b/web/escape/audio/voice/male/inv_fuse.ogg differ
diff --git a/web/escape/audio/voice/male/inv_key.ogg b/web/escape/audio/voice/male/inv_key.ogg
index 1e009e45..9422a85c 100644
Binary files a/web/escape/audio/voice/male/inv_key.ogg and b/web/escape/audio/voice/male/inv_key.ogg differ
diff --git a/web/escape/audio/voice/male/menu_back.ogg b/web/escape/audio/voice/male/menu_back.ogg
index 6656fa68..435db607 100644
Binary files a/web/escape/audio/voice/male/menu_back.ogg and b/web/escape/audio/voice/male/menu_back.ogg differ
diff --git a/web/escape/audio/voice/male/menu_home.ogg b/web/escape/audio/voice/male/menu_home.ogg
index 91cdfbf1..823689b4 100644
Binary files a/web/escape/audio/voice/male/menu_home.ogg and b/web/escape/audio/voice/male/menu_home.ogg differ
diff --git a/web/escape/audio/voice/male/menu_open.ogg b/web/escape/audio/voice/male/menu_open.ogg
index 15a32de4..8eea57f8 100644
Binary files a/web/escape/audio/voice/male/menu_open.ogg and b/web/escape/audio/voice/male/menu_open.ogg differ
diff --git a/web/escape/audio/voice/male/menu_restart.ogg b/web/escape/audio/voice/male/menu_restart.ogg
index 39af33df..b8713bd1 100644
Binary files a/web/escape/audio/voice/male/menu_restart.ogg and b/web/escape/audio/voice/male/menu_restart.ogg differ
diff --git a/web/escape/audio/voice/male/nav_down.ogg b/web/escape/audio/voice/male/nav_down.ogg
index 3e8a331a..4b2306ac 100644
Binary files a/web/escape/audio/voice/male/nav_down.ogg and b/web/escape/audio/voice/male/nav_down.ogg differ
diff --git a/web/escape/audio/voice/male/nav_left.ogg b/web/escape/audio/voice/male/nav_left.ogg
index 7f51fcf6..61bf56a4 100644
Binary files a/web/escape/audio/voice/male/nav_left.ogg and b/web/escape/audio/voice/male/nav_left.ogg differ
diff --git a/web/escape/audio/voice/male/nav_right.ogg b/web/escape/audio/voice/male/nav_right.ogg
index 8f4c6378..f126fabe 100644
Binary files a/web/escape/audio/voice/male/nav_right.ogg and b/web/escape/audio/voice/male/nav_right.ogg differ
diff --git a/web/escape/audio/voice/male/nav_up.ogg b/web/escape/audio/voice/male/nav_up.ogg
index 91679cab..d80adae8 100644
Binary files a/web/escape/audio/voice/male/nav_up.ogg and b/web/escape/audio/voice/male/nav_up.ogg differ
diff --git a/web/escape/audio/voice/male/reopen_prompt.ogg b/web/escape/audio/voice/male/reopen_prompt.ogg
index f5fffd10..8b78016d 100644
Binary files a/web/escape/audio/voice/male/reopen_prompt.ogg and b/web/escape/audio/voice/male/reopen_prompt.ogg differ
diff --git a/web/escape/audio/voice/male/replay.ogg b/web/escape/audio/voice/male/replay.ogg
index 23707e9b..30787521 100644
Binary files a/web/escape/audio/voice/male/replay.ogg and b/web/escape/audio/voice/male/replay.ogg differ
diff --git a/web/escape/audio/voice/male/room_cabinet.ogg b/web/escape/audio/voice/male/room_cabinet.ogg
index 25d820f6..d0daee7a 100644
Binary files a/web/escape/audio/voice/male/room_cabinet.ogg and b/web/escape/audio/voice/male/room_cabinet.ogg differ
diff --git a/web/escape/audio/voice/male/room_gate.ogg b/web/escape/audio/voice/male/room_gate.ogg
index 39c196ce..c50b0dc6 100644
Binary files a/web/escape/audio/voice/male/room_gate.ogg and b/web/escape/audio/voice/male/room_gate.ogg differ
diff --git a/web/escape/audio/voice/male/room_power.ogg b/web/escape/audio/voice/male/room_power.ogg
index b66d1119..e669bb7a 100644
Binary files a/web/escape/audio/voice/male/room_power.ogg and b/web/escape/audio/voice/male/room_power.ogg differ
diff --git a/web/escape/audio/voice/male/room_storage.ogg b/web/escape/audio/voice/male/room_storage.ogg
index 5fa4c965..3bbe8aac 100644
Binary files a/web/escape/audio/voice/male/room_storage.ogg and b/web/escape/audio/voice/male/room_storage.ogg differ
diff --git a/web/escape/audio/voice/male/skip_hint.ogg b/web/escape/audio/voice/male/skip_hint.ogg
index 2c49e448..db7f4cd2 100644
Binary files a/web/escape/audio/voice/male/skip_hint.ogg and b/web/escape/audio/voice/male/skip_hint.ogg differ
diff --git a/web/escape/audio/voice/male/start_room.ogg b/web/escape/audio/voice/male/start_room.ogg
index 1640bb02..9014b533 100644
Binary files a/web/escape/audio/voice/male/start_room.ogg and b/web/escape/audio/voice/male/start_room.ogg differ
diff --git a/web/escape/audio/voice/male/stuck_ask.ogg b/web/escape/audio/voice/male/stuck_ask.ogg
index fced4ec6..82e7d110 100644
Binary files a/web/escape/audio/voice/male/stuck_ask.ogg and b/web/escape/audio/voice/male/stuck_ask.ogg differ
diff --git a/web/escape/audio/voice/male/stuck_box_1.ogg b/web/escape/audio/voice/male/stuck_box_1.ogg
index 1843c448..149788f7 100644
Binary files a/web/escape/audio/voice/male/stuck_box_1.ogg and b/web/escape/audio/voice/male/stuck_box_1.ogg differ
diff --git a/web/escape/audio/voice/male/stuck_box_2.ogg b/web/escape/audio/voice/male/stuck_box_2.ogg
index c879bc0f..ed7b3cb1 100644
Binary files a/web/escape/audio/voice/male/stuck_box_2.ogg and b/web/escape/audio/voice/male/stuck_box_2.ogg differ
diff --git a/web/escape/audio/voice/male/stuck_box_3.ogg b/web/escape/audio/voice/male/stuck_box_3.ogg
index a69e07af..4aabdc26 100644
Binary files a/web/escape/audio/voice/male/stuck_box_3.ogg and b/web/escape/audio/voice/male/stuck_box_3.ogg differ
diff --git a/web/escape/audio/voice/male/stuck_cabinet_1.ogg b/web/escape/audio/voice/male/stuck_cabinet_1.ogg
index 4f6f41e7..bcc8b363 100644
Binary files a/web/escape/audio/voice/male/stuck_cabinet_1.ogg and b/web/escape/audio/voice/male/stuck_cabinet_1.ogg differ
diff --git a/web/escape/audio/voice/male/stuck_cabinet_2.ogg b/web/escape/audio/voice/male/stuck_cabinet_2.ogg
index 6dd6b281..de99ac65 100644
Binary files a/web/escape/audio/voice/male/stuck_cabinet_2.ogg and b/web/escape/audio/voice/male/stuck_cabinet_2.ogg differ
diff --git a/web/escape/audio/voice/male/stuck_cabinet_3.ogg b/web/escape/audio/voice/male/stuck_cabinet_3.ogg
index 2b2f3259..9db7d2cc 100644
Binary files a/web/escape/audio/voice/male/stuck_cabinet_3.ogg and b/web/escape/audio/voice/male/stuck_cabinet_3.ogg differ
diff --git a/web/escape/audio/voice/male/stuck_gate_1.ogg b/web/escape/audio/voice/male/stuck_gate_1.ogg
index be8c2429..58e9f4d4 100644
Binary files a/web/escape/audio/voice/male/stuck_gate_1.ogg and b/web/escape/audio/voice/male/stuck_gate_1.ogg differ
diff --git a/web/escape/audio/voice/male/stuck_gate_2.ogg b/web/escape/audio/voice/male/stuck_gate_2.ogg
index b7553275..62dbf755 100644
Binary files a/web/escape/audio/voice/male/stuck_gate_2.ogg and b/web/escape/audio/voice/male/stuck_gate_2.ogg differ
diff --git a/web/escape/audio/voice/male/stuck_gate_3.ogg b/web/escape/audio/voice/male/stuck_gate_3.ogg
index addd99bf..e1ccaf49 100644
Binary files a/web/escape/audio/voice/male/stuck_gate_3.ogg and b/web/escape/audio/voice/male/stuck_gate_3.ogg differ
diff --git a/web/escape/audio/voice/male/stuck_key_1.ogg b/web/escape/audio/voice/male/stuck_key_1.ogg
index 8f972240..26daec20 100644
Binary files a/web/escape/audio/voice/male/stuck_key_1.ogg and b/web/escape/audio/voice/male/stuck_key_1.ogg differ
diff --git a/web/escape/audio/voice/male/stuck_key_2.ogg b/web/escape/audio/voice/male/stuck_key_2.ogg
index a5ee330b..726fa7c1 100644
Binary files a/web/escape/audio/voice/male/stuck_key_2.ogg and b/web/escape/audio/voice/male/stuck_key_2.ogg differ
diff --git a/web/escape/audio/voice/male/stuck_key_3.ogg b/web/escape/audio/voice/male/stuck_key_3.ogg
index 02f4ea04..c2862907 100644
Binary files a/web/escape/audio/voice/male/stuck_key_3.ogg and b/web/escape/audio/voice/male/stuck_key_3.ogg differ
diff --git a/web/escape/audio/voice/male/time_band1.ogg b/web/escape/audio/voice/male/time_band1.ogg
index a1c10449..1a6f7b67 100644
Binary files a/web/escape/audio/voice/male/time_band1.ogg and b/web/escape/audio/voice/male/time_band1.ogg differ
diff --git a/web/escape/audio/voice/male/time_band2.ogg b/web/escape/audio/voice/male/time_band2.ogg
index 613c783b..e9f8ff1b 100644
Binary files a/web/escape/audio/voice/male/time_band2.ogg and b/web/escape/audio/voice/male/time_band2.ogg differ
diff --git a/web/escape/audio/voice/male/time_band3.ogg b/web/escape/audio/voice/male/time_band3.ogg
index 21f4a920..dbe55931 100644
Binary files a/web/escape/audio/voice/male/time_band3.ogg and b/web/escape/audio/voice/male/time_band3.ogg differ
diff --git a/web/escape/audio/voice/male/time_band4.ogg b/web/escape/audio/voice/male/time_band4.ogg
index bd4c9a92..e6138936 100644
Binary files a/web/escape/audio/voice/male/time_band4.ogg and b/web/escape/audio/voice/male/time_band4.ogg differ
diff --git a/web/escape/audio/voice/male/unlock_cabinet.ogg b/web/escape/audio/voice/male/unlock_cabinet.ogg
index 04ca1f6f..4a4a24dc 100644
Binary files a/web/escape/audio/voice/male/unlock_cabinet.ogg and b/web/escape/audio/voice/male/unlock_cabinet.ogg differ
diff --git a/web/escape/audio/voice/male/use_fail.ogg b/web/escape/audio/voice/male/use_fail.ogg
index 57487922..e2e60203 100644
Binary files a/web/escape/audio/voice/male/use_fail.ogg and b/web/escape/audio/voice/male/use_fail.ogg differ
diff --git a/web/escape/audio/voice/male/wall.ogg b/web/escape/audio/voice/male/wall.ogg
index a2f5e071..7ceddd74 100644
Binary files a/web/escape/audio/voice/male/wall.ogg and b/web/escape/audio/voice/male/wall.ogg differ
diff --git a/web/escape/game.js b/web/escape/game.js
index 5115de79..bfa34826 100644
--- a/web/escape/game.js
+++ b/web/escape/game.js
@@ -438,7 +438,13 @@ export class EscapeGame extends Game {
this.audio.play('sfx/unlock');
this.audio.play('sfx/door_creak', { volume: 0.7 });
vibrate('success');
- this._playVoice('voice/unlock_cabinet', { skippable: false }); // 关键获得不可跳
+ // G4(round3):拾取反馈链尾接下一目标句「保险丝到手。接下来,去找电箱。」
+ // (游戏反馈层全档位,gd_economy 先例——走游戏语音链不走向导通道)——堵上
+ // P2-round2 P0「保险丝到手后目标悬空:没有新指令、没有下文」。
+ this._playVoice('voice/unlock_cabinet', {
+ skippable: false, // 关键获得不可跳
+ onComplete: () => this._playVoice('voice/gd_next_fuse'),
+ });
} else if (x === 0 && y === 0 && this.hasFuse && !this.powerOn) {
// 保险丝修电箱 -> 恢复供电(保险丝消耗)
this.powerOn = true;
diff --git a/web/harness/guide.test.mjs b/web/harness/guide.test.mjs
index 9e7421a2..f18d3a2a 100644
--- a/web/harness/guide.test.mjs
+++ b/web/harness/guide.test.mjs
@@ -23,6 +23,8 @@ const ROOT = path.resolve(path.dirname(url.fileURLToPath(import.meta.url)), '..'
const GAME_DIRS = {
StorylineGame: path.join(ROOT, 'web', 'storyline'),
SimonGame: path.join(ROOT, 'web', 'simon'),
+ RhythmGame: path.join(ROOT, 'web', 'rhythm'),
+ SpaceGame: path.join(ROOT, 'web', 'space'),
};
let currentGameDir = GAME_DIRS.StorylineGame;
@@ -53,6 +55,20 @@ globalThis.setTimeout = (cb, ms = 0) => {
return id;
};
globalThis.clearTimeout = (id) => { timers.delete(id); };
+// rhythm 的 40ms 调度泵 / space 的局内定时链依赖 interval(round3 G1/G7 用例需要)
+const intervals = new Set();
+globalThis.setInterval = (cb, ms = 0) => {
+ const id = timerSeq++;
+ const step = () => {
+ if (!intervals.has(id)) return; // 已被 clearInterval
+ cb();
+ if (intervals.has(id)) timers.set(id, { fireAt: now + Math.max(0, Number(ms) || 0), cb: step });
+ };
+ intervals.add(id);
+ timers.set(id, { fireAt: now + Math.max(0, Number(ms) || 0), cb: step });
+ return id;
+};
+globalThis.clearInterval = (id) => { intervals.delete(id); timers.delete(id); };
Object.defineProperty(globalThis, 'performance', {
value: { now: () => now }, configurable: true,
});
@@ -113,7 +129,9 @@ class MockOscillator {
}
}
class MockAudioContext {
- constructor() { this.state = 'running'; this.currentTime = 0; this.destination = {}; }
+ constructor() { this.state = 'running'; this.destination = {}; this.sampleRate = 44100; }
+ // 跟随虚拟时钟:rhythm 用 ctx.currentTime 绝对排程(round3 G1 时间窗断言的前提)
+ get currentTime() { return now / 1000; }
createGain() { return new MockGainNode(); }
createOscillator() { return new MockOscillator(); }
createDynamicsCompressor() {
@@ -123,7 +141,7 @@ class MockAudioContext {
return n;
}
createBufferSource() {
- return { buffer: null, loop: false, connect() {}, start() {}, stop() {} };
+ return { buffer: null, loop: false, playbackRate: new MockParam(), connect() {}, start() {}, stop() {} };
}
createScriptProcessor() { return { connect() {}, disconnect() {}, onaudioprocess: null }; }
decodeAudioData() { return Promise.resolve({ duration: 2.0, numberOfChannels: 1, sampleRate: 44100, getChannelData: () => new Float32Array(16) }); }
@@ -149,6 +167,8 @@ const { settings } = await import('../engine/settings.js');
const { Guide } = await import('../engine/guide.js');
const { StorylineGame } = await import('../storyline/game.js');
const { SimonGame } = await import('../simon/game.js');
+const { RhythmGame } = await import('../rhythm/game.js');
+const { SpaceGame } = await import('../space/game.js');
// guide='full':本文件验证向导层行为(既有 playtest 以 guide='off' 验证零干扰)
settings.set({ guide: 'full', voice: 'female', speed: 1.0, bgm: 1.0 });
@@ -156,10 +176,11 @@ settings.set({ guide: 'full', voice: 'female', speed: 1.0, bgm: 1.0 });
/** 组装一局:playLog + 震动/事件捕获(每个用例全新 audio+game)。 */
function makeRig(GameClass) {
currentGameDir = GAME_DIRS[GameClass.name];
+ storageData.clear(); // 用例间进度隔离(rhythm tutorialDone / simon best 等不串场)
const audio = new WebAudioEngine('audio/');
const playLog = [];
const origPlay = audio.play.bind(audio);
- audio.play = (id, opts) => { playLog.push({ id, t: now }); return origPlay(id, opts); };
+ audio.play = (id, opts) => { playLog.push({ id, t: now, opts: opts || {} }); return origPlay(id, opts); };
const game = new GameClass(audio, {});
const events = [];
game.guide.setEventHook((evt) => events.push({ ...evt, t: now }));
@@ -167,6 +188,7 @@ function makeRig(GameClass) {
return {
audio, playLog, game, events, vibBase,
vibrated: (pattern) => vibrateLog.slice(vibBase).some((p) => JSON.stringify(p) === JSON.stringify(pattern)),
+ vibratedSince: (mark, pattern) => vibrateLog.slice(mark).some((p) => JSON.stringify(p) === JSON.stringify(pattern)),
};
}
const voicePlays = (playLog, id) => playLog.filter((e) => e.id === id).length;
@@ -364,6 +386,219 @@ realLog('== ⑤ guide=off:全部 API 静默 no-op(无事件、无 gd_* 播
settings.set({ guide: 'full' });
}
+// ================================================================ ⑥ G1/G3 rhythm
+
+realLog('== ⑥ G1/G3 rhythm:gd_answer 落在首个应答窗口前整整 1 小节;菜单恢复 count-in 可感知 ==');
+{
+ const { audio, playLog, game, events } = makeRig(RhythmGame);
+ const tSec = () => now / 1000;
+ const SPB = 60 / 90; // 曲目一 90BPM
+ await audio.unlock();
+ game.start();
+ await advance(() => audio.isVoicePlaying()); // welcome 开播
+ await gesture(game, 'tap'); // 播放中单击 = 跳过 → 教学链
+ await advance(() => game.phase === 'tut');
+ await gesture(game, 'down'); // 跳过教学 → 曲目一 main
+ await advance(() => game.phase === 'main' && game._cues.length > 0);
+ assert(game._song && game._song.id === 'song1', '前提:进入曲目一 main(90BPM)');
+
+ // G1:gd_answer(曲谱定时队列直达)在首个应答窗口起点之前整整 1 小节
+ await advance(() => playLog.some((e) => e.id === 'voice/gd_answer'));
+ const ans = playLog.find((e) => e.id === 'voice/gd_answer');
+ const win0 = game._cues[0].expected; // 首个应答窗口起点(秒)
+ assert(ans.t / 1000 < win0, `G1:gd_answer(${(ans.t / 1000).toFixed(2)}s) < 首窗口起点(${win0.toFixed(2)}s)`);
+ assert(Math.abs(win0 - ans.t / 1000 - 4 * SPB) < 0.06,
+ `G1:窗口前整整 1 小节(提前 ${(win0 - ans.t / 1000).toFixed(2)}s ≈ ${(4 * SPB).toFixed(2)}s)`);
+ assert(events.some((e) => e.type === 'turn'), 'G1:turn earcon 同点发出(standard 档也发,off 静默)');
+
+ // G3:曲中开菜单 → 关菜单恢复:full 档先播 gd_count,链播完才开始 4 拍 count-in
+ await advance(() => tSec() >= game._bgmT0 + 1.5); // BGM 已起、首窗口未到
+ await gesture(game, 'down');
+ assert(game.phase === 'menu', 'G3:曲中下滑呼出菜单(无悬置 down 音符)');
+ const kicksBefore = game._sched.filter((e) => e.sfx === 'sfx/inst_kick').length;
+ await gesture(game, 'down');
+ assert(voicePlays(playLog, 'voice/gd_count') === 1, 'G3:恢复先播 gd_count(full 档)');
+ assert(audio.isVoicePlaying(), 'G3:count-in 在 gd_count 链播完之后才开始(语音串行)');
+ await advance(() => !audio.isVoicePlaying() && game._timer !== null);
+ const allKicks = game._sched.filter((e) => e.sfx === 'sfx/inst_kick').map((e) => e.time).sort((a, b) => a - b);
+ assert(allKicks.length === kicksBefore + 4, 'G3:count-in 4 记底鼓排入 _sched(sfx 层音量 1.0)');
+ const schedTimes = game._sched.map((e) => e.time);
+ assert(schedTimes.every((t, i) => i === 0 || t >= schedTimes[i - 1]), 'G3:_sched 已按时间重排(count-in 位于队头,round2 版未重排被队头阻塞的根因)');
+ const ciKicks = allKicks.slice(0, 4);
+ assert(ciKicks.every((t, i) => i === 0 || Math.abs(t - ciKicks[i - 1] - SPB) < 0.05), 'G3:底鼓按一拍间距排布');
+ const vibMark = vibrateLog.length;
+ await advance(() => tSec() >= ciKicks[3] + 0.3);
+ assert(vibrateLog.slice(vibMark).filter((p) => JSON.stringify(p) === '[8]').length >= 4,
+ 'G3:4 记 count-in 底鼓各带 beat 震(按拍点准时落)');
+ assert(game.phase === 'main', 'G3:恢复后回 main');
+
+ // G1:恢复 = 一次「进 main」:暂停前旧标记已消费 → 对恢复后的首个未判定窗口重排
+ const gdCountBefore = voicePlays(playLog, 'voice/gd_answer');
+ await advance(() => voicePlays(playLog, 'voice/gd_answer') > gdCountBefore);
+ const ans2 = playLog.filter((e) => e.id === 'voice/gd_answer').pop();
+ assert(ans2.t / 1000 < game._cues[0].expected, 'G1:恢复后的 gd_answer 仍在首个未判定窗口起点之前');
+
+ // G3:gd_count 每局恢复限 1 次(第二次恢复直接 count-in)
+ await gesture(game, 'down');
+ const cntBefore = voicePlays(playLog, 'voice/gd_count');
+ await gesture(game, 'down');
+ assert(voicePlays(playLog, 'voice/gd_count') === cntBefore, 'G3:gd_count 每局恢复限 1 次');
+ assert(game.phase === 'main', 'G3:第二次恢复不经语音直接 count-in');
+ game.stop();
+ resetTimers();
+}
+
+// ================================================================ ⑦ G2 rhythm 教学 DDA
+
+realLog('== ⑦ G2 rhythm:教学同一步连 2 失败 → 领奏降速 25% 重演 + gd_slow;做对恢复、每局封顶 ==');
+{
+ const { audio, playLog, game } = makeRig(RhythmGame);
+ const tSec = () => now / 1000;
+ const SPB = 60 / 90;
+ await audio.unlock();
+ game.start();
+ await advance(() => audio.isVoicePlaying());
+ await gesture(game, 'tap'); // 跳过 welcome
+ await advance(() => game.phase === 'tut' && game._cues.length > 0);
+ let lead = Math.min(...game._sched.filter((e) => e.sfx === 'sfx/inst_kick').map((e) => e.time));
+ assert(Math.abs(game._cues[0].expected - lead - 4 * SPB) < 0.05, '基准:T1 应答窗 = 领奏后 4 拍(正常速率)');
+
+ // 失败①:整句不出手(F2.1 归因 + 纠正重教)。用持久里程碑停表:
+ //(_tutEvaluate 会先把 _phaseEnd 置 Infinity 防重入,等「阶段末」类条件会跑飞)
+ await advance(() => game._tutFails === 1);
+ assert(game._tutFails === 1, '失败 1 次:纠正重教(原路径不变)');
+ await advance(() => game._phaseEnd < 1e9 && tSec() < game._phaseEnd - 0.5); // 纠正链播完、重新领奏
+
+ // 失败②:再整句不出手 → G2 降速重演
+ await advance(() => game._tutSlowUsed === true);
+ assert(game._tutSlowUsed === true, '同一步连续 2 次失败 → 进入降速路径');
+ await advance(() => voicePlays(playLog, 'voice/gd_slow') === 1);
+ assert(voicePlays(playLog, 'voice/gd_slow') === 1, 'G2:连 2 失败播 gd_slow(full 档)');
+ assert(game._tutRate === 0.75, 'G2:该步领奏降速 25%(_tutRate=0.75)');
+ await advance(() => game._cues.length > 0 && game._sched.some((e) => e.sfx === 'sfx/inst_kick' && e.time > tSec()));
+ lead = Math.min(...game._sched.filter((e) => e.sfx === 'sfx/inst_kick').map((e) => e.time));
+ assert(Math.abs(game._cues[0].expected - lead - 4 * SPB / 0.75) < 0.06,
+ `G2:降速后应答窗 = 领奏后 4 拍×1/0.75(实际 ${(game._cues[0].expected - lead).toFixed(2)}s)`);
+
+ // 降速步做对 → 恢复正常速度
+ await advance(() => tSec() >= game._cues[0].expected + 0.29);
+ await gesture(game, 'tap'); // tap 补偿 -0.30s 后 dt≈0,判对
+ await advance(() => game._tutIdx === 1);
+ assert(game._tutRate === 1.0, 'G2:该步做对恢复正常速度');
+
+ // 封顶:T2 再连 2 失败 → 不再降速,维持 retry_skip 跳步
+ await advance(() => game._tutIdx === 1 && game._tutFails === 1); // T2 失败 1
+ await advance(() => game._phaseEnd < 1e9 && tSec() < game._phaseEnd - 0.5 && game._tutIdx === 1);
+ await advance(() => voicePlays(playLog, 'voice/retry_skip') === 1); // T2 失败 2 → 跳步
+ assert(voicePlays(playLog, 'voice/gd_slow') === 1, 'G2:gd_slow 每教学局 1 次封顶');
+ assert(voicePlays(playLog, 'voice/retry_skip') === 1, 'G2:封顶后维持 retry_skip 跳步不卡流程');
+ await advance(() => game._tutIdx === 2);
+ assert(game._tutIdx === 2, 'G2:跳步进 T3');
+ game.stop();
+ resetTimers();
+}
+
+// ================================================================ ⑧ G5 simon 双击/上滑
+
+realLog('== ⑧ G5 simon:input 阶段双击永远=作答、上滑=主动重听(full 与 off 双档)==');
+function driveSimonToInput(rig) {
+ const { audio, game } = rig;
+ return (async () => {
+ await audio.unlock();
+ rig.game.start();
+ await advance(() => game.phase === 'tutorial' && game.teachAwait);
+ for (const g of ['up', 'down', 'left', 'right', 'tap', 'doubletap']) {
+ await advance(() => game.teachAwait && game.phase === 'tutorial');
+ await gesture(game, g);
+ }
+ await advance(() => game.phase === 'input');
+ return game;
+ })();
+}
+{
+ const rig = makeRig(SimonGame);
+ const { playLog, game } = rig;
+ await driveSimonToInput(rig);
+ assert(game.round === 1 && game.phase === 'input', '前提:教学完进第 1 轮 input');
+ assert(voicePlays(playLog, 'voice/gd_economy') === 1, 'G5:教学收尾播 gd_economy(重录新文案)');
+ // 固定期望序列(测试钩子):idx0=doubletap、idx1=left
+ game.sequence[0] = 'doubletap';
+ game.sequence[1] = 'left';
+ await gesture(game, 'doubletap');
+ assert(game.inputIdx === 1 && game.phase === 'input', 'G5:期望恰为 doubletap 时双击=作答(inputIdx 前进)');
+ const ch = game.chances;
+ const relistenN = voicePlays(playLog, 'voice/relisten');
+ await gesture(game, 'up'); // 期望非 up → 主动重听
+ assert(game.chances === ch - 1 && voicePlays(playLog, 'voice/relisten') === relistenN + 1,
+ 'G5:input 上滑=主动重听(耗机会、播 relisten)');
+ await advance(() => game.phase === 'input');
+ assert(game.inputIdx === 0, 'G5:重听后输入进度清零');
+
+ // G6:第 1 轮答完 → 轮结算链尾 gd_clear(每局 1 次)
+ await gesture(game, 'doubletap'); // 期望 doubletap → 答对
+ await gesture(game, 'left');
+ await advance(() => game.phase === 'roundend');
+ assert(voicePlays(playLog, 'voice/gd_clear') === 1, 'G6:轮成功链尾播 gd_clear(漂亮,过了)');
+ await advance(() => game.phase === 'input' && game.round === 2);
+
+ // G6:第 2 轮答完且超过预设历史纪录(钩子 best=1)→ 追加 gd_record(每局 1 次)
+ game.best = 1; // 模拟上局留下纪录(测试钩子)
+ game.sequence[0] = 'up'; // 顺带验证期望恰为 up 时上滑=作答(00 §5.3 豁免同款)
+ await gesture(game, 'up');
+ assert(game.inputIdx === 1 && game.phase === 'input', 'G5:期望恰为 up 时上滑=作答');
+ for (let i = 0; i < 8 && game.phase === 'input'; i++) await gesture(game, game.sequence[game.inputIdx]);
+ await advance(() => game.phase === 'roundend' && game.round === 2);
+ assert(voicePlays(playLog, 'voice/gd_record') === 1, 'G6:局中破个人纪录播 gd_record(破纪录了)');
+ assert(voicePlays(playLog, 'voice/gd_clear') === 1, 'G6:gd_clear 每局仅第 1 次轮成功播');
+ await advance(() => game.phase === 'input' && game.round === 3);
+
+ // 双击永远=作答的判错面:chances=0(重听已耗)时双击期望非双击 → 判错到底(gameover),不是 chances_out
+ game.sequence[0] = 'left'; // 钩子固定期望,注入 doubletap 必判错
+ await gesture(game, 'doubletap');
+ assert(game.phase === 'gameover', 'G5:input 双击永远=作答(期望非双击时判错到底,不再触发重听)');
+ game.stop();
+ resetTimers();
+}
+{
+ settings.set({ guide: 'off' });
+ const rig = makeRig(SimonGame);
+ const { game } = rig;
+ await driveSimonToInput(rig);
+ game.sequence[0] = 'doubletap';
+ game.sequence[1] = 'left';
+ await gesture(game, 'doubletap');
+ assert(game.inputIdx === 1, 'off:双击=作答同样成立(玩法映射与向导档无关)');
+ await gesture(game, 'up');
+ assert(game.chances === 0, 'off:上滑=主动重听同样成立');
+ await advance(() => game.phase === 'input');
+ await gesture(game, 'doubletap');
+ await gesture(game, 'doubletap');
+ assert(game.phase === 'gameover', 'off:双击期望非双击时判错(无重听兜底)');
+ settings.set({ guide: 'full' });
+ game.stop();
+ resetTimers();
+}
+
+// ================================================================ ⑨ G7 space 方向呼喊
+
+realLog('== ⑨ G7 space:loud 警报档(撞击前 500ms)同窗 dir_* 超短方向呼喊 ==');
+{
+ const { audio, playLog, game } = makeRig(SpaceGame);
+ await audio.unlock();
+ game.start();
+ await advance(() => game.phase === 'drill');
+ await gesture(game, 'down'); // 无悬置演练陨石:下滑跳过演练
+ await advance(() => game.phase === 'playing');
+ assert(game.phase === 'playing', '前提:跳过演练进对局');
+ await advance(() => playLog.some((e) => e.id.startsWith('voice/dir_')));
+ const shout = playLog.find((e) => e.id.startsWith('voice/dir_'));
+ const louds = playLog.filter((e) => e.id === 'sfx/alarm' && e.opts.volume === 1).map((e) => e.t);
+ assert(['left', 'right', 'up', 'down'].includes(shout.id.slice('voice/dir_'.length)), 'G7:呼喊方向合法');
+ assert(louds.some((t) => Math.abs(t - shout.t) < 60), `G7:dir_* 与 loud 警报同窗(≤50ms,实际最小 ${Math.min(...louds.map((t) => Math.abs(t - shout.t)))}ms)`);
+ game.stop();
+ resetTimers();
+}
+
// ---------------------------------------------------------------- 汇总
realLog(`\n通过 ${passCount} 条断言,失败 ${failures.length} 条`);
diff --git a/web/harness/mock.mjs b/web/harness/mock.mjs
index 0dbbb28a..3582efe3 100644
--- a/web/harness/mock.mjs
+++ b/web/harness/mock.mjs
@@ -135,9 +135,12 @@ export function installMock(gameDir) {
};
}
createScriptProcessor() { return { connect() {}, disconnect() {}, onaudioprocess: null }; }
- decodeAudioData() {
+ decodeAudioData(ab) {
+ // 时长按这块 buffer 自己的 url 估算(round3 修复:原来读 lastFetched——
+ // prewarm 与 play 并发 fetch 时 voice 会随机继承 bgm 的 90s 时长,语音
+ // 结束定时器形同虚设、链全靠兜底看门狗推进,tap 也会被"仍在播"的语音吃掉)
return Promise.resolve({
- duration: estimateDuration(gameName, lastFetched),
+ duration: estimateDuration(gameName, ab && ab.__url),
numberOfChannels: 1, sampleRate: 44100,
getChannelData: () => new Float32Array(16),
});
@@ -167,9 +170,11 @@ export function installMock(gameDir) {
}
const data = fs.readFileSync(p);
fetchedLog.push({ url: s, ok: true });
+ const ab = data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength);
+ ab.__url = s; // 供 decodeAudioData 按自身 url 估时长(见上)
return {
ok: true, status: 200,
- arrayBuffer: async () => data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength),
+ arrayBuffer: async () => ab,
};
};
diff --git a/web/harness/sessions/escape.mjs b/web/harness/sessions/escape.mjs
index f1bb756f..f4b4b213 100644
--- a/web/harness/sessions/escape.mjs
+++ b/web/harness/sessions/escape.mjs
@@ -66,7 +66,11 @@ export async function session(ctx, mock) {
await move('right', '往东走,风声换了个方向');
await move('right');
await move('down', '到了铁柜房,柜子锁着');
- await ctx.gesture('doubletap'); // 用钥匙 → unlock_cabinet(第二间解完)
- await ctx.waitVirtual(3000);
- ctx.status('柜子开了,拿到保险丝——解到第二间,收工');
+ await ctx.gesture('doubletap'); // 用钥匙 → unlock_cabinet + gd_next_fuse(round3 G4)
+ await ctx.waitVirtual(4200);
+ ctx.status('柜子开了,听到「保险丝到手。接下来,去找电箱」——目标又有了');
+ // round3 G4 剧本:拿到保险丝后再走两步(朝西边的电箱房方向),目标链不断
+ await move('left', '照新目标往西摸');
+ await move('left', '再走一步,西边隐隐有电流声——电箱在那边');
+ ctx.status('解到第二间、照下一目标句又摸了两步,收工');
}
diff --git a/web/harness/sessions/rhythm.mjs b/web/harness/sessions/rhythm.mjs
index 361a64b3..d48d1ae1 100644
--- a/web/harness/sessions/rhythm.mjs
+++ b/web/harness/sessions/rhythm.mjs
@@ -1,13 +1,16 @@
/**
- * 《节拍行者》新手会话剧本:首局完整走教学 T1-T3 → 曲目一(90 BPM);
- * 曲中下滑呼出菜单逛一圈再恢复;第一乐句故意整句漏掉(连 2 Miss 触发向导
- * 「慢了半拍」提示),之后跟着领奏把一曲打完到结算。
+ * 《节拍行者》新手会话剧本:首局完整走教学 T1-T3(第 2 句故意连错两遍,
+ * 触发 round3 G2 的「降速 25% 重演 + gd_slow」,跟着慢速领奏做对后恢复正常)
+ * → 曲目一(90 BPM);曲中下滑呼出菜单逛一圈再恢复(round3 G3:恢复先听
+ * gd_count「四拍之后,继续」,再跟 4 拍底鼓 count-in 进场;首个应答窗口前
+ * 整整 1 小节有 gd_answer+turn 交接标记);第一乐句故意整句漏掉(连 2 Miss
+ * 触发向导「慢了半拍」提示),之后跟着领奏把一曲打完到结算。
*/
export function describe(game) {
switch (game.phase) {
case 'intro': return '开场旁白在播,单击可以跳过';
case 'tut': return game._cues.length
- ? `教学:听领奏,下一小节照样打(${game._cues.map((c) => c.gesture).join('→')})`
+ ? `教学:听领奏,下一小节照样打(${game._cues.map((c) => c.gesture).join('→')})${game._tutRate < 1 ? '(领奏已放慢 25%)' : ''}`
: '教学准备中,听鼓点';
case 'select': return '选曲:左右滑换曲,单击开始,下滑回大厅';
case 'main': {
@@ -33,6 +36,26 @@ export async function session(ctx, mock) {
for (let step = 0; step < 3; step++) {
await ctx.waitCond(() => game.phase === 'tut' && game._cues.length > 0 && game._tutAttempts.length === 0);
ctx.status(`教学第 ${step + 1}/3 句`);
+ if (step === 1) {
+ // round3 G2 剧本:这一句故意连错两遍(整句不出手),听它放慢一些再带着打。
+ // 注意 _tutEvaluate 判定即把 _phaseEnd 置 Infinity 防重入——等待一律挂
+ // 「持久里程碑」条件(_tutFails/_tutSlowUsed),别挂阶段末时刻。
+ await ctx.waitCond(() => game._tutFails === 1); // 失败①:没出手
+ ctx.status('第一遍没敢出手,先听它归因');
+ await ctx.waitCond(() => game._phaseEnd < 1e8 && t() < game._phaseEnd - 1); // 纠正链播完、重新领奏
+ ctx.status('又重新领奏了一遍,还是没敢出手');
+ await ctx.waitCond(() => game._tutSlowUsed === true); // 失败② → 触发降速重演
+ await ctx.waitCond(() => game._phaseEnd < 1e8 && t() < game._phaseEnd - 1); // gd_slow 播完、慢速领奏已排
+ ctx.status('听到「我放慢一些,跟着试试」——领奏降速 25% 重演,这回跟着慢拍打');
+ for (const cue of game._cues) {
+ const at = cue.expected - (cue.gesture === 'tap' ? -0.28 : 0.04);
+ await ctx.waitCond(() => t() >= at || cue.judged);
+ if (cue.judged) continue;
+ await ctx.gesture(cue.gesture);
+ }
+ await ctx.waitCond(() => game._tutIdx > step || game.phase !== 'tut');
+ continue;
+ }
for (const cue of game._cues) {
const at = cue.expected - (cue.gesture === 'tap' ? -0.28 : 0.04); // tap 补偿引擎 ~300ms 延迟
await ctx.waitCond(() => t() >= at || cue.judged);
@@ -42,10 +65,11 @@ export async function session(ctx, mock) {
await ctx.waitCond(() => game._tutIdx > step || game.phase !== 'tut');
}
await ctx.waitCond(() => game.phase === 'main');
- ctx.status('教学完毕,曲目一《启程》90 拍开始');
+ ctx.status('教学完毕,曲目一《启程》90 拍开始。领奏响之前先听到「现在跟着我打」');
// 曲中逛菜单:下滑呼出(模态暂停)→ 听选项 → 下滑恢复
- await ctx.waitVirtual(2500);
+ //(round3 G3:恢复先播「四拍之后,继续」,再跟 4 拍底鼓 count-in 进场)
+ await ctx.waitCond(() => t() >= game._bgmT0 + 1.5);
await ctx.gesture('down');
await ctx.waitCond(() => game.phase === 'menu');
ctx.status('曲中暂停,进了菜单');
@@ -54,6 +78,7 @@ export async function session(ctx, mock) {
ctx.note('还是想打完这首,下滑回去');
await ctx.gesture('down'); // 恢复
await ctx.waitCond(() => game.phase === 'main');
+ ctx.status('听到「四拍之后,继续」,跟着四下底鼓数拍进来了');
// 第一乐句故意整句不打:连 2 次 Miss → 向导 gd_miss
const firstPhrase = game._cues.filter((c) => c.phrase === 0);
diff --git a/web/harness/sessions/simon.mjs b/web/harness/sessions/simon.mjs
index 93871df9..9fc6d46b 100644
--- a/web/harness/sessions/simon.mjs
+++ b/web/harness/sessions/simon.mjs
@@ -1,10 +1,10 @@
/**
* 《音序回响》新手会话剧本:教学六音一步一步学(中间故意做错一次听纠错)、
- * 收尾听完机会经济句(免费重听两次、用完扣机会);第 1 轮直接答对;第 2 轮开局
- * 忘序列僵住 10 秒,听到向导「双击可以重新听」提示后 5 秒内照做——用掉一次免费
- * 重听(round2:25s 升级已不再自动重播序列,坐着等答案重念的路子废了);第 3 轮
- * 凭记忆答对,在**整轮边界**收工(round2 剧本修正:不在轮中退出——round1 转写
- * 「第 4 轮报数后再没人说话」与「干晾 85 秒」都是剧本失真,不是游戏失真)。
+ * 收尾听完机会经济句(round3 G5 重录口径:记不住就向上滑重新听);第 1 轮
+ * 直接答对(途中有双击音就演示「双击=作答」);第 2 轮开局忘序列僵住 10 秒,
+ * 听到向导「向上滑可以重新听」提示后照做——用掉一次免费重听(round3 G5:
+ * input 双击永远=作答,重听改绑上滑);第 3 轮凭记忆答对,在**整轮边界**收工
+ * (round2 剧本修正:不在轮中退出)。
*/
export function describe(game) {
const GN = { up: '上滑', down: '下滑', left: '左滑', right: '右滑', tap: '单击', doubletap: '双击' };
@@ -16,7 +16,7 @@ export function describe(game) {
: '教学旁白在播,先听着';
case 'announce': return `第 ${game.round} 轮报数呢,听好了`;
case 'playback': return `第 ${game.round} 轮序列演奏中(${game.sequence.length} 个音),记住顺序,先别动手`;
- case 'input': return `第 ${game.round} 轮轮到你了:已对上 ${game.inputIdx}/${game.sequence.length},照原顺序做手势`;
+ case 'input': return `第 ${game.round} 轮轮到你了:已对上 ${game.inputIdx}/${game.sequence.length},照原顺序做手势(双击就是双击那个音,要重听就向上滑)`;
case 'roundend': return '刚答完一轮,播报中';
case 'gameover': return `游戏结束,完成 ${game.round - 1} 轮。单击再来一局,下滑开菜单`;
case 'menu': return '菜单里:单击切选项,双击确认,上滑听规则';
@@ -47,28 +47,48 @@ export async function session(ctx, mock) {
await ctx.waitIdle();
}
}
- ctx.status('教学讲完了,机会经济也交代清楚了:免费重听两次,用完要扣机会');
+ ctx.status('教学讲完了:免费重听两次、用完扣机会,想重听就向上滑');
// 正式对局:完整打完第 3 轮,在轮边界收工
let relistenDone = false;
while (mock.now < 12 * 60 * 1000 && game.phase !== 'gameover') {
if (game.phase === 'input') {
- // 第 2 轮先失忆僵住 10 秒:听向导「双击可以重新听一遍序列」,5 秒内照做。
- //(期望输入恰为双击时先答这一下,下一步再演示重听——双击语境判定)
- if (game.round === 2 && !relistenDone
- && game.inputIdx <= 1 && game.sequence[game.inputIdx] !== 'doubletap') {
+ // 第 1 轮开局先失忆僵 10 秒(还没动过手,input 看门狗在挂):听向导
+ // 「向上滑可以重新听一遍序列」,照做——round3 G5:重听已改绑上滑。
+ // 测试钩子把序列摆成无 up 的两音,保证上滑=重听不被「期望恰为 up」豁免干扰。
+ if (game.round === 1 && !relistenDone && game.inputIdx === 0) {
relistenDone = true;
- ctx.status('序列有点长,先僵一会儿');
+ if (game.sequence.includes('up')) { game.sequence[0] = 'left'; game.sequence[1] = 'tap'; }
+ ctx.status('第 1 轮有点懵,先僵一会儿');
ctx.silence(10, '想不起来序列了');
- await ctx.waitVirtual(10600); // 10s 看门狗:nudge + gd_relisten
- ctx.status('听到提示:需要的话,双击可以重新听一遍序列');
- ctx.note('照提示双击,用掉一次免费重听');
- await ctx.gesture('doubletap');
+ // 10s 看门狗到点:nudge + gd_relisten。直接等提示语音开播(input 态无
+ // BGM、无别的语音,voiceBusy=提示在播;别用「等满 10.6s」——定时刻度会
+ // 恰好迈过语音结束点,等成第二次升级)
+ await ctx.waitCond(() => ctx.voiceBusy());
+ ctx.status('听到提示:需要的话,向上滑可以重新听一遍序列');
+ ctx.note('照提示向上滑,用掉一次免费重听');
+ await ctx.gesture('up');
await ctx.waitCond(() => game.phase === 'playback' || game.phase === 'input');
continue;
}
+ // 第 2 轮开头演示「期望恰为 up 时上滑=作答」(00 §5.3 豁免同款口径)
+ if (game.round === 2 && !game.__upDemoDone && game.inputIdx === 0) {
+ game.__upDemoDone = true;
+ game.sequence[0] = 'up';
+ ctx.status('这个是上行音——上滑作答(期望恰为 up 时上滑=作答)');
+ await ctx.gesture('up');
+ continue;
+ }
if (game.round === 3 && game.inputIdx === game.sequence.length - 1) {
- ctx.status('最后一轮最后一个音,打完这轮就收');
+ // round3 G5 演示钩子(13 号文档允许直读/改实例字段):把最后一个期望音
+ // 摆成 doubletap,保证转写演示到「input 双击永远=作答」
+ if (game.sequence[game.inputIdx] !== 'doubletap' && !game.__dtDemoDone) {
+ game.__dtDemoDone = true;
+ game.sequence[game.inputIdx] = 'doubletap';
+ }
+ ctx.status(game.sequence[game.inputIdx] === 'doubletap'
+ ? '这个是双击音——双击作答(round3:input 双击永远=作答)'
+ : '最后一轮最后一个音,打完这轮就收');
} else {
ctx.status('轮到我复现了');
}
diff --git a/web/harness/sessions/space.mjs b/web/harness/sessions/space.mjs
index 10ba4151..6c7d0198 100644
--- a/web/harness/sessions/space.mjs
+++ b/web/harness/sessions/space.mjs
@@ -1,9 +1,10 @@
/**
* 《盲航》新手会话剧本:首局完整演练 D1-D4(第二颗故意超时,听当场重教)→
- * 正式对局躲过保护期(20s/45s 的加速/护盾引入都照做)→ 保护期结束后故意漏两颗
- * (第 1 次听归因+向导「同向滑动就能拨开」,第 2 次听 gd_last_life「最后一次机会」
- * ——round2 F2.2:受击经济透明)→ 之后全部躲开,保护期结束后再撑 20 秒以上收工
- * (不再像 round1 那样在保护期后 8 秒就撤,也没有第三次被撞)。
+ * 正式对局躲过保护期(20s/45s 的加速/护盾引入都照做)→ 每颗陨石都撑到 loud
+ * 警报档(撞击前 500ms:警报 + dir_* 方向呼喊同时响,round3 G7)才拨开 →
+ * 保护期结束后故意漏两颗(第 1 次听归因+向导「同向滑动就能拨开」,第 2 次听
+ * gd_last_life「最后一次机会」——round2 F2.2:受击经济透明)→ 之后全部躲开,
+ * 保护期结束后再撑 20 秒以上收工。
*/
export function describe(game) {
const DIR = { left: '左边', right: '右边', up: '上面', down: '下面' };
@@ -48,7 +49,9 @@ export async function session(ctx, mock) {
ctx.status('演练做完了,要出发了');
// 正式对局:保护期 60s + 结束后再撑 20s 以上收工。
- // 每颗陨石生成(呼啸声起)就在判定窗口将开时同向拨开——比盯着 1.5s 判定窗口更稳。
+ // 每颗陨石都撑到 loud 警报档(撞击前 500ms:第二段警报 + 「左!/右!…」方向
+ // 呼喊同时响,round3 G7)才同向拨开——仍在 1.5s 判定窗口内,稳。呼喊与警报
+ // 同一刻先落,随即滑开(=500ms 阈值恰在 loud 警报定时器触发点上)。
//(刷怪链是自驱动的定时器链——禁止裸 waitIdle,等待一律挂条件)
await ctx.waitCond(() => game.phase === 'playing');
ctx.status('出发。引擎声起来了,保护期里先练手');
@@ -75,9 +78,10 @@ export async function session(ctx, mock) {
: '被撞了。先听到方位归因,又听到「同向滑动就能拨开」');
continue;
}
- // 只在判定窗口将开未开时出手(警报第一响 = 撞击前 1s,窗口内)
+ // 撑到 loud 警报档(撞击前 0.5s,第二段警报 + dir 方向呼喊同窗)再出手
+ //(=500ms 恰在 loud 警报定时器触发点:呼喊先落,同一拍跟着滑开)
const target = [...game.obstacles].find((o) => !dodged.has(o)
- && o.impactAt - performance.now() < 1300);
+ && o.impactAt - performance.now() <= 500);
if (target) {
if (eaten < 2 && performance.now() >= game.protectionUntil) {
eaten++;
@@ -89,13 +93,14 @@ export async function session(ctx, mock) {
continue;
}
dodged.add(target);
+ ctx.note('听到第二段警报和方向呼喊,同向滑开');
await ctx.gesture(target.dir);
continue;
}
await ctx.waitCond(() => game.phase !== 'playing'
|| victims.some((v) => !game.obstacles.has(v))
- || [...game.obstacles].some((o) => !dodged.has(o) && o.impactAt - performance.now() < 1300));
+ || [...game.obstacles].some((o) => !dodged.has(o) && o.impactAt - performance.now() <= 500));
}
const aliveSec = Math.round((performance.now() - game.runStart) / 1000);
- ctx.status(`保护期结束后撑了 ${aliveSec - 60} 秒、挨了两下还活着(警报也只起一波了),先到这`);
+ ctx.status(`保护期结束后撑了 ${aliveSec - 60} 秒、挨了两下还活着;每回撞击前半秒都能听到方向呼喊,先到这`);
}
diff --git a/web/harness/voice_text.json b/web/harness/voice_text.json
index 0c99d203..5aac951b 100644
--- a/web/harness/voice_text.json
+++ b/web/harness/voice_text.json
@@ -129,7 +129,8 @@
"menu_restart": "重新开始。",
"menu_home": "回大厅。",
"menu_back": "返回游戏。",
- "skip_hint": "单击可跳过旁白。"
+ "skip_hint": "单击可跳过旁白。",
+ "gd_next_fuse": "保险丝到手。接下来,去找电箱。"
},
"simon": {
"t0_welcome": "欢迎来到音序回响。先认识六种声音。",
@@ -155,7 +156,7 @@
"t_blunt_tap": "用指尖,轻轻点一下屏幕。",
"t_blunt_double": "用指尖,快速点两下屏幕。",
"t7_ready": "六种声音都记住了。后面的序列,会越来越长。",
- "t7_retry": "答错可以消耗机会重听。双击,可以随时重听。",
+ "t7_retry": "答错可以消耗机会重听。向上滑,可以随时重听。",
"t_skip": "跳过教学,直接开始。",
"round_01": "第一轮,听好了。",
"round_02": "第二轮,听好了。",
@@ -201,8 +202,10 @@
"menu_home": "回大厅。",
"menu_back": "返回游戏。",
"skip_hint": "单击可跳过旁白。",
- "gd_relisten": "需要的话,双击可以重新听一遍序列。",
- "gd_economy": "记不住就双击重新听,免费机会有两次,用完要扣一次机会。"
+ "gd_relisten": "需要的话,向上滑可以重新听一遍序列。",
+ "gd_economy": "记不住就向上滑,重新听一遍。免费机会有两次,用完要扣一次机会。",
+ "gd_clear": "漂亮,过了。",
+ "gd_record": "破纪录了。"
},
"rhythm": {
"welcome": "欢迎来到节拍行者。跟着音乐,我奏一句,你跟一句。",
@@ -241,7 +244,9 @@
"gd_miss": "慢了半拍,下一小节跟上我就行。",
"gd_miss_early": "抢拍了。等声音落下再滑。",
"gd_miss_late": "慢了半拍。跟着节拍走。",
- "gd_miss_wrong": "方向不对。跟着音色滑。"
+ "gd_miss_wrong": "方向不对。跟着音色滑。",
+ "gd_slow": "我放慢一些,跟着试试。",
+ "gd_count": "四拍之后,继续。"
},
"space": {
"drill_welcome": "欢迎登上盲航。你只有一双耳朵。",
@@ -298,7 +303,11 @@
"paused": "已暂停。",
"skip_hint": "单击可跳过旁白。",
"gd_hit_hint": "被撞了。听方位,同向滑动就能拨开。",
- "gd_last_life": "这是最后一次机会,撑住。"
+ "gd_last_life": "这是最后一次机会,撑住。",
+ "dir_left": "左!",
+ "dir_right": "右!",
+ "dir_up": "上!",
+ "dir_down": "下!"
},
"rpg": {
"intro_1": "你的眼睛看不见了。但你的耳朵,比谁都灵。",
diff --git a/web/rhythm/audio/voice/female/gd_answer.ogg b/web/rhythm/audio/voice/female/gd_answer.ogg
index 54cf7c78..3ff19bb7 100644
Binary files a/web/rhythm/audio/voice/female/gd_answer.ogg and b/web/rhythm/audio/voice/female/gd_answer.ogg differ
diff --git a/web/rhythm/audio/voice/female/gd_count.m4a b/web/rhythm/audio/voice/female/gd_count.m4a
new file mode 100644
index 00000000..967657de
Binary files /dev/null and b/web/rhythm/audio/voice/female/gd_count.m4a differ
diff --git a/web/rhythm/audio/voice/female/gd_count.ogg b/web/rhythm/audio/voice/female/gd_count.ogg
new file mode 100644
index 00000000..74cdf7df
Binary files /dev/null and b/web/rhythm/audio/voice/female/gd_count.ogg differ
diff --git a/web/rhythm/audio/voice/female/gd_miss.ogg b/web/rhythm/audio/voice/female/gd_miss.ogg
index 7088ded8..20b9aee4 100644
Binary files a/web/rhythm/audio/voice/female/gd_miss.ogg and b/web/rhythm/audio/voice/female/gd_miss.ogg differ
diff --git a/web/rhythm/audio/voice/female/gd_miss_early.ogg b/web/rhythm/audio/voice/female/gd_miss_early.ogg
index a5678913..3cde7f70 100644
Binary files a/web/rhythm/audio/voice/female/gd_miss_early.ogg and b/web/rhythm/audio/voice/female/gd_miss_early.ogg differ
diff --git a/web/rhythm/audio/voice/female/gd_miss_late.ogg b/web/rhythm/audio/voice/female/gd_miss_late.ogg
index 23670137..41caf75e 100644
Binary files a/web/rhythm/audio/voice/female/gd_miss_late.ogg and b/web/rhythm/audio/voice/female/gd_miss_late.ogg differ
diff --git a/web/rhythm/audio/voice/female/gd_miss_wrong.ogg b/web/rhythm/audio/voice/female/gd_miss_wrong.ogg
index ada22fea..41bcec64 100644
Binary files a/web/rhythm/audio/voice/female/gd_miss_wrong.ogg and b/web/rhythm/audio/voice/female/gd_miss_wrong.ogg differ
diff --git a/web/rhythm/audio/voice/female/gd_slow.m4a b/web/rhythm/audio/voice/female/gd_slow.m4a
new file mode 100644
index 00000000..c458a560
Binary files /dev/null and b/web/rhythm/audio/voice/female/gd_slow.m4a differ
diff --git a/web/rhythm/audio/voice/female/gd_slow.ogg b/web/rhythm/audio/voice/female/gd_slow.ogg
new file mode 100644
index 00000000..2c1d21b6
Binary files /dev/null and b/web/rhythm/audio/voice/female/gd_slow.ogg differ
diff --git a/web/rhythm/audio/voice/female/grade_a.ogg b/web/rhythm/audio/voice/female/grade_a.ogg
index ab62e5a9..16870f64 100644
Binary files a/web/rhythm/audio/voice/female/grade_a.ogg and b/web/rhythm/audio/voice/female/grade_a.ogg differ
diff --git a/web/rhythm/audio/voice/female/grade_b.ogg b/web/rhythm/audio/voice/female/grade_b.ogg
index e1ca00e8..a3991f4c 100644
Binary files a/web/rhythm/audio/voice/female/grade_b.ogg and b/web/rhythm/audio/voice/female/grade_b.ogg differ
diff --git a/web/rhythm/audio/voice/female/grade_c.ogg b/web/rhythm/audio/voice/female/grade_c.ogg
index 73042093..b7e99563 100644
Binary files a/web/rhythm/audio/voice/female/grade_c.ogg and b/web/rhythm/audio/voice/female/grade_c.ogg differ
diff --git a/web/rhythm/audio/voice/female/grade_s.ogg b/web/rhythm/audio/voice/female/grade_s.ogg
index ca82729a..98481fc3 100644
Binary files a/web/rhythm/audio/voice/female/grade_s.ogg and b/web/rhythm/audio/voice/female/grade_s.ogg differ
diff --git a/web/rhythm/audio/voice/female/menu_lobby.ogg b/web/rhythm/audio/voice/female/menu_lobby.ogg
index ab937a9d..e417f21e 100644
Binary files a/web/rhythm/audio/voice/female/menu_lobby.ogg and b/web/rhythm/audio/voice/female/menu_lobby.ogg differ
diff --git a/web/rhythm/audio/voice/female/menu_main.ogg b/web/rhythm/audio/voice/female/menu_main.ogg
index 11f3a76c..a8a6dcc8 100644
Binary files a/web/rhythm/audio/voice/female/menu_main.ogg and b/web/rhythm/audio/voice/female/menu_main.ogg differ
diff --git a/web/rhythm/audio/voice/female/menu_resume.ogg b/web/rhythm/audio/voice/female/menu_resume.ogg
index 5956079b..89d9e484 100644
Binary files a/web/rhythm/audio/voice/female/menu_resume.ogg and b/web/rhythm/audio/voice/female/menu_resume.ogg differ
diff --git a/web/rhythm/audio/voice/female/mid_song.ogg b/web/rhythm/audio/voice/female/mid_song.ogg
index fd306797..788c843b 100644
Binary files a/web/rhythm/audio/voice/female/mid_song.ogg and b/web/rhythm/audio/voice/female/mid_song.ogg differ
diff --git a/web/rhythm/audio/voice/female/new_best_combo.ogg b/web/rhythm/audio/voice/female/new_best_combo.ogg
index b23d0068..bf378a82 100644
Binary files a/web/rhythm/audio/voice/female/new_best_combo.ogg and b/web/rhythm/audio/voice/female/new_best_combo.ogg differ
diff --git a/web/rhythm/audio/voice/female/restart.ogg b/web/rhythm/audio/voice/female/restart.ogg
index 51869350..71edbf0f 100644
Binary files a/web/rhythm/audio/voice/female/restart.ogg and b/web/rhythm/audio/voice/female/restart.ogg differ
diff --git a/web/rhythm/audio/voice/female/retry_early.ogg b/web/rhythm/audio/voice/female/retry_early.ogg
index 24f61b10..18e11d75 100644
Binary files a/web/rhythm/audio/voice/female/retry_early.ogg and b/web/rhythm/audio/voice/female/retry_early.ogg differ
diff --git a/web/rhythm/audio/voice/female/retry_gesture.ogg b/web/rhythm/audio/voice/female/retry_gesture.ogg
index 6ab4308b..0a20dd98 100644
Binary files a/web/rhythm/audio/voice/female/retry_gesture.ogg and b/web/rhythm/audio/voice/female/retry_gesture.ogg differ
diff --git a/web/rhythm/audio/voice/female/retry_late.ogg b/web/rhythm/audio/voice/female/retry_late.ogg
index b8fe1b6b..fb3cb96e 100644
Binary files a/web/rhythm/audio/voice/female/retry_late.ogg and b/web/rhythm/audio/voice/female/retry_late.ogg differ
diff --git a/web/rhythm/audio/voice/female/retry_listen.ogg b/web/rhythm/audio/voice/female/retry_listen.ogg
index 01bd0be8..02143167 100644
Binary files a/web/rhythm/audio/voice/female/retry_listen.ogg and b/web/rhythm/audio/voice/female/retry_listen.ogg differ
diff --git a/web/rhythm/audio/voice/female/retry_skip.ogg b/web/rhythm/audio/voice/female/retry_skip.ogg
index 7e81d586..8b846e56 100644
Binary files a/web/rhythm/audio/voice/female/retry_skip.ogg and b/web/rhythm/audio/voice/female/retry_skip.ogg differ
diff --git a/web/rhythm/audio/voice/female/rules.ogg b/web/rhythm/audio/voice/female/rules.ogg
index ce34e482..e2c9fd9a 100644
Binary files a/web/rhythm/audio/voice/female/rules.ogg and b/web/rhythm/audio/voice/female/rules.ogg differ
diff --git a/web/rhythm/audio/voice/female/select_hint.ogg b/web/rhythm/audio/voice/female/select_hint.ogg
index 81bacab7..ebd7808b 100644
Binary files a/web/rhythm/audio/voice/female/select_hint.ogg and b/web/rhythm/audio/voice/female/select_hint.ogg differ
diff --git a/web/rhythm/audio/voice/female/settings_hint.ogg b/web/rhythm/audio/voice/female/settings_hint.ogg
index 45338c6d..638cd593 100644
Binary files a/web/rhythm/audio/voice/female/settings_hint.ogg and b/web/rhythm/audio/voice/female/settings_hint.ogg differ
diff --git a/web/rhythm/audio/voice/female/skip_hint.ogg b/web/rhythm/audio/voice/female/skip_hint.ogg
index 1593fa46..10319632 100644
Binary files a/web/rhythm/audio/voice/female/skip_hint.ogg and b/web/rhythm/audio/voice/female/skip_hint.ogg differ
diff --git a/web/rhythm/audio/voice/female/song1_name.ogg b/web/rhythm/audio/voice/female/song1_name.ogg
index 0c97ae19..69650cbb 100644
Binary files a/web/rhythm/audio/voice/female/song1_name.ogg and b/web/rhythm/audio/voice/female/song1_name.ogg differ
diff --git a/web/rhythm/audio/voice/female/song2_name.ogg b/web/rhythm/audio/voice/female/song2_name.ogg
index af361943..4c04350f 100644
Binary files a/web/rhythm/audio/voice/female/song2_name.ogg and b/web/rhythm/audio/voice/female/song2_name.ogg differ
diff --git a/web/rhythm/audio/voice/female/song3_name.ogg b/web/rhythm/audio/voice/female/song3_name.ogg
index a0370148..07ab57f0 100644
Binary files a/web/rhythm/audio/voice/female/song3_name.ogg and b/web/rhythm/audio/voice/female/song3_name.ogg differ
diff --git a/web/rhythm/audio/voice/female/song_locked.ogg b/web/rhythm/audio/voice/female/song_locked.ogg
index 0183d2d3..1b958238 100644
Binary files a/web/rhythm/audio/voice/female/song_locked.ogg and b/web/rhythm/audio/voice/female/song_locked.ogg differ
diff --git a/web/rhythm/audio/voice/female/tut_1.ogg b/web/rhythm/audio/voice/female/tut_1.ogg
index 85ffe52b..2ccda92f 100644
Binary files a/web/rhythm/audio/voice/female/tut_1.ogg and b/web/rhythm/audio/voice/female/tut_1.ogg differ
diff --git a/web/rhythm/audio/voice/female/tut_2.ogg b/web/rhythm/audio/voice/female/tut_2.ogg
index 6626e3fe..5ea6d50d 100644
Binary files a/web/rhythm/audio/voice/female/tut_2.ogg and b/web/rhythm/audio/voice/female/tut_2.ogg differ
diff --git a/web/rhythm/audio/voice/female/tut_3.ogg b/web/rhythm/audio/voice/female/tut_3.ogg
index eb11d243..33942add 100644
Binary files a/web/rhythm/audio/voice/female/tut_3.ogg and b/web/rhythm/audio/voice/female/tut_3.ogg differ
diff --git a/web/rhythm/audio/voice/female/tut_done.ogg b/web/rhythm/audio/voice/female/tut_done.ogg
index 854b4adc..9314d5ea 100644
Binary files a/web/rhythm/audio/voice/female/tut_done.ogg and b/web/rhythm/audio/voice/female/tut_done.ogg differ
diff --git a/web/rhythm/audio/voice/female/tut_skip.ogg b/web/rhythm/audio/voice/female/tut_skip.ogg
index d99131ab..f8ba89d5 100644
Binary files a/web/rhythm/audio/voice/female/tut_skip.ogg and b/web/rhythm/audio/voice/female/tut_skip.ogg differ
diff --git a/web/rhythm/audio/voice/female/unlock_song2.ogg b/web/rhythm/audio/voice/female/unlock_song2.ogg
index 592e7dfb..c87ff460 100644
Binary files a/web/rhythm/audio/voice/female/unlock_song2.ogg and b/web/rhythm/audio/voice/female/unlock_song2.ogg differ
diff --git a/web/rhythm/audio/voice/female/unlock_song3.ogg b/web/rhythm/audio/voice/female/unlock_song3.ogg
index 3e16048f..c210cb71 100644
Binary files a/web/rhythm/audio/voice/female/unlock_song3.ogg and b/web/rhythm/audio/voice/female/unlock_song3.ogg differ
diff --git a/web/rhythm/audio/voice/female/welcome.ogg b/web/rhythm/audio/voice/female/welcome.ogg
index 825570a1..274c0c24 100644
Binary files a/web/rhythm/audio/voice/female/welcome.ogg and b/web/rhythm/audio/voice/female/welcome.ogg differ
diff --git a/web/rhythm/audio/voice/female/welcome_back.ogg b/web/rhythm/audio/voice/female/welcome_back.ogg
index bdab9883..3b7f009c 100644
Binary files a/web/rhythm/audio/voice/female/welcome_back.ogg and b/web/rhythm/audio/voice/female/welcome_back.ogg differ
diff --git a/web/rhythm/audio/voice/male/gd_answer.ogg b/web/rhythm/audio/voice/male/gd_answer.ogg
index 106a1050..5ec1ddbf 100644
Binary files a/web/rhythm/audio/voice/male/gd_answer.ogg and b/web/rhythm/audio/voice/male/gd_answer.ogg differ
diff --git a/web/rhythm/audio/voice/male/gd_count.m4a b/web/rhythm/audio/voice/male/gd_count.m4a
new file mode 100644
index 00000000..0dda9616
Binary files /dev/null and b/web/rhythm/audio/voice/male/gd_count.m4a differ
diff --git a/web/rhythm/audio/voice/male/gd_count.ogg b/web/rhythm/audio/voice/male/gd_count.ogg
new file mode 100644
index 00000000..d3906913
Binary files /dev/null and b/web/rhythm/audio/voice/male/gd_count.ogg differ
diff --git a/web/rhythm/audio/voice/male/gd_miss.ogg b/web/rhythm/audio/voice/male/gd_miss.ogg
index 4920033d..e732e7bd 100644
Binary files a/web/rhythm/audio/voice/male/gd_miss.ogg and b/web/rhythm/audio/voice/male/gd_miss.ogg differ
diff --git a/web/rhythm/audio/voice/male/gd_miss_early.ogg b/web/rhythm/audio/voice/male/gd_miss_early.ogg
index 03c6c473..27dbf890 100644
Binary files a/web/rhythm/audio/voice/male/gd_miss_early.ogg and b/web/rhythm/audio/voice/male/gd_miss_early.ogg differ
diff --git a/web/rhythm/audio/voice/male/gd_miss_late.ogg b/web/rhythm/audio/voice/male/gd_miss_late.ogg
index 830b08ae..b5b117ae 100644
Binary files a/web/rhythm/audio/voice/male/gd_miss_late.ogg and b/web/rhythm/audio/voice/male/gd_miss_late.ogg differ
diff --git a/web/rhythm/audio/voice/male/gd_miss_wrong.ogg b/web/rhythm/audio/voice/male/gd_miss_wrong.ogg
index 77bab56f..0a2ef29c 100644
Binary files a/web/rhythm/audio/voice/male/gd_miss_wrong.ogg and b/web/rhythm/audio/voice/male/gd_miss_wrong.ogg differ
diff --git a/web/rhythm/audio/voice/male/gd_slow.m4a b/web/rhythm/audio/voice/male/gd_slow.m4a
new file mode 100644
index 00000000..fae8e566
Binary files /dev/null and b/web/rhythm/audio/voice/male/gd_slow.m4a differ
diff --git a/web/rhythm/audio/voice/male/gd_slow.ogg b/web/rhythm/audio/voice/male/gd_slow.ogg
new file mode 100644
index 00000000..81aee20f
Binary files /dev/null and b/web/rhythm/audio/voice/male/gd_slow.ogg differ
diff --git a/web/rhythm/audio/voice/male/grade_a.ogg b/web/rhythm/audio/voice/male/grade_a.ogg
index 49fec51d..755e7990 100644
Binary files a/web/rhythm/audio/voice/male/grade_a.ogg and b/web/rhythm/audio/voice/male/grade_a.ogg differ
diff --git a/web/rhythm/audio/voice/male/grade_b.ogg b/web/rhythm/audio/voice/male/grade_b.ogg
index 52b0035f..1f51a6cf 100644
Binary files a/web/rhythm/audio/voice/male/grade_b.ogg and b/web/rhythm/audio/voice/male/grade_b.ogg differ
diff --git a/web/rhythm/audio/voice/male/grade_c.ogg b/web/rhythm/audio/voice/male/grade_c.ogg
index 52b94b44..6358f27d 100644
Binary files a/web/rhythm/audio/voice/male/grade_c.ogg and b/web/rhythm/audio/voice/male/grade_c.ogg differ
diff --git a/web/rhythm/audio/voice/male/grade_s.ogg b/web/rhythm/audio/voice/male/grade_s.ogg
index 48421749..87c71f27 100644
Binary files a/web/rhythm/audio/voice/male/grade_s.ogg and b/web/rhythm/audio/voice/male/grade_s.ogg differ
diff --git a/web/rhythm/audio/voice/male/menu_lobby.ogg b/web/rhythm/audio/voice/male/menu_lobby.ogg
index 96d66510..701a0eda 100644
Binary files a/web/rhythm/audio/voice/male/menu_lobby.ogg and b/web/rhythm/audio/voice/male/menu_lobby.ogg differ
diff --git a/web/rhythm/audio/voice/male/menu_main.ogg b/web/rhythm/audio/voice/male/menu_main.ogg
index 8c2054c2..438138d0 100644
Binary files a/web/rhythm/audio/voice/male/menu_main.ogg and b/web/rhythm/audio/voice/male/menu_main.ogg differ
diff --git a/web/rhythm/audio/voice/male/menu_resume.ogg b/web/rhythm/audio/voice/male/menu_resume.ogg
index 296c4651..d9ed7930 100644
Binary files a/web/rhythm/audio/voice/male/menu_resume.ogg and b/web/rhythm/audio/voice/male/menu_resume.ogg differ
diff --git a/web/rhythm/audio/voice/male/mid_song.ogg b/web/rhythm/audio/voice/male/mid_song.ogg
index bef065ff..bb3c3d2b 100644
Binary files a/web/rhythm/audio/voice/male/mid_song.ogg and b/web/rhythm/audio/voice/male/mid_song.ogg differ
diff --git a/web/rhythm/audio/voice/male/new_best_combo.ogg b/web/rhythm/audio/voice/male/new_best_combo.ogg
index a280fb70..00f25a36 100644
Binary files a/web/rhythm/audio/voice/male/new_best_combo.ogg and b/web/rhythm/audio/voice/male/new_best_combo.ogg differ
diff --git a/web/rhythm/audio/voice/male/restart.ogg b/web/rhythm/audio/voice/male/restart.ogg
index b5b1bc1f..18445bd7 100644
Binary files a/web/rhythm/audio/voice/male/restart.ogg and b/web/rhythm/audio/voice/male/restart.ogg differ
diff --git a/web/rhythm/audio/voice/male/retry_early.ogg b/web/rhythm/audio/voice/male/retry_early.ogg
index 5391328a..43127b18 100644
Binary files a/web/rhythm/audio/voice/male/retry_early.ogg and b/web/rhythm/audio/voice/male/retry_early.ogg differ
diff --git a/web/rhythm/audio/voice/male/retry_gesture.ogg b/web/rhythm/audio/voice/male/retry_gesture.ogg
index a5076f68..4566341c 100644
Binary files a/web/rhythm/audio/voice/male/retry_gesture.ogg and b/web/rhythm/audio/voice/male/retry_gesture.ogg differ
diff --git a/web/rhythm/audio/voice/male/retry_late.ogg b/web/rhythm/audio/voice/male/retry_late.ogg
index 9fc04bb2..87466c37 100644
Binary files a/web/rhythm/audio/voice/male/retry_late.ogg and b/web/rhythm/audio/voice/male/retry_late.ogg differ
diff --git a/web/rhythm/audio/voice/male/retry_listen.ogg b/web/rhythm/audio/voice/male/retry_listen.ogg
index 755cb5e2..2b11865e 100644
Binary files a/web/rhythm/audio/voice/male/retry_listen.ogg and b/web/rhythm/audio/voice/male/retry_listen.ogg differ
diff --git a/web/rhythm/audio/voice/male/retry_skip.ogg b/web/rhythm/audio/voice/male/retry_skip.ogg
index b494fc52..87736d99 100644
Binary files a/web/rhythm/audio/voice/male/retry_skip.ogg and b/web/rhythm/audio/voice/male/retry_skip.ogg differ
diff --git a/web/rhythm/audio/voice/male/rules.ogg b/web/rhythm/audio/voice/male/rules.ogg
index 3cc74346..15de1e18 100644
Binary files a/web/rhythm/audio/voice/male/rules.ogg and b/web/rhythm/audio/voice/male/rules.ogg differ
diff --git a/web/rhythm/audio/voice/male/select_hint.ogg b/web/rhythm/audio/voice/male/select_hint.ogg
index 69afb7ea..d01c8594 100644
Binary files a/web/rhythm/audio/voice/male/select_hint.ogg and b/web/rhythm/audio/voice/male/select_hint.ogg differ
diff --git a/web/rhythm/audio/voice/male/settings_hint.ogg b/web/rhythm/audio/voice/male/settings_hint.ogg
index 23ffed3f..9eb0c70b 100644
Binary files a/web/rhythm/audio/voice/male/settings_hint.ogg and b/web/rhythm/audio/voice/male/settings_hint.ogg differ
diff --git a/web/rhythm/audio/voice/male/skip_hint.ogg b/web/rhythm/audio/voice/male/skip_hint.ogg
index 453d6edb..84b4f847 100644
Binary files a/web/rhythm/audio/voice/male/skip_hint.ogg and b/web/rhythm/audio/voice/male/skip_hint.ogg differ
diff --git a/web/rhythm/audio/voice/male/song1_name.ogg b/web/rhythm/audio/voice/male/song1_name.ogg
index 2c75d33d..02967ed6 100644
Binary files a/web/rhythm/audio/voice/male/song1_name.ogg and b/web/rhythm/audio/voice/male/song1_name.ogg differ
diff --git a/web/rhythm/audio/voice/male/song2_name.ogg b/web/rhythm/audio/voice/male/song2_name.ogg
index cc0edc81..5f404054 100644
Binary files a/web/rhythm/audio/voice/male/song2_name.ogg and b/web/rhythm/audio/voice/male/song2_name.ogg differ
diff --git a/web/rhythm/audio/voice/male/song3_name.ogg b/web/rhythm/audio/voice/male/song3_name.ogg
index 434d1dda..7100b68c 100644
Binary files a/web/rhythm/audio/voice/male/song3_name.ogg and b/web/rhythm/audio/voice/male/song3_name.ogg differ
diff --git a/web/rhythm/audio/voice/male/song_locked.ogg b/web/rhythm/audio/voice/male/song_locked.ogg
index 8c3bf39d..f01ccb41 100644
Binary files a/web/rhythm/audio/voice/male/song_locked.ogg and b/web/rhythm/audio/voice/male/song_locked.ogg differ
diff --git a/web/rhythm/audio/voice/male/tut_1.ogg b/web/rhythm/audio/voice/male/tut_1.ogg
index 2d6d55ca..b5cb3740 100644
Binary files a/web/rhythm/audio/voice/male/tut_1.ogg and b/web/rhythm/audio/voice/male/tut_1.ogg differ
diff --git a/web/rhythm/audio/voice/male/tut_2.ogg b/web/rhythm/audio/voice/male/tut_2.ogg
index 9e3cb2ca..9413b731 100644
Binary files a/web/rhythm/audio/voice/male/tut_2.ogg and b/web/rhythm/audio/voice/male/tut_2.ogg differ
diff --git a/web/rhythm/audio/voice/male/tut_3.ogg b/web/rhythm/audio/voice/male/tut_3.ogg
index eae12816..709e7cf3 100644
Binary files a/web/rhythm/audio/voice/male/tut_3.ogg and b/web/rhythm/audio/voice/male/tut_3.ogg differ
diff --git a/web/rhythm/audio/voice/male/tut_done.ogg b/web/rhythm/audio/voice/male/tut_done.ogg
index fbfb1c91..8c8a2816 100644
Binary files a/web/rhythm/audio/voice/male/tut_done.ogg and b/web/rhythm/audio/voice/male/tut_done.ogg differ
diff --git a/web/rhythm/audio/voice/male/tut_skip.ogg b/web/rhythm/audio/voice/male/tut_skip.ogg
index 34c76a88..f7f0c4c3 100644
Binary files a/web/rhythm/audio/voice/male/tut_skip.ogg and b/web/rhythm/audio/voice/male/tut_skip.ogg differ
diff --git a/web/rhythm/audio/voice/male/unlock_song2.ogg b/web/rhythm/audio/voice/male/unlock_song2.ogg
index b9bde096..c6ed5bb1 100644
Binary files a/web/rhythm/audio/voice/male/unlock_song2.ogg and b/web/rhythm/audio/voice/male/unlock_song2.ogg differ
diff --git a/web/rhythm/audio/voice/male/unlock_song3.ogg b/web/rhythm/audio/voice/male/unlock_song3.ogg
index 8befb271..6cd7d96d 100644
Binary files a/web/rhythm/audio/voice/male/unlock_song3.ogg and b/web/rhythm/audio/voice/male/unlock_song3.ogg differ
diff --git a/web/rhythm/audio/voice/male/welcome.ogg b/web/rhythm/audio/voice/male/welcome.ogg
index c3c52224..b4dda543 100644
Binary files a/web/rhythm/audio/voice/male/welcome.ogg and b/web/rhythm/audio/voice/male/welcome.ogg differ
diff --git a/web/rhythm/audio/voice/male/welcome_back.ogg b/web/rhythm/audio/voice/male/welcome_back.ogg
index 36057ad9..38527a84 100644
Binary files a/web/rhythm/audio/voice/male/welcome_back.ogg and b/web/rhythm/audio/voice/male/welcome_back.ogg differ
diff --git a/web/rhythm/game.js b/web/rhythm/game.js
index c4b2de43..652a5f33 100644
--- a/web/rhythm/game.js
+++ b/web/rhythm/game.js
@@ -35,13 +35,18 @@
* main 演奏阶段单击是演奏手势不跳(mid_song 短句按裁定不跳)。
* 长按快进豁免(12 文档 §2.2:main 演奏期):audio.setRateBoostEnabled(false)
* per-game 开关(引擎已支持),进 main 关、进菜单/结算/退出恢复。
- * 向导层(docs/design/14-guide-layer.md + round2 synthesis F2.1/F3):每曲首次
- * 领奏→应答切换在谱面定时队列直接落 gd_answer(不走 guide queue,保证窗口前
- * 听到)+ turn earcon;教学 Miss 首次即归因分档(gd_miss_early/late/wrong,
- * 挂纠正链尾空闲点);连续 2 Miss 播 gd_miss(queue 插播,同曲一次);暂停
- * 断点续播前插 4 拍 count-in(off 档保持即时续播);结算链换 _speakGuarded
- * (资产缺失不卡结算 BGM);状态签名 earcon 与状态 BGM 同点
- * (select=menu、main=battle、end=settle)。
+ * 向导层(docs/design/14-guide-layer.md + round2 synthesis F2.1/F3 + round3 G1~G3):
+ * 每曲首次领奏→应答切换在谱面定时队列直接落 gd_answer(不走 guide queue,保证
+ * 窗口前听到)+ turn earcon;round3 G1 修正排程点:落在首个应答窗口**前整整
+ * 1 小节**(= 领奏小节头;round2 排在窗口起点本身,P4 实测窗口开了才听到),
+ * 菜单恢复对下一个未判定窗口重排同款标记;教学 Miss 首次即归因分档
+ * (gd_miss_early/late/wrong,挂纠正链尾空闲点);连续 2 Miss 播 gd_miss(queue
+ * 插播,同曲一次);暂停断点续播前插 4 拍 count-in(round3 G3:底鼓 sfx 层可辨
+ * 音量 + full 档 gd_count 每局恢复限 1 次 + beat 震;round2 版因 push 后未重排
+ * _sched 被队头卡死从未按时响过;off 档保持即时续播);教学 DDA(round3 G2):
+ * 同一步连 2 次失败该步领奏降速 25% 重演并播 gd_slow(full 档、每教学局 1 次,
+ * off 档维持 retry_skip 原路径);结算链换 _speakGuarded(资产缺失不卡结算 BGM);
+ * 状态签名 earcon 与状态 BGM 同点(select=menu、main=battle、end=settle)。
*/
import { Game } from '../engine/game.js';
import { Guide } from '../engine/guide.js';
@@ -159,10 +164,15 @@ export class RhythmGame extends Game {
this._tutIdx = 0;
this._tutFails = 0;
this._tutAttempts = [];
+ this._tutRate = 1.0; // G2:教学领奏速率(0.75 = 降速 25%,做对/离开该步恢复 1.0)
+ this._tutSlowUsed = false; // G2:降速重演每教学局 1 次封顶
// 菜单/暂停状态
this._menuIdx = 0;
this._pauseAt = 0;
this._bgmOffset = 0;
+ this._resumeSeq = 0; // G3:恢复令牌(count-in 语音期间再开菜单时作废旧恢复)
+ this._gdCountUsed = false; // G3:gd_count 每局(曲)恢复限 1 次
+ this._answerArmed = false; // G1:gd_answer+turn 交接标记是否已在 _timed 里待响
this._consecMiss = 0; // 连续 Miss 计数(向导 gd_miss:连 2 次提示一次)
}
@@ -173,6 +183,9 @@ export class RhythmGame extends Game {
'voice/tut_1', 'voice/select_hint', 'bgm/menu', ...SONGS.map((s) => s.bgm)]);
const rid = ++this._runId;
this._cleanup();
+ this._tutRate = 1.0;
+ this._tutSlowUsed = false; // G2:每教学局重新封顶
+ this._gdCountUsed = false; // G3:每局(曲)恢复限 1 次
if (this._progress.tutorialDone) {
// 二周目起:缩减开场 → 选曲
this.phase = 'intro';
@@ -309,10 +322,13 @@ export class RhythmGame extends Game {
+ Math.max(0, Math.ceil((now + 1.2 - this._bgmT0) / (4 * spb))) * 4 * spb;
this._tutAttempts = [];
this._cues = [];
+ // G2(round3):降速只拉伸该步的领奏/应答网格(间隔 ×1/0.75),领奏小节头
+ // 仍对齐 BGM 小节;排程照走 _sched 绝对时间 + 40ms 泵,泵与判定无需感知速率。
+ const stepSpb = spb / this._tutRate;
for (const [beat, g] of TUT_STEPS[this._tutIdx].notes) {
- const t = leadBar + (beat - 1) * spb;
+ const t = leadBar + (beat - 1) * stepSpb;
this._sched.push({ time: t, sfx: INST[g], volume: 1 });
- this._cues.push({ gesture: g, expected: t + 4 * spb, judged: false, phrase: -1 });
+ this._cues.push({ gesture: g, expected: t + 4 * stepSpb, judged: false, phrase: -1 });
}
this._sortSched();
const last = this._cues[this._cues.length - 1];
@@ -332,6 +348,7 @@ export class RhythmGame extends Game {
return a && a.correct && Math.abs(a.dt) <= GOOD;
});
if (pass) {
+ this._tutRate = 1.0; // G2:该步做对,恢复正常速度
if (this._tutIdx + 1 < TUT_STEPS.length) {
this._beginTutorial(rid, this._tutIdx + 1);
} else {
@@ -344,6 +361,22 @@ export class RhythmGame extends Game {
this._tutFails++;
vibrate('error');
if (this._tutFails >= 2) {
+ // G2(round3 教学降难 DDA):同一步连续 2 次失败 → 该步领奏降速 25% 重演
+ // (每教学局 1 次封顶;full 档先播 gd_slow「我放慢一些,跟着试试。」)——
+ // P4「六连错无出路」:失败后第一次有变慢的路,而不是直接跳步。封顶用尽
+ // 或 off 档(零改动红线)→ 维持 round2 的 retry_skip 跳步原路径。
+ if (this.guide.level() !== 'off' && !this._tutSlowUsed) {
+ this._tutSlowUsed = true;
+ this._tutRate = 0.75;
+ this._tutFails = 0; // 降速重演 = 该步重新给两次机会(再连 2 失败才跳步)
+ if (this.guide.level() === 'full') {
+ this._speakGuarded(['voice/gd_slow'], () => this._tutLead(rid));
+ } else {
+ this._tutLead(rid);
+ }
+ return;
+ }
+ this._tutRate = 1.0; // 离开该步(跳步):降速只作用于该步
// 同一步失败 2 次跳过,不卡流程(归因已在首次失败时给过,此处不再叠加)
this._speakGuarded(['voice/retry_skip'], () => {
if (this._tutIdx + 1 < TUT_STEPS.length) this._beginTutorial(rid, this._tutIdx + 1);
@@ -440,17 +473,14 @@ export class RhythmGame extends Game {
this._timed.push({ time: leadBarT0, fn: () => this.audio.play('voice/mid_song') });
}
if (i === 0) {
- // 向导层(round2 F3):每曲首次领奏→应答切换的交接标记。gd_answer 不走
- // guide 的 queue(对白在播时会排到链尾、错过首个应答窗口)——排进曲谱
- // 定时队列、在窗口前直接落下;turn earcon 走向导(full 语音,standard
- // 只听提示音,off 全静)。mid_song 同款先例。
- this._timed.push({
- time: leadBarT0 + 4 * spb,
- fn: () => {
- if (this.guide.level() === 'full') this.audio.play('voice/gd_answer');
- this.guide.turn({});
- },
- });
+ // 向导层(round3 G1):每次进 main,首个应答窗口**前整整 1 小节**(= 领奏
+ // 小节头)落下 gd_answer+turn 交接标记。round2 F3 的排程点(leadBarT0 +
+ // 4*spb)其实是窗口起点本身——P4 实测(窗口 t+79~95,gd_answer t+93.7)
+ // 窗口开了才听到,起不到「快轮到你了」的预警作用。gd_answer 不走 guide
+ // 的 queue(对白在播时会排到链尾);语音 full 档直达,turn earcon standard
+ // 也发(off 全静不变)。mid_song 同款先例。
+ this._answerArmed = true;
+ this._timed.push({ time: leadBarT0, fn: () => this._fireAnswerCue() });
}
bar += 2 + (this._song.restAfter[i] || 0);
});
@@ -460,6 +490,32 @@ export class RhythmGame extends Game {
this._startPump(rid);
}
+ /** G1:gd_answer+turn 交接标记(语音 full 档直达,turn earcon standard 也发)。 */
+ _fireAnswerCue() {
+ this._answerArmed = false;
+ if (this.guide.level() === 'full') this.audio.play('voice/gd_answer');
+ this.guide.turn({});
+ }
+
+ /**
+ * G1:为「下一个未判定的应答窗口」排交接标记,落在窗口前整整 1 小节(= 该句
+ * 领奏小节头;已迫近则尽早在 0.15s 内补上)。_startSong 已为乐句 0 排过;菜单
+ * 恢复(也是一次「进 main」)时若旧标记已消费、且前面还有未判定的窗口,对
+ * 恢复后的首个窗口重排同款标记。上一句结束后的下一句不适用(裁定原文)。
+ */
+ _armAnswerCue(rid) {
+ if (this._answerArmed) return; // 旧标记仍在 _timed 里,随网格平移照常提前 1 小节响
+ if (this._runId !== rid || !this._song || !this.audio.ctx) return;
+ const now = this.audio.ctx.currentTime;
+ const next = this._cues.find((c) => !c.judged && c.expected > now);
+ if (!next) return;
+ const spb = 60 / this._song.bpm;
+ const t = Math.max(now + 0.15, next.expected - 4 * spb);
+ this._answerArmed = true;
+ this._timed.push({ time: t, fn: () => this._fireAnswerCue() });
+ this._sortSched();
+ }
+
// ---------------- 手势与判定 ----------------
onGesture(g) {
@@ -619,8 +675,11 @@ export class RhythmGame extends Game {
this.guide.state('menu'); // 状态签名:菜单(模态暂停)
// 暂停:停泵、停 BGM(记断点),已排程的 ≤0.6s 音符自然播完
if (this._timer) { clearInterval(this._timer); this._timer = null; }
+ this._resumeSeq++; // G3:作废还在等 gd_count 播完的旧恢复
this._pauseAt = this.audio.ctx.currentTime;
- this._bgmOffset = this._pauseAt - this._bgmT0;
+ // 断点续播偏移只在 BGM 真在播时刷新(count-in 语音期间再开菜单时 BGM 未起,
+ // 沿用首次开的偏移,避免把暂停时长算进播放位置)
+ if (this._bgmSrc) this._bgmOffset = this._pauseAt - this._bgmT0;
this._stopBgmSrc();
this._speak(['voice/menu_main', MENU_ITEMS[0]]);
}
@@ -641,27 +700,43 @@ export class RhythmGame extends Game {
_closeMenu(rid) {
if (this._runId !== rid) return;
- const resumeAt = this.audio.ctx.currentTime + 0.1;
- // F3(round2):断点续播前插一整小节 4 拍 count-in(复用底鼓节拍音,走既有
- // _sched 网格排程 = 每拍一个 inst_kick + beat 轻震),网格与 BGM 整体后移一小节,
- // 杜绝 P1/P2/P3 实测的「回来 5 秒死寂、第一句报废」。off 档保持原即时续播
- // (向导层 off = 零改动路径)。
- const countIn = this.guide.level() !== 'off' ? 4 * (60 / this._song.bpm) : 0;
- const bgmAt = resumeAt + countIn;
- const shift = bgmAt - this._pauseAt;
- // 全部绝对时刻平移(暂停时长 + count-in 小节),节拍网格与 BGM 断点续播保持同步
- for (const ev of this._sched) ev.time += shift;
- for (const ev of this._timed) ev.time += shift;
- for (const cue of this._cues) cue.expected += shift;
- this._phaseEnd += shift;
- for (let i = 0; i < 4 && countIn > 0; i++) {
- this._sched.push({ time: resumeAt + i * (countIn / 4), sfx: INST.tap, volume: 0.7 });
- }
- // _startBgm 内部重算 _bgmT0 = bgmAt - offset = 旧网格 + shift(负偏移保护同款成立)
- this._startBgm(this._song, bgmAt, this._bgmOffset);
this.phase = 'main';
this.audio.setRateBoostEnabled(false); // 回到演奏期
- this._startPump(rid);
+ const token = ++this._resumeSeq; // G3:恢复令牌(语音等待期间再开菜单则作废)
+ const resume = () => {
+ if (this._runId !== rid || token !== this._resumeSeq) return;
+ const resumeAt = this.audio.ctx.currentTime + 0.1;
+ // G3(round3):断点续播前插一整小节 4 拍 count-in——底鼓走 sfx 层独立于
+ // BGM、音量提到可辨(0.7→1.0),每拍带 beat 轻震(_sched 泵同步排),网格
+ // 与 BGM 整体后移一小节,杜绝 P3 实测的「回来 5 秒死寂、第一句报废」。
+ // round2 F3 的 count-in 实际从未按时响过:底鼓 push 进 _sched 后没重排,
+ // 队头是数秒外的领奏音符,40ms 泵的 0.6s 前瞻窗口永远轮不到它——本次修复
+ // push 后 _sortSched()。off 档保持原即时续播(零改动路径)。
+ const countIn = this.guide.level() !== 'off' ? 4 * (60 / this._song.bpm) : 0;
+ const bgmAt = resumeAt + countIn;
+ const shift = bgmAt - this._pauseAt;
+ // 全部绝对时刻平移(暂停时长 + count-in 小节),节拍网格与 BGM 断点续播保持同步
+ for (const ev of this._sched) ev.time += shift;
+ for (const ev of this._timed) ev.time += shift;
+ for (const cue of this._cues) cue.expected += shift;
+ this._phaseEnd += shift;
+ for (let i = 0; i < 4 && countIn > 0; i++) {
+ this._sched.push({ time: resumeAt + i * (countIn / 4), sfx: INST.tap, volume: 1.0 });
+ }
+ this._sortSched(); // G3 修复:count-in 必须重排入队,否则被队头阻塞整段迟到
+ // _startBgm 内部重算 _bgmT0 = bgmAt - offset = 旧网格 + shift(负偏移保护同款成立)
+ this._startBgm(this._song, bgmAt, this._bgmOffset);
+ this._startPump(rid);
+ this._armAnswerCue(rid); // G1:菜单恢复也是一次「进 main」,给下一个窗口补交接标记
+ };
+ // G3:gd_count「四拍之后,继续。」full 档、每局(曲)恢复限 1 次,在 count-in
+ // 之前经语音链串行播出(链完或缺失看门狗兜底后才开始数拍)。
+ if (this.guide.level() === 'full' && !this._gdCountUsed) {
+ this._gdCountUsed = true;
+ this._speakGuarded(['voice/gd_count'], resume);
+ } else {
+ resume();
+ }
}
_goHome() {
diff --git a/web/simon/audio/voice/female/chance_plus.ogg b/web/simon/audio/voice/female/chance_plus.ogg
index 1080246e..10270922 100644
Binary files a/web/simon/audio/voice/female/chance_plus.ogg and b/web/simon/audio/voice/female/chance_plus.ogg differ
diff --git a/web/simon/audio/voice/female/chances_out.ogg b/web/simon/audio/voice/female/chances_out.ogg
index 88ee3d24..4cfd823b 100644
Binary files a/web/simon/audio/voice/female/chances_out.ogg and b/web/simon/audio/voice/female/chances_out.ogg differ
diff --git a/web/simon/audio/voice/female/correct.ogg b/web/simon/audio/voice/female/correct.ogg
index bfc96079..98a6494c 100644
Binary files a/web/simon/audio/voice/female/correct.ogg and b/web/simon/audio/voice/female/correct.ogg differ
diff --git a/web/simon/audio/voice/female/gameover.ogg b/web/simon/audio/voice/female/gameover.ogg
index d64ffc9e..9fa11bb6 100644
Binary files a/web/simon/audio/voice/female/gameover.ogg and b/web/simon/audio/voice/female/gameover.ogg differ
diff --git a/web/simon/audio/voice/female/gd_clear.m4a b/web/simon/audio/voice/female/gd_clear.m4a
new file mode 100644
index 00000000..f27a7659
Binary files /dev/null and b/web/simon/audio/voice/female/gd_clear.m4a differ
diff --git a/web/simon/audio/voice/female/gd_clear.ogg b/web/simon/audio/voice/female/gd_clear.ogg
new file mode 100644
index 00000000..54e96d31
Binary files /dev/null and b/web/simon/audio/voice/female/gd_clear.ogg differ
diff --git a/web/simon/audio/voice/female/gd_economy.m4a b/web/simon/audio/voice/female/gd_economy.m4a
index 51091466..9df26486 100644
Binary files a/web/simon/audio/voice/female/gd_economy.m4a and b/web/simon/audio/voice/female/gd_economy.m4a differ
diff --git a/web/simon/audio/voice/female/gd_economy.ogg b/web/simon/audio/voice/female/gd_economy.ogg
index 42f6eaef..319cdee6 100644
Binary files a/web/simon/audio/voice/female/gd_economy.ogg and b/web/simon/audio/voice/female/gd_economy.ogg differ
diff --git a/web/simon/audio/voice/female/gd_record.m4a b/web/simon/audio/voice/female/gd_record.m4a
new file mode 100644
index 00000000..93d3ba66
Binary files /dev/null and b/web/simon/audio/voice/female/gd_record.m4a differ
diff --git a/web/simon/audio/voice/female/gd_record.ogg b/web/simon/audio/voice/female/gd_record.ogg
new file mode 100644
index 00000000..c008bcbe
Binary files /dev/null and b/web/simon/audio/voice/female/gd_record.ogg differ
diff --git a/web/simon/audio/voice/female/gd_relisten.m4a b/web/simon/audio/voice/female/gd_relisten.m4a
index 4e845aa9..a67f33e4 100644
Binary files a/web/simon/audio/voice/female/gd_relisten.m4a and b/web/simon/audio/voice/female/gd_relisten.m4a differ
diff --git a/web/simon/audio/voice/female/gd_relisten.ogg b/web/simon/audio/voice/female/gd_relisten.ogg
index 21c803d6..ca936de6 100644
Binary files a/web/simon/audio/voice/female/gd_relisten.ogg and b/web/simon/audio/voice/female/gd_relisten.ogg differ
diff --git a/web/simon/audio/voice/female/menu_back.ogg b/web/simon/audio/voice/female/menu_back.ogg
index 9e7ac47f..0fdcff23 100644
Binary files a/web/simon/audio/voice/female/menu_back.ogg and b/web/simon/audio/voice/female/menu_back.ogg differ
diff --git a/web/simon/audio/voice/female/menu_home.ogg b/web/simon/audio/voice/female/menu_home.ogg
index 992f9383..ca22d7c8 100644
Binary files a/web/simon/audio/voice/female/menu_home.ogg and b/web/simon/audio/voice/female/menu_home.ogg differ
diff --git a/web/simon/audio/voice/female/menu_open.ogg b/web/simon/audio/voice/female/menu_open.ogg
index 4152646a..bb93f07e 100644
Binary files a/web/simon/audio/voice/female/menu_open.ogg and b/web/simon/audio/voice/female/menu_open.ogg differ
diff --git a/web/simon/audio/voice/female/menu_restart.ogg b/web/simon/audio/voice/female/menu_restart.ogg
index db7397e6..f464a7b4 100644
Binary files a/web/simon/audio/voice/female/menu_restart.ogg and b/web/simon/audio/voice/female/menu_restart.ogg differ
diff --git a/web/simon/audio/voice/female/new_record.ogg b/web/simon/audio/voice/female/new_record.ogg
index 4d56f345..099ea85d 100644
Binary files a/web/simon/audio/voice/female/new_record.ogg and b/web/simon/audio/voice/female/new_record.ogg differ
diff --git a/web/simon/audio/voice/female/relisten.ogg b/web/simon/audio/voice/female/relisten.ogg
index 1776be21..c64d5462 100644
Binary files a/web/simon/audio/voice/female/relisten.ogg and b/web/simon/audio/voice/female/relisten.ogg differ
diff --git a/web/simon/audio/voice/female/replay.ogg b/web/simon/audio/voice/female/replay.ogg
index 1696d5ce..37835ec2 100644
Binary files a/web/simon/audio/voice/female/replay.ogg and b/web/simon/audio/voice/female/replay.ogg differ
diff --git a/web/simon/audio/voice/female/retry_use.ogg b/web/simon/audio/voice/female/retry_use.ogg
index e46ac8c5..27a64e98 100644
Binary files a/web/simon/audio/voice/female/retry_use.ogg and b/web/simon/audio/voice/female/retry_use.ogg differ
diff --git a/web/simon/audio/voice/female/round_01.ogg b/web/simon/audio/voice/female/round_01.ogg
index dcc29bd2..8b337505 100644
Binary files a/web/simon/audio/voice/female/round_01.ogg and b/web/simon/audio/voice/female/round_01.ogg differ
diff --git a/web/simon/audio/voice/female/round_02.ogg b/web/simon/audio/voice/female/round_02.ogg
index c26c0ccf..73e16fd5 100644
Binary files a/web/simon/audio/voice/female/round_02.ogg and b/web/simon/audio/voice/female/round_02.ogg differ
diff --git a/web/simon/audio/voice/female/round_03.ogg b/web/simon/audio/voice/female/round_03.ogg
index 36271908..03103b58 100644
Binary files a/web/simon/audio/voice/female/round_03.ogg and b/web/simon/audio/voice/female/round_03.ogg differ
diff --git a/web/simon/audio/voice/female/round_04.ogg b/web/simon/audio/voice/female/round_04.ogg
index fb3cea5b..83398a87 100644
Binary files a/web/simon/audio/voice/female/round_04.ogg and b/web/simon/audio/voice/female/round_04.ogg differ
diff --git a/web/simon/audio/voice/female/round_05.ogg b/web/simon/audio/voice/female/round_05.ogg
index ae4aa79d..15deedfa 100644
Binary files a/web/simon/audio/voice/female/round_05.ogg and b/web/simon/audio/voice/female/round_05.ogg differ
diff --git a/web/simon/audio/voice/female/round_06.ogg b/web/simon/audio/voice/female/round_06.ogg
index 3a6279a3..a22d0e3c 100644
Binary files a/web/simon/audio/voice/female/round_06.ogg and b/web/simon/audio/voice/female/round_06.ogg differ
diff --git a/web/simon/audio/voice/female/round_07.ogg b/web/simon/audio/voice/female/round_07.ogg
index baa3c667..c71f811d 100644
Binary files a/web/simon/audio/voice/female/round_07.ogg and b/web/simon/audio/voice/female/round_07.ogg differ
diff --git a/web/simon/audio/voice/female/round_08.ogg b/web/simon/audio/voice/female/round_08.ogg
index 5ad51db8..0a308fed 100644
Binary files a/web/simon/audio/voice/female/round_08.ogg and b/web/simon/audio/voice/female/round_08.ogg differ
diff --git a/web/simon/audio/voice/female/round_09.ogg b/web/simon/audio/voice/female/round_09.ogg
index a8dc27da..4978d709 100644
Binary files a/web/simon/audio/voice/female/round_09.ogg and b/web/simon/audio/voice/female/round_09.ogg differ
diff --git a/web/simon/audio/voice/female/round_10.ogg b/web/simon/audio/voice/female/round_10.ogg
index 8602592c..28b06590 100644
Binary files a/web/simon/audio/voice/female/round_10.ogg and b/web/simon/audio/voice/female/round_10.ogg differ
diff --git a/web/simon/audio/voice/female/round_11.ogg b/web/simon/audio/voice/female/round_11.ogg
index f918199a..55645b94 100644
Binary files a/web/simon/audio/voice/female/round_11.ogg and b/web/simon/audio/voice/female/round_11.ogg differ
diff --git a/web/simon/audio/voice/female/round_12.ogg b/web/simon/audio/voice/female/round_12.ogg
index 1547f3d7..fc3ea4fb 100644
Binary files a/web/simon/audio/voice/female/round_12.ogg and b/web/simon/audio/voice/female/round_12.ogg differ
diff --git a/web/simon/audio/voice/female/round_13.ogg b/web/simon/audio/voice/female/round_13.ogg
index 89a0d4a1..90ff5e53 100644
Binary files a/web/simon/audio/voice/female/round_13.ogg and b/web/simon/audio/voice/female/round_13.ogg differ
diff --git a/web/simon/audio/voice/female/round_14.ogg b/web/simon/audio/voice/female/round_14.ogg
index c0b4e3cb..6244cab5 100644
Binary files a/web/simon/audio/voice/female/round_14.ogg and b/web/simon/audio/voice/female/round_14.ogg differ
diff --git a/web/simon/audio/voice/female/round_15.ogg b/web/simon/audio/voice/female/round_15.ogg
index 5d01ec8b..a71fb82e 100644
Binary files a/web/simon/audio/voice/female/round_15.ogg and b/web/simon/audio/voice/female/round_15.ogg differ
diff --git a/web/simon/audio/voice/female/round_16.ogg b/web/simon/audio/voice/female/round_16.ogg
index e43a0329..e48194e0 100644
Binary files a/web/simon/audio/voice/female/round_16.ogg and b/web/simon/audio/voice/female/round_16.ogg differ
diff --git a/web/simon/audio/voice/female/round_17.ogg b/web/simon/audio/voice/female/round_17.ogg
index 627f28ed..4e79e4a5 100644
Binary files a/web/simon/audio/voice/female/round_17.ogg and b/web/simon/audio/voice/female/round_17.ogg differ
diff --git a/web/simon/audio/voice/female/round_18.ogg b/web/simon/audio/voice/female/round_18.ogg
index f3f2dd17..0bb7f5c8 100644
Binary files a/web/simon/audio/voice/female/round_18.ogg and b/web/simon/audio/voice/female/round_18.ogg differ
diff --git a/web/simon/audio/voice/female/round_19.ogg b/web/simon/audio/voice/female/round_19.ogg
index 79412da7..d9e82f77 100644
Binary files a/web/simon/audio/voice/female/round_19.ogg and b/web/simon/audio/voice/female/round_19.ogg differ
diff --git a/web/simon/audio/voice/female/round_20.ogg b/web/simon/audio/voice/female/round_20.ogg
index 8bb41064..c34fe040 100644
Binary files a/web/simon/audio/voice/female/round_20.ogg and b/web/simon/audio/voice/female/round_20.ogg differ
diff --git a/web/simon/audio/voice/female/round_more.ogg b/web/simon/audio/voice/female/round_more.ogg
index ee078a6f..fb0ba481 100644
Binary files a/web/simon/audio/voice/female/round_more.ogg and b/web/simon/audio/voice/female/round_more.ogg differ
diff --git a/web/simon/audio/voice/female/rules.ogg b/web/simon/audio/voice/female/rules.ogg
index 8246a015..551e7ee4 100644
Binary files a/web/simon/audio/voice/female/rules.ogg and b/web/simon/audio/voice/female/rules.ogg differ
diff --git a/web/simon/audio/voice/female/rules_prompt.ogg b/web/simon/audio/voice/female/rules_prompt.ogg
index 0d3dcbbf..053e3f4e 100644
Binary files a/web/simon/audio/voice/female/rules_prompt.ogg and b/web/simon/audio/voice/female/rules_prompt.ogg differ
diff --git a/web/simon/audio/voice/female/score_band1.ogg b/web/simon/audio/voice/female/score_band1.ogg
index df38ac5f..0791b9f9 100644
Binary files a/web/simon/audio/voice/female/score_band1.ogg and b/web/simon/audio/voice/female/score_band1.ogg differ
diff --git a/web/simon/audio/voice/female/score_band2.ogg b/web/simon/audio/voice/female/score_band2.ogg
index b59d274d..213729da 100644
Binary files a/web/simon/audio/voice/female/score_band2.ogg and b/web/simon/audio/voice/female/score_band2.ogg differ
diff --git a/web/simon/audio/voice/female/score_band3.ogg b/web/simon/audio/voice/female/score_band3.ogg
index d1af20df..7aa1a2b8 100644
Binary files a/web/simon/audio/voice/female/score_band3.ogg and b/web/simon/audio/voice/female/score_band3.ogg differ
diff --git a/web/simon/audio/voice/female/score_band4.ogg b/web/simon/audio/voice/female/score_band4.ogg
index 0a83c08b..3fce656d 100644
Binary files a/web/simon/audio/voice/female/score_band4.ogg and b/web/simon/audio/voice/female/score_band4.ogg differ
diff --git a/web/simon/audio/voice/female/score_band5.ogg b/web/simon/audio/voice/female/score_band5.ogg
index 8d52d208..cc18fcfd 100644
Binary files a/web/simon/audio/voice/female/score_band5.ogg and b/web/simon/audio/voice/female/score_band5.ogg differ
diff --git a/web/simon/audio/voice/female/score_band6.ogg b/web/simon/audio/voice/female/score_band6.ogg
index 4b903167..dcef4a94 100644
Binary files a/web/simon/audio/voice/female/score_band6.ogg and b/web/simon/audio/voice/female/score_band6.ogg differ
diff --git a/web/simon/audio/voice/female/skip_hint.ogg b/web/simon/audio/voice/female/skip_hint.ogg
index a43d3658..9de67061 100644
Binary files a/web/simon/audio/voice/female/skip_hint.ogg and b/web/simon/audio/voice/female/skip_hint.ogg differ
diff --git a/web/simon/audio/voice/female/t0_goal.ogg b/web/simon/audio/voice/female/t0_goal.ogg
index 5e4876f4..6234b875 100644
Binary files a/web/simon/audio/voice/female/t0_goal.ogg and b/web/simon/audio/voice/female/t0_goal.ogg differ
diff --git a/web/simon/audio/voice/female/t0_welcome.ogg b/web/simon/audio/voice/female/t0_welcome.ogg
index ecce46fc..ff4a21e1 100644
Binary files a/web/simon/audio/voice/female/t0_welcome.ogg and b/web/simon/audio/voice/female/t0_welcome.ogg differ
diff --git a/web/simon/audio/voice/female/t1_up.ogg b/web/simon/audio/voice/female/t1_up.ogg
index 5ae0b352..1c4bad2a 100644
Binary files a/web/simon/audio/voice/female/t1_up.ogg and b/web/simon/audio/voice/female/t1_up.ogg differ
diff --git a/web/simon/audio/voice/female/t2_down.ogg b/web/simon/audio/voice/female/t2_down.ogg
index fa2e2a15..cc117b22 100644
Binary files a/web/simon/audio/voice/female/t2_down.ogg and b/web/simon/audio/voice/female/t2_down.ogg differ
diff --git a/web/simon/audio/voice/female/t3_left.ogg b/web/simon/audio/voice/female/t3_left.ogg
index 28f1a285..aba84232 100644
Binary files a/web/simon/audio/voice/female/t3_left.ogg and b/web/simon/audio/voice/female/t3_left.ogg differ
diff --git a/web/simon/audio/voice/female/t4_right.ogg b/web/simon/audio/voice/female/t4_right.ogg
index af9b24dc..9e5b547a 100644
Binary files a/web/simon/audio/voice/female/t4_right.ogg and b/web/simon/audio/voice/female/t4_right.ogg differ
diff --git a/web/simon/audio/voice/female/t5_tap.ogg b/web/simon/audio/voice/female/t5_tap.ogg
index 42eccd42..e7d14452 100644
Binary files a/web/simon/audio/voice/female/t5_tap.ogg and b/web/simon/audio/voice/female/t5_tap.ogg differ
diff --git a/web/simon/audio/voice/female/t6_double.ogg b/web/simon/audio/voice/female/t6_double.ogg
index c808a0df..6534832e 100644
Binary files a/web/simon/audio/voice/female/t6_double.ogg and b/web/simon/audio/voice/female/t6_double.ogg differ
diff --git a/web/simon/audio/voice/female/t7_ready.ogg b/web/simon/audio/voice/female/t7_ready.ogg
index 3a080b9f..34d09dfa 100644
Binary files a/web/simon/audio/voice/female/t7_ready.ogg and b/web/simon/audio/voice/female/t7_ready.ogg differ
diff --git a/web/simon/audio/voice/female/t7_retry.m4a b/web/simon/audio/voice/female/t7_retry.m4a
index 1b092096..f8698820 100644
Binary files a/web/simon/audio/voice/female/t7_retry.m4a and b/web/simon/audio/voice/female/t7_retry.m4a differ
diff --git a/web/simon/audio/voice/female/t7_retry.ogg b/web/simon/audio/voice/female/t7_retry.ogg
index 3b78c941..9aac7679 100644
Binary files a/web/simon/audio/voice/female/t7_retry.ogg and b/web/simon/audio/voice/female/t7_retry.ogg differ
diff --git a/web/simon/audio/voice/female/t_blunt_double.ogg b/web/simon/audio/voice/female/t_blunt_double.ogg
index 7d2b6d2c..27d4209d 100644
Binary files a/web/simon/audio/voice/female/t_blunt_double.ogg and b/web/simon/audio/voice/female/t_blunt_double.ogg differ
diff --git a/web/simon/audio/voice/female/t_blunt_down.ogg b/web/simon/audio/voice/female/t_blunt_down.ogg
index 7b592852..ae182c0c 100644
Binary files a/web/simon/audio/voice/female/t_blunt_down.ogg and b/web/simon/audio/voice/female/t_blunt_down.ogg differ
diff --git a/web/simon/audio/voice/female/t_blunt_left.ogg b/web/simon/audio/voice/female/t_blunt_left.ogg
index 9a60b472..66aa2613 100644
Binary files a/web/simon/audio/voice/female/t_blunt_left.ogg and b/web/simon/audio/voice/female/t_blunt_left.ogg differ
diff --git a/web/simon/audio/voice/female/t_blunt_right.ogg b/web/simon/audio/voice/female/t_blunt_right.ogg
index e185b228..c4674246 100644
Binary files a/web/simon/audio/voice/female/t_blunt_right.ogg and b/web/simon/audio/voice/female/t_blunt_right.ogg differ
diff --git a/web/simon/audio/voice/female/t_blunt_tap.ogg b/web/simon/audio/voice/female/t_blunt_tap.ogg
index 13f2f237..c54c7059 100644
Binary files a/web/simon/audio/voice/female/t_blunt_tap.ogg and b/web/simon/audio/voice/female/t_blunt_tap.ogg differ
diff --git a/web/simon/audio/voice/female/t_blunt_up.ogg b/web/simon/audio/voice/female/t_blunt_up.ogg
index 98ab5965..45c1d066 100644
Binary files a/web/simon/audio/voice/female/t_blunt_up.ogg and b/web/simon/audio/voice/female/t_blunt_up.ogg differ
diff --git a/web/simon/audio/voice/female/t_ok.ogg b/web/simon/audio/voice/female/t_ok.ogg
index 927f5c21..20c6e1be 100644
Binary files a/web/simon/audio/voice/female/t_ok.ogg and b/web/simon/audio/voice/female/t_ok.ogg differ
diff --git a/web/simon/audio/voice/female/t_skip.ogg b/web/simon/audio/voice/female/t_skip.ogg
index 80bc1d13..5fba831c 100644
Binary files a/web/simon/audio/voice/female/t_skip.ogg and b/web/simon/audio/voice/female/t_skip.ogg differ
diff --git a/web/simon/audio/voice/female/t_try.ogg b/web/simon/audio/voice/female/t_try.ogg
index 01ad1fe0..f48a80f2 100644
Binary files a/web/simon/audio/voice/female/t_try.ogg and b/web/simon/audio/voice/female/t_try.ogg differ
diff --git a/web/simon/audio/voice/female/t_wrong_double.ogg b/web/simon/audio/voice/female/t_wrong_double.ogg
index d5c0cb1f..4abe591c 100644
Binary files a/web/simon/audio/voice/female/t_wrong_double.ogg and b/web/simon/audio/voice/female/t_wrong_double.ogg differ
diff --git a/web/simon/audio/voice/female/t_wrong_down.ogg b/web/simon/audio/voice/female/t_wrong_down.ogg
index 208c0380..2a8812e0 100644
Binary files a/web/simon/audio/voice/female/t_wrong_down.ogg and b/web/simon/audio/voice/female/t_wrong_down.ogg differ
diff --git a/web/simon/audio/voice/female/t_wrong_left.ogg b/web/simon/audio/voice/female/t_wrong_left.ogg
index fd50571a..99bb089b 100644
Binary files a/web/simon/audio/voice/female/t_wrong_left.ogg and b/web/simon/audio/voice/female/t_wrong_left.ogg differ
diff --git a/web/simon/audio/voice/female/t_wrong_right.ogg b/web/simon/audio/voice/female/t_wrong_right.ogg
index 59bb5667..2e80ae60 100644
Binary files a/web/simon/audio/voice/female/t_wrong_right.ogg and b/web/simon/audio/voice/female/t_wrong_right.ogg differ
diff --git a/web/simon/audio/voice/female/t_wrong_tap.ogg b/web/simon/audio/voice/female/t_wrong_tap.ogg
index a16047c0..f7cafbf9 100644
Binary files a/web/simon/audio/voice/female/t_wrong_tap.ogg and b/web/simon/audio/voice/female/t_wrong_tap.ogg differ
diff --git a/web/simon/audio/voice/female/t_wrong_up.ogg b/web/simon/audio/voice/female/t_wrong_up.ogg
index ed0fb739..93e9945a 100644
Binary files a/web/simon/audio/voice/female/t_wrong_up.ogg and b/web/simon/audio/voice/female/t_wrong_up.ogg differ
diff --git a/web/simon/audio/voice/female/wrong.ogg b/web/simon/audio/voice/female/wrong.ogg
index 0991be65..fc11ae8e 100644
Binary files a/web/simon/audio/voice/female/wrong.ogg and b/web/simon/audio/voice/female/wrong.ogg differ
diff --git a/web/simon/audio/voice/female/your_turn.ogg b/web/simon/audio/voice/female/your_turn.ogg
index 7b92bfad..d99582c6 100644
Binary files a/web/simon/audio/voice/female/your_turn.ogg and b/web/simon/audio/voice/female/your_turn.ogg differ
diff --git a/web/simon/audio/voice/male/chance_plus.ogg b/web/simon/audio/voice/male/chance_plus.ogg
index 72ce4424..a2cff8ae 100644
Binary files a/web/simon/audio/voice/male/chance_plus.ogg and b/web/simon/audio/voice/male/chance_plus.ogg differ
diff --git a/web/simon/audio/voice/male/chances_out.ogg b/web/simon/audio/voice/male/chances_out.ogg
index a464cf76..44fc5e8d 100644
Binary files a/web/simon/audio/voice/male/chances_out.ogg and b/web/simon/audio/voice/male/chances_out.ogg differ
diff --git a/web/simon/audio/voice/male/correct.ogg b/web/simon/audio/voice/male/correct.ogg
index 51a1db86..8e70e849 100644
Binary files a/web/simon/audio/voice/male/correct.ogg and b/web/simon/audio/voice/male/correct.ogg differ
diff --git a/web/simon/audio/voice/male/gameover.ogg b/web/simon/audio/voice/male/gameover.ogg
index 8a32a619..37435f90 100644
Binary files a/web/simon/audio/voice/male/gameover.ogg and b/web/simon/audio/voice/male/gameover.ogg differ
diff --git a/web/simon/audio/voice/male/gd_clear.m4a b/web/simon/audio/voice/male/gd_clear.m4a
new file mode 100644
index 00000000..e676f302
Binary files /dev/null and b/web/simon/audio/voice/male/gd_clear.m4a differ
diff --git a/web/simon/audio/voice/male/gd_clear.ogg b/web/simon/audio/voice/male/gd_clear.ogg
new file mode 100644
index 00000000..c846e28c
Binary files /dev/null and b/web/simon/audio/voice/male/gd_clear.ogg differ
diff --git a/web/simon/audio/voice/male/gd_economy.m4a b/web/simon/audio/voice/male/gd_economy.m4a
index f28c527c..32538c43 100644
Binary files a/web/simon/audio/voice/male/gd_economy.m4a and b/web/simon/audio/voice/male/gd_economy.m4a differ
diff --git a/web/simon/audio/voice/male/gd_economy.ogg b/web/simon/audio/voice/male/gd_economy.ogg
index c933519a..673cf749 100644
Binary files a/web/simon/audio/voice/male/gd_economy.ogg and b/web/simon/audio/voice/male/gd_economy.ogg differ
diff --git a/web/simon/audio/voice/male/gd_record.m4a b/web/simon/audio/voice/male/gd_record.m4a
new file mode 100644
index 00000000..bd5f2ac6
Binary files /dev/null and b/web/simon/audio/voice/male/gd_record.m4a differ
diff --git a/web/simon/audio/voice/male/gd_record.ogg b/web/simon/audio/voice/male/gd_record.ogg
new file mode 100644
index 00000000..c8d4a7c5
Binary files /dev/null and b/web/simon/audio/voice/male/gd_record.ogg differ
diff --git a/web/simon/audio/voice/male/gd_relisten.m4a b/web/simon/audio/voice/male/gd_relisten.m4a
index 658671dd..406944a3 100644
Binary files a/web/simon/audio/voice/male/gd_relisten.m4a and b/web/simon/audio/voice/male/gd_relisten.m4a differ
diff --git a/web/simon/audio/voice/male/gd_relisten.ogg b/web/simon/audio/voice/male/gd_relisten.ogg
index d587953c..5b78e09d 100644
Binary files a/web/simon/audio/voice/male/gd_relisten.ogg and b/web/simon/audio/voice/male/gd_relisten.ogg differ
diff --git a/web/simon/audio/voice/male/menu_back.ogg b/web/simon/audio/voice/male/menu_back.ogg
index 0873b642..109a5114 100644
Binary files a/web/simon/audio/voice/male/menu_back.ogg and b/web/simon/audio/voice/male/menu_back.ogg differ
diff --git a/web/simon/audio/voice/male/menu_home.ogg b/web/simon/audio/voice/male/menu_home.ogg
index 7db24e5f..40995013 100644
Binary files a/web/simon/audio/voice/male/menu_home.ogg and b/web/simon/audio/voice/male/menu_home.ogg differ
diff --git a/web/simon/audio/voice/male/menu_open.ogg b/web/simon/audio/voice/male/menu_open.ogg
index 55a72c44..f3819dd2 100644
Binary files a/web/simon/audio/voice/male/menu_open.ogg and b/web/simon/audio/voice/male/menu_open.ogg differ
diff --git a/web/simon/audio/voice/male/menu_restart.ogg b/web/simon/audio/voice/male/menu_restart.ogg
index 248bf972..4679aca4 100644
Binary files a/web/simon/audio/voice/male/menu_restart.ogg and b/web/simon/audio/voice/male/menu_restart.ogg differ
diff --git a/web/simon/audio/voice/male/new_record.ogg b/web/simon/audio/voice/male/new_record.ogg
index c219e5aa..2d9c1f90 100644
Binary files a/web/simon/audio/voice/male/new_record.ogg and b/web/simon/audio/voice/male/new_record.ogg differ
diff --git a/web/simon/audio/voice/male/relisten.ogg b/web/simon/audio/voice/male/relisten.ogg
index 87d92e17..0541fe5c 100644
Binary files a/web/simon/audio/voice/male/relisten.ogg and b/web/simon/audio/voice/male/relisten.ogg differ
diff --git a/web/simon/audio/voice/male/replay.ogg b/web/simon/audio/voice/male/replay.ogg
index 60a29314..2d695a3b 100644
Binary files a/web/simon/audio/voice/male/replay.ogg and b/web/simon/audio/voice/male/replay.ogg differ
diff --git a/web/simon/audio/voice/male/retry_use.ogg b/web/simon/audio/voice/male/retry_use.ogg
index 38caa9a0..a83384e0 100644
Binary files a/web/simon/audio/voice/male/retry_use.ogg and b/web/simon/audio/voice/male/retry_use.ogg differ
diff --git a/web/simon/audio/voice/male/round_01.ogg b/web/simon/audio/voice/male/round_01.ogg
index fee020c0..37520e90 100644
Binary files a/web/simon/audio/voice/male/round_01.ogg and b/web/simon/audio/voice/male/round_01.ogg differ
diff --git a/web/simon/audio/voice/male/round_02.ogg b/web/simon/audio/voice/male/round_02.ogg
index 033bc970..6ebc6fbc 100644
Binary files a/web/simon/audio/voice/male/round_02.ogg and b/web/simon/audio/voice/male/round_02.ogg differ
diff --git a/web/simon/audio/voice/male/round_03.ogg b/web/simon/audio/voice/male/round_03.ogg
index 20f10eca..ffda4a5c 100644
Binary files a/web/simon/audio/voice/male/round_03.ogg and b/web/simon/audio/voice/male/round_03.ogg differ
diff --git a/web/simon/audio/voice/male/round_04.ogg b/web/simon/audio/voice/male/round_04.ogg
index 2041327a..82efd421 100644
Binary files a/web/simon/audio/voice/male/round_04.ogg and b/web/simon/audio/voice/male/round_04.ogg differ
diff --git a/web/simon/audio/voice/male/round_05.ogg b/web/simon/audio/voice/male/round_05.ogg
index b1212862..f434b091 100644
Binary files a/web/simon/audio/voice/male/round_05.ogg and b/web/simon/audio/voice/male/round_05.ogg differ
diff --git a/web/simon/audio/voice/male/round_06.ogg b/web/simon/audio/voice/male/round_06.ogg
index c8aff54c..004cad7a 100644
Binary files a/web/simon/audio/voice/male/round_06.ogg and b/web/simon/audio/voice/male/round_06.ogg differ
diff --git a/web/simon/audio/voice/male/round_07.ogg b/web/simon/audio/voice/male/round_07.ogg
index 6e56d886..187efe46 100644
Binary files a/web/simon/audio/voice/male/round_07.ogg and b/web/simon/audio/voice/male/round_07.ogg differ
diff --git a/web/simon/audio/voice/male/round_08.ogg b/web/simon/audio/voice/male/round_08.ogg
index b6a4966c..09eadb25 100644
Binary files a/web/simon/audio/voice/male/round_08.ogg and b/web/simon/audio/voice/male/round_08.ogg differ
diff --git a/web/simon/audio/voice/male/round_09.ogg b/web/simon/audio/voice/male/round_09.ogg
index 5e71c0b8..0c50ce89 100644
Binary files a/web/simon/audio/voice/male/round_09.ogg and b/web/simon/audio/voice/male/round_09.ogg differ
diff --git a/web/simon/audio/voice/male/round_10.ogg b/web/simon/audio/voice/male/round_10.ogg
index 3a4d35cc..9d3f5662 100644
Binary files a/web/simon/audio/voice/male/round_10.ogg and b/web/simon/audio/voice/male/round_10.ogg differ
diff --git a/web/simon/audio/voice/male/round_11.ogg b/web/simon/audio/voice/male/round_11.ogg
index 5f1f713e..bd08e47d 100644
Binary files a/web/simon/audio/voice/male/round_11.ogg and b/web/simon/audio/voice/male/round_11.ogg differ
diff --git a/web/simon/audio/voice/male/round_12.ogg b/web/simon/audio/voice/male/round_12.ogg
index d1137d2c..13607b1e 100644
Binary files a/web/simon/audio/voice/male/round_12.ogg and b/web/simon/audio/voice/male/round_12.ogg differ
diff --git a/web/simon/audio/voice/male/round_13.ogg b/web/simon/audio/voice/male/round_13.ogg
index 382d1ed0..3a2f49a3 100644
Binary files a/web/simon/audio/voice/male/round_13.ogg and b/web/simon/audio/voice/male/round_13.ogg differ
diff --git a/web/simon/audio/voice/male/round_14.ogg b/web/simon/audio/voice/male/round_14.ogg
index 2698db17..f12ecbbc 100644
Binary files a/web/simon/audio/voice/male/round_14.ogg and b/web/simon/audio/voice/male/round_14.ogg differ
diff --git a/web/simon/audio/voice/male/round_15.ogg b/web/simon/audio/voice/male/round_15.ogg
index 7ed795d6..0fc902ef 100644
Binary files a/web/simon/audio/voice/male/round_15.ogg and b/web/simon/audio/voice/male/round_15.ogg differ
diff --git a/web/simon/audio/voice/male/round_16.ogg b/web/simon/audio/voice/male/round_16.ogg
index 6b6a9817..c48e9fa0 100644
Binary files a/web/simon/audio/voice/male/round_16.ogg and b/web/simon/audio/voice/male/round_16.ogg differ
diff --git a/web/simon/audio/voice/male/round_17.ogg b/web/simon/audio/voice/male/round_17.ogg
index ac41bd17..b6137e5a 100644
Binary files a/web/simon/audio/voice/male/round_17.ogg and b/web/simon/audio/voice/male/round_17.ogg differ
diff --git a/web/simon/audio/voice/male/round_18.ogg b/web/simon/audio/voice/male/round_18.ogg
index 32343bc6..94a9f900 100644
Binary files a/web/simon/audio/voice/male/round_18.ogg and b/web/simon/audio/voice/male/round_18.ogg differ
diff --git a/web/simon/audio/voice/male/round_19.ogg b/web/simon/audio/voice/male/round_19.ogg
index 8a92a07a..f96f7846 100644
Binary files a/web/simon/audio/voice/male/round_19.ogg and b/web/simon/audio/voice/male/round_19.ogg differ
diff --git a/web/simon/audio/voice/male/round_20.ogg b/web/simon/audio/voice/male/round_20.ogg
index f988904d..07687c88 100644
Binary files a/web/simon/audio/voice/male/round_20.ogg and b/web/simon/audio/voice/male/round_20.ogg differ
diff --git a/web/simon/audio/voice/male/round_more.ogg b/web/simon/audio/voice/male/round_more.ogg
index 9af6eb6d..cd1d27aa 100644
Binary files a/web/simon/audio/voice/male/round_more.ogg and b/web/simon/audio/voice/male/round_more.ogg differ
diff --git a/web/simon/audio/voice/male/rules.ogg b/web/simon/audio/voice/male/rules.ogg
index fee626cd..de512408 100644
Binary files a/web/simon/audio/voice/male/rules.ogg and b/web/simon/audio/voice/male/rules.ogg differ
diff --git a/web/simon/audio/voice/male/rules_prompt.ogg b/web/simon/audio/voice/male/rules_prompt.ogg
index 82ffa506..34f02709 100644
Binary files a/web/simon/audio/voice/male/rules_prompt.ogg and b/web/simon/audio/voice/male/rules_prompt.ogg differ
diff --git a/web/simon/audio/voice/male/score_band1.ogg b/web/simon/audio/voice/male/score_band1.ogg
index 6dab0a5e..492e41d1 100644
Binary files a/web/simon/audio/voice/male/score_band1.ogg and b/web/simon/audio/voice/male/score_band1.ogg differ
diff --git a/web/simon/audio/voice/male/score_band2.ogg b/web/simon/audio/voice/male/score_band2.ogg
index 1f0abe7d..198e0d8b 100644
Binary files a/web/simon/audio/voice/male/score_band2.ogg and b/web/simon/audio/voice/male/score_band2.ogg differ
diff --git a/web/simon/audio/voice/male/score_band3.ogg b/web/simon/audio/voice/male/score_band3.ogg
index 4b3fef01..c70509ec 100644
Binary files a/web/simon/audio/voice/male/score_band3.ogg and b/web/simon/audio/voice/male/score_band3.ogg differ
diff --git a/web/simon/audio/voice/male/score_band4.ogg b/web/simon/audio/voice/male/score_band4.ogg
index aca33c52..60b6ac16 100644
Binary files a/web/simon/audio/voice/male/score_band4.ogg and b/web/simon/audio/voice/male/score_band4.ogg differ
diff --git a/web/simon/audio/voice/male/score_band5.ogg b/web/simon/audio/voice/male/score_band5.ogg
index 8975c710..281f8ff0 100644
Binary files a/web/simon/audio/voice/male/score_band5.ogg and b/web/simon/audio/voice/male/score_band5.ogg differ
diff --git a/web/simon/audio/voice/male/score_band6.ogg b/web/simon/audio/voice/male/score_band6.ogg
index a1bc22de..b712697d 100644
Binary files a/web/simon/audio/voice/male/score_band6.ogg and b/web/simon/audio/voice/male/score_band6.ogg differ
diff --git a/web/simon/audio/voice/male/skip_hint.ogg b/web/simon/audio/voice/male/skip_hint.ogg
index 7149fc95..e45121c0 100644
Binary files a/web/simon/audio/voice/male/skip_hint.ogg and b/web/simon/audio/voice/male/skip_hint.ogg differ
diff --git a/web/simon/audio/voice/male/t0_goal.ogg b/web/simon/audio/voice/male/t0_goal.ogg
index 3b4840f1..fa989c84 100644
Binary files a/web/simon/audio/voice/male/t0_goal.ogg and b/web/simon/audio/voice/male/t0_goal.ogg differ
diff --git a/web/simon/audio/voice/male/t0_welcome.ogg b/web/simon/audio/voice/male/t0_welcome.ogg
index c1584adb..9d201494 100644
Binary files a/web/simon/audio/voice/male/t0_welcome.ogg and b/web/simon/audio/voice/male/t0_welcome.ogg differ
diff --git a/web/simon/audio/voice/male/t1_up.ogg b/web/simon/audio/voice/male/t1_up.ogg
index e20da5ac..4d177bf7 100644
Binary files a/web/simon/audio/voice/male/t1_up.ogg and b/web/simon/audio/voice/male/t1_up.ogg differ
diff --git a/web/simon/audio/voice/male/t2_down.ogg b/web/simon/audio/voice/male/t2_down.ogg
index 4932af6b..14d16d02 100644
Binary files a/web/simon/audio/voice/male/t2_down.ogg and b/web/simon/audio/voice/male/t2_down.ogg differ
diff --git a/web/simon/audio/voice/male/t3_left.ogg b/web/simon/audio/voice/male/t3_left.ogg
index b14342ef..59adbe81 100644
Binary files a/web/simon/audio/voice/male/t3_left.ogg and b/web/simon/audio/voice/male/t3_left.ogg differ
diff --git a/web/simon/audio/voice/male/t4_right.ogg b/web/simon/audio/voice/male/t4_right.ogg
index 476ad566..08e5c18a 100644
Binary files a/web/simon/audio/voice/male/t4_right.ogg and b/web/simon/audio/voice/male/t4_right.ogg differ
diff --git a/web/simon/audio/voice/male/t5_tap.ogg b/web/simon/audio/voice/male/t5_tap.ogg
index ebc24eb4..7962305f 100644
Binary files a/web/simon/audio/voice/male/t5_tap.ogg and b/web/simon/audio/voice/male/t5_tap.ogg differ
diff --git a/web/simon/audio/voice/male/t6_double.ogg b/web/simon/audio/voice/male/t6_double.ogg
index dc431a26..017a030c 100644
Binary files a/web/simon/audio/voice/male/t6_double.ogg and b/web/simon/audio/voice/male/t6_double.ogg differ
diff --git a/web/simon/audio/voice/male/t7_ready.ogg b/web/simon/audio/voice/male/t7_ready.ogg
index a7fd5330..7f60c2f8 100644
Binary files a/web/simon/audio/voice/male/t7_ready.ogg and b/web/simon/audio/voice/male/t7_ready.ogg differ
diff --git a/web/simon/audio/voice/male/t7_retry.m4a b/web/simon/audio/voice/male/t7_retry.m4a
index 1f855fc7..fb414c06 100644
Binary files a/web/simon/audio/voice/male/t7_retry.m4a and b/web/simon/audio/voice/male/t7_retry.m4a differ
diff --git a/web/simon/audio/voice/male/t7_retry.ogg b/web/simon/audio/voice/male/t7_retry.ogg
index 8553cfe2..018f5937 100644
Binary files a/web/simon/audio/voice/male/t7_retry.ogg and b/web/simon/audio/voice/male/t7_retry.ogg differ
diff --git a/web/simon/audio/voice/male/t_blunt_double.ogg b/web/simon/audio/voice/male/t_blunt_double.ogg
index 5b21303e..382994ff 100644
Binary files a/web/simon/audio/voice/male/t_blunt_double.ogg and b/web/simon/audio/voice/male/t_blunt_double.ogg differ
diff --git a/web/simon/audio/voice/male/t_blunt_down.ogg b/web/simon/audio/voice/male/t_blunt_down.ogg
index d008663e..4198ceaf 100644
Binary files a/web/simon/audio/voice/male/t_blunt_down.ogg and b/web/simon/audio/voice/male/t_blunt_down.ogg differ
diff --git a/web/simon/audio/voice/male/t_blunt_left.ogg b/web/simon/audio/voice/male/t_blunt_left.ogg
index 60929c28..c389b668 100644
Binary files a/web/simon/audio/voice/male/t_blunt_left.ogg and b/web/simon/audio/voice/male/t_blunt_left.ogg differ
diff --git a/web/simon/audio/voice/male/t_blunt_right.ogg b/web/simon/audio/voice/male/t_blunt_right.ogg
index c51609b2..68360df0 100644
Binary files a/web/simon/audio/voice/male/t_blunt_right.ogg and b/web/simon/audio/voice/male/t_blunt_right.ogg differ
diff --git a/web/simon/audio/voice/male/t_blunt_tap.ogg b/web/simon/audio/voice/male/t_blunt_tap.ogg
index 98611729..6ad4d39d 100644
Binary files a/web/simon/audio/voice/male/t_blunt_tap.ogg and b/web/simon/audio/voice/male/t_blunt_tap.ogg differ
diff --git a/web/simon/audio/voice/male/t_blunt_up.ogg b/web/simon/audio/voice/male/t_blunt_up.ogg
index 716969bd..4931c2b8 100644
Binary files a/web/simon/audio/voice/male/t_blunt_up.ogg and b/web/simon/audio/voice/male/t_blunt_up.ogg differ
diff --git a/web/simon/audio/voice/male/t_ok.ogg b/web/simon/audio/voice/male/t_ok.ogg
index a49b4679..f0fc9d62 100644
Binary files a/web/simon/audio/voice/male/t_ok.ogg and b/web/simon/audio/voice/male/t_ok.ogg differ
diff --git a/web/simon/audio/voice/male/t_skip.ogg b/web/simon/audio/voice/male/t_skip.ogg
index b360034b..ab05564d 100644
Binary files a/web/simon/audio/voice/male/t_skip.ogg and b/web/simon/audio/voice/male/t_skip.ogg differ
diff --git a/web/simon/audio/voice/male/t_try.ogg b/web/simon/audio/voice/male/t_try.ogg
index c27b6ba8..3de46b1a 100644
Binary files a/web/simon/audio/voice/male/t_try.ogg and b/web/simon/audio/voice/male/t_try.ogg differ
diff --git a/web/simon/audio/voice/male/t_wrong_double.ogg b/web/simon/audio/voice/male/t_wrong_double.ogg
index 25016ba7..7740cd5d 100644
Binary files a/web/simon/audio/voice/male/t_wrong_double.ogg and b/web/simon/audio/voice/male/t_wrong_double.ogg differ
diff --git a/web/simon/audio/voice/male/t_wrong_down.ogg b/web/simon/audio/voice/male/t_wrong_down.ogg
index 1a2a9be0..e3921484 100644
Binary files a/web/simon/audio/voice/male/t_wrong_down.ogg and b/web/simon/audio/voice/male/t_wrong_down.ogg differ
diff --git a/web/simon/audio/voice/male/t_wrong_left.ogg b/web/simon/audio/voice/male/t_wrong_left.ogg
index c40f4a76..e849c60b 100644
Binary files a/web/simon/audio/voice/male/t_wrong_left.ogg and b/web/simon/audio/voice/male/t_wrong_left.ogg differ
diff --git a/web/simon/audio/voice/male/t_wrong_right.ogg b/web/simon/audio/voice/male/t_wrong_right.ogg
index 436a36de..df1d191c 100644
Binary files a/web/simon/audio/voice/male/t_wrong_right.ogg and b/web/simon/audio/voice/male/t_wrong_right.ogg differ
diff --git a/web/simon/audio/voice/male/t_wrong_tap.ogg b/web/simon/audio/voice/male/t_wrong_tap.ogg
index 25c9c6b3..702bdbf0 100644
Binary files a/web/simon/audio/voice/male/t_wrong_tap.ogg and b/web/simon/audio/voice/male/t_wrong_tap.ogg differ
diff --git a/web/simon/audio/voice/male/t_wrong_up.ogg b/web/simon/audio/voice/male/t_wrong_up.ogg
index 71178c1c..334a502b 100644
Binary files a/web/simon/audio/voice/male/t_wrong_up.ogg and b/web/simon/audio/voice/male/t_wrong_up.ogg differ
diff --git a/web/simon/audio/voice/male/wrong.ogg b/web/simon/audio/voice/male/wrong.ogg
index f5292173..db75742d 100644
Binary files a/web/simon/audio/voice/male/wrong.ogg and b/web/simon/audio/voice/male/wrong.ogg differ
diff --git a/web/simon/audio/voice/male/your_turn.ogg b/web/simon/audio/voice/male/your_turn.ogg
index 740bf0c0..64704a57 100644
Binary files a/web/simon/audio/voice/male/your_turn.ogg and b/web/simon/audio/voice/male/your_turn.ogg differ
diff --git a/web/simon/game.js b/web/simon/game.js
index fa674e85..472f8b7d 100644
--- a/web/simon/game.js
+++ b/web/simon/game.js
@@ -19,10 +19,12 @@
* - 反馈全部改震动:对/错 SUCCESS/ERROR,sfx/correct、wrong、newrecord 已删除;
* sfx/gameover 保留为内容性结束音。
*
- * 设计冲突的处理(02 文档 §4.2 与 §6.3):双击既是六种音色之一(序列可出现
- * doubletap)又是"主动重听"手势。本实现按**上下文**判定:输入阶段若当前期望
- * 输入恰为 doubletap,双击视为答题;否则视为重听(有机会时)。两者不会同时
- * 歧义落空——序列永远可答,重听仅在"不期望双击"时可用。
+ * 设计冲突的处理(round3 synthesis G5 裁定,替代 round2 的双击语境判定):双击是
+ * 六种音色之一(序列可出现 doubletap),历史上又兼「主动重听」。round3 改全局规则:
+ * **input 阶段双击永远=作答(第 6 音色)**——期望恰为 doubletap 判对,否则照常判错,
+ * 不再承担重听;主动重听改绑**上滑**(期望输入恰为 up 时上滑=作答,六手势全是
+ * 答题输入的 00 §5.3 豁免同款)。非输入阶段行为不变(gameover/菜单上滑仍是规则/
+ * 帮助)。同一手势在 input 阶段不再有第二种含义(P1 round2 P0 根治)。
*
* 手势 → 音色映射:
* up 上行琶音 / down 下行低音 / left 左声道弹拨 / right 右声道弹拨 /
@@ -87,6 +89,9 @@ export class SimonGame extends Game {
this._menuIdx = 0;
this._session = 0; // 会话令牌:重开后使旧计时器/语音链回调失效
this._timers = [];
+ // G6(round3):轮结算链尾轻量反馈每局各限 1 次
+ this._clearSaid = false;
+ this._recordSaid = false;
}
start() {
@@ -205,8 +210,9 @@ export class SimonGame extends Game {
if (this.teachIdx + 1 < GESTURES.length) {
this._teachStep(this.teachIdx + 1);
} else {
- // T7:收尾两句 + 机会经济一句(round2 F5:记不住就双击重听、免费两次、
- // 用完扣机会——P1「经济不透明」开局一句话讲清)→ 正式对局
+ // T7:收尾两句 + 机会经济一句(round2 F5 → round3 G5 重录:记不住就
+ // 向上滑重新听、免费两次、用完扣机会——P1「经济不透明」开局一句话
+ // 讲清,且与新手势映射一致)→ 正式对局
this._speakGuarded(['voice/t7_ready', 'voice/t7_retry', 'voice/gd_economy'],
() => this._beginGame(), 20000);
}
@@ -234,6 +240,8 @@ export class SimonGame extends Game {
this.sequence = [];
this.round = 0;
this.chances = 1;
+ this._clearSaid = false; // G6:每局重新封顶
+ this._recordSaid = false;
this._nextRound();
}
@@ -346,9 +354,10 @@ export class SimonGame extends Game {
}
_onInput(g) {
- // 双击的上下文判定(见文件头"设计冲突的处理"):
- // 期望输入是 doubletap → 答题;否则 → 主动重听(耗机会)
- if (g === 'doubletap' && this.sequence[this.inputIdx] !== 'doubletap') {
+ // G5(round3):双击永远=作答(第 6 音色)——期望恰为 doubletap 判对,否则
+ // 照常判错,不再承担重听。主动重听改绑上滑:期望输入恰为 up 时上滑=作答
+ // (六手势全是答题输入,00 §5.3 豁免同款),其余时刻上滑=主动重听(耗机会)。
+ if (g === 'up' && this.sequence[this.inputIdx] !== 'up') {
this._relisten();
return;
}
@@ -390,6 +399,18 @@ export class SimonGame extends Game {
vibrate('pickup');
ids.push('voice/chance_plus');
}
+ // G6(round3):轮结算链尾轻量反馈——gd_clear「漂亮,过了。」每局 1 次;
+ // 本轮完成数超过历史最佳(且确有旧纪录可破)时追加 gd_record「破纪录了。」
+ // 每局 1 次(结算另有 new_record,此处是局中破纪录的即时一刻)。游戏规则句
+ // 随链播(全档位,gd_economy 先例),不走向导通道。
+ if (!this._clearSaid) {
+ this._clearSaid = true;
+ ids.push('voice/gd_clear');
+ }
+ if (!this._recordSaid && this.best > 0 && this.round > this.best) {
+ this._recordSaid = true;
+ ids.push('voice/gd_record');
+ }
this._speakGuarded(ids, () => {
if (s !== this._session) return;
this._timer(() => this._nextRound(), 300);
diff --git a/web/simon/test/playtest.mjs b/web/simon/test/playtest.mjs
index 798c15e5..d5f496cf 100644
--- a/web/simon/test/playtest.mjs
+++ b/web/simon/test/playtest.mjs
@@ -375,6 +375,13 @@ async function answerPastDoubletaps() {
}
}
+/** 把前缀里连续的 up 答掉,直到期望输入非 up(round3 G5:期望恰为 up 时上滑=作答)。 */
+async function answerPastUps() {
+ while (game.phase === 'input' && game.sequence[game.inputIdx] === 'up') {
+ await gesture('up'); // 期望即 up → 答题
+ }
+}
+
// ---------------------------------------------------------------- 第 1-3 轮
section('第 1-3 轮(含单击跳播报、playback 忽略、看门狗)');
assert(game._interval() === 700, '第 1 轮播放间隔 700ms');
@@ -398,7 +405,8 @@ assert(game.chances === 1, '初始 1 次重听机会');
{
const prevSeq = game.sequence;
const exp = game.sequence[0];
- const wrong = GESTURES.find((g) => g !== exp && g !== 'doubletap');
+ // round3 G5:up=重听键,注入错手势时避开(否则触发重听而非判错)
+ const wrong = GESTURES.find((g) => g !== exp && g !== 'doubletap' && g !== 'up');
await gesture(wrong);
assert(game.chances === 0, '答错自动消耗复活:chances 1→0');
assert(game.phase === 'roundend' && played('voice/retry_use'), '播 retry_use');
@@ -415,26 +423,29 @@ assert(game.chances === 1, '每完成 4 轮 chances +1(回到 1)');
assert(played('voice/chance_plus'), '播 chance_plus');
// ---------------------------------------------------------------- 第 5 轮:主动重听 + 边界
-section('第 5 轮:主动重听 / chances=0 双击 / 双击冲突裁定');
+section('第 5 轮:主动重听(上滑)/ chances=0 上滑 / 双击=作答(round3 G5,13 号文档 §8 变更记录)');
await toInputViaSkip(5);
{
+ // round3 G5:input 阶段双击永远=作答,主动重听改绑上滑(期望恰为 up 时上滑=作答)
await answerPastDoubletaps();
+ await answerPastUps(); // 先把期望恰为 up 的音答掉
const relistenCount = playCount('voice/relisten');
- await gesture('doubletap'); // 期望非 doubletap → 主动重听
+ await gesture('up'); // 期望非 up → 主动重听
assert(game.chances === 0, '主动重听耗机会:chances 1→0');
assert(playCount('voice/relisten') === relistenCount + 1 && game.phase === 'roundend', '播 relisten 并重播');
await advanceUntil(() => game.phase === 'input', { desc: '重听重播后回输入' });
assert(game.inputIdx === 0, '重听后输入进度清零');
}
{
- // chances=0 时双击非期望手势:不判错、播 chances_out
+ // chances=0 时上滑非期望手势:不判错、播 chances_out
await answerPastDoubletaps();
+ await answerPastUps();
const round = game.round;
const idx = game.inputIdx;
const coCount = playCount('voice/chances_out');
- await gesture('doubletap');
- assert(game.phase === 'input' && game.round === round && game.inputIdx === idx, 'chances=0 双击非期望:不判错(round/inputIdx 不变)');
- assert(playCount('voice/chances_out') === coCount + 1, 'chances=0 双击播 chances_out');
+ await gesture('up');
+ assert(game.phase === 'input' && game.round === round && game.inputIdx === idx, 'chances=0 上滑非期望:不判错(round/inputIdx 不变)');
+ assert(playCount('voice/chances_out') === coCount + 1, 'chances=0 上滑播 chances_out');
assert(game.chances === 0, 'chances 不变(不为负)');
}
// 答完第 5 轮(途中验证双击=答题);若本轮没遇到 doubletap 则继续往下轮找
@@ -459,7 +470,8 @@ assert(game.chances === 0, '复活已耗尽');
const finalRound = game.round;
{
const exp = game.sequence[game.inputIdx];
- const wrong = GESTURES.find((g) => g !== exp && g !== 'doubletap');
+ // round3 G5:up=重听键,注入错手势时避开
+ const wrong = GESTURES.find((g) => g !== exp && g !== 'doubletap' && g !== 'up');
await gesture(wrong);
}
assert(game.phase === 'gameover', 'chances=0 答错 → gameover');
diff --git a/web/space/audio/voice/female/dir_down.m4a b/web/space/audio/voice/female/dir_down.m4a
new file mode 100644
index 00000000..b954baa2
Binary files /dev/null and b/web/space/audio/voice/female/dir_down.m4a differ
diff --git a/web/space/audio/voice/female/dir_down.ogg b/web/space/audio/voice/female/dir_down.ogg
new file mode 100644
index 00000000..21399ebe
Binary files /dev/null and b/web/space/audio/voice/female/dir_down.ogg differ
diff --git a/web/space/audio/voice/female/dir_left.m4a b/web/space/audio/voice/female/dir_left.m4a
new file mode 100644
index 00000000..6d4d5946
Binary files /dev/null and b/web/space/audio/voice/female/dir_left.m4a differ
diff --git a/web/space/audio/voice/female/dir_left.ogg b/web/space/audio/voice/female/dir_left.ogg
new file mode 100644
index 00000000..1d6fe2a9
Binary files /dev/null and b/web/space/audio/voice/female/dir_left.ogg differ
diff --git a/web/space/audio/voice/female/dir_right.m4a b/web/space/audio/voice/female/dir_right.m4a
new file mode 100644
index 00000000..a2d62873
Binary files /dev/null and b/web/space/audio/voice/female/dir_right.m4a differ
diff --git a/web/space/audio/voice/female/dir_right.ogg b/web/space/audio/voice/female/dir_right.ogg
new file mode 100644
index 00000000..ea2e7874
Binary files /dev/null and b/web/space/audio/voice/female/dir_right.ogg differ
diff --git a/web/space/audio/voice/female/dir_up.m4a b/web/space/audio/voice/female/dir_up.m4a
new file mode 100644
index 00000000..b688fde1
Binary files /dev/null and b/web/space/audio/voice/female/dir_up.m4a differ
diff --git a/web/space/audio/voice/female/dir_up.ogg b/web/space/audio/voice/female/dir_up.ogg
new file mode 100644
index 00000000..cecf0769
Binary files /dev/null and b/web/space/audio/voice/female/dir_up.ogg differ
diff --git a/web/space/audio/voice/female/dodge_1.ogg b/web/space/audio/voice/female/dodge_1.ogg
index 3c8d808d..0756b9d4 100644
Binary files a/web/space/audio/voice/female/dodge_1.ogg and b/web/space/audio/voice/female/dodge_1.ogg differ
diff --git a/web/space/audio/voice/female/dodge_2.ogg b/web/space/audio/voice/female/dodge_2.ogg
index fd2a7963..5dd841bf 100644
Binary files a/web/space/audio/voice/female/dodge_2.ogg and b/web/space/audio/voice/female/dodge_2.ogg differ
diff --git a/web/space/audio/voice/female/dodge_3.ogg b/web/space/audio/voice/female/dodge_3.ogg
index 9adfd7e7..dcf080a9 100644
Binary files a/web/space/audio/voice/female/dodge_3.ogg and b/web/space/audio/voice/female/dodge_3.ogg differ
diff --git a/web/space/audio/voice/female/dodge_4.ogg b/web/space/audio/voice/female/dodge_4.ogg
index 3999b115..ee02e1c9 100644
Binary files a/web/space/audio/voice/female/dodge_4.ogg and b/web/space/audio/voice/female/dodge_4.ogg differ
diff --git a/web/space/audio/voice/female/drill_done.ogg b/web/space/audio/voice/female/drill_done.ogg
index d438685d..79c7753b 100644
Binary files a/web/space/audio/voice/female/drill_done.ogg and b/web/space/audio/voice/female/drill_done.ogg differ
diff --git a/web/space/audio/voice/female/drill_down.ogg b/web/space/audio/voice/female/drill_down.ogg
index 003f991f..c8afe457 100644
Binary files a/web/space/audio/voice/female/drill_down.ogg and b/web/space/audio/voice/female/drill_down.ogg differ
diff --git a/web/space/audio/voice/female/drill_good.ogg b/web/space/audio/voice/female/drill_good.ogg
index 7226008d..58b2b8f7 100644
Binary files a/web/space/audio/voice/female/drill_good.ogg and b/web/space/audio/voice/female/drill_good.ogg differ
diff --git a/web/space/audio/voice/female/drill_left.ogg b/web/space/audio/voice/female/drill_left.ogg
index 451e229b..91104ed0 100644
Binary files a/web/space/audio/voice/female/drill_left.ogg and b/web/space/audio/voice/female/drill_left.ogg differ
diff --git a/web/space/audio/voice/female/drill_moveon.ogg b/web/space/audio/voice/female/drill_moveon.ogg
index 2062de2c..127515de 100644
Binary files a/web/space/audio/voice/female/drill_moveon.ogg and b/web/space/audio/voice/female/drill_moveon.ogg differ
diff --git a/web/space/audio/voice/female/drill_retry_down.ogg b/web/space/audio/voice/female/drill_retry_down.ogg
index ce54e446..5e3dbb4c 100644
Binary files a/web/space/audio/voice/female/drill_retry_down.ogg and b/web/space/audio/voice/female/drill_retry_down.ogg differ
diff --git a/web/space/audio/voice/female/drill_retry_left.ogg b/web/space/audio/voice/female/drill_retry_left.ogg
index bd16a2b3..8d12aaa0 100644
Binary files a/web/space/audio/voice/female/drill_retry_left.ogg and b/web/space/audio/voice/female/drill_retry_left.ogg differ
diff --git a/web/space/audio/voice/female/drill_retry_right.ogg b/web/space/audio/voice/female/drill_retry_right.ogg
index 3f621d5e..192a6d03 100644
Binary files a/web/space/audio/voice/female/drill_retry_right.ogg and b/web/space/audio/voice/female/drill_retry_right.ogg differ
diff --git a/web/space/audio/voice/female/drill_retry_up.ogg b/web/space/audio/voice/female/drill_retry_up.ogg
index f561d914..c61ae6f3 100644
Binary files a/web/space/audio/voice/female/drill_retry_up.ogg and b/web/space/audio/voice/female/drill_retry_up.ogg differ
diff --git a/web/space/audio/voice/female/drill_right.ogg b/web/space/audio/voice/female/drill_right.ogg
index 8fabfbd8..e46e6368 100644
Binary files a/web/space/audio/voice/female/drill_right.ogg and b/web/space/audio/voice/female/drill_right.ogg differ
diff --git a/web/space/audio/voice/female/drill_rule.ogg b/web/space/audio/voice/female/drill_rule.ogg
index bfd917b0..690a3b61 100644
Binary files a/web/space/audio/voice/female/drill_rule.ogg and b/web/space/audio/voice/female/drill_rule.ogg differ
diff --git a/web/space/audio/voice/female/drill_skip.ogg b/web/space/audio/voice/female/drill_skip.ogg
index 1226adde..96223092 100644
Binary files a/web/space/audio/voice/female/drill_skip.ogg and b/web/space/audio/voice/female/drill_skip.ogg differ
diff --git a/web/space/audio/voice/female/drill_up.ogg b/web/space/audio/voice/female/drill_up.ogg
index eea2746a..298df44a 100644
Binary files a/web/space/audio/voice/female/drill_up.ogg and b/web/space/audio/voice/female/drill_up.ogg differ
diff --git a/web/space/audio/voice/female/drill_welcome.ogg b/web/space/audio/voice/female/drill_welcome.ogg
index c6315b91..0d81edac 100644
Binary files a/web/space/audio/voice/female/drill_welcome.ogg and b/web/space/audio/voice/female/drill_welcome.ogg differ
diff --git a/web/space/audio/voice/female/feat_boost.ogg b/web/space/audio/voice/female/feat_boost.ogg
index a261fe48..7391b27a 100644
Binary files a/web/space/audio/voice/female/feat_boost.ogg and b/web/space/audio/voice/female/feat_boost.ogg differ
diff --git a/web/space/audio/voice/female/feat_boost_done.ogg b/web/space/audio/voice/female/feat_boost_done.ogg
index ef6c3e83..d7adcd0a 100644
Binary files a/web/space/audio/voice/female/feat_boost_done.ogg and b/web/space/audio/voice/female/feat_boost_done.ogg differ
diff --git a/web/space/audio/voice/female/feat_shield.ogg b/web/space/audio/voice/female/feat_shield.ogg
index f7c9c128..82fdd707 100644
Binary files a/web/space/audio/voice/female/feat_shield.ogg and b/web/space/audio/voice/female/feat_shield.ogg differ
diff --git a/web/space/audio/voice/female/feat_shield_done.ogg b/web/space/audio/voice/female/feat_shield_done.ogg
index 8e9434b1..eade815c 100644
Binary files a/web/space/audio/voice/female/feat_shield_done.ogg and b/web/space/audio/voice/female/feat_shield_done.ogg differ
diff --git a/web/space/audio/voice/female/gd_hit_hint.ogg b/web/space/audio/voice/female/gd_hit_hint.ogg
index 250a1280..5c459a10 100644
Binary files a/web/space/audio/voice/female/gd_hit_hint.ogg and b/web/space/audio/voice/female/gd_hit_hint.ogg differ
diff --git a/web/space/audio/voice/female/gd_last_life.ogg b/web/space/audio/voice/female/gd_last_life.ogg
index 6162f036..6d7aa831 100644
Binary files a/web/space/audio/voice/female/gd_last_life.ogg and b/web/space/audio/voice/female/gd_last_life.ogg differ
diff --git a/web/space/audio/voice/female/help_recap.ogg b/web/space/audio/voice/female/help_recap.ogg
index 58fb6e56..ef64883c 100644
Binary files a/web/space/audio/voice/female/help_recap.ogg and b/web/space/audio/voice/female/help_recap.ogg differ
diff --git a/web/space/audio/voice/female/hit_down.ogg b/web/space/audio/voice/female/hit_down.ogg
index e6b7cf53..6b390ffc 100644
Binary files a/web/space/audio/voice/female/hit_down.ogg and b/web/space/audio/voice/female/hit_down.ogg differ
diff --git a/web/space/audio/voice/female/hit_last.ogg b/web/space/audio/voice/female/hit_last.ogg
index 787db9b7..0ea48763 100644
Binary files a/web/space/audio/voice/female/hit_last.ogg and b/web/space/audio/voice/female/hit_last.ogg differ
diff --git a/web/space/audio/voice/female/hit_left.ogg b/web/space/audio/voice/female/hit_left.ogg
index beb4ca55..95fa0614 100644
Binary files a/web/space/audio/voice/female/hit_left.ogg and b/web/space/audio/voice/female/hit_left.ogg differ
diff --git a/web/space/audio/voice/female/hit_right.ogg b/web/space/audio/voice/female/hit_right.ogg
index 9d2b0aef..989339f2 100644
Binary files a/web/space/audio/voice/female/hit_right.ogg and b/web/space/audio/voice/female/hit_right.ogg differ
diff --git a/web/space/audio/voice/female/hit_up.ogg b/web/space/audio/voice/female/hit_up.ogg
index 2efcb3e9..63854da7 100644
Binary files a/web/space/audio/voice/female/hit_up.ogg and b/web/space/audio/voice/female/hit_up.ogg differ
diff --git a/web/space/audio/voice/female/menu_help.ogg b/web/space/audio/voice/female/menu_help.ogg
index f26b4c7b..70133436 100644
Binary files a/web/space/audio/voice/female/menu_help.ogg and b/web/space/audio/voice/female/menu_help.ogg differ
diff --git a/web/space/audio/voice/female/menu_lobby.ogg b/web/space/audio/voice/female/menu_lobby.ogg
index 4decea35..bd82b38c 100644
Binary files a/web/space/audio/voice/female/menu_lobby.ogg and b/web/space/audio/voice/female/menu_lobby.ogg differ
diff --git a/web/space/audio/voice/female/menu_main.ogg b/web/space/audio/voice/female/menu_main.ogg
index 40336488..cc88d134 100644
Binary files a/web/space/audio/voice/female/menu_main.ogg and b/web/space/audio/voice/female/menu_main.ogg differ
diff --git a/web/space/audio/voice/female/menu_resume.ogg b/web/space/audio/voice/female/menu_resume.ogg
index e486aeb1..6c1d9cea 100644
Binary files a/web/space/audio/voice/female/menu_resume.ogg and b/web/space/audio/voice/female/menu_resume.ogg differ
diff --git a/web/space/audio/voice/female/ms_10.ogg b/web/space/audio/voice/female/ms_10.ogg
index 60f01dfb..babd8f43 100644
Binary files a/web/space/audio/voice/female/ms_10.ogg and b/web/space/audio/voice/female/ms_10.ogg differ
diff --git a/web/space/audio/voice/female/ms_100.ogg b/web/space/audio/voice/female/ms_100.ogg
index fae5e6e3..9c19f688 100644
Binary files a/web/space/audio/voice/female/ms_100.ogg and b/web/space/audio/voice/female/ms_100.ogg differ
diff --git a/web/space/audio/voice/female/ms_25.ogg b/web/space/audio/voice/female/ms_25.ogg
index 472456d8..3617bc10 100644
Binary files a/web/space/audio/voice/female/ms_25.ogg and b/web/space/audio/voice/female/ms_25.ogg differ
diff --git a/web/space/audio/voice/female/ms_50.ogg b/web/space/audio/voice/female/ms_50.ogg
index 51832307..b8b5fb37 100644
Binary files a/web/space/audio/voice/female/ms_50.ogg and b/web/space/audio/voice/female/ms_50.ogg differ
diff --git a/web/space/audio/voice/female/new_record.ogg b/web/space/audio/voice/female/new_record.ogg
index 684aca5f..e3873b88 100644
Binary files a/web/space/audio/voice/female/new_record.ogg and b/web/space/audio/voice/female/new_record.ogg differ
diff --git a/web/space/audio/voice/female/paused.ogg b/web/space/audio/voice/female/paused.ogg
index e6b5c25c..abaa864e 100644
Binary files a/web/space/audio/voice/female/paused.ogg and b/web/space/audio/voice/female/paused.ogg differ
diff --git a/web/space/audio/voice/female/protect_down.ogg b/web/space/audio/voice/female/protect_down.ogg
index e8def423..d4220e1f 100644
Binary files a/web/space/audio/voice/female/protect_down.ogg and b/web/space/audio/voice/female/protect_down.ogg differ
diff --git a/web/space/audio/voice/female/protect_end.ogg b/web/space/audio/voice/female/protect_end.ogg
index 610c58a5..a2aa8360 100644
Binary files a/web/space/audio/voice/female/protect_end.ogg and b/web/space/audio/voice/female/protect_end.ogg differ
diff --git a/web/space/audio/voice/female/protect_left.ogg b/web/space/audio/voice/female/protect_left.ogg
index 98db3d18..e8626ee6 100644
Binary files a/web/space/audio/voice/female/protect_left.ogg and b/web/space/audio/voice/female/protect_left.ogg differ
diff --git a/web/space/audio/voice/female/protect_right.ogg b/web/space/audio/voice/female/protect_right.ogg
index 619ccab6..06fdd071 100644
Binary files a/web/space/audio/voice/female/protect_right.ogg and b/web/space/audio/voice/female/protect_right.ogg differ
diff --git a/web/space/audio/voice/female/protect_up.ogg b/web/space/audio/voice/female/protect_up.ogg
index 74c9bb2b..1b719c91 100644
Binary files a/web/space/audio/voice/female/protect_up.ogg and b/web/space/audio/voice/female/protect_up.ogg differ
diff --git a/web/space/audio/voice/female/restart_hint.ogg b/web/space/audio/voice/female/restart_hint.ogg
index b654115a..41679109 100644
Binary files a/web/space/audio/voice/female/restart_hint.ogg and b/web/space/audio/voice/female/restart_hint.ogg differ
diff --git a/web/space/audio/voice/female/second_run_ask.ogg b/web/space/audio/voice/female/second_run_ask.ogg
index 0914b5a5..d11bae89 100644
Binary files a/web/space/audio/voice/female/second_run_ask.ogg and b/web/space/audio/voice/female/second_run_ask.ogg differ
diff --git a/web/space/audio/voice/female/settings_hint.ogg b/web/space/audio/voice/female/settings_hint.ogg
index 60957db3..4b105570 100644
Binary files a/web/space/audio/voice/female/settings_hint.ogg and b/web/space/audio/voice/female/settings_hint.ogg differ
diff --git a/web/space/audio/voice/female/shield_block.ogg b/web/space/audio/voice/female/shield_block.ogg
index 169b22d6..304b824c 100644
Binary files a/web/space/audio/voice/female/shield_block.ogg and b/web/space/audio/voice/female/shield_block.ogg differ
diff --git a/web/space/audio/voice/female/shield_ready.ogg b/web/space/audio/voice/female/shield_ready.ogg
index bfeedc65..1fbddc39 100644
Binary files a/web/space/audio/voice/female/shield_ready.ogg and b/web/space/audio/voice/female/shield_ready.ogg differ
diff --git a/web/space/audio/voice/female/skip_hint.ogg b/web/space/audio/voice/female/skip_hint.ogg
index d83298cb..dc3fbb0c 100644
Binary files a/web/space/audio/voice/female/skip_hint.ogg and b/web/space/audio/voice/female/skip_hint.ogg differ
diff --git a/web/space/audio/voice/female/time_1.ogg b/web/space/audio/voice/female/time_1.ogg
index cadd4ea2..684d3718 100644
Binary files a/web/space/audio/voice/female/time_1.ogg and b/web/space/audio/voice/female/time_1.ogg differ
diff --git a/web/space/audio/voice/female/time_2.ogg b/web/space/audio/voice/female/time_2.ogg
index 164136bf..3d30fa1d 100644
Binary files a/web/space/audio/voice/female/time_2.ogg and b/web/space/audio/voice/female/time_2.ogg differ
diff --git a/web/space/audio/voice/female/time_3.ogg b/web/space/audio/voice/female/time_3.ogg
index 35a3dd4b..5925aceb 100644
Binary files a/web/space/audio/voice/female/time_3.ogg and b/web/space/audio/voice/female/time_3.ogg differ
diff --git a/web/space/audio/voice/female/time_4.ogg b/web/space/audio/voice/female/time_4.ogg
index 68715cfb..cc6ba83d 100644
Binary files a/web/space/audio/voice/female/time_4.ogg and b/web/space/audio/voice/female/time_4.ogg differ
diff --git a/web/space/audio/voice/male/dir_down.m4a b/web/space/audio/voice/male/dir_down.m4a
new file mode 100644
index 00000000..618bdda0
Binary files /dev/null and b/web/space/audio/voice/male/dir_down.m4a differ
diff --git a/web/space/audio/voice/male/dir_down.ogg b/web/space/audio/voice/male/dir_down.ogg
new file mode 100644
index 00000000..df1698a1
Binary files /dev/null and b/web/space/audio/voice/male/dir_down.ogg differ
diff --git a/web/space/audio/voice/male/dir_left.m4a b/web/space/audio/voice/male/dir_left.m4a
new file mode 100644
index 00000000..ce78fb16
Binary files /dev/null and b/web/space/audio/voice/male/dir_left.m4a differ
diff --git a/web/space/audio/voice/male/dir_left.ogg b/web/space/audio/voice/male/dir_left.ogg
new file mode 100644
index 00000000..5b304bf1
Binary files /dev/null and b/web/space/audio/voice/male/dir_left.ogg differ
diff --git a/web/space/audio/voice/male/dir_right.m4a b/web/space/audio/voice/male/dir_right.m4a
new file mode 100644
index 00000000..45d7cb54
Binary files /dev/null and b/web/space/audio/voice/male/dir_right.m4a differ
diff --git a/web/space/audio/voice/male/dir_right.ogg b/web/space/audio/voice/male/dir_right.ogg
new file mode 100644
index 00000000..a6aca1c3
Binary files /dev/null and b/web/space/audio/voice/male/dir_right.ogg differ
diff --git a/web/space/audio/voice/male/dir_up.m4a b/web/space/audio/voice/male/dir_up.m4a
new file mode 100644
index 00000000..cad4085f
Binary files /dev/null and b/web/space/audio/voice/male/dir_up.m4a differ
diff --git a/web/space/audio/voice/male/dir_up.ogg b/web/space/audio/voice/male/dir_up.ogg
new file mode 100644
index 00000000..09855ca9
Binary files /dev/null and b/web/space/audio/voice/male/dir_up.ogg differ
diff --git a/web/space/audio/voice/male/dodge_1.ogg b/web/space/audio/voice/male/dodge_1.ogg
index 508e21b8..0bd11396 100644
Binary files a/web/space/audio/voice/male/dodge_1.ogg and b/web/space/audio/voice/male/dodge_1.ogg differ
diff --git a/web/space/audio/voice/male/dodge_2.ogg b/web/space/audio/voice/male/dodge_2.ogg
index 8165a201..47e1435d 100644
Binary files a/web/space/audio/voice/male/dodge_2.ogg and b/web/space/audio/voice/male/dodge_2.ogg differ
diff --git a/web/space/audio/voice/male/dodge_3.ogg b/web/space/audio/voice/male/dodge_3.ogg
index 963d0c73..71dbf169 100644
Binary files a/web/space/audio/voice/male/dodge_3.ogg and b/web/space/audio/voice/male/dodge_3.ogg differ
diff --git a/web/space/audio/voice/male/dodge_4.ogg b/web/space/audio/voice/male/dodge_4.ogg
index 60f77a8d..9513208f 100644
Binary files a/web/space/audio/voice/male/dodge_4.ogg and b/web/space/audio/voice/male/dodge_4.ogg differ
diff --git a/web/space/audio/voice/male/drill_done.ogg b/web/space/audio/voice/male/drill_done.ogg
index c48ec145..61944ed0 100644
Binary files a/web/space/audio/voice/male/drill_done.ogg and b/web/space/audio/voice/male/drill_done.ogg differ
diff --git a/web/space/audio/voice/male/drill_down.ogg b/web/space/audio/voice/male/drill_down.ogg
index 65562882..ae219e75 100644
Binary files a/web/space/audio/voice/male/drill_down.ogg and b/web/space/audio/voice/male/drill_down.ogg differ
diff --git a/web/space/audio/voice/male/drill_good.ogg b/web/space/audio/voice/male/drill_good.ogg
index 1ebb8adb..59c55ab3 100644
Binary files a/web/space/audio/voice/male/drill_good.ogg and b/web/space/audio/voice/male/drill_good.ogg differ
diff --git a/web/space/audio/voice/male/drill_left.ogg b/web/space/audio/voice/male/drill_left.ogg
index 910e6fae..eaf35a0a 100644
Binary files a/web/space/audio/voice/male/drill_left.ogg and b/web/space/audio/voice/male/drill_left.ogg differ
diff --git a/web/space/audio/voice/male/drill_moveon.ogg b/web/space/audio/voice/male/drill_moveon.ogg
index a00dca76..14cfa727 100644
Binary files a/web/space/audio/voice/male/drill_moveon.ogg and b/web/space/audio/voice/male/drill_moveon.ogg differ
diff --git a/web/space/audio/voice/male/drill_retry_down.ogg b/web/space/audio/voice/male/drill_retry_down.ogg
index 81628924..74ba6aa7 100644
Binary files a/web/space/audio/voice/male/drill_retry_down.ogg and b/web/space/audio/voice/male/drill_retry_down.ogg differ
diff --git a/web/space/audio/voice/male/drill_retry_left.ogg b/web/space/audio/voice/male/drill_retry_left.ogg
index be57cf6b..3ecddf8a 100644
Binary files a/web/space/audio/voice/male/drill_retry_left.ogg and b/web/space/audio/voice/male/drill_retry_left.ogg differ
diff --git a/web/space/audio/voice/male/drill_retry_right.ogg b/web/space/audio/voice/male/drill_retry_right.ogg
index 7403e3e6..87547481 100644
Binary files a/web/space/audio/voice/male/drill_retry_right.ogg and b/web/space/audio/voice/male/drill_retry_right.ogg differ
diff --git a/web/space/audio/voice/male/drill_retry_up.ogg b/web/space/audio/voice/male/drill_retry_up.ogg
index e1274df3..a053458d 100644
Binary files a/web/space/audio/voice/male/drill_retry_up.ogg and b/web/space/audio/voice/male/drill_retry_up.ogg differ
diff --git a/web/space/audio/voice/male/drill_right.ogg b/web/space/audio/voice/male/drill_right.ogg
index 2432dc92..b24e2613 100644
Binary files a/web/space/audio/voice/male/drill_right.ogg and b/web/space/audio/voice/male/drill_right.ogg differ
diff --git a/web/space/audio/voice/male/drill_rule.ogg b/web/space/audio/voice/male/drill_rule.ogg
index eb180b73..d15c62c6 100644
Binary files a/web/space/audio/voice/male/drill_rule.ogg and b/web/space/audio/voice/male/drill_rule.ogg differ
diff --git a/web/space/audio/voice/male/drill_skip.ogg b/web/space/audio/voice/male/drill_skip.ogg
index f31b7417..3dea61b6 100644
Binary files a/web/space/audio/voice/male/drill_skip.ogg and b/web/space/audio/voice/male/drill_skip.ogg differ
diff --git a/web/space/audio/voice/male/drill_up.ogg b/web/space/audio/voice/male/drill_up.ogg
index a69bdc18..5085d9a2 100644
Binary files a/web/space/audio/voice/male/drill_up.ogg and b/web/space/audio/voice/male/drill_up.ogg differ
diff --git a/web/space/audio/voice/male/drill_welcome.ogg b/web/space/audio/voice/male/drill_welcome.ogg
index f2cc3d0f..ddef8d9c 100644
Binary files a/web/space/audio/voice/male/drill_welcome.ogg and b/web/space/audio/voice/male/drill_welcome.ogg differ
diff --git a/web/space/audio/voice/male/feat_boost.ogg b/web/space/audio/voice/male/feat_boost.ogg
index ca853946..9f02fa03 100644
Binary files a/web/space/audio/voice/male/feat_boost.ogg and b/web/space/audio/voice/male/feat_boost.ogg differ
diff --git a/web/space/audio/voice/male/feat_boost_done.ogg b/web/space/audio/voice/male/feat_boost_done.ogg
index 8ea1f830..5577a69e 100644
Binary files a/web/space/audio/voice/male/feat_boost_done.ogg and b/web/space/audio/voice/male/feat_boost_done.ogg differ
diff --git a/web/space/audio/voice/male/feat_shield.ogg b/web/space/audio/voice/male/feat_shield.ogg
index cb4fdc3b..26d83819 100644
Binary files a/web/space/audio/voice/male/feat_shield.ogg and b/web/space/audio/voice/male/feat_shield.ogg differ
diff --git a/web/space/audio/voice/male/feat_shield_done.ogg b/web/space/audio/voice/male/feat_shield_done.ogg
index 6e615885..44779aba 100644
Binary files a/web/space/audio/voice/male/feat_shield_done.ogg and b/web/space/audio/voice/male/feat_shield_done.ogg differ
diff --git a/web/space/audio/voice/male/gd_hit_hint.ogg b/web/space/audio/voice/male/gd_hit_hint.ogg
index 569ba9ee..53bc6629 100644
Binary files a/web/space/audio/voice/male/gd_hit_hint.ogg and b/web/space/audio/voice/male/gd_hit_hint.ogg differ
diff --git a/web/space/audio/voice/male/gd_last_life.ogg b/web/space/audio/voice/male/gd_last_life.ogg
index 9c184d63..595348d0 100644
Binary files a/web/space/audio/voice/male/gd_last_life.ogg and b/web/space/audio/voice/male/gd_last_life.ogg differ
diff --git a/web/space/audio/voice/male/help_recap.ogg b/web/space/audio/voice/male/help_recap.ogg
index eb13ed7c..f672a85c 100644
Binary files a/web/space/audio/voice/male/help_recap.ogg and b/web/space/audio/voice/male/help_recap.ogg differ
diff --git a/web/space/audio/voice/male/hit_down.ogg b/web/space/audio/voice/male/hit_down.ogg
index f26c03e6..f9f10e25 100644
Binary files a/web/space/audio/voice/male/hit_down.ogg and b/web/space/audio/voice/male/hit_down.ogg differ
diff --git a/web/space/audio/voice/male/hit_last.ogg b/web/space/audio/voice/male/hit_last.ogg
index e3608264..b791372f 100644
Binary files a/web/space/audio/voice/male/hit_last.ogg and b/web/space/audio/voice/male/hit_last.ogg differ
diff --git a/web/space/audio/voice/male/hit_left.ogg b/web/space/audio/voice/male/hit_left.ogg
index d3fa8520..c9f8d163 100644
Binary files a/web/space/audio/voice/male/hit_left.ogg and b/web/space/audio/voice/male/hit_left.ogg differ
diff --git a/web/space/audio/voice/male/hit_right.ogg b/web/space/audio/voice/male/hit_right.ogg
index 751e4813..e9172264 100644
Binary files a/web/space/audio/voice/male/hit_right.ogg and b/web/space/audio/voice/male/hit_right.ogg differ
diff --git a/web/space/audio/voice/male/hit_up.ogg b/web/space/audio/voice/male/hit_up.ogg
index 2b093264..ea748f29 100644
Binary files a/web/space/audio/voice/male/hit_up.ogg and b/web/space/audio/voice/male/hit_up.ogg differ
diff --git a/web/space/audio/voice/male/menu_help.ogg b/web/space/audio/voice/male/menu_help.ogg
index 4f6046f5..6d6dd74d 100644
Binary files a/web/space/audio/voice/male/menu_help.ogg and b/web/space/audio/voice/male/menu_help.ogg differ
diff --git a/web/space/audio/voice/male/menu_lobby.ogg b/web/space/audio/voice/male/menu_lobby.ogg
index 2a02eb9b..4b13cdef 100644
Binary files a/web/space/audio/voice/male/menu_lobby.ogg and b/web/space/audio/voice/male/menu_lobby.ogg differ
diff --git a/web/space/audio/voice/male/menu_main.ogg b/web/space/audio/voice/male/menu_main.ogg
index b65c374e..5d2d515b 100644
Binary files a/web/space/audio/voice/male/menu_main.ogg and b/web/space/audio/voice/male/menu_main.ogg differ
diff --git a/web/space/audio/voice/male/menu_resume.ogg b/web/space/audio/voice/male/menu_resume.ogg
index d5ffeda5..6c156aec 100644
Binary files a/web/space/audio/voice/male/menu_resume.ogg and b/web/space/audio/voice/male/menu_resume.ogg differ
diff --git a/web/space/audio/voice/male/ms_10.ogg b/web/space/audio/voice/male/ms_10.ogg
index d33513fa..0b9cd3cb 100644
Binary files a/web/space/audio/voice/male/ms_10.ogg and b/web/space/audio/voice/male/ms_10.ogg differ
diff --git a/web/space/audio/voice/male/ms_100.ogg b/web/space/audio/voice/male/ms_100.ogg
index 1737162d..d38bad99 100644
Binary files a/web/space/audio/voice/male/ms_100.ogg and b/web/space/audio/voice/male/ms_100.ogg differ
diff --git a/web/space/audio/voice/male/ms_25.ogg b/web/space/audio/voice/male/ms_25.ogg
index 11f462a2..825d7c76 100644
Binary files a/web/space/audio/voice/male/ms_25.ogg and b/web/space/audio/voice/male/ms_25.ogg differ
diff --git a/web/space/audio/voice/male/ms_50.ogg b/web/space/audio/voice/male/ms_50.ogg
index 44efbd00..aad4c049 100644
Binary files a/web/space/audio/voice/male/ms_50.ogg and b/web/space/audio/voice/male/ms_50.ogg differ
diff --git a/web/space/audio/voice/male/new_record.ogg b/web/space/audio/voice/male/new_record.ogg
index cf4b7ded..9f6b5c4e 100644
Binary files a/web/space/audio/voice/male/new_record.ogg and b/web/space/audio/voice/male/new_record.ogg differ
diff --git a/web/space/audio/voice/male/paused.ogg b/web/space/audio/voice/male/paused.ogg
index 7e00000c..458eb57b 100644
Binary files a/web/space/audio/voice/male/paused.ogg and b/web/space/audio/voice/male/paused.ogg differ
diff --git a/web/space/audio/voice/male/protect_down.ogg b/web/space/audio/voice/male/protect_down.ogg
index 5d07eed0..8f5ef0ae 100644
Binary files a/web/space/audio/voice/male/protect_down.ogg and b/web/space/audio/voice/male/protect_down.ogg differ
diff --git a/web/space/audio/voice/male/protect_end.ogg b/web/space/audio/voice/male/protect_end.ogg
index 37ce4d49..57c35c01 100644
Binary files a/web/space/audio/voice/male/protect_end.ogg and b/web/space/audio/voice/male/protect_end.ogg differ
diff --git a/web/space/audio/voice/male/protect_left.ogg b/web/space/audio/voice/male/protect_left.ogg
index bdda8cdd..edef54fd 100644
Binary files a/web/space/audio/voice/male/protect_left.ogg and b/web/space/audio/voice/male/protect_left.ogg differ
diff --git a/web/space/audio/voice/male/protect_right.ogg b/web/space/audio/voice/male/protect_right.ogg
index c1903a7d..55f2f3b1 100644
Binary files a/web/space/audio/voice/male/protect_right.ogg and b/web/space/audio/voice/male/protect_right.ogg differ
diff --git a/web/space/audio/voice/male/protect_up.ogg b/web/space/audio/voice/male/protect_up.ogg
index 9ba3eb76..125f71c8 100644
Binary files a/web/space/audio/voice/male/protect_up.ogg and b/web/space/audio/voice/male/protect_up.ogg differ
diff --git a/web/space/audio/voice/male/restart_hint.ogg b/web/space/audio/voice/male/restart_hint.ogg
index 84fcaf66..e793eb6b 100644
Binary files a/web/space/audio/voice/male/restart_hint.ogg and b/web/space/audio/voice/male/restart_hint.ogg differ
diff --git a/web/space/audio/voice/male/second_run_ask.ogg b/web/space/audio/voice/male/second_run_ask.ogg
index 6a0cdd62..34a6717b 100644
Binary files a/web/space/audio/voice/male/second_run_ask.ogg and b/web/space/audio/voice/male/second_run_ask.ogg differ
diff --git a/web/space/audio/voice/male/settings_hint.ogg b/web/space/audio/voice/male/settings_hint.ogg
index 14e209bc..4c30cb0f 100644
Binary files a/web/space/audio/voice/male/settings_hint.ogg and b/web/space/audio/voice/male/settings_hint.ogg differ
diff --git a/web/space/audio/voice/male/shield_block.ogg b/web/space/audio/voice/male/shield_block.ogg
index fb44e807..7bd8f5a5 100644
Binary files a/web/space/audio/voice/male/shield_block.ogg and b/web/space/audio/voice/male/shield_block.ogg differ
diff --git a/web/space/audio/voice/male/shield_ready.ogg b/web/space/audio/voice/male/shield_ready.ogg
index 949b82bf..38cb2ac6 100644
Binary files a/web/space/audio/voice/male/shield_ready.ogg and b/web/space/audio/voice/male/shield_ready.ogg differ
diff --git a/web/space/audio/voice/male/skip_hint.ogg b/web/space/audio/voice/male/skip_hint.ogg
index 57c6a401..2e2bbff4 100644
Binary files a/web/space/audio/voice/male/skip_hint.ogg and b/web/space/audio/voice/male/skip_hint.ogg differ
diff --git a/web/space/audio/voice/male/time_1.ogg b/web/space/audio/voice/male/time_1.ogg
index 53bbf3a3..6a43f5f9 100644
Binary files a/web/space/audio/voice/male/time_1.ogg and b/web/space/audio/voice/male/time_1.ogg differ
diff --git a/web/space/audio/voice/male/time_2.ogg b/web/space/audio/voice/male/time_2.ogg
index 7e0b88be..87e68127 100644
Binary files a/web/space/audio/voice/male/time_2.ogg and b/web/space/audio/voice/male/time_2.ogg differ
diff --git a/web/space/audio/voice/male/time_3.ogg b/web/space/audio/voice/male/time_3.ogg
index 11c26009..8bb18247 100644
Binary files a/web/space/audio/voice/male/time_3.ogg and b/web/space/audio/voice/male/time_3.ogg differ
diff --git a/web/space/audio/voice/male/time_4.ogg b/web/space/audio/voice/male/time_4.ogg
index b47e5fc0..9f17ab54 100644
Binary files a/web/space/audio/voice/male/time_4.ogg and b/web/space/audio/voice/male/time_4.ogg differ
diff --git a/web/space/game.js b/web/space/game.js
index 22888167..6bbd2060 100644
--- a/web/space/game.js
+++ b/web/space/game.js
@@ -31,11 +31,12 @@
* 语音 id 权威清单:docs/design/04-space-voice-ids.md(52 句双性别);
* 旧 num 拼接件、n_ 前缀件、intro1-4/hit1/hit2/gameover/restart 全部弃用。
*
- * 向导层(docs/design/14-guide-layer.md + round2 synthesis F2.2/F6):对局第 1 次
- * 受击(保护期外)在归因链播完后补指令式 gd_hit_hint、第 2 次补 gd_last_life
- * (idle-only:挂在语音空闲点);警报音效 600ms 去重、danger 震 ≥400ms 去抖;
- * 结算链换 _speakGuarded(资产缺失不卡结算 BGM);对局期长按快进豁免
- * (setRateBoostEnabled);状态签名 earcon 与状态 BGM 同点。
+ * 向导层(docs/design/14-guide-layer.md + round2 synthesis F2.2/F6 + round3 G7):
+ * 对局第 1 次受击(保护期外)在归因链播完后补指令式 gd_hit_hint、第 2 次补
+ * gd_last_life(idle-only:挂在语音空闲点);警报音效 600ms 去重、danger 震
+ * ≥400ms 去抖;loud 警报档(撞击前 500ms)同窗播 dir_ 超短方向呼喊
+ * (voice 层直达、全档位,G7);结算链换 _speakGuarded(资产缺失不卡结算 BGM);
+ * 对局期长按快进豁免(setRateBoostEnabled);状态签名 earcon 与状态 BGM 同点。
*/
import { Game } from '../engine/game.js';
import { Guide } from '../engine/guide.js';
@@ -461,7 +462,15 @@ export class SpaceGame extends Game {
if (this.obstacles.has(ob)) this._alarm(0.5);
});
this._after(impactAt - ALARM_LEAD_MS / 2 - now, () => {
- if (this.obstacles.has(ob)) this._alarm(1);
+ if (this.obstacles.has(ob)) {
+ this._alarm(1);
+ // G7(round3):loud 档(撞击前 500ms)同窗超短方向呼喊 dir_——与
+ // 警报分属 voice/sfx 两通道,天然同时不互顶(引擎 duck 压 BGM 保证可闻),
+ // 噪音环境下方位不再只装在呼啸单通道(P3 round2 P0)。游戏反馈层全档位
+ // (gd_economy 先例);直达式播放不排队——呼喊必须赶在撞击前,宁可顶掉
+ // 里程/充能类短句,也不排到链尾迟到。
+ this.audio.play(`voice/dir_${ob.dir}`);
+ }
});
this._after(impactAt - now, () => this._resolve(ob));
}