实验目的:
• 熟悉 Matlab 工具的基本用法
• 掌握 Matlab 代码编写方法
• 理解序列的离散时间傅里叶变换
• 理解 DFT 结果的频谱能量泄露
• 理解 DFT 和 DTFT 的对应关系
• 理解信号加窗的作用
实验内容:
• 任务1、单音正弦信号采样序列的时域绘图
• 任务2、单音正弦信号采样序列的DFT结果绘图
• 任务3、有限长矩形窗序列的DTFT
• 任务4、有限长正弦序列的DTFT
• 任务5、 DTFT 和 DFT 关系探寻
• 最终任务:双音信号频率分析
正弦信号及其采样序列的数学描述如下:
仿真中需要设定的信号配置参数:
1. 信号采样率 fs
2. 信号幅度 Amp
3. 正弦信号频率 f
4. 正弦初始相位为 phy
5. 信号采样序列长度 N
任务1、单音正弦信号采样序列的时域绘图
• 按照以下两组配置参数修改代码
• 观察绘制出的信号时域图样
配置参数 1:
f1 = 1000; Amp1 = 1; phy1 = 0; f2 = 7000; Amp2 = 1; phy2 = 0;
配置参数 2:
f1 = 1000; Amp1 = 1; phy1 = 0; f2 = 9000; Amp2 = 1; phy2 = 0;
实验代码:
% test with Matlab 2016
close all;
clear;
fig_fname = 'sine_1_tone.jpg';
fs = 8E3; % 采样率
N = 32; % 向量长度
% 信号频率、幅度、初相位
f1 = 1000; Amp1 = 1; phy1 = 0;
f2 = 7000; Amp2 = 1; phy2 = 0;
% 信号向量的下标索引
n_idx = [0:N-1];
% 生成信号采样序列向量
x1 = Amp1*sin(2*pi*f1/fs*n_idx + phy1);
x2 = Amp2*sin(2*pi*f2/fs*n_idx + phy2);
% 生成绘图的标题文字
str_fs = num2str(fs); str_N = num2str(N);
str_f1 = num2str(f1); str_Amp1 = num2str(Amp1); str_phy1 = num2str(phy1);
str_f2 = num2str(f2); str_Amp2 = num2str(Amp2); str_phy2 = num2str(phy2);
% 合成绘图标题文字
title_str1 = ['f1:', str_f1,'Hz, ', 'fs:', str_fs,'Hz, ' 'N:', str_N, ', Amp1:' str_Amp1, ', Phy1:', str_phy1];
title_str2 = ['f2:', str_f2,'Hz, ', 'fs:', str_fs,'Hz, ' 'N:', str_N, ', Amp2:' str_Amp2, ', Phy2:', str_phy2];
% 绘图
h = figure;
subplot(2,1,1);
plot(n_idx, x1, 'color', 'blue'); % 连线方式绘图
grid on; hold;
stem(n_idx, x1, 'color', 'red' ); % 离散样值方式绘图
title(title_str1, 'fontsize',14); % 绘制标题文字
subplot(2,1,2);
plot(n_idx, x2, 'color', 'blue'); % 连线方式绘图
grid on; hold;
stem(n_idx, x2, 'color', 'red' ); % 离散样值方式绘图
title(title_str2, 'fontsize',14); % 绘制标题文字
配置参数2代码与配置参数1代码相似,只需修改具体数值,下面只给出绘图。
• 请回答: 数字信号处理的课本中说数字采样信号的归一化角频率 ω 的数值范围是宽度为 2π 区间,这是为什么?
归一化频率是信号频率除以采样频率的一半,如果将归一化频率转换为角频率,则将归一化频率乘以π ,所以归一化角频率是宽度为2π 的区间。
• 请自行上网搜索关键字“带通采样定理”思考其原理和可行性
带通采样定理:设带通信号m(t),其频率限制在fL与fH之间,带宽为B=fH-fL,如果最小抽样速率fs=2fH/m,m是一个不超过fH/B的最大整数,那么m(t),可以完全由其抽样值确定。
• 任务2、单音正弦信号采样序列的DFT结果绘图
• 离散傅里叶变换 DFT
– 拥有著名的快速算法 — FFT
– DFT的主要用途:分析信号频谱
• 本实验的内容 – 计算确知信号(正弦信号)采样序列的DFT谱
– 设定不同的仿真配置,观察正弦信号的DFT谱
• 改变DFT的计算长度
• 改变输入正弦信号采样序列的频率
• 完成实验后思考问题 – 序列的DFT结果和其连续版本信号的频谱完全一致么?
实验代码:
主函数
% file: sine_1_tone_dft.m
% test with Matlab 2016
close all;
clear;
fig_fname_0 = 'sine_1_tone_dft_0.jpg';
fig_fname_1 = 'sine_1_tone_dft_1.jpg';
fig_fname_2 = 'sine_1_tone_dft_2.jpg';
fs = 8E3;
f0_0 = 500; f0_1 = 600; f0_2 = 500;
N_0 = 32 ; N_1 = 32 ; N_2 = 35 ;
% plot each case
func_sine_1_tone_dft_plot(f0_0, fs, N_0, fig_fname_0);
func_sine_1_tone_dft_plot(f0_1, fs, N_1, fig_fname_1);
func_sine_1_tone_dft_plot(f0_2, fs, N_2, fig_fname_2);
子函数
% test with Matlab 2016
% file: func_sine_1_tone_dft_plot.m
% 绘图程序:绘制信号采样序列的 时域波形,
% 线性尺度DFT幅度谱,对数尺度DFT幅度谱
function func_sine_1_tone_dft_plot(f0, fs, N, fig_fname);
n_idx = [0:N-1]; % 信号序列的下标向量
x = sin(2*pi*f0/fs*n_idx); % 生成正弦信号序列
y = abs(fft(x)); y_dB = 20*log10(1E-6+y); % 计算 DFT 结果线性幅度谱及对数幅度谱
h = figure;
% 绘图横轴左右边界
x_left = -1; x_right = N+1;
% 时域绘图
subplot(3,1,1);
stem(n_idx, x); grid on; hold;
plot(n_idx, x); xlim([x_left, x_right]);
xlim([x_left, x_right]);
title_str = ['f0:', num2str(f0),'Hz, ', 'fs:', num2str(fs),'Hz, ' 'N:', num2str(N)];
title(title_str, 'fontsize',14);
% 绘图线性幅度谱
subplot(3,1,2); stem(n_idx, y); grid on;
xlim([x_left, x_right]);
title_str = ['DFT Magtitude Linear Scale, '];
title_str = [title_str, ' Max:', num2str(max(y)), ', Min:', num2str(min(y))];
title(title_str, 'fontsize',14);
% 绘图对数幅度谱
subplot(3,1,3); stem(n_idx, y_dB); grid on;
xlim([x_left, x_right]);
title_str = ['DFT Magtitude dB Scale, '];
title_str = [title_str, ' Max:', num2str(max(y_dB)), ', Min:', num2str(min(y_dB))];
title(title_str, 'fontsize',14);
print(h, '-djpeg', fig_fname); % 保存绘图结果文件
end
• 实验代码说明
– sine_1_tone_dft.m : 实验入口代码
– 函数说明
• function func_sine_1_tone_dft_plot(f0, fs, N, fig_fname);
• 功能:绘制正弦信号采样序列的DFT幅度谱,然后保存曲线图
• 参数 f0:正弦信号频率
• 参数 fs :采样率
• 参数 N :序列长度
• 参数 fig_fname:保存的绘图文件名(jpg格式)
仿真图:
采样序列中包含了2个完整的信号周期的采样值,DFT幅度谱分析结果有2根峰值谱线,其余位置上均是0。
采样序列中包含了2个完整的信号周期,以及 一个不完整信号周期的采样值,DFT幅度谱分析结果有2根极大值谱线,但是其余位置上不为0。
采样序列中包含了2个完整的信号周期,以及 一个不完整信号周期的采样值,DFT幅度谱 分析结果有2根极大值谱线,但是其余位置上不为0。
总结规律
– 在采样序列包含整数个信号周期的情况下,信号采样后的DFT分析结果和连续信号的傅里叶变换频谱最相似。
–频谱泄露的最根本原因还在于信号的非周期截断,可以从时域和频域两方面来理解:
(1) 从时域上,傅里叶变换的潜在假设为待处理的有限信号为周期性无限信号的周期主体,即假设原始信号为当前有限信号的无限个周期延拓。因此,举个简单例子。我们截取50HZ 正弦信号的一个周期,其无限延拓就是最原始的50HZ正弦信号,因此一个周期的有限信号即可代表其原始的无限信号;若截取的有限信号不是50HZ信号的整数倍周期,可知该有限信号的无限延拓不可完全的复原原始的50HZ无限信号,其首尾连接处出现断续,从而引入高次谐波分量,产生频谱泄露。
(2)从频域上,假设信号周期T,频率F, 采样周期Ts,采样频率Fs, 采样点数N,则整数周期截断的物理表达为N*Ts = m*T <=> N*1/Fs=m*1/F <=> F=m*Fs/N. 在频域上,Fs对应2π,且频域分辨率为2π/N。 因此F=m*Fs/N意义为信号频率在FFT后的第m根谱线上。反之,当非周期截断时,则无法满足F=m*Fs/N,信号的频率成分分散k*2π/N的频率点上。
由于工程实际处理的信号基本为非平稳多谐波信号,因此频谱泄露不可避免。为了改善频谱泄露,可行的方向包含以下几点:
1. 增大FFT变换的点数N。 通过增大N,一方面提高频域分辨率,更大可能满足F=m*Fs/N, 另一方面,压缩sinc的瓣宽,降低泄露水平。
2. 选用合适的窗函数。根据不同的需求来选择不同特性的窗函数,主瓣宽但旁瓣衰减大的窗或是主瓣窄但旁瓣相对衰减小的窗。
• 任务3、有限长矩形窗序列的DTFT
背景知识:DTFT的重要性
• 计算机的局限性
– 只能计算有限长的数据(无限长的数据,只存在于理论分析的世界里)
– 只能计算离散化的数据(连续变量的函数,计算其函数值时,只能 在离散化的自变量的抽样点上进行)
• 离散时间序列傅里叶变换(DTFT)的重要性
– 在无穷长的尺度上累加
– 输出的结果函数是连续变量函数
– 确定的离散序列,无论有限长、无限长
• 其DTFT变换结果,具有理论唯一性
– 理论唯一性的重要在于:
• 可以使用多种工程计算方法无限逼近
• 可以用来检验工程计算方法的正确性和有效性
实验代码:
主函数:
% file: plot_dtft.m
% test with Matlab 2007
clc
clear
close all
w_min = -1*pi;
w_max = 1*pi;
w_delta = pi/1000;
n_min = 0;
n_max = 3 ;
n = [n_min:1:n_max];
w = [w_min:w_delta:w_max];
N = length(n);
x = ones(1,N);
x_dscp_str = 'x(n)';
Y = func_calc_dtft(x, n, w);
h = func_plot_dtft(x,n,w,Y, x_dscp_str);
子函数1:
% file: func_plot_dtft.m
% test with Matlab 2007
% Y[w] = DTFT(x[n]);
% plot time sequence x[n], real/imag part of Y[w], abs of Y[w]
function h = func_plot_dtft(x,n,w,Y, x_dscp_str);
h = figure;
N = length(n);
n_min = min(n);
n_max = max(n);
w_min = min(w);
w_max = max(w);
N_w = length(w);
w_delta = (w_max-w_min)/(N_w-1);
w_x_tick_delta = 1*pi/4;
w_x_tick = get_w_x_tick_vec(w_min, w_max, w_x_tick_delta);
w_x_tick_label_cell = get_w_x_tick_label_cell(w_x_tick, w_x_tick_delta);
Y_real = real(Y); Y_imag = imag(Y); Y_abs = abs(Y);
subplot(2,2,1);
title_str = [x_dscp_str, ', n \in [',int2str(n_min),',', int2str(n_max), ...
'], ', int2str(N), ' samples'];
stem(n, x, 'fill'); title(title_str, 'fontsize',14);
y_lim_max = 1.1*max(abs(x)); y_lim_min = -y_lim_max;
grid on; xlim([n_min-1,n_max+1]); ylim([y_lim_min, y_lim_max]);
subplot(2,2,2);
Left_str = get_tick_str((w_min/pi),1,'\pi');
Right_str = get_tick_str((w_max/pi),1,'\pi');
w_xLabelStr =['\omega: [', Left_str,',', Right_str, ']'];
title_str = ['\{X(e^{j\omega})\}, \Delta\omega = \pi/', num2str(pi/w_delta)];
plot(w, Y_real);title(['Re', title_str], 'fontsize',14);
grid on; xlim([w_min,w_max]);ylim([(min(Y_real)-0.5),(max(Y_real)+0.5)]);
xlabel(w_xLabelStr, 'fontsize',14);
line([w_min,w_max],[0,0], 'color','black');
set(gca,'xtick',w_x_tick);
set(gca,'xticklabel', w_x_tick_label_cell );
subplot(2,2,3);
plot(w, Y_imag);title(['Im', title_str], 'fontsize',14);
grid on; xlim([w_min,w_max]);ylim([(min(Y_imag)-0.5),(max(Y_imag)+0.5)]);
xlabel(w_xLabelStr, 'fontsize',14);
line([w_min,w_max],[0,0], 'color','black');
set(gca,'xtick',w_x_tick);
set(gca,'xticklabel', w_x_tick_label_cell );
subplot(2,2,4);
plot(w, Y_abs);title(['Mod', title_str], 'fontsize',14);
grid on; xlim([w_min,w_max]);ylim([(min(Y_abs)-0.5),(max(Y_abs)+0.5)]);
xlabel(w_xLabelStr, 'fontsize',14);
line([w_min,w_max],[0,0], 'color','black');
set(gca,'xtick',w_x_tick);
set(gca,'xticklabel', w_x_tick_label_cell );
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function tick_str = get_tick_str(num_val, denorm_val, unit_str)
num_val = round(num_val*1000);
denorm_val = round(denorm_val*1000);
gcd_n_d = gcd(num_val, denorm_val);
num_val = num_val/gcd_n_d;
denorm_val = denorm_val/gcd_n_d;
if(num_val == 0)
tick_str = ['0'];
else
if (denorm_val == 1)
denorm_str = unit_str;
else
denorm_str = [unit_str, '/', num2str(denorm_val)];
end
if(num_val == 1)
num_str = [];
elseif (num_val == -1)
num_str = ['-'];
else
num_str = num2str(num_val);
end
tick_str = [num_str, denorm_str];
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function ver_num = get_matlab_version()
ver_str_all = version; % such as 7.5.0.342 (R2007b)
ver_str = [ver_str_all(1), ver_str_all(2),ver_str_all(3)]; % such as 7.5
ver_num = str2num(ver_str);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function w_x_tick = get_w_x_tick_vec(w_min, w_max, w_x_tick_delta)
if(w_min < 0)
w_x_tick_R = [0:w_x_tick_delta: w_max];
temp = [w_x_tick_delta:w_x_tick_delta:-w_min];
w_x_tick_L = fliplr(-temp);
w_x_tick = [w_x_tick_L, w_x_tick_R];
else
w_x_tick = [w_min:w_x_tick_delta:w_max];
end
if(w_x_tick(1) > w_min)
w_x_tick = [w_min, w_x_tick];
end
if(w_x_tick(length(w_x_tick)) < w_max)
w_x_tick = [w_x_tick, w_max];
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function w_x_tick_label_cell = get_w_x_tick_label_cell(w_x_tick, w_x_tick_delta)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
N_w_x_tick = length(w_x_tick);
w_x_tick_label_cell = cell(N_w_x_tick,1);
ver_num = get_matlab_version();
if(ver_num >= 8.4)
tick_unit_str = '\pi';
else
tick_unit_str = 'pi';
end
for(idx = 1:N_w_x_tick)
num_val = w_x_tick(idx)/w_x_tick_delta ;
denorm_val = pi/w_x_tick_delta ;
tick_str = get_tick_str(num_val, denorm_val, tick_unit_str);
w_x_tick_label_cell{idx} = tick_str;
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
子函数2:
% file: .func_calc_dtft.m
% test with Matlab 2007
% Y(w) = DTFT(x[n]);
function Y = func_calc_dtft(x, n, w)
N = length(n);
N_w = length(w);
Y = zeros(N_w,1);
for idx = 1:N_w
e_jw = exp(-j*w(idx)*n);
Y(idx) = sum(e_jw .* x);
end
–rec_dtft_plot.m 调用 func_calc_dtft.m 计算序列 的 DTFT( ω )
–rec_dtft_plot.m 调用 func_plot_dtft.m 绘制 曲线, 包括:序列的时域图、 DTFT( ω ) 的实部、虚部、模值 曲线。
rec_dtft_plot.m 代码 仿真配置参数
w_min :频域变量左边界
w_delta :频域变量计算精度
n_min :时域序列左边界
n_max :时域序列右边界
func_plot_dtft.m 代码仿真配置参数
w_x_tick_delta:绘图水平栅格单位长度
仿真图:
完成上机实验后,回答以下问题
• 对于N点的矩形窗序列
– 其时域的相位变化(即序列最左边和最右边的位置)对DTFT变换的模值有影响么?
相位变化越多,模值的主瓣越窄,旁瓣越多。
– 其时域的相位变化对DTFT变换的实部、虚部有影响么?
相位变化越多,分辨率越高
– 把序列按照纵轴翻转,DTFT变换的结果发生什么变化呢?
虚部变为相反数,实部及模值不变
– DTFT变换的模值曲线有几个0点(0值栅格频率)?有几个峰值点?各自的位置和N的关系是什么?(用公式表达)
N个采样点,如果N为偶数则有N个0点,如果N为奇数则有N-1个0点。
有一个峰值点
– DTFT变换的模值曲线特征(需要推导一下公式)
• 主瓣和旁瓣、以及各次旁瓣之间,宽度关系是什么?
• 主瓣和旁瓣、以及各次旁瓣之间,高度关系是什么?
• 任务4、有限长正弦序列的DTFT
背景知识:有限长序列和矩形窗
• 有限长序列等效为: – 概念上的原始无限长序列,再乘以有限长的矩形窗之后得到
背景知识:频域卷积定理
背景知识:有限长正弦序列的DTFT变换
实验代码:
主函数
% file: plot_dtft.m
% test with Matlab 2007
clc
clear
close all
fig_fname = 'plot_dtft.png';
w_min = -1*pi;
w_max = 1*pi;
w_delta = pi/1000;
n_min = 0;
n_max = 7;
f0 = 125;
fs = 1000;
n = [n_min:1:n_max];
w = [w_min:w_delta:w_max];
N = length(n);
x = cos( 2*pi*f0/fs*n);
Y = func_calc_dtft(x, n, w);
x_dscp_str = ['x[n] = sin(2\pi\cdotf0/fs\cdotn), f0=', num2str(f0),',fs=' num2str(fs)];
h = func_plot_dtft(x,n,w,Y, x_dscp_str);
子函数1:
% file: func_plot_dtft.m
% test with Matlab 2007, 2014
% Y[w] = DTFT(x[n]);
% plot time sequence x[n], real/imag part of Y[w], abs of Y[w]
function h = func_plot_dtft(x,n,w,Y, x_dscp_str);
h = figure;
N = length(n);
n_min = min(n);
n_max = max(n);
w_min = min(w);
w_max = max(w);
N_w = length(w);
w_delta = (w_max-w_min)/(N_w-1);
w_x_tick_delta = 1*pi/4 ;
w_x_tick = get_w_x_tick_vec(w_min, w_max, w_x_tick_delta);
w_x_tick_label_cell = get_w_x_tick_label_cell(w_x_tick, w_x_tick_delta);
ver_num = get_matlab_version();
if(ver_num >= 8.4)
if(length(w_x_tick_label_cell) >= 12)
x_tick_rot_angle = 270;
else
x_tick_rot_angle = 0;
end
end
Y_real = real(Y); Y_imag = imag(Y); Y_abs = abs(Y);
subplot(2,2,1);
title_str = {x_dscp_str; ['n \in [',int2str(n_min),',', int2str(n_max), ...
'], ', int2str(N), ' samples']};
stem(n, x, 'fill'); title(title_str, 'fontsize',14);
y_lim_max = 1.1*max(abs(x)); y_lim_min = -y_lim_max;
grid on; xlim([n_min-1,n_max+1]); ylim([y_lim_min, y_lim_max]);
subplot(2,2,2);
Left_str = get_tick_str((w_min/pi),1,'\pi');
Right_str = get_tick_str((w_max/pi),1,'\pi');
w_xLabelStr =['\omega: [', Left_str,',', Right_str, ']'];
title_str = ['\{X(e^{j\omega})\}, \Delta\omega = \pi/', num2str(pi/w_delta)];
plot(w, Y_real);title(['Re', title_str], 'fontsize',14);
grid on; xlim([w_min,w_max]);ylim([(min(Y_real)-0.5),(max(Y_real)+0.5)]);
xlabel(w_xLabelStr, 'fontsize',14);
line([w_min,w_max],[0,0], 'color','black');
set(gca,'xtick',w_x_tick);
set(gca,'xticklabel', w_x_tick_label_cell );
if(ver_num >= 8.4) set(gca,'XTickLabelRotation',x_tick_rot_angle); end
subplot(2,2,3);
plot(w, Y_imag);title(['Im', title_str], 'fontsize',14);
grid on; xlim([w_min,w_max]);ylim([(min(Y_imag)-0.5),(max(Y_imag)+0.5)]);
xlabel(w_xLabelStr, 'fontsize',14);
line([w_min,w_max],[0,0], 'color','black');
set(gca,'xtick',w_x_tick);
set(gca,'xticklabel', w_x_tick_label_cell );
if(ver_num >= 8.4) set(gca,'XTickLabelRotation',x_tick_rot_angle); end
subplot(2,2,4);
plot(w, Y_abs);title(['Mod', title_str], 'fontsize',14);
grid on; xlim([w_min,w_max]);ylim([(min(Y_abs)-0.5),(max(Y_abs)+0.5)]);
xlabel(w_xLabelStr, 'fontsize',14);
line([w_min,w_max],[0,0], 'color','black');
set(gca,'xtick',w_x_tick);
set(gca,'xticklabel', w_x_tick_label_cell );
if(ver_num >= 8.4) set(gca,'XTickLabelRotation',x_tick_rot_angle); end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function tick_str = get_tick_str(num_val, denorm_val, unit_str)
num_val = round(num_val*1000);
denorm_val = round(denorm_val*1000);
gcd_n_d = gcd(num_val, denorm_val);
num_val = num_val/gcd_n_d;
denorm_val = denorm_val/gcd_n_d;
if(num_val == 0)
tick_str = ['0'];
else
if (denorm_val == 1)
denorm_str = unit_str;
else
denorm_str = [unit_str, '/', num2str(denorm_val)];
end
if(num_val == 1)
num_str = [];
elseif (num_val == -1)
num_str = ['-'];
else
num_str = num2str(num_val);
end
if (num_val > 0)
num_str = ['+',num_str];
end
tick_str = [num_str, denorm_str];
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function ver_num = get_matlab_version()
ver_str_all = version; % such as 7.5.0.342 (R2007b)
ver_str = [ver_str_all(1), ver_str_all(2),ver_str_all(3)]; % such as 7.5
ver_num = str2num(ver_str);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function w_x_tick = get_w_x_tick_vec(w_min, w_max, w_x_tick_delta)
if(w_min < 0)
w_x_tick_R = [0:w_x_tick_delta: w_max];
temp = [w_x_tick_delta:w_x_tick_delta:-w_min];
w_x_tick_L = fliplr(-temp);
w_x_tick = [w_x_tick_L, w_x_tick_R];
else
w_x_tick = [w_min:w_x_tick_delta:w_max];
end
if(w_x_tick(1) > w_min)
w_x_tick = [w_min, w_x_tick];
end
if(w_x_tick(length(w_x_tick)) < w_max)
w_x_tick = [w_x_tick, w_max];
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function w_x_tick_label_cell = get_w_x_tick_label_cell(w_x_tick, w_x_tick_delta)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
N_w_x_tick = length(w_x_tick);
w_x_tick_label_cell = cell(N_w_x_tick,1);
ver_num = get_matlab_version();
if(ver_num >= 8.4)
tick_unit_str = '\pi';
else
tick_unit_str = 'pi';
end
for(idx = 1:N_w_x_tick)
num_val = w_x_tick(idx)/w_x_tick_delta ;
denorm_val = pi/w_x_tick_delta ;
tick_str = get_tick_str(num_val, denorm_val, tick_unit_str);
w_x_tick_label_cell{idx} = tick_str;
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
子函数2:
% file: .func_calc_dtft.m
% test with Matlab 2007
% Y(w) = DTFT(x[n]);
function Y = func_calc_dtft(x, n, w)
N = length(n);
N_w = length(w);
Y = zeros(N_w,1);
for idx = 1:N_w
e_jw = exp(-j*w(idx)*n);
Y(idx) = sum(e_jw .* x);
end
sin_dtft_plot.m 代码 仿真配置参数
w_min :频域变量左边界
w_max :频域变量右边界
w_delta:频域变量计算精度
n_min :时域序列左边界
n_max :时域序列右边界
f0 :正弦信号频率
fs :正弦信号采样率
func_plot_dtft.m 代码 仿真配置参数
w_x_tick_delta : 绘图水平栅格单位长
实验结果:
修改实验参数,可以得到以下结果:
• 回答以下问题
• 对于实数序列信号,其DTFT变换的对称性如何? – 请按照实部、虚部、模值分别回答
实部、模值是偶对称,虚部是奇对称。
• 正弦序列的DTFT曲线峰值,一定出现在信号归一化数字角频率的位置么?为什么会这样?
不一定,
• 从实验中可以看到,对于单音正弦信号,频率过低时在DTFT 曲线上将无法分辨出正负频率的峰值。请尝试分析一下原因
• 假定正弦信号序列不变,截取不同的有限长相位区间构成不 同的有限长序列,然后进行DTFT分析 – 请问序列相位对DTFT变换有什么影响? – 请尝试分别从实部、虚部、模值的角度分析
模值不变,只是影响实部、虚部的各位置的数值大小。
• 任务5、 DTFT 和 DFT 关系探寻
DFT等于DTFT的采样
DTFT 定义式
DFT 定义式
若 x[n] 是一个在[0,N − 1]区间内有非零值的有限长序列, 且,令:ω(k) = 2π·k/N, 0 ≤ k ≤ N − 1,则在ω(k) 的位置上 DFT 和 DTFT 等价。
以上结论说明,DFT是在0 ~ 2π 区间上对 DTFT 的等间隔 采样,采样间隔大小为: 2π/N
实验代码:
• sin_dtft_dft_plot.m :主程序
• func_plot_dtft_dft.m:绘图DTFT和DFT的函数
• 注意:如果要同时显示DFT和DTFT结果需要如下设定 – w_min = 0; w_max = 2*pi;
主函数:
% file: sin_dtft_dft_plot.m
% test with Matlab 2007,2014
clc
clear
close all
fig_fname = 'plot_dtft.png';
% to plot DFT with DTFT, must set w range as [0,2pi]
w_min = 0;
w_max = 2*pi;
w_delta = pi/1000;
n_min = 0;
n_max = 16-1;
f0 = 10;
fs = 100;
n = [n_min:1:n_max];
w = [w_min:w_delta:w_max];
N = length(n);
x = sin(2*pi*f0/fs*n);
Y = func_calc_dtft(x, n, w);
Y_DFT = fft(x);
x_dscp_str = ['x[n] = sin(2\pi\cdotf0/fs\cdotn), f0=', num2str(f0),',fs=' num2str(fs)];
h = func_plot_dtft_dft(x,n,w,Y,Y_DFT, fs, x_dscp_str);
子函数1:
% file: func_calc_dtft.m
% test with Matlab 2007
% Y(w) = DTFT(x[n]);
function Y = func_calc_dtft(x, n, w)
N = length(n);
N_w = length(w);
Y = zeros(N_w,1);
for idx = 1:N_w
e_jw = exp(-j*w(idx)*n);
Y(idx) = sum(e_jw .* x);
end
子函数2:
% file: func_plot_dtft_dft.m
% test with Matlab 2007, 2014
% Y[w] = DTFT(x[n]);
% plot time sequence x[n], real/imag part of Y[w], abs of Y[w]
function h = func_plot_dtft_dft(x,n,w,Y, Y_DFT, fs, x_dscp_str);
h = figure;
N = length(n);
n_min = min(n);
n_max = max(n);
w_min = min(w);
w_max = max(w);
if(w_min ~= 0 ) disp('WARNING, to plot DFT with DTFT w_min must be 0'); end
if(w_max ~= 2*pi) disp('WARNING, to plot DFT with DTFT w_max must be 2*pi'); end
N_w = length(w);
w_delta = (w_max-w_min)/(N_w-1);
w_x_tick_delta = 2*pi/16 ;
w_x_tick = get_w_x_tick_vec(w_min, w_max, w_x_tick_delta);
w_x_tick_label_cell = get_w_x_tick_label_cell(w_x_tick, w_x_tick_delta);
ver_num = get_matlab_version();
if(ver_num >= 8.4)
if(length(w_x_tick_label_cell) >= 12)
x_tick_rot_angle = 270;
else
x_tick_rot_angle = 0;
end
end
Y_real = real(Y); Y_imag = imag(Y); Y_abs = abs(Y);
N_DFT = length(Y_DFT);
w_DFT = n*2*pi/N;
Y_DFT_real = real(Y_DFT); Y_DFT_imag = imag(Y_DFT); Y_DFT_abs = abs(Y_DFT);
subplot(2,2,1);
title_str = {x_dscp_str; ['n \in [',int2str(n_min),',', int2str(n_max), ...
'], ', int2str(N), ' samples']};
stem(n, x, 'fill'); title(title_str, 'fontsize',14);
y_lim_max = 1.1*max(abs(x)); y_lim_min = -y_lim_max;
grid on; xlim([n_min-1,n_max+1]); ylim([y_lim_min, y_lim_max]);
subplot(2,2,2);
Left_str = get_tick_str((w_min/pi),1,'\pi');
Right_str = get_tick_str((w_max/pi),1,'\pi');
w_xLabelStr =['\omega: [', Left_str,',', Right_str, ']'];
title_str = ['\{X(e^{j\omega})\}, \Delta\omega = \pi/', num2str(pi/w_delta)];
plot(w, Y_real);title(['Re', title_str], 'fontsize',14);
grid on; xlim([w_min,w_max]);ylim([(min(Y_real)-0.5),(max(Y_real)+0.5)]);
xlabel(w_xLabelStr, 'fontsize',14);
line([w_min,w_max],[0,0], 'color','black');
set(gca,'xtick',w_x_tick);
set(gca,'xticklabel', w_x_tick_label_cell );
if(ver_num >= 8.4) set(gca,'XTickLabelRotation',x_tick_rot_angle); end
hold; stem(w_DFT, Y_DFT_real, 'filled');
subplot(2,2,3);
plot(w, Y_imag);title(['Im', title_str], 'fontsize',14);
grid on; xlim([w_min,w_max]);ylim([(min(Y_imag)-0.5),(max(Y_imag)+0.5)]);
xlabel(w_xLabelStr, 'fontsize',14);
line([w_min,w_max],[0,0], 'color','black');
set(gca,'xtick',w_x_tick);
set(gca,'xticklabel', w_x_tick_label_cell );
if(ver_num >= 8.4) set(gca,'XTickLabelRotation',x_tick_rot_angle); end
hold; stem(w_DFT, Y_DFT_imag, 'filled');
subplot(2,2,4);
plot(w, Y_abs);title(['Mod', title_str], 'fontsize',14);
grid on; xlim([w_min,w_max]);ylim([(min(Y_abs)-0.5),(max(Y_abs)+0.5)]);
xlabel(w_xLabelStr, 'fontsize',14);
line([w_min,w_max],[0,0], 'color','black');
set(gca,'xtick',w_x_tick);
set(gca,'xticklabel', w_x_tick_label_cell );
if(ver_num >= 8.4) set(gca,'XTickLabelRotation',x_tick_rot_angle); end
hold; stem(w_DFT, Y_DFT_abs, 'filled');
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function tick_str = get_tick_str(num_val, denorm_val, unit_str)
num_val = round(num_val*1000);
denorm_val = round(denorm_val*1000);
gcd_n_d = gcd(num_val, denorm_val);
num_val = num_val/gcd_n_d;
denorm_val = denorm_val/gcd_n_d;
if(num_val == 0)
tick_str = ['0'];
else
if (denorm_val == 1)
denorm_str = unit_str;
else
denorm_str = [unit_str, '/', num2str(denorm_val)];
end
if(num_val == 1)
num_str = [];
elseif (num_val == -1)
num_str = ['-'];
else
num_str = num2str(num_val);
end
if (num_val > 0)
num_str = ['+',num_str];
end
tick_str = [num_str, denorm_str];
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function ver_num = get_matlab_version()
ver_str_all = version; % such as 7.5.0.342 (R2007b)
ver_str = [ver_str_all(1), ver_str_all(2),ver_str_all(3)]; % such as 7.5
ver_num = str2num(ver_str);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function w_x_tick = get_w_x_tick_vec(w_min, w_max, w_x_tick_delta)
if(w_min < 0)
w_x_tick_R = [0:w_x_tick_delta: w_max];
temp = [w_x_tick_delta:w_x_tick_delta:-w_min];
w_x_tick_L = fliplr(-temp);
w_x_tick = [w_x_tick_L, w_x_tick_R];
else
w_x_tick = [w_min:w_x_tick_delta:w_max];
end
if(w_x_tick(1) > w_min)
w_x_tick = [w_min, w_x_tick];
end
if(w_x_tick(length(w_x_tick)) < w_max)
w_x_tick = [w_x_tick, w_max];
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function w_x_tick_label_cell = get_w_x_tick_label_cell(w_x_tick, w_x_tick_delta)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
N_w_x_tick = length(w_x_tick);
w_x_tick_label_cell = cell(N_w_x_tick,1);
ver_num = get_matlab_version();
if(ver_num >= 8.4)
tick_unit_str = '\pi';
else
tick_unit_str = 'pi';
end
for(idx = 1:N_w_x_tick)
num_val = w_x_tick(idx)/w_x_tick_delta ;
denorm_val = pi/w_x_tick_delta ;
tick_str = get_tick_str(num_val, denorm_val, tick_unit_str);
w_x_tick_label_cell{idx} = tick_str;
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
实验结果:
修改实验代码,可得以下结果:
•回答以下问题
• 假设有一个单音频率为f0的正弦信号采样序列,采样条件满足奈奎斯特 定律。使用fs的采样率,记录了时间长度T,N个样点
• 如果用序列的DFT结果来估计正弦信号的频率,在什么情况下频率的估 计值会比较准确?
• 保持序列的时间长度T 不变,提高采样率,对使用DFT估计正弦信号的 频率有帮助么?
• 保持序列的记录个数N 不变,提高采样率,对使用DFT估计正弦信号的 频率有帮助么?
• 保持采样率fs不变,提高记录个数N,对使用DFT估计正弦信号的频率有 帮助么?
• 对序列补零对使用DFT分析信号频率有什么帮助?补零能够彻底解决有 限长序列效应带来的问题么?
• 对序列补零时,补零的位置(在序列前面或后面)对使用DFT分析信号 频率有什么影响?
• 最终任务:双音信号频率分析