Série de correctifs après diagnostic device (logs) :
- AudioTrack : garde STATE_INITIALIZED + retry à la construction (le HAL rend
parfois un track non initialisé après interruption + réouverture micro).
- Interruption pendant la synthèse : abandon PROPRE (check identité du track +
play() gardé) → plus de « play() on uninitialized AudioTrack » / tour avorté.
- Drain DÉTERMINISTE de fin de lecture : on ne se fie plus à onMarkerReached
(exige un Looper, absent sur Dispatchers.Default → ne se déclenchait jamais →
~6-9 s morts après l'audio). On lit playbackHeadPosition et on attend EXACTEMENT
le reste à jouer avant de libérer → fin au plus près de la dernière syllabe,
sans queue morte NI troncature (le flush prématuré coupait la fin).
- Pré-chauffage : warmup() synthétise une phrase jetée au démarrage pour remplir
le cache K/V du prompt voix → 1er vrai tour chaud (~3 s) au lieu de ~10 s
(mesuré : 1er énoncé à froid 10→8→5 s en chauffant). Idempotent par voix.
- Mutex de synthèse : warmup et vraie synthèse ne tournent jamais en parallèle.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>