フィルタ

##### FILTER ##################################################################

def biquad_lpf(fc, samprate):
    """
    Biquad low-pass filter
    Usage:
       samprate = 44100
       b, a = biquad_lpf(1000, samprate)
       w, h = sig.freqz(b, a)
       plt.plot(w/np.pi*(samprate/2.0), amplitude_to_db(np.absolute(h)))
       plt.xlabel("Frequency (Hz)")
       plt.ylabel("Amplitude (dB)")
       plt.grid()
       plt.show()
    """
    K = np.tan(np.pi * fc / samprate)
    b0 =   K**2 / (1 + np.sqrt(2)*K + K**2)
    b1 = 2*K**2 / (1 + np.sqrt(2)*K + K**2)
    b2 =   K**2 / (1 + np.sqrt(2)*K + K**2)
    a0 = 1
    a1 = 2*(K**2-1) / (1 + np.sqrt(2)*K + K**2)
    a2 = (1 - np.sqrt(2)*K + K**2) / (1 + np.sqrt(2)*K + K**2)
    b = [b0, b1, b2]
    a = [a0, a1, a2]
    return(b, a)

def biquad_hpf(fc, samprate):
    K = np.tan(np.pi * fc / samprate)
    b0 =  1 / (1 + np.sqrt(2)*K + K**2)
    b1 = -2 / (1 + np.sqrt(2)*K + K**2)
    b2 =  1 / (1 + np.sqrt(2)*K + K**2)
    a0 = 1
    a1 = 2*(K**2-1) / (1 + np.sqrt(2)*K + K**2)
    a2 = (1 - np.sqrt(2)*K + K**2) / (1 + np.sqrt(2)*K + K**2)
    b = [b0, b1, b2]
    a = [a0, a1, a2]
    return(b, a)

def biquad_lowshelf(fc, G, samprate):
    K = np.tan(np.pi * fc / samprate)
    if (G >= 0.0):
        V0 = 10 ** (G/20)
        b0 = (1 + np.sqrt(2*V0)*K + V0*K**2) / (1 + np.sqrt(2)*K + K**2)
        b1 =                    2*(V0*K**2 - 1) / (1 + np.sqrt(2)*K + K**2)
        b2 = (1 - np.sqrt(2*V0)*K + V0*K**2) / (1 + np.sqrt(2)*K + K**2)
        a0 = 1
        a1 =                       2*(K**2 - 1) / (1 + np.sqrt(2)*K + K**2)
        a2 =       (1 - np.sqrt(2)*K + K**2) / (1 + np.sqrt(2)*K + K**2)
    else:
        V0 = 10 ** (-G/20)
        b0 =       (1 + np.sqrt(2)*K + K**2) / (1 + np.sqrt(2*V0)*K + V0*K**2)
        b1 =                       2*(K**2 - 1) / (1 + np.sqrt(2*V0)*K + V0*K**2)
        b2 =       (1 - np.sqrt(2)*K + K**2) / (1 + np.sqrt(2*V0)*K + V0*K**2)
        a0 = 1
        a1 =                    2*(V0*K**2 - 1) / (1 + np.sqrt(2*V0)*K + V0*K**2)
        a2 = (1 - np.sqrt(2*V0)*K + V0*K**2) / (1 + np.sqrt(2*V0)*K + V0*K**2)
    b = [b0, b1, b2]
    a = [a0, a1, a2]
    return(b, a)

def biquad_highshelf(fc, G, samprate):
    K = np.tan(np.pi * fc / samprate)
    if (G >= 0.0):
        V0 = 10 ** (G/20)
        b0 =   (V0 + np.sqrt(2*V0)*K + K**2) / (1 + np.sqrt(2)*K + K**2)
        b1 =                      2*(K**2 - V0) / (1 + np.sqrt(2)*K + K**2)
        b2 =   (V0 - np.sqrt(2*V0)*K + K**2) / (1 + np.sqrt(2)*K + K**2)
        a0 = 1
        a1 =                       2*(K**2 - 1) / (1 + np.sqrt(2)*K + K**2)
        a2 =       (1 - np.sqrt(2)*K + K**2) / (1 + np.sqrt(2)*K + K**2)
    else:
        V0 = 10 ** (-G/20)
        b0 =       (1 + np.sqrt(2)*K + K**2) / (V0 + np.sqrt(2*V0)*K + K**2)
        b1 =                       2*(K**2 - 1) / (V0 + np.sqrt(2*V0)*K + K**2)
        b2 =       (1 - np.sqrt(2)*K + K**2) / (V0 + np.sqrt(2*V0)*K + K**2)
        a0 = 1
        a1 =              2*(K**2/V0 - 1) / (1 + np.sqrt(2/V0)*K + K**2/V0)
        a2 = (1 - np.sqrt(2/V0)*K + K**2/V0) / (1 + np.sqrt(2/V0)*K + K**2/V0)
    b = [b0, b1, b2]
    a = [a0, a1, a2]
    return(b, a)

def biquad_peak(fc, G, Q, samprate):
    K = np.tan(np.pi * fc / samprate)
    if (G >= 0.0):
        V0 = 10 ** (G/20)
        b0 = (1 + V0/Q*K + K**2) / (1 + 1/Q*K + K**2)
        b1 =        2*(K**2 - 1) / (1 + 1/Q*K + K**2)
        b2 = (1 - V0/Q*K + K**2) / (1 + 1/Q*K + K**2)
        a0 = 1
        a1 =        2*(K**2 - 1) / (1 + 1/Q*K + K**2)
        a2 =  (1 - 1/Q*K + K**2) / (1 + 1/Q*K + K**2)
    else:
        V0 = 10 ** (-G/20)
        b0 =  (1 + 1/Q*K + K**2) / (1 + V0/Q*K + K**2)
        b1 =        2*(K**2 - 1) / (1 + V0/Q*K + K**2)
        b2 =  (1 - 1/Q*K + K**2) / (1 + V0/Q*K + K**2)
        a0 = 1
        a1 =        2*(K**2 - 1) / (1 + V0/Q*K + K**2)
        a2 = (1 - V0/Q*K + K**2) / (1 + V0/Q*K + K**2)
    b = [b0, b1, b2]
    a = [a0, a1, a2]
    return(b, a)

def filterbank(x, samprate, oct=1):
    ”'
    FILTERBANK   octave filterbank using raised cosine frequency window
        out, cfreqs = filterbank(x, samprate) create filtered signals `out' from x.
        Columns of `out' is a filtered signal with corresponding center
        frequency in `cfreqs'.  By default, 1/1-octave band filters are used.
        Filtered signals at the lowest frequency is processed with low-pass,
        the highest frequency is processed with high-pass, and all frequencies
        in between are processed with band-pass filters.  This yields to
        (almost) perfect reconstruction of the original signal, such that:
            out, cfreqs = filterbank(x, samprate)
            z = sum(out, 1)
        creates z almost the same as x.

        out, cfreqs = filterbank(x, samprate, oct) creates and filters using
        1/oct-octave band filters.
    ”'
    # prepare center frequencies
    cfreqs = 1000 * 2**(np.arange(-100, 100)/oct)
    cfreqs = cfreqs[np.logical_and(20<=cfreqs, cfreqs<=samprate/2)]
    # create octave-band bandpass filter
    if len(x) % 2 == 1:
        x = np.concatenate((x, [0]))
    out = np.zeros((len(x), len(cfreqs)))
    xx = scipy.fft(x)
    for n in range(len(cfreqs)):
        fc = cfreqs[n]
        fl = fc * 2**(-1/oct)
        fh = fc * 2**(+1/oct)
        W = np.zeros(len(xx)//2)
        f = np.linspace(0, samprate/2, len(W))
        ff = np.logical_and(fl<=f, f<=fh)
        cc = (np.cos(np.log2(f[ff]/fc)*math.pi*oct) + 1) / 2
        W[ff] = cc
        if n==0:
            W[f < fc] = 1
        elif n==len(cfreqs)-1:
            W[fc < f] = 1
        W = np.concatenate((W, np.flipud(W)))
        W[0] = 0
        W[len(W)//2] = 0
        # apply filter
        y = np.real(scipy.ifft(xx * W))
        out[:,n] = y
    return(out, cfreqs)



MARUI Atsushi
2026-03-25