快速相关

一、功能

用快速傅里叶变换计算两个有限长序列的线性相关。

二、方法简介

设序列\(x(n)\)的长度为\(M\),序列\(y(n)\)的长度为\(N\),序列\(x(n)\)\(y(n)\)的互相关定义为
\[ z(n)=\sum_{i=0}^{M-1}x(i)y(n+i), \ n=-(M-1),...,N-1 \]
序列\(x(n)\)的自相关定义为
\[ z(n)=\sum_{i=0}^{M-1}x(i)x(n+i), \ n=-(M-1),...,N-1 \]
显然,如果\(M=M\)并且序列\(x(n)\)\(y(n)\)相同,那么互相关就变成了自相关。

用快速傅里叶变换计算线性相关的算法如下:

1、选择\(L\)满足下述条件

\[ \left\{\begin{matrix}\begin{align*}L &\geqslant M + N - 1\\ L &= 2^{\gamma }, \ \gamma \ is \ positive \ integer\end{align*}\end{matrix}\right. \]
2、将序列\(x(n)\)\(y(n)\)按如下方式补零,形成长度为\(L=2^{\gamma }\)的序列
\[ \bar{x}(n)=\left\{\begin{matrix}\begin{align*}x(n) & , \ n=0,1,...,M-1\\ 0 & , \ n=0,1,...,M,M+1,...,L-1\end{align*}\end{matrix}\right. \]

\[ \bar{y}(n)=\left\{\begin{matrix}\begin{align*}0 & , \ n = 0,1,...,M-2\\ y(n) & , \ n = M-1, M,...,M+N-2\\ 0 & , \ n = M+N-1, M+N,...,L-1\end{align*}\end{matrix}\right. \]

3、用FFT算法分别计算序列\(\bar{x}(n)\)\(\bar{y}(n)\)的离散傅里叶变换\(X(k)\)\(Y(k)\)
\[ X(k)=\sum_{n=0}^{L-1}\bar{x}(n)e^{-j2\pi nk/L} \]

\[ Y(k)=\sum_{n=0}^{L-1}\bar{y}(n)e^{-j2\pi nk/L} \]

4、计算\(X(k)\)\(Y(k)\)的乘积
\[ Z(k)=X^*(k)Y(K) \]
其中\(*\)表示复共轭;

5、用FFT算法计算\(Z(k)\)的离散傅里叶反变换,得到线性相关\(z(n)\)
\[ z(n)=\frac{1}{N}\sum_{k=0}^{L-1}Z(k)e^{j2\pi nk/L}, \ n=0,1,...,L-1 \]
序列\(z(n)\)的前\(M+N-1\)点的值就是序列\(x(n)\)\(y(n)\)的线性相关。

三、使用说明

快速卷积的C语言实现方式如下

/************************************
    x           ----双精度实型一维数组,长度为m。开始时存放实序列x(i),最后存放线性相关的值。
    y           ----双精度实型一维数组,长度为n。开始时存放实序列y(i)。
    m           ----整型变量。序列x(i)的长度。
    n           ----整型变量。序列y(i)的长度。
    len         ----整型变量。len>=m+n-1,且必须是2的整数次幂,即len=2^gamma
************************************/
#include "stdlib.h"
#include "rfft.c"
#include "irfft.c"
void correl(double *x, double *y, int m, int n, int len)
{
    int i, len2;
    double t, *z;
    z = mlloc(len * sizeof(double));
    for(i = m; i < len; i++)
        x[i] = 0.0;
    for(i = 0; i < (m - 1); i++)
        z[i] = 0.0;
    for(i = (m - 1); i <= (m + n - 2); i++)
        z[i] = y[i - m + 1];
    for(i = (m + n - 1); i < len; i++)
        z[i] = 0.0;
    rfft(x, len);
    rfft(z, len);
    len2 = len / 2;
    x[0] = x[0] * z[0];
    x[len2] = x[len2] * z[len2];
    for(i = 1; i < len2; i++){
        t = x[i] * z[i] + x[len - i] * z[len - i];
        x[len - 1] = x[i] * z[len - i] - x[len - i] * z[i];
        x[i] = t;
    }
    irfft(x, len);
    free(z);
}

其中rfft.c文件请参考实序列快速傅里叶变换(一)

irfft.c在rfft.c的基础上添加系数长度的倒数。

猜你喜欢

转载自www.cnblogs.com/liam-ji/p/12057279.html