• 传统语音增强——基本谱减法


    一、基本谱减法的概念

    设语音信号的时间序列为x(n),加窗分帧处理后得到第i帧语音信号为x(m),帧长为
    N。任何一帧语音信号x(m)做FFT后为

    对Xi(k)求出每个分量的幅值和相角,幅值是|Xi(k)|,相角为

    已知前导无话段(噪声段)时长为IS,对应的帧数为NIS,可以求出该噪声段的平均能量为

    谱减公式为

    式中,a和b是两个常数,a称为过减因子;b称为增益补偿因子。

    整个算法的原理下图所示:

     

    二、基本谱减法的实验

    信噪比计算函数SNR_Calc

    名称:SNR_Calc
    功能:计算信噪比。
    调用格式:
    snr=SNR_Calc(x,xn)

    说明:输入信号x是输入的纯净语音信号;xn是输入的含噪信号。输出参数snr是计算的信噪比。

    函数程序如下:

    1. function snr=SNR_Calc(I,In)
    2. % 计算带噪语音信号的信噪比
    3. % I 是纯语音信号
    4. % In 是带噪的语音信号
    5. % 信噪比计算公式是
    6. % snr=10*log10(Esignal/Enoise)
    7. I=I(:)'; % 把数据转为一列
    8. In=In(:)';
    9. Ps=sum((I-mean(I)).^2); % 信号的能量
    10. Pn=sum((I-In).^2); % 噪声的能量
    11. snr=10*log10(Ps/Pn); % 信号的能量与噪声的能量之比,再求分贝值

    基本谱减法函数SpectralSub

    名称:SpectralSub
    功能:谱减法语音降噪。
    调用格式:
    output =SpectralSub(signal, wlen, inc,NIS,a,b)

    说明:输入参数signal是输入的含噪语音信号;wlen为窗函数或窗长;inc是帧移;NIS
    是前导无话段帧数;a为过减因子;b为增益补偿因子。output是降噪后的信号。

    函数程序如下:

    1. function output=SpectralSub(signal,wlen,inc,NIS,a,b)
    2. wnd=hamming(wlen); % 设置窗函数
    3. N=length(signal); % 计算信号长度
    4. y=enframe(signal,wnd,inc)'; % 分帧
    5. fn=size(y,2); % 求帧数
    6. y_fft = fft(y); % FFT
    7. y_a = abs(y_fft); % 求取幅值
    8. y_phase=angle(y_fft); % 求取相位角
    9. y_a2=y_a.^2; % 求能量
    10. Nt=mean(y_a2(:,1:NIS),2); % 计算噪声段平均能量
    11. nl2=wlen/2+1; % 求出正频率的区间
    12. for i = 1:fn; % 进行谱减
    13. for k= 1:nl2
    14. if y_a2(k,i)>a*Nt(k)
    15. temp(k) = y_a2(k,i) - a*Nt(k);
    16. else
    17. temp(k)=b*y_a2(k,i);
    18. end
    19. U(k)=sqrt(temp(k)); % 把能量开方得幅值
    20. end
    21. X(:,i)=U;
    22. end;
    23. output=OverlapAdd2(X,y_phase(1:nl2,:),wlen,inc); % 合成谱减后的语音
    24. Nout=length(output); % 把谱减后的数据长度补足与输入等长
    25. if Nout>N
    26. output=output(1:N);
    27. elseif Nout
    28. output=[output; zeros(N-Nout,1)];
    29. end
    30. output=output/max(abs(output)); % 幅值归一

    案例、实验基本谱减法给带噪语音降噪

    程序如下:

    1. clear all; clc; close all;
    2. [xx, fs] = audioread('C5_2_y.wav'); % 读入数据文件
    3. xx=xx-mean(xx); % 消除直流分量
    4. x=xx/max(abs(xx)); % 幅值归一化
    5. IS=0.25; % 设置前导无话段长度
    6. wlen=200; % 设置帧长为25ms
    7. inc=80; % 设置帧移为10ms
    8. SNR=5; % 设置信噪比SNR
    9. N=length(x); % 信号长度
    10. time=(0:N-1)/fs; % 设置时间
    11. signal=awgn(x,SNR,'measured','db'); % 叠加噪声
    12. snr1=SNR_Calc(x,signal); % 计算初始信噪比
    13. NIS=fix((IS*fs-wlen)/inc +1); % 求前导无话段帧数
    14. a=4; b=0.001; % 设置参数a和b
    15. output=SpectralSub(signal,wlen,inc,NIS,a,b);% 谱减
    16. snr2=SNR_Calc(x,output); % 计算谱减后的信噪比
    17. snr=snr2-snr1;
    18. fprintf('snr1=%5.4f snr2=%5.4f snr=%5.4f\n',snr1,snr2,snr);
    19. % 作图
    20. subplot 311; plot(time,x,'k'); grid; axis tight;
    21. title('纯语音波形'); ylabel('幅值')
    22. subplot 312; plot(time,signal,'k'); grid; axis tight;
    23. title(['带噪语音 信噪比=' num2str(SNR) 'dB']); ylabel('幅值')
    24. subplot 313; plot(time,output,'k');grid;%hold on;
    25. title('谱减后波形'); ylabel('幅值'); xlabel('时间/s');

    运行结果如下:

    实验使用到的语音数据下载链接如下:

    https://download.csdn.net/download/qq_42233059/86442782

    参考文献:语音信号处理实验教程;梁瑞宇、赵力、魏昕(编著) 

     

  • 相关阅读:
    Locust 断言的实现?
    linux常见命令-文件目录类
    轻松上手 | 使用国内资源安装 K3s 全攻略
    秋招面经记录
    AVL 树
    放弃华为天才少年 Offer、和陆奇 10 分钟定投资,25 岁的关超宇想让钢铁侠成为现实 | AGI 技术 50 人...
    电子电机行业万界星空科技MES解决方案
    Elasticsearch入门(一):CentOS 7.6 安装ES 7.6.1
    一张图读懂TuGraph Analytics开源技术架构
    C++圆的面积与周长 自定义函数
  • 原文地址:https://blog.csdn.net/qq_42233059/article/details/126499837