分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow
也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!
本文是音频处理的朋友icoolmedia(QQ:314138065)的投稿。各位做视音频技术朋友如果好的原创技术文章并希望通过我的博客分享给大家,也欢迎投稿到我的邮箱:[email protected],我会选择内容合适的文章注明作者及联系方式后进行发布。希望通过这种方式帮助大家结交更多的同道中人~
谱减算法为最早的语音降噪算法之一,它的提出,基于一个简单的原理:假设语音中的噪声只有加性噪声,只要将带噪语音谱减去噪声谱,就可以得到纯净语音幅度。这么做的前提是噪声信号是平稳的或者缓慢变化的。
得到纯净信号的幅度谱后,可以结合带噪语音相位(近似带替纯净语音相位),从而得到近似的纯净语音,可以这么做的原因是因为语音信号相位不会对语音可懂度造成影响。按上述所示,如果我们设y(n)为受噪声污染的信号,则y(n)由纯净语音信号x(n)和加性噪声d(n)组成,即:y(n)=X(n)+d(n)。其傅里叶变换后表示为:Y(ω)=X(ω)+D(ω),或写为:
X(ω) = Y(ω) – D(ω),如果用功率谱表示可以写为:
这里 被称为交叉项,我们假定d(n)具有0均值,并且与x(n)不相关,则交叉项为0,上述公式简化为:
或写为:
function specsub(filename,outfile)if nargin < 2 fprintf('Usage: specsub noisyfile.wav outFile.wav \n\n'); return;end[x,fs,nbits] = wavread(filename);len = floor(20*fs/1000); % Frame size in samplesif rem(len,2) == 1, len=len+1; end;PERC = 50; % window overlap in percent of frame sizelen1 = floor(len*PERC/100);len2 = len-len1; Thres = 3; % VAD threshold in dB SNRseg Expnt = 2.0; % power exponentbeta = 0.002;G = 0.9;win = hamming(len);winGain = len2/sum(win); % normalization gain for overlap+add with 50% overlap% Noise magnitude calculations - assuming that the first 5 frames is noise/silencenFFT = 2*2^nextpow2(len);noise_mean = zeros(nFFT,1);j=1;for k = 1:5 noise_mean = noise_mean+abs(fft(win.*x(j:j+len-1),nFFT)); j = j+len;endnoise_mu = noise_mean/5;%--- allocate memory and initialize various variablesk = 1;img = sqrt(-1);x_old = zeros(len1,1);Nframes = floor(length(x)/len2)-1;xfinal = zeros(Nframes*len2,1);%========================= Start Processing ===============================for n = 1:Nframes insign = win.*x(k:k+len-1); % Windowing spec = fft(insign,nFFT); % compute fourier transform of a frame sig = abs(spec); % compute the magnitude %save the noisy phase information theta = angle(spec); SNRseg = 10*log10(norm(sig,2)^2/norm(noise_mu,2)^2); if Expnt == 1.0 % 幅度谱 alpha = berouti1(SNRseg); else alpha = berouti(SNRseg); % 功率谱 end %&&&&&&&&& sub_speech = sig.^Expnt - alpha*noise_mu.^Expnt; diffw = sub_speech - beta*noise_mu.^Expnt; % 当纯净信号小于噪声信号的功率时 % beta negative components z = find(diffw <0); if~isempty(z) sub_speech(z) = beta*noise_mu(z).^Expnt; % 用估计出来的噪声信号表示下限值 end % --- implement a simple VAD detector -------------- if (SNRseg < Thres) % Update noise spectrum noise_temp = G*noise_mu.^Expnt+(1-G)*sig.^Expnt; % 平滑处理噪声功率谱 noise_mu = noise_temp.^(1/Expnt); % 新的噪声幅度谱 end% flipud函数实现矩阵的上下翻转,是以矩阵的“水平中线”为对称轴%交换上下对称元素 sub_speech(nFFT/2+2:nFFT) = flipud(sub_speech(2:nFFT/2)); x_phase = (sub_speech.^(1/Expnt)).*(cos(theta)+img*(sin(theta))); % take the IFFT xi = real(ifft(x_phase)); % --- Overlap and add --------------- xfinal(k:k+len2-1)=x_old+xi(1:len1); x_old = xi(1+len1:len); k = k+len2;endwavwrite(winGain*xfinal,fs,16,outfile);function a = berouti1(SNR)if SNR >= -5.0 & SNR <= 20 a = 3-SNR*2/20;else if SNR < -5.0 a = 4; end if SNR > 20 a = 1; endendfunction a = berouti(SNR)if SNR >= -5.0 & SNR <= 20 a = 4-SNR*3/20; else if SNR < -5.0 a = 5; end if SNR > 20 a = 1; endend
1> 双频带谱减法。通过将带噪语音能量与某一阈值进行比较,把语音帧分为浊音和清音。对于浊音帧,用算法确定一个截止频率,在该截止频率之上,语音被认为是随机信号。浊音段则通过滤波分为两个频带,一个频带位于截止频率之下(低通滤波后的语音),另外一个频带高于截止频率(高通滤波后的语音)。然后对低通和高通后的语音信号使用不同的算法进行处理。对低通语音部分在短时傅立叶变换的基础上使用过减算法,对于高通部分以及清音段,使用Thomson的多窗谱估计器取代FFT估计器。主要目的在于减小高频部分的频谱值的波动。具体请参考论文:Adaptive two-band spectral subtraction with multi-window spectral estimation
2> 双激励语音模型法,该算法把语音分为两个独立的组成部分--浊音分量和清音分量。也就是说,语音由这两个分量的和来表示(注意不同于将语音分为浊音段和清音段)。浊音分量的分析是基于对基音频率和谐波幅度的提取。然后从带噪语音谱中减去浊音谱就得到了清音谱。然后使用一个双通道系统,基中一个包括改进的维纳滤波器,被用于增强清音谱。最终增强的语音由增强后的浊音分量和清音分量求和得到。具体请参考论文:Speech enhancement using the dual excitation speech model
3> 还有一种基于浊音、清音的谱减算法,在该算法中语音帧首先根据能量和过零率被划分为浊音和清音。然后将带噪语音谱与锐化函数进行卷积,清音的频谱就会被锐化(用锐化函数进行镨锐化的目的在于增加谱对比度,即在抑制谱谷的同时使谱峰更加突出)。具体请参考论文:Spectral subtraction based on phonetic dependency and masking effects