FFT算法理解与实现

快速傅里叶变换(一)
参考这本书理解FFT基本概念
FFT是DFT(discrete Fourier Transform)一种快速算法。
傅里叶变换: 任何连续的周期信号可以分解成许多正弦波与余弦波。

为什么分解成正余弦波?
因为正余弦波输入一个系统,输出仍然是正余弦波,只有幅度与相位发生变化,频率与波形保持不变,更容易分析信号特征。

傅里叶变换可以分为四种:
1.非周期连续信号———->傅里叶变换(FourierTransform)
例如:高斯分布曲线
2. 周期连续信号———–>傅里叶级数 (Fourier Series)
例如:正弦波,方波
3. 非周期离散信号———>离散时间域的傅里叶变换(Discrete TimeFourierTransform)DTFT
4. 周期离散信号———->离散傅里叶级数(DiscreteFourierSeries)但一般都叫(Discrete Fourier Transform)DFT

傅里叶变换分类比较容易弄混,记住就好了。
实际用于DSP的只有DFT(离散傅里叶变换)
DFT 基本方程:
cK[i]=cos(2πKi/N),(i[0,N1]);
sK[i]=sin(2πKi/N),(i[0,N1]);
k[0,N/2];
k 代表频率,cK[i],sK[i]分别表示余弦波、正弦波。
由下面公式

ReX[k]=i=0N1x[i]cos(2πki/N)

ImX[k]=i=0N1x[i]sin(2πki/N)

k[0,N/2];
可以实现DFT算法

        //1 real inverse_DFT ,[in]frequency domain realARR;
        //2. [in] frequency domain imagine maguide
        //3. [out] y synthesis time domain signal
        public static void I_DFT(double[] X_R, double[] X_I, out double[] y)
        {
            int N = (X_R.Length - 1) * 2;/////N 点时域信号。
            double[] yy = new double[N];//X_R[] Frequency  real Part, X_I[] Frequency Im part.
            for (int i = 0; i <= N / 2; i++)
            {
                X_R[i] = X_R[i] / (N / 2);
                X_I[i] = -X_I[i] / (N / 2);

            }
            X_R[0] = X_R[0] / 2;
            X_R[N / 2] = X_R[N / 2] / 2;

            for (int k = 0; k <= N / 2; k++)
            {
                for (int i = 0; i < N; i++)
                {
                    yy[i] = yy[i] + X_R[k] * Math.Cos(2 * Math.PI * k * i / N);
                    yy[i] = yy[i] + X_I[k] * Math.Sin(2 * Math.PI * k * i / N);
                }
            }
            /////////////////////////////////////////////////
            y = yy;
        }
        public static void DFT(double[] xx, out double[] REX, out double[] IMX)
        {
            int N = xx.Length;
            double[] temp_re = new double[N / 2 + 1];
            double[] temp_im = new double[N / 2 + 1];

            for (int k = 0; k <= N / 2; k++)
            {
                for (int i = 0; i < N; i++)
                {
                    temp_re[k] = temp_re[k] + xx[i] * Math.Cos(2 * Math.PI * k * i / N);
                    temp_im[k] = temp_im[k] - xx[i] * Math.Sin(2 * Math.PI * k * i / N);

                }
            }
            REX = temp_re;
            IMX = temp_im;
        }
  • 0
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 以下是基于2fft算法的Matlab代码实现,带有注释说明: ```matlab function [y] = fft2(x) % 2fft算法,输入x为列向量 % 输出y为x的傅里叶变换结果 N = length(x); if N == 1 % 若序列长度为1,则返回x本身 y = x; else % 若序列长度不为1,则进行递归计算 % 将x拆分为奇数项和偶数项 x_odd = x(1:2:N-1); x_even = x(2:2:N); % 对奇数项和偶数项分别进行fft2计算 y_odd = fft2(x_odd); y_even = fft2(x_even); % 构建旋转因子矩阵W W_N = exp(-2*pi*1i/N); W = ones(N, 1); for k = 2:N/2 W(k) = W(k-1) * W_N; end % 将y_odd和y_even按照W进行加权和 y = [y_odd + W(1:N/2) .* y_even; y_odd - W(1:N/2) .* y_even]; end end ``` 需要注意的是,该实现只适用于输入为列向量的情况。如果输入为行向量,需要先将其转置为列向量再进行计算。另外,在实际使用中,建议使用Matlab内置的fft函数,该函数已经经过高度优化,可以获得更快的计算速度。 ### 回答2: 2FFT算法是快速傅里叶变换(FFT)的一种变体,用于高效计算离散傅里叶变换(DFT)。它将长度为2的信号序列分成两个具有相等长度的子序列,然后对每个子序列进行FFT计算。最后通过合并两个子序列的结果,得到原始序列的FFT结果。 在MATLAB中实现2FFT算法,首先需要定义一个计算FFT的函数。该函数的输入参数包括信号序列和采样频率。其中,信号序列是一个长度为2的向量,采样频率是一个标量。 然后,可以通过定义一个主函数,并调用刚刚定义的FFT函数来实现2FFT算法。在主函数中,首先读取信号序列和采样频率,然后调用FFT函数进行计算。最后,输出计算得到的FFT结果。 以下是用300字中文描述的示例代码和注释: ```MATLAB % 定义FFT函数 function fft_result = fft_func(signal, sample_rate) % 对输入信号序列进行FFT计算 fft_result = fft(signal); end % 主函数 function main() % 读取信号序列和采样频率 signal = [1, 2]; sample_rate = 1000; % 调用FFT函数进行计算 fft_result = fft_func(signal, sample_rate); % 输出计算结果 disp(fft_result); end % 调用主函数 main(); ``` 在上述代码中,我们首先定义了一个名为`fft_func`的函数,用来计算输入信号序列的FFT结果。这个函数直接使用MATLAB内置的`fft`函数进行计算,并将计算结果返回。 然后,我们定义了一个名为`main`的主函数。在这个函数中,我们定义了输入信号序列`signal`和采样频率`sample_rate`的值。然后,我们调用了`fft_func`函数,并将信号序列和采样频率作为参数传递给它。最后,使用`disp`函数将计算得到的FFT结果输出到命令行窗口中。 最后,我们调用了`main`函数,开始执行主程序。成功运行后,将在命令行窗口中显示计算得到的FFT结果。 ### 回答3: 2-FFT(快速傅里叶变换)算法是一种用于加快傅里叶变换计算速度的算法。它的实现基于分治法,通过将一次N点的傅里叶变换拆分为两次N/2点的傅里叶变换,从而实现快速计算。 以下是基于2-FFT算法的Matlab实现,加上了注释以便理解: ```matlab function y = fft2(x) N = length(x); % 如果输入序列长度为1,返回输入序列本身 if N == 1 y = x; return; end % 将输入序列分成偶数和奇数部分 even = x(1:2:N); odd = x(2:2:N); % 递归地对偶数、奇数部分分别进行2-FFT变换 even_fft = fft2(even); odd_fft = fft2(odd); % 计算旋转因子 W_N = exp(-1i * 2 * pi / N).^((0:N/2-1)'); % 合并结果 y_top = even_fft + W_N .* odd_fft; y_bottom = even_fft - W_N .* odd_fft; % 连接子问题的解 y = [y_top; y_bottom]; end % 测试代码 x = [1 2 3 4]; % 输入序列 y = fft2(x); % 调用2-FFT算法计算傅里叶变换 disp(y); % 输出结果 ``` 此代码实现了基于2-FFT算法的傅里叶变换。首先判断输入序列的长度,如果长度为1,则返回序列本身。否则,将输入序列分成偶数和奇数部分,并递归地对分开的序列进行2-FFT变换。然后计算旋转因子,并将变换后的结果合并。最后返回合并后的结果,即为输入序列的傅里叶变换结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值