feat(cw): add 20s rolling buffer with periodic full re-decode
DeepCW 是整段 CTC 批处理模型, 不能像传统 DSP 那样逐样本流式输出。
实测否决了滑动窗口+增量拼接方案。整段批处理 CER 0.0%, 而所有窗口/步进
组合最好仅 67.6%, 最差 294.1% (呼号被重复三遍)。根因是模型每获得更多
上下文就重写已输出内容 —— 同一音频逐渐加长时 11 次采样有 6 次修正前缀
(BM -> BG7 -> BG7NTI -> BG7NTA), 任何"只追加增量"策略都会把这些中间态
永久留在屏幕上。
改为: 固定 20 秒滚动缓冲 + 每 1.5 秒重解全量 + 整体替换显示。
参数由实测定案, 是两条约束的交点:
- 准确率侧: 20s 是达到 0.0% CER 的最小窗口 (16s 仍有 5.9%)
- 算力侧: 耗时超线性增长, 60s 音频推理耗时约为 20s 的 13 倍, 实时余量
不足; 20s 时余量约 13 倍, 安全
实现: 环形缓冲, snapshot() 返回按时序展开的副本 (调用方无法污染内部
存储), append() 返回是否该触发重解。
验证:
./gradlew :core:domain:test --tests '*CwDeepBufferTest*'
=> tests="10" skipped="0" failures="0" errors="0"
含断言: 容量封顶、最旧样本先丢、环绕后时序正确、超容量分块只留尾部、
重解间隔不漂移 (150 个 100ms 分块恰好触发 10 次)、snapshot 不共享内存