fractal / app.py
gnosticdev's picture
Update app.py
12361b7 verified
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()