From 4c16f87a3e2be51fec8e5a0de15075f2651575d8 Mon Sep 17 00:00:00 2001 From: Javis Date: Sat, 10 Oct 2026 13:07:32 +0200 Subject: [PATCH] Correct the voice_gate_ratio tuning direction A higher ratio raises the loudness gate, so it rejects more audio rather than less. The config guidance claimed the opposite; pin the direction with a test. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- config.example.yaml | 5 +++-- src/javis/core/config.py | 4 +++- tests/test_endpointing.py | 16 ++++++++++++++++ 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/config.example.yaml b/config.example.yaml index 2c3b5a9..b554a58 100644 --- a/config.example.yaml +++ b/config.example.yaml @@ -58,8 +58,9 @@ wake_word: silence_ms: 800 # end-of-utterance silence voice_gate_ratio: 3.0 # how much louder than the background a frame must be to count as # the user talking — lets recording end while your own speakers play - # music (Silero rates music as speech). 0 = off, raise if commands - # get cut off, lower if music keeps the recorder running. + # music (Silero rates music as speech). 0 = off. Higher is stricter: + # raise it if music keeps the recorder running, lower it if quiet + # commands get cut off. mcp: servers_config: "mcp_servers.json" diff --git a/src/javis/core/config.py b/src/javis/core/config.py index 82669b1..08fd003 100644 --- a/src/javis/core/config.py +++ b/src/javis/core/config.py @@ -131,7 +131,9 @@ class WakeWordConfig: # How much louder than the background a frame must be to count as the user # talking. This is what lets a recording end when the *user* stops even # while the device's own speakers keep playing music (which Silero happily - # classifies as speech). 0 = off (plain VAD endpointing). + # classifies as speech). Higher is stricter: raise it when playback keeps + # the recorder running, lower it when quiet commands get cut off. + # 0 = off (plain VAD endpointing). voice_gate_ratio: float = 3.0 diff --git a/tests/test_endpointing.py b/tests/test_endpointing.py index aed4336..992cf43 100644 --- a/tests/test_endpointing.py +++ b/tests/test_endpointing.py @@ -129,6 +129,22 @@ class SpeechEndpointerTests(unittest.TestCase): self.assertAlmostEqual(ep.background, before) self.assertFalse(ep.process(frame(MUSIC_RMS * 2.0)).is_speech) + def test_a_higher_ratio_is_stricter(self) -> None: + """Pins the documented tuning direction. + + Raising the ratio rejects more audio (so it can clip quiet commands); + lowering it admits more (so playback can keep the recorder running). + """ + def accepts(ratio: float) -> bool: + ep = endpointer(ratio=ratio) + for _ in range(50): + ep.observe(frame(MUSIC_RMS)) + ep.reset() + return ep.process(frame(MUSIC_RMS * 2.5)).is_speech + + self.assertTrue(accepts(2.0)) # permissive — the frame counts as the user + self.assertFalse(accepts(4.0)) # strict — the same frame is rejected + def test_ratio_zero_disables_the_gate(self) -> None: ep = endpointer(ratio=0.0) self.assertFalse(ep.enabled)