Ejemplo n.º 1
0
    def playrec(self, y, send_signal=True):
        """Simulatenously play through secondary path while recording the result.

        Parameters
        ----------
        y : (blocklength,) ndarray
            Control signal.
        send_signal : bool, optional
            If `False`, turn of the disturbance. Can be used to 'measure' the secondary
            path.

        Returns
        -------
        x, e, u, d : (blocklength,) ndarray
            Reference signal, error signal, control signal at error microphone, primary
            at error microphone.

        """
        y = np.atleast_1d(y)

        if send_signal:
            x = np.atleast_1d(next(self.signal))  # reference signal
        else:
            x = np.zeros((self.blocklength, *self._orig_signal.shape[1:2]))

        subscripts_sec = (
            "nlm"[: self._orig_h_pri.ndim - 1] + "," + "nm"[: y.ndim] + "->n"
        )
        subscripts_pri = (
            "nlk"[: self._orig_h_pri.ndim - 1]
            + ","
            + "nk"[: self._orig_signal.ndim]
            + "->n"
        )
        if self._orig_h_sec.ndim - 1 > 1:
            subscripts_sec += "l"
            subscripts_pri += "l"

        d, self._zi_pri = olafilt(
            next(self.h_pri), x, subscripts_pri, zi=self._zi_pri
        )  # primary path signal at error mic
        u, self._zi_sec = olafilt(
            next(self.h_sec), y, subscripts_sec, zi=self._zi_sec
        )  # secondary path signal at error mic

        e = d + u  # error signal

        if self.noise is not None:
            e += next(self.noise)

        return x, e, u, d
Ejemplo n.º 2
0
    def __call__(self, x):
        """Filter signal x.

        Parameters
        ----------
        x : array_like
            Input signal

        Returns
        -------
        y : numpy.ndarray
            Output signal. Has same length as `x`.
        """
        y, self.zi = olafilt(self.w, x, zi=self.zi)
        return y
Ejemplo n.º 3
0
    def filt(self, x):
        """Filter signal x.

        Parameters
        ----------
        x : array_like
            Input signal

        Returns
        -------
        y : numpy.ndarray
            Output signal with `y.shape[0] == x.shape[0]`.

        """
        y, self.zi = olafilt(self.w, x, subscripts=self.subscripts, zi=self.zi)
        return y
Ejemplo n.º 4
0
    def filt(self, x):
        """Filter reference signal.

        Parameters
        ----------
        x : (blocklength, Nin) array_like
            Reference signal.

        Returns
        -------
        y : (blocklength, Nout) numpy.ndarray
            Filter output.

        """
        x = atleast_2d(x)
        assert x.shape[0] == self.blocklength
        assert x.shape[1] == self.Nin

        # NOTE: filtering could also be done in FD. When is each one better?
        # NOTE: give olafilt the FFT of w?
        y, self.zifilt = olafilt(self.w, x, "nmk,nk->nm", zi=self.zifilt)
        return y
Ejemplo n.º 5
0
    def __call__(self, x, d, sec_path_coeff=None, sec_path_est=None):
        """Compute filter output, error, and coefficients.

        Parameters
        ----------
        x : (N,) array_like
            Reference signal. `N` must be divisable by filter blocklength.
        d : (N,) array_like
            Desired signal. `N` must be divisable by filter blocklength.
        sec_path_coeff : array_like or None, optional
            Coefficients of the secondary path filter model.
        sec_path_est : None, optional
            Estimate of secondary path filter model.

        Returns
        -------
        y : (N,) numpy.ndarray
            Filter output.
        u : (N,) numpy.ndarray
            Filter output at error signal.
        e : (N,) numpy.ndarray
            Error signal.
        w : (N, length)
            Filter coefficients at each block.

        """
        x = np.atleast_1d(x)
        d = np.atleast_1d(d)
        assert x.ndim == 1
        assert x.shape[0] % self.blocklength == 0
        assert x.shape == d.shape

        if sec_path_est is not None:
            fx = olafilt(sec_path_est, x)  # filtered reference signal
        else:
            fx = x

        x = x.reshape((-1, self.blocklength))
        d = d.reshape((-1, self.blocklength))
        n_blocks = x.shape[0]
        w = np.zeros((n_blocks, self.length))  # filter history
        e = np.zeros((n_blocks, self.blocklength))  # error signal
        y = np.zeros((n_blocks, self.blocklength))  # filtered output signal
        u = np.zeros(
            (n_blocks, self.blocklength))  # control signal at error mic
        fx = fx.reshape((-1, self.blocklength))

        if sec_path_coeff is not None:
            zi = 0

        for n in range(n_blocks):
            w[n] = self.w
            y[n] = self.filt(x[n])

            # control signal at error sensor
            if sec_path_coeff is not None:
                u[n], zi = olafilt(sec_path_coeff, y[n], zi=zi)
            else:
                u[n] = y[n]

            # error signal
            e[n] = d[n] + u[n]

            self.adapt(fx[n], e[n])

        return y.reshape(-1), u.reshape(-1), e.reshape(-1), w
Ejemplo n.º 6
0
signal = np.random.normal(0, 1, size=n_buffers * blocklength)

# the adaptive filter
filt = FastBlockLMSFilter(length, blocklength, stepsize=0.1, leakage=0.9999)

# secondary path estimate has to account for block size
plant_model = SimpleFilter(np.concatenate((np.zeros(blocklength), h_sec)))

# simulates an audio interface with primary and secondary paths and 40 dB SNR noise
# at the error sensor
sim = FakeInterface(
    blocklength,
    signal,
    h_pri=h_pri,
    h_sec=h_sec,
    noise=wgn(olafilt(h_pri, signal), 40, "dB"),
)

elog = []
y = np.zeros(blocklength)  # control signal is zero for first block
for i in range(n_buffers):

    # record reference signal x and error signal e while playing back y
    x, e, _, _ = sim.playrec(y)

    # filter the reference signal
    fx = plant_model(x)

    # adapt filter
    filt.adapt(fx, e)