【音频滤波】两个谱减法滤波的例子~如何用谱减法滤除宽带or窄带噪声?

两个谱减法滤波的例子

  • 前言
  • 示例1(宽带白噪声的滤除)
    • 频谱分析
    • 谱减法初步处理
    • 低通滤波处理
      • 数字频率
      • 低通滤波器的设计
      • 滤波结果
  • 示例2(窄带噪声的滤除)
    • 频谱分析
    • 初步处理结果
    • 最终处理结果
  • 代码
    • 下载链接
    • 示例1代码
    • 示例2代码
  • 后语

前言

首先祝大家元宵节快乐,这是在本科的时候《离散信号处理》的一个作业,今天整理硬盘发现了,发上来给大家作为谱减法的入门参考。

示例1(宽带白噪声的滤除)

频谱分析

拿到信号,第一步一般是先观察信号的频谱。
【音频滤波】两个谱减法滤波的例子~如何用谱减法滤除宽带or窄带噪声?_第1张图片
从上图可以看出,此噪声是一个宽带白噪声,幸运的是噪声并没有把有用的频谱成分淹没。

谱减法初步处理

通过观察,有用信号的频谱振幅基本都在 200 以上,所以只要截取频谱幅度大于 200 的部分,就可以基本保留原始信号的主要信息,并且可以较好地过滤掉宽带白噪声。
截取结果如下图所示。
【音频滤波】两个谱减法滤波的例子~如何用谱减法滤除宽带or窄带噪声?_第2张图片
以上初步处理结果试听后,发现声音中仍然有尖锐的声音,这可能是由上图中的 6kHz 到 8kHz 以及2kHz附近的高频噪声导致的,所以,为了滤除高频噪声,还需要使信号通过一个低通滤波器。

低通滤波处理

数字频率

数字频率即为归一化的频率,其定义为:
f d = f a / f s ∗ 2 f_d =f_a/f_s*2 fd=fa/fs2
其中, f s f_s fs表示信号的采样率,单位为(Hz); f a f_a fa为模拟频率,其最大值为采样率的一半; f d f_d fd表示模拟频率 f a f_a fa所对应的数字频率。

低通滤波器的设计

通过观察“初步处理后的频谱”,需要设置一个截止到1kHz的0.8kHz低通滤波器,因为信号的采样率为16kHz,所以数字频率分别为1kHz对应0.125,0.8kHz对应0.1。
设计出的FIR滤波器的分析如下图所示,上面的是幅频响应曲线,下面的是相频响应曲线。
【音频滤波】两个谱减法滤波的例子~如何用谱减法滤除宽带or窄带噪声?_第3张图片
观察幅频响应曲线可以发现该FIR滤波器在通带内保持平缓,在约0.125时截止。从相频响应曲线可以看到滤波器在通带内的响应具有线性相位,这点可以保证滤波时相位不失真。

滤波结果

滤波最终结果的频谱如下图所示,从图中可以看到大于1kHz的杂音都被去除了。
【音频滤波】两个谱减法滤波的例子~如何用谱减法滤除宽带or窄带噪声?_第4张图片
接下来就可以聆听一下滤波后的结果。

示例2(窄带噪声的滤除)

频谱分析

按照惯例,第一步肯定是频谱分析。
【音频滤波】两个谱减法滤波的例子~如何用谱减法滤除宽带or窄带噪声?_第5张图片
可以看到,信号被中心频率约为1.2kHz的窄带噪声所污染,同时,有用的频谱成分的幅度都在 1000 以下,所以用谱减法截取幅度在1000以下的频谱成分。

初步处理结果

初步处理结果如下图所示,截取后对音频进行试听,发现仍然有刺耳的交流成分,猜测是 1.2kHz 附近的
残留噪声在作怪,于是对信号进行二次截取。
【音频滤波】两个谱减法滤波的例子~如何用谱减法滤除宽带or窄带噪声?_第6张图片

最终处理结果

为了保留信号最重要的成分,二次截取选择的开始频率为 1kHz,截取幅度小于 450 的频谱成分。二次截取后的频谱如下图所示,此为滤波的最终结果。
【音频滤波】两个谱减法滤波的例子~如何用谱减法滤除宽带or窄带噪声?_第7张图片
接下来就可以聆听一下滤波后的结果了。

代码

示例1的主运行文件为soundHandle.m
示例2为soundHandle2.m

下载链接

GitHub:https://github.com/highskyno1/spectral-subtraction
度盘:https://pan.baidu.com/s/1LBkkCbTOAsxawiDDz9m7LA
提取码:e2pg

示例1代码

soundHandle.m

clear;
close;
[y,fs]=audioread('./处理前1.wav');
fq = fft(y);
%获取频谱的半长度
length_half = floor(length(fq)/2);
%计算数字频率
f_x = fs/2*(0:length_half-1)/length_half;
figure(1);
%观察信号的频谱
plot(f_x,abs(fq(1:length_half)));
title('原始信号的频谱');
xlabel('频率(Hz)');
ylabel('幅度');
%初始化频谱输出
fo = zeros(1,length(y));
for i = 1:1:length(y)
    if(abs(fq(i)) >= 200)
        fo(i) = fq(i);  %截取大于幅度200的频率成分
    end
end
figure(2);
%观察截取到的频谱
plot(f_x,abs(fo(1:length_half)));
title('初步处理后的频谱');
xlabel('频率(Hz)');
ylabel('幅度');
%把初步处理的结果变换回时域
yo = ifft(fo);
%把初步处理的结果进行低通滤波
%获取FIR滤波序列
h = lowPass(0.1,0.125,0.017,0.017);
%分析滤波器
figure(4);
freqz(h);
%用卷积实现滤波
yo = conv(h,yo);
yof = fft(yo);
figure(3);
%观察低通滤波的结果的频谱
plot(f_x,abs(yof(1:length_half)));
title('最终输出的频谱');
xlabel('频率(Hz)');
ylabel('幅度');
%播放并保存结果
sound(yo,fs);
audiowrite('./处理后1.wav',yo,fs);

lowPass.m

function h = lowPass(Fp,Fs,ds,dp)
%lowPass 返回按要求设计的数字FIR滤波器实现对输入信号的低通滤波
%     Fp 低通数字频率
%     Fs 通带截止数字频率
%     ds 阻带波动
%     dp 通带波动
    f = [Fp Fs];
    a = [1 0];
    dev = [dp ds];
    [N,fo,ao,w] = remezord(f,a,dev);
    h = remez(N,fo,ao,w);   %时域的滤波器
end

示例2代码

clear;
close;
[y,fs]=audioread('./处理前2.wav');
fq = fft(y);
f_len_half = floor(length(fq)/2);
f_x = fs/2*(0:f_len_half-1)/f_len_half;
figure(1);
%观察声音的频谱
plot(f_x,abs(fq(1:f_len_half)));
title('原声音信号的频谱');
xlabel('频率(Hz)');
ylabel('幅度');
%截取频谱幅度小于800的部分
fo = zeros(1,length(fq));
for i=1:1:length(fq)
    if abs(fq(i)) < 1000
        fo(i) = fq(i);
    end
end
figure(2);
plot(f_x,abs(fo(1:f_len_half)));%处理后的频谱
title('初步处理后的频谱');
xlabel('频率(Hz)');
ylabel('幅度');
%截取大于1kHz部分的幅度小于500的部分频谱
low = 30000;    %对应1kHz
fo2 = [fo(1:low),zeros(1,length(fo)-2 * low),fo(length(fo)-low+1:length(fo))];
for i=low + 1:1:length(fo)-low
    if abs(fo(i)) < 450
        fo2(i) = fo(i);
    end
end
yout = ifft(fo2);%把信号从频域返回至时域
figure(3);
yof = fft(yout);
long3 = floor(length(yof)/2);
fout = fs/2/long3*(0:long3-1);
plot(fout,abs(yof(1:long3)));
title('最终处理结果的频谱');
xlabel('频率(Hz)');
ylabel('幅度');
sound(yout,fs);
audiowrite('./处理后2.wav',yout,fs);

后语

现在还是研究生的寒假,学校3月1号开学,一开学了估计又没有时间写文章了。看到这了,不点个赞再走嘛?

你可能感兴趣的:(仿真,信号处理,源代码,信号处理,滤波,谱减法,matlab)