* refactor(audio): extract capture source from recognition manager
Move audio capture out of the silence-segmented dictation loop into
vocalinux.audio.capture: a reusable PortAudioCaptureSource that owns
device resolution, format negotiation, downmixing, resampling, and
stream lifecycle (open/read/reopen/close). The dictation loop now
consumes 16 kHz mono chunks and keeps only segmentation policy (VAD,
silence counters, buffer limits, reconnection backoff).
This unblocks alternate capture sources (PipeWire system-audio capture
for #751, tdrz long-form output for #756) which need the same capture
mechanics without dictation's silence segmentation.
Behavior is identical: the same helpers run in the same order, moved
verbatim. They are re-exported from recognition_manager for existing
imports, and a CaptureSource protocol is declared in common_types.py.
Tests repoint their patches of the moved helpers to the new module.
Closes#760
* fix(audio): annotate capture API and keep a superseded session's source
* fix(audio): reset retry counters when a new capture session starts
* fix(audio): keep last-error timestamp across capture sessions
The new-session reset wiped _last_audio_error_time, so an error within five seconds of the previous session's error always took the reconnect path instead of failing fast. Only the attempt count is per-session; the timestamp is also the rapid-failure throttle.
---------
Co-authored-by: Jatin K Malik <jatinkrmalik@gmail.com>