[C言語]離散フーリエ変換、逆変換の実装[コード付き]

C言語コード

はい今日はフーリエ変換を実装していきます

フーリエ変換自体については割愛します。
数学のブログではないし説明すると長くなりそうだし。

一応今回は1次元の離散フーリエ変換をやっていきます。
有限長の信号のデータセットを扱う感じです。

計算式

信号の個数をNとして

xを信号の値、
Xを離散フーリエ変換とします


つまり周波数も0からNまでの整数です。


その時の離散フーリエ変換がこちら

逆変換がこちら


この計算のコードを書いていきます。



コードの実装

虚数の部分どうするか問題

まあ計算のシグマの部分はforループで良いですね。

問題は虚数が出ていることですね
残念ながらC言語では標準で虚数を扱う関数がないのでどうしよう。

と思ったのですが、
今回、虚数が出ているのがeの係数ですね。
なのでオイラーの公式を使って分解できます

オイラーの公式

これで虚数iをただの係数に落とし込めるので計算できそうですね。
オイラーマジ感謝。

まあオイラーの公式についての詳しいことは調べてください。



離散フーリエ変換の関数

void Fourier(void){ //フーリエ変換
    
    double xr[N];
   
    char r_r[NAME];
    printf("どのファイルから読み込みますか?:");
    scanf("%s",r_r);
    SCAN(xr,r_r);
    
    int n,k;
        
    double X_R[N];
    double X_I[N];
    double r;
    double i;
                 
        
    for(k=0; k<N; k++){
        r=0;
        i=0;
        for(n=0; n<N; n++){
            r += xr[n] * cos((2*M_PI*k*n)/N);
            i -= xr[n] * sin((2*M_PI*k*n)/N);
        }
        X_R[k] = r;

        X_I[k] = i;
    }
        
    writeru(X_R, X_I);
    
}

信号はファイルに入っているものとします。
SCANはファイルの中身を配列に入れる関数です。
で、X_RとX_Iがフーリエ変換の結果の実部と虚部を入れる配列です。

内側for文の中で、フーリエ変換の式とオイラーの公式に従って計算しています。
内側ループが終わったらX_R,X_Iに格納して外側ループに戻るって感じです。

最後に配列をファイルに格納します。writeruがそれ。



離散フーリエ逆変換

void r_Fourier(void){ //フーリエ逆変換
   
    double X_R[N];
    double X_I[N];
    scanru(X_R, X_I);
        
    int n,k;
    double x_r[N];
    
    for(n=0; n<N; n++){
        double r=0;
            
        for(k=0; k<N; k++){
            r += X_R[k] * cos((2*M_PI*k*n)/N) - X_I[k] * sin((2*M_PI*k*n)/N);
        }
            
        x_r[n] = r/N;
    }
    
    char r_w[NAME];
    printf("どのファイルに書き込みますか?:");
    scanf("%s",r_w);
    WRITE(x_r, r_w);
}

こちらも同様ですね。
こっちは普通の信号に戻るので返す配列は1つです。
あと式の1/Nの場所を間違えないように。

ゆーてどちらも計算式がややこしいだけですね。



終わり

今回はこれだけですね。

そのうちフィルタを掛けてみる実験の記事を書いても良いかも。


ではまた〜


コメント

タイトルとURLをコピーしました