Pregunta

Tengo un archivo de audio y estoy iterando a través del archivo y tomando 512 muestras en cada paso y luego pasándolas a través de una FFT.

Tengo los datos como un bloque de 514 flotaciones de largo (usando ippsFFTFwd_RToCCS_32f_I de IPP) con componentes reales e imaginarios intercalados.

Mi problema es ¿qué hago con estos números complejos una vez que los tengo?De momento estoy haciendo por cada valor

const float realValue   = buffer[(y * 2) + 0];
const float imagValue   = buffer[(y * 2) + 1];
const float value       = sqrt( (realValue * realValue) + (imagValue * imagValue) );

Esto proporciona algo ligeramente utilizable, pero prefiero alguna forma de obtener los valores en el rango de 0 a 1.El problema con lo anterior es que los picos terminan volviendo a alrededor de 9 o más.Esto significa que las cosas se saturan brutalmente y luego hay otras partes del espectrograma que apenas aparecen a pesar de que parecen ser bastante fuertes cuando paso el audio por el espectrograma de la audición.Admito plenamente que no estoy 100% seguro de cuáles son los datos devueltos por la FFT (aparte de eso, representan los valores de frecuencia del bloque largo de 512 muestras que estoy pasando).Especialmente me falta comprensión sobre qué representa exactamente el número complejo.

¡Cualquier consejo y ayuda sería muy apreciado!

Editar:Solo para aclarar.Mi gran problema es que los valores de FFT devueltos no tienen sentido sin una idea de cuál es la escala.¿Alguien puede indicarme cómo resolver esa escala?

Editar2:Obtengo resultados realmente bonitos haciendo lo siguiente:

size_t count2   = 0;
size_t max2     = kFFTSize + 2;
while( count2 < max2 )
{
    const float realValue   = buffer[(count2) + 0];
    const float imagValue   = buffer[(count2) + 1];
    const float value   = (log10f( sqrtf( (realValue * realValue) + (imagValue * imagValue) ) * rcpVerticalZoom ) + 1.0f) * 0.5f;
    buffer[count2 >> 1] = value;
    count2 += 2;
}

En mi opinión, esto incluso se ve mejor que la mayoría de las otras implementaciones de espectrogramas que he visto.

¿Hay algo MUY IMPORTANTE en lo que estoy haciendo?

¿Fue útil?

Solución

Lo habitual hacer para conseguir la totalidad de una FFT visible es tomar el logaritmo de la magnitud.

Por lo tanto, la posición de la memoria intermedia de salida le indica qué frecuencia se detecta. La magnitud (norma L2) del número complejo te dice qué tan fuerte era la frecuencia detectada, y la fase (arcotangente) le proporciona información que es mucho más importante en el espacio de la imagen que el espacio de audio. Debido a que la FFT es discreta, las frecuencias van de 0 a la frecuencia de Nyquist. En las imágenes, el primer término (DC) suele ser la más grande, y por lo tanto un buen candidato para su uso en la normalización si ese es su objetivo. No sé si eso es cierto también para el audio (lo dudo)

Otros consejos

Para cada ventana de 512 muestras, que calculan la magnitud de la FFT como lo hizo. Cada valor representa la magnitud de la frecuencia correspondiente presente en la señal.

mag
 /\
 |
 |      !         !
 |      !    !    !
 +--!---!----!----!---!--> freq
 0          Fs/2      Fs

Ahora tenemos que averiguar las frecuencias.

Dado que la señal de entrada es de valores reales, la FFT es simétrica alrededor de la mitad (componente Nyquist) con ser el primer término de la componente continua. Conociendo la Fs frecuencia de muestreo de la señal, la frecuencia de Nyquist es Fs / 2. Y por lo tanto para la k índice, la frecuencia correspondiente se k*Fs/512

Así que para cada ventana de longitud 512, obtenemos las magnitudes de frecuencia especificada. El grupo de los mayores de ventanas consecutivas forman el espectrograma.

Al igual que la gente sepa que he hecho un montón de trabajo en todo este problema. Lo más importante que he descubierto es que la FFT requiere la normalización después de hacerlo.

Para hacer esto usted hace un promedio de todos los valores de su vector ventana en conjunto para obtener un valor algo inferior a 1 (o 1 si está utilizando una ventana rectangular). A continuación, dividir ese número por el número de intervalos de frecuencia que tiene enviar a transformar la FFT.

Por último se divide el número real devuelto por la FFT por el número normalización. Sus valores de amplitud deben estar ahora en los -Inf a 1 rango. Registro, etc, a su gusto. Aún se trabaja con un rango conocido.

Hay algunas cosas que creo que le resultarán útiles.

El FT directo tenderá a dar cifras mayores en la salida que en la entrada.Puede pensar en ello como si toda la intensidad a una determinada frecuencia se mostrara en un lugar en lugar de distribuirse a través del conjunto de datos.¿Esto importa?Probablemente no, porque siempre puedes escalar los datos para adaptarlos a tus necesidades.Una vez escribí un par FFT/IFFT basado en números enteros y cada pasada requirió un cambio de escala para evitar el desbordamiento de enteros.

Los datos reales que son su entrada se convierten en algo casi complejo.Resulta que el buffer[0] y el buffer[n/2] son ​​reales e independientes.Hay una buena discusión al respecto. aquí.

Los datos de entrada son valores de intensidad del sonido tomados a lo largo del tiempo, igualmente espaciados.Se dice que están, con bastante propiedad, en el dominio del tiempo.Se dice que la salida del FT está en el dominio de la frecuencia porque el eje horizontal es la frecuencia.La escala vertical sigue siendo intensidad.Aunque no es obvio a partir de los datos de entrada, también hay información de fase en la entrada.Aunque todo el sonido es sinusoidal, no hay nada que fije las fases de las ondas sinusoidales.Esta información de fase aparece en el dominio de la frecuencia como las fases de los números complejos individuales, pero a menudo no nos importa (¡y a menudo también nos importa!).Simplemente depende de lo que estés haciendo.El cálculo

const float value = sqrt((realValue * realValue) + (imagValue * imagValue));

recupera la información de intensidad pero descarta la información de fase.Tomar el logaritmo básicamente amortigua los grandes picos.

Espero que esto sea útil.

Si usted está consiguiendo resultados extraños a continuación, una cosa es comprobar la documentación de la biblioteca FFT para ver cómo se embala la salida. Algunas rutinas utilizan un formato empaquetado, donde se intercalan los valores reales / imaginarias, o pueden comenzar en el elemento de N / 2 y se envuelven alrededor.

Para una cordura comprobar que sugeriría la creación de datos de la muestra con características conocidas, por ejemplo, Fs / 2, fs / 4 (Fs = frecuencia de muestreo) y comparar la salida de la rutina FFT con lo que se espera. Trate de crear tanto un seno y coseno a la misma frecuencia, ya que éstos deben tener la misma magnitud en el espectro, pero tienen diferentes fases (es decir, el RealValue / imagValue será diferente, pero la suma de cuadrados debe ser el mismo.

Si está con la intención en el uso de la FFT, aunque entonces usted realmente necesita saber cómo funciona matemáticamente, de lo contrario es probable encontrar otros problemas extraños tales como aliasing.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top