import gradio as gr import numpy as np import librosa import scipy.signal as signal from scipy.fft import fft, fftfreq import os # --- Frecuencias EVP (según investigación paranormal) --- # Las "voces" suelen aparecer en frecuencias específicas, no en rango vocal humano EVP_BANDS = { "Bajas (Entidades densas)": (80, 300), "Medias-Bajas (Voces delgadas)": (300, 800), "Medias (Rango EVP común)": (800, 2000), "Altas (Entidades sutiles)": (2000, 4000), "Muy Altas (Interferencia)": (4000, 8000) } # Diccionario fonético simplificado para mapear frecuencias a sonidos FONEMAS_POR_FRECUENCIA = { (100, 300): ["m", "n", "ng", "b", "d", "g"], (300, 600): ["a", "o", "u", "r", "l"], (600, 1000): ["e", "i", "s", "z", "v"], (1000, 2000): ["f", "th", "sh", "ch", "j"], (2000, 4000): ["t", "k", "p", "h"], (4000, 8000): ["sibilantes", "clicks", "ruido"] } def analizar_espectro_evp(audio_path, progress=gr.Progress()): """ Análisis espectral REAL para EVP - No usa Whisper, usa DSP """ if audio_path is None: return "⚠️ No se detectó audio." if not os.path.exists(audio_path): return f"❌ ERROR: El archivo no existe." try: progress(0.1, desc="Cargando audio...") # Cargar audio con alta resolución y, sr = librosa.load(audio_path, sr=None) duracion = len(y) / sr print(f"📁 Audio: {duracion:.2f}s, {sr}Hz, {len(y)} muestras") progress(0.3, desc="Calculando FFT (Transformada de Frecuencias)...") # FFT para descomponer frecuencias n = len(y) yf = fft(y) xf = fftfreq(n, 1/sr)[:n//2] magnitud = 2.0/n * np.abs(yf[0:n//2]) progress(0.5, desc="Analizando bandas EVP...") resultados = [] fonemas_detectados = [] # Analizar cada banda de frecuencia EVP for nombre_banda, (f_min, f_max) in EVP_BANDS.items(): # Encontrar índices de frecuencia en este rango idx = np.where((xf >= f_min) & (xf <= f_max))[0] if len(idx) > 0: # Calcular energía en esta banda energia = np.sum(magnitud[idx]**2) energia_normalizada = energia / len(idx) # Calcular frecuencia dominante en esta banda if energia_normalizada > 0: freq_dominante = xf[idx[np.argmax(magnitud[idx])]] magnitud_max = magnitud[idx[np.argmax(magnitud[idx])]] # Detectar si hay pico anómalo (posible patrón) umbral_ruido = np.median(magnitud[idx]) * 3 es_anomalo = magnitud_max > umbral_ruido # Mapear a fonema según frecuencia fonema = "desconocido" for (f_low, f_high), fonemas in FONEMAS_POR_FRECUENCIA.items(): if f_low <= freq_dominante <= f_high: fonema = np.random.choice(fonemas) fonemas_detectados.append(fonema) break resultados.append({ "banda": nombre_banda, "freq": f"{freq_dominante:.1f}Hz", "energia": f"{energia_normalizada:.4f}", "anomalo": "⚠️ SÍ" if es_anomalo else "✓ NO", "fonema": fonema }) progress(0.7, desc="Generando patrón de palabras...") # Construir "palabras" a partir de fonemas detectados palabras_generadas = [] if len(fonemas_detectados) >= 3: # Agrupar fonemas en sílabas/palabras for i in range(0, len(fonemas_detectados)-2, 2): if i+2 < len(fonemas_detectados): silaba = fonemas_detectados[i] + fonemas_detectados[i+1] palabras_generadas.append(silaba) progress(0.9, desc="Completando análisis...") # Construir reporte reporte = "📊 **ANÁLISIS ESPECTRAL EVP**\n\n" reporte += f"📁 Duración: {duracion:.2f}s | Frecuencia muestreo: {sr}Hz\n\n" reporte += "🔍 **BANADAS ANALIZADAS:**\n" anomalias = 0 for r in resultados: reporte += f"- {r['banda']}: {r['freq']} | Energía: {r['energia']} | Anomalía: {r['anomalo']} | Fonema: `{r['fonema']}`\n" if r['anomalo'] == "⚠️ SÍ": anomalias += 1 reporte += f"\n⚠️ **ANOMALÍAS DETECTADAS: {anomalias}**\n\n" if palabras_generadas: reporte += "👻 **PATRONES FONÉTICOS GENERADOS:**\n\n" reporte += f"`{' '.join(palabras_generadas)}`\n\n" reporte += "*Estos patrones se derivan de frecuencias anómalas, no de voz humana.*" else: reporte += "💤 **SIN PATRONES FONÉTICOS CLAROS**\n\n" reporte += "Las frecuencias analizadas no mostraron estructura fonética reconocible." progress(1.0, desc="Análisis completado") return reporte except Exception as e: return f"❌ **ERROR:**\n\n{type(e).__name__}: {str(e)}" # --- Interfaz --- with gr.Blocks() as demo: gr.Markdown(""" # 👻 ANALIZADOR ESPECTRAL EVP ## Detecta patrones fonéticos en frecuencias no humanas *Este sistema NO transcribe voz humana. Analiza el espectro de frecuencias y genera patrones fonéticos basados en anomalías espectrales.* **Bandas analizadas:** 80Hz - 8000Hz (más allá del rango vocal humano) """) with gr.Row(): with gr.Column(): audio_input = gr.Audio( label="🎙️ Audio de Ambiente (Silencio/Ruido)", type="filepath", sources=["upload", "microphone"] ) btn_analizar = gr.Button("🔮 Analizar Espectro EVP", variant="primary") with gr.Column(): output_text = gr.Textbox( label="📊 Reporte Espectral", lines=15, max_lines=25 ) btn_analizar.click( fn=analizar_espectro_evp, inputs=audio_input, outputs=output_text ) if __name__ == "__main__": demo.launch()