aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/extra
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/extra')
-rw-r--r--vendor/extra/LEEME.md10
-rw-r--r--vendor/extra/canary-rs/examples/bench_live.rs91
-rwxr-xr-xvendor/extra/qwentts.cpp/examples/all.sh99
-rwxr-xr-xvendor/extra/qwentts.cpp/examples/server-test.sh51
4 files changed, 251 insertions, 0 deletions
diff --git a/vendor/extra/LEEME.md b/vendor/extra/LEEME.md
new file mode 100644
index 0000000..658bde9
--- /dev/null
+++ b/vendor/extra/LEEME.md
@@ -0,0 +1,10 @@
+# Ficheros sueltos de los submódulos
+
+Los parches de `vendor/patches/` sólo llevan cambios a ficheros que sus
+repositorios ya versionaban. Estos otros existían únicamente en el árbol de
+trabajo local, así que se guardan aquí enteros y `scripts/bootstrap.sh` los
+copia al submódulo correspondiente tras aplicar el parche.
+
+Hace falta al menos uno de ellos para que el submódulo compile:
+`canary-rs/Cargo.toml` declara el ejemplo `bench_live`, y cargo se niega a
+resolver el paquete si el fichero no está.
diff --git a/vendor/extra/canary-rs/examples/bench_live.rs b/vendor/extra/canary-rs/examples/bench_live.rs
new file mode 100644
index 0000000..71c8420
--- /dev/null
+++ b/vendor/extra/canary-rs/examples/bench_live.rs
@@ -0,0 +1,91 @@
+#[path = "shared/utils.rs"]
+mod utils;
+
+use canary_rs::{Canary, StreamConfig};
+use std::time::Instant;
+
+/// Benchmarks the pieces that drive live-streaming latency:
+///
+/// * encoder cost as a function of window length,
+/// * decoder cost per generated token,
+/// * end-to-end cost of one streaming window vs. one full-utterance decode.
+///
+/// Usage: `bench_live <wav> [lang]`, honouring the same `CANARY_*` environment
+/// variables as the other examples.
+fn main() -> Result<(), Box<dyn std::error::Error>> {
+ let wav = match std::env::args().nth(1) {
+ Some(path) => path,
+ None => return Err("usage: bench_live <wav> [lang]".into()),
+ };
+ let lang = std::env::args().nth(2).unwrap_or_else(|| "en".to_string());
+
+ let config = utils::execution_config_from_env();
+ let model_dir =
+ std::env::var("CANARY_MODEL_DIR").unwrap_or_else(|_| "canary-180m-flash".to_string());
+
+ let t0 = Instant::now();
+ let model = Canary::from_pretrained(&model_dir, Some(config))?;
+ println!("model load: {:.2?}", t0.elapsed());
+
+ let mut reader = hound::WavReader::open(&wav)?;
+ let spec = reader.spec();
+ let samples: Vec<f32> = reader
+ .samples::<i16>()
+ .map(|s| s.map(|v| v as f32 / 32768.0))
+ .collect::<std::result::Result<_, _>>()?;
+ let sr = spec.sample_rate as usize;
+ let duration = samples.len() as f32 / sr as f32;
+ println!("audio: {:.2}s @ {} Hz, {} ch", duration, sr, spec.channels);
+
+ let mut session = model.session();
+ let warm = &samples[..(sr).min(samples.len())];
+ let _ = session.transcribe_samples(warm, sr, 1, &lang, &lang)?;
+
+ // A live window always ends mid-utterance, so mirror that here: take the
+ // *last* `window` seconds and append the same tail silence the stream uses.
+ let tail = StreamConfig::default().tail_silence_duration;
+ println!("\nrolling windows (tail silence {:.2}s):", tail);
+ for window_s in [2.0f32, 4.0, 6.0, 8.0] {
+ if window_s > duration {
+ continue;
+ }
+ let start = samples.len() - (sr as f32 * window_s) as usize;
+ let mut win = samples[start..].to_vec();
+ win.resize(win.len() + (sr as f32 * tail) as usize, 0.0);
+
+ let mut best = f64::MAX;
+ let mut tokens = 0;
+ for _ in 0..3 {
+ let t = Instant::now();
+ let r = session.transcribe_samples(&win, sr, 1, &lang, &lang)?;
+ best = best.min(t.elapsed().as_secs_f64());
+ tokens = r.tokens.len();
+ }
+ // No tokens means the model saw nothing worth transcribing, and the time is encoder-only.
+ let per_token = match tokens {
+ 0 => "encoder only".to_string(),
+ n => format!("{:.1} ms/token", best * 1000.0 / n as f64),
+ };
+ println!(
+ " {:>4.1}s window -> {:>6.0} ms ({:>3} tokens, {})",
+ window_s,
+ best * 1000.0,
+ tokens,
+ per_token
+ );
+ }
+
+ let t = Instant::now();
+ let r = session.transcribe_samples(&samples, sr, 1, &lang, &lang)?;
+ let full = t.elapsed().as_secs_f64();
+ println!(
+ "\nfull utterance ({:.1}s) -> {:.0} ms ({} tokens, {:.1}x realtime)",
+ duration,
+ full * 1000.0,
+ r.tokens.len(),
+ duration as f64 / full
+ );
+ println!("text: {}", r.text);
+
+ Ok(())
+}
diff --git a/vendor/extra/qwentts.cpp/examples/all.sh b/vendor/extra/qwentts.cpp/examples/all.sh
new file mode 100755
index 0000000..f0b701c
--- /dev/null
+++ b/vendor/extra/qwentts.cpp/examples/all.sh
@@ -0,0 +1,99 @@
+#!/bin/bash
+# Matriz completa de pruebas de qwentts.cpp con los modelos disponibles.
+# Genera un WAV por cada posibilidad en examples/out/ y un resumen al final.
+# Uso: ./all.sh
+set -u
+cd "$(dirname "$0")"
+
+TTS=../build/qwen-tts
+CODEC=../build/qwen-codec
+COD=../models/qwen-tokenizer-12hz-Q8_0.gguf
+T06B=../models/qwen-talker-0.6b-base-Q4_K_M.gguf
+T06C=../models/qwen-talker-0.6b-customvoice-Q4_K_M.gguf
+T17B=../models/qwen-talker-1.7b-base-Q8_0.gguf
+T17C=../models/qwen-talker-1.7b-customvoice-Q8_0.gguf
+T17V=../models/qwen-talker-1.7b-voicedesign-Q8_0.gguf
+OUT=out
+mkdir -p "$OUT"
+
+EN="qwentts runs entirely offline on your own machine."
+ES="Hola, esto es una prueba de sintesis de voz totalmente local."
+ZH="这是一个完全本地运行的语音合成测试。"
+
+n=0; ok=0
+# run <desc> <outfile> <texto> [args extra de qwen-tts...]
+run() {
+ local desc="$1" out="$2" text="$3"; shift 3
+ n=$((n+1))
+ printf '%2d) %-46s ' "$n" "$desc"
+ local t0 t1
+ t0=$(date +%s.%N)
+ if printf '%s' "$text" | "$TTS" --codec "$COD" --seed 42 "$@" \
+ -o "$OUT/$out" >"$OUT/$out.log" 2>&1; then
+ t1=$(date +%s.%N)
+ printf 'OK %5s %4.0fs %s\n' "$(du -h "$OUT/$out" | cut -f1)" \
+ "$(echo "$t1 - $t0" | bc)" "$out"
+ ok=$((ok+1))
+ else
+ printf 'FALLO (ver %s)\n' "$OUT/$out.log"
+ fi
+}
+
+echo "########## A. BASE (voz por defecto) ##########"
+run "Base 0.6B english" base_0.6b_en.wav "$EN" --model "$T06B" --lang english
+run "Base 1.7B english" base_1.7b_en.wav "$EN" --model "$T17B" --lang english
+run "Base 1.7B auto (autodetec)" base_1.7b_auto.wav "$EN" --model "$T17B"
+run "Base 1.7B spanish" base_1.7b_es.wav "$ES" --model "$T17B" --lang spanish
+run "Base 1.7B chinese" base_1.7b_zh.wav "$ZH" --model "$T17B" --lang chinese
+
+echo "########## B. CLONACION (referencia freeman, Base) ##########"
+run "Clone ref-wav (encode interno)" clone_refwav_1.7b.wav "$EN" --model "$T17B" --lang english \
+ --ref-wav freeman.wav --ref-text freeman.txt
+run "Clone x-vector only (solo .spk)" clone_xvec_1.7b.wav "$EN" --model "$T17B" --lang english \
+ --ref-spk freeman.spk
+run "Clone ICL (.spk+.rvq+.txt)" clone_icl_1.7b.wav "$EN" --model "$T17B" --lang english \
+ --ref-spk freeman.spk --ref-rvq freeman.rvq --ref-text freeman.txt
+run "Clone ICL 0.6B" clone_icl_0.6b.wav "$EN" --model "$T06B" --lang english \
+ --ref-spk freeman.spk --ref-rvq freeman.rvq --ref-text freeman.txt
+
+echo "########## C. CUSTOMVOICE (speakers con nombre) ##########"
+for spk in serena vivian uncle_fu ryan aiden ono_anna sohee; do
+ run "CustomVoice 1.7B $spk" "cv_1.7b_${spk}.wav" "$EN" --model "$T17C" --lang english --speaker "$spk"
+done
+run "CustomVoice 1.7B eric (sichuan, ZH)" cv_1.7b_eric_zh.wav "$ZH" --model "$T17C" --lang chinese --speaker eric
+run "CustomVoice 1.7B dylan (beijing, ZH)" cv_1.7b_dylan_zh.wav "$ZH" --model "$T17C" --lang chinese --speaker dylan
+run "CustomVoice 0.6B vivian" cv_0.6b_vivian.wav "$EN" --model "$T06C" --lang english --speaker vivian
+run "CustomVoice 1.7B vivian + instruct" cv_1.7b_vivian_instr.wav "$EN" --model "$T17C" --lang english \
+ --speaker vivian --instruct "happy, energetic"
+
+echo "########## D. VOICEDESIGN (instruccion de atributos, 1.7B) ##########"
+run "VoiceDesign male young" vd_male_young.wav "$EN" --model "$T17V" --lang english \
+ --instruct "male, young adult, moderate pitch"
+run "VoiceDesign female elderly" vd_female_elderly.wav "$EN" --model "$T17V" --lang english \
+ --instruct "female, elderly, low pitch, calm"
+run "VoiceDesign teen excited" vd_teen_excited.wav "$EN" --model "$T17V" --lang english \
+ --instruct "female, teenager, high pitch, excited and fast"
+
+echo "########## E. MUESTREO / FORMATO (Base 1.7B) ##########"
+run "Greedy (determinista)" fmt_greedy.wav "$EN" --model "$T17B" --lang english --greedy
+run "Sampled temp=1.2 top-p=0.9" fmt_temp.wav "$EN" --model "$T17B" --lang english --temp 1.2 --top-p 0.9
+run "Formato wav24" fmt_wav24.wav "$EN" --model "$T17B" --lang english --format wav24
+run "Formato wav32" fmt_wav32.wav "$EN" --model "$T17B" --lang english --format wav32
+
+echo "########## F. QWEN-CODEC (encode/decode round-trip) ##########"
+cp -f freeman.wav "$OUT/rt.wav"
+echo -n "F1) codec encode (wav -> .rvq + .spk) "
+if "$CODEC" --model "$COD" --talker "$T17B" -i "$OUT/rt.wav" >"$OUT/codec_encode.log" 2>&1; then
+ echo "OK ($(du -h "$OUT/rt.rvq" 2>/dev/null | cut -f1) rvq, $(du -h "$OUT/rt.spk" 2>/dev/null | cut -f1) spk)"
+else echo "FALLO (ver $OUT/codec_encode.log)"; fi
+cp -f "$OUT/rt.rvq" "$OUT/roundtrip.rvq"
+echo -n "F2) codec decode (.rvq -> wav round-trip) "
+if "$CODEC" --model "$COD" -i "$OUT/roundtrip.rvq" >"$OUT/codec_decode.log" 2>&1; then
+ echo "OK ($(du -h "$OUT/roundtrip.wav" 2>/dev/null | cut -f1))"
+else echo "FALLO (ver $OUT/codec_decode.log)"; fi
+
+echo
+echo "########## RESUMEN ##########"
+echo "Sintesis OK: $ok / $n"
+echo "WAVs en $(pwd)/$OUT/:"
+/bin/ls -1 "$OUT"/*.wav 2>/dev/null | sed 's|^| |'
diff --git a/vendor/extra/qwentts.cpp/examples/server-test.sh b/vendor/extra/qwentts.cpp/examples/server-test.sh
new file mode 100755
index 0000000..7242afe
--- /dev/null
+++ b/vendor/extra/qwentts.cpp/examples/server-test.sh
@@ -0,0 +1,51 @@
+#!/bin/bash
+# Prueba de punta a punta del tts-server (API OpenAI-compatible).
+set -u
+cd "$(dirname "$0")"
+OUT=out; mkdir -p "$OUT"
+PORT=8080; H=127.0.0.1; B="http://$H:$PORT"
+
+echo "== arrancando tts-server (base 1.7B) =="
+../build/tts-server \
+ --model ../models/qwen-talker-1.7b-base-Q8_0.gguf \
+ --codec ../models/qwen-tokenizer-12hz-Q8_0.gguf \
+ --alias qwen3-tts-base --host $H --port $PORT --lang auto \
+ >"$OUT/server.log" 2>&1 &
+SRV=$!
+trap 'kill $SRV 2>/dev/null' EXIT
+
+echo -n "esperando readiness"
+for i in $(seq 1 60); do
+ curl -sf "$B/v1/models" >/dev/null 2>&1 && { echo " listo"; break; }
+ kill -0 $SRV 2>/dev/null || { echo " el server murio"; tail -20 "$OUT/server.log"; exit 1; }
+ printf '.'; sleep 1
+done
+
+echo "== 1) GET /v1/models =="
+curl -s "$B/v1/models"; echo
+
+echo "== 2) voz por defecto -> wav =="
+curl -s -X POST "$B/v1/audio/speech" -H "Content-Type: application/json" \
+ -d '{"input":"This is the default server voice.","response_format":"wav","seed":42}' \
+ -o "$OUT/srv_default.wav"
+echo " $(du -h "$OUT/srv_default.wav" | cut -f1) $OUT/srv_default.wav"
+
+echo "== 3) registrar voz clonada 'freeman' (spk+rvq b64) =="
+curl -s -X POST "$B/v1/audio/voices" -H "Content-Type: application/json" \
+ -d "{\"name\":\"freeman\",\"ref_text\":\"$(cat freeman.txt)\",
+ \"spk_b64\":\"$(base64 -w0 freeman.spk)\",\"rvq_b64\":\"$(base64 -w0 freeman.rvq)\"}"
+echo
+
+echo "== 4) sintesis con la voz clonada -> wav =="
+curl -s -X POST "$B/v1/audio/speech" -H "Content-Type: application/json" \
+ -d '{"input":"Now I am speaking with the cloned voice.","voice":"freeman","response_format":"wav","seed":42,"temperature":0.8}' \
+ -o "$OUT/srv_freeman.wav"
+echo " $(du -h "$OUT/srv_freeman.wav" | cut -f1) $OUT/srv_freeman.wav"
+
+echo "== 5) streaming PCM (s16le) -> archivo raw =="
+curl -s -X POST "$B/v1/audio/speech" -H "Content-Type: application/json" \
+ -d '{"input":"Streaming pcm chunks.","response_format":"pcm","seed":42}' \
+ -o "$OUT/srv_stream.pcm"
+echo " $(du -h "$OUT/srv_stream.pcm" | cut -f1) $OUT/srv_stream.pcm (s16le mono 24k)"
+
+echo "== ok, parando server =="