72 lines
3.1 KiB
C++
72 lines
3.1 KiB
C++
// Engine TTS Qwen3 in-process : load une fois (modèles + fixtures + tokenizer),
|
|
// synthesize N fois (texte FR -> WAV). Conçu pour être appelé depuis :
|
|
// - tts_pipeline.cpp (CLI dev)
|
|
// - kazeia_tts_jni.cpp (bridge Kotlin)
|
|
// - test_jni_tts.cpp (harness sans VM Java)
|
|
//
|
|
// État load-once (poids talker ~1.6 GB, CP ~250 MB, decoder ~325 MB, vocab ~50 MB,
|
|
// fixtures text_embed ~1.2 GB) = ~3.5 GB cumulé sur tablette. Une seule instance
|
|
// par process recommandée.
|
|
#pragma once
|
|
#include <cstdint>
|
|
#include <string>
|
|
|
|
struct TtsEngine; // opaque
|
|
|
|
struct TtsEngineLoadCfg {
|
|
const char * talker_gguf = nullptr; // talker_f32.gguf
|
|
const char * vocab_gguf = nullptr; // ex: Qwen3-4B-Q4_0.gguf (vocab_only) ; nullptr -> pas de tokenize
|
|
const char * dump_dir = nullptr; // contient cp_f16.gguf, cp_heads.bin, cp_codec_embs.bin,
|
|
// qwen3tts_decoder.gguf, text_embed.bin, tp_fc1/2_*, talker_tok_embd.bin,
|
|
// damien_xvector.bin, manifest_text.txt
|
|
bool use_htp = false; // true -> HTP0 prefill (option C), false -> CPU pur
|
|
int n_threads = 6;
|
|
bool cp_use_cache = true; // KV cache CP (cp_predict_cached) ; false -> cp_predict oracle
|
|
};
|
|
|
|
struct TtsSynthesizeCfg {
|
|
const char * text = nullptr;
|
|
const char * out_wav_path = nullptr;
|
|
int max_steps = 256;
|
|
uint32_t seed = 42;
|
|
|
|
// Sampling (par défaut = défauts in-house validés sur fixture FR)
|
|
float cp_temp = 0.9f;
|
|
int cp_top_k = 50;
|
|
float cp_top_p = 1.0f;
|
|
float cp_rep_penalty = 1.05f;
|
|
|
|
float talker_temp = 0.9f;
|
|
int talker_top_k = 50;
|
|
float talker_top_p = 1.0f;
|
|
float talker_rep_penalty = 1.05f;
|
|
};
|
|
|
|
struct TtsSynthesizeResult {
|
|
int err = 0; // 0=ok ; <0 erreur (load/tokenize/decode)
|
|
int frames = 0; // N frames audio (12.5 Hz)
|
|
double audio_s = 0; // = frames/12
|
|
double total_s = 0; // prefill + talker_loop + decoder (hors writing WAV)
|
|
double prefill_s = 0;
|
|
double talker_loop_s = 0;
|
|
double cp_loop_s = 0;
|
|
double decoder_s = 0;
|
|
// Streaming TTFB (Time To First Byte audio) : si KZTTS_STREAM_CHUNK > 0, mesure le
|
|
// délai entre le début de tts_engine_synthesize et le 1er chunk audio prêt à écrire.
|
|
// 0 si streaming désactivé. Pour comparer à total_s : audio commence à sortir bien
|
|
// avant que tout soit fini si streaming actif.
|
|
double ttfb_s = 0;
|
|
int n_chunks = 0; // nombre de chunks decoder exécutés (1 = pas de streaming)
|
|
};
|
|
|
|
// Charge tout. Retourne nullptr en cas d'échec.
|
|
// IMPORTANT : llama_backend_init() est appelé en interne (idempotent).
|
|
TtsEngine * tts_engine_load(const TtsEngineLoadCfg & cfg);
|
|
|
|
// Synthétise une phrase. Réinitialise la KV cache talker avant le prefill, donc
|
|
// les appels sont indépendants (pas d'état conversationnel).
|
|
TtsSynthesizeResult tts_engine_synthesize(TtsEngine * eng, const TtsSynthesizeCfg & cfg);
|
|
|
|
// Libère tout.
|
|
void tts_engine_free(TtsEngine * eng);
|