我目前正在尝试写一些傅里叶变换算法。我从数学定义中描述的一个简单的DFT算法开始:
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;
}
}所以我用下面的代码测试了这个算法:
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);
}转换可以正常工作,但仅当numberValues是samplingFrequency的倍数时(在本例中: 120、240、360、...)。这是我对240个值的结果:

这种转变工作得很好。
如果我试图计算280个值,我会得到这个结果:

为什么我更改了我的计算值的数量会得到不正确的结果?我不确定这里的问题是我的代码的问题还是对DFT的数学定义的误解。无论哪种方式,有人能帮我解决我的问题吗?谢谢。
发布于 2011-09-28 19:56:06
您正在经历的情况称为Spectral Leakage。
这是因为傅立叶变换的基本数学假设是从-infinity到+无穷大的连续函数。因此,您提供的样本范围实际上重复了无限次。如果你在窗口中没有完整的波形周期数,两端将不会对齐,你将得到一个不连续,这表现为频率向两边拖尾。
处理这种情况的正常方法称为Windowing。然而,这确实带来了一个缺点,因为它会导致振幅略有下降。这是将要处理的样本的整个窗口乘以某个函数的过程,该函数在窗口的两端趋于0,导致两端对齐,但具有一些幅度失真,因为此过程降低了总信号功率。
因此,总而言之,您的代码中没有错误,并且结果与预期一致。可以使用窗口函数来减少伪影,但是这将影响振幅的准确性。您将需要调查并确定最适合您的项目需求的解决方案。
发布于 2011-09-29 01:59:17
对于非周期正弦曲线,您不会得到错误的结果。而且它们不仅仅是“神器”。你的结果实际上是更完整的DFT结果,这是周期正弦曲线看不到的。那些其他非零值包含有用的信息,其可用于例如内插单个非周期孔径正弦波的频率。
DFT可以看作是一个矩形窗口与正弦波的卷积。这会产生一个正弦函数(非常接近),它有无限的范围,但只是碰巧在每个DFT bin频率上为零,而不是它的中心DFT bin对于任何以DFT bin为中心的正弦函数。只有当频率在FFT孔径中是完全周期性的时,才会发生这种情况,对于其他任何情况都不会发生。Sinc函数有很多“驼峰”,它们都隐藏在您的第一个图中。
https://stackoverflow.com/questions/7582744
复制相似问题