import librosa import numpy as np from basis import ScoreBasis class FWSEGSNR(ScoreBasis): def __init__(self): super(FWSEGSNR, self).__init__(name='FWSEGSNR') self.intrusive = False def windowed_scoring(self, audios, score_rate): if len(audios) != 2: return None return fwsegsnr(audios[1], audios[0], score_rate) def fwsegsnr(x, y, fs, frame_sz = 0.025, shift_sz= 0.01, win='hann', numband=23): epsilon = np.finfo(np.float32).eps frame = int(np.fix(frame_sz * fs)) shift = int(np.fix(shift_sz * fs)) window = win nband = numband noverlap = frame - shift fftpt = int(2**np.ceil(np.log2(np.abs(frame)))) x = x / np.sqrt(sum(np.power(x, 2))) y = y / np.sqrt(sum(np.power(y, 2))) assert len(x) == len(y), print('Wav length are not matched!') X_stft = np.abs(librosa.stft(x, n_fft=fftpt, hop_length=shift, win_length=frame, window=window, center=False)) Y_stft = np.abs(librosa.stft(y, n_fft=fftpt, hop_length=shift, win_length=frame, window=window, center=False)) num_freq = X_stft.shape[0] num_frame = X_stft.shape[1] X_mel = librosa.feature.melspectrogram(S=X_stft, sr=fs, n_mels=nband, fmin=0, fmax=fs/2) Y_mel = librosa.feature.melspectrogram(S=Y_stft, sr=fs, n_mels=nband, fmin=0, fmax=fs/2) # Calculate SNR. W = np.power(Y_mel, 0.2) E = X_mel - Y_mel E[E == 0.0] = epsilon E_power = np.power(E, 2) Y_div_E = np.divide((np.power(Y_mel,2)), (np.power(E,2))) Y_div_E[Y_div_E==0] = epsilon ds = 10 * np.divide(np.sum(np.multiply(W, np.log10(Y_div_E)), 1), np.sum(W, 1)) ds[ds > 35] = 35 ds[ds < -10] = -10 d = np.mean(ds) return d