from __future__ import annotations import json import sys from dataclasses import asdict, dataclass from pathlib import Path REPO_ROOT = Path(__file__).resolve().parents[1] SRC_DIR = REPO_ROOT / "src" if str(SRC_DIR) not in sys.path: sys.path.insert(0, str(SRC_DIR)) from wfloat_tts import SPEAKER_IDS, load_generator, write_wave @dataclass(frozen=True) class SampleSpec: voice: str emotion: str intensity: float text: str SAMPLES = ( SampleSpec( voice="skilled_hero_man", emotion="joy", intensity=0.7, text="We did it! The bridge is secure and everyone made it across. Take a breath and enjoy this moment with me.", ), SampleSpec( voice="skilled_hero_woman", emotion="neutral", intensity=0.5, text="Stay close. The stones are loose near the edge. We will move carefully and get there together.", ), SampleSpec( voice="fun_hero_man", emotion="surprise", intensity=0.6, text="Wait, that worked? I pulled one lever, the whole wall spun around, and now there is treasure everywhere!", ), SampleSpec( voice="fun_hero_woman", emotion="joy", intensity=0.7, text="Come on, keep up! The crowd is cheering.", ), SampleSpec( voice="strong_hero_man", emotion="anger", intensity=0.80, text="Enough. You had your warning, and you kept pushing innocent people around. Take one more step, and I end this.", ), SampleSpec( voice="strong_hero_woman", emotion="anger", intensity=0.8, text="The chain is holding, and we are not letting this town fall today. Push harder.", ), SampleSpec( voice="mad_scientist_man", emotion="joy", intensity=0.90, text="Look at that reaction. The coils are singing, the chamber is stable, and the entire machine is finally alive. Oh, this is magnificent.", ), SampleSpec( voice="mad_scientist_woman", emotion="surprise", intensity=0.80, text="No, no, that's not possible. The formula should have crystallized, but it adapted instead. Do you realize what that means for the rest of my work?", ), SampleSpec( voice="clever_villain_man", emotion="dismissive", intensity=0.60, text="You came all this way for that little threat? I have heard sharper words from people with far less ambition. Sit down and let the adults finish the game.", ), SampleSpec( voice="clever_villain_woman", emotion="dismissive", intensity=0.74, text="Please. If that was your grand reveal, I expected more style and much better timing. You are already behind, and you still do not know the real plan.", ), SampleSpec( voice="narrator_man", emotion="neutral", intensity=0.5, text="The harbor was quiet again. The storm had passed in the night, leaving scattered crates, broken rope, and one unanswered question.", ), SampleSpec( voice="narrator_woman", emotion="sadness", intensity=0.4, text="When the letter finally arrived, no one rushed to open it. The room had grown too familiar with bad news, and hope had learned to speak softly.", ), SampleSpec( voice="wise_elder_man", emotion="anger", intensity=0.4, text="I have seen this mistake before. Pride speaks loudly in the beginning, but regret is the voice that stays with you. Listen while there is still time to change course.", ), SampleSpec( voice="wise_elder_woman", emotion="joy", intensity=0.5, text="There you are. The answer was never as far away as you feared, and your patience has finally borne fruit. Let yourself be proud of how far you have come.", ), SampleSpec( voice="outgoing_anime_man", emotion="joy", intensity=0.8, text="Yes. This is our chance, and I can feel the whole day lighting up around us. We are going in together, and we are coming out legends.", ), SampleSpec( voice="outgoing_anime_woman", emotion="surprise", intensity=0.5, text="Hold on, you are telling me that tiny mascot can drive the entire ship? That is completely ridiculous, and somehow it makes me want to see it even more.", ), SampleSpec( voice="scary_villain_man", emotion="anger", intensity=0.5, text="You should have stayed hidden. Now I know your face, your voice, and exactly how afraid you are trying not to sound. Run, if it helps you feel alive.", ), SampleSpec( voice="scary_villain_woman", emotion="fear", intensity=0.80, text="Did you hear that? The halls were silent a moment ago, and now something is moving behind the walls. Do not leave me alone with that sound.", ), SampleSpec( voice="news_reporter_man", emotion="neutral", intensity=0.5, text="We are live outside city hall, where officials say the meeting will begin within the hour. Security has tightened, and a large crowd is still gathering behind us.", ), SampleSpec( voice="news_reporter_woman", emotion="neutral", intensity=0.6, text="We are receiving conflicting reports from the scene. One agency says the system is back online, while another says key services are still down. We are working to confirm the facts.", ), ) def intensity_slug(value: float) -> str: return f"{int(round(value * 100)):03d}" def sample_filename(index: int, sample: SampleSpec) -> str: return f"{index:02d}_{sample.voice}_{sample.emotion}_{intensity_slug(sample.intensity)}.wav" def main() -> None: output_dir = REPO_ROOT / "samples" output_dir.mkdir(parents=True, exist_ok=True) generator = load_generator( checkpoint_path=REPO_ROOT / "model.safetensors", config_path=REPO_ROOT / "config.json", ) manifest: list[dict[str, object]] = [] for index, sample in enumerate(SAMPLES, start=1): sid = SPEAKER_IDS[sample.voice] audio = generator.generate( text=sample.text, sid=sid, emotion=sample.emotion, intensity=sample.intensity, ) filename = sample_filename(index, sample) output_path = output_dir / filename write_wave(output_path, audio.samples, audio.sample_rate) manifest.append( { "filename": filename, "sid": sid, **asdict(sample), } ) print(output_path.relative_to(REPO_ROOT)) manifest_path = output_dir / "manifest.json" manifest_path.write_text(json.dumps(manifest, indent=2) + "\n", encoding="utf-8") print(manifest_path.relative_to(REPO_ROOT)) if __name__ == "__main__": main()