I've got a script (Python) that chops 44.1 kHz realtime audio into 10 ms chunks, processes each chunk, and stitches the chunks back together with no added artifacts. I'm trying to create a low-pass filter that operates on each chunk, but every filter I've tried introduces unwanted artifacts.
I've tried creating various types filters, including IIR (Butterworth) and FIR (Hann, Hamming, rectangular windows, etc.), and Remez. The attempted methods of applying the filters to the input signal include just a straight transfer function, convolution, and a forward-then-backward filter (namely scipy.signal.filtfilt). I've also tried the moving average approach, but I don't know what to do near the endpoints of the chunk.
Is there such a filter that is designed for this kind of application?
INPUT WAVE (lots of harmonic content) |<-- 1 CHUNK -->| : : : : : : : : : ----- ---:- ----- : ----- -: :| | | : | | | : | | | : :| | | : | | | : | | | : :| | | : | | | : | | | : : ----- : ----- --:-- ----- : : : : : V V V V V V FILTER FILTER FILTER V V V V V V : : : : : --- -:- --- : --- : : / \ / : \ / \ : / \ : : / \ / : \ / \ : / \ /: :/ \ / : \ / \: / \ / : : --- : --- :-- --- : : : : : OUTPUT WAVE (less harmonic content)
EDIT: Following the answer from @hotpaw2, I wish to try the IIR approach first (I'm a novice at this, but my gut tells me try IIR first). For discussion purposes, let's define these arrays:
B = transfer function numerator coefficients A = transfer function denominator coefficients I0 = previous input array (same size) I1 = current input array (441 samples) R0 = previous output, post-filtered (DO WE NEED?) R1 = current output, desired post-filtered result array
Do I generate the initial conditions from I0 only, or do I need to figure R0 into the equation? To ask another way, here's the Python code I'm trying:
initCon = scipy.signal.filtic(B, A, I0)
Once I have this set of initial conditions, are they directly applied to the filter, or is there more that I need to do with them? Again, the Python code:
R1, _ = scipy.signal.lfilter(B, A, I1, z = initCon)
As the code stands now, it executes but there is a lot of off-frequency buzzing.