Files
mission-control-v2/client/lucy-tts/diag_voice_f0.py
T
Hitonabi 09a1c98514 Lucy-TTS/F5: Skripte + Batches versionieren, schwere Assets ignoriert
- pocket_server.py (Produktions-TTS mit Stimmen-Waechter), text_norm, Bench-/Diag-Skripte
- lucy-f5: f5_server/f5_test/bench_dml (DirectML-Experiment, Phase C/D offen)
- .gitignore: venvs/Modelle/Audio/Logs der beiden Ordner + box_recon/gemma_swap-Scratch

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 10:29:33 +02:00

45 lines
1.9 KiB
Python

# -*- coding: utf-8 -*-
"""Verifiziert die 'Stimme wurde männlich'-Hypothese: misst F0 (Grundfrequenz) vieler Generierungen
bei temp 0.9 vs 0.7. Weiblich (Saber-Klon) ~180-240Hz, männlich-Drift (Default 'juergen') ~100-140Hz.
Sucht Ausreißer = Stimm-Identitäts-Kollaps."""
import os, numpy as np, librosa, soundfile as sf
from pocket_tts import TTSModel
BASE = r"F:\Coding Stuff\mission-control-2\client\lucy-tts"
src,_ = librosa.load(os.path.join(BASE,"ref.mp3"), sr=24000, mono=True)
srt,_ = librosa.effects.trim(src, top_db=30); ref=os.path.join(BASE,"ref.wav")
sf.write(ref, srt[:int(18*24000)], 24000)
LEAD="Tja. "
TEXTS = [
"Hallo Commander, ich höre dich.",
"Natürlich, Commander, das mache ich sofort.",
"Die Hitze in Hamburg ist heute wirklich heftig.",
"Klar, ich kümmere mich gleich darum für dich.",
"Guten Morgen, Commander, alles läuft sauber.",
"Das Backup ist durchgelaufen, keine Fehler.",
]
def median_f0(a, sr):
f0,_,_ = librosa.pyin(a, fmin=80, fmax=400, sr=sr, frame_length=1024)
v = f0[~np.isnan(f0)]
return float(np.median(v)) if v.size else float("nan")
def run(temp):
m = TTSModel.load_model(language="german_24l", lsd_decode_steps=6, temp=temp)
vs = m.get_state_for_audio_prompt(ref); sr=m.sample_rate
print(f"=== temp={temp} ===", flush=True)
f0s=[]
for i,t in enumerate(TEXTS):
a = m.generate_audio(vs, LEAD+t, frames_after_eos=4)
a = a.numpy() if hasattr(a,"numpy") else np.asarray(a)
a = np.asarray(a,dtype=np.float32).reshape(-1)
f0 = median_f0(a, sr); f0s.append(f0)
flag = " <<< MÄNNLICH?" if (f0==f0 and f0<150) else ""
print(f" [{i}] F0={f0:6.1f}Hz{flag} ({t[:30]})", flush=True)
arr=np.array([x for x in f0s if x==x])
print(f" -> median {np.median(arr):.0f}Hz, min {arr.min():.0f}, max {arr.max():.0f}", flush=True)
run(0.9)
run(0.7)
print("F0_DONE")