Friday, 15 July 2016

modulation - Real-time modulated IIR filter


I've been learning to implement an IIR filter for a synthesizer project. It is now more or less stable when the parameters are constant, but ultimately I want the parameters to be arbitrarily modulated.


I figured it would be too slow to compute new recursion coefficients every sample, so instead I'm computing them every "chunk" (a piece of 256 or so samples which the synthesizer produces in a batch and then sends to the audio driver). This brings me to my question:


How should I approach hotswapping the recursion coefficients? Or is there a more correct way of modulating IIR filters?



I am curently linearly interpolating the output of the model generated in the last chunk with the one generated in the current. (at the beginning of the chunk, the output is 100% from the old one, and at the end 100% from the new one) This isn't enough, since the new filter needs to be initialized somehow. I have tried some things with various degrees of success:




  • The new filter is initialized with signal history pulled from the old one.


    This sounds the best, but when too heavy modulation is applied (for example, the cutoff frequency changes too much at once), the new filter might initially output an uncontrollable spike which then peaks. This mostly happens along with a discontinuity in the input signal.


    Here's a 60 Hz saw wave LP-filtered using a cutoff oscillating at 20 Hz. (the filter is configured to have two biquads). Such a spike never occurs when the cutoff frequency is kept constant.




Peaking filtered signal





  • The filter history is initialized in a stable state. (e.g. constant signal in and out at the intensity of the last seen sample for LP, or plain zero)


    This causes some audible rattle when modulating, no matter how I try to fade in the new filter gradually. The new filter never quite reaches the old one's state.




All ideas and advice are welcome.


Edit:


I have implemented the biquads in a lattice topology, as per Robert's suggestion. Modulation now works great, but raising the cutoff frequency too high (or too low for a high pass filter) breaks something. This should be a single biquad low pass filter with cutoff $\frac{3}{4}\pi$:



The direct form parameters, from which the lattice is derived, work just fine. It is certainly possible, that there is some error in my equations for the conversion. I also noticed that the shape of the frequency response isn't quite as steep as with the direct form. I am suspecting it has something to do with the "tap" coefficients..



What could be going on now? Perhaps I should make a new question with details about my implementation, as the original issue is now more or less solved.



Answer



okay, using the snipping tool, i tried to put in just the 2nd-order IIR lattice in the following drawing. $x[n]$ is being input in the upper left. the numbering for the $v_*$ coefficients is horrible, but i just cut this drawing out from somewhere else.


biquad lattice


now the transfer function i get for this is


$$ H(z) = \frac{Y(z)}{X(z)} = \frac{v_4 + v_3(-k_1 + z^{-1}) + v_2\big(-k_2+k_1(k_2-1)z^{-1} + z^{-2}\big)}{1 + k_1(k_2-1) z^{-1} - k_2 z^{-2}}$$


and if you compare that to the standard direct form


$$ H(z) = \frac{b_0 + b_1 z^{-1} + b_2 z^{-2}}{1 + a_1 z^{-1} + a_2 z^{-2}} $$


you should have equivalence when


$$\begin{align} k_2 &= -a_2 \\ k_1 &= -\frac{a_1}{a_2+1} \\ \\ v_2 &= b_2 \\ v_3 &= b_1 - a_1 b_2 \\ v_4 &= b_0 - \frac{a_1}{a_2+1} b_1 + \left( \frac{a_1^2}{a_2+1} - a_2 \right)b_2 \\ \end{align}$$



i would appreciate it if someone else would check my work. i could well have fucked up a sign or something.


so, wherever you get your five Direct Form $a_k$ and $b_k$ coefficients (e.g., the Cookbook, but remember to divide everything by $a_0$), you can convert them to the five Lattice Form coefficients with the above equations (assuming i didn't mess it up).


No comments:

Post a Comment

readings - Appending 内 to a company name is read ない or うち?

For example, if I say マイクロソフト内のパートナーシップは強いです, is the 内 here read as うち or ない? Answer 「内」 in the form: 「Proper Noun + 内」 is always read 「ない...