Пример #1
0
    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]
Пример #2
0
    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]
Пример #3
0
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)
Пример #4
0
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)
Пример #5
0
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
Пример #6
0
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))
Пример #7
0
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))
Пример #8
0
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
Пример #9
0
    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