Interpretación inexacta de FFT de audio en tiempo real con Python.
Estoy tratando de usar Python para crear una visualización de música en tiempo real. Las bibliotecas que estoy utilizando son SoundCard (para la captura de audio en vivo) y Librosa (para la transformada de Fourier en tiempo corto).
Sin embargo, sospecho que no estoy interpretando correctamente los datos de audio. Al observar el rango de frecuencia de 100Hz a 200Hz, obtengo un flujo constante de sonido incluso cuando la canción no contiene tanto bajo (o en realidad, ninguno en absoluto). Admito que estoy un poco por encima de mi nivel con todo el procesamiento de audio y la transformada de Fourier, ya que no es realmente mi especialidad y las matemáticas me confunden la mayor parte del tiempo.
Esta es la función que captura y analiza el audio. “Ib” está configurado en los altavoces y funciona correctamente. “Fs” está configurado en 48000 y grabo 1000 cuadros en un intento de mantener 48FPS. “fftwindowsize” está configurado en 2048*8 porque… no estoy seguro. Aumenté el número hasta que Librosa dejó de mostrar advertencias.
def audioanalysis():
with lb.recorder(samplerate=Fs) as mic:
rawdata = mic.record(numframes=1000)
datalen: int = int(rawdata.size/2)
monodata = numpy.empty(datalen)
for x in range(0, datalen):
monodata[x] = max(rawdata[x][0], rawdata[x][1])
data = numpy.abs(librosa.stft(monodata, n_fft=fftwindowsize, hop_length=1024))
return librosa.amplitude_to_db(data, ref=numpy.max)
Y el código para crear los “buckets”:
frequencies = librosa.core.fft_frequencies(n_fft=fftwindowsize)
freq_index_ratio = len(frequencies)/frequencies[len(frequencies)-1] / 2
[...]
for i in range(0, buckets):
avg = 0
for j in range (i * bucketsize, (i+1)*bucketsize):
avg += amp(spectrogram=spectrogram, freq=j)
amps[i] = avg/bucketsize
def amp(spectrogram, freq) -> float:
return spectrogram[int(freq*freq_index_ratio)]
A lo largo de una canción, amps[1]
(es decir, de 100Hz a 200Hz) permanece en el rango de -50dB a -30dB, lo cual no es realmente útil ni representativo de la canción que se está reproduciendo.
¿Está mal mi análisis de la transformada de Fourier? ¿No hay forma de interpretar de manera más precisa muestras cortas de sonido?
P.D. Sé que mi código en Python no es excelente. Este es mi primer proyecto en Python 🙂
davy.ai
Parece que el problema podría estar en el paso de análisis de frecuencia de tu código. Específicamente, cuando calculas la amplitud de un bin de frecuencia dado utilizando la función
amp
, estás utilizando la entradaspectrogram
y la entradafreq
para seleccionar un índice específico en el arrayspectrogram
. Sin embargo, parece que estás utilizandofreq_index_ratio
para realizar esta selección, lo cual no te dará el índice correcto para la frecuencia en la que estás interesado.En lugar de utilizar
freq_index_ratio
, prueba utilizando la funciónlibrosa.core.fft_frequencies
para obtener el índice de frecuencia correcto para una frecuencia dada. Por ejemplo, podrías modificar la funciónamp
de la siguiente manera:Esto encontrará el bin de frecuencia más cercano a la frecuencia deseada, en lugar de utilizar una aproximación como
freq_index_ratio
.Además, puede que quieras considerar el uso de un tamaño de ventana más largo para la STFT (por ejemplo, 4096 o 8192) para obtener una mejor resolución de frecuencia. Esto te permitirá capturar con mayor precisión el contenido de baja frecuencia de la señal de audio, que podría ser la causa de la corriente constante de sonido a 100-200 Hz que estás observando.
Finalmente, ten en cuenta que incluso con el mejor procesamiento posible, crear una visualización de música “en vivo” puede ser desafiante debido a la complejidad inherente y la variabilidad de la música. Es posible que algunas canciones simplemente no se presten bien a la visualización, independientemente de las técnicas de análisis utilizadas.