"""Wakeword benchmark: deterministic parts (script, audio decode, framing, scoring). The network parts (TTS /audio/speech, streaming to wyoming-openwakeword) need live servers and are exercised manually from Settings → Benchmark; here we cover everything that can be checked offline. """ import io import json import random import wave import numpy as np from blitztext import wakeword_bench as wb def test_wakeword_phrase(): assert wb.wakeword_phrase("okay_computer") == "okay computer" assert wb.wakeword_phrase("hey_jarvis") == "hey jarvis" assert wb.wakeword_phrase("models/okay_nabu.tflite") == "okay nabu" assert wb.wakeword_phrase("alexa_v0.1") == "alexa" def test_build_utterances_deterministic_and_covers_voices(): a = wb.build_utterances("computer", 8, "de", voices=["nova", "onyx"], rng=random.Random(7)) b = wb.build_utterances("computer", 8, "de", voices=["nova", "onyx"], rng=random.Random(7)) key = lambda us: [(u.text, u.has_wakeword, u.voice) for u in us] assert key(a) == key(b) # seeded → reproducible assert sum(u.has_wakeword for u in a) == 8 assert all(u.voice in ("nova", "onyx") for u in a) assert all("computer" in u.text for u in a if u.has_wakeword) assert any(not u.has_wakeword for u in a) # filler added for false-fire check def test_wav_to_pcm_resamples_to_16k_mono(): buf = io.BytesIO() with wave.open(buf, "wb") as w: w.setnchannels(2); w.setsampwidth(2); w.setframerate(48000) n = 48000 # 1.0 s stereo @ 48 kHz tone = (np.sin(2 * np.pi * 440 * np.linspace(0, 1, n, endpoint=False)) * 8000).astype("