def _env_extraction(self, signal): """Extracts the envelope of a time signal. Parameters ---------- signal : ndarray Input signal. Returns ------- ndarray Low-pass filtered envelope. Notes ----- The envelope is extracted by calculating the absolute value of the Hilbert transform, and then by low-pass filtering the envelope at a frequency of 150 Hz using a first order Butterworth filter. """ # Extract envelope tmp_env = inner.hilbert_envelope(signal).squeeze() # Low-pass filtering tmp_env = inner.lowpass_env_filtering(tmp_env, 150.0, n=1, fs=self.fs) # Downsample the envelope for faster processing return tmp_env[::self.downsamp_factor]
def test_envelope_extraction(): x = np.array( [-0.00032745, -0.00031198, -0.00029605, -0.00027965, -0.00026281, -0.00024553, -0.00022783, -0.00020972]) target = np.array( [0.00068165, 0.00068556, 0.00068946, 0.00069335, 0.00069725, 0.00070113, 0.00070502, 0.0007089]) envelope = inner.hilbert_envelope(x) np.testing.assert_allclose(envelope, target, atol=1e-3)
def test_envelope_extraction(): x = np.array([ -0.00032745, -0.00031198, -0.00029605, -0.00027965, -0.00026281, -0.00024553, -0.00022783, -0.00020972 ]) target = np.array([ 0.00068165, 0.00068556, 0.00068946, 0.00069335, 0.00069725, 0.00070113, 0.00070502, 0.0007089 ]) envelope = inner.hilbert_envelope(x) np.testing.assert_allclose(envelope, target, atol=1e-3)
def get_env(x, fs, filt=True): """ get filtered temporal envelope of signal x input: signal, sampling frequency output: :param x: :param fs: :return: """ x_env = hilbert_envelope(x) if filt: return lowpass_env_filtering(x_env, cutoff=cutoff, n=4, fs=fs) else: return x_env
def test_hilbert_env_on_2d_array_with_last_dimension(): tests = ( ([0.70710678, 1.56751612, 2., 1.56751612, 0.70710678], [0, 1, 2, 1, 0]), ([0.70710678, 1.56751612, 2., 1.56751612, 0.70710678], [0, 1, 2, 1, 0]), ([[0., 1.], [0., 1.]], [[0, 1], [0, 1]]), ([[0.5, 1., 0.5], [2.5, 3.16227766, 1.5]], [[0, 1, 0], [2, 3, 0]]), ) for target, x in tests: env = inner.hilbert_envelope(x) np.testing.assert_allclose(env, target, err_msg="Input was {}".format(x))
def envelope_spectrogram(x, fs, fmin, fmax, nbands, tau_ms=8, use_hilbert=False, order=4, q=9.26): # Cochlear filtering fmin = 80 # corresponds to 4.55 filters per band at nsgt erb, 2.5 for 64 filters nsgt = NSGT_ERB(fs, len(x), 4.55, cutoff_frequency=6000, plot=False) # 82.1 to 6000 Hz with 128 filters xf = np.real(nsgt.forward_full_temp(x)) xf = xf[13:, :] if use_hilbert: env = hilbert_envelope(xf) # (Bands, Time) env = low_pass_filter(env, fs, cutoff=50) else: env = np.maximum(xf, 0) env = low_pass_filter(env, fs, cutoff=50) env = np.maximum(env, 1e-9) # match energy scale_factor = np.sqrt( np.sum(np.square(xf), axis=-1) / np.sum(np.square(env), axis=-1)) env = np.multiply(env, scale_factor[:, np.newaxis]) # Integration tau = int(tau_ms / 1000 * fs) # 8ms win_slope = 1 window = np.exp(-np.linspace(0, win_slope * tau - 1, tau) / tau) window = np.transpose(np.repeat(window[:, np.newaxis], nbands, axis=1)) # (frequency, time) y = np.transpose([ np.sqrt(np.sum(window * env[:, i:i + tau]**2, axis=-1)) for i in range(0, env.shape[1] - tau, tau) ]) return y**0.5
def predict(self, clean, mixture, noise): """Predicts intelligibility using the mr-sEPSM. Predicts the SNRenv value for the combination of mixture and noise alone. Parameters ---------- clean, mixture, noise : ndarrays Single-dimension arrays for the clean speech, the mixture of the clean speech ans noise, and the noise alone. Returns ------- dict Dictionary with the predictions by the model. Notes ----- """ fs_new = self.fs / self.downsamp_factor n_clean = len(clean) n_modf = len(self.modf) n_cf = len(self.cf) # Process only the mixture and noise if the clean speech is the same # as the noise. if (clean is None) or (np.array_equal(clean, mixture)): signals = (mixture, noise) else: signals = (clean, mixture, noise) downsamp_chan_envs = np.zeros( (len(signals), np.ceil(n_clean / self.downsamp_factor).astype('int'))) if (downsamp_chan_envs.shape[-1] % 2) == 0: len_offset = 1 else: len_offset = 0 chan_mod_envs = np.zeros((len(signals), len(self.modf), downsamp_chan_envs.shape[-1] - len_offset)) time_av_mr_snr_env_matrix = np.zeros((n_cf, n_modf)) lt_exc_ptns = np.zeros((len(signals), n_cf, n_modf)) mr_snr_env_matrix = [] mr_exc_ptns = [] # find bands above threshold filtered_rms_mix = inner.noctave_filtering(mixture, self.cf, self.fs, width=3) bands_above_thres_idx = self._bands_above_thres(filtered_rms_mix) for idx_band in bands_above_thres_idx: channel_envs = \ [self._peripheral_filtering(signal, self.cf[idx_band]) for signal in signals] for i_sig, channel_env in enumerate(channel_envs): # Extract envelope tmp_env = inner.hilbert_envelope(channel_env).squeeze() # Low-pass filtering tmp_env = inner.lowpass_env_filtering(tmp_env, 150.0, n=1, fs=self.fs) # Downsample the envelope for faster processing downsamp_chan_envs[i_sig] = tmp_env[::self.downsamp_factor] # Sub-band modulation filtering lt_exc_ptns[i_sig, idx_band], chan_mod_envs[i_sig] = \ central.mod_filterbank(downsamp_chan_envs[i_sig], fs_new, self.modf) chan_mr_exc_ptns = [] for chan_env, mod_envs in zip(downsamp_chan_envs, chan_mod_envs): chan_mr_exc_ptns.append(self._mr_env_powers( chan_env, mod_envs)) mr_exc_ptns.append(chan_mr_exc_ptns) time_av_mr_snr_env_matrix[idx_band], _, chan_mr_snr_env_matrix \ = self._mr_snr_env(*chan_mr_exc_ptns[-2:]) # Select only the # env powers from the mixture and the noise, even if we # calculated the envelope powers for the clean speech. mr_snr_env_matrix.append(chan_mr_snr_env_matrix) lt_snr_env_matrix = super(MrSepsm, self)._snr_env(*lt_exc_ptns[-2:]) lt_snr_env = super(MrSepsm, self)._optimal_combination(lt_snr_env_matrix, bands_above_thres_idx) snr_env = self._optimal_combination(time_av_mr_snr_env_matrix, bands_above_thres_idx) res = { 'p': { 'snr_env': snr_env, 'lt_snr_env': lt_snr_env, }, 'snr_env_matrix': time_av_mr_snr_env_matrix, # .snr_env_matrix': snr_env_matrix # Output of what is essentially the sEPSM. 'lt_snr_env_matrix': lt_snr_env_matrix, 'lt_exc_ptns': lt_exc_ptns, # .mr_snr_env': mr_snr_env 'mr_snr_env_matrix': mr_snr_env_matrix, 'mr_exc_ptns': mr_exc_ptns, 'bands_above_thres_idx': bands_above_thres_idx } return res