diff --git a/vigilancia/voz.py b/vigilancia/voz.py index 78f402f..132f8dd 100644 --- a/vigilancia/voz.py +++ b/vigilancia/voz.py @@ -156,37 +156,37 @@ def _esperar_fin(cast, url, timeout=120): def _generar_pitido(): - """Genera una sirena estilo Proteccion Civil (wail) si no existe.""" + """Genera sirena estilo Proteccion Civil (wail). Usa solo math (sin numpy).""" + import math, struct ruta = os.path.join(MEDIA_DIR, "pitido_emergencia.wav") if os.path.exists(ruta): return ruta try: - import numpy as np - import wave as _wave - os.makedirs(MEDIA_DIR, exist_ok=True) sr = 44100 dur = config.GOOGLE_TV_PITIDO_SG - t = np.linspace(0, dur, int(sr * dur), endpoint=False) - if config.GOOGLE_TV_PITIDO_ESTILO == "wail": - # wail defensa civil: sube 400->1000 y baja en ciclos de ~4s - periodo = 4.0 - fase = (t % periodo) / periodo - freq = 400 + 600 * (1 - abs(2 * fase - 1)) - else: - freq = 500 + 400 * np.abs(np.sin(2 * np.pi * 0.5 * t)) - fase = 2 * np.pi * np.cumsum(freq) / sr - y = 0.8 * np.sin(fase) - fade = min(0.3, dur / 4) - n_fade = int(fade * sr) - y[:n_fade] *= np.linspace(0, 1, n_fade) - y[-n_fade:] *= np.linspace(1, 0, n_fade) - data = (y * 32767).astype(np.int16) - with _wave.open(ruta, "w") as w: - w.setnchannels(1) - w.setsampwidth(2) - w.setframerate(sr) - w.writeframes(data.tobytes()) + n = int(sr * dur) + periodo = 4.0 + nfade = min(int(0.3 * sr), n // 4) + phase = 0.0 + samples = [] + for i in range(n): + t = i / sr + if config.GOOGLE_TV_PITIDO_ESTILO == "wail": + f = (t % periodo) / periodo + freq = 400 + 600 * (1 - abs(2 * f - 1)) + else: + freq = 500 + 400 * abs(math.sin(2 * math.pi * 0.5 * t)) + phase += 2 * math.pi * freq / sr + y = 0.8 * math.sin(phase) + if i < nfade: y *= i / nfade + elif i > n - nfade: y *= (n - i) / nfade + samples.append(struct.pack("