フィルタ

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

# biquad.lpf = function(fc, samprate) {
#   K = tan(pi * fc / samprate)
#   b0 =   K**2 / (1 + sqrt(2)*K + K**2)
#   b1 = 2*K**2 / (1 + sqrt(2)*K + K**2)
#   b2 =   K**2 / (1 + sqrt(2)*K + K**2)
#   a0 = 1
#   a1 = 2*(K**2-1) / (1 + sqrt(2)*K + K**2)
#   a2 = (1 - sqrt(2)*K + K**2) / (1 + sqrt(2)*K + K**2)
#   filt = Arma(c(b0, b1, b2), c(a0, a1, a2))
#   return(filt)
# }

# biquad.hpf = function(fc, samprate) {
#   K = tan(pi * fc / samprate)
#   b0 =  1 / (1 + sqrt(2)*K + K**2)
#   b1 = -2 / (1 + sqrt(2)*K + K**2)
#   b2 =  1 / (1 + sqrt(2)*K + K**2)
#   a0 = 1
#   a1 = 2*(K**2-1) / (1 + sqrt(2)*K + K**2)
#   a2 = (1 - sqrt(2)*K + K**2) / (1 + sqrt(2)*K + K**2)
#   filt = Arma(c(b0, b1, b2), c(a0, a1, a2))
#   return filt
# }

# biquad.lowshelf = function(fc, G, samprate) {
#   K = tan(pi * fc / samprate)
#   if (G >= 0.0) {
#     V0 = 10 ** (G/20)
#     b0 = (1 + sqrt(2*V0)*K + V0*K**2) / (1 + sqrt(2)*K + K**2)
#     b1 =              2*(V0*K**2 - 1) / (1 + sqrt(2)*K + K**2)
#     b2 = (1 - sqrt(2*V0)*K + V0*K**2) / (1 + sqrt(2)*K + K**2)
#     a0 = 1
#     a1 =                 2*(K**2 - 1) / (1 + sqrt(2)*K + K**2)
#     a2 =       (1 - sqrt(2)*K + K**2) / (1 + sqrt(2)*K + K**2)
#   } else {
#     V0 = 10 ** (-G/20)
#     b0 =       (1 + sqrt(2)*K + K**2) / (1 + sqrt(2*V0)*K + V0*K**2)
#     b1 =                 2*(K**2 - 1) / (1 + sqrt(2*V0)*K + V0*K**2)
#     b2 =       (1 - sqrt(2)*K + K**2) / (1 + sqrt(2*V0)*K + V0*K**2)
#     a0 = 1
#     a1 =              2*(V0*K**2 - 1) / (1 + sqrt(2*V0)*K + V0*K**2)
#     a2 = (1 - sqrt(2*V0)*K + V0*K**2) / (1 + sqrt(2*V0)*K + V0*K**2)
#   }
#   filt = Arma(c(b0, b1, b2), c(a0, a1, a2))
#   return filt
# }

# biquad.highshelf = function(fc, G, samprate) {
#   K = tan(pi * fc / samprate)
#   if (G >= 0.0) {
#     V0 = 10 ** (G/20)
#     b0 =   (V0 + sqrt(2*V0)*K + K**2) / (1 + sqrt(2)*K + K**2)
#     b1 =                2*(K**2 - V0) / (1 + sqrt(2)*K + K**2)
#     b2 =   (V0 - sqrt(2*V0)*K + K**2) / (1 + sqrt(2)*K + K**2)
#     a0 = 1
#     a1 =                 2*(K**2 - 1) / (1 + sqrt(2)*K + K**2)
#     a2 =       (1 - sqrt(2)*K + K**2) / (1 + sqrt(2)*K + K**2)
#   } else {
#     V0 = 10 ** (-G/20)
#     b0 =       (1 + sqrt(2)*K + K**2) / (V0 + sqrt(2*V0)*K + K**2)
#     b1 =                 2*(K**2 - 1) / (V0 + sqrt(2*V0)*K + K**2)
#     b2 =       (1 - sqrt(2)*K + K**2) / (V0 + sqrt(2*V0)*K + K**2)
#     a0 = 1
#     a1 =              2*(K**2/V0 - 1) / (1 + sqrt(2/V0)*K + K**2/V0)
#     a2 = (1 - sqrt(2/V0)*K + K**2/V0) / (1 + sqrt(2/V0)*K + K**2/V0)
#   }
#   filt = Arma(c(b0, b1, b2), c(a0, a1, a2))
#   return filt
# }

# biquad.peak = function(fc, G, Q, samprate) {
#   K = tan(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)
#   }
#   filt = Arma(c(b0, b1, b2), c(a0, a1, a2))
#   return filt
# }

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
2025-04-15