⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 subspec_magic.m

📁 基于谱减法的语音增强程序
💻 M
字号:
function subspec_magic(a,b);
%经典谱减法  语音增强程序
% 07.12.20  magic

[filename,pathname]=uigetfile('*.wav','请选择语音文件:');
[wavin,fs,nbits]=wavread([pathname filename]);

%基音周期最大为20ms,为使ifft还原后语音失真尽量小,帧长至少要为基音周期的2倍
%根据fs选择帧长:
switch fs
    case 8000
        frame_len=320;step_len=160;
    case 10000
        frame_len=400;step_len=200;
    case 12000
        frame_len=480;step_len=240;
    case 16000
        frame_len=640;step_len=320;
    case 44100
        frame_len=1800;step_len=900;
    otherwise
        frame_len=1800;step_len=900;
end;
inframe=(ENFRAME(wavin,frame_len,step_len))';   %分帧
frame_num=size(inframe,2);          %求帧数
window=hamming(frame_len);          %定义汉明窗
% window=boxcar(frame_len);           %定义矩形窗

%分别对每帧fft,求幅值,求相角
for i=1:frame_num;
    fft_frame(:,i)=fft(window.*inframe(:,i));
    abs_frame(:,i)=abs(fft_frame(:,i));
    ang_frame(:,i)=angle(fft_frame(:,i));
end;

%相邻3帧平滑
abs_frame_f=abs_frame;
for i=2:(frame_num-1);
    abs_frame_f(:,i)=mean(abs_frame(:,(i-1):(i+1)),2);
end;
abs_frame=abs_frame_f;

%取前20帧,求平均,做为噪声幅值
abs_noise=mean(abs_frame(:,1:20),2);

%对前20帧求最大残余噪声
res_noise=max(abs_frame(:,1:20)-abs_noise*ones(1,20),[],2);

%谱减运算,可适当调节a,b的值来获取合适的结果
%(sub_frame=abs_frame^a-b*abs_noise^a)
if a==1
     for i=1:frame_num;
        sub_frame(:,i)=abs_frame(:,i)-b*abs_noise;
     end;
else for i=1:frame_num;
        sub_frame_p(:,i)=abs_frame(:,i).^a-b*(abs_noise.^a);
        sub_frame(:,i)=sub_frame_p(:,i).^(1/a);
    end;
end;

zero_frame=zeros(frame_len,frame_num);       %定义与sub_frame同维数的零距阵
sub_frame_z=sub_frame;

%谱减结果修正:将sub_frame距阵中小于0的点置0
[I,J]=find(sub_frame_z<zero_frame);
sub_frame_z(sub2ind(size(sub_frame_z),I,J))=zero_frame(sub2ind(size(sub_frame_z),I,J));
sub_frame=sub_frame_z;

%残余噪声消去:将sub_frame中小于res_noise的点用相邻3中的最小值来代替
for i=2:(frame_num-1);
    I=find(sub_frame(:,i)<res_noise);
    sub_frame(I,i)=min(sub_frame_z(I,(i-1):(i+1)),[],2);
end;

% 非语音帧衰减
T=20*log10(mean(sub_frame./(abs_noise*ones(1,frame_num))));
T_noise=mean(T(:,1:20),2);
c=10^(-2/3);            %衰减系数为 10^(-1.5)
noise_frame=find(T<T_noise);
% noise_frame=find(T<-20);
sub_frame(:,noise_frame)=c*sub_frame(:,noise_frame);

%将处理结果还原至时域
wavout=zeros(1,(frame_num-1)*step_len+frame_len);
j=sqrt(-1);
% for i=1:frame_len;
%     wavout(((i-1)*step_len+1):((i-1)*step_len+frame_len))=...
%     wavout(((i-1)*step_len+1):((i-1)*step_len+frame_len))+real(ifft(sub_frame(:,i).*(exp^(j*ang_frame(:,i))))';
% end;
i=1;
for t=1:step_len:((frame_num-1)*step_len+1);
    wavout(:,t:(t+frame_len-1))=wavout(:,t:(t+frame_len-1))+real(ifft(sub_frame(:,i).*exp(j*ang_frame(:,i))))';
    i=i+1;
end;

%将处理结果输出为'wav'文件
wavwrite(wavout,fs,nbits,['2ss_' num2str(frame_len) 'f_' num2str(a) num2str(b) '_' filename]);

%将处理前后的结果进行作图比较
subplot(2,1,1);
plot(wavin);grid on;
subplot(2,1,2);
plot(wavout);grid on;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -