【语音处理】人耳掩蔽效应的语音增强算法信噪比计算【Matlab 336期】

一、简介

人耳能够在寂静的环境中分辨出轻微的声音,但是在嘈杂的环境里,这些轻微的声音就会被杂音所淹没。这种由于第一个声音的存在而使得第二个声音听阈提高的现象就称为掩蔽效应。第一个声音称为掩蔽声,第二个声音称为被掩蔽声,第二个声音听阈提高的数量称为掩蔽效应。

掩蔽效应发生时,一般以不同性质的声音作为掩蔽声,比如纯音、复音、噪声等。研究还发现,当掩蔽声和被掩蔽声不同时到达时,也会发生掩蔽,这种掩蔽现象称为非同时掩蔽。掩蔽声作用在被掩蔽声之前所发生的掩蔽,称为前掩蔽;掩蔽声作用在被掩蔽声之后所发生的掩蔽,称为后掩蔽。

听觉的掩蔽效应一般是用掩蔽声存在时的新的听阈曲线来表示,因此这里涉及的被掩蔽声一般是指纯音。掩蔽声存在的听阈称为掩蔽阈。

1、纯音的掩蔽

纯音是最简单的一种声音,下图反映的是1KHz,80dB纯音为掩蔽声时,测得的纯音的听阈随频率变化的特性。图中,虚线为听阈的曲线,实线为掩蔽阈曲线,文字表示了在不同区域所能听到的声音。

在700Hz以下,和9KHz以上的频率范围,纯音的听阈几乎不受掩蔽声的影响。

在700Hz到9KHz之间,纯音的听阈明显提高,越接近掩蔽声的频率,掩蔽量就越大。

纯音的掩蔽基本符合以下几个规律:低音容易掩蔽高音,高音较难掩蔽低音;频率相近的纯音容易互相掩蔽;提高掩蔽声的声压级时,掩蔽阈会提高,而且被掩蔽的频率范围会扩展。

2、复音的掩蔽

大多数声音是以复音的形式存在的。乐音一般是由一个基频和多个谐频组成的,音色主要取决于其谐频结构。复音的掩蔽范围主要是由复音所包含的频率成分决定,在每个所包含的频率附近都有产生一个最大的掩蔽量,当频率小于复音所包含的最小频率或大于其所包含的最大频率时,掩蔽效应逐渐减弱,并且掩蔽阈趋近于无掩蔽声时的听阈。

3、窄带噪声的掩蔽

窄带噪声通常是指带宽等于或者小于听觉临界频带的噪声。用纯音做为掩蔽声时,由于存在拍音和差音,掩蔽阈的测量比较困难。如果用窄带白噪声作为掩蔽声,测量较为容易,结果比较可靠。窄带噪声的掩蔽特性和纯音的掩蔽特性十分相似,只是曲线的左右不对称特性没有那么强。下图显示的是,以不同中心频率的窄带噪声作为掩蔽声时的听阈曲线,窄带噪声的中心频率分别为0.25KHz,1KHz,4KHz。

3、非同时掩蔽效应

声音信号大多数时候时非稳态的瞬时信号,声压级随着时间变化很快,即强音后面跟着弱音,弱音后面又可能跟着强音。比较强的声音往往会掩蔽随后到来的较弱音。

一般来说,同时掩蔽效应最强,掩蔽量最大;前掩蔽效应要大于后掩蔽效应,前掩蔽发生作用的时间远大于后掩蔽的时间。掩蔽声发生在测试信号之前的掩蔽现象容易理解,因为听觉具有记忆功能。而由于听觉对声音的感觉需要一个建立过程,所以就会有一定的延迟,而听觉对于较强声音感觉的建立要快于对较弱声音感觉的建立,所以存在后掩蔽的现象。

根据掩蔽效应的原理,才衍生出电声技术指标中的SNR(信号噪声比),以及THD(谐波失真)等。当噪声或者失真保持在一定范围内的时候,对听觉效果没有影响。

二、源代码

clc;
clear all;
[x,fs,nbits]=wavread('beijing.wav');
y=awgn(x,0,'measured');%加噪
function output=sub_rener(Signal,fs)

L=size(Signal,1);

W=1024;
SP=0.5;
OverLapNum=W*SP;
Window=hamming(W);
y=segment(Signal,W,SP,Window);

FrameNum=size(y,2);
ffty=fft(y,W);

Yabs=abs(ffty);
Yangle=angle(ffty);


 %%%%24个Bark频率群%%%%
k=0;
for f=21:fs
    k=k+1;
    z(k)=ceil(13*atan(0.76*f/1000)+3.5*atan((f/7500)^2));    
end 

BarkNum=18;%实验中使用的音频信号其采样频率为8k

va=20;
dz=diff(z);
fz=find(dz==1)+va;

% %%%%扩展函数B%%%% 
i=1:1:BarkNum;
delta=abs(repmat(i',1,BarkNum)-repmat(i,BarkNum,1));
S=10.^((15.81+7.5.*(delta+0.474)-17.5.*(1+(delta+0.474).^2).^(1/2))./10);%~db

DC_Gain=S*ones(BarkNum,1); %~db

%%%%每个bark中的能量%%%%
Nz=fix(fz.*W/fs);
Nz(BarkNum)=W/2+1;
start=1;
B=zeros(BarkNum,FrameNum);
for i=1:BarkNum;
    B(i,:)=sum(Yabs(start:Nz(i),:).^2);
    start=Nz(i)+1;
end %~db

%%%%算术/几何平均值%%%%
Py=Yabs(1:W/2+1,:).^2;

Am=sum(Py)./(W/2+1);%~db
half=fix(W/4)+1;
Gm=prod(Py(1:half,:)).^(1/(W/2+1)).*prod(Py(half+1:end,:)).^(1/(W/2+1));%~db
SFM=10.*log10(Gm./Am);%db
SFMmax=-60;%db


C=zeros(BarkNum,FrameNum);

for i=1:BarkNum
    Btemp=repmat(B(i,:),BarkNum,1);
    C(i,:)=S(i,:)*Btemp; %~db
end

Alpha=max(min(SFM./SFMmax,1),0);

%%%%激励-掩蔽阈O(i)%%%%
i=1:1:BarkNum;
O=Alpha'*(i+9)+5.5;
O=O';%db

%%%实际掩蔽阈T(i)%%%%
TT=10.^(log10(C)-O./10);%~db


%%%%%%%%%%%%%%%%%%%%

T=TT./DC_Gain(:,ones(1,FrameNum));%~db
%%%%%%%%%%%%%%%%%%%%%

w=fz(1:BarkNum);
Tqq=10.^((3.64.*(w./1000).^(-0.8)-6.5.*exp(-0.6.*(w./1000-3.3).^2)+(10^(-3)).*(w./1000).^4)./10);
Tq=repmat(Tqq',1,FrameNum);

Tfinal=max(Tq,T);

%减参数aw bw
AlphaMin=1;AlphaMax=6;
BetaMin=0;BetaMax=0.02;
Alphaw=zeros(BarkNum,FrameNum);
Betaw=zeros(BarkNum,FrameNum);

Tmin=repmat(min(Tfinal),BarkNum,1);
Tmax=repmat(max(Tfinal),BarkNum,1);

Alphaw(:,:)=AlphaMin;
Betaw(:,:)=BetaMin;

    
index=Tfinal>=Tmax;
Alphaw(index)=AlphaMax;
Betaw(index)=BetaMax;
    
index=(Tfinal>Tmin)&(Tfinal<Tmax);
Alphaw(index)=(AlphaMax.*(Tmax(index)-Tfinal(index))+AlphaMin.*(Tfinal(index)-Tmin(index)))...
        ./(Tmax(index)-Tmin(index));
Betaw(index)=(BetaMax.*(Tmax(index)-Tfinal(index))+BetaMin.*(Tfinal(index)-Tmin(index)))...
        ./(Tmax(index)-Tmin(index));


start=1;
Alpha=zeros(W/2+1,FrameNum);
Beta=zeros(W/2+1,FrameNum);


for i=1:BarkNum
    Alpha(start:Nz(i),:)=repmat(Alphaw(i,:),Nz(i)-start+1,1);
    Beta(start:Nz(i),:)=repmat(Beta(i,:),Nz(i)-start+1,1);
    start=Nz(i)+1;
end

    

Gamma=3;

Yabs=Yabs(1:W/2+1,:);

G=zeros(W/2+1,FrameNum);

NoiseLength=9;
NIS=20;
N=mean(Yabs(:,1:NIS),2);
NoiseCounter=0;
for i=1:FrameNum
    [~, SpeechFlag, NoiseCounter, Dist]=vad(Yabs(:,i),N,NoiseCounter); %Magnitude Spectrum Distance VAD
    if SpeechFlag==0
        N=(NoiseLength*N+Yabs(:,i))/(NoiseLength+1); %Update and smooth noise
    end
    for k=1:W/2+1
        if N(i)^2>Yabs(k,i)^2
            G(k,i)=0;
        else
            if ((N(i)/Yabs(k,i))^2)<(1/(Gamma.*Alpha(k,i)+Beta(k,i)))
                G(k,i)=(1-Gamma.*Alpha(k,i).*( N(i)./Yabs(k,i) ).^2).^(1/2);
            else
                G(k,i)=(Beta(k,i).*(N(i)./Yabs(k,i)).^2).^(1/2);
            end
        end
    end
end


S=Yabs.*G;

Sfinal=[S;S(W/2:-1:2,:)];
j=sqrt(-1);

Yfinal=Sfinal.*exp(j.*Yangle);


output=zeros(1,L);
hamwin=zeros(1,L);
for i=1:FrameNum   
    output(1+(i-1)*OverLapNum:W+(i-1)*OverLapNum)=...
    output(1+(i-1)*OverLapNum:W+(i-1)*OverLapNum)+(real(ifft(Yfinal(:,i))))';
    hamwin(1+(i-1)*OverLapNum:W+(i-1)*OverLapNum)=...
    hamwin(1+(i-1)*OverLapNum:W+(i-1)*OverLapNum)+Window';
end
for i=1:L
    if hamwin(i)==0
        output(i)=0;
    else
        output(i)=output(i)/hamwin(i);
    end
end
output=output';

function [NoiseFlag, SpeechFlag, NoiseCounter, Dist]=vad(signal,noise,NoiseCounter,NoiseMargin,Hangover)

%[NOISEFLAG, SPEECHFLAG, NOISECOUNTER, DIST]=vad(SIGNAL,NOISE,NOISECOUNTER,NOISEMARGIN,HANGOVER)
%Spectral Distance Voice Activity Detector
%SIGNAL is the the current frames magnitude spectrum which is to labeld as
%noise or speech, NOISE is noise magnitude spectrum template (estimation),
%NOISECOUNTER is the number of imediate previous noise frames, NOISEMARGIN
%(default 3)is the spectral distance threshold. HANGOVER ( default 8 )is
%the number of noise segments after which the SPEECHFLAG is reset (goes to
%zero). NOISEFLAG is set to one if the the segment is labeld as noise
%NOISECOUNTER returns the number of previous noise segments, this value is
%reset (to zero) whenever a speech segment is detected. DIST is the
%spectral distance. 
%Saeed Vaseghi
%edited by Esfandiar Zavarehei
%Sep-04

if nargin<4
    NoiseMargin=3;
end
if nargin<5
    Hangover=8;
end
if nargin<3
    NoiseCounter=0;
end

三、运行结果

在这里插入图片描述

四、备注

完整代码或者代写添加QQ912100926
往期回顾>>>>>>
【信号处理】基于GUI界面之处理录音与音频【Matlab 123期】
【信号处理】CDR噪声和混响抑制【含Matlab源码 198期】
【信号处理】最小二乘法解决稀疏信号恢复问题【Matlab 199期】
【信号处理】遗传算法的VST混响【Matlab 200期】
【信号处理】HMM的睡眠状态检测【Matlab 201期】
【信号处理】小波变换的音频水印嵌入提取【Matlab 202期】
【信号处理】ICA算法信号分离【Matlab 203期】
【信号处理】基于GUI界面的脉搏信号之脉率存档【Matlab 204期】
【信号处理】基于GUI界面的虚拟信号发生器(各种波形)【Matlab 205期】
【信号处理】基于GUI界面信号发生器之电子琴【Matlab 206期】
【信号处理】数字电子琴设计与实现【Matlab 207期】
【雷达通信】雷达数字信号处理【Matlab 214期】
【雷达通信】线性调频(LFM)脉冲压缩雷达仿真【Matlab 215期】
【雷达通信】距离多普勒(RD)、CS、RM算法的机载雷达成像【Matlab 216期】
【雷达通信】《现代雷达系统分析与设计》【Matlab 217期】
【语音处理】基于matlab GUI语音信号处理平台【含Matlab源码 218期】
【语音采集】基于GUI语音信号采集【Matlab 219期】
【语音调制】基于GUI语音幅度调制【Matlab 220期】
【语音合成】基于GUI语音合成【Matlab 221期】
【语音识别】基于GUI语音基频识别【Matlab 222期】
【语音加密】基于GUI语音信号加密解密【Matlab 223期】
【信号处理】小波变换的语音增强【Matlab 224期】
【信号处理】基于GUI语音去噪【Matlab 225期】
【语音增强】基于GUI维纳滤波之语音增强【Matlab 226期】
【音频处理】基于GUI语音信号处理【含Matlab 227期】
【雷达通信】基于GUI雷达定位【Matlab 244期】
【雷达通信】基于GUI雷达脉冲压缩【Matlab 245期】
【雷达通信】基于GUI雷达定位模拟【Matlab 246期】
【雷达通信】SVM识别雷达数据【Matlab 247期】
【信息处理】GUI数字波束的算法库【Matlab 249期】
【通信】OFDM-MIMO通信建模与仿真【Matlab 250期】
【通信】OFDM仿真【Matlab 251期】
【信号处理】窗函数法的FIR数字滤波器设计【Matlab 252期】
【通信】FIR低通数字滤波器设计【Matlab 253期】
【通信】FIR IIR数字滤波器设计【Matlab 254期】
【调制信号】基于GUI数字调制信号仿真【Matlab 255期】
【通信】扩频通信系统设计【Matlab 256期】
【通信】多径衰落信道的仿真【Matlab 257期】
【语音识别】基于BP神经网络的语音情感识别【Matlab 258期】
【信号处理】音频水印嵌入与提取【Matlab 259期】
【音频水印】小波变换的量化音频数字水印【Matlab 260期】
【语音去噪】低通和自适应滤波去噪【Matlab 261期】
【信号处理】8级m序列【Matlab 262期】
【情感识别】基于GUI语音情感分类识别【Matlab 263期】
【信号处理】FIR与IIR滤波器低通、高通、带通设计【Matlab 273期】
【语音处理】语音信号的预处理【Matlab 274期】
【语音识别】傅立叶变换0-9的数字语音识别【含Matlab 333期】
【语音识别】基于GUI DTW的0-9数字语音识别【Matlab 334期】
【语音播放】基于GUI MP3设计【Matlab 335期】

猜你喜欢

转载自blog.csdn.net/m0_54742769/article/details/114298866