#!/usr/bin/env python3
"""Synthetische 'Plappi'-Rufe für openWakeWord-Training (positive Samples).

Erzeugt viele Varianten des Wake-Words über edge-tts (verschiedene Stimmen,
Tempi, Tonhöhen, Phrasierungen) -> 16kHz Mono WAV. Diese positiven Beispiele
+ Negativ-/Hintergrund-Daten trainieren später das openWakeWord-Modell für den Pi.

Run:  ./.venv/bin/python scripts/owww_gen_samples.py
"""
import asyncio
import subprocess
from pathlib import Path

import edge_tts

OUT = Path(__file__).resolve().parent.parent / "clients" / "pi" / "wakeword" / "samples" / "positive"
OUT.mkdir(parents=True, exist_ok=True)

VOICES = ["de-AT-IngridNeural", "de-AT-JonasNeural", "de-DE-KatjaNeural",
          "de-DE-ConradNeural", "de-DE-AmalaNeural", "sr-RS-SophieNeural",
          "sr-RS-NicholasNeural"]
PHRASES = ["Plappi", "Plappi.", "Plappi!", "Hey Plappi", "Plappi?", "Plappi, Plappi"]
RATES = ["-15%", "+0%", "+12%"]
PITCHES = ["-10Hz", "+0Hz", "+12Hz"]


async def one(voice, phrase, rate, pitch, idx):
    mp3 = OUT / f"plappi_{idx:04d}.mp3"
    wav = OUT / f"plappi_{idx:04d}.wav"
    if wav.exists():
        return True
    try:
        await edge_tts.Communicate(phrase, voice, rate=rate, pitch=pitch).save(str(mp3))
    except Exception:
        return False
    subprocess.run(["ffmpeg", "-nostdin", "-y", "-i", str(mp3),
                    "-ar", "16000", "-ac", "1", str(wav)], capture_output=True)
    mp3.unlink(missing_ok=True)
    return wav.exists()


async def main():
    tasks, idx = [], 0
    for v in VOICES:
        for p in PHRASES:
            for r in RATES:
                for pi in PITCHES:
                    # nicht alle Kombinationen (zu viele) -> jede 2. Tonhöhe je nach idx
                    if (idx % 2 == 0):
                        tasks.append(one(v, p, r, pi, idx))
                    idx += 1
    # gestaffelt ausführen (Netz-Rate)
    ok = 0
    for i in range(0, len(tasks), 12):
        ok += sum(await asyncio.gather(*tasks[i:i + 12]))
    print(f"positive Samples: {ok} WAVs in {OUT}")


if __name__ == "__main__":
    asyncio.run(main())
