噪声的干扰不仅会降低语音通信的质量,而且也会使得那些基于特征参数提取的语音处理系统(如:低速率语音编码、语音识别等)性能下降,而在语音处理系统中采用抑制噪声的语音增强技术就是解决上述问题的有效途径。

谱减法的基本思路是:假设在加性噪声与短时平稳的语音信号相互独立的条件下,从带噪语音的功率谱中减去噪声功率谱,得到较为纯净的语音频谱,从而估计出原始语音。设为纯净的原始语音信号,为噪声信号,为带噪语音信号,则有


                                 

                 的傅里叶变换,对(1)式两端进行傅里叶变换,根据傅里叶变换的线性性质可以得到


                                                      

对(2)式两端取模后再平方,可得


 

可得


                     

由于相对平稳的噪声信号可认为发音前和发音期间的变化甚小,所以可以通过发音前的“寂静段”信号的功率谱来估计发音期间噪声的功率谱,从而得到原始语音功率谱的估计值为


                   

根据人耳对语音信号相位不敏感的特点,可以用噪声信号的相位来代替估计之后语音信号的相位,进行傅里叶逆变换,即可得到增强后语音的时域信号。

谱减法是以寂静段统计的平均噪声方差代替了当前点的噪声频谱分量,而实际上噪声随机变化的幅度是比较大的。若某点的噪声分量较大,相减后噪声仍被保留了一大部分,就形成了节奏性起伏的类似音乐的噪声。

为解决这一问题,在原有的谱减法基础上引入过减系数k进行改进, 形式如下


                   

由(6)式看出,通过调整系数k,可以有意识多减去或者少减去一些噪声,更好地突出语音功率谱。但是,过减系数k如何取值才能比较好地控制被减噪声量,又成为一个新的问题。

下面是最简单的谱减算法的源代码


function specsub_simple3(mix) 
    [wav,fs,bit] =wavread(['E:\A_ebm_pitch1\test\0db\cocktail\F01A100.wav']);
    x = wav;
    x = x - mean(x);%减去直流分量
    N = length(x);  %采样点的个数
    winsize = 320;   shiftsize = 160;  frame=ceil((N)/(shiftsize));%帧长 帧移  帧数 
    window = hamming(winsize);
    winc = getframe(x,winsize,shiftsize,window);%获得每一帧
    sf = fft(winc);%fft
    ang1 = angle(sf)';%相位
    power = abs(sf).*abs(sf);%能量
    power = power';

     threshold = sum( (sum(power(2:5,:))) )/(1*winsize ); %阈值  
     power = power - threshold;
     power(find( power < 0)) = 0;
     
     power = sqrt(power);
     ima = power.*exp(j*ang1);%求频域部分
     for i=1:frame
        out1(i,:) = real(ifft(ima(i,:)))./hamming(winsize)';
     end   
    zong = out1(1,:)';
    jiewei = winsize;
    for i=2:frame  %将一系列的帧组合还原
        zong(jiewei-shiftsize+1:jiewei) = (zong(jiewei-shiftsize+1:jiewei)+out1(i,1:shiftsize)')/2;
        jiewei = jiewei +winsize -shiftsize;
        zong = [zong;out1(i,shiftsize+1:end)'];
    end

    sound(zong,fs);
    sound(x,fs);
    
        function winc = getframe(wav,winsize,shiftsize,window)
        slen = length(wav); %原始语音文件有多少个点
        numframe = ceil(slen/shiftsize); %一共有多少帧
        for n=1:numframe
            st = (n-1)*shiftsize;
            ed = min(st+winsize,slen);
            winc(1:ed-st,n) = wav(st+1:ed);
            winc(:,n) = winc(:,n).*window;
        end


Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐