まず、機能
高速コンボリューション法で特に長い系列と短いシーケンスを計算し、オーバーラップセーブ高速フーリエ変換。これは通常、デジタルフィルタリングのために使用されています。
第二に、この方法の紹介
リセットシーケンス\(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相互の長さ係数を追加します。