# 02 · 音频信息流设计分析(Q2 方位判读 / Q3 信道拥挤)· Phase 2 > 视角:纯音频信息流——耳朵在每一秒能听到什么、能不能判读、被谁掩蔽。 > 数据:`metrics.md`(28 局总账)+ 4 份抽样精读转写(P02/P08 · R1-quick,P07 · R2-quick,P10 · R0-teach)+ P01/P02/P09/P10 终评。 > 硬约束(全程自检):**R6 红线——方位信息永远由声像承载,语音不得报方位**;语音资产每句重新 TTS 有成本。 > 改动面缩写:**G** = `web/hunt/game.js`,**S** = `web/server/hunt-room.js`,**V** = `docs/design/23-hunt-voice-ids.md`(含 `tools/gen_voice_dual.py` 两表一致铁律),**D** = `docs/design/23-hunt.md` 同步。 ## 0. 总判断 信息流层面三个结构性断点,且互相放大:**① 前后轴只有"音量 ×0.6"一条线索,且与距离档共用响度维度(混淆是数学上注定的)**;**② 出击冷却 2.5s 对玩家是纯黑箱(666 次乱滑被拦,无一毫秒就绪信息)**;**③ up/down 手势"有怪=出击、无怪=菜单/状态链"的语境折中,把方位判读弱点直接兑换成误触 UI 与语音轰炸**。R1-R8 机制本身全部成立(无叠播、无超限),但 R2 的"占线丢弃"打在唯一正确的时机上(波始),bot 喊话在快速局近乎绝迹。掩蔽的代价不在判读准确率(10% vs 10%,无差异),而在**漏检与迟到**——当前指标没有这个口径,复测需补。 --- ## A1 · 前后轴(N/S 家族)判读 63-69%:单线索、且与距离轴共维度 ### 现象(数据+转写引用) - 混淆账(821 次登记,按 90° 弧可命中口径):**N 63%(n=120)/ S 69%(n=85)**,而 E/W 100%、四斜向 96-99%。弱点严格落在 "pan=0、只能靠音量分前后" 的家族;N 同时是尝试量最大的桶(玩家默认往前滑)。 - 转写翻车样本(全部是前后翻转,不是左右混淆): - P02 R1 `00:45.7`「以为左前实在正左」、`01:11.4`「上滑出击→以为正前的狼(其实在正后)」、`01:18.9`/`01:44.7`「以为正后(其实在正前)→下滑变菜单」; - P07 R2 `01:44.2`「以为正前其实在正后」、`01:51.3`「以为左前其实在正前——挥空」; - P10 R0 `01:53.9`「闷声以为左前,实在左后」、`02:29.1`「以为右后,其实在正前」。 - 终评三方盖章:P01(资深,斜向混淆 <8% 的人设)「单音量线索在旁白轰炸下等于无线索」;P02「三局五验同判不同果,等于不可用」;P10「三局了这条规则从没进过我脑子」。 ### 根因(三层,一层比一层深) 1. **几何层**:`pan = sin(az)`,N/S 同为 0——StereoPanner 前后同位是已知物理边界,设计已用 ×0.6 补偿;但 **-4.4dB 是一个响度差**。 2. **维度混淆层(设计根源)**:距离三档 0.30/0.55/0.80 与前后系数 ×0.6 **共用同一个响度维度**,且量级相当(档间差 -5.2dB / -3.2dB vs 前后差 -4.4dB)。具体对撞:前方中档 0.55 vs 后方贴脸档 0.80×0.6=**0.48**——差 0.5dB,人耳不可分;后方中档 0.33 与前方远档 0.30 直接重叠。**"多远"和"前还是后"两个信息轴被压进同一根响度刻度**,这不是练不练的问题,是解码不出来。 3. **实现与教学层**: - game.js `_ensureMobLoop` 里"闷"= `vol × 0.6` 纯增益(G:961),**没有任何低通滤波**——设计词面"身后发闷"承诺的是音色,实现只给了响度; - 教学零覆盖:hunt-room.js `tickTeach` 的教学狼全在前半平面(stage1 `dir:'N'`、stage2 `N+NE`,S:591/606-607),`tut_rule` 台词不含闷约定(voice-ids 头注写"由音效演示承担"——**演示狼根本不从身后来**)。P10 终评 P0-1 原话:「闷=身后零教学」。 ### 修复提案(全部不越 R6 红线:方位仍由声像/音色承载,无语音报方位) | # | 修法 | 机制/参数 | 改动面 | 新台词? | |---|---|---|---|---| | F1 | **后半平面低通第二线索(音色轴)** | loop 链路 `src→gain→BiquadFilter(lowpass, f≈900Hz, Q≈0.7)→panner→sfxBus`,后半平面启用、前半平面直通;与 ×0.6 音量并行。音色与响度正交,距离档不再污染前后判读。loop 走游戏层自建节点(abyss 先例),**不动引擎面** | G(`_ensureMobLoop`) | 否 | | F2 | **前后系数加深** | ×0.6→**×0.5**(-6dB),配合 F1 后响度只做辅助确认 | G(一行常量)+D §8.3 同步 | 否 | | F3 | **教学补"身后"课** | T1 杀掉 N 狼后补放一只 `dir:'S', eta:12` 教学狼(同样零惩罚、可挥空重教 ≤2 次);新台词点破:`tut_back`「这一声发闷——它在身后。声音发闷,就在背后。」;同时**换写既有 `tut_rule`**:「野兽会从八个方向围上来。声音在哪边,就往哪边滑。听着发闷的,在身后。」(重生成,不加 id) | S(`tickTeach`)+V(+1 id)| **是:新增 `tut_back` 1 id ×2 性别;`tut_rule` + key 变体各重生成 ×2**。预算说明:旁白 60 句已打满,+1 需设计裁决(扩到 61,或砍 1 句低价值句腾位;候选:`st_wave_c`「最后一波了」与 `wave_band5` 语义重复度最高,但状态链在用——建议直接扩容并更新 D §10.3/自检 #5 口径) | | F4 | **挥空增亮反馈(错向的真话由声像自己说)** | `ev miss` 后 0.3s 内,把当前内圈 eta 最小怪的 loop 短暂增亮 0.6s(vol×1.3;若在身后,这 0.6s **暂时解除低通**)——玩家当场听到"真实方位",形成前后轴的即时纠错学习回路 | G(`_onMiss` → `_highlightNearest`) | 否 | | F5 | (P2 备选)呼啸 howl 同样加低通 | howl 走引擎 `opts.pan` one-shot,插滤波需引擎面例外——与 §9"引擎改动唯一一处"冲突,暂缓;外圈损失由中圈 loop(已带 F1)接管 | (引擎例外,暂缓) | 否 | ### 预期指标变化 - N/S 可命中率 63%/69% → **≥85%**(R4 同口径复测);斜向 96-99% 与 E/W 100% 不回归(F1 不动 pan)。 - 前后翻转型挥空(转写归因"以为前/其实在后"类)样本占比下降 ≥60%;P02 类"同判不同果"主观报告消失(F1 使线索可解码,F3/F4 使其可学习)。 - P10 类新手「闷声判反两次」→ 教学局内至少一次正确应对身后世狼。 --- ## A2 · 冷却黑箱:666 次乱滑被拦,就绪状态零外显 ### 现象 - 全场 666 次冷却乱滑被拦;P07 R2 一局 **138 次**(`01:48.3-01:49.7` 十一连滑、`02:21.1-02:22.7` 又十余次,每 100-300ms 一记 error 震,间夹 threat 重听);P09 三局局局「回神头两秒全在吃震」,P10「三局从没数清过一次冷却」「一度以为是我滑法不对」。 - 实现现状(G):`_attackDir` 冷却内 `vibrate('error'); return;`——**2.5s 冷却没有任何音/震/节拍外显**;旋风斩 8s 有 `skill_ready` 语音,但 `queue:true` 排队在拥挤信道里迟到:P07 R2 `02:25.3` 战斗最烈时排不上,**`02:32.7` 局已进入结算才播出来**(`_enterEnd` 未清 `_skillReadyTimer`,跨局泄漏,bug 级)。 - 附带偏差(需核查):P02 R1 `00:37.2/00:38.1/00:39.0` 三次被拦右滑,转写播了 `gd_invalid`「这个操作现在用不上」——设计口径是"冷却仅 error 震、gd_invalid onceKey 同局 1 次"。sim 感知模型与 game.js 两处不符(或真实客户端存在异常路径),实施前先对 harness 复刻核对。 ### 根因 就绪状态只存在于客户端 `_atkReadyAt` 时间戳,**没有任何模态把它交给耳朵/手掌**;error 震语义是"不行"而不是"还差多久";冷却被拦与无效手势用同一种震(P10 三局分不清是冷却还是手势错);`skill_ready` 绑在语音队列上,信道越挤越迟到。 ### 修复提案 | # | 修法 | 机制/参数 | 改动面 | 新台词? | |---|---|---|---|---| | F6 | **出击就绪双信号** | 冷却到期播 0.2s 合成短音 `atk_ready`(SYN 高频双 blip,中央,vol 0.5,R5 合规 <1s)+轻触觉(`vibrate('confirm')`)。**节流:仅当本冷却窗内发生过被拦尝试才播**(没人急着出手时不出声,避免每 2.5s 空响成噪声) | G(`_attackDir` 内 arm setTimeout,复用 `_armSkillReady` 模式)+1 条程序合成 sfx | 否(SYN 无 TTS) | | F7 | **被拦反馈分级** | 同一冷却窗内首次被拦:专用触觉模式(0.4s 双脉冲,与"无效手势"单短震区分);第 2 次起合并静默至窗尾(消灭 P07 式连震风暴)。冷却与无效手势两种 error 从此可分辨 | G(`_attackDir` + `_invalid`) | 否 | | F8 | **skill_ready 去语音化+修跨局泄漏** | 改合成 earcon(上行双音 0.3s)+success 轻震;`_enterEnd/_teardownRound/stop` 一律清 `_skillReadyTimer`;`skill_ready` 语音 id 保留给 TEACH 讲解用 | G(`_armSkillReady`、`_enterEnd`)+1 条 SYN sfx | 否 | | F9 | (P2 可选)冷却进度 tick | 被拦时按剩余时间给 1-3 声短 tick(P02 要的"还差半秒");有 F6 后收益边际化 | G | 否 | ### 预期指标变化 - 冷却乱滑被拦 **666 → ≤200**(就绪可听后 spam 自熄:P07 类玩家的连滑在第一声 ready 后失去动机)。 - P09「回神头两秒吃震」消除;P10「扣的那 1 分」收回;`skill_ready` 跨局/迟到播报归零(语音打断 37 次中 skill_ready 相关子项清空)。 --- ## A3 · down/up 双语义陷阱:误触菜单与状态链误播 ### 现象 - **下滑=菜单误触,6/10 玩家中招**:P01 R1 连环 14 次(终评:「下滑退出和下滑打正后是同一根手指,三次下滑全弹回菜单」);P07 R2 `01:15.6-01:17.6` 菜单乒乓 6 轮(每轮 `sys_menu→回到猎场→settings_hint` 三句链互相打断,"回到猎场"四度播不完);P02 R1 五次(`01:18.9/01:44.7/02:20.9-02:21.3` 连环);P08 R1 三次;P09 三局同坑(进菜单后 `01:09.3` 盲单击又误触"重新听帮助")。 - **上滑=状态链误播**:错向挥出的上/下滑恰好制造"弧内无怪"→ 变成播报。P02 R1 `01:11.4`「以为正前其实在正后→上滑变成 4 句状态链」;P07 R2 `01:44.2` 同型。状态链 4 句 ≈5-6s 占满语音通道(见 A4)。 - 菜单打开战斗照走(E3 豁免本意),P01 终评 P0-1 定性:「操作本身就是在跟系统打架」。 ### 根因 23-hunt §2.1 表格自身双重定义(四向滑=出击 vs 上滑=状态链/下滑=菜单);game.js 文件头"语境折中"用 `_arcHasTarget()`(客户端本地、eta≤4、事件流瞬时空窗都影响判定)做分流——**把"打不打得到"这个毫秒级动态事实当作"出招还是开 UI"的开关**。且误触率与 A1 前后弱点正相关:错向 → 无怪 → 菜单。退出菜单仍是下滑,同一根手指解自己上的锁。 ### 修复提案 | # | 修法 | 机制/参数 | 改动面 | 新台词? | |---|---|---|---|---| | F10 | **WAVE 态下滑恒=出击** | 无目标也走完整出击:`atk_whoosh`+服务器 miss → `atk_swish` 真话+error 震(与左/右滑同待遇)。菜单入口改为:①**波间休整**(`wave_clear` 后 8s 窗)内下滑=菜单;②战斗中**长按**=菜单(WAVE 态旁白极少,快进让渡成本最低——需宪法裁决登记 E3 修订);若裁决不动长按,则战斗中无菜单、退出只在波间 | G(`_onWaveGesture`)+D §2.1/§2.4/§2.5 豁免表同步 | 否 | | F11 | **上滑状态链两条护栏** | ①链播中再上滑=**立即停止**(现在会再排 4 句,P02 R0 23 秒里"营地固若金汤"五遍);②**危急截断**:任一怪进入贴脸档(eta<2.5s)时,正在播的状态/菜单/帮助/watchdog 链立即截断(`_chainSeq++`+`stopVoice`;警报/教学/结算链豁免)——即 P02 点名的"危急时刻静默通道",实现"loop 优先"而不动引擎 ducking | G(`_statusChain`、`_refreshLoops` 内挂钩) | 否 | | F12 | **状态链瘦身** | 4 句→按变化播:耐久档+击杀档恒播;波次档仅波次变更后首次播;猎人数仅 roster 变更后播(P08 是状态链重度用户且终评正向——保留主干只砍复读) | G(`_statusIds`) | 否 | ### 预期指标变化 - 战斗中 menu-open 误触:P01 的 14 次/局 → **0**(结构性消除)。 - 语音打断 37 → **≤15**(大头是菜单乒乓互切,见 A4 清单)。 - "状态链压贴脸脚步"型掩蔽案例(P02 R2 01:21.0-01:26.8)归零;P01 P0-1/P0-2 直接收口。 --- ## A4 · 语音通道 × 战斗信息冲突账 ### 掩蔽源清单(按占用时长与伤害排序;样本来自 4 份精读转写) | 源 | 单次占用 | 样本频次 | 价值裁定 | |---|---|---|---| | 误触菜单链(`sys_menu`+`sys_menu_resume`+`settings_hint`) | 3 句 ≈5s | P02 R1 ×5、P07 R2 菜单乒乓期近连续、P08 R1 ×3 | **负价值**;F10 后归零 | | `help_main` 战斗中整播 | ≈8s | P08 R1 `01:33.4/02:02.3`、P07 R2 `01:40.9`、P01 R1 ×2 | **负价值**(P01:「对老手重播基础教学=战斗中没收我的耳朵」);F10 后结构性消失(菜单不在战斗态) | | 状态链 4 句 | ≈5-6s | P08 R1 主动使用 ×6;P02 R0 23s 五遍复读 | **中价值**(P08/P06 靠它感知战局)——瘦身保留(F11/F12),不删功能 | | watchdog 两级(idle 提示音+`gd_idle`) | ≈2s×2 | 全场 93 次 ≈3.3 次/局;P10 R2 七次全误伤(在等怪不是挂机) | **救命索但触发条件错**(P09 走神 9 次全被拽回)。修:inner-ring 有怪、或 5s 内有击杀/被拦/呼喊记录时不触发;第 1 级降为纯震+短音,第 2 级才上语音(G `_rearmWatchdog` 条件) | | 波次/威胁/警报(`wave_band*`/`threat_*`/`breach*`) | 各 1 句 | 合法占用 | **警报可达性 PASS**:28 局 6 次 breach 全部按时到达并正确顶掉状态类(R1 实测有效);`threat_*` 重听是 P07 的双击主出口,属宪法语义,保留 | | `skill_ready` | 1 句 | P07 R2 高频 | F8 去语音化后退出竞争 | ### 掩蔽 × 误判的诚实读数 metrics:掩蔽下误判率 10%(n=297)vs 干净时 10%(n=524)——**判读准确率不受掩蔽影响**(拟人模型"听到后"的判读与掩蔽无关)。但掩蔽的真实代价是**漏检/迟到**:P01「menu 播报正好盖掉右后闷脚步→四连打空」、P02「状态链四句压着贴脸脚步」。当前混淆账不测这个。**复测新增指标:「掩蔽窗漏检率」=语音在播期间进入内圈的怪,玩家首次针对性出手延迟 >1.5s 的比例**(基线值 R4 复测时先量再比)。 ### bot 喊话饿死(结构性对撞) - R2 客户端规则"旁白在播→延迟 ≤2s→丢弃",撞上服务端触发时机:`greet` 排在开局(`GREET_FIRST_MS` 起,S:352-353)、`wave` 排在波始(S:371)——**这两个时刻旁白必播**(`room_start`+`wave_band1` / `wave_bandN`),氛围句 2s TTL 必死。 - 实测:P10 R0 教学局 12 条 botline 中 **7 条被挤掉**(`00:04.6` greet、`01:07.3/02:11.5/02:43.1` 恰为波始),5 条可闻(help_call/help_ack/cover/kill×2——priority 句 4s TTL 兑现了"呼救不可被顶");**P02/P07/P08 三份快速局转写可闻 bot 喊话 0 条**。 - 注意另一根因:P01 R1 是 4 真人房(0 bot),bot 喊话结构性为零——"真人房社交声道缺失"要靠呼喊链路补(全场呼喊仅 3 次/28 局,且 P02 R1 `02:12.6` 呼喊的本地反馈在转写里呈现为旁白"重新听帮助。",同房 P01 也没报告听到空间化喊话——**呼喊播放链路需专项核查**)。 **修法 F13(S+G,无新台词)**:服务端 `wave`/`greet` botline 延迟 3.5s 投递(等 `wave_band` 播完;BOTLINE 预算 10s≤2 不变);客户端非优先句 TTL 2s→4s。预期:快速局人均可闻喊话 0→3-5 条;教学局挤掉 7→≤2。 --- ## A5 · R1-R8 拥挤规则在真实并发下的表现 | 规则 | 机制是否成立 | 真实并发下的表现与裁定 | |---|---|---| | R1 旁白单句队列 | ✅ | 全程无叠播;警报顶状态类实测有效(breach 到达 6/6)。代价=队列拥堵与打断(37 次,主因菜单乒乓,F10 后大减);**发现的 bug:`skill_ready` 排队跨入结算链**(P07 R2 02:32.7),F8 修复 | | R2 喊话 sfx ≤1+延迟丢弃 | ✅(但丢弃打错时机) | 上限无违例;丢弃全落在 greet/wave 两类"旁白必播时刻"——**修触发时机(F13),不放宽 ≤1 上限**。help_call/help_ack 优先级兑现(教学局 5 条可闻里 3 条是 priority) | | R3 loop ≤3 路 | ✅ 且无害 | 无"第 4 近怪因静默突入"的可归因案例(快速局 6 局全零 breach);被裁剪怪的方位由击杀倒地音(带 pan)部分补偿。**维持原样** | | R4 one-shot ≤2+呼啸可弃 | ✅ | 波 4-5 生成潮确有呼啸被弃(外圈方向预告缺失),但中圈起 loop 接管,本数据集无可归因损失。可选微调 HOWL_QUEUE_MAX 2→3 / TTL 1.5→1.2s——收益小,列 P2 | | R5 非语音 <1s | ✅ | 无违例 | | R6 方位由声像承载 | ✅ | 全程无语音报方位。**这是立身之本:本报告所有修法(低通/增亮/earcon)均让声像自己说话,明确拒绝"语音报前后"类越线捷径** | | R7 电平分层 | ⚠️ 半成立 | BGM duck 语音方向正确;但"语音 vs loop"无互让——用 F11 危急截断在游戏层实现"贴脸 loop 优先",不动引擎 | | R8 ≤7 声流 | ✅ | 转写无超限/叠爆证据 | --- ## 修复优先级表 | 级 | 编号 | 修法 | 改动面 | 新台词(TTS 成本) | 预期指标 | |---|---|---|---|---|---| | **P0** | F1 | 后半平面 loop 低通(音色第二线索) | G | 否 | N/S 63/69% → ≥80%(配合 F3 冲 ≥85%) | | **P0** | F6 | 出击就绪 earcon+触觉(有被拦才播) | G+1 SYN sfx | 否(程序合成) | 乱滑被拦 666 → ≤200 | | **P0** | F10 | WAVE 下滑恒出击;菜单改波间窗/长按 | G+D(E3 修订) | 否 | 战斗中误触菜单 →0;语音打断 37 → ≤15 | | **P0** | F3 | 教学补身后期:S 向教学狼+`tut_back`+`tut_rule` 换写 | S+V | **是:+1 id×2 性别;`tut_rule`(含 key 变体) 重生成 ×4**;60 句预算需裁决扩容 | 新手前后翻车率减半;「闷」从零教学变一课学会 | | **P1** | F11 | 危急截断+链中再上滑即停 | G | 否 | 状态链压贴脸脚步案例归零 | | **P1** | F7 | 被拦反馈分级(冷却≠无效手势,连震合并) | G | 否 | P10 类"自我怀疑"消除 | | **P1** | F13 | botline 波始延迟 3.5s+客户端 TTL 2→4s;呼喊链路专项核查 | S+G | 否 | 快速局可闻喊话 0→3-5 条/人 | | **P1** | F8 | skill_ready 去语音化+局末清 timer | G+1 SYN sfx | 否 | 跨局泄漏/迟到归零 | | **P1** | F12 | 状态链按变化播(4 句→2-4 句) | G | 否 | "固若金汤"复读投诉归零,状态感知功能保留 | | **P2** | F4 | 挥空增亮(0.6s 突出真方位 loop) | G | 否 | 前后错向即时纠错学习回路 | | **P2** | F2 | 前后系数 0.6→0.5 | G+D §8.3 | 否 | F1 的响度辅助确认 | | **P2** | F5/F9 及 watchdog 降级、HOWL 队列微调 | 见 A4/A5 | G/S | 否 | 边际改善 | **汇总账**:12 项修法中仅 F3 需要新台词(1 个新 id + 1 个既有 id 换写重生成,合计 6 条 TTS:`tut_back`×2 性别、`tut_rule`×2 性别+key 变体×2);其余全部是 game.js / hunt-room.js 逻辑与程序合成 sfx,零 TTS 成本。全部修法通过 R6 红线自检(无一句语音报方位)。 **复测口径提醒(给 synthesis)**:①混淆账同口径重跑(N/S 家族单列);②新增"掩蔽窗漏检率";③新增"战斗中 menu-open 次数""被拦后至就绪出手的中位延迟""bot 喊话可闻条数/人/局";④先核对 sim 感知模型两处偏差(冷却被拦播 `gd_invalid`、呼喊本地反馈异常),确保 R4 对比不被 harness 噪声污染。