diff --git a/app/src/main/java/com/k2fsa/sherpa/onnx/MainActivity.kt b/app/src/main/java/com/k2fsa/sherpa/onnx/MainActivity.kt index e723bf1..7001eac 100644 --- a/app/src/main/java/com/k2fsa/sherpa/onnx/MainActivity.kt +++ b/app/src/main/java/com/k2fsa/sherpa/onnx/MainActivity.kt @@ -188,11 +188,13 @@ class MainActivity : AppCompatActivity() { private val speakerCheckHandler by lazy { Handler(speakerCheckThread.looper) } // 实测(2026-09-14):2s 短窗 + base 模型下同人 simA 在 0.05~0.7 震荡, // 阈值维度已不可分 → 判定窗加长到 4s 拉开分布,阈值回调到 0.35 - private val speakerSwitchDrop = 0.35f // cos(window, reference) below this => switch + // 稳健档(2026-09-16 用户拍板"宽松一点,不要这么灵敏"):四闸阈值整体上调, + // 少切宁合;原值 0.35/0.22/0.32/0.5 见 git history + private val speakerSwitchDrop = 0.30f // cos(window, reference) below this => switch // 深低分一票强切(2026-09-16):同人波动实测最低 ~0.39,异人插话窗稳落 // 0.14~0.19,0.22 取安全带中枢——深低首票即切(无缝插话 4~6s→3~4s); // 0.22~0.35 浅低维持连续两票,毛刺照旧被误断防护拦下 - private val deepLowSwitch = 0.22f + private val deepLowSwitch = 0.18f // 最近邻兜底(P1 收紧,2026-09-11):精确匹配不中→top≥0.42 且领先第二名 // ≥0.06 才归入最相似身份;模糊判新人(修"错并到别人行") private val verdictFallbackMin = 0.42f @@ -207,7 +209,7 @@ class MainActivity : AppCompatActivity() { // 最速档:1.2s 周期 + 单票(switchStrikesNeeded=1)。误断的代价只是 // 多分行+流重置,不丢音频(快照平铺保证时间轴连续)。 private val switchStrikesNeeded = 1 // 长窗方差小,单票(真换人检出 3~6s) - private val minWindowRms = 0.012f // 真语音窗才判定:0.004 挡不住房间底噪,垃圾嵌入引发换人风暴 + private val minWindowRms = 0.015f // 真语音窗才判定:0.004 挡不住房间底噪;稳健档上调挡低能量碎音 // 窗长门槛(短窗 embedding 方差是误切主因):锚点需 ≥2s,判定需 ≥3s private val anchorMinSamples = 32000 private val judgeMinSamples = 48000 @@ -226,10 +228,11 @@ class MainActivity : AppCompatActivity() { // →3s(折中)→ 终选回 2s;护持:连续两窗/注册表复用/销案/冷却/并回自愈。 // 若闪烁不可接受,顺序:阈值 0.32→0.36 → 窗 48000(3s) → 64000(4s) private val fastRollEnabled = true - private val fastRollDrop = 0.32f + private val fastRollDrop = 0.28f private val fastStepSamples = 16000 // 1s private val fastWinSamples = 32000 // 2s 尾窗(用户终选) private val fastMinSamples = 24000 // ≥1.5s 才判 + private val onsetFireGate = 0.35f // 开口即查:快片 ≥0.35 视为同人不动(稳健档) private val namingWinSamples = 24000 // 切后命名窗 1.5s(纯净素材,方案三) private val namingMinSamples = 16000 // ≥1s 才判 private val feedLagSamples = 24000 // 1.5s:覆盖判定链(1.2s采集+计算)的 @@ -253,7 +256,7 @@ class MainActivity : AppCompatActivity() { @Volatile private var switchSerial = 0L @Volatile private var switchPrevActive: String? = null private var grayLinePending = false // 主线程:下一新行先以灰行开(等命名) - private val forceSwitchStreaks = 2 + private val forceSwitchStreaks = 3 // 强切冷却(仅 speakerCheckHandler 线程访问,无需 volatile) private var lastForceSwitchAtMs = 0L // 快速通道连续低分计数(同上,单线程访问)。2026-09-16 现场:2s 窗 @@ -716,7 +719,9 @@ class MainActivity : AppCompatActivity() { if (rseq != onsetSeq) return@post val simFast = SpeakerRecognition.similarity( fastEmb, anchor) - if (simFast >= emaAbsorbMin) return@post + // 稳健档:开口即查的"同人"判定线从 0.5 收到 0.35 + // (0.5 时 0.35~0.5 的同人波动都会误切) + if (simFast >= onsetFireGate) return@post // 方案三(2026-09-16):开火不发号——只切行(灰行), // 名字由切后纯净窗在 T+2.5s 诞生 val serial = ++switchSerial