I would like to apply a FIR or IIR filter (example: lowpass filter) on successive blocks/time-frames of 1024 samples each.
Possible applications:
realtime audio processing, such as EQing. At a precise time, we only have the next 1024 samples in a buffer. The next samples to process are not available yet (realtime).
make a cutoff-time-varying filter by splitting the input signal in blocks, as suggested in this answer.
I tried this here:
import numpy as np
from scipy.io import wavfile
from scipy.signal import butter, lfilter, filtfilt, firwin
sr, x = wavfile.read('input.wav')
x = np.float32(x)
y = np.zeros_like(x)
N = 1024 # buffer block size = 23ms for a 44.1 Khz audio file
f = 1000 # cutoff
pos = 0 # position
while True:
b, a = butter(2, 2.0 * f / sr, btype='low')
y[pos:pos+N] = filtfilt(b, a, x[pos:pos+N])
pos += N
f -= 1 # cutoff decreases of 1 hz every 23 ms, but the issue described here also present with constant cutoff!
print f
if pos+N > len(x):
break
y /= max(y) # normalize
wavfile.write('out_fir.wav', sr, y)
I tried:
both with a Butterworth filter or a FIR (replace the line before by
b, a = firwin(1000, cutoff=f, fs=sr), 1.0
)both with
lfilter
andfiltfilt
(the latter has the advantage to apply the filter forward and backwards, and this solves phase issues),
but here is the problem:
At the boundaries of each time-frames' output, there is a continuity issue, that makes the audio signal heavily distorded.
How to solve this discontinuity problem? I thought about windowing+OverlapAdd method, but there surely must be an easier way.
z_f
output andz_i
input parameters oflfilt
. You need to setz_i
of the filter for the current block toz_f
of the filter of the previous block. That way your filter state is persisted from one block to the next. This topic from dsp stackexchange might also be useful. dsp.stackexchange.com/questions/28725/… Also it would probably be a good idea for you to understand the basics of how a filter is built up internally so this all makes sense. – Binucleatea
,b
too)? – Freakishcreate a ramp function from parameter start value to parameter end value and try to make the change as smooth as possible, not instantly
: how would you do a more continuous ramp than a few hz for each buffer/block? (Thanks again for all the tips, it really helped me!) – Freakish