音频噪声抑制(2):维纳(Wiener)滤波器篇
之前的文章讲了使用经典滤波器来抑制噪声。
Review:噪声抑制之经典滤波器篇
里面提到,“用经典滤波器抑制噪声,非常简单。如果噪声的功率谱PSD和有用信号功率谱PSD没有重叠的话,那可以实现非常好的效果。
但是,如果有重叠,去噪的效果就不是特别理想了。因为在复指数信号空间里面,没办法把有用信号和噪声信号分离啊。”
正是由于“噪声谱和有用信号谱可能重叠”,所以发展了维纳滤波器。
前面的文章对维纳滤波器的设计也讲过了。
Review:维纳滤波器的设计
这篇文章,就是真实地来操作一下,设计一个维纳滤波器来抑制噪声。
因为没有去录音,所以噪声源还是matlab里的randn产生的高斯过程的数据。
再假设高斯过程并不是直接加入有用数据的,而是经过了一个“信道”,发生了一些变化,比如,AR过程。
然后就是分两步了。
1. 训练过程,用已知的训练信号和已知的接收信号,通过解方程,求得滤波器系数;
2. 滤波器系数不变,用这组系数对此后接收到的信号进行滤波,实现噪声抑制。
代码比较简单,所以直接出来了。
主函数。
%% 维纳去噪,基于训练的
% 通过解方程求滤波器系数
% 作者:qcy% 版本说明:补充滤波阶段
% 版本:v1.1
% 时间:2016年10月29日18:18:21% 版本说明:训练阶段
% 版本:v1.0
% 时间:2016年10月29日16:52:37clear;
close all;
clc%% 读入音频
filedir=[]; % 设置路径
filename='bluesky1.wav'; % 设置文件名
fle=[filedir filename]; % 构成完整的路径和文件名
[s, fs] = audioread(fle); % 读入数据文件s=s-mean(s); % 消除直流分量
s=s/max(abs(s)); % 幅值归一
N=length(s); % 语音长度
time=(0:N-1)/fs; % 设置时间刻度%% 产生噪声并加入
SNR = 0; % 设置信噪比
r2=randn(size(s)); % 产生随机噪声
b=fir1(31,0.5); % 设计FIR滤波器,代替H
r21=filter(b,1,r2); % FIR滤波
% [signal_with_noise,noise]=add_noisedata(s,data,fs,fs1,snr);
[r1,r22]=add_noisedata(s,r21,fs,fs,SNR);% 产生带噪语音,信噪比为SNR %% 解方程
% 【训练阶段】
h_length = 100; % 这个东西我目前所知道的,就只有凭感觉去设置了。
desired_signal = s;
observed_signal = r1;
h = my_weiner_filter1( h_length,desired_signal,observed_signal );% 滤波
% 用维纳滤波器,作用在接收到的训练信号上。看看效果-->这还是属于训练阶段
y = filter(h,1,r1);
output = y;snr1=SNR_singlech(s,r1); % 计算初始信噪比
snr2=SNR_singlech(s,output); % 计算滤波后的信噪比
snr=snr2-snr1;%% 画图
figure;
subplot 311; plot(time,s,'k'); ylabel('幅值');
ylim([-1 1 ]); title('原始语音信号');
subplot 312; plot(time,r1,'k'); ylabel('幅值')
ylim([-1 1 ]); title('带噪语音信号');
subplot 313; plot(time,output,'k');
ylim([-1 1 ]); title('滤波输出语音信号');
xlabel('时间/s'); ylabel('幅值')%% 打印SNR
fprintf('[训练]\n',snr1);
fprintf('滤波前 SNR = %f [dB] \n',snr1);
fprintf('滤波后 SNR = %f [dB] \n',snr2);
fprintf('提升 %f [dB] \n',snr);
fprintf('\n');%% 听效果
% sound(s,fs); % 干净的语音
% sound(r1,fs); % 含噪的语音
% sound(output,fs); % 滤波后的语音%% 【降噪阶段】% 假设这是后来录的一段音,混入了性质类似的噪声。
% 现在想用刚刚得到的滤波器系数,来去除掉现在这段含噪信号中的噪声。filedir=[]; % 设置路径
filename='risesun.wav'; % 设置文件名
fle=[filedir filename]; % 构成完整的路径和文件名
[s, fs] = audioread(fle); % 读入数据文件s=s-mean(s); % 消除直流分量
s=s/max(abs(s)); % 幅值归一
N=length(s); % 语音长度
time=(0:N-1)/fs; % 设置时间刻度%% 产生噪声并加入
% SNR = 0; % 设置信噪比
r2=randn(size(s)); % 产生随机噪声
b=fir1(31,0.5); % 设计FIR滤波器,代替H
r21=filter(b,1,r2); % FIR滤波
% [signal_with_noise,noise]=add_noisedata(s,data,fs,fs1,snr);
[r1,r22]=add_noisedata(s,r21,fs,fs,SNR);% 产生带噪语音,信噪比为SNR %% 用上一阶段求得的h,降噪% 滤波
y = filter(h,1,r1);
output = y;snr1=SNR_singlech(s,r1); % 计算初始信噪比
snr2=SNR_singlech(s,output); % 计算滤波后的信噪比
snr=snr2-snr1;%% 画图
figure;
subplot 311; plot(time,s,'k'); ylabel('幅值');
ylim([-1 1 ]); title('原始语音信号');
subplot 312; plot(time,r1,'k'); ylabel('幅值')
ylim([-1 1 ]); title('带噪语音信号');
subplot 313; plot(time,output,'k');
ylim([-1 1 ]); title('滤波输出语音信号');
xlabel('时间/s'); ylabel('幅值')%% 打印SNR
fprintf('去噪 \n',snr);
fprintf('滤波前 SNR = %f [dB] \n',snr1);
fprintf('滤波后 SNR = %f [dB] \n',snr2);
fprintf('提升 %f [dB] \n',snr);%% 听效果
% sound(s,fs); % 干净的语音
% sound(r1,fs); % 含噪的语音
sound(output,fs); % 滤波后的语音
维纳滤波器设计的函数。
function h = my_weiner_filter1( h_length,desired_signal,observed_signal )
%function h = my_weiner_filter1( h_length,desired_signal,observed_signal )
% 维纳滤波器的实现
% 输入参数
% h_length: 返回的FIR滤波器的长度
% desired_signal: 所期望的信号,训练信号,干净信号
% observed_signal: 观测到的信号
% 返回参数
% h: FIR滤波器系数
%
% 作者:qcy
% 版本:v1.0
% 时间:2016年10月29日18:50:56% 0. 定义线性方程组的大小
row_number = h_length;
col_number = row_number;% 1. Rx --> observed_signal
M = col_number;
% lags = -(N-1):(N-1);
Rx_c_full = xcorr(observed_signal);
[~,k] = max(Rx_c_full);
Rx_c = Rx_c_full(k:k+M-1);
Rx_c = Rx_c.';% 2. Rdx
Rdx_c_full = xcorr(desired_signal,observed_signal);
Rdx_c = Rdx_c_full(k:k+M-1);% 3. 求h, Ax = b
% (1) 生成自相关A阵
A = toeplitz(Rx_c,Rx_c);
b = Rdx_c;
h = A\b;end
其中,加入噪声的代码如下。
function [signal,noise]=add_noisedata(s,data,fs,fs1,snr)
s=s(:); % 把信号转换成列数据
s=s-mean(s); % 消除直流分量
sL=length(s); % 求出信号的长度if fs~=fs1 % 若纯语音信号的采样频率与噪声的采样频率不相等x=resample(data,fs,fs1); % 对噪声重采样,使噪声采样频率与纯语音信号的采样频率相同
elsex=data;
endx=x(:); % 把噪声数据转换成列数据
x=x-mean(x); % 消除直流分量
xL=length(x); % 求噪声数据长度
if xL>=sL % 如果噪声数据长度与信号数据长度不等,把噪声数据截断或补足x=x(1:sL);
elsedisp('Warning: 噪声数据短于信号数据,以补0来补足!')x=[x; zeros(sL-xL,1)];
endSr=snr;
Es=sum(x.*x); % 求出信号的能量
Ev=sum(s.*s); % 求出噪声的能量
a=sqrt(Ev/Es/(10^(Sr/10))); % 计算出噪声的比例因子
noise=a*x; % 调整噪声的幅值
signal=s+noise; % 构成带噪语音
主要是要注意采样率,还有要根据信噪比重新调整噪声幅度。
效果示意图。
训练阶段。
滤波阶段。
求解方程得到的滤波器的频率响应。
看得出来,因为是语音嘛,所以,设计出来的滤波器的性质可能更多的还是低通…
总之,这是一种在整个频率范围内的,均方意义下的最优……
最后,因为维纳滤波器的前提是,信号与噪声不相关,信号与噪声宽平稳,……
反正约束条件还是挺多的,所以,虽然对信号的噪声抑制效果,比经典滤波器的要好,
但是,为了得到更好的效果,还需要利用更先进的技术。比如,之后要讲的,自适应滤波器(adaptive filter)。
谢谢观赏。
敬请期待。
音频噪声抑制(2):维纳(Wiener)滤波器篇相关推荐
- 滤波器篇(一):利用Filter DesignGuide实现LC低通滤波器
设计目标:基于两种不同网络(LC网络以及微带网络)分别实现4GHz低通滤波器 低通滤波器设计指标: 具有最平坦响应,通带内波纹系数小于2: 截止频率为4GHz: 在8GHz处的插入损耗必须大于15dB ...
- 音频D类功放LC滤波器设计(二)
上一节我们分析了D类功放的频谱,这一节就来具体看看滤波器该怎么设计. 截止频率的确定 首先,要设计滤波器,自然需要知道截止频率设计到多少比较合适. 我们上一节分析了频谱,可以知道,频谱里面除了包含音频 ...
- 为什么D类音频功放可以免输出滤波器
简单地说就是,扬声器本身有电阻,和电感,自身就是一个滤波器. 扬声器内固有的线圈电感和扬声器来对发声频率范围内人耳所能听到的声音成份实现自然滤波,只要采用线圈电感大于30μH的扬声器就能有效还原PWM ...
- 压缩音频文件怎么弄?这篇文章告诉你怎么实现
嘿,小伙伴们,如果你需要将音频文件上传到云端或通过电子邮件发送给他人,但是文件过大而无法上传或发送,那么压缩音频文件就能够为你解决这个问题.通过使用压缩音频文件的软件,你可以将音频文件有效地压缩,并减 ...
- 分享matlab程序之——滤波器篇(高通,低通)
快毕业了,把自己写的现成的matlab函数分享给有需要的人,由于个人水平有限,写的不好请见谅,愿意拍砖的尽管拍好了.目前还不考虑读博,所以写的程序仍了可惜,所以就拿出来分享.好了不废话了,开始正题. ...
- matlab 滤波器篇
快毕业了,把自己写的现成的matlab函数分享给有需要的人,由于个人水平有限,写的不好请见谅,愿意拍砖的尽管拍好了.目前还不考虑读博,所以写的程序仍了可惜,所以就拿出来分享.好了不废话了,开始正题. ...
- 音频(六)Mel滤波器组_原理简介
为什么会产生出Mel 这种尺度的机制呢? 人耳朵具有特殊的功能,可以使得人耳朵在嘈杂的环境中,以及各种变异情况下仍能正常的分辨出各种语音: 其中,耳蜗有关键作用; 耳蜗实质上的作用相当于一个滤波器组, ...
- 立体匹配 之 代价聚合 滤波器篇
立体匹配 之代价聚合 滤波器 本文内容部分引用下面文章 https://blog.csdn.net/weixin_36558054/article/details/74832494 https://b ...
- 关于人们感知与数字视音频编码的关系入门-视觉篇01.
众所周知,视音频的数字化是为惹方便人们更好地记录视听而被人们所折腾出来的一门技术.既然主要是为惹人们而服务的,在我们的探究过程中就水到渠成地首先偏向于贴合人们所设计惹.本文主要是从生理角度上浅谈一下人 ...
最新文章
- 企业级IT运维平台的发展趋势与规划要点
- [异常笔记] zookeeper集群启动异常: Cannot open channel to 2 at election address ……
- linux系统中用户切换
- hudson linux节点,Linux 环境下搭建 Jenkins(Hudson)平台
- python的二维数组操作
- 张勇谈组织架构调整:领导者要善于“从后排把人往前拔”
- php - MySQL创建新用户并授权
- 分享一个c++ 加密算法 ,在百度贴吧找的,比较好玩
- java中为什么同步_如何在Java中同步工作
- bresenham算法画圆mfc实现_kd-tree理论以及在PCL 中的代码的实现
- python使用opencv库_python库(OpenCV的简单使用)
- Pocket Gems面经prepare: Diamond and Ruby
- ora-20011 ora-01555
- win10误删的注册表能还原吗_win10注册表删错了怎么办_win10注册表删错东西如何恢复-win7之家...
- Python爬虫爬取中国大学慕课MOOC课程的课程评价信息(讨论信息),采用selenium动态爬取方法
- 四级英语图表作文真题计算机,2016年四级作文模板之图片与图表
- E280 P0410故障修复
- 关于Matlab中Max函数的用法
- [转]Android入门基础教程
- 关于发那科工具偏移指令