简单记录一下最近复习《信号与系统》的时候用 MATLAB 设计语音滤波器的过程。

首先利用自带的录音机录下一段语音信号,运用 MATLAB 对语音进行频域分析。

rec_sound(3,44100,'voice_rec') %时间 采样率 文件名

[x1,fs]=audioread('voice_rec.wav'); %读取语音信号的数据
% sound(x1,fs); %播放语音信号
y1=fft(x1,1024);  %对信号做 1024 点 FFT 变换
f=fs*(0:511)/1024;
figure(1);
plot(x1)  %做原始语音信号的时域图形
title('原始语音信号');xlabel('time n');ylabel('fuzhi n');
figure(2);freqz(x1) %绘制原始语音信号的频率响应图
title('频率响应图')
figure(3);
subplot(2,1,1);
plot(abs(y1(1:512))) %做原始语音信号的 FFT 频谱图
title('原始语音信号 FFT 频谱');
subplot(2,1,2);
plot(f,abs(y1(1:512)));
title('原始语音信号频谱')
xlabel('Hz');ylabel('fuzhi');

之后利用 ellipord 函数设计 IIR 带通滤波器,所取的具体性能指标如下,其中最关键的参数就是通带阻带的截止频率。需要注意的是,滤波器的性能一定是有理论上限的,需要根据不同的采样率等进行调整,提高采样率的时候适当放松性能要求,否则会出现异常。

Fp1=1000; Fp2=2000; %通带截止频率上下限
Fs1=800; Fs2=2200; %阻带截止频率上下限
Ft=44100; %采样率
As=30; Ap=1; %通带边衰减 DB 值和阻带边衰减 DB 值
wp=[2*pi*Fp1/Ft,2*pi*Fp2/Ft];
ws=[2*pi*Fs1/Ft,2*pi*Fs2/Ft];
[n,wn]=ellipord(wp,ws,Ap,As,'s');
[b,a]=ellip(n,Ap,As,wn,'s');
[B,A]=bilinear(b,a,1);
[h,w]=freqz(B,A);
plot(w*Ft/pi/2,abs(h));
title('IIR 带通滤波器');
xlabel('频率');
ylabel('幅度');
grid on;

将滤波器应用到语音信号后的效果如下。可以看到只有对应频率带内的信号得到了保留,阻带的信号都被大幅度衰减,实际听起来的声音少了很多高频的信号,非常沉闷。

% 滤波效果
[x1,fs]=audioread('voice_rec.wav');

f1=filter(B,A,x1);
figure
subplot(2,1,1)
plot(t,x1)                %画出滤波前的时域图
title('滤波前的时域波形');
subplot(2,1,2)
plot(t,f1);               %画出滤波后的时域图
title('滤波后的时域波形');
sound(f1,fs);             %播放滤波后的信号
F0=fft(f1,1024);
f=fs*(0:511)/1024;

figure
y2=fft(x1,1024);
subplot(2,1,1);
plot(f,abs(y2(1:512)));          %画出滤波前的频谱图
title('滤波前的频谱')
xlabel('Hz');
ylabel('幅值');
axis([0 10000 0 0.3]);
subplot(2,1,2)
F1=plot(f,abs(F0(1:512)));     %画出滤波后的频谱图
title('滤波后的频谱')
xlabel('Hz');
ylabel('幅值');
axis([0 10000 0 0.3]);


还可以给原始的语音信号加上一个高频余弦噪声,之后再使用滤波器进行滤波,这样可以看到很明显的效果。

[x1,fs]=audioread('voice_zxc.wav');
t=0:1/fs:(size(x1)-1)/fs; % 时间轴
Au=0.3;
d=[Au*cos(2*pi*10000*t)]';
x2=x1+d;                  % 叠加噪声
wp=0.25*pi;
ws=0.3*pi;
Rp=1;
Rs=15;

参考资料

  1. Matlab:语音信号处理与滤波