Richard Loyer
|
82d206137f
|
chantier B TTS #8 : speaker encoder embedded + clonage in-process
SE.3+SE.4+SE.5 : ECAPA-TDNN ggml C++ bit-exact + intégration TtsEngine.
speaker_encoder.{h,cpp} :
- API publique : speaker_encoder_load / encode_wav / encode_waveform / free
- mel C++ (FFT radix-2, Hann, reflect pad, librosa basis) bit-exact Python
- ECAPA-TDNN forward : conv0 + 3 SE-Res2Net + MFA + ASP + FC -> x_vector[1024]
- validation : cos=0.9997 vs Python ref (damien_5s.wav)
- SPK_STANDALONE -> binaire CLI kazeia_speaker_encode
tts_engine :
- TtsEngineLoadCfg.speaker_encoder_gguf + mel_basis_path (load-time opt-in)
- TtsSynthesizeCfg.xvector_override (per-call, RAII restore)
- tts_engine_encode_speaker_wav / _waveform exposés
tts_pipeline : KZTTS_SPK_GGUF + KZTTS_MEL_BASIS + KZTTS_REF_WAV -> clonage
in-process (un seul binaire, plus de subprocess swap manuel).
Pièges trouvés en route (documentés CLAUDE.md project_tts_*) :
- ggml_conv_1d exige weights F16 -> cast au call site
- input layout : data[c*T+t] (ggml ne[0]=T fastest) pas memcpy [T,C]
- refs Python en bytes [C,T] = ggml [T,C] côté cpp
- RIFF reader chunk-parsing (ffmpeg = LIST/JUNK avant data)
Test E2E : 4 voix (damien/amir/elodie/zelda) clonées à partir de WAV ref 5s,
toutes audibles et distinctes.
Reste : JNI nativeSynthesizeWithReference (refactor mécanique, prochaine session).
|
2026-05-31 15:54:29 +02:00 |