¿Es válido aumentar la amplitud (y presumiblemente la calidad FFT) simplemente escalando los datos?

10

Estoy usando una versión de "KISS FFT" de Mark Borgerding. Acepta una matriz de valores de entrada de punto fijo de 16 bits y produce una matriz de resultado flotante de 32 bits.

He descubierto que si las amplitudes de entrada son bajas, muchos de los valores de resultado flotantes salen a cero, pero si simplemente escalo las entradas (por, digamos, el factor 16), menos valores de salida son cero y, por lo tanto, la salida parece contener mas detalle. (No es que importe mucho para mis propósitos, pero por coherencia, luego divido los valores flotantes resultantes por el mismo factor de escala).

De todos modos, esto parece funcionar, en términos de producir un resultado cuando anteriormente acababa de obtener un búfer de prácticamente todos los ceros, pero me pregunto si hay alguna razón por la que podría no ser un enfoque válido.

(Tenga en cuenta que este enfoque significa que hay mucha más "grosor" / granularidad en los datos y, en particular, el ruido de bajo nivel que normalmente estaría presente no lo está. Casi me pregunto si sería prudente inyectar algo de ruido de bajo nivel para reemplazar los valores cero en la entrada).

Daniel R Hicks
fuente
"Casi me pregunto si sería prudente inyectar algo de ruido de bajo nivel para reemplazar los valores cero en la entrada". = en.wikipedia.org/wiki/Dither
endolith

Respuestas:

7

Este puede ser un enfoque válido. Está observando un problema muy práctico que surge a menudo cuando se usa la aritmética de punto fijo (es decir, entero) (aunque también puede ocurrir en punto flotante). Cuando el formato numérico que está utilizando para realizar cálculos no tiene la precisión suficiente para expresar el rango completo de valores que pueden surgir de sus cálculos, se requiere alguna forma de redondeo (por ejemplo, truncamiento, redondeo al más cercano, etc.) en). Esto a menudo se modela como un error de cuantificación aditivo para su señal.

Sin embargo, para algunas combinaciones de algoritmo y esquema de redondeo, cuando la magnitud de la señal de entrada es muy baja, es posible obtener lo que observó: una gran cantidad de salidas cero. Básicamente, en algún lugar de la secuencia de operaciones, los resultados intermedios se están volviendo lo suficientemente pequeños como para no romper el umbral requerido para cuantificar a un nivel distinto de cero. El valor se redondea a cero, que a menudo puede propagarse hacia la salida. El resultado es, como notó, un algoritmo que genera muchos ceros de salida.

Entonces, ¿puedes evitar esto ampliando los datos? A veces (¡hay muy pocas técnicas que funcionan todo el tiempo!). Si su señal de entrada está limitada en magnitud a un valor por debajo de la escala completa del formato numérico (los enteros con signo de 16 bits se ejecutan desde -32768 a +32767), entonces puede escalar la señal de entrada para usar más el rango disponible para eso. Esto puede ayudar a mitigar los efectos del error de redondeo, ya que la magnitud de cualquier error de redondeo se reduce en comparación con la señal de interés. Por lo tanto, en el caso de que todas sus salidas se redondeen a ceros internamente al algoritmo, esto puede ayudar.

¿Cuándo puede lastimarte una técnica así? Dependiendo de la estructura de los cálculos del algoritmo, la ampliación de la señal de entrada puede exponerlo a desbordamientos numéricos. Además, si la señal contiene ruido de fondo o interferencia que es mayor en magnitud que el error de redondeo del algoritmo, entonces la calidad de lo que obtienes en la salida generalmente estará limitada por el entorno, no por el error introducido en el cálculo.

Jason R
fuente
Estoy usando una técnica dinámica para escalar que parece funcionar bastante bien. Y, por suerte, los transitorios extremos se tratan como ruido y se recortan de todos modos, por lo que el recorte ocasional no debería ser un problema. ¿Crees que es válido "descalcificar" la salida dividiendo por el factor de escala de la entrada?
Daniel R Hicks
1

La forma más fácil y más infalible de lidiar con esto es convertir los datos a coma flotante ANTES de la FFT y usar una FFT de coma flotante. El único inconveniente de este enfoque sería que puede consumir más procesador y memoria. Como su salida es de coma flotante, probablemente haya poca diferencia práctica.

Hilmar
fuente
Me entregaron este proyecto con el algoritmo FFT actual ya en su lugar, y soy reacio a meterme con él en este momento. Y todo esto sucede en un teléfono, en tiempo real, por lo que el rendimiento es definitivamente un problema.
Daniel R Hicks
Entendido. ¿Sabes si el FFT interno es de punto fijo o flotante? Si está arreglado, debe preocuparse por el recorte, el desbordamiento y el desbordamiento
Hilmar
La documentación y los comentarios son excepcionales en su ausencia, pero veo muchas entradas en el código y preciosas pocas carrozas y dobles. Parece incluir el marco bruto #ifdef para cambiar de 16 bits a 32 bits o flotante, pero el marco aparentemente ha estado desactivado durante mucho tiempo.
Daniel R Hicks
Un iPhone (ARM + NEON CPU) puede hacer una FFT de flotador más rápido (a través del marco Acelerar) que una FFT número entero en C.
hotpaw2