资讯动态

MATLAB语音信号去噪课程设计:从加噪到FIR滤波与SNR评估

发布时间:2026/10/18 13:34:06 来源:尧图企业网站定制
简介面向数字信号处理课程设计场景提供一套完整的基于MATLAB的有噪声语音信号处理方案适合电子信息、通信等相关专业学生参考。资源共4个文件压缩包大小1.04MB包含m源码文件、fig图形文件、doc设计文档和wav语音样本覆盖程序实现、结果可视化、理论说明及测试数据。内容综合运用FIR与IIR滤波器设计方法通过窗函数法实现FIR滤波采用巴特沃斯、切比雪夫及双线性变换设计IIR滤波器对含噪语音进行时域和频域分析并给出滤波前后对比图形。doc文档阐述理论推导与设计思路m文件可直接运行或修改便于理解各环节实现细节。目前已有2296人学习下载可作为课程设计报告撰写、MATLAB仿真练习及滤波器参数对比实验的实用参考资料。1. 从一段带噪语音到可听结果这个课程设计到底在做什么数字信号处理课程设计里语音信号处理是最贴近真实工程的一类题目。它不像理论推导那样只求公式成立而是要把一段实际录制的 WAV 文件变成肉眼可见的频谱、耳朵可闻的去噪结果还要用 SNR 这类数字指标给自己打分。很多第一次做这个题目的人都会卡在同一个地方代码写完了波形也画出来了但滤波后的声音依然糊成一团——问题往往不在滤波器本身而在你对语音信号的基本参数和噪声建模不够重视。这份资源解决的就是这条完整的链路从读入 WAV、加噪、设计滤波器、做频谱分析到最后的客观评价和结果对比。它适合正在做课程设计的学生也适合刚接触 MATLAB 语音处理、想快速跑通一个可用流程的开发者。你不需要懂很深的自适应算法但需要能把采样率、帧长、截止频率这些基础参数讲清楚。2. 语音信号的数字域表示与噪声来源打开 WAV 之前先看清这两件事2.1 采样率、位深与帧长三个参数决定后续算法怎么设计语音信号在 MATLAB 里就是一个一维数组每个元素代表一个采样点的幅值但你不能把它当普通数组处理。第一个要确认的是采样率 fs。语音处理的标准场景里电话语音 8 kHz宽带语音 16 kHzCD 音质 44.1 kHz课程设计一般用 8 kHz 或 16 kHz 就够了。fs 直接决定你的滤波器截止频率能设到多少——理论极限是 fs/2也就是奈奎斯特频率超过这个值就没有意义了。第二个参数位深决定了信号的动态范围16 bit 量化时每个采样点最大值不超过 32767MATLAB 的 audioread 会自动归一化到 [-1, 1] 区间。第三个概念是帧长。语音是非平稳信号但在 2030 ms 的短时间窗内可以近似看成平稳所以后续滤波、频谱分析都要分帧。8 kHz 采样率下20 ms 对应 160 点30 ms 对应 240 点16 kHz 采样率下20 ms 是 320 点。这个概念在做谱减法或短时傅里叶变换时会反复用到。读取语音文件的第一步就是获取这些基本参数代码很简单但很多人会漏掉后面的预处理[x, fs] audioread(speech.wav); if size(x, 2) 1 x mean(x, 2); % 双声道转单声道避免后续矩阵维度错误 end x x / max(abs(x)); % 幅度归一化到 [-1, 1] sound(x, fs); % 试听原始语音这段代码的逻辑是先读出数据和采样率如果是立体声就取左右声道均值转成单声道再归一化幅度。归一化这一步不是可选项因为后续无论加噪还是 SNR 计算都要求信号幅度在一个可控范围内。如果原录音本身音量很小加噪后的混合信噪比会失真滤波器的效果也不容易评估。2.2 噪声类型识别高斯白噪声、脉冲噪声和周期性噪声很多课程设计对噪声的要求只有一句“加噪”但不同噪声对滤波器设计的影响完全不同。最常见的是高斯白噪声它在整个频带上均匀分布用低通或带通滤波就能去除语音频带以外的能量。脉冲噪声是时域上的突发尖峰频谱上表现为宽带冲击单纯低通滤波反而会把尖峰抹开产生更长的拖尾。周期性噪声比如 50 Hz 工频干扰在频谱上是一条窄带谱线用陷波器更合适。判断噪声类型不需要多高级的手段画一段时域波形和频谱图就够了noise 0.05 * randn(size(x)); % 高斯白噪声系数控制幅度 xn x noise; % 语音加噪 N length(xn); Xk fft(xn, N); f (0:N-1) * fs / N; % 频率轴单位为 Hz plot(f, 20*log10(abs(Xk(1:N/2)))); xlabel(频率/Hz); ylabel(幅度/dB); title(加噪信号的频谱);这里的核心逻辑是使用 randn 生成高斯白噪声乘以 0.05 这个幅度系数来控制信噪比。系数越大噪声越强0.01 约对应 40 dB 以上的高信噪比0.1 对应约 20 dB 的低信噪比。FFT 之后取单边频谱画对数幅度因为语音频谱动态范围很大线性幅度下低频细节完全看不清。很多人说“频谱图看不出来”多半是没取 log 或没截取前半段。【关键词】数字信号处理课程设计在这个环节就要体现出对参数的理解采样率、帧长、噪声幅度系数都要能在报告里写清楚为什么这么选。3. 滤波器设计的三种选择FIR、IIR 与谱减法3.1 选型依据从过渡带、线性相位与阻带衰减对比 FIR 和 IIR语音去噪最常见的做法是低通或带通滤波因为语音能量主要集中在 3003400 Hz 的频带内。FIR 滤波器的最大优势是线性相位所有频率分量的延迟一致波形不会发生相位失真。对语音这种对相位敏感的信号线性相位很重要——相位失真会让去噪后的声音发“闷”或发“空”。IIR 滤波器的优势是阶数低、计算量小同样的过渡带指标用 Butterworth 可能只需要 10 阶而 FIR 可能要 60 阶。但 IIR 的相位是非线性的而且无限冲激响应在定点实现时容易不稳定。课程设计的场景里我一般建议选 FIRMATLAB 的 fir1 函数一行就能设计完成参数含义清晰报告中也好解释。如果你用的是 fdatool 或 filterDesigner界面生成的系数可以直接导出适合那些不想手写设计代码的人。具体到滤波器参数过渡带越窄FIR 阶数越高。一个常用的经验公式是N ≈ 3.3 / 归一化过渡带宽度。比如采样率 16 kHz截止频率 3400 Hz过渡带从 3400 到 4000 Hz归一化过渡带宽就是 (4000-3400)/16000 0.0375算出来 N ≈ 88。这里的 N 是滤波器阶数fir1 的向量长度是 N1。3.2 用 fir1 设计 FIR 低通滤波器一个可直接替换参数的代码框架这一小节的代码可以直接粘贴运行结构上是一个完整的“设计-滤波-评估”框架fs 16000; % 采样率电话语音用 8000 fc 3400; % 语音频带上限 fst 4000; % 过渡带起点fc 与 fst 之间是过渡带 norm_fc fc / (fs/2); % 截止频率归一化 norm_fst fst / (fs/2); % 过渡带起点归一化 N 65; % 滤波器阶数根据过渡带调整 h fir1(N, norm_fc, low, hamming(N1)); y filter(h, 1, xn); % 用设计好的 FIR 对加噪信号滤波 sound(y, fs); % 试听去噪效果代码的核心逻辑是先用归一化频率调用 fir1再通过 filter 对加噪语音滤波。归一化的含义是把真实频率除以 fs/2让截止频率变成一个 01 之间的无量纲数这是 filter 函数族和 fdatool 的共同约定。滤波器阶数 N 决定过渡带陡峭程度N 太小则过渡带宽阻带衰减不够。hamming(N1) 是窗函数用于压低旁瓣减少滤波后频谱上的波纹。这里有个细节值得注意filter 函数是因果滤波会有群延迟输出信号的前若干点会出现瞬态响应。你听的时候可能觉得开头“啵”了一声这就是瞬态。课程设计报告里如果被问到可以说这是 FIR 的固有延迟也可以用 filtfilt 做零相位滤波来消除但 filtfilt 会引入非因果性在某些实时场景不可用。3.3 补充一个非滤波手段谱减法及其“音乐噪声”边界低通滤波能去掉高频噪声但如果噪声和语音频带重叠单纯滤波会把语音本身的高频细节也切掉。这个时候谱减法是一个常用的补充方案。它的思路是在频域上把估计出的噪声幅度谱减掉保留语音相位再反变换回时域X fft(xn); mag abs(X); % 幅度谱 phase angle(X); % 相位谱语音感知对相位不敏感 % 用前 0.3 秒无声段估计噪声幅度谱 noise_frame xn(1:round(0.3*fs)); Nn abs(fft(noise_frame, N)); mag_est max(mag - 1.5 * Nn, 0.2 * mag); y2 ifft(mag_est .* exp(1i * phase), symmetric); sound(real(y2), fs);注释里写清楚了每步的作用。这里的关键参数是减因子 1.5 和下限系数 0.2减因子太大语音会被损伤太小则噪声残留明显。0.2*mag 的下限防止某些频点被减成负值后出现刺耳的残留噪声——俗称“音乐噪声”。你要知道谱减法适合宽带噪声但对周期性噪声效果很差周期性噪声应该在时域或频域用梳状滤波或陷波器处理而不是谱减。4. 完整实验流程从加噪、滤波到 SNR 与语谱图定量评价4.1 三段式流程每段都能独立复现和对比课程设计的完整流程可以分为三段构造含噪信号、设计滤波器去噪、评价结果。三段式的好处是每一阶段都能画图、试听、记录数据报告中可以直接对比处理前后的波形和频谱。rng(2024); % 固定随机种子确保结果可复现 noise 0.05 * randn(size(x)); xn x noise; y filter(h, 1, xn); % FIR 低通结果 % 如果想做 IIR 对比可以用 butter、cheby1 [b, a] butter(8, 3400/(fs/2), low); y2 filter(b, a, xn);设置随机种子 2024 这个细节很重要。很多课程设计需要多次运行调试如果不固定种子每次生成的噪声不同前后实验结果无法对比导师问起“为什么这次 SNR 比上次高”时你很难解释。4.2 频谱与语谱图别只看波形这三个图才是报告的主菜时域波形只能看到幅度变化看不出频率成分。课程设计报告里至少要有三张图加噪前后的频谱图、滤波前后的频谱图、语谱图。频谱图用 FFT 就能画语谱图用 spectrogram 函数figure; spectrogram(xn, hamming(256), 128, 512, fs, yaxis); title(加噪语音的语谱图);参数含义是窗长 256 点重叠 128 点FFT 点数 512采样率 fs。窗长决定了时间分辨率和频率分辨率的取舍——窗长越大频率分辨率越高但时间分辨率越差。128 点重叠是默认的 50% 重叠对于语音信号来说是经验上比较稳的选择。看语谱图时你关注两点横轴是时间、纵轴是频率、颜色深浅代表能量大小。滤波后的语谱图应该看到 3400 Hz 以上的非语音能量明显变暗而 3003400 Hz 的语音能量基本保持。4.3 评价指标SNR 与分段 SNR主客观结合才可信SNR 是课程设计里必须计算的指标但很多人算错。正确的是用原始纯净语音和噪声或误差信号的能量比snr_in 10 * log10(sum(x.^2) / sum((xn - x).^2)); snr_out 10 * log10(sum(x.^2) / sum((y - x).^2)); fprintf(滤波前 SNR: %.2f dB, 滤波后 SNR: %.2f dB\n, snr_in, snr_out);先说 snr_in分子是原始语音能量分母是加噪前后信号的差值也就是噪声能量。后面是 snr_out分子不变分母变成滤波后信号和原始语音的差值包含残留噪声和语音失真两部分。你要注意一个事实如果滤波器把语音的高频细节也切掉了snr_out 可能不升反降这是正常现象恰恰说明单纯低通不是万能的。分段 SNRsegmental SNR是更接近主观听感的指标做法是把信号分成多帧逐帧计算 SNR 再求平均。比全局 SNR 更能反映语音在时间上非平稳的特点。课程设计里如果你的滤波器效果明显分段 SNR 的提升会比全局 SNR 更直观也更能体现你对语音特性的理解。5. 避坑与常见问题五个高频翻车现场及排查方法5.1 WAV 文件读出来是两列处理时报维度错误现象audioread 读取立体声 WAV 后生成的是 N×2 矩阵直接做 FFT 或 filter 时报“矩阵维度不一致”错误。原因大部分课程设计用的语音文件是单声道但网上下载的素材很多是双声道。MATLAB 不会自动帮你合并。解决读入后先检查 size(x)如果第二维大于 1 就取均值转成单声道。前面 2.1 的代码里已经写了这里再强调一次因为它真的是最常见的第一个坑。5.2 滤波后声音“闷”高频全没了现象去噪后的语音虽然背景噪声小了但人声像隔着被子说话辅音部分明显模糊。原因截止频率设置过低。语音的齿音和擦音能量可以延伸到 68 kHz把截止频率设成 2 kHz 会把这些信息全部滤掉。另一个可能是 FIR 阶数太大引入了明显的群延迟。解决把截止频率提高到 3400 Hz 以上或者改用带通滤波而不是低通只切除 300 Hz 以下和 4 kHz 以上的能量。先试听再调参不要只看滤波器频率响应曲线。5.3 每次运行结果都不一样实验记录对不上现象同一段语音、同一个滤波器两次运行出来的 SNR 值不同图形也不同。原因randn 每次生成的随机序列不同等于每次实验都在不同的含噪信号上做测试。解决rng(0); % 任意固定种子在生成噪声前固定随机种子。这样不仅结果可复现你写报告时也能稳定复述实验数据。5.4 加噪后信号幅度超过 [-1, 1]波形被削顶现象sound 播放时有明显破音时域波形顶部被切平。原因加噪后信号峰值超过了 1而声卡对超过满量程的采样值会截断。解决加噪后重新归一化或者把噪声幅度系数调小。xn x 0.05 * randn(size(x)); xn xn / max(abs(xn)); % 加噪后再归一化一次但注意如果做了这一步SNR 计算公式里的分母要相应调整最好在归一化之前记录噪声能量。5.5 谱减法后出现“音乐噪声”听起来像流水声现象用 3.3 节的谱减法处理后背景残余噪声变成了断续的、带金属感的噪声。原因减因子设置不合适或者噪声估计不准或者下限系数过小。音乐噪声是频谱上孤立尖峰产生的听觉伪影是谱减法的固有缺陷。解决把下限系数从 0.2 提高到 0.4或者对减下来的频谱做平滑滤波。也可以改用 Wiener 滤波变体它对残留噪声的抑制更温和。5.6 滤波器阶数过高导致运行缓慢甚至矩阵奇异现象fir1 的 N 设置到几千设计阶段耗时明显滤波后信号反而变形。原因N 过大不代表效果更好。FIR 滤波器阶数由过渡带决定N 超出需要后只会增加计算量不会显著改善阻带衰减。N 超过一定值后数值稳定性也会变差。解决按 3.1 的经验公式估算 N然后在 ±20% 范围内扫描对比 SNR 选择最优值不要盲目加大。6. 一条可复用的调参路线从预加重到窗函数再到帧叠放如果你觉得上面的流程每一步都跑通了但效果还差口气这里有三个可以继续优化的方向按收益从高到低排列。第一个是预加重。语音信号的高频分量能量低低通滤波后高频更容易被噪声淹没。常见做法是把预加重滤波器放在加噪之前y_pre(n) x(n) - 0.97 * x(n-1)。这个高通特性可以让高频段在频域上获得更大的权重后面再做低通去噪时频率响应匹配度会更好。预加重系数 0.97 是语音处理里的经验值你可以在 0.90.99 之间微调。第二个是窗函数的选择。FIR 设计里 hamming 是默认推荐但如果你想压低阻带旁瓣可以用 blackman如果更在意主瓣宽度可以用 kaiser它有一个 beta 参数控制旁瓣与主瓣的权衡。做分帧分析时用 50% 重叠的 hamming 窗是标准做法换成 75% 重叠对短时能量的估计更平滑但计算量会增加近一倍课设场景下通常没必要。第三个是分段评价维度。除了整体 SNR按频率分段统计去噪效果比如把频带分成 01 kHz、13 kHz、35 kHz 三段分别计算能量衰减。这个方法能直观看出滤波器对不同频段的影响也能帮你判断有没有过度损伤语音的高频成分。我的个人习惯是拿到一段新语音先花一分钟画出它的频谱确定语音能量集中的频段再定滤波器的截止频率和过渡带最后才写设计代码。从那以后我每次做数字信号处理课程设计都强制走一遍这个流程先听后看先看频谱再选滤波器而不是一上来就套函数。这个方法帮我避掉了至少一半的返工希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑