原文链接:https://blog.csdn.net/defu123sss/article/details/80457699

点击查看更多通信知识点击此处

快速傅里叶变换(Fast Fourier transform,FFT)

利用离散傅里叶变换(DTF)算法进行运算时,复数乘法运行次,复数加法运行次,计算量其实可以通过fft减小。1965年,首先由Cooley-Tukey提出了基-2FFT算法,对DFT的发展起到了极大推进作用。随后又出现了混合基算法。fft 是一种计算DTF的快速算法,利用因子的周期性、共轭对称性、可约性。

 

1、fft算法主要有以下3种

时域抽取基-2FFT算法(Decimation -In- Time,DIT-FFT)

频域抽取基-2FFT算法(Decimation-In-Freqency,DIF-FFT)

序列长度N可表示为合数的FFT 算法(混合基)

 

2、fft函数

(matlab说明文档:https://ww2.mathworks.cn/help/matlab/ref/fft.html?searchHighlight=fft&s_tid=doc_srchtitle

  
  
  1. Y = fft(X)
  2. Y = fft(X,n)
  3. Y = fft(X,n,dim)

 

2.1 Y = fft(X) ——用快速傅里叶变换 (FFT) 算法计算 X 的离散傅里叶变换 (DFT)。

如果 X 是向量,则 fft(X) 返回该向量的傅里叶变换。

如果 X 是矩阵,则 fft(X) 将 X 的各列视为向量,并返回每列的傅里叶变换。

如果 X 是一个多维数组,则 fft(X) 将沿大小不等于 1 的第一个数组维度的值视为向量,并返回每个向量的傅里叶变换。

 

2.2 Y = fft(X,n) ——返回 n 点 DFT。如果未指定任何值,则 Y 的大小与 X 相同。

如果 X 是向量且 X 的长度小于 n,则为 X 补上尾零以达到长度 n。

如果 X 是向量且 X 的长度大于 n,则对 X 进行截断以达到长度 n。

如果 X 是矩阵,则每列的处理与在向量情况下相同。

如果 X 为多维数组,则大小不等于 1 的第一个数组维度的处理与在向量情况下相同。

 

2.3 Y = fft(X,n,dim) ——返回沿维度 dim 的傅里叶变换。

如果 X 是矩阵,则 fft(X,n,2) 返回每行的 n 点傅里叶变换。

 

具体的示例都在官方文档中,这里说说fft函数的特点:

1.  函数fft返回值的数据结构具有对称性

根据采样定理,fft能分辨的最高频率为采样频率的一半(即Nyquist频率),函数fft返回值是以Nyqusit频率为轴对称的,Y的前一半与后一半是复数共轭关系,信息其实是重复的。所以,如果进行N点的fft,实际上有用的点数为n+1点(N为奇数或者偶数的情况下有用的点数均相同)。

Fn = (n-1)* Fs /N

Fn是第n点所表示的真实频率值。当然,n只取前一半的点就足够了。这样,可以达到的频率分辨率即为Fs/N。

2.  幅值

作FFT分析时,幅值大小与输入点数有关,要得到真实的幅值大小,需要将变换后的结果除以N。且由于零频在双边谱中本没有被一分为二,所以对于零频外的点还有乘以2,得到的才是真实的频率幅值。

  
  
  1. Y = fft(X); % X为信号
  2. P2 = abs(Y/L); % 计算双侧频谱 P 2
  3. P1 = L*P 2( 1:L/ 2+ 1); % 将P 2的前半段信号赋给P 1,P 1即是我们关心的部分
  4. P1( 2:end- 1) = 2*P 1( 2:end- 1); % 将除零频外的信号乘以 2

3.  基频

​若分析数据时长为T,则分析结果的基频就是f0=1/T,分析结果的频率序列为[0:N-1]*f0

4.  执行N点FFT

在调用格式 2.2 中,函数执行N点FFT。若y为向量且长度小于N,则函数将y补零至长度N,若向量y的长度大于N,则函数截断y使之长度为N。由于fft算法的本质,对于N的选取一般为大于序列长度点数的最小2的幂次方,这样能改善 fft 的计算性能。

  
  
  1. N = 2^nextpow2(L) ; % 将高斯脉冲转换为频域
  2. Y = fft(X,N) ;

而如果未制定进行fft的点数N,默认产生的结果为N点,默认进行的fft便是基于混合基来进行计算的,性能当然不会优于基2。

3、fftshift函数

官方文档:

https://ww2.mathworks.cn/help/matlab/ref/fftshift.html

fftshift的功能是将零频分量移到频谱中心。怎么理解这句话呢?fft计算得到的频域信号的频率区间是0~Fs(Fs是采样频率)的,且关于Fs/2对称。称0~FS为数字频率,对应模拟角频。但是我们只关心区间,fftshift函数的功能就是将fft处理之后的部分搬移至,从而使零频分量居于频谱的中心位置。

 

Y = fftshift(X) 通过将零频分量移动到数组中心,重新排列傅里叶变换 X。

如果 X 是向量,则 fftshift 会将 X 的左右两半部分进行交换。

如果 X 是矩阵,则 fftshift 会将 X 的第一象限与第三象限交换,将第二象限与第四象限交换。

如果 X 是多维数组,则 fftshift 会沿每个维度交换 X 的半空间。

 

Y = fftshift(X,dim) 沿 X 的维度 dim 执行运算。例如,如果 X 是矩阵,其行表示多个一维变换,则 fftshift(X,2) 会将 X 的每一行的左右两半部分进行交换。

注意:fftshift 没有fft的功能,是在 fft 之后进行的(有需要的话)。

运行代码:

  
  
  1. % fftshift
  2. fs = 100; % sampling frequency
  3. t = 0:( 1/fs):( 10 -1/fs); % time vector
  4. S = cos( 2*pi* 15*t);
  5. n = length(S);
  6. X = fft(S);
  7. f = ( 0:n -1)*(fs/n); %frequency range
  8. power = abs(X).^ 2/n; % power
  9. subplot (121);
  10. plot(f,power)
  11. xlabel( 'f');
  12. Y = fftshift(X);
  13. fshift = (-n/ 2:n/ 2 -1)*(fs/n); % zero-centered frequency range
  14. powershift = abs(Y).^ 2/n; % zero- centered power
  15. subplot (122);
  16. plot(fshift,powershift)
  17. xlabel( 'f');

得到如下的结果: