数字信号处理基础(二):FFT和IFFT的使用以及详细分析代码书写思路

1. fft和ifft的原理

1.1 fft

fft是快速傅里叶变换,是MATLAB中计算信号频谱的函数,使用方法是fft(x),直接对信号x进行fft计算。
由于fft函数计算信号的频谱是0-fs范围的,但是我们更习惯观察的信号的双边频谱,即-fs/2-fs/2范围的频谱,因此常用fftshift(x)函数将0-fs范围的信号频谱搬移到-fs/2-fs/2范围,也就是将原来0-fs范围中的fs/2-fs范围的频谱搬移到-fs/2-0范围处。

1.2 ifft

ifft是快速逆傅里叶变换,是MATLAB中求信号的逆傅里叶变换的函数,使用方法是ifft(x)。

2. 书写代码思路

1.养成良好习惯,在代码的最上面书写三件套代码,该清除的清除。

clear all;                  % 清除所有变量
close all;                  % 关闭所有窗口
clc;                        % 清屏

2.确定各个信号的频率以及信号的最高频率,本例中信号是正弦信号和余弦信号之和,分别确定各个信号频率,以及信号的最高频率,这里是3000Hz

fc1 = 1000;                 % 信号1的中心频率
fc2 = 3000;                 % 信号2的中心频率

3.根据信号的最高频率和奈奎斯特采样定理确定采样频率(大于信号最高频率的2倍即可),本人为了时域信号的平滑,通常将采样频率设置为最高频率的30倍左右。

fs = 100000;                % 采样频率,满足奈奎斯特采样定理即可,这里为信号频率的33倍原因是为了采样点数多,时域波形平滑

4.根据采样频率求得采样间隔,即采样频率的倒数

dt = 1/fs;                  % 采样间隔

5.确定仿真信号时长,这个一般根据实际情况来定,例如在通信系统中,首先需要确定码元周期,然后确定码元个数,两者相乘即是仿真时长,在本例中设置的时长是0.1。

T = 0.1;                    % 采样总时长

6.确定采样点数,为采样时长除以采样间隔。

N = T*fs;                   % 采样点数,N=T/dt=T*fs

7.确定仿真时间变量,从0开始,以采样间隔为间隔,形成1*N的行向量

t = 0:dt:(N-1)*dt;          % 时间行向量,间隔为dt

8.产生信号,并且绘制图像。

sig = sin(2*pi*fc1*t)+cos(2*pi*fc2*t);% 信号
figure(1);                  % 绘制第1幅图
plot(t,sig,'LineWidth',2);  % 绘制信号波形
axis([0 0.002 -2 2]);       % 坐标轴范围设置
xlabel('时间/t');           % 横坐标标签
ylabel('幅值');             % 纵坐标
title('原始信号');          % 标题
grid on;                    % 打开网格线

9.对信号进行fft,fft三步走

sig_f = fft(sig);           % 对信号进行fft
sig_f_2 = abs(sig_f);       % fft后取绝对值得到幅度响应
sig_f_2 = fftshift(sig_f_2);%0-fs频谱移动到-fs/2-fs/2

10.确定频谱分辨率fs/N=1/T

df = 1/T;                   % 频谱分辨率fs/N=1/T

11.确定频谱范围,即-fs/2-fs/2,间隔为频谱分辨率

f=(-N/2:N/2-1)*df;          % 频率范围

12.绘制频谱

figure(2);                  % 绘制第2幅图
plot(f,sig_f_2,'LineWidth',2);% 绘制信号的频谱
axis([-5000 5000 -inf inf]);% 坐标轴范围设置
xlabel('频率/Hz');          % 横坐标标签
ylabel('幅值');             % 纵坐标
title('原始信号的频谱');    % 标题
grid on;                    % 打开网格线

13.对信号做ifft,这里是对fft后的信号sig_f进行ifft,而不是对进行fft三步走后的信号sig_f_2进行ifftshift,然后进行ifft,因为三步走中有一步是取绝对值,通过ifftshift然后ifft无法准确还原出原始信号,因此为了还原出原始信号,应该对fft后的信号sig_f进行ifft,这也是为什么要三步走的原因,而不采用一行生成的代码fftshift(abs(fft(x)))。

sig_ifft = ifft(sig_f);     % 对fft后的信号进行ifft还原成时域信号

14.绘制还原后信号图像

plot(t,sig_ifft,'LineWidth',2);% 绘制还原后的时域信号
axis([0 0.002 -2 2]);       % 坐标轴范围设置
xlabel('时间/t');           % 横坐标标签
ylabel('幅值');             % 纵坐标
title('还原后信号');        % 标题
grid on;                    % 打开网格线

3. 完整代码

clear all;                  % 清除所有变量
close all;                  % 关闭所有窗口
clc;                        % 清屏
%% 基本参数
fc1 = 1000;                 % 信号1的中心频率
fc2 = 3000;                 % 信号2的中心频率
fs = 100000;                % 采样频率,满足奈奎斯特采样定理即可,这里为信号频率的33倍原因是为了采样点数多,时域波形平滑
dt = 1/fs;                  % 采样间隔
T = 0.1;                    % 采样总时长
N = T*fs;                   % 采样点数,N=T/dt=T*fs
t = 0:dt:(N-1)*dt;          % 时间行向量,间隔为dt
sig = sin(2*pi*fc1*t)+cos(2*pi*fc2*t);% 信号
figure(1);                  % 绘制第1幅图
plot(t,sig,'LineWidth',2);  % 绘制信号波形
axis([0 0.002 -2 2]);       % 坐标轴范围设置
xlabel('时间/t');           % 横坐标标签
ylabel('幅值');             % 纵坐标
title('原始信号');          % 标题
grid on;                    % 打开网格线
sig_f = fft(sig);           % 对信号进行fft
sig_f_2 = abs(sig_f);       % fft后取绝对值得到幅度响应
sig_f_2 = fftshift(sig_f_2);%0-fs频谱移动到-fs/2-fs/2
df = 1/T;                   % 频谱分辨率fs/N=1/T
f=(-N/2:N/2-1)*df;          % 频率范围
figure(2);                  % 绘制第2幅图
plot(f,sig_f_2,'LineWidth',2);% 绘制信号的频谱
axis([-5000 5000 -inf inf]);% 坐标轴范围设置
xlabel('频率/Hz');          % 横坐标标签
ylabel('幅值');             % 纵坐标
title('原始信号的频谱');    % 标题
grid on;                    % 打开网格线
sig_ifft = ifft(sig_f);     % 对fft后的信号进行ifft还原成时域信号
figure(3);                  % 绘制第3幅图
plot(t,sig_ifft,'LineWidth',2);% 绘制还原后的时域信号
axis([0 0.002 -2 2]);       % 坐标轴范围设置
xlabel('时间/t');           % 横坐标标签
ylabel('幅值');             % 纵坐标
title('还原后信号');        % 标题
grid on;                    % 打开网格线

4. 结果图

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_47598782/article/details/130773079