30

我目前正在尝试编写一些傅立叶变换算法。我从数学定义中描述的简单 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 的数学定义有误解。无论哪种方式,任何人都可以帮助我解决我的问题吗?谢谢。

4

2 回答 2

32

您所经历的称为光谱泄漏

这是因为傅立叶变换的基础数学假设一个从 - 无穷大到 + 无穷大的连续函数。因此,您提供的样本范围有效地重复了无数次。如果您在窗口中没有完整数量的波形周期,则末端将不会对齐,您将得到一个不连续性,表现为频率向任一侧涂抹。

处理此问题的常规方法称为Windowing。然而,这确实有一个缺点,因为它会导致幅度略微偏离。这是将要处理的样本的整个窗口乘以某个函数的过程,该函数在窗口的两端趋于 0,导致两端对齐,但有一些幅度失真,因为这个过程会降低总信号功率。

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

于 2011-09-28T11:56:06.460 回答
6

You are NOT getting the incorrect result for a non-periodic sinusoid. And they are not just "artifacts". Your result is actually the more complete DFT result which you don't see with a periodic sinusoid. Those other non-zero values contain useful information which can be used to, for example, interpolate the frequency of a single non-periodic-in-aperture sinusoid.

A DFT can be thought of as convolving a rectangular window with your sine wave. This produces (something very close to) a Sinc function, which has infinite extent, BUT just happens to be zero at every DFT bin frequency other than its central DFT bin for any sinusoid centered exactly on a DFT bin. This happens only when the frequency is exactly periodic in the FFT aperture, not for any other. The Sinc function has lots of "humps" which are all hidden in your first plot.

于 2011-09-28T17:59:16.530 回答