graficar_respuesta_del_barrido_en_frecuencia_con_python

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
graficar_respuesta_del_barrido_en_frecuencia_con_python [2024/06/02 22:36] – [Notas Adicionales] osograficar_respuesta_del_barrido_en_frecuencia_con_python [2024/10/17 21:42] (current) – external edit 127.0.0.1
Line 212: Line 212:
   * **Seguridad Auditiva**: Asegúrate de mantener el volumen a un nivel seguro para evitar daños auditivos, especialmente cuando trabajes con frecuencias altas y barridos de amplio rango.   * **Seguridad Auditiva**: Asegúrate de mantener el volumen a un nivel seguro para evitar daños auditivos, especialmente cuando trabajes con frecuencias altas y barridos de amplio rango.
  
-Prueba este script ajusta los parámetros según tus necesidades. ¡Buena suerte con tu análisis de la respuesta en frecuencia de tu dispositivo de sonido!+===== Ventana de Hann media móvil =====
  
 +<code python: sweep_Hanning_5x_movingavg.py>
 +import numpy as np
 +import pyaudio
 +import matplotlib.pyplot as plt
 +from scipy.signal import get_window, butter, filtfilt
 +from scipy.fft import fft
  
 +def generate_sweep(start_freq, end_freq, duration, sample_rate=44100):
 +    t = np.linspace(0, duration, int(sample_rate * duration), False)
 +    sweep = np.sin(2 * np.pi * np.logspace(np.log10(start_freq), np.log10(end_freq), t.size))
 +    return t, sweep
 +
 +def play_and_record(sweep, duration, sample_rate=44100, channels=1):
 +    p = pyaudio.PyAudio()
 +    
 +    stream = p.open(format=pyaudio.paFloat32,
 +                    channels=channels,
 +                    rate=sample_rate,
 +                    output=True,
 +                    input=True,
 +                    frames_per_buffer=1024)
 +    
 +    recorded_frames = []
 +    
 +    stream.start_stream()
 +    stream.write(sweep.astype(np.float32).tobytes())
 +    
 +    for _ in range(0, int(sample_rate / 1024 * duration)):
 +        data = stream.read(1024)
 +        recorded_frames.append(np.frombuffer(data, dtype=np.float32))
 +    
 +    stream.stop_stream()
 +    stream.close()
 +    p.terminate()
 +    
 +    recorded_signal = np.hstack(recorded_frames)
 +    return recorded_signal
 +
 +def analyze_frequency_response(sweep, recorded_signal, sample_rate=44100):
 +    len_min = min(len(sweep), len(recorded_signal))
 +    sweep = sweep[:len_min]
 +    recorded_signal = recorded_signal[:len_min]
 +    
 +    # Aplicar una ventana de Hann
 +    window = get_window('hann', len(recorded_signal))
 +    yf = fft(recorded_signal * window)
 +    xf = np.fft.fftfreq(len(recorded_signal), 1 / sample_rate)
 +    
 +    # Solo tomar la parte positiva del espectro
 +    pos_freqs = xf[:len(xf) // 2]
 +    power = np.abs(yf[:len(yf) // 2]) ** 2
 +    
 +    return pos_freqs, power
 +
 +def moving_average(data, window_size):
 +    return np.convolve(data, np.ones(window_size)/window_size, mode='valid')
 +
 +def plot_frequency_response(frequencies, power):
 +    power += 1e-10  # Agregar un valor pequeño para evitar log10(0)
 +    smoothed_power = moving_average(10 * np.log10(power), 1000)  # Ajusta el tamaño de la ventana según sea necesario
 +
 +    plt.figure(figsize=(10, 6))
 +    plt.plot(frequencies[:len(smoothed_power)], smoothed_power, label='Smoothed Response')
 +    plt.plot(frequencies, 10 * np.log10(power), alpha=0.3, label='Original Response')
 +    plt.title('Frequency Response')
 +    plt.xlabel('Frequency (Hz)')
 +    plt.ylabel('Power (dB)')
 +    plt.xscale('log')
 +    plt.grid()
 +    plt.legend()
 +    plt.show()
 +
 +if __name__ == "__main__":
 +    start_freq = 20
 +    end_freq = 20000
 +    duration = 10  # Duración en segundos
 +    sample_rate = 44100
 +    
 +    t, sweep = generate_sweep(start_freq, end_freq, duration, sample_rate)
 +    recorded_signals = [play_and_record(sweep, duration, sample_rate) for _ in range(5)]
 +    
 +    # Promediar las respuestas en frecuencia
 +    power_avg = np.zeros(len(recorded_signals[0]) // 2)
 +    for recorded_signal in recorded_signals:
 +        frequencies, power = analyze_frequency_response(sweep, recorded_signal, sample_rate)
 +        power_avg += power
 +    power_avg /= len(recorded_signals)
 +    
 +    plot_frequency_response(frequencies, power_avg)
 +</code>
 +
 +==== Resultado ====
 +
 +{{:sweep_hann_window_test01.png?nolink|}}
 +
 +{{:figure_1_probing.png?nolink|}}
graficar_respuesta_del_barrido_en_frecuencia_con_python.1717367794.txt.gz · Last modified: 2024/10/17 21:42 (external edit)