2009-03-02 18 views
95

Estoy intentando crear un analizador de espectro gráfico en python.Analizar audio usando Fast Fourier Transform

Actualmente estoy leyendo 1024 bytes de una secuencia de audio de frecuencia de muestreo de doble canal de 44,100 Hz de 16 bits y haciendo un promedio de la amplitud de los 2 canales. Entonces ahora tengo una matriz de 256 cortos firmados. Ahora quiero preformar un fft en ese arreglo, usando un módulo como numpy, y usar el resultado para crear el analizador de espectro gráfico, que, para comenzar, será de solo 32 bares.

He leído los artículos de la wikipedia sobre Transformación de Fourier rápida y Transformada de Fourier discreta, pero todavía no tengo claro qué representa la matriz resultante. Esto es lo que la matriz se ve como después de preforma una FFT en mi matriz mediante numpy:

[ -3.37260500e+05 +0.00000000e+00j 7.11787022e+05 +1.70667403e+04j 
    4.10040193e+05 +3.28653370e+05j 9.90933073e+04 +1.60555003e+05j 
    2.28787050e+05 +3.24141951e+05j 2.09781047e+04 +2.31063376e+05j 
    -2.15941453e+05 +1.63773851e+05j -7.07833051e+04 +1.52467334e+05j 
    -1.37440802e+05 +6.28107674e+04j -7.07536614e+03 +5.55634993e+03j 
    -4.31009964e+04 -1.74891657e+05j 1.39384348e+05 +1.95956947e+04j 
    1.73613033e+05 +1.16883207e+05j 1.15610357e+05 -2.62619884e+04j 
    -2.05469722e+05 +1.71343186e+05j -1.56779748e+04 +1.51258101e+05j 
    -2.08639913e+05 +6.07372799e+04j -2.90623668e+05 -2.79550838e+05j 
    -1.68112214e+05 +4.47877871e+04j -1.21289916e+03 +1.18397979e+05j 
    -1.55779104e+05 +5.06852464e+04j 1.95309737e+05 +1.93876325e+04j 
    -2.80400414e+05 +6.90079265e+04j 1.25892113e+04 -1.39293422e+05j 
    3.10709174e+04 -1.35248953e+05j 1.31003438e+05 +1.90799303e+05j... 

Me pregunto qué es exactamente lo que estos números representan y cómo iba a convertir estos números en un porcentaje de la altura de cada una de las 32 barras. Además, ¿debería promediar los 2 canales juntos?

Respuesta

187

La matriz que está mostrando son los coeficientes de transformación de Fourier de la señal de audio. Estos coeficientes se pueden usar para obtener el contenido de frecuencia del audio. La FFT se define para las funciones de entrada con valores complejos, por lo que los coeficientes que obtenga serán números imaginarios, aunque su entrada sea de valores reales. Para obtener la cantidad de potencia en cada frecuencia, debe calcular la magnitud del coeficiente de FFT para cada frecuencia. Esto es no solo el componente real del coeficiente, necesita calcular la raíz cuadrada de la suma del cuadrado de sus componentes real e imaginario. Es decir, si su coeficiente es a + b * j, entonces su magnitud es sqrt (a^2 + b^2).

Una vez que ha calculado la magnitud de cada coeficiente de FFT, necesita averiguar a qué frecuencia de audio pertenece cada coeficiente de FFT. Un N point FFT le dará el contenido de frecuencia de su señal en N frecuencias equiespaciadas, comenzando en 0. Debido a que su frecuencia de muestreo es de 44100 muestras/seg. y el número de puntos en su FFT es 256, su espaciamiento de frecuencia es 44100/256 = 172 Hz (aproximadamente)

El primer coeficiente en su matriz será el coeficiente de frecuencia 0. Ese es básicamente el nivel de potencia promedio para todas las frecuencias. El resto de tus coeficientes contará desde 0 en múltiplos de 172 Hz hasta llegar a 128. En una FFT, solo puedes medir frecuencias hasta la mitad de tus puntos de muestra. Lea estos enlaces en Nyquist Frequency y Nyquist-Shannon Sampling Theorem si es un glotón para el castigo y necesita saber por qué, pero el resultado básico es que sus frecuencias más bajas se replicarán o aliased en los intervalos de frecuencia más altos.Entonces las frecuencias comenzarán desde 0, aumentarán 172 Hz para cada coeficiente hasta el coeficiente N/2, luego disminuirán en 172 Hz hasta el coeficiente N - 1.

Eso debería ser suficiente información para comenzar. Si desea una introducción mucho más accesible a las FFT que la dada en Wikipedia, puede intentar Understanding Digital Signal Processing: 2nd Ed.. Fue muy útil para mí.

Así que eso es lo que representan esos números. La conversión a un porcentaje de altura se puede hacer escalando cada magnitud de componente de frecuencia por la suma de todas las magnitudes de los componentes. Aunque, eso solo le daría una representación de la distribución de frecuencia relativa, y no la potencia real para cada frecuencia. Podría intentar escalar por la magnitud máxima posible para un componente de frecuencia, pero no estoy seguro de que eso se muestre muy bien. La forma más rápida de encontrar un factor de escalado viable sería experimentar con señales de audio fuertes y suaves para encontrar la configuración correcta.

Finalmente, debe promediar los dos canales si desea mostrar el contenido de frecuencia de toda la señal de audio como un todo. Está mezclando el audio estéreo en audio mono y mostrando las frecuencias combinadas. Si desea dos pantallas separadas para las frecuencias derecha e izquierda, deberá realizar la Transformada de Fourier en cada canal por separado.

+3

+1 para la gran respuesta y me hace aprender un nuevo modismo, como No soy un hablante de inglés nativo.;) – macbirdie

+1

+1 Impresionante, esto me ayudó a entender lo que estaba haciendo mal. – Davido

+4

+1 - Aunque ya conozco las FFT, una de las mejores explicaciones sencillas en inglés en la web. – OldTinfoil

10

lo que tiene es una muestra cuya longitud en el tiempo es 256/44100 = 0.00580499 segundos. Esto significa que su resolución de frecuencia es 1/0.00580499 = 172 Hz. Los 256 valores que obtiene de Python corresponden a las frecuencias, básicamente, de 86 Hz a 255 * 172 + 86 Hz = 43946 Hz. Los números que obtienes son números complejos (de ahí la "j" al final de cada segundo número).

EDITADO: FIJA INFORMACIÓN MAL

es necesario convertir los números complejos en amplitud mediante el cálculo de la raíz cuadrada (i + j) donde i y j son las partes real e imaginaria, respectivamente.

Si desea tener 32 compases, por lo que yo entiendo tome la media de cuatro amplitudes sucesivas, obteniendo 256/4 = 32 compases como desee.

+0

Hola, perdón por la respuesta inicial (errónea) ... no obtuve los cálculos correctos. Esto debería ser correcto ahora. –

+4

Tenga en cuenta que, si c es un número complejo, sqrt (c.real ** 2 + c.imag ** 2) == abs (c) – tzot

25

Aunque este hilo tiene años, lo encontré muy útil. Solo quería dar mi opinión a cualquiera que encuentre esto y esté intentando crear algo similar.

En cuanto a la división en barras esto no debe hacerse como sugieren antti, dividiendo los datos por igual en función del número de barras. Lo más útil sería dividir los datos en partes de octava, cada octava es el doble de la frecuencia de la anterior. (es decir, 100 Hz es una octava por encima de 50 Hz, que es una octava por encima de 25 Hz).

Dependiendo de la cantidad de barras que desee, divida todo el rango en rangos de 1/X de octava. Sobre la base de una frecuencia central determinada de A en la barra, se obtienen los límites superior e inferior de la barra de:

upper limit = A * 2^(1/2X) 
lower limit = A/2^(1/2X) 

Para calcular la siguiente frecuencia central contigua se utiliza un cálculo similar:

next lower = A/2^(1/X) 
next higher = A * 2^(1/X) 

Luego promedia los datos que se ajustan a estos rangos para obtener la amplitud de cada barra.

Por ejemplo: Queremos dividir en rangos de 1/3 octavas y comenzamos con una frecuencia central de 1khz.

Upper limit = 1000 * 2^(1/(2 * 3)) = 1122.5 
Lower limit = 1000/2^(1/(2 * 3)) = 890.9 

44100Hz Dada y 1024 muestras (43 Hz entre cada punto de datos) debemos promediar valores de 21 a 26. (890,9/43 = 20,72 ~ 21 y 1122.5/43 = 26,10 ~ 26)

(Las barras de 1/3 de octava te darán alrededor de 30 compases entre ~ 40hz y ~ 20khz). Como puede ver ahora, a medida que vamos más arriba promediaremos una mayor gama de números. Normalmente, las barras bajas solo incluyen 1 o una pequeña cantidad de puntos de datos. Mientras que las barras más altas pueden ser el promedio de cientos de puntos. La razón es que 86hz es una octava por encima de 43hz ... mientras que 10086hz suena casi igual a 10043hz.