DSP语音信号处理Matlab课设:从加噪滤波到STFT时频分析全流程指南 📅 发布时间:2026/8/31 5:13:02 👁 浏览次数: 简介本资源是一份面向高校数字信号处理DSP课程学习者与初学者的语音信号处理综合实践材料聚焦语音信号分析、滤波、加噪建模与时频分析等核心环节适用于课程大作业、课程设计及MATLAB实践训练。压缩包共3个文件1.65MB包含一份结构清晰的Word格式实验报告.docx、一份完整可运行的MATLAB主程序代码.m以及一份PDF版课程作业说明文档分别承担原理阐述、算法实现与任务要求说明功能。已有1237人下载学习内容覆盖语音信号采集预处理、时域波形与频谱可视化、IIR/FIR滤波器设计与应用、白噪声叠加与SNR计算、短时傅里叶变换STFT时频图绘制等关键步骤代码注释详尽、变量命名规范报告中含实验结果截图、参数设置依据与现象分析便于读者理解算法逻辑并复现全流程。 这个题目我太熟了。本科那会儿室友拿下“dsp语音信号处理 代码报告”这个课程大作业的时候第一反应都是“这玩意儿到底要我干嘛”。等真正做完了回头看其实核心就一句话把一段干净语音变成带噪声的脏信号再用滤波器把噪声干掉最后用时频分析把整个过程可视化串成一份能讲清原理的报告。它是数字信号处理课程的集大成作业覆盖采样定理、傅里叶变换、滤波器设计、频谱分析这些最硬核的知识点也是Matlab能力的一次集中锻炼。网上关于这个题的版本很多有的给你一堆现成代码但讲不清为什么有的只谈滤波器原理跟实操完全脱节还有的直接丢一份报告让你换数据交差真答辩一下就会被问住。这篇博文我会按自己当年实际做课设的完整流程来写——从需求拆解、语音读取、加噪滤波到STFT语谱图、SNR/MSE量化评估再到报告排版思路和排查避坑每一段都是实测跑过的方案尽量让零基础的同学也能照着走通让想拿高分的同学也能做出有区分度的结果。1. 先拆解作业需求这题到底考什么1.1 用户标题里藏着哪些关键信息先看标题“dsp语音信号处理 代码报告_语音信号分析_语音信号滤波_matlab语音_时频分析作业_语音信号处理”。外行看是一堆关键词堆叠内行看其实已经给了三个硬性要求第一必须有“代码报告”双交付代码要能复现结果报告要能解释原理第二核心任务包含“语音信号分析”和“语音信号滤波”也就是既要做分析又要做处理第三要用到“时频分析”而且指明Matlab环境。这三个要求对应到课程能力点分别是用audioread读入wav并分析信号基本属性、构造噪声并设计数字滤波器消除干扰、用FFT/STFT/语谱图观察信号在频域和时频联合域的分布。很多同学拿到题目第一件事就问“有现成代码吗”我反而建议先花半小时把需求拆成一张表明确自己要做哪几步因为所有零散代码都能在网上找到真正拉开差距的是你有没有理解每一步在干什么。1.2 为什么选Matlab而不是Python这个题目指定Matlab是有原因的。首先是信号处理工具箱非常成熟filter、butter、designfilt、spectrogram这些函数开箱即用不像Python还要装scipy、librosa版本之间还容易打架。其次是Matlab的矩阵运算语义和信号处理教材高度吻合x mean(x,2)这种转单声道的写法比Python里np.mean(x, axis1)更接近自然语言调试时心智负担小很多。当然Python不是不行但考虑到交作业时老师大概率用Matlab打开你的.m文件和.fig图窗而且很多学校实验室的正版Matlab都预装了DSP System Toolbox你代码里用的每个函数在实验室都能原样跑通这是Python生态很难替代的。我的建议是别在这个环节纠结工具选型哪个能用通哪个核心是信号处理的思路。1.3 整体流程怎么规划才不容易翻车结合我自己的经验一个稳妥的流程大致是六步采集/选取语音样本、读取并分析原始信号、人为叠加噪声、设计滤波器去噪、时频分析前后对比、计算量化指标并写入报告。这个流程看起来简单但每一步都有坑比如选wav文件时没注意采样率导致滤波截止频率算错加噪声时没固定随机种子导致结果不能复现滤波器阶数选太高导致语音本身也被削掉。我习惯在动手写代码之前先在草稿纸上把“输入-处理-输出”画出来输入是原始wav和噪声参数处理是滤波器和STFT输出是波形图、频谱图、语谱图和指标表。画完你就知道先写哪个脚本后写哪个脚本最后报告里哪些图放哪里整个结构自然就出来了也不会写到一半发现缺这个步骤缺那个数据。2. Matlab环境准备与语音读取基础打牢2.1 工具版本和函数兼容性要注意什么Matlab版本建议用R2019b之后因为audioread替代旧版wavread已经非常稳定老版本跑新函数会报Undefined function新版本跑老代码也可能因为wavread被移除而直接红字。如果你装的版本比较新比如R2022b或者更新请优先使用audioread、audiowrite这套接口不要照搬网上老代码里的wavread。如果你在实验室机器上跑版本可能比较老那就老老实实先查一下当前版本支持哪些函数。我给一个万能方法在命令窗口输入help audioread如果返回帮助文档说明这个版本支持如果提示找不到就用wavread。这一步虽然只有十秒钟但能避免你后面所有代码连环报错。2.2 读取wav语音并做基本预处理假设你已经有一份speech.wav正常情况下是采样率8000或16000或44100的语音文件。第一步就是读进来并探明采样率[x, fs] audioread(speech.wav); % 如果文件是双声道合并为单声道 if size(x, 2) 1 x mean(x, 2); end % 查看语音时长和数据信息 duration length(x) / fs; fprintf(采样率: %d Hz, 时长: %.2f s\n, fs, duration); plot((0:length(x)-1)/fs, x); xlabel(时间 (s)); ylabel(幅值); title(原始语音信号波形);很多同学会忽略双声道合并这一步。如果你用手机录的音频大概率是双声道不合并的话后面做FFT时虽然不影响幅度谱的模值但做STFT时语谱图会显得很“脏”因为左右声道轻微延迟叠加后会形成梳状滤波效应。合并成单声道后在语义上也更符合“语音信号分析”这个主题。采样率这个概念我多解释一句它决定你能分析的最高频率。采样率8000对应最高4000Hz采样率44100对应最高22050Hz。做完FFT后你画频谱图时横轴必须画到fs/2不是画到fs否则会在报告里闹笑话。这个问题我在批改学弟作业时见过太多次属于高频翻车点。2.3 加噪声之前先观察原始信号的频率结构不要急着加噪声先对原始信号做一次快速频谱观察这能让你后面写报告时更有底气。最简单的做法就是FFT加fftshift在看频谱之前先确认一点语音信号的能量主要集中在低频段通常100Hz到4000Hz之间高频段能量迅速衰减。N length(x); X fft(x, N); f (0:N-1) * fs / N; plot(f, abs(X(1:N))); xlabel(频率 (Hz)); ylabel(幅度); title(原始语音信号频谱);这段代码里有个小陷阱直接用fft(x, N)得到的是双边谱右侧一半是镜像画图时只画前一半即可。如果你想让频谱以0为中心对称显示用fftshift横轴频率也要对应改成从-fs/2到fs/2。这些都是报告中能体现专业度的细节。我建议你在加噪声前先保存一张原始波形图和一张原始频谱图后面滤波前后对比会非常直观。很多同学一上来就加噪声最后报告里全是噪声信号没有原始干净信号的图老师一看就是没做对比印象分会大打折扣。3. 滤波器设计从加噪到去噪的关键一公里3.1 加噪声怎么做才规范且可复现加噪声之前先固定随机种子这是很多教程不会强调但特别重要的点。如果你不固定随机种子每次运行生成的噪声序列都不同滤波前后前后对比的结果就每次都不一样报告里的截图和实际运行结果对不上答辩时容易被问住。固定随机种子的写法如下rng(42); % 任意整数都可目的是让噪声可复现 noise 0.1 * randn(size(x)); % 高斯白噪声幅度系数0.1 xn x noise;噪声幅度系数0.1是我比较常用的取值。如果信号本身幅值在正负1之间0.1倍高斯白噪声的信噪比大约在20dB左右听感上是“有底噪但语音清晰”滤波效果也能比较明显地看出来。如果噪声系数设太大比如1.0语音彻底淹没在噪声里滤波器怎么设计都救不回来设太小比如0.01滤波前后对比又看不出区别。你也可以根据SNR需求反推噪声系数这取决于你报告的侧重点。另外在报告中建议写一句“本文采用加性高斯白噪声(AWGN)模拟环境干扰”然后在代码里用randn实现这是最标准的教学做法。如果你想让实验更有层次还可以对比不同噪声强度比如噪声系数分别取0.1、0.2、0.5对应低、中、高三种干扰最后用一张表列出不同强度下的滤波后SNR这个设计会让你的报告明显高于“能跑就行”的水平。3.2 低通滤波器设计从Butterworth到FIR语音信号加噪声后大部分噪声分布在整个频带但语音本身主要集中在中低频所以经典做法是设计低通滤波器。Matlab里最常用的就是butter设计巴特沃斯IIR滤波器fc 3000; % 截止频率根据语音内容和采样率调整 [b, a] butter(6, fc/(fs/2), low); y_iir filter(b, a, xn);这里阶数6是一个很微妙的平衡点。阶数低了过渡带太宽滤波不干净噪声残留多阶数高了比如10阶以上虽然阻带衰减更快但MATLAB语音处理过程中会出现明显的相位失真波形看起来“扭曲了”听感也不自然。IIR滤波器的优点是计算效率高、幅度特性好缺点是相位非线性这在语音信号分析中往往可以容忍因为人耳对相位不敏感。如果你想让报告更有技术含量可以同时设计一个FIR等波纹滤波器做对比。FIR用designfilt比较好用firFilter designfilt(lowpassfir, ... PassbandFrequency, 2800, ... StopbandFrequency, 3200, ... PassbandRipple, 0.5, ... StopbandAttenuation, 60, ... SampleRate, fs); y_fir filter(firFilter, xn);FIR的优点是严格线性相位缺点是同等性能下阶数远高于IIR滤波计算量大。报告中把两种滤波器放在一起对比说明IIR适合资源受限但语音可容忍相位失真的场景FIR适合对相位敏感的应用这就是一个非常漂亮的加分点。3.3 滤波参数怎么选才科学滤波截止频率的选取不能拍脑袋建议先看原始语音的频谱找到语音能量明显下降的频率点。如果语音内容是普通说话声采样率8000截止频率选3000Hz左右比较合理如果是音乐类的素材高频成分丰富选4000Hz以上才不破坏音质。这个过程体现的就是“先分析后处理”的工程思维。一个非常关键的实操点是butter的截止频率参数必须是归一化频率也就是fc/(fs/2)。很多同学直接写butter(6, 3000)结果滤波结果完全是乱的因为Matlab把3000当成了0到1之间的归一化值相当于把Nyquist频率变成了6000Hz完全不对劲。这个坑我在帮人debug时遇到过不下十次。滤波后建议用fvtool(b,a)打开滤波器可视化工具看一眼幅频响应曲线确认截止频率位置是否合理、阻带衰减是否够大。这个过程虽然不直接出现在报告里但能把你对滤波结果的判断从“凭感觉”变成“看数据”非常重要。4. 时频分析别只会画频谱图4.1 FFT频谱只能告诉你“有什么频率”不能告诉你“频率什么时候出现”很多同学交上去的“时频分析”就是一张FFT频谱图严格来说这只能叫频域分析不能叫时频分析。FFT把整个时间段的频率信息平均到了一起它回答的问题是“这段语音包含哪些频率成分”但回答不了“某个频率出现在哪一秒”。语音信号最大的特点是非平稳同一句话里元音段能量集中在低频辅音段会有明显的瞬态高频这些时间信息对语音识别和语音增强非常重要。要观察这种“频率随时间变化”的规律就得用短时傅里叶变换STFT。把这个区别想明白你报告里的“时频分析”章节就高出平均水平一大截。4.2 用STFT做出语谱图Matlab里最方便的STFT实现是spectrogram函数一行代码就能出图[S, f, t] spectrogram(xn, hann(256), 128, 1024, fs); % 画出语谱图 figure; imagesc(t, f, abs(S)); axis xy; xlabel(时间 (s)); ylabel(频率 (Hz)); title(加噪语音信号的语谱图); colorbar;这里面几个参数值得仔细解释。hann(256)是窗函数和窗口长度窗口越短时间分辨率越高、频率分辨率越低窗口越长频率分辨率越高、时间分辨率越低这是海森堡测不准原理在信号处理中的体现。取256点对应约32ms的窗口比较符合语音信号短时平稳的假设。128是hop size也就是窗每次移动128个样本一般取窗口长度的一半保证相邻帧有50%重叠平滑度更好。1024是FFT点数一般大于窗口长度等效于在频域插值让语谱图看起来更细腻。这行代码做完你已经有了“时频分析”核心图。建议把原始语音、加噪语音、IIR滤波后语音、FIR滤波后语音四张语谱图放在同一张大图里subplot(2,2,x)这种对比图是整份报告里最有视觉冲击力的部分老师一眼就能看出你的滤波设计真的有效果。4.3 频谱质心和能量分布也可以算如果想在时频分析部分再加一点量化维度可以计算频谱质心spectrum abs(S); freq_bins repmat(f, 1, size(spectrum, 2)); centroid sum(freq_bins .* spectrum) ./ sum(spectrum); plot(t, centroid); xlabel(时间 (s)); ylabel(频谱质心 (Hz)); title(语音信号的频谱质心随时间变化);频谱质心描述的是信号“重心”所在频率元音段质心低辅音段质心高。加噪声后质心会被抬高滤波后质心会回落这个变化趋势可以作为一个客观指标写进报告说明滤波器不只是“听起来干净了”而是从数据上证实了高频噪声被有效压制。这种多维度的分析会让你的报告内容更扎实而不是只有三张图。5. 量化评估与图表呈现让结果可解释5.1 用SNR评价滤波效果的完整思路信噪比SNR是语音增强最常用的评价指标定义为信号功率与噪声功率的比值单位dB。关键点在于真实场景中你拿不到“纯净噪声”但在作业里你有原始干净信号所以可以这么算% 滤波后残余噪声 residual_noise y_iir - x; % 计算信噪比 SNR_after 10 * log10(sum(x.^2) / sum(residual_noise.^2)); fprintf(IIR滤波后SNR %.2f dB\n, SNR_after);同样的方法可以算加噪后的SNR。因为加噪是人为的理论上加噪后SNR约等于10*log10(mean(x.^2)/mean(noise.^2))滤波后SNR应该比加噪后高这才说明滤波有效果。如果滤波后SNR反而更低了说明滤波器参数有问题可能是截止频率把太多语音成分也削掉了也可能是滤波器不稳定。SNR提升幅度一般在5到15dB比较正常如果提升太多比如30dB要怀疑是不是信号本身被过度平滑了。这里有一个容易忽略的点计算残差时由于IIR滤波器有非线性相位滤波后信号和原始信号之间有时间偏移或相位差直接相减会出现很大的“假残差”。更稳妥的处理是用xcorr做对齐或者在报告里说明“本文以幅度谱和语谱图对比为主SNR计算作为辅助参考”。5.2 用MSE和相关系数做多维印证除了SNR另外两个常见指标是均方误差MSE和相关系数。MSE描述滤波后信号与原始干净信号的误差大小越小越好相关系数描述两者线性相关程度越接近1越好。Matlab里一行一个mse_value mean((y_iir - x).^2); corr_value corrcoef(y_iir, x); fprintf(MSE %.6f, 相关系数 %.4f\n, mse_value, corr_value(1,2));这三个指标放在报告中做成一张表格比干巴巴写“滤波后效果良好”有说服力得多。我建议的表格长这样处理阶段 | SNR (dB) | MSE | 相关系数 原始语音 | 高无噪声 | 0 | 1 加噪后语音 | 根据噪声强度计算 | 较大 | 较低如0.7-0.9 IIR滤波后 | 提升 | 降低 | 升高 FIR滤波后 | 提升 | 降低 | 升高注意原始语音的SNR理论上无穷大表格里写“无穷”并不可取可以写“参考值”或画横线报告里简单说明即可。加噪后的SNR、MSE和相关系数都具体算出来滤波后也具体算出来这一表格就是你量化分析的全部证据链。5.3 图表排版和报告结构怎么处理报告结构我建议按这样一个逻辑走摘要和关键词、引言背景与任务、原理方法语音信号、噪声模型、滤波器原理、时频分析原理、实验流程读取、加噪、滤波、分析、结果与讨论波形图、频谱图、语谱图、量化指标表、总结与体会、参考文献。图表排版上有一个细节每张图都要有编号和图题坐标轴必须有中文或英文说明字体调大不要直接截一张Matlab默认窗口就贴上去。Matlab里可以用set(gcf,Color,white)去掉灰色背景用grid on加网格线这些处理都会让报告看起来专业不少。我在第4节提到的对比图四张语谱图并排放建议统一坐标范围颜色轴caxis设置相同的上下限这样对比才公平否则每张图色标范围不同视觉上会误导读者。6. 高频踩坑与报告撰写经验6.1 我踩过的那些坑第一次做这个作业时我踩过一个特别隐蔽的坑。我用的音频是44.1kHz采样率但我设计滤波器时习惯性地写了截止频率3000Hz这个没错问题出在我把fc/(fs/2)算错了3000/(44100/2)约等于0.136我写成了3000/44100约等于0.068结果实际截止频率只有1500Hz滤波后语音明显发闷元音部分的高次谐波全被切掉了。后来我把语音频谱画出来才发现这个素材的能量一直延伸到8000Hz用1500Hz的截止频率等于把语音内容的“声调信息”也削掉了听感像隔着被子说话。另一个坑是滤波器的初始状态。直接filter(b,a,xn)时Matlab默认初始状态为零这没问题。但如果你把信号分成一段一段处理再拼接每一段开始时滤波器状态没有延续就会在拼接处产生爆音和瞬间冲激。正确的做法是用[y, zf] filter(b, a, xn, zi)把上一段的终止状态传给下一段。虽然作业不太需要分段处理但如果你做实时流式处理这个问题完全绕不开。6.2 常见问题速查表信号与系统里有个特别好的思维习惯出现任何指标异常先画图、先看波形再判断是参数问题还是逻辑问题。这张表我按“症状-原因-解法”整理了一下症状 | 可能原因 | 解决方式 滤波后语音严重失真 | 截止频率过低或滤波器阶数过高 | 查看频谱后调整截止频率降低阶数 滤波后仍有明显噪声 | 截止频率过高或噪声频带与信号重叠 | 降低截止频率或用带通/自适应滤波 SNR计算结果为负 | 残余噪声能量大于信号能量或信号对齐问题 | 检查滤波参数用xcorr对齐后再计算 语谱图全是竖条纹 | STFT参数不合理或信号太短 | 增大窗口重叠率检查hop size 运行报错Undefined function | Matlab版本过老或函数名拼写错误 | 用help查函数是否存在用audioread替代wavread 加了噪声后结果每次不同 | 没有固定随机种子 | 加rng(42)等固定种子还要补充一个很多人忽略的点如果audioread读取时返回的是double类型但幅度范围在正负1之间而某些旧版代码用wavread返回的是int16类型范围在正负32768之间两种类型直接混用会导致幅度差异巨大加噪声的系数就会完全失效。6.3 报告怎么写才能拿高分报告不是代码的堆砌不是把所有函数说明复制一遍就完事而是要把“我做了什么、为什么这么做、结果说明了什么”讲清楚。我常用的一个套路是每个实验步骤先写“目的”再写“方法”再写“结果与讨论”。比如滤波这一节目的就是“消除加性高斯白噪声恢复语音清晰度”方法就是“设计6阶巴特沃斯低通滤波器截止频率3000Hz”结果与讨论就是放滤波前后的波形图和频谱图并解释为什么噪声被压制而语音主体得以保留。一个比较容易被忽略的加分点是“体会与改进”。这一个小节可以写你在实验中发现的问题比如IIR滤波器相位失真对语音可懂度的影响、固定截止频率无法适应不同噪声环境、未来可以考虑自适应滤波或小波去噪。这种自我批评式的内容反而会让报告显得真实且深刻比无脑吹“本设计实现了良好去噪效果”有说服力得多。另外报告中一定要包含核心代码并逐段注释但不需要把所有代码整段贴进去只贴关键片段比如加噪、滤波、STFT三块每块不超过二十行老师扫一眼就能看懂你的思路。完整代码作为附录放在最后或者提供单独的.m文件这样既保证报告可读性又保证可复现性。6.4 答辩前的准备技巧课程设计通常有五分钟到十分钟的答辩老师大概率会问你三个问题为什么选这个滤波器、截止频率怎么定的、滤波效果怎么评价的。这三个问题在报告中都有答案但你最好能用一句话各回答清楚。比如“因为巴特沃斯滤波器通带最平坦过渡带和阻带特性在IIR里最适合语音6阶是兼顾过渡带陡峭度和相位失真的选择截止频率3000Hz是根据语音频谱能量分布选的效果用SNR从多少dB提升到多少dB、语谱图高频噪声明显减少来评价”。我还建议你把所有图用saveas导出为png格式统一放到Report/figures目录在答辩PPT里直接引用。另外准备一份“原始语音-加噪语音-滤波后语音”的音频demo放给老师听体感冲击力比任何数据都强。这一招在课设答辩里几乎百试百灵。最后再说一个我在多次帮人review代码后总结出来的习惯所有脚本在交付前一定要从头到尾跑一遍确认没有warning和error生成的所有图片和指标都对得上。很多同学代码写得很漂亮但交付前随手改了参数没重跑结果报告里的截图是旧版本现场演示时老师一运行数值对不上非常尴尬。这种细节虽然看起来不起眼但恰恰是区分一份作业是“认真完成”还是“草率了事”的关键指标。本文还有配套的精品资源点击获取