##### 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)