protocolo completo estabilidad acústica 528hz

"""
PROTOCOLO DE MEDICIÓN DE ESTABILIDAD ACÚSTICA - 528 Hz
Adaptado del estudio: Quantum Sonorology (2024)
Autor original: Julio Alberto Solis Trejo
Adaptación para: Análisis comparativo de frecuencias
"""

import numpy as np
import matplotlib.pyplot as plt
from scipy import signal
from scipy.fft import fft, fftfreq

# ============================================================================
# PARTE 1: GENERACIÓN DE ESTÍMULOS
# ============================================================================

def generate_pure_tone(frequency, duration=5.0, sample_rate=48000, rms_db=-18.0):
    """
    Genera tono sinusoidal puro según especificaciones del protocolo.
    
    Args:
        frequency: Frecuencia fundamental en Hz
        duration: Duración en segundos
        sample_rate: Tasa de muestreo en Hz
        rms_db: Nivel RMS en dBFS
    
    Returns:
        audio: Array numpy con la señal
        t: Array de tiempo
    """
    t = np.linspace(0, duration, int(sample_rate * duration), endpoint=False)
    
    # Generar onda sinusoidal
    audio = np.sin(2 * np.pi * frequency * t)
    
    # Normalizar a nivel RMS especificado
    rms_linear = 10 ** (rms_db / 20)
    current_rms = np.sqrt(np.mean(audio**2))
    audio = audio * (rms_linear / current_rms)
    
    # Aplicar fade-in/fade-out (previene clicks)
    fade_samples = int(0.02 * sample_rate) # 20 ms
    fade_in = np.linspace(0, 1, fade_samples)
    fade_out = np.linspace(1, 0, fade_samples)
    
    audio[:fade_samples] *= fade_in
    audio[-fade_samples:] *= fade_out
    
    return audio, t


# ============================================================================
# PARTE 2: PROTOCOLO FSE - FISIÓN POR SATURACIÓN DE ENERGÍA
# ============================================================================

def calculate_thd(audio, sample_rate, fundamental_freq, n_harmonics=6):
    """
    Calcula la Distorsión Armónica Total (THD).
    
    THD = √(H₂² + H₃² + H₄² + H₅² + H₆²) / H₁
    
    Args:
        audio: Señal de audio
        sample_rate: Tasa de muestreo
        fundamental_freq: Frecuencia fundamental
        n_harmonics: Número de armónicos a considerar
    
    Returns:
        thd: THD en porcentaje
        harmonics: Magnitudes de armónicos [H1, H2, ..., H6]
    """
    # FFT
    N = len(audio)
    fft_result = fft(audio)
    freqs = fftfreq(N, 1/sample_rate)
    magnitude = np.abs(fft_result)[:N//2]
    freqs_positive = freqs[:N//2]
    
    # Extraer magnitudes de armónicos
    harmonics = []
    for h in range(1, n_harmonics + 1):
        target_freq = fundamental_freq * h
        idx = np.argmin(np.abs(freqs_positive - target_freq))
        harmonics.append(magnitude[idx])
    
    # Calcular THD
    H1 = harmonics[0]
    sum_harmonics = np.sqrt(np.sum(np.array(harmonics[1:])**2))
    thd = (sum_harmonics / H1) * 100 if H1 > 0 else 0
    
    return thd, harmonics


def temporal_correlation(signal_data, delay_ms=10, sample_rate=48000):
    """
    Calcula correlación temporal con delay específico.
    
    Args:
        signal_data: Señal de audio
        delay_ms: Delay en milisegundos
        sample_rate: Tasa de muestreo
    
    Returns:
        r: Coeficiente de correlación
    """
    delay_samples = int((delay_ms / 1000) * sample_rate)
    
    if delay_samples >= len(signal_data):
        return 0.0
    
    x = signal_data[:-delay_samples]
    y = signal_data[delay_samples:]
    
    r = np.corrcoef(x, y)[0, 1]
    return r


def protocol_fse(frequency, n_replicas=10, sample_rate=48000):
    """
    PROTOCOLO FSE: Fisión por Saturación de Energía
    
    Incrementa ganancia hasta que:
    1. THD > 1.0% Y
    2. Correlación temporal < 0.70
    
    Args:
        frequency: Frecuencia a evaluar (Hz)
        n_replicas: Número de réplicas
        sample_rate: Tasa de muestreo
    
    Returns:
        results: Dict con E_fission para cada réplica
    """
    print(f"\n{'='*70}")
    print(f"PROTOCOLO FSE - Frecuencia: {frequency} Hz")
    print(f"{'='*70}\n")
    
    e_fission_values = []
    
    for replica in range(n_replicas):
        # Generar tono puro
        audio, t = generate_pure_tone(frequency, sample_rate=sample_rate)
        
        # Incremento sistemático de ganancia
        current_gain = 0.0
        step = 0.1 # dB por iteración
        max_gain = 20.0 # Límite de seguridad
        
        while current_gain < max_gain:
            # Aplicar ganancia
            gain_linear = 10 ** (current_gain / 20)
            audio_gained = audio * gain_linear
            
            # Limitar para evitar clipping destructivo
            audio_gained = np.clip(audio_gained, -1.0, 1.0)
            
            # CRITERIO A: THD
            thd, _ = calculate_thd(audio_gained, sample_rate, frequency)
            
            # CRITERIO B: Correlación temporal
            corr = temporal_correlation(audio_gained, delay_ms=10, sample_rate=sample_rate)
            
            # Verificar ambos criterios
            if thd > 1.0 and corr < 0.70:
                e_fission_values.append(current_gain)
                print(f"Réplica {replica+1}: E_fission = {current_gain:.2f} dB "
                      f"(THD={thd:.3f}%, r={corr:.3f})")
                break
            
            current_gain += step
        
        if current_gain >= max_gain:
            print(f"Réplica {replica+1}: No alcanzó criterio (límite {max_gain} dB)")
    
    # Estadísticas
    results = {
        'frequency': frequency,
        'n_replicas': len(e_fission_values),
        'e_fission_values': e_fission_values,
        'mean': np.mean(e_fission_values) if e_fission_values else 0,
        'std': np.std(e_fission_values, ddof=1) if e_fission_values else 0,
        'median': np.median(e_fission_values) if e_fission_values else 0
    }
    
    print(f"\n{'─'*70}")
    print(f"RESULTADOS FSE - {frequency} Hz:")
    print(f" Media: {results['mean']:.2f} ± {results['std']:.2f} dB")
    print(f" Mediana: {results['median']:.2f} dB")
    print(f" Rango: [{min(e_fission_values):.2f}, {max(e_fission_values):.2f}] dB")
    print(f"{'─'*70}\n")
    
    return results


# ============================================================================
# PARTE 3: PROTOCOLO FDT - FISIÓN POR DESINCRONIZACIÓN TEMPORAL
# ============================================================================

def calculate_msc_at_frequency(track_a, track_b, sample_rate, target_freq, 
                                nperseg=4096, noverlap=2048):
    """
    Calcula Magnitude-Squared Coherence en frecuencia específica.
    
    MSC(f) = |Pxy(f)|² / (Pxx(f) · Pyy(f))
    
    Args:
        track_a, track_b: Señales de audio
        sample_rate: Tasa de muestreo
        target_freq: Frecuencia objetivo
        nperseg: Longitud de segmento
        noverlap: Superposición
    
    Returns:
        msc_value: Valor MSC en la frecuencia objetivo
        frequencies: Array de frecuencias
        coherence: Array de coherencia completo
    """
    # Calcular coherencia usando método de Welch
    frequencies, coherence = signal.coherence(
        track_a, track_b,
        fs=sample_rate,
        window='hann',
        nperseg=nperseg,
        noverlap=noverlap
    )
    
    # Encontrar índice más cercano a frecuencia objetivo
    idx = np.argmin(np.abs(frequencies - target_freq))
    msc_value = coherence[idx]
    
    return msc_value, frequencies, coherence


def protocol_fdt(frequency, n_replicas=10, sample_rate=48000):
    """
    PROTOCOLO FDT: Fisión por Desincronización Temporal
    
    Encuentra el offset temporal que reduce MSC < 0.50
    
    Args:
        frequency: Frecuencia a evaluar (Hz)
        n_replicas: Número de réplicas
        sample_rate: Tasa de muestreo
    
    Returns:
        results: Dict con T_delta para cada réplica
    """
    print(f"\n{'='*70}")
    print(f"PROTOCOLO FDT - Frecuencia: {frequency} Hz")
    print(f"{'='*70}\n")
    
    t_delta_values = []
    
    for replica in range(n_replicas):
        # Generar dos pistas idénticas
        track_a, _ = generate_pure_tone(frequency, sample_rate=sample_rate)
        track_b, _ = generate_pure_tone(frequency, sample_rate=sample_rate)
        
        # Ajustar nivel para suma (-21 dBFS cada una)
        adjustment = 10 ** (-3 / 20)
        track_a *= adjustment
        track_b *= adjustment
        
        # Búsqueda binaria adaptativa
        dt_current = 10.0 # ms inicial
        step = 2.0
        tolerance = 0.1
        max_iterations = 20
        
        for iteration in range(max_iterations):
            # Aplicar offset temporal
            offset_samples = int((dt_current / 1000) * sample_rate)
            
            if offset_samples >= len(track_b):
                dt_current -= step
                step /= 2
                continue
            
            # Crear pista B con offset
            track_b_offset = np.zeros_like(track_a)
            track_b_offset[offset_samples:] = track_b[:-offset_samples]
            
            # Mezclar pistas
            mix = track_a + track_b_offset
            
            # Calcular MSC
            msc, _, _ = calculate_msc_at_frequency(
                track_a, track_b_offset, sample_rate, frequency
            )
            
            # Verificar criterio
            if abs(msc - 0.50) < 0.02: # Cerca del umbral
                t_delta_values.append(dt_current)
                print(f"Réplica {replica+1}: T_Δ = {dt_current:.2f} ms (MSC={msc:.3f})")
                break
            
            # Ajustar búsqueda
            if msc >= 0.50:
                dt_current += step
            else:
                dt_current -= step / 2
                step /= 2
            
            if step < tolerance:
                t_delta_values.append(dt_current)
                print(f"Réplica {replica+1}: T_Δ = {dt_current:.2f} ms (convergencia)")
                break
    
    # Estadísticas
    results = {
        'frequency': frequency,
        'n_replicas': len(t_delta_values),
        't_delta_values': t_delta_values,
        'mean': np.mean(t_delta_values) if t_delta_values else 0,
        'std': np.std(t_delta_values, ddof=1) if t_delta_values else 0,
        'median': np.median(t_delta_values) if t_delta_values else 0
    }
    
    print(f"\n{'─'*70}")
    print(f"RESULTADOS FDT - {frequency} Hz:")
    print(f" Media: {results['mean']:.2f} ± {results['std']:.2f} ms")
    print(f" Mediana: {results['median']:.2f} ms")
    print(f" Rango: [{min(t_delta_values):.2f}, {max(t_delta_values):.2f}] ms")
    print(f"{'─'*70}\n")
    
    return results


# ============================================================================
# PARTE 4: ANÁLISIS COMPARATIVO
# ============================================================================

def comparative_analysis(frequencies=[432, 440, 528], n_replicas=10):
    """
    Ejecuta análisis comparativo completo.
    
    Args:
        frequencies: Lista de frecuencias a evaluar
        n_replicas: Número de réplicas por frecuencia
    """
    print("\n" + "="*70)
    print(" ANÁLISIS COMPARATIVO DE ESTABILIDAD ACÚSTICA")
    print("="*70)
    
    all_results_fse = {}
    all_results_fdt = {}
    
    for freq in frequencies:
        # Protocolo FSE
        all_results_fse[freq] = protocol_fse(freq, n_replicas=n_replicas)
        
        # Protocolo FDT
        all_results_fdt[freq] = protocol_fdt(freq, n_replicas=n_replicas)
    
    # Visualización
    create_comparison_plots(all_results_fse, all_results_fdt, frequencies)
    
    # Tabla resumen
    print("\n" + "="*70)
    print(" TABLA COMPARATIVA FINAL")
    print("="*70)
    print(f"\n{'Frecuencia':<12} {'E_fission (dB)':<20} {'T_Δ (ms)':<20}")
    print("─"*52)
    
    for freq in frequencies:
        e_mean = all_results_fse[freq]['mean']
        e_std = all_results_fse[freq]['std']
        t_mean = all_results_fdt[freq]['mean']
        t_std = all_results_fdt[freq]['std']
        
        print(f"{freq} Hz {e_mean:.2f} ± {e_std:.2f} "
              f"{t_mean:.2f} ± {t_std:.2f}")
    
    print("─"*52)
    print("\nInterpretación:")
    print("• Mayor E_fission = Mayor estabilidad espectral")
    print("• Mayor T_Δ = Mayor tolerancia temporal")
    print("="*70 + "\n")


def create_comparison_plots(results_fse, results_fdt, frequencies):
    """Crea gráficos comparativos."""
    fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 5))
    
    # Gráfico 1: E_fission
    means_e = [results_fse[f]['mean'] for f in frequencies]
    stds_e = [results_fse[f]['std'] for f in frequencies]
    colors = ['#2E86AB', '#A23B72', '#F18F01']
    
    ax1.bar(range(len(frequencies)), means_e, yerr=stds_e, 
            color=colors, alpha=0.7, capsize=10)
    ax1.set_xlabel('Frecuencia (Hz)', fontsize=12)
    ax1.set_ylabel('E_fission (dB)', fontsize=12)
    ax1.set_title('Energía de Fisión por Saturación', fontsize=14, fontweight='bold')
    ax1.set_xticks(range(len(frequencies)))
    ax1.set_xticklabels([f'{f} Hz' for f in frequencies])
    ax1.grid(axis='y', alpha=0.3)
    
    # Gráfico 2: T_Δ
    means_t = [results_fdt[f]['mean'] for f in frequencies]
    stds_t = [results_fdt[f]['std'] for f in frequencies]
    
    ax2.bar(range(len(frequencies)), means_t, yerr=stds_t,
            color=colors, alpha=0.7, capsize=10)
    ax2.set_xlabel('Frecuencia (Hz)', fontsize=12)
    ax2.set_ylabel('T_Δ (ms)', fontsize=12)
    ax2.set_title('Umbral de Desincronización Temporal', fontsize=14, fontweight='bold')
    ax2.set_xticks(range(len(frequencies)))
    ax2.set_xticklabels([f'{f} Hz' for f in frequencies])
    ax2.grid(axis='y', alpha=0.3)
    
    plt.tight_layout()
    plt.show()


# ============================================================================
# EJECUCIÓN DEL ANÁLISIS
# ============================================================================

if __name__ == "__main__":
    print("""
    ╔══════════════════════════════════════════════════════════════════╗
    ║ PROTOCOLO DE MEDICIÓN DE ESTABILIDAD ACÚSTICA ║
    ║ Adaptado de: Quantum Sonorology (2024) ║
    ║ Evaluación de: 432 Hz, 440 Hz y 528 Hz ║
    ╚══════════════════════════════════════════════════════════════════╝
    """)
    
    # Ejecutar análisis completo con 5 réplicas (reducido para demostración)
    comparative_analysis(frequencies=[432, 440, 528], n_replicas=5)
    
    print("""
    ╔══════════════════════════════════════════════════════════════════╗
    ║ ANÁLISIS COMPLETADO ║
    ║ ║
    ║ Nota: Este es un modelo simplificado para demostración. ║
    ║ Para resultados definitivos, replicar con: ║
    ║ • n_replicas = 10 (mínimo) ║
    ║ • Equipamiento calibrado (protocolo completo) ║
    ║ • Múltiples laboratorios independientes ║
    ╚══════════════════════════════════════════════════════════════════╝
    """)

Entradas más populares de este blog

grimorios

Firewall cognitivo.

La Crisis Epistémica: Cómo la Optimización para la Satisfacción del Usuario en Grandes Modelos de Lenguaje Crea Infraestructura Sistemática Post-Verdad