Move the speech-SNR floor from the timing gate to the pitch estimate - #29
Merged
Conversation
…mate Three measured sessions reported zero voice segments and withheld all seven voice metrics. The cause is arithmetic, not luck: eligibleSegments ends a segment on ANY unusable frame, and 32% of speech-active frames sat below the 15 dB SNR floor, scattered. Expected contiguous usable run is about 3 frames, or 31 ms, against a 2000 ms segment minimum -- P(a segment surviving) is 1.5e-34. The floor was also in the wrong place. It exists so f0 is not estimated from speech buried in noise, which is a PITCH concern. Timing metrics need only reliable voice-activity detection, robust well below 15 dB, and a noisy speech frame is still evidence that speech occurred. validPitch did not check SNR at all, so the gate was applied only where it did harm and absent where it belonged. It now lives in validPitch. This is the same defect the face lane had twice over: a gate built for one measurement class applied to all of them. There it cost every bin; here it cost every segment. Tests drive 32%, 50%, and 95% of speech frames below the floor: timing measures through the first, pitched duration falls at the second, and pitch withholds entirely at the third. The floor is relocated, not abandoned. Pack 3.3.0, voice algorithm versions to 1.1.0. Voice measurements are not interchangeable across this bump. NOT changed: the face lane. Its remaining failures are genuine head movement rather than a structural gate, and the resting-pose fix from the previous commit has not yet been exercised on a real session. Changing more before that data arrives would be guessing. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Three measured sessions reported zero voice segments and withheld all seven
voice metrics. The cause is arithmetic, not luck.
The measurement
eligibleSegmentsends a segment on any unusable frame, and 32% ofspeech-active frames sat below the 15 dB SNR floor, scattered through:
Zero segments was certain, in every session, before anyone spoke.
The floor was also in the wrong place
It exists so f0 is not estimated from speech buried in noise — a pitch
concern. Timing metrics need only reliable voice-activity detection, which is
robust well below 15 dB, and a noisy speech frame is still evidence that speech
occurred.
validPitchdid not check SNR at all. So the gate was applied only where it didharm and was absent where it belonged. It now lives in
validPitch.This is the same defect the face lane had twice: a gate built for one
measurement class applied to all of them. There it cost every bin; here it cost
every segment.
Tests
Drive 32%, 50%, and 95% of speech frames below the floor:
The floor is relocated, not abandoned.
Contract
Pack 3.2.0 → 3.3.0, voice algorithm versions to 1.1.0. Voice
measurements are not interchangeable across this bump. The registry/pack parity
test caught the version mismatch before it shipped.
Deliberately not changed
The face lane. Its remaining failures are genuine head movement rather than
a structural gate, and the resting-pose fix has not yet been exercised on a real
session. Changing more before that data arrives would be guessing — the same
mistake the corrected acceptance curve already made once in this project.
Verification
277 unit tests, typecheck, structure + digest check, build, 6 browser e2e.
🤖 Generated with Claude Code