离散傅里叶变换及matlab实现(按时间抽选(DIT)的基-2 FFT算法(库利-图基算法))

转,傅里叶变换,很好的解释 很好的文章,可惜水平太差,还没有完全理解。

快速傅里叶的matlab实现

按时间抽选(DIT)的基-2 FFT算法(库利-图基算法)

傅里叶要用到的nn个复数,不是随机找的,而是——把单位圆(圆心为原点、1为半径的圆)nn等分,取这nn个点(或点表示的向量)所表示的虚数,即分别以这nn个点的横坐标为实部、纵坐标为虚部,所构成的虚数。

 

64点傅里叶变换的matlab代码

function FFT(x)
%******************************************************
%*********按时间抽选的基2-FFT算法*******
%输入参数:x-离散时间信号
%输出参数:X-序列x的N点DFT(N是序列长度,必须是2的整数次幂)
%*******************************************************
    N = 64;                                             %64点FFT N应该为一个全局变量
    M=log2(N);
    if length(x) < N 
        x = [x; zeros(1,N-length(x))'];                   %若x的长度不是2的整数次幂,则补零至N
    end
    BRTable = bin2dec(fliplr(dec2bin([1:N]-1,M))) + 1;  %求 1:N 序列序号的倒位序:1.将系数取二进制并对调,然后取十进制 
                                                        %2.matlab的下标从1开始,需要加1
    X = x(BRTable);                                     %调整x输入顺序后的序列,并作为X的初始化 
    
    WN = exp(-j*2*pi/N);                                %旋转因子
    
    for L = 1:M;
        B = 2^(L-1);                                    %第L级中,每个蝶形的两个输入数据相聚B个点,共有B个旋转因子
        for J = 0:B-1;                                  %第L级中不同的旋转因子
            p = J*2^(M-L);                              %旋转因子的指数
            WNp = WN^p;
            for k = J+1 : 2^L : N ;                
                t = X(k+B) * WNp;                       %产生错误:未定义与'cell'类型的输入参数相对应的运算符‘*’-x=[]非x={}
                X(k+B) = X(k)-t;
                X(k) = X(k)+t;                
            end
        end
    end
end

离散化处理,求64点FFT(以下代码已更新,之前有几个符号写错了,天知道我是怎么工作的!!!以头抢地尔)

function Result = FFT(x, N)
x = double(x);
f = 1;
if f > 0
    %N = 64;                                             %64点FFT N应该为一个全局变量
    M = log2(N);
    if length(x) < N ;
        x = [x zeros(1,N-length(x))];                   %若x的长度不是2的整数次幂,则补零至N
    end
    BRTable = bin2dec(fliplr(dec2bin([1:N]-1,M))) + 1;  %求 1:N 序列序号的倒位序:1.将系数取二进制并对调,然后取十进制 
                                                        %2.matlab的下标从1开始,需要加1
    Xreal = x(BRTable);                                 %调整x输入顺序后的序列,并作为X的初始化 
    Ximag = zeros(1,N);
    X = x(BRTable);
    WN = exp(-j*2*pi/N);
    for L = 1:M;
        B = 2^(L-1);                                    %第L级中,每个蝶形的两个输入数据相聚B个点,共有B个旋转因子
        for J = 0:B-1;                                  %第L级中不同的旋转因子
            p = J*2^(M-L);                              %旋转因子的指数
            WNp = WN^p;
            %p = p*j;
            for k = J+1: 2^L : N; 
 %计算出来的包括实部和虚部  此种方法已验证正确
 f=0;
 if f>0
                 t = X(k+B) * WNp;                         %产生错误:未定义与'cell'类型的输入参数相对应的运算符‘*’-x=[]非x={}              
                 X(k+B) = X(k)-t;                          %将公式写成指数的形式,按虚实区分
                 X(k) = X(k)+t;
 else 
 %计算出来的实部 虚部分开,正确
                 Wncosp = cos(2*pi/N*p);
                 Wnsinp = sin(2*pi/N*p);
                 Treal = Xreal(k+B)*Wncosp+Ximag(k+B)*Wnsinp;
                 Timag = Ximag(k+B)*Wncosp-Xreal(k+B)*Wnsinp;
                 Xreal(k+B) = Xreal(k) -Treal;
                 Ximag(k+B) = Ximag(k) -Timag;
                 Xreal(k) = Xreal(k)+Treal;
                 Ximag(k) = Ximag(k)+Timag;
  
%以下C语言中应该可以                 
%                  Xreal(k+B) = Xreal(k)-Xreal(k+B)*cos(2*pi/N*p)-Ximag(k+B)*sin(2*pi/N*p);
%                  Ximag(k+B) = Ximag(k)+Xreal(k+B)*sin(2*pi/N*p)-Ximag(k+B)*cos(2*pi/N*p);
%                  Xreal(k) = Xreal(k)+Xreal(k+B)*cos(2*pi/N*p)+Ximag(k+B)*sin(2*pi/N*p);
%                  Ximag(k) = Ximag(k)-Xreal(k+B)*sin(2*pi/N*p)+Ximag(k+B)*cos(2*pi/N*p);

%将l写成了1,以下正确
%                   a1 = real(X(k+B));
%                   a2 = real(exp(-j*2*pi/N*p));
%                   b1 = imag(X(k+B));
%                   b2 = imag(exp(-j*2*pi/N*p));
%                   temp =a1*a2-b1*b2+j*(a1*b2+b1*a2);
%                   X(k+B) = X(k)-temp;
%                   X(k) = X(k)+temp;
end

            end
        end
    end

%}
else
    L = ceil(log2(length(x)));
    N = 2^L;

    if length(x) < N
         x = [x zeros(1,N-length(x))];
    end 
    BRTable = bin2dec(fliplr(dec2bin([1:N]-1,L))) + 1;
    % x_rep = x(BRTable);
    x_rep = seq_replace(x);

    for l = 1:L
        d = 2^(l-1);
        for n = 1:d
            for k = n:2*d:N
                k_dual = k+d;
                r = (k-1)*2^(L-1);
                a1 = real(x_rep(k_dual));
                a2 = real(exp(-j*2*pi/N*r));
                b1 = imag(x_rep(k_dual));
                b2 = imag(exp(-j*2*pi/N*r));
                temp = a1*a2-b1*b2+j*(a1*b2+b1*a2);
                x_rep(k_dual) = x_rep(k) -temp;
                x_rep(k) = x_rep(k)+temp;
            end
        end
    end

end

    %求数据的模
    for i = 1:1:N;
        Rereal(i) = Xreal(i)*Xreal(i);
        Reimag(i) = Ximag(i)*Ximag(i);
        Result(i) = sqrt(Rereal(i)+Reimag(i));
        %fprintf('%d  ',Result(i));
    end
end

输入错一个:,写成了;,找了一小时的错误,唉

基于64点输入如下:

L = log2(N);
 
if length(x) < N
     x = [x zeros(1,N-length(x))];
end 
 BRTable = bin2dec(fliplr(dec2bin([1:N]-1,L))) + 1;
x_rep = x(BRTable);

for l = 1:L
    d = 2^(l-1);
    for n = 1:d
        for k = n:2*d:N
            k_dual = k+d;
            r = (k-1)*2^(L-l);  %这里是l,不是1
            a1 = real(x_rep(k_dual));
            a2 = real(exp(-j*2*pi/N*r));
            b1 = imag(x_rep(k_dual));
            b2 = imag(exp(-j*2*pi/N*r));
            temp = a1*a2-b1*b2+j*(a1*b2+b1*a2);
            x_rep(k_dual) = x_rep(k) -temp;
            x_rep(k) = x_rep(k)+temp;
        end
    end
end

验证

x=[1 2 3 4 5 6 7 8];
调用 FFT(x,8);
result =

  1 至 7 列

  36.0000 + 0.0000i  -4.0000 + 9.6569i  -4.0000 + 4.0000i  -4.0000 + 1.6569i  -4.0000 + 0.0000i  -4.0000 - 1.6569i  -4.0000 - 4.0000i

  8 列

  -4.0000 - 9.6569i

基于64点的FFT求128点FFT

%% 128点FFT(基于以上64点)
% x:输入序列
% N:128
% X:输出序列
function X = FFT128(x,N)
    if length(x) < N
        x = [x,zeros(1,N-length(x))];
    end
    
    y1 = FFT(x(1:2:128),64);  %计算偶数组的64点FFT
    y2 = FFT(X(2:2:128),64);    %计算奇数组的64点FFT
    wn = exp(-j*2*pi/128);
    X(1:64) = y1+y2.*(wn.^[0:63]);
    X(65:128) = y1-y2.*(wn.^[0:63]);
 end

1.

2,

3,

 

你可能感兴趣的:(matlab)