Review feedback (CRITICAL): when a chunk hit max_chunk_samples during
continuous speech, emit_active_chunk reset state to Idle. The next
1-2 loud frames of post-split continued speech went into onset_buffer
and were silently cleared if silence arrived before the 3-frame onset
threshold — 50-100ms of user audio lost at every max-chunk boundary
in long-continuous-speech scenarios.
Splits emit_active_chunk into two variants:
- emit_active_chunk_and_close: the existing behaviour. Used for
end-of-utterance closes and end-of-session flush. Truncates trailing
silence, resets state to Idle.
- emit_active_chunk_continue: mid-utterance split on max_chunk. Stays
in State::InSpeech, clears active_chunk for continued accumulation,
advances active_chunk_start by the emitted length so the next
chunk's start_sample is contiguous with this one's end. No
silence-trim (by definition still in speech — end-of-utterance
takes priority).
Adds max_chunk_split_preserves_audio_contiguity test: feeds 17 frames
of continuous speech into a chunker with a 4-frame cap, asserts
(a) chunk[i+1].start_sample == chunk[i].start_sample + chunk[i].samples.len()
across every pair, and (b) the final emitted region reaches the end
of the fed speech with no sample loss.