コード例 #1
0
def wiener_deconvolve(y, x, length=None, noise_variance=1., let_n_points=15, let_div_base=2):
    '''
    Deconvolve an excitation signal from an impulse response

    We use Wiener filter

    Parameters
    ----------

    y : ndarray
        The recording
    x : ndarray
        The excitation signal
    length: int, optional
        the length of the impulse response to deconvolve
    noise_variance : float, optional
        estimate of the noise variance
    let_n_points: int
        number of points to use in the LET approximation
    let_div_base: float
        the divider used for the LET grid
    '''

    # FFT length including zero padding
    n = y.shape[0] + x.shape[0] - 1

    # let FFT size be even for convenience
    if n % 2 != 0:
        n += 1

    # when unknown, pick the filter size as size of test signal
    if length is None:
        length = n

    # Forward transforms
    Y  = fft.rfft(np.array(y, dtype=np.float32), n=n) / np.sqrt(n)  # recording
    X = fft.rfft(np.array(x, dtype=np.float32), n=n) / np.sqrt(n)   # test signal

    # Squared amplitude of test signal
    X_sqm = np.abs(X)**2

    # approximate SNR
    SNR_hat = np.maximum(1e-7, ((np.linalg.norm(Y)**2 / np.linalg.norm(X)**2) - noise_variance))  / noise_variance
    dividers = let_div_base**np.linspace(-let_n_points/2, let_n_points, let_n_points)
    SNR_grid = SNR_hat / dividers

    # compute candidate points
    G = (X_sqm[:,None] / (X_sqm[:,None] + 1./SNR_grid[None,:])) * Y[:,None]
    H_candidates = G / X[:,None]

    # find the best linear combination of the candidates
    weights = np.linalg.lstsq(G, Y)[0]

    # compute the estimated filter
    H = np.squeeze(np.dot(H_candidates, weights))
    h = fft.irfft(H, n=n)

    return h[:length]
コード例 #2
0
def deconvolve(y, s, noise, periodogram_len=64):
    '''
    Wiener deconvolution of an excitation signal from an impulse response

    Parameters
    ----------

    y : ndarray
        The recording
    s : ndarray
        The excitation signal
    noise: ndarray
        The noise reference signal

    Returns
    -------
    h_len : int
        The length of the impulse response
    '''

    # FFT length including zero padding
    n = y.shape[0] + s.shape[0] - 1

    # let FFT size be even for convenience
    if n % 2 != 0:
        n += 1

    # Compute the periodogram of the noise signal
    N = periodogram(noise, periodogram_len, n=n)

    # Forward transforms
    Y = fft.rfft(y, n=n, axis=0) / np.sqrt(n)
    S = fft.rfft(s, n=n, axis=0) / np.sqrt(n)

    # Wiener deconvolution
    if Y.ndim > 1:
        S = S[:, None]

    H = Y * np.conj(S) / (np.abs(S)**2 + N)

    # Inverse transform
    h = fft.irfft(H, n=n, axis=0)

    return h
コード例 #3
0
def deconvolve(y, s, length=None, thresh=0.0):
    '''
    Deconvolve an excitation signal from an impulse response

    Parameters
    ----------

    y : ndarray
        The recording
    s : ndarray
        The excitation signal
    length: int, optional
        the length of the impulse response to deconvolve
    thresh : float, optional
        ignore frequency bins with power lower than this
    '''

    # FFT length including zero padding
    n = y.shape[0] + s.shape[0] - 1

    # let FFT size be even for convenience
    if n % 2 != 0:
        n += 1

    # when unknown, pick the filter size as size of test signal
    if length is None:
        length = n

    # Forward transforms
    Y  = fft.rfft(np.array(y, dtype=np.float32), n=n) / np.sqrt(n)
    S = fft.rfft(np.array(s, dtype=np.float32), n=n) / np.sqrt(n)

    # Only do the division where S is large enough
    H = np.zeros(*Y.shape, dtype=Y.dtype)
    I = np.where(np.abs(S) > thresh)
    H[I] = Y[I] / S[I]

    # Inverse transform
    h = fft.irfft(H, n=n)

    return h[:length]
コード例 #4
0
ファイル: sync.py プロジェクト: zha80052/pyroomacoustics
def correlate(x1, x2, interp=1, phat=False):
    """
    Compute the cross-correlation between x1 and x2

    Parameters
    ----------
    x1,x2: array_like
        The data arrays
    interp: int, optional
        The interpolation factor for the output array, default 1.
    phat: bool, optional
        Apply the PHAT weighting (default False)

    Returns
    -------
    The cross-correlation between the two arrays
    """

    N1 = x1.shape[0]
    N2 = x2.shape[0]

    N = N1 + N2 - 1

    X1 = fft.rfft(x1, n=N)
    X2 = fft.rfft(x2, n=N)

    if phat:
        eps1 = np.mean(np.abs(X1)) * 1e-10
        X1 /= np.abs(X1) + eps1
        eps2 = np.mean(np.abs(X2)) * 1e-10
        X2 /= np.abs(X2) + eps2

    m = np.minimum(N1, N2)

    out = fft.irfft(X1 * np.conj(X2), n=int(N * interp))

    return np.concatenate([out[-interp * (N2 - 1):], out[:(interp * N1)]])
コード例 #5
0
ファイル: dft.py プロジェクト: whiteweak/pyroomacoustics
    def analysis(self, x):
        """
        Perform frequency analysis of a real input using DFT.

        Parameters
        ----------
        x: numpy array (float32)
            Real input signal in time domain. Must be of size (N,D).
        plot_spec: bool
            Whether or not to plot frequency magnitude spectrum.

        Returns
        -------
        Frequency spectrum, numpy array of size (N/2+1,D) and of type complex64.
        """

        # check for valid input
        if self.D != 1:
            if x.shape != (self.nfft, self.D):
                raise ValueError('Invalid input dimensions.')
        elif self.D == 1:
            if x.ndim != 1 and x.shape[0] != self.nfft:
                raise ValueError('Invalid input dimensions.')
        # apply window if needed
        if self.analysis_window is not None:
            try:
                np.multiply(self.analysis_window, x, x)
            except:
                self.analysis_window = self.analysis_window.astype(x.dtype,
                                                                   copy=False)
                np.multiply(self.analysis_window, x, x)
        # apply DFT
        if self.transform == 'fftw':
            self.a[:, ] = x
            self.X[:, ] = self.forward()
        elif self.transform == 'mkl':
            self.X[:, ] = mkl_fft.rfft(x, axis=0)
        else:
            self.X[:, ] = rfft(x, axis=0)

        return self.X