信噪比SNR)
有用信号功率与噪声功率的比(此处功率为平均功率),也等于幅度比的平方
$$SNRdB)=10log_{10}frac{sum_{n=0}^{N-1}s^2n)}{sum_{n=0}^{N-1}d^2n)}=10*log_{10}frac{P_{signal}}{P_{noise}})=20*log_{10}frac{A_{signal}}{A_{noise}})$$
$$SNRdB)=10log_{10}frac{sum_{n=0}^{N-1}s^2n)}{sum_{n=0}^{N-1}[xn)-sn)^2]}$$
其中:
$P_{signal}$为信号功率;$P_{noise}$为噪声功率;$A_{signal}$为信号幅度;$A_{noise}$为噪声幅度值,功率等于幅度值的平方
MATLAB版本代码
# 信号与噪声长度应该一样 function snr=SNR_singlechSignal,Noise) P_signal = sumSignal-meanSignal)).^2; # 信号的能量 P_noise = sumNoise-meanNoise)).^2; # 噪声的能量 snr = 10 * log10P_signal/P_noise)
View Code
def compute_snrlabels, loss): sqrn_l2_norm = tf.sqrttf.reduce_meanlabels ** 2, axis=[1, 2])) snr = 20 * tf.logsqrn_l2_norm / loss + 1e-8) / tf.log10.) avg_snr = tf.reduce_meansnr, axis=0) return avg_snr
tensorflow版本
python代码
def numpy_SNRorigianl_waveform, target_waveform): # 单位 dB signal = np.sumorigianl_waveform ** 2) noise = np.sumorigianl_waveform - target_waveform) ** 2) snr = 10 * np.log10signal / noise) return snr
$$np.linalg.normx)=sqrt{x_1^2+x_2^2+…+x_n^2}$$
这个公式和上面是一样的
def wav_snrref_wav, in_wav):# 如果ref wav稍长,则用0填充in_wav if absin_wav.shape[0] - ref_wav.shape[0]) < 10): pad_width = ref_wav.shape[0] - in_wav.shape[0] in_wav = np.padin_wav, 0, pad_width), 'constant') else: print"错误:参考wav与输入wav的长度明显不同") return -1 # 计算 SNR norm_diff = np.squarenp.linalg.normin_wav - ref_wav)) if norm_diff == 0): print"错误:参考wav与输入wav相同") return -1 ref_norm = np.squarenp.linalg.normref_wav)) snr = 10 * np.log10ref_norm / norm_diff) return snr
峰值信噪比PSNR)
表示信号的最大瞬时功率和噪声功率的比值,最大瞬时功率为语音数据中最大值得平方。
$$SNRdB)=10*log _{10}frac{MAXP_{signal})}{P_{noise}})=10log_{10}frac{MAX[sn)]^2}{d^2n)}$$
$$SNRdB)=10log_{10}frac{MAX[sn)]^2}{frac{1}{N}sum_{n=0}^{N-1}[xn)-sn)]^2}=20log_{10}frac{MAX[sn)]}{sqrt{MSE}}$$
import numpy as np def psnrref_wav, in_wav): MSE = numpy.meanref_wav - in_wav) ** 2) MAX = np.maxref_wav) # 信号的最大平时功率 return 20 * np.log10MAX / np.sqrtMSE))
分段信噪比SegSNR)
由于语音信号是一种缓慢变化的短时平稳信号,因而在不同时间段上的信噪比也应不一样。为了改善上面的问题,可以采用分段信噪比。分段信噪比即是先对语音进行分帧,然后对每一帧语音求信噪比,最好求均值。
MATLAB版本的代码
function [segSNR] = Evaluationclean_speech,enhanced) N = 25*16000/1000; %length of the segment in terms of samples M = fixsizeclean_speech,1)/N); %number of segments segSNR = zerossizeenhanced)); for i = 1:sizeenhanced,1) for m = 0:M-1 sum1 =0; sum2 =0; for n = m*N +1 : m*N+N sum1 = sum1 +clean_speechn)^2; sum2 = sum2 +enhanced{i}n) - clean_speechn))^2; end r = 10*log10sum1/sum2); if r>55 r = 55; elseif r < -10 r = -10; end segSNRi) = segSNRi) +r; end segSNRi) = segSNRi)/M; end
View Code
python代码
def SegSNRref_wav, in_wav, windowsize, shift): if lenref_wav) == lenin_wav): pass else: print'音频的长度不相等!') minlenth = minlenref_wav), lenin_wav)) ref_wav = ref_wav[: minlenth] in_wav = in_wav[: minlenth] # 每帧语音中有重叠部分,除了重叠部分都是帧移,overlap=windowsize-shift # num_frame = lenref_wav)-overlap) // shift # num_frame = lenref_wav)-windowsize+shift) // shift num_frame = lenref_wav) - windowsize) // shift + 1 # 计算帧的数量 SegSNR = np.zerosnum_frame) # 计算每一帧的信噪比 for i in range0, num_frame): noise_frame_energy = np.sumref_wav[i * shift, i * shift+windowsize] ** 2) # 每一帧噪声的功率 speech_frame_energy = np.sumin_wav[i * shift, i * shift+windowsize] ** 2) # 每一帧信号的功率 SegSNR[i] = np.log10speech_frame_energy / noise_frame_energy) return 10 * np.meanSegSNR)
对数拟然对比度log Likelihood Ratio Measure)
坂仓距离测度是通过语音信号的线性预测分析来实现的。ISD基于两组线性预测参数(分别从原纯净语音和处理过的语音的同步帧得到)之间的差异。LLR可以看成一种坂仓距离(Itakura Distance,IS)但是IS距离需要考虑模型增益。而LLR不需要考虑模型争议引起的幅度位移,更重视整体谱包络的相似度。
PESQ
PESQ是用于语音质量评估的一种方法,ITU提供了C语言代码,下载请点击这里,但是在使用之前我们需要先编译C脚本,生成可执行文件exe
编译方式为:在命令行进入下载好的文件
cd Softwaresource
gcc -o PESQ *.c
经过编译,会在当前文件夹生成一个pesq.exe的可执行文件
使用方式为:
命令行进入pesq.exe所在的文件夹
执行命令:pesq 采样率 “原始文件路径名” “劣化文件路径名”
回车
等待结果即可,值越大,质量越好。
例如:pesq +16000 raw.wav processed.wav
对数谱距离Log Spectral Distance)
对数谱距离Log Spectral Distance是两个频谱之间的距离度量(用分贝表示)。两个频谱$PW)$和$hat{P}w)$之间的对数谱距离被定义为:
$$D_{LS}=sqrt{frac{1}{2pi}int_{-pi}^{pi}[10*log _{10}frac{Pw)}{hat{P}w)}]^2dw}$$
其中,$pw)$和$hat{P}w)$是功率谱。对数谱距离是时多对称的。
def numpy_LSDorigianl_waveform, target_waveform): """ 比较原始和目标音频之间的对数谱距离(LSD),也称为对数谱失真, 是两个频谱之间的距离测量值(以dB表示) """ print"数据形状为", origianl_waveform.shape) print"数据类型为", typeorigianl_waveform)) original_spectrogram = librosa.core.stftorigianl_waveform, n_fft=2048) target_spectrogram = librosa.core.stfttarget_waveform, n_fft=2048) original_log = np.log10np.absoriginal_spectrogram) ** 2) target_log = np.log10np.abstarget_spectrogram) ** 2) original_target_squared = original_log - target_log) ** 2 target_lsd = np.meannp.sqrtnp.meanoriginal_target_squared, axis=0))) return target_lsd