2

私は私のプロジェクトで 2D FFT を使用してきましたが、2 つの異なる FFT ライブラリを使用して正しい結果を得ることができませんでした。最初は間違った使い方をしていると思っていましたが、MATLAB や Linux の GCC 参照実装と比較すると、私のコンパイラ (MSVC 2013 Express) で何か不吉なことが起こっているようです。

私のテスト ケースは次のとおりです: 256x256 複素数から実際の IFFT へ、10000 に設定された 255 (X、Y 表記では 0,255) の単一ビン。

AMPFFT を使用して、次の 2D 変換を取得します。

壊れた AMPFFT の例

FFTW を使用すると、次の 2D 変換が得られます。

壊れた FFTW の例

ご覧のとおり、AMPFFT バージョンは「ほぼ」正しいですが、この奇妙なサンプルのバンディングがすべて含まれており、FFTW バージョンはいたるところにあり、ランチに出かけています。

2 つの異なるテスト バージョンの出力を取得し、それらを MATLAB (技術的には FFTW を内部で使用するオクターブ) と比較しました。また、GCC を使用する Linux で FFTW に対して同じテスト ケースを実行しました。これは、127 番目の行の一連のテストからのスライスです (ビンの選択では、すべての行が同一である必要があるため、行番号は技術的には問題ではありません)。

FFT比較

この例では、オクターブと Linux の実装は正しい結果を表し、赤い線に従っています (オクターブは黒でプロットされ、Linux は赤でプロットされ、オクターブと完全に一致しました)。MSVC の下の FFTW は青色でプロットされ、AMP FFT 出力はマゼンタでプロットされます。ご覧のとおり、やはり AMPFFT バージョンはほぼ近いように見えますが、この奇妙な高周波リップルが含まれており、MSVC での FFTW は、この奇妙な「パケット化された」外観で混乱しています。

この段階では、Visual Studio に指を向けることしかできませんが、何が起こっているのか、それを修正する方法はわかりません。

ここに私の2つのテストプログラムがあります:

FFTW テスト:

//fftwtest.cpp
//2 dimensional complex-to-real inverse FFT test.
//Produces a 256 x 256 real-valued matrix that is loadable by octave/MATLAB
#include <fstream>
#include <iostream>
#include <complex>
#include <fftw3.h>

int main(int argc, char** argv)
{
    int FFTSIZE = 256;

    std::complex<double>* cpxArray;
    std::complex<double>* fftOut;

   // cpxArray = new std::complex<double>[FFTSIZE * FFTSIZE];
    //fftOut = new double[FFTSIZE * FFTSIZE];
    fftOut = (std::complex<double>*)fftw_alloc_complex(FFTSIZE*FFTSIZE);
    cpxArray = (std::complex<double>*)fftw_alloc_complex(FFTSIZE * FFTSIZE);

    for(int i = 0; i < FFTSIZE * FFTSIZE; i++) cpxArray[i] = 0;
    cpxArray[255] = std::complex<double>(10000, 0);
    fftw_plan p = fftw_plan_dft_2d(FFTSIZE, FFTSIZE, (fftw_complex*)cpxArray, (fftw_complex*)fftOut, FFTW_BACKWARD, FFTW_DESTROY_INPUT | FFTW_ESTIMATE);
    fftw_execute(p);

    std::ofstream debugDump("debugdumpFFTW.txt");
    for(int j = 0; j < FFTSIZE; j++)
    {
        for(int i = 0; i < FFTSIZE; i++)
        {
            debugDump << " " << fftOut[j * FFTSIZE + i].real();
        }
        debugDump << std::endl;
    }
    debugDump.close();

}

AMPFFT テスト:

//ampffttest.cpp
//2 dimensional complex-to-real inverse FFT test.
//Produces a 256 x 256 real-valued matrix that is loadable by octave/MATLAB
#include <amp_fft.h>
#include <fstream>
#include <iostream>



int main(int argc, char** argv)
{
    int FFTSIZE = 256;

    std::complex<float>* cpxArray;
    float* fftOut;

    cpxArray = new std::complex<float>[FFTSIZE * FFTSIZE];
    fftOut = new float[FFTSIZE * FFTSIZE];

    for(size_t i = 0; i < FFTSIZE * FFTSIZE; i++) cpxArray[i] = 0;
    cpxArray[255] = std::complex<float>(10000, 0);

    concurrency::extent<2> e(FFTSIZE, FFTSIZE);
    std::cout << "E[0]: " << e[0] << " E[1]: " << e[1] << std::endl;

    fft<float, 2> m_fft(e);
    concurrency::array<float, 2> outpArray(concurrency::extent<2>(FFTSIZE, FFTSIZE));
    concurrency::array<std::complex<float>, 2> inpArray(concurrency::extent<2>(FFTSIZE, FFTSIZE), cpxArray);


    m_fft.inverse_transform(inpArray, outpArray);
    std::vector<float> outVec = outpArray;

    std::copy(outVec.begin(), outVec.end(), fftOut);

    std::ofstream debugDump("debugdump.txt");
    for(int j = 0; j < FFTSIZE; j++)
    {
        for(int i = 0; i < FFTSIZE; i++)
        {
            debugDump << " " << fftOut[j * FFTSIZE + i];
        }
        debugDump << std::endl;
    }
}

これらは両方とも、win32 コンソール アプリ用に MSVC 2013 のストック設定でコンパイルされ、FFTW テストも GCC 4.4.7 を使用する Centos 6.4 で実行されました。どちらの FFTW テストも FFTW バージョン 3.3.4 を使用します。

この問題を解決しようとする Visual Studio コンパイラの設定について、少しでも手がかりを持っている人はいますか?

4

1 に答える 1

1

MSVC FFTW の出力を青で見ると、複数のサインが乗算されているように見えます。つまり、周期 64 程度の正弦波と周期 4 の正弦波があり、ビートを生成する同様の周波数を持つ別の正弦波が存在する可能性があります。

これは基本的に、MSVC バージョンにゼロ以外の入力が少なくとも 2 つあったことを意味します。fftw_complex型を介してオブジェクトを書き込むため、原因は型キャストであると思われますstd::complex<double>

于 2014-06-12T08:14:17.857 に答える