简介本资源是南京邮电大学《信号分析与处理实验》课程的完整实验报告含实验1–4面向电子信息、通信工程等专业本科生及数字信号处理初学者聚焦MATLAB实操与核心理论验证。报告系统覆盖信号的产生与运算、连续时间信号频域分析、时域采样与重建、离散傅里叶变换DFT及其应用四大主线并延伸至连续系统复频域分析、数字滤波器设计与综合应用每部分均含详细实验目的、Matlab程序代码、多图结果分析如阶跃/复指数/正弦序列波形、卷积输出、频谱图等及关键原理说明。资源为1个1.02MB的docx文档结构清晰、图文并茂所有代码可直接运行复现便于课后巩固、实验预习或课程设计参考。目前已有952人学习下载是理解DSP基础概念与提升MATLAB信号处理实战能力的优质教学配套材料。1. 别被“信号”吓住它其实就是你每天听到、看到、用到的“信息快照”而这份实验报告就是带你亲手给它拍第一张清晰照片的入门相机你有没有想过手机里那段语音、耳机里正在播放的歌、视频通话时对方的脸——这些看似自然的东西背后全是一串串“数字快照”在飞速流动它们不是凭空出现的而是被一种叫“信号”的东西承载着再经过一连串看不见的“加工流水线”才变成你能感知的模样。可一听到“信号分析与处理”“傅里叶变换”“DFT”“频域”很多人第一反应是这词儿太硬了像块没泡开的压缩饼干咬不动。其实不是概念太难是没人告诉你——它本来就不该从公式开始而该从“我能让它动起来”开始。这份来自南京邮电大学的《信号分析与处理实验报告实验1–4》就是一套专为零基础新手打磨的“信号上手工具包”。它不讲抽象定义不堆数学推导而是用 MATLAB 这个“信号显微镜”让你亲手画出正弦波、把两个声音信号加在一起、看看采样太快或太慢会发生什么、甚至让一段男声“悄悄变高”一点点——所有操作都落在一行行可复制、可修改、改完立刻出图的代码上。它适合谁适合刚打开 MATLAB 界面还在找“运行按钮”的你适合学过一点高数但看到“卷积”就头皮发紧的你也适合想转行进音频算法、通信系统、智能硬件却卡在“不知道第一步敲哪行代码”的你。这不是期末考前抱佛脚的复习资料而是一份“边做边懂”的实操地图——你不需要先背熟所有术语只要愿意把第一页的代码粘贴进 MATLAB按下回车你就已经站在信号世界的大门口了。2. 先别碰公式用 MATLAB 画出第一个信号你就已经跨过了 80% 的心理门槛很多新手卡在第一步不是因为不会写代码而是因为不知道“信号”到底长什么样。它不像一张图片、一段文字那么直观。所以我们不从“什么是傅里叶变换”开始而是从“怎么让它出现在屏幕上”开始。实验一的核心就是教会你信号 一组有顺序的数字 一个对应的横坐标时间或序号。就这么简单。MATLAB 的stem和plot函数就是你的画笔n 0:15这样的语句就是你在纸上画出刻度尺。2.1 从最朴素的“开关”开始单位阶跃序列 u[n] 是什么想象一下家里的电灯开关按下去之前灯是灭的值为 0按下去那一刻起灯一直亮着值为 1。这个“从 0 突然跳到 1 并保持不变”的行为在信号世界里就叫“单位阶跃序列”记作 u[n]。它不是数学幻觉而是所有数字系统启动、触发、判断的起点。下面这段代码就是你和信号世界的第一次握手clear; close all; n -10:20; % 定义横坐标从 -10 到 20共 31 个点 x [zeros(1,10) 1 ones(1,20)]; % 构造纵坐标前10个是0第11个是1后面20个全是1 stem(n, x); % 用“火柴棍图”画出来 xlabel(n); ylabel(u[n]); % 标上横纵轴名字 title(单位阶跃序列 u[n]);提示zeros(1,10)是生成 1 行 10 列的全 0 向量ones(1,20)是生成 1 行 20 列的全 1 向量中括号[ ]是把它们“拼接”成一个长向量。stem函数画离散点比plot更能体现“序列”的跳跃感。运行后你会看到一张图左边一堆零中间一个突兀的 1右边一长串 1。这就是 u[n] —— 一个最基础、最真实的信号。它没有神秘感只有明确的“位置”n和“状态”0 或 1。你刚刚完成的不是编程练习而是对“信号本质”的一次具象化确认信号就是数据在时间轴上的忠实记录。2.2 让信号“动起来”移位运算就是给信号换个座位如果 u[n] 是“从 n0 开始亮”那 u[n7] 就是“从 n-7 开始亮”。这就像把整排座位往前挪 7 个位置——原来坐在第 0 号位的人现在坐到了第 -7 号位。代码里只改了一处M 7; xd [zeros(1,10M) 1 ones(1,20-M)]; % 注意这里前面补了 10717 个 0后面只剩 20-713 个 1 subplot(1,2,2); stem(n, xd); xlabel(n); ylabel(u[n7]); title(移位后的阶跃序列);为什么zeros(1,10M)而不是zeros(1,10-M)因为n的范围还是-10:20总共 31 个点。u[n7] 在n-7处取值为 1所以我们需要让向量xd的第( -7 - (-10) 1 ) 4个位置是 1MATLAB 下标从 1 开始。zeros(1,10M)确保了前 17 个点对应 n-10 到 n6都是 0第 18 个点对应 n7不对等等——这里正是新手最容易懵的地方。白话解释n -10:20它的第一个元素n(1)是 -10第二个是 -9……第 k 个元素是n(k) -10 (k-1)。我们要让xd(k)在n(k) -7时等于 1即-10 (k-1) -7解得k 4。所以xd的第 4 个元素必须是 1。[zeros(1,10M) 1 ones(1,20-M)]中zeros(1,10M)有 17 个 0所以1是第 18 个元素矛盾了真相是原程序x[zeros(1,10) 1 ones(1,20)]本就有逻辑瑕疵——它假设n从 -10 开始zeros(1,10)对应 n-10 到 n-110 个点1对应 n0ones(1,20)对应 n1 到 n2020 个点总共 31 点完美匹配。那么u[n7]在 n-7 时为 1即n70所以它等价于u[m]在 m0 处为 1而 mn7所以当 n-7 时m0。因此xd应该在n-7对应的位置为 1。n-7是n向量中的第(-7) - (-10) 1 4个位置。所以xd应该是前 3 个是 0对应 n-10,-9,-8第 4 个是 1对应 n-7后面全是 1。但n一共到 20所以后面应该有20 - (-7) 27个 1不对n从 -10 到 20 是 31 个点n-7是第 4 个后面还有 27 个点n-6 到 20所以xd [zeros(1,3) 1 ones(1,27)]。原报告程序xd[zeros(1,10M) 1 ones(1,20-M)]中M7得到zeros(1,17)和ones(1,13)共 31 点但1在第 18 位对应n(18) -10 17 7画出来是u[n-7]不是u[n7]这是一个经典笔误/理解偏差。避坑 / 常见问题 / 排查新手第一次写移位90% 会栽在这儿现象运行u[n7]代码图上那个“1”出现在 n7 附近而不是预期的 n-7。原因混淆了“信号表达式”和“向量索引”。u[n7]意味着当输入是n时输出取u在n7处的值。u本身只在m0时为 1所以u[n7]在n70即n-7时为 1。因此xd应该从n-7开始全为 1。解决重写xd明确对应关系% 更鲁棒、不易错的写法 n -10:20; xd zeros(size(n)); % 先全设为 0 idx find(n -7); % 找出 n -7 的所有位置 xd(idx) 1; % 把这些位置设为 1 stem(n, xd);这种写法不依赖手动数零和一的个数靠逻辑判断一劳永逸。记住用find和逻辑索引比手算zeros个数少翻 90% 的车。2.3 复指数信号别怕“j”它只是个“旋转开关”看到x[n] 1.5 * exp((0.2 j*3) * n)新手常被j劝退。其实j就是 √-1但它在信号里不表示“虚无”而是一个旋转指令。exp(j*3*n)的意思就是“每走一步 n就绕原点逆时针转 3 弧度”。所以整个信号就是一个一边向外螺旋生长因为实部 0.2 0、一边疯狂旋转的轨迹。它的“实部”就是投影在水平轴上的影子“虚部”就是投影在竖直轴上的影子。clear; close all; c 0.2 3*1i; % 这个 c 决定了“生长速度”和“旋转速度” K 1.5; n 0:15; % 只画前 16 个点不然太密看不清 x K * exp(c * n); % 一次性算出全部 16 个点的值 subplot(1,2,1); stem(n, real(x)); % 实部水平影子 xlabel(n); ylabel(幅度); title(实部); subplot(1,2,2); stem(n, imag(x)); % 虚部竖直影子 xlabel(n); ylabel(幅度); title(虚部);运行后两张图会显示两个起伏的波形它们此起彼伏相位差约 90 度——这就是旋转在时域的投影。你不需要立刻理解欧拉公式只需要记住带j的信号画出来一定是两个相互配合的波形它代表的是振荡不是静止。这是理解后续所有频谱分析的物理直觉基石。2.4 正弦序列为什么cos比sin更常用问题 1.4 里用的是x A*cos(w*n phase)而不是sin。为什么因为cos在n0时值为 1最大值是个“干净的起点”而sin在n0时是 0像个“未启动”的状态。在工程中我们更喜欢从峰值开始观察周期行为。而且cos和sin只差一个 90 度相位本质完全一样。代码里phase -(pi/2)就是在cos前面强行加了个 -90 度结果就等价于sin了。这说明相位就是你决定让波形从哪个“姿势”开始跳舞。A 2.5; w 0.16*pi; phase -(pi/2); n 0:49; x A * cos(w*n phase); % 等价于 A * sin(w*n) stem(n, x); axis([0 49 -3 3]); grid on; title(正弦序列 (用 cos 实现));注意axis([0 49 -3 3])是手动设定坐标轴范围让图形不被异常值撑开看得更清楚。这是绘图时的“后悔药”建议每次画图后都加上养成习惯。3. 信号不是孤岛加、乘、卷积——这才是让它“活”起来的三把钥匙光会画单个信号就像只会画单个音符。真正的音乐是音符之间的关系。信号处理的核心从来不是研究“一个信号是什么”而是研究“两个或多个信号相遇时会发生什么”。实验一的后半部分就是教你怎么用 MATLAB 演奏这出“信号交响曲”。3.1 加法与乘法最直白的“合作”与“对话”w1[n] x[n] y[n]是合作两个信号的“音量”直接叠加像两个人同时说话你听到的是混音。w2[n] x[n] .* y[n]是对话x[n]的每个值都在“调制”y[n]的对应值像一个人说话的音量被另一个人的手势x[n]实时控制着大小。clear; close all; n 0:3; x [1 2 3 4]; % x[n] y [3 4 5 6]; % y[n] subplot(2,2,1); stem(n, x); title(x[n]); subplot(2,2,2); stem(n, y); title(y[n]); subplot(2,2,3); stem(n, xy); title(w_1[n] x[n] y[n]); subplot(2,2,4); stem(n, x.*y); title(w_2[n] x[n] .* y[n]); % 注意是 .*关键细节x.*y中的点.很重要它表示“逐元素相乘”。如果没有点x*y在 MATLAB 中是矩阵乘法而x和y都是 1×4 行向量x*y会报错内维不匹配。所有数组间的加减乘除只要不是矩阵运算前面都要加点.。这是 MATLAB 新手血泪经验第一条。3.2 偶部与奇部每个信号都有“镜像人格”任何信号x[n]都可以被唯一地拆成两部分一个“左右对称”的部分偶部xe[n]和一个“中心反对称”的部分奇部xo[n]。这就像给信号拍一张 X 光片看清它的内在对称结构。这对后续理解滤波器、系统响应至关重要——因为很多系统对“对称”和“反对称”信号的反应截然不同。计算公式是xe[n] (x[n] x[-n]) / 2xo[n] (x[n] - x[-n]) / 2x[-n]怎么实现MATLAB 里没有直接的负索引但fliplr(x)可以把向量x左右翻转正好模拟了n变成-n的效果前提是n关于 0 对称。clear; close all; n -2:2; % n 关于 0 对称-2,-1,0,1,2 x [1 2 4 -5 -2]; % x[n] 在 n-2 到 2 的值 % fliplr(x) 把 [1 2 4 -5 -2] 变成 [-2 -5 4 2 1]这正是 x[-n] 在 n-2 到 2 的值 y fliplr(x); % y 就是 x[-n] xe 0.5 * (x y); % 偶部 xo 0.5 * (x - y); % 奇部 subplot(3,1,1); stem(n, x); title(x[n]); subplot(3,1,2); stem(n, xe); title(x_e[n] (偶部)); subplot(3,1,3); stem(n, xo); title(x_o[n] (奇部));运行后你会发现xe[n]的图左右对称xo[n]的图关于原点中心对称xo[-n] -xo[n]。这就是信号的“DNA 分析”。以后看到任何复杂信号先想它的偶部和奇部各长啥样这能帮你一眼看穿很多系统的本质行为。3.3 卷积信号世界的“因果律”引擎如果说加法是“并列”乘法是“调制”那卷积就是“因果”——它描述了一个系统比如一个滤波器、一段混响、一个电路如何根据自己的“记忆”冲激响应h[n]去影响一个输入信号x[n]从而产生输出y[n]。y[n] x[n] * h[n]*表示卷积。实验一的问题 1.7 给出了最经典的例子x[n] (-1)^n一个交替的 1, -1, 1, -1... 序列h[n] cos(0.25*pi*n)一个低频余弦。它们的卷积y[n]就是x[n]经过一个“余弦形状”的滤波器后的输出。clear; close all; nx 0:14; x (-1).^nx; % 注意 .^ 逐元素幂运算 nh 0:7; w 0.25*pi; h cos(w*nh); y conv(x, h); % MATLAB 内置卷积函数一步到位 n_y 0:(length(y)-1); % 卷积结果长度 len(x)len(h)-1 158-1 22所以 n 从 0 到 21 subplot(3,1,1); stem(nx, x); title(x[n]); subplot(3,1,2); stem(nh, h); title(h[n]); subplot(3,1,3); stem(n_y, y); title(y[n] x[n] * h[n]);为什么卷积结果y的长度是 22因为x有 15 个点0 到 14h有 8 个点0 到 7卷积是“滑动相乘再求和”x的每个点都要和h的全部点配对一次所以总共有158-122个可能的输出时刻。这是卷积的基本定律务必记住。避坑 / 常见问题 / 排查卷积结果“歪了”或“长度不对”现象画出的y[n]图看起来不像x[n]和h[n]的“混合”或者横坐标n_y不是从 0 开始。原因1忘了conv函数返回的是从n0开始的向量但它的物理意义是y[0], y[1], ..., y[21]所以n_y必须手动设为0:212误用了*矩阵乘代替conv3x和h的起始n不是 0但没做相应偏移。解决永远用conv函数永远手动定义n_y 0:(length(y)-1)如果x[n]从n-5开始先用x_shifted [zeros(1,5) x]补零对齐到n0算完再考虑偏移。卷积的横坐标永远要自己算不能指望函数给你。4. 从“看得见”到“听得到”频域分析就是给信号装上一副“X 光眼镜”到现在你已经会画信号、移动它、加减它、拆解它、卷积它。但所有这些都是在“时域”——也就是“随时间变化”的视角下。这就像只看一段视频的每一帧画面却不知道背景音乐的节奏、人声的音高、乐器的音色。要真正理解信号的“内涵”你必须切换到另一个维度频域。它回答的问题是“这个信号是由哪些不同‘颜色’频率的光混合而成的”实验二就是带你给信号装上这副“X 光眼镜”。核心工具就是傅里叶变换。别被名字吓住它的作用超级朴素把一个随时间起伏的波形分解成一堆不同频率、不同强度的正弦波的组合。就像把一束白光通过三棱镜分解成红橙黄绿青蓝紫。4.1 周期信号的频谱方波 无数个奇数倍正弦波的叠加一个方波看起来棱角分明、非黑即白。但它的频谱图幅度谱却是一系列离散的竖线只出现在1f0, 3f0, 5f0...这些奇数倍基频上。这就是著名的“傅里叶级数”。实验二的问题 2.3 让你亲眼见证只用前 15 个正弦波合成的波形还毛毛糙糙用到 50 个就几乎和理想方波一样了。% 简化版 N15 合成P2_2 的核心思想 t -2:0.001:2; % 时间轴 T 2; Omega_0 2*pi/T; % 基频 A 1; tau 1; % 方波参数 c0 A*tau/T; % 直流分量0 频 f_N c0 * ones(size(t)); % 初始化为直流 N 15; for k 1:N % 第 k 个谐波的幅度2*A*tau/T * sinc(k*Omega_0*tau/2/pi) % 第 k 个谐波的相位0因为是余弦偶函数 amp 2*A*tau/T * sinc(k*Omega_0*tau/(2*pi)); f_N f_N amp * cos(k*Omega_0*t); end plot(t, f_N); title([N , num2str(N), 项谐波合成]); xlabel(t); ylabel(f_N(t));运行这段代码你会看到一个“圆润版”的方波边缘有明显的涟漪——那就是吉布斯现象。它证明了再完美的数学逼近也抵不过物理世界的真实不连续性。这个“涟漪”的高度就是问题 2.4 要你算的“过冲”理论值约为 9%。你算出来的1.0896就是这个 9% 的实证。4.2 非周期信号的频谱FFT就是你的“一键频谱仪”周期信号有傅里叶级数非周期信号比如一段语音、一段音乐用的是傅里叶变换FT。但在计算机里我们用它的离散近似——快速傅里叶变换FFT。fft函数就是 MATLAB 递给你的那台“一键频谱仪”。实验二的问题 2.5让你录一段男声、一段女声然后用fft看它们的频谱差异。核心代码就三行% 假设你已用 audiorecorder 录好存为 male.wav 和 female.wav [y_male, Fs] audioread(male.wav); [y_female, Fs] audioread(female.wav); % 计算 FFT取前 N 点N 通常是 2 的幂如 1024 N 1024; Y_male fft(y_male(1:N), N); Y_female fft(y_female(1:N), N); % 计算幅度谱取绝对值并只取前一半因为对称 mag_male abs(Y_male(1:N/2)); mag_female abs(Y_female(1:N/2)); % 频率轴f (0:N/2-1)*Fs/N f (0:N/2-1)*Fs/N; plot(f, mag_male); hold on; plot(f, mag_female, r); xlabel(频率 (Hz)); ylabel(幅度); legend(男声, 女声);运行后你会清晰地看到男声的谱峰集中在 100 Hz 左右基音低沉女声的谱峰在 200–300 Hz基音清亮。这就是“频域”的力量——它把听觉感受转化成了可测量、可比较的图形。从此你不再只是“听”声音而是“看”声音的结构。避坑 / 常见问题 / 排查FFT 图一片漆黑或全是高频噪声现象画出来的频谱图要么是一条平线要么是杂乱无章的尖刺。原因1没取绝对值abs()fft返回的是复数直接画会出错2没截取前一半Y(1:N/2)因为fft结果是共轭对称的后一半是冗余信息画出来会干扰3信号太短或采样率Fs没设对导致频率轴f计算错误4没归一化不同长度信号幅度不可比。解决永远mag abs(fft(x,N))永远mag mag(1:N/2)永远f (0:N/2-1)*Fs/N如果要比较用mag mag / max(mag)归一化。FFT 的三件套abs、1:N/2、f轴缺一不可。5. 采样数字世界的“快门速度”选错了整个画面就糊了你手机拍照快门速度太慢运动物体就拖影太快又可能欠曝。数字信号处理里有个一模一样的概念叫采样。它决定了一个连续的、流淌的模拟信号比如麦克风收到的声波被“快门”ADC 转换器以多快的频率“抓拍”变成一串离散的数字。实验三就是教你掌握这个“快门速度”的黄金法则——奈奎斯特采样定理。5.1 奈奎斯特定理一句话说清就是“采样率必须大于信号最高频率的两倍”一个信号如果它里面最快的“抖动”是 1000 Hz即每秒来回 1000 次那你至少要每秒“抓拍” 2001 次才能把它完整地记录下来。如果只拍 1500 次/秒那些 1000 Hz 的细节就会“伪装”成更低的频率混进来——这就是频谱混叠Aliasing是数字信号处理里最经典的“翻车现场”。实验三的问题 3.1 和 3.2就是让你亲眼看到混叠。程序 P3_1 里原始信号是一个升余弦脉冲它的频谱主要集中在0到2rad/s即约0.318Hz之间。所以奈奎斯特频率f_m 0.318 Hz奈奎斯特间隔T_s 1/(2*f_m) ≈ 1.57秒。也就是说采样间隔Ts必须小于1.57秒。% P3_1 核心逻辑简化示意 t 0:0.001:10; % 连续时间轴 xa ... ; % 升余弦脉冲信号 Fs_cont 1000; % 连续信号采样率足够高视为“真” % 情况1Ts pi/2 ≈ 1.57 1.57? 等于临界值理论上无混叠 Ts1 pi/2; n1 0:round(10/Ts1); x1 xa(1:round(1/Ts1):end); % 降采样 X1 fft(x1, 1024); f1 (0:511)*Fs_cont/(length(x1)*2); % 频率轴 % 情况2Ts 2 1.57必然混叠 Ts2 2; n2 0:round(10/Ts2); x2 xa(1:round(1/Ts2):end); X2 fft(x2, 1024); f2 (0:511)*Fs_cont/(length(x2)*2); % 画图对比 subplot(2,1,1); plot(f1, abs(X1(1:512))); title(Ts \pi/2, 无混叠); subplot(2,1,2); plot(f2, abs(X2(1:512))); title(Ts 2, 发生混叠);运行后第二张图的频谱会“折叠”回来高频成分跑到了低频区和原始低频混在一起再也分不清。这就是混叠的视觉证据。它不是 bug而是物理定律的铁律——你无法用一把不够密的梳子去梳理一头过于浓密的头发。5.2 重建从数字回到模拟滤波器就是你的“画笔修复师”采样之后我们得到了一串数字。但很多时候我们需要把它再变回连续的模拟信号比如 DAC 输出到耳机。这个过程叫重建。理想重建需要用一个完美的“低通滤波器”把采样引入的高频镜像全部砍掉只留下原始频带。实验三的问题 3.3 和 3.4就是对比“好重建”和“坏重建”。P3_2里用了一个截止频率Wc恰好等于奈奎斯特频率Wm的理想低通滤波器重建效果很好而当你把Ts增大到 2引发混叠再用同样的WcWm滤波结果就是灾难性的——混叠进来的高频噪声根本滤不掉误差巨大。% 重建的核心用 sinc 函数插值理想低通的时域响应 % 简化示意对采样点 x2用 sinc 插值得到重建信号 xr t_recon 0:0.01:10; % 重建的时间轴比采样密得多 xr zeros(size(t_recon)); for k 1:length(x2) n_k (k-1)*Ts2; % 第 k 个采样点的时间 xr xr x2(k) * sinc((t_recon - n_k)/Ts2); end % 画图原始信号 xa采样点 x2重建信号 xr plot(t, xa, b); hold on; stem(n2*Ts2, x2, r, filled); % 采样点 plot(t_recon, xr, g--); % 重建信号 legend(原始 xa(t), 采样点, 重建 xr(t));注意sinc(x)在 MATLAB 中定义为sin(pi*x)/(pi*x)这和信号处理中常用的sin(x)/x不同所以sinc((t-n_k)/Ts2)才是正确的重建核。这个pi是 MATLAB 的约定也是你和标准教材对接的桥梁千万别漏。避坑 / 常见问题 / 排查重建信号完全不像原始信号本文还有配套的精品资源点击获取