def apply_filter(x, W):
    """
    Applies a filter on the mixture. Just corresponds to a matrix
    multiplication.

    Parameters
    ----------
    x: np.ndarray [shape=(nb_frames, nb_bins, nb_channels)]
        STFT of the signal on which to apply the filter.

    W: np.ndarray [shape=(nb_frames, nb_bins, nb_channels, nb_channels)]
        filtering matrices, as returned, e.g. by :func:`wiener_gain`

    Returns
    -------
    y_hat: np.ndarray [shape=(nb_frames, nb_bins, nb_channels)]
        filtered signal
    """
    nb_channels = W.shape[-1]

    # apply the filter
    y_hat = 0+0j
    for i in range(nb_channels):
        y_hat += W[..., i] * x[..., i, None]
    return y_hat