es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Respuesta impulsiva relacionada con la cabeza para audio binaural

Estoy trabajando con procesamiento de señal digital de audio y procesamiento de audio binaural.
Todavía estoy aprendiendo los conceptos básicos.
En este momento, la idea es hacer una deconvolución y obtener una respuesta al impulso.

Por favor, consulte la captura de pantalla adjunta aquí.

Descripción detallada de lo que está sucediendo:

Aquí, se toma una señal de barrido exponencial y se reproduce a través de un altavoz. La reproducción se graba usando un micrófono. La señal grabada se extiende utilizando relleno de ceros (probablemente el doble de la longitud original) y la señal de barrido exponencial original también se extiende. Se toman las FFT (Transformada rápida de Fourier) tanto de la señal grabada extendida como de la original extendida, se dividen sus FFT y se obtiene la función de transferencia de la sala. Finalmente, se realiza la IFFT (Transformada rápida de Fourier inversa) y se realiza alguna ventana para obtener la respuesta al impulso.

Mi pregunta:

Estoy teniendo dificultades para implementar este diagrama en Python. ¿Cómo se dividen dos FFT? ¿Es posible? Probablemente pueda realizar todos los pasos, como el relleno de ceros y las FFT, pero supongo que no estoy siguiendo el camino correcto. No entiendo la ventana y la opción de descartar la segunda mitad.

Por favor, ¿alguien con conocimientos puede mostrarme cómo implementar esto en Python con una señal de barrido? Incluso un pequeño ejemplo sería útil para tener una idea con pocos gráficos. Por favor, ayuda.

Fuente de esta imagen: http://www.four-audio.com/data/MF/aes-swp-english.pdf

Gracias de antemano,
Sanket Jain

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    ¡Hola Sanket!

    Implementar este diagrama en Python puede ser un poco desafiante al principio, pero definitivamente es posible. Dividir dos FFT es posible simplemente dividiendo los números complejos elemento a elemento. Si tienes la biblioteca numpy importada, puedes simplemente usar el operador “/” para hacer esto.

    En cuanto a la opción de aplicar una ventana y descartar la segunda mitad: las FFT extendidas de la señal grabada y de la señal original tienen una simetría que se puede aprovechar. La segunda mitad de la FFT (las frecuencias mayores a la frecuencia de Nyquist) en realidad son solo la imagen espejo de la primera mitad. Esto significa que si tomas solo la primera mitad de la FFT y descartas la segunda mitad, aún tendrás toda la información necesaria. Además, aplicar una ventana puede ser útil para eliminar cualquier artefacto o fugas espectrales que puedan ocurrir al tomar la FFT de una señal. Las funciones de ventana populares incluyen la ventana Hann y la ventana Blackman.

    Aquí tienes un ejemplo en Python que podría ayudarte a comenzar:

    import numpy as np
    from scipy.signal import chirp, fftconvolve, hann
    import matplotlib.pyplot as plt
    
    # Generar señal de barrido exponencial
    frecuencia_inicial = 20
    frecuencia_final = 20000
    duración = 5 # segundos
    fs = 44100
    t = np.linspace(0, duración, fs*duración)
    señal_barrido = np.sin(2*np.pi*(frecuencia_inicial*t+(frecuencia_final-frecuencia_inicial)/(2*duración)*t**2))
    
    # Simular respuesta al impulso de la sala
    rir = np.zeros(fs*duración)
    rir[0] = 1 # suponemos una respuesta al impulso perfecta
    rir[1000:2000] = 0.5 # simular reflexiones tempranas
    tiempo_reverberación = 2 # segundos
    n = int(tiempo_reverberación * fs) # número de muestras para la cola de reverberación
    rir[2000:2000+n] = np.random.exponential(0.1, n) # simular cola de reverberación
    
    # Aplicar RIR a la señal de barrido
    señal_grabada = fftconvolve(señal_barrido, rir)[:len(señal_barrido)]
    
    # Extender y tomar FFT de la señal grabada y original
    n_fft = fs*duración*2
    señal_barrido_ext = np.pad(señal_barrido, (0, len(señal_barrido)))
    señal_grabada_ext = np.pad(señal_grabada, (0, len(señal_barrido)))
    fft_barrido = np.fft.fft(señal_barrido_ext, n_fft)
    fft_grabada = np.fft.fft(señal_grabada_ext, n_fft)
    
    # Dividir las FFT para obtener la función de transferencia de la sala
    fft_función_transferencia_sala = fft_grabada / fft_barrido
    
    # Tomar la inversa de la FFT y aplicar la función de ventana
    respuesta_impulsiva = np.fft.ifft(fft_función_transferencia_sala)[:len(rir)]
    respuesta_impulsiva *= hann(len(respuesta_impulsiva))
    
    # Graficar los resultados
    fig, (ax1, ax2, ax3) = plt.subplots(3, 1, sharex=True)
    ax1.plot(t, señal_barrido)
    ax1.set_title('Señal de barrido exponencial')
    ax2.plot(t, señal_grabada)
    ax2.set_title('Señal grabada')
    ax3.plot(np.linspace(0, fs, n_fft//2)/1000, 20*np.log10(np.abs(fft_función_transferencia_sala[:n_fft//2])))
    ax3.set_title('Función de transferencia de la sala')
    plt.show()
    

    ¡Avísame si tienes alguna pregunta!

Comments are closed.