def rakeOneForcingFilters(self, sources, interferers, R_n, epsilon=5e-3):
        '''
        Compute the time-domain filters of a beamformer with unit response
        towards multiple sources.
        '''

        dist_mat = distance(self.R, sources.images)
        s_time = dist_mat / constants.get('c')
        s_dmp = 1./(4*np.pi*dist_mat)

        dist_mat = distance(self.R, interferers.images)
        i_time = dist_mat / constants.get('c')
        i_dmp = 1./(4*np.pi*dist_mat)

        # compute offset needed for decay of sinc by epsilon
        offset = np.maximum(s_dmp.max(), i_dmp.max())/(np.pi*self.Fs*epsilon)
        t_min = np.minimum(s_time.min(), i_time.min())
        t_max = np.maximum(s_time.max(), i_time.max())

        # adjust timing
        s_time -= t_min - offset
        i_time -= t_min - offset
        Lh = np.ceil((t_max - t_min + 2*offset)*float(self.Fs))

        # the channel matrix
        K = sources.images.shape[1]
        Lg = self.Lg
        off = (Lg - Lh)/2
        L = self.Lg + Lh - 1

        H = np.zeros((Lg*self.M, 2*L))
        As = np.zeros((Lg*self.M, K))

        for r in np.arange(self.M):

            # build constraint matrix
            hs = u.lowPassDirac(s_time[r,:,np.newaxis], s_dmp[r,:,np.newaxis], self.Fs, Lh)[:,::-1]
            As[r*Lg+off:r*Lg+Lh+off,:] = hs.T

            # build interferer RIR matrix
            hx = u.lowPassDirac(s_time[r,:,np.newaxis], s_dmp[r,:,np.newaxis], self.Fs, Lh).sum(axis=0)
            H[r*Lg:(r+1)*Lg,:L] = u.convmtx(hx, Lg).T

            # build interferer RIR matrix
            hq = u.lowPassDirac(i_time[r,:,np.newaxis], i_dmp[r,:,np.newaxis], self.Fs, Lh).sum(axis=0)
            H[r*Lg:(r+1)*Lg,L:] = u.convmtx(hq, Lg).T

        ones = np.ones((K,1))

        # We first assume the sample are uncorrelated
        K_x = np.dot(H[:,:L], H[:,:L].T)
        K_nq = np.dot(H[:,L:], H[:,L:].T) + R_n

        # Compute the TD filters
        K_nq_inv = np.linalg.inv(K_x+K_nq)
        C = np.dot(K_nq_inv, As)
        B = np.linalg.inv(np.dot(As.T, C))
        g_val = np.dot(C, np.dot(B, ones))
        self.filters = g_val.reshape((self.M,Lg))

        # compute and return SNR
        A = np.dot(g_val.T, H[:,:L])
        num = np.dot(A, A.T)
        denom =  np.dot(np.dot(g_val.T, K_nq), g_val)

        return num/denom
def buildRIRMatrix(mics, sources, Lg, Fs, epsilon=5e-3, unit_damping=False):
    """
    A function to build the channel matrix for many sources and microphones

    mics is a dim-by-M ndarray where each column is the position of a microphone
    sources is a list of SoundSource objects
    Lg is the length of the beamforming filters
    Fs is the sampling frequency
    epsilon determines how long the sinc is let to decay. Defaults to epsilon=5e-3
    unit_damping determines if the wall damping parameters are used or not. Default to false.

    returns the RIR matrix H = 

    --------------------
    | H_{11} H_{12} ...
    | ...
    |
    --------------------

    where H_{ij} is channel matrix between microphone i and source j.
    H is of type (M*Lg)x((Lg+Lh-1)*S) where Lh is the channel length (determined by epsilon),
    and M, S are the number of microphones, sources, respectively.
    """

    from beamforming import distance
    from utilities import lowPassDirac, convmtx
    from scipy.linalg import toeplitz

    # set the boundaries of RIR filter for given epsilon
    d_min = np.inf
    d_max = 0.0
    dmp_max = 0.0
    for s in xrange(len(sources)):
        dist_mat = distance(mics, sources[s].images)
        if unit_damping == True:
            dmp_max = np.maximum((1.0 / (4 * np.pi * dist_mat)).max(), dmp_max)
        else:
            dmp_max = np.maximum((sources[s].damping[np.newaxis, :] / (4 * np.pi * dist_mat)).max(), dmp_max)
        d_min = np.minimum(dist_mat.min(), d_min)
        d_max = np.maximum(dist_mat.max(), d_max)

    t_max = d_max / constants.get("c")
    t_min = d_min / constants.get("c")

    offset = dmp_max / (np.pi * Fs * epsilon)

    # RIR length
    Lh = int((t_max - t_min + 2 * offset) * float(Fs))

    # build the channel matrix
    L = Lg + Lh - 1
    H = np.zeros((Lg * mics.shape[1], len(sources) * L))

    for s in xrange(len(sources)):
        for r in np.arange(mics.shape[1]):

            dist = sources[s].distance(mics[:, r])
            time = dist / constants.get("c") - t_min + offset
            if unit_damping == True:
                dmp = 1.0 / (4 * np.pi * dist)
            else:
                dmp = sources[s].damping / (4 * np.pi * dist)

            h = lowPassDirac(time[:, np.newaxis], dmp[:, np.newaxis], Fs, Lh).sum(axis=0)
            H[r * Lg : (r + 1) * Lg, s * L : (s + 1) * L] = convmtx(h, Lg).T

    return H
def buildRIRMatrix(mics, sources, Lg, Fs, epsilon=5e-3, unit_damping=False):
    '''
    A function to build the channel matrix for many sources and microphones

    mics is a dim-by-M ndarray where each column is the position of a microphone
    sources is a list of SoundSource objects
    Lg is the length of the beamforming filters
    Fs is the sampling frequency
    epsilon determines how long the sinc is let to decay. Defaults to epsilon=5e-3
    unit_damping determines if the wall damping parameters are used or not. Default to false.

    returns the RIR matrix H = 

    --------------------
    | H_{11} H_{12} ...
    | ...
    |
    --------------------

    where H_{ij} is channel matrix between microphone i and source j.
    H is of type (M*Lg)x((Lg+Lh-1)*S) where Lh is the channel length (determined by epsilon),
    and M, S are the number of microphones, sources, respectively.
    '''

    from beamforming import distance
    from utilities import lowPassDirac, convmtx
    from scipy.linalg import toeplitz

    # set the boundaries of RIR filter for given epsilon
    d_min = np.inf
    d_max = 0.
    dmp_max = 0.
    for s in xrange(len(sources)):
        dist_mat = distance(mics, sources[s].images)
        if unit_damping == True:
            dmp_max = np.maximum((1. / (4 * np.pi * dist_mat)).max(), dmp_max)
        else:
            dmp_max = np.maximum((sources[s].damping[np.newaxis, :] /
                                  (4 * np.pi * dist_mat)).max(), dmp_max)
        d_min = np.minimum(dist_mat.min(), d_min)
        d_max = np.maximum(dist_mat.max(), d_max)

    t_max = d_max / constants.get('c')
    t_min = d_min / constants.get('c')

    offset = dmp_max / (np.pi * Fs * epsilon)

    # RIR length
    Lh = int((t_max - t_min + 2 * offset) * float(Fs))

    # build the channel matrix
    L = Lg + Lh - 1
    H = np.zeros((Lg * mics.shape[1], len(sources) * L))

    for s in xrange(len(sources)):
        for r in np.arange(mics.shape[1]):

            dist = sources[s].distance(mics[:, r])
            time = dist / constants.get('c') - t_min + offset
            if unit_damping == True:
                dmp = 1. / (4 * np.pi * dist)
            else:
                dmp = sources[s].damping / (4 * np.pi * dist)

            h = lowPassDirac(time[:, np.newaxis], dmp[:, np.newaxis], Fs,
                             Lh).sum(axis=0)
            H[r * Lg:(r + 1) * Lg, s * L:(s + 1) * L] = convmtx(h, Lg).T

    return H