mirror of
https://github.com/kitlangton/Hex.git
synced 2026-10-23 08:10:58 +00:00
Overhaul audio engine lifecycle: route-change recovery, sleep suspension, teardown fixes
Addresses the audio-engine bug cluster (#209, #218, #226, #245, #246, #251, #252) while keeping Super Fast Mode's warm-microphone design intact. Root problems, all variations of 'the engine outlives the world it was built for': 1. Route/device changes while idle only *deferred* the engine rebuild to the next recording, leaving the stale engine running against the old route indefinitely. That kept coreaudiod churning while idle (#209) and made the first post-change recording unreliable. 2. Route/device changes *during* a recording deferred entirely: the recording kept 'running' while the dead engine captured nothing, producing empty transcripts after Bluetooth connects, A2DP<->HFP switches, and AirPods handoffs (#251, #252, #218, #226). 3. App-quit teardown was a fire-and-forget Task racing process exit, with SuperFastCaptureController.deinit as a second competing teardown path - the EXC_BAD_ACCESS in AVAudioEngine teardown (#245). 4. The sound-effects output engine (isAutoShutdownEnabled = false) ran forever once started, keeping an output IOProc alive even in standard mode. Fixes: - SuperFastCaptureController gains restartPreservingRecording(reason:), which rebuilds engine/tap/converter while keeping the active AVAudioFile open, so mid-recording route changes resume capture onto the same file (small gap) instead of silently losing the rest of the take. startIfNeeded/stop are refactored around shared armEngine/detachEngine helpers; detachEngine bumps the capture generation so in-flight tap callbacks from the old engine are ignored. - RecordingClient rebuilds the engine immediately (debounced 250ms) on idle environment changes instead of deferring; failures fall back to the previous deferred-restart marker. - The warm engine is suspended on screen lock / display sleep / system sleep and rearmed on unlock/wake. Nobody dictates at a locked screen, the mic indicator no longer glows while locked, and a whole class of stale-engine-across-sleep states disappears. Active recordings are never interrupted; an explicit recording request overrides suspension. The pre-roll ring buffer is cleared on suspend so no pre-lock audio is retained. - applicationWillTerminate now blocks (3s bound) on recording.cleanup() via a detached task + semaphore, making teardown deterministic. - The sound-effects engine stops 10 seconds after the last play; restarting on the next play costs milliseconds. The persistent mic indicator while unlocked-and-idle (#246) remains by design when Super Fast Mode is on - that is what keeps the 0.45s pre-roll available - but it now clears whenever the screen is locked or asleep.
This commit is contained in:
parent
2c5d8aea4d
commit
8739929294
5 changed files with 193 additions and 20 deletions
Loading…
Add table
Add a link
Reference in a new issue