一、快速傅里叶变换
1.语法
Y = fft(X)
Y = fft(X,n)
Y = fft(X,n,dim)
2.说明
(1)Y = fft(X)
使用快速傅里叶变换 (FFT) 算法计算 X 的离散傅里叶变换 (DFT)。Y 与 X 的大小相同。
如果 X 是向量,则 fft(X) 返回该向量的傅里叶变换。
如果 X 是矩阵,则 fft(X) 将 X 的各列视为向量,并返回每列的傅里叶变换。
如果 X 是一个多维数组,则 fft(X) 将沿大小不等于 1 的第一个数组维度的值视为向量,并返回每个向量的傅里叶变换。
(2)Y = fft(X,n)
返回 n 点 DFT。
如果 X 是向量且 X 的长度小于 n,则为 X 补上尾零以达到长度 n。
如果 X 是向量且 X 的长度大于 n,则对 X 进行截断以达到长度 n。
如果 X 是矩阵,则每列的处理与在向量情况下相同。
如果 X 为多维数组,则大小不等于 1 的第一个数组维度的处理与在向量情况下相同。
(3)Y = fft(X,n,dim)
返回沿维度 dim 的傅里叶变换。例如,如果 X 是矩阵,则 fft(X,n,2) 返回每行的 n 点傅里叶变换。
二、实数信号的FFT
1.采样点为偶数的情况
(1)单边谱
经过FFT之后的频率对应的幅值并不是真实的幅值,想要将FFT之后的频谱图跟实际的幅值对应,就要进行相应的转换。频率序号为0和
N
2
\frac{N}{2}
2N的两个点的带宽只占中间频率点的一半,也就是占
1
N
\frac{1}{N}
N1的带宽,因此只需要将幅值乘以
1
N
\frac{1}{N}
N1即可。
代码如下:
% DrawRealFFT:绘制实数信号的FFT
% N为偶数(最好为2的整数次方)
function [MagY,f] = DrawRealFFT(RealData, fs)
N = length(RealData);
fft_RealData = fft(RealData);
MagY = abs(fft_RealData(1:N/2+1));
MagY(1)=MagY(1)/N; % 频率为0的位置除以N
MagY(end)=MagY(end)/N; % 频率为Fs/2的位置也除以N
MagY(2:end-1)=2*MagY(2:end-1)/N; % 其余频率点乘以2/N
f = (0:N/2)'*fs/N;
plot(f,MagY);
grid on;
xlabel('f(Hz)'), ylabel('幅度');
end
(2)双边谱
代码如下:
function [f,MagY] = DrawRealBilateralSpectrum(RealxData,fs)
N = length(RealxData);
Fs = fs;
f = Fs/N*(-N/2:N/2-1) ;
MagY = abs(fftshift(fft(RealxData)))*1/N;
plot(f,MagY);
xlabel('Frequency');
ylabel('Amplitude');
end
2.采样点为奇数的情况
(1)单边谱
当我们的样本点N为奇数时,只有0频率占
1
N
\frac{1}{N}
N1带宽,其余的
N
+
1
2
\frac{N+1}{2}
2N+1个频率点仍然是对应幅值乘以
2
N
\frac{2}{N}
N2得到真实的幅值。
代码如下:
% DrawRealFFT:绘制实数信号的FFT
% N为偶数(最好为2的整数次方)
function [MagY,f] = DrawRealFFT(RealData, fs)
N = length(RealData);
fft_RealData = fft(RealData);
MagY = abs(fft_RealData(1:N/2+1));
MagY(1)=MagY(1)/N; % 频率为0的位置除以N
MagY(2:end)=2*MagY(2:end)/N; % 其余频率点乘以2/N
f = (0:N/2)'*fs/N;
plot(f,MagY);
grid on;
xlabel('f(Hz)'), ylabel('幅度');
end
(2)双边谱
代码如下:
function [f,MagY] = DrawRealBilateralSpectrum(RealxData,fs)
N = length(RealxData);
Fs = fs;
f = Fs/N*(-N/2:N/2-1) ;
MagY = abs(fftshift(fft(RealxData)))*1/N;
plot(f,MagY);
xlabel('Frequency');
ylabel('Amplitude');
end
三、复数信号的FFT
1.单边谱
对于复数信号,N个点FFT之后会产生N个频率点,频谱的带宽为N,每个点所占的带宽为
1
N
\frac{1}{N}
N1 ,将每个幅值都乘以
1
N
\frac{1}{N}
N1即可得到真实的频率幅值。
代码如下:
% DrawComplexFFT:绘制复数信号的FFT
% 对于复数信号,N个点FFT之后会产生N个频率点,频谱的带宽为N,每个点所占的带宽为1/N
% 将每个幅值都乘以1/N即可得到真实的频率幅值
function [MagY,f] = DrawComplexFFT(ComplexData, fs)
N = length(ComplexData);
fft_ComplexData = fft(ComplexData);
MagY = abs(fft_ComplexData(1:N/2+1))*1/N;
f = (0:N/2)'*fs/N;
plot(f,MagY);
grid on;
xlabel('f(Hz)'), ylabel('幅度');
end
2.双边谱
代码如下:
function [f,MagY] = DrawComplexBilateralSpectrum(ComplexData,fs)
N = length(ComplexData);
Fs = fs;
f = Fs/N*(-N/2:N/2-1) ;
MagY = abs(fftshift(fft(ComplexData)))*1/N;
plot(f,MagY);
xlabel('Frequency');
ylabel('Amplitude');
end
四、示例
1.实验代码
clear;clc;
close all;
Fs=1000; % 采集频率
T=1/Fs; % 采集时间间隔
N=2000; % 采集信号的长度--采样点数
f1=33; % 第一个余弦信号的频率
f2=200; % 第二个余弦信号的频率
f3=500; % 第二个余弦信号的频率
t=(0:1:N-1)*T; % 定义整个采集时间点
t=t'; % 转置成列向量
ComplexY = 1.2+2.7*exp(1j*2*pi*f1*t)+5*exp(1j*2*pi*f2*t)+4*exp(1j*2*pi*f3*t); % 复数时域信号
DoubleY = 1.2+2.7*cos(2*pi*f1*t+pi/4)+5*cos(2*pi*f2*t+pi/6)+4*cos(2*pi*f3*t+pi/3); % 实数时域信号
figure(1);
DrawComplexFFT(ComplexY,Fs);
figure(2);
DrawComplexBilateralSpectrum(ComplexY,Fs);
figure(3);
DrawRealFFT(DoubleY,Fs);
figure(4);
DrawRealBilateralSpectrum(DoubleY,Fs);
2.实验结果
如图所示,复数信号的双边谱不是对称的。画图时,单边谱的横坐标为f = (0:N/2)'fs/N,即频率从0到
F
s
2
\frac{F_{s}}{2}
2Fs,所以对于单边谱来说,频率为500(即
F
s
2
\frac{F_{s}}{2}
2Fs)的谱线出现在频率为500处。双边谱的横坐标为Fs/N(-N/2:N/2-1),即频率从
−
F
s
2
-\frac{F_{s}}{2}
−2Fs到
F
s
2
−
F
s
N
\frac{F_{s}}{2}-\frac{F_{s}}{N}
2Fs−NFs,在本例中即-500Hz~499.5Hz,所以对于双边谱来说,频率为500(即
F
s
2
\frac{F_{s}}{2}
2Fs)的谱线出现在频率为-500处。