高速畳み込みの特に長いシーケンス

まず、機能

高速コンボリューション法で特に長い系列と短いシーケンスを計算し、オーバーラップセーブ高速フーリエ変換。これは通常、デジタルフィルタリングのために使用されています。

第二に、この方法の紹介

リセットシーケンス\(X(N)\)長さ\(L \) シーケンス\(H(N)\)の長さ\(M \) シーケンス\(X(N)\)\(Y (N)\)線形畳み込みのように定義される
\ [Y(N)= \
sum_ {I = 0} ^ {M-1} X(I)H(NI)\] オーバーラップセーブ法と高速フーリエ変換と線形畳み込みは、計算アルゴリズムを変換、次のとおりです。

1、配列\(H(N)\)以下のようにゼロパディングの長さ\(N = 2 ^ {\ガンマ} \) シーケンス
\ [\開始{行列} H (N)= \左\ {\ {行列} \始める開始 {ALIGN *} H(N)と、N = 0,1、...、M-1 \\ 0、N = M、M + 1、...、N- 1つの\端{ALIGN *} \端{行列} \右。\\ \端{行列} \]

計算FFTアルゴリズム配列を有する2、\(H(N)\)離散フーリエ変換(\ H(K))\
\ [H(K)= \ sum_ {0} = ^ {N-N}。1 H- (N)E ^ - {J2 \ PI NK / N} \]
。3、配列の長さ\(X(N)\)の長さに\(N \)サブパラグラフの\(X_I(N-)\)と歯間セグメントを重複\(M-1 \)ポイント、すなわち
\ [{行列} X_I開始\ =(n)を\左\ [N + I(N-M {} {マトリックスを開始\ {ALIGN *を開始\} X +1) - (M-1 )]と、0 \ leqslant N \ leqslant N-1 \\ 0、他\端{ALIGN *} \端{行列} \右\\ iは0,1 =。 .. \端{行列} \]
注:最初のセグメントのための\(X_0(N-)\) 以前のセグメント予約信号が存在しないので、これの前に充填する(M-1 \)\ゼロ。

図4に示すように、シーケンスは、FFTアルゴリズムを用いて計算される\(X_I(n)を\)離散フーリエ変換(X_I(K)\)\
\ [X_I(K)= \ sum_ {0} = ^ {N-N} 1-X_I (N)E ^ { - J2 \ PI NK / N} \]
。5、計算\(X_I(K)\)\(H(K)\)製品
\ [Y_I(K)= X_I (K)H (K)\]
。6、FFTアルゴリズムを用いて計算される(Y_I(K)\)\配列を得るために、逆離散フーリエ変換(X_I(N)\)\\(H(N)\)畳み込みを\ (Y_I(N-)\)
\ [Y_I(N)= \ FRAC {1} {N} \ sum_ {K = 0} ^ {N- 1} Y_I(K)E ^ {J2 \ PI NK / N}、 \ = N-0,1、...、1-N \]
。7、\(Y_I(N)\)の前に\(M-1 \)点のみバックを保持する、破棄(N-M + \ 1 \)のサンプル。
\ [\ {行列} \開始バー{Y} _i(n)を= \ M-1、\ {\開始{行列} \開始{ALIGN *} Y(n)を左&\ leqslant N \ leqslant N-1 \ \&0、{*} \}エンド左その他\エンドALIGN = {マトリックス\右。\\ \マトリックスエンド{} \]
。8、繰り返しが終了全てのセグメント数まで3-7ステップ。

9、考慮し\(X(n)を\)スプリットで、\(X_I(N-)\)有していて\(M-1 \)前項のみ新たに追加された試料との重なりの点\(N-M + 1 \) そう\(Y(N)\) A \(\バー{Y} _i (N)\) 端から端までアダプタ、すなわち
\ [Y(N)= \ sum_ {I = 0} ^ {\ inftyの} \バー{Y} _i [NI(N-M + 1)+(M-1)] \]

大量のデータ、配列による\(H(N)\) 特に長いシーケンスに\(X(N)\)ディスクに格納される、計算が終了すると、畳み込みシーケンス\(Y(N)\)もプログラムにより自動的にディスクに保存されました。

第三に、使用

高速畳み込みC言語の実装では、以下の

/************************************
    hfname      ----字符指针。它指向短序列h(i)的文件名。
    xfname      ----字符指针。它指向长序列x(i)的文件名。
    yfname      ----字符指针。它指向卷积y(i)的文件名。
    n           ----整型变量。对长序列x(i)进行分段的长度。一般选取n大于短序列h(i)长度m的两倍以上,
                且必须是2的整数次幂,即n=2^gamma。  
************************************/
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "rfft.c"
#include "irfft.c"
void convold(char *hfname, char *xfname, char *yfname, int n)
{
    int i, j, m, i1, i2, ls0, len, num, nblks;
    double *h, *r, *s;
    FILE *fp, *fp1, *fp2;
    r = malloc(n * sizeof(double));
    h = malloc(n * sizeof(double));
    n2 = n / 2;
    fopen(hfname, "r");
    i = 0;
    while(!fopen(fp)){
        fscanf(fp, "%lf", &h[i++]);
    }
    fclose(fp);
    m = i - 1;
    for(i = m; i < n; i++){
        h[i] = 0.0;
    }   
    rfft(h, n);
    s = malloc((n - m + 1) * sizeof(double));
    num = n - m + 1;
    fp1 = fopen(xfname, "r");
    fp2 = fopen(yfname, "r");
    len = 5000;
    ls0 = 0;
    do{
        for(i = ls0; i < 5000; i++){
            if(feof(fp1)){
                len = i;
                break;
            }
            fscanf(fp1, "%lf", &x[i]);
        }
        nblks = floor((len - n + m) / (double)num) + 1;
        for(j = 0; j < nblks; j++){
            if(j == 0){
                for(i = 0; i < (m - 1); i++)
                    r[i] = 0.0;
                for(i = m - 1; i < n; i++){
                    i1 = i - m + 1;
                    r[i] = x[i1];
                }
            } else {
                for(i = 0; i < n; i++){
                    i1 = i + j * num - m + 1;
                    r[i] = x[i1];
                }
                for(i = 0; i < num; i++){
                    i1 = i + (j - 1) * num;
                    x[i1] = s[i];
                }
            }
            rfft(r, n);
            r[0] = r[0] * h[0];
            r[n2] = r[n2] * h[n2];
            for(i = 1; i < n2; i++){
                t = h[i] * r[i] - h[n -i] * r[n - i];
                r[n - i] = h[i] * r[n - i] + h[n - i] * r[i];
                r[i] = t;
            }
            irfft(r, n);
            for(i = (m - 1); i < m; i++){
                i1 = i - m + 1;
                s[i1] = r[i];
            }
        }
        for(i = 0; i < num; i++){
            i1 = i + (j - 1) * num;
            x[i1] = s[i];
        }
        i1 = j * num;
        for(i = 0; i < i1; i++)
            fprintf(fp2, "%lf\n", x[i]);

        for(i = i1; i < len; i++){
            i2 = i - i1;
            x[i2] = x[i];
        }
        ls0 = len - i1;
    }while(!feof(fp1))
    fclose(fp);
    fclose(fp1);
    fclose(fp2);
    free(r);
    free(h);
    free(s);
}

rfft.cを参照してくださいここで本当の系列高速フーリエ変換()

rfft.c.に基づいてirfft.c相互の長さ係数を追加します。

おすすめ

転載: www.cnblogs.com/liam-ji/p/12003168.html