有用信號功率與噪聲功率的比(此處功率爲平均功率),也等於幅度比的平方python
$$SNR(dB)=10\log_{10}\frac{\sum_{n=0}^{N-1}s^2(n)}{\sum_{n=0}^{N-1}d^2(n)}=10*\log_{10}(\frac{P_{signal}}{P_{noise}})=20*log_{10}(\frac{A_{signal}}{A_{noise}})$$git
$$SNR(dB)=10\log_{10}\frac{\sum_{n=0}^{N-1}s^2(n)}{\sum_{n=0}^{N-1}[x(n)-s(n)^2]}$$github
其中:windows
$P_{signal}$爲信號功率;$P_{noise}$爲噪聲功率;$A_{signal}$爲信號幅度;$A_{noise}$爲噪聲幅度值,功率等於幅度值的平方ide
MATLAB版本代碼lua
# 信號與噪聲長度應該同樣 function snr=SNR_singlech(Signal,Noise) P_signal = sum(Signal-mean(Signal)).^2; # 信號的能量 P_noise = sum(Noise-mean(Noise)).^2; # 噪聲的能量 snr = 10 * log10(P_signal/P_noise)
python代碼spa
def numpy_SNR(origianl_waveform, target_waveform): # 單位 dB signal = np.sum(origianl_waveform ** 2) noise = np.sum((origianl_waveform - target_waveform) ** 2) snr = 10 * np.log10(signal / noise) return snr
$$np.linalg.norm(x)=\sqrt{x_1^2+x_2^2+...+x_n^2}$$.net
這個公式和上面是同樣的命令行
def wav_snr(ref_wav, in_wav):# 若是ref wav稍長,則用0填充in_wav if (abs(in_wav.shape[0] - ref_wav.shape[0]) < 10): pad_width = ref_wav.shape[0] - in_wav.shape[0] in_wav = np.pad(in_wav, (0, pad_width), 'constant') else: print("錯誤:參考wav與輸入wav的長度明顯不一樣") return -1 # 計算 SNR norm_diff = np.square(np.linalg.norm(in_wav - ref_wav)) if (norm_diff == 0): print("錯誤:參考wav與輸入wav相同") return -1 ref_norm = np.square(np.linalg.norm(ref_wav)) snr = 10 * np.log10(ref_norm / norm_diff) return snr
表示信號的最大瞬時功率和噪聲功率的比值,最大瞬時功率爲語音數據中最大值得平方。code
$$SNR(dB)=10*\log _{10}(\frac{MAX(P_{signal})}{P_{noise}})=10\log_{10}\frac{MAX[s(n)]^2}{d^2(n)}$$
$$SNR(dB)=10\log_{10}\frac{MAX[s(n)]^2}{\frac{1}{N}\sum_{n=0}^{N-1}[x(n)-s(n)]^2}=20\log_{10}\frac{MAX[s(n)]}{\sqrt{MSE}}$$
import numpy as np def psnr(ref_wav, in_wav): MSE = numpy.mean((ref_wav - in_wav) ** 2) MAX = np.max(ref_wav) # 信號的最大平時功率 return 20 * np.log10(MAX / np.sqrt(MSE))
因爲語音信號是一種緩慢變化的短時平穩信號,於是在不一樣時間段上的信噪比也應不同。爲了改善上面的問題,能夠採用分段信噪比。分段信噪比便是先對語音進行分幀,而後對每一幀語音求信噪比,最好求均值。
MATLAB版本的代碼
function [segSNR] = Evaluation(clean_speech,enhanced) N = 25*16000/1000; %length of the segment in terms of samples M = fix(size(clean_speech,1)/N); %number of segments segSNR = zeros(size(enhanced)); for i = 1:size(enhanced,1) for m = 0:M-1 sum1 =0; sum2 =0; for n = m*N +1 : m*N+N sum1 = sum1 +clean_speech(n)^2; sum2 = sum2 +(enhanced{i}(n) - clean_speech(n))^2; end r = 10*log10(sum1/sum2); if r>55 r = 55; elseif r < -10 r = -10; end segSNR(i) = segSNR(i) +r; end segSNR(i) = segSNR(i)/M; end
python代碼
def SegSNR(ref_wav, in_wav, windowsize, shift): if len(ref_wav) == len(in_wav): pass else: print('音頻的長度不相等!') minlenth = min(len(ref_wav), len(in_wav)) ref_wav = ref_wav[: minlenth] in_wav = in_wav[: minlenth] # 每幀語音中有重疊部分,除了重疊部分都是幀移,overlap=windowsize-shift # num_frame = (len(ref_wav)-overlap) // shift # num_frame = (len(ref_wav)-windowsize+shift) // shift num_frame = (len(ref_wav) - windowsize) // shift + 1 # 計算幀的數量 SegSNR = np.zeros(num_frame) # 計算每一幀的信噪比 for i in range(0, num_frame): noise_frame_energy = np.sum(ref_wav[i * shift, i * shift+windowsize] ** 2) # 每一幀噪聲的功率 speech_frame_energy = np.sum(in_wav[i * shift, i * shift+windowsize] ** 2) # 每一幀信號的功率 SegSNR[i] = np.log10(speech_frame_energy / noise_frame_energy) return 10 * np.mean(SegSNR)
阪倉距離測度是經過語音信號的線性預測分析來實現的。ISD基於兩組線性預測參數(分別從原純淨語音和處理過的語音的同步幀獲得)之間的差別。LLR能夠當作一種阪倉距離(Itakura Distance,IS)可是IS距離須要考慮模型增益。而LLR不須要考慮模型爭議引發的幅度位移,更重視總體譜包絡的類似度。
PESQ是用於語音質量評估的一種方法,ITU提供了C語言代碼,下載請點擊這裏,可是在使用以前咱們須要先編譯C腳本,生成可執行文件exe
編譯方式爲:在命令行進入下載好的文件
通過編譯,會在當前文件夾生成一個pesq.exe的可執行文件
使用方式爲:
對數譜距離Log Spectral Distance是兩個頻譜之間的距離度量(用分貝表示)。兩個頻譜$P(W)$和$\hat{P}(w)$之間的對數譜距離被定義爲:
$$D_{LS}=\sqrt{\frac{1}{2\pi}\int_{-\pi}^{\pi}[10*\log _{10}\frac{P(w)}{\hat{P}(w)}]^2dw}$$
其中,$p(w)$和$\hat{P}(w)$是功率譜。對數譜距離是時多對稱的。
def numpy_LSD(origianl_waveform, target_waveform): """ 比較原始和目標音頻之間的對數譜距離(LSD),也稱爲對數譜失真, 是兩個頻譜之間的距離測量值(以dB表示) """ print("數據形狀爲", origianl_waveform.shape) print("數據類型爲", type(origianl_waveform)) original_spectrogram = librosa.core.stft(origianl_waveform, n_fft=2048) target_spectrogram = librosa.core.stft(target_waveform, n_fft=2048) original_log = np.log10(np.abs(original_spectrogram) ** 2) target_log = np.log10(np.abs(target_spectrogram) ** 2) original_target_squared = (original_log - target_log) ** 2 target_lsd = np.mean(np.sqrt(np.mean(original_target_squared, axis=0))) return target_lsd