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

あなたが経験しているのはスペクトル漏れと呼ばれています。

これは、フーリエ変換の基礎となる数学が-無限大から+無限大までの連続関数を想定しているために発生します。したがって、提供するサンプルの範囲は、効果的に無限に繰り返されます。ウィンドウに波形の完全なサイクル数がない場合、端が整列せず、周波数がいずれかの側に不鮮明になることでそれ自体が現れる不連続性が発生します。

これを処理する通常の方法は、ウィンドウ処理と呼ばれます。ただし、振幅がわずかにずれてしまうため、これには欠点があります。これは、処理しようとしているサンプルのウィンドウ全体に、ウィンドウの両端で0に近づく傾向がある関数を乗算するプロセスです。このプロセスでは、合計信号電力が低下するため、両端が整列しますが、振幅の歪みがあります。

したがって、要約すると、コードにエラーはなく、結果は期待どおりです。窓関数を使用してアーティファクトを減らすことができますが、これは振幅の精度に影響します。プロジェクトの要件に最適なソリューションを調査して決定する必要があります。

于 2011-09-28T11:56:06.460 に答える
6

非周期的な正弦波に対して誤った結果が得られることはありません。そして、それらは単なる「アーティファクト」ではありません。実際の結果は、周期的な正弦波では見られない、より完全なDFT結果です。これらの他の非ゼロ値には、たとえば、単一の非周期的開口正弦波の周波数を補間するために使用できる有用な情報が含まれています。

DFTは、正弦波で長方形のウィンドウを畳み込むと考えることができます。これにより、無限の範囲を持つSinc関数(非常に近いもの)が生成されますが、DFTビンを正確に中心とする正弦波の場合、中央のDFTビン以外のすべてのDFTビン周波数でたまたまゼロになります。これは、周波数がFFTアパーチャで正確に周期的である場合にのみ発生し、他のアパーチャでは発生しません。Sinc関数には多くの「こぶ」があり、それらはすべて最初のプロットに隠されています。

于 2011-09-28T17:59:16.530 に答える