基于PSD-ML算法的语音增强算法matlab仿真

发布时间 2023-12-09 21:36:07作者: 简简单单做算法

1.算法运行效果图预览

 

 

 

2.算法运行软件版本

matlab2022A

 

3.算法理论概述

       PSD-ML(Power Spectral Density Maximum Likelihood)算法是一种基于最大似然估计的语音增强算法,通过对语音信号的功率谱密度进行估计,并利用估计结果对原始语音信号进行滤波处理,以达到增强语音信号的目的。下面将详细介绍PSD-ML算法的原理和数学公式。

 

        PSD-ML算法的基本思想是利用最大似然估计对语音信号的功率谱密度进行估计,并根据估计结果对原始语音信号进行滤波处理。具体实现过程中,首先需要将语音信号分成多个重叠的帧,并对每帧信号进行加窗处理以减少频谱泄漏。然后,利用快速傅里叶变换(FFT)将每帧信号转换为频域表示,并根据功率谱密度的估计结果对频域信号进行滤波处理。最后,将滤波后的频域信号通过逆快速傅里叶变换(IFFT)转换回时域表示,并将重叠的帧进行合并以得到增强后的语音信号。

 

      假设原始语音信号为x(n),加窗后的信号为x_w(n),分帧后的第i帧信号为x_i(n),其对应的功率谱密度为P_i(k),其中k表示频率索引。则PSD-ML算法的数学公式可以表示为:

 

1.加窗处理:

x_w(n) = w(n) * x(n)

 

其中,w(n)为窗函数,如汉明窗或汉宁窗等。

 

2.分帧处理:

x_i(n) = x_w(n+iL)

 

其中,L为帧长,i为帧索引。

 

3.功率谱密度估计:

P_i(k) = |X_i(k)|^2 / N

 

其中,X_i(k)为第i帧信号的FFT变换结果,N为帧长。

 

4.滤波处理:

Y_i(k) = G_i(k) * X_i(k)

 

其中,G_i(k)为滤波器的增益函数,可以根据功率谱密度的估计结果计算得到。

 

5.逆变换处理:

y_i(n) = IFFT{Y_i(k)}

 

其中,IFFT表示逆快速傅里叶变换。

 

6.合并处理:

y(n) = ∑ y_i(n-iL)

 

其中,∑表示对所有重叠的帧进行合并。

 

       需要注意的是,在实际应用中,为了进一步提高语音增强的效果,可以采用一些优化策略,如自适应滤波器、多通道滤波器等。同时,也需要根据实际应用场景和需求来选择合适的窗函数、帧长、滤波器类型等参数。

 

 

 

 

4.部分核心程序

% 处理最后一帧,如果最后一帧的长度小于帧长,用零填充至帧长  
y_seg = y(1+(Nframe-1)*(Len_frame-Len_loop):end); 
y_seg = [y_seg; zeros(Len_frame-length(y_seg), 1)];
y_t   = [y_t y_seg];
%应用汉宁窗函数  
window= hann(Len_frame);%apply hanning window
y_fft   = zeros(size(y_t));
for idx = 1 : Nframe
    y_fft(:, idx) = fft(window .* y_t(:, idx)); 
end
 
 
%计算带噪语音的功率谱密度(PSD)估计值,采用Barlett方法,L为周期图的段数  
L    = 12;  
Pyy  = func_Bartlett(y_fft,L); 
 
% 噪声功率谱密度(PSD)估计,选择MS或MMSE方法,这里采用MS方法,M为段数,B为偏差补偿系数 
M     = 12;  
B     = 1;  
Pnn   = func_nPSD(Pyy,M,B);
 
% 目标语音功率谱密度(PSD)估计,选择ML或DD方法,这里采用ML方法,得到SNR的ML估计值SNR_ml  
SNR_ml       = func_PSDML(Pyy,Pnn);%DD方法的代码被注释掉了,alpha为平滑系数,取值一般在0.96-0.99之间 
% 使用wiener函数计算Wiener增益,得到降噪后的频域信号s_hat_k 
y_wiener_fft = func_wiener(y_fft,SNR_ml);
 
% 进行逆变换和重叠相加操作,得到降噪后的时域信号s_t 
y_wiener_ifft= ifft(y_wiener_fft);% Inverse FFT transform
% 取s_t的前半部分作为s_t_est1  
y_wiener2    = y_wiener_ifft(1:Len_frame-Len_loop/2, 1);
% 取s_t的后半部分作为s_t_est2  
y_wiener3    = y_wiener_ifft(1+Len_loop/2:end,end);
% 去掉s_t的第一列和最后一列 
y_wiener_ifft(:, 1)   = [];
y_wiener_ifft(:, end) = [];
% 去掉s_t的前hop_length/2行和后hop_length/2行
y_wiener_ifft(1:Len_loop/2, :)            = [];
y_wiener_ifft(end-(Len_loop/2-1): end, :) = [];
% 将s_t重塑为一列向量  
y_wiener_ifft         = reshape(y_wiener_ifft, [], 1);
% 取s_t的实部作为最终的降噪后的时域信号s_t  
y_wiener_ifft         = real(y_wiener_ifft);