c# - tiempo - transformada discreta de fourier online
Transformada discreta de Fourier (2)
Lo que estás experimentando se llama fuga espectral .
Esto se debe a que las matemáticas subyacentes de la transformada de Fourier asumen una función continua desde el infinito hasta el infinito. Por lo tanto, el rango de muestras que proporciona se repite efectivamente un número infinito de veces. Si no tiene un número completo de ciclos de la forma de onda en la ventana, los extremos no se alinearán y obtendrá una discontinuidad que se manifiesta a sí misma a medida que la frecuencia se difumina a ambos lados.
La forma normal de manejar esto se llama Windowing . Sin embargo, esto viene con un inconveniente, ya que hace que las amplitudes sean ligeramente más bajas. Este es el proceso de multiplicar toda la ventana de muestras que se procesarán mediante alguna función que tiende a 0 en ambos extremos de la ventana, lo que hace que los extremos se alineen, pero con cierta distorsión de amplitud, ya que este proceso reduce la potencia total de la señal.
Entonces, para resumir, no hay ningún error en su código, y el resultado es el esperado. Los artefactos se pueden reducir usando una función de ventana, sin embargo, esto afectará la precisión de las amplitudes. Deberá investigar y determinar qué solución se ajusta mejor a los requisitos de su proyecto.
Actualmente estoy tratando de escribir algún algoritmo de transformación de Fourier. Comencé con un algoritmo DFT simple como se describe en la definición matemática:
public class DFT {
public static Complex[] Transform(Complex[] input) {
int N = input.Length;
Complex[] output = new Complex[N];
double arg = -2.0 * Math.PI / (double)N;
for (int n = 0; n < N; n++) {
output[n] = new Complex();
for (int k = 0; k < N; k++)
output[n] += input[k] * Complex.Polar(1, arg * (double)n * (double)k);
}
return output;
}
}
Así que probé este algoritmo con el siguiente código:
private int samplingFrequency = 120;
private int numberValues = 240;
private void doCalc(object sender, EventArgs e) {
Complex[] input = new Complex[numberValues];
Complex[] output = new Complex[numberValues];
double t = 0;
double y = 0;
for (int i = 0; i < numberValues; i++) {
t = (double)i / (double)samplingFrequency;
y = Math.Sin(2 * Math.PI * t);
input[i] = new Complex(y, 0);
}
output = DFT.Transform(input);
printFunc(input);
printAbs(output);
}
La transformación funciona bien, pero solo si numberValues es un número múltiple de la frecuencia de muestreo (en este caso: 120, 240, 360, ...). Ese es mi resultado para 240 valores:
http://s1.directupload.net/images/110928/n3m8hqg6.jpg
La transformación simplemente funcionó bien.
Si estoy tratando de calcular 280 valores obtengo este resultado:
http://s7.directupload.net/images/110928/qizoiqbt.jpg
¿Por qué obtengo un resultado incorrecto si cambio el número de mis valores calculados? No estoy seguro si mi problema aquí es un problema con mi código o una mala interpretación de la definición matemática de la DFT. De cualquier manera, ¿alguien puede ayudarme con mi problema? Gracias.
NO está obteniendo el resultado incorrecto para una sinusoide no periódica. Y no son solo "artefactos". Su resultado es en realidad el resultado de DFT más completo que no ve con una sinusoide periódica. Esos otros valores distintos de cero contienen información útil que puede utilizarse para, por ejemplo, interpolar la frecuencia de una sola sinusoide no periódica en la apertura.
Se puede pensar en un DFT como convolving de una ventana rectangular con su onda sinusoidal. Esto produce (algo muy parecido a) una función Sinc, que tiene una extensión infinita, PERO resulta que es cero en cada frecuencia de un contenedor DFT que no sea su depósito DFT central para cualquier sinusoide centrado exactamente en un contenedor DFT. Esto sucede solo cuando la frecuencia es exactamente periódica en la apertura FFT, no para ninguna otra. La función Sinc tiene un montón de "jorobas" que están ocultas en tu primera trama.