2011-09-28 85 views
26

我目前正在尝试写一些傅里叶变换算法。我开始用一个简单的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是多采样频率的数量(在这种情况下:120,240,360,...)。这就是我的结果为240倍的值:

http://s1.directupload.net/images/110928/n3m8hqg6.jpg

转型刚刚工作的罚款。

如果我试图计算280个值我得到这样的结果:

http://s7.directupload.net/images/110928/qizoiqbt.jpg

为什么我得到一个不正确的结果,如果我改变我的计算值是多少? 我不确定这里的问题是否与我的代码有关,或者是对DFT数学定义的误解。无论哪种方式,任何人都可以帮我解决我的问题吗?谢谢。

+0

你能告诉我为什么你的变换函数的输入是一个复杂的数组?当然,如果你从一个标准的声波(时域)转换,它会是一个单一的双数组? –

+2

好吧,我明白了 - 虚数部分设置为0,所以它基本上等于如果它只是一个双倍。顺便说一句,在你的代码中,'Complex.Polar'应该是'Complex.FromPolarCoordinates'。 –

+2

你对地块有什么用处? – GorillaApe

回答

28

您遇到的问题叫做Spectral Leakage

这是由于傅立叶变换的基础数学假设从无穷到无穷的连续函数引起的。所以你提供的样品范围有效地重复无数次。如果在窗口中没有完整数量的波形周期,则两端不会对齐,您将得到一个不连续点,这表示其自身为频率模糊到任一侧的自身。

处理此问题的常规方法称为Windowing。然而,这确实会带来不利影响,因为它会导致幅度稍微偏离。这是将你要处理的样本的整个窗口乘以在窗口两端倾向于0的一个函数的过程,从而导致两端对齐,但会产生一些幅度失真,因为此过程会降低总信号功率。

所以总结一下,在你的代码中没有错误,结果如预期。使用窗函数可以减少伪像,但这会影响幅度的准确性。您需要调查并确定最适合您项目要求的解决方案。

4

您没有得到非周期正弦曲线的错误结果。它们不只是“神器”。您的结果实际上是您在周期性正弦曲线中看不到的更完整的DFT结果。那些其他非零值包含有用的信息,可用于例如内插单个非周期性孔径正弦曲线的频率。

DFT可以被认为是用正弦波卷积矩形窗口。这产生了一个Sinc函数,它具有无限的延伸范围,但是在除了其中央DFT箱以外的每个DFT箱频率恰好为零,对于任何正好位于DFT箱中心的正弦波。只有在FFT窗口中的频率完全是周期性的时候才会发生这种情况,而不是任何其他情况。 Sinc函数有很多“小丘”,都隐藏在你的第一个阴谋。