1 同态处理
信号的同态处理也称同态滤波。大概步骤为:
f(x,y)→ln→DFT→H(u,v)→(DFT)-1→exp→g(x,y)
虽然,一般用于图像处理。但是,博主将同态滤波用于语音信号的滤波。直接上程序吧
clc;clear
%%
filedir=[]; % 指定文件路径
filename='bluesky3.wav'; % 指定文件名
fle=[filedir filename] % 构成路径和文件名的字符串
[xx,fs]=audioread(fle); % 读入数据文件
xx=xx-mean(xx); % 消除直流分量
x=xx/max(abs(xx)); % 幅值归一化
SNR=5; % 设置SNR
I=Gnoisegen(x,SNR); % 叠加噪声
N=length(x); % 信号长度
time=(0:N-1)/fs; % 设置时间
%%
%同态滤波
[M,N]=size(I);
rL=0.2;
rH=7.7;%可根据需要效果调整参数
c=2;
d0=10;
I1=log(I+1);%取对数
FI=fft2(I1);%傅里叶变换
n1=floor(M/2);
n2=floor(N/2);
for i=1:M
for j=1:N
D(i,j)=((i-n1).^2+(j-n2).^2);
H(i,j)=(rH-rL).*(exp(c*(-D(i,j)./(d0^2))))+rL;%高斯同态滤波
end
end
I2=ifft2(H.*FI);%傅里叶逆变换
output=real(exp(I2))-1;
%%
% 作图
subplot 311; plot(time,xx,'k'); ylabel('幅值')
ylim([-1 1 ]); title('原始语音信号');
subplot 312; plot(time,I,'k'); ylabel('幅值')
ylim([-1 1 ]); title('带噪语音信号');
subplot 313; plot(time,output,'k');
ylim([-1 1 ]); title('同态滤波输出语音信号');
xlabel('时间/s'); ylabel('幅值')
结果
当语音信号加入信噪比为5的高斯白噪声之后,得到了带噪语音信号,经过同态滤波之后,虽然达不到完全滤波,但是跟带噪语音相比,达到了降噪效果。这里,博主并未对语音信号进行分帧,之前试过,效果都差不多,最后还需要把分帧后的信号进行整合。语音信号与图像信号不同之处在于前者是一维,后者是二维。博主之前从电影上面剪下一段语音,来进行语音处理,但是发现无法处理。这是因为剪下来的语音的双声道,而我们一般处理的语音信号都是单声道,所以博主最后用Goldwave软件,将双声道语音变为单声道。
2 倒谱分析
(1)
序列c(n)是x(n)对数幅值谱的逆傅立叶变换,称做倒频谱,简称倒谱。这里,c(n)的量纲是Quefrency,又被称做倒频,它实际的单位还是时间的单位。
例子:从su1.txt中读入语音信号,信号采样频率是16000Hz,要求如下:
a.按照公式(1)计算信号的倒谱;
b.把语音的声门激励信号和声道冲激响应分离,分别计算相应的频谱。
clear all; clc; close all;
y=load('su1.txt'); % 读入数据
fs=16000; nfft=1024; % 采样频率和FFT的长度
time=(0:nfft-1)/fs; % 时间刻度
figure(1), subplot 211; plot(time,y,'k'); % 画出信号波形
title('信号波形'); axis([0 max(time) -0.7 0.7]);
ylabel('幅值'); xlabel(['时间/s' 10 '(a)']); grid;
figure(2)
nn=1:nfft/2; ff=(nn-1)*fs/nfft; % 计算频率刻度
Y=log(abs(fft(y))); % 按式(1)取实数部分
subplot 211; plot(ff,Y(nn),'k'); hold on; % 画出信号的频谱图
z=ifft(Y); % 按式(1)求取倒谱
figure(1), subplot 212; plot(time,z,'k'); % 画出倒谱图
title('信号倒谱图'); axis([0 time(512) -0.2 0.2]); grid;
ylabel('幅值'); xlabel(['倒频率/s' 10 '(b)']);
mcep=29; % 分离声门激励脉冲和声道冲激响应
zy=z(1:mcep+1);
zy=[zy' zeros(1,1000-2*mcep-1) zy(end:-1:2)']; % 构建声道冲激响应的倒谱序列
ZY=fft(zy); % 计算声道冲激响应的频谱
figure(2), % 画出声道冲激响应的频谱,用灰线表示
line(ff,real(ZY(nn)),'color',[.6 .6 .6],'linewidth',3);
grid; hold off; ylim([-4 5]);
title('信号频谱(黑线)和声道冲激响频谱(灰线)')
ylabel('幅值'); xlabel(['频率/Hz' 10 '(a)']);
ft=[zeros(1,mcep+1) z(mcep+2:end-mcep)' zeros(1,mcep)]; % 构建声门激励脉冲的倒谱序列
FT=fft(ft); % 计算声门激励脉冲的频谱
subplot 212; plot(ff,real(FT(nn)),'k'); grid;% 画出声门激励脉冲的频谱
title('声门激励脉冲频谱')
ylabel('幅值'); xlabel(['频率/Hz' 10 '(b)']);
结果如下:
这里,博主想重点说一下以下三行程序。
mcep=29;
zy=[zy' zeros(1,1000-2*mcep-1) zy(end:-1:2)']; % 构建声道冲激响应的倒谱序列(预加重)
ft=[zeros(1,mcep+1) z(mcep+2:end-mcep)' zeros(1,mcep)]; % 构建声门激励脉冲的倒谱序列(预加重)
function ccc=mfcc_m(x,fs,p,frameSize,inc)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% function ccc=mfcc_m(x);
%对输入的语音序列x进行MFCC参数的提取,返回MFCC参数和一阶
%差分MFCC参数,Mel滤波器的个数为p,采样频率为fs
%对x每frameSize点分为一帧,相邻两帧之间的帧移为inc
% fft变换的长度为帧长
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 按帧长为frameSize,Mel滤波器的个数为p,采样频率为fs
% 提取Mel滤波器参数,用海明窗函数
bank=melbankm(p,frameSize,fs,0,0.5,'m');
% 归一化mel滤波器组系数
bank=full(bank);
bank=bank/max(bank(:));
% DCT系数,12*p
for k=1:12
n=0:p-1;
dctcoef(k,:)=cos((2*n+1)*k*pi/(2*p));
end
% 归一化倒谱提升窗口
w = 1 + 6 * sin(pi * [1:12] ./ 12);
w = w/max(w);
% 预加重滤波器
xx=double(x);
xx=filter([1 -0.9375],1,xx);
% 语音信号分帧
xx=enframe(xx,frameSize,inc);
n2=fix(frameSize/2)+1;
% 计算每帧的MFCC参数
for i=1:size(xx,1)
y = xx(i,:);
s = y' .* hamming(frameSize);
t = abs(fft(s));
t = t.^2;
c1=dctcoef * log(bank * t(1:n2));
c2 = c1.*w';
m(i,:)=c2';
end
%差分系数
dtm = zeros(size(m));
for i=3:size(m,1)-2
dtm(i,:) = -2*m(i-2,:) - m(i-1,:) + m(i+1,:) + 2*m(i+2,:);
end
dtm = dtm / 3;
%合并mfcc参数和一阶差分mfcc参数
ccc = [m dtm];
%去除首尾两帧,因为这两帧的一阶差分参数为0
ccc = ccc(3:size(m,1)-2,:);
%
% pr3_3_2
clear all; clc; close all;
[x1,fs]=audioread('s1.wav'); % 读入信号s1-\i1\
x3=audioread('a1.wav'); % 读入信号a1-\a1\
wlen=200; % 帧长
inc=80; % 帧移
x1=x1/max(abs(x1)); % 幅值归一化
x3=x3/max(abs(x3));
% 计算/i1/与/a1/之间的匹配比较
[Dcep,Ccep1,Ccep2]=mel_dist(x1,x3,fs,16,wlen,inc);
figure(2)
plot(Ccep1(3,:),Ccep2(3,:),'k+'); hold on
plot(Ccep1(7,:),Ccep2(7,:),'kx');
plot(Ccep1(12,:),Ccep2(12,:),'k^');
plot(Ccep1(16,:),Ccep2(16,:),'kh');
legend('第3帧','第7帧','第12帧','第16帧')
xlabel('信号x1');ylabel('信号x3')
axis([-12 12 -12 12]);
line([-12 12],[-12 12],'color','k','linestyle','--');
title('/i1/与/a1/之间的MFCC参数匹配比较')