| Author | Topic: help with simple resonant RC_filter in AVR ASM | ||
|---|---|---|---|
|
|||
hello all,
i started experimenting with some simple DSP routines on an Atmega644 works surprisingly well so far - allready got 1 FM pair and 1 PWM/Saw Osc with separate vol EGs... my problem is the filter. I decided to implement a simple RC filter: a += f * ((in - a) + q * (a - b)); b += f * (a - b); without resonance the filter is working like a charm. but as soon as i raise Q i get horrible clipping. since i'm quite new to assembler, heres my source, maybe someone spots my error. http://chipmusik.de/lp.txt have a nice day, nemuri |
|||
| ^ | Joined: 25 Aug 2005 Member: #79200 Location: germany/bonn | ||
|
|||
a += f * ((in - a) + q * (a - b)); b += f * (a - b); If I understand correctly you have two 1 pole lowpass sections, with the 2nd one taped as highpass (in-out), so the feedback is bandpass? What looks odd to me is where you actualy adding in the feedback. I think it'd probably be better like this.. in += q * (a - b); a += f * (in - a); b += f * (a - b); Assuming you dont already know of it, there is a famous dsp version of the State Variable Filter. It's done in the same way, replacing electronic components with digital equivelants. Anyway here's some info on it... http://www.earlevel.com/Digital%20Audio/StateVar.h tml http://vellocet.com/dsp/svf/svf-stability.html plenty of code for filters, a few versions of the SVF http://www.musicdsp.org/archive.php?classid=3 |
|||
| ^ | Joined: 09 Dec 2003 Member: #10919 | ||
|
|||
| ^ | Joined: 25 Aug 2005 Member: #79200 Location: germany/bonn | ||
|
|||
Nemuri wrote: how the resonance comes in is explained in the famous thread
here Heh, I was going to post a link to that thread. q = feedback + feedback / (1.0 - f); |
|||
| ^ | Joined: 03 Dec 2006 Member: #131095 | ||
|
|||
Nemuri wrote:
Ok, lossy integrator == 1 pole lowpass filter. Now I understand why the resonance was done like that. He's scaling the resonance / feedback relative to frequency. Likey for stability reasons. [edit] it'd be like altering what i wrote to this.. in += f * (q * (a - b)); ermm.. so that looks fine, i guess it must be some issue with your assembler. Looks like you're using an 8 bit microcontroler Ok it's do-able, but rather you than me. Are you calculating f and q correctly? And it looks like your multiply instructions are only 8 bit? At least you're using the registers in 8 bit add/sub in one part and them in a multiply. I cant see that working very well, if at all. sub temp, ZL;\ sbc r21, ZH ;/ (a-b) signed mulsu r21,r22 ;mul signed:unsigned -> (a-b) * Q Looks to me like the result of (a-b) is spread across two registers. "temp|r21" But you're only using "r21" in the multiply. Which is the just the bottom half of the result and will cause some weirdness. In part cause it's basicly like extreme foldback clipping. Second cause the sign bit is now bit 8 of what was a 16 bit integer. Which actualy means the sign bit is now nothing to do with the sign of the original 16 bit number. Then again I dont know that particular microcontroler, so i could be completely wrong. *shrug* |
|||
| ^ | Joined: 09 Dec 2003 Member: #10919 | ||
|
|||
you need a minimum of a twelve-bit register to do a multimode filter if my memory is accurate. (often not, experiment for yourself..)
"Likey for stability reasons." actually that function adjusts the amplitude of the feedback to account for group-delay in the filter. each integrator introduces one sample of delay in a digital filter (generally) and this means the maximum frequency of the filter is (samplerate/4). "stability" actually is another issue, and the practical range of a filter like this is actually (samplerate/6.5), due to numerical stability issues. (classic newton issue.) the multimode / "state-variable" (#1) filter generally is uncompensated as it has only a single sample delay in it's feedback path meaning that a full range can be managed with 2x oversample. the first filter which is a sallen-key filter is much more unstable due to two samples of delay in it's feedback path. it simply isnt possible to correctly calculate a filter in dsp - period. you can only ever approximate the values that you should be getting to the point where noise, quantization and so on make it irrelevant. this is generally achieved via oversampling and a minimum of 2x oversampling is generally needed in every filter. additional oversampling can sometimes help, but it often does not. approximate compensations are generally used instead while the real phase error introduced into the filter is ignored. the only way to absolutely overcome this issue is to use infinite, or practically infinite (1024x or something?) oversample. 1) (this name isnt perfectly accurate as it can refer to other filters as well) the solution to your PROBLEM however is that you simply must hard-clip the feedback path. a hard-clip will introduce no distortion, avoiding aliasing while the feedback level remains below or equal to 1.0. a waveshaper/saturation will introduce distortion and result in aliasing - you should try to use a band-limited waveshaper. for example, if you use 2x oversample, you should use a waveshaping function with a band limit of 0.5. if you introduce frequencies above nyquist you will need to filter/convolve your output before decimating. |
|||
| ^ | Joined: 07 Dec 2004 Member: #50793 Location: Vancouver, Canada | ||
|
|||
juggled a little bit with the scaling...
now i've got this AVRfilter still not exactly resonating, and tends to overshoot, but i will try to limit the feedback like recomended |
|||
| ^ | Joined: 25 Aug 2005 Member: #79200 Location: germany/bonn | ||
|
|||
btw, i think the "theoretical" frequency limit of a filter like this without oversampling is sr/[2pi].
the "practical" limit however is like i said, sr/[6.5]. |
|||
| ^ | Joined: 07 Dec 2004 Member: #50793 Location: Vancouver, Canada | ||
|
|||
| ^ | Joined: 25 Aug 2005 Member: #79200 Location: germany/bonn | ||
|
|||
@aciddose:
great! the tip with the harclipping really solved the problem ringin-filter finally thank you very much! |
|||
| ^ | Joined: 25 Aug 2005 Member: #79200 Location: germany/bonn | ||
|
|||
if the chip doesn't have a clipping function, you should try something like this for fast clipping without a branch:
#define _B (15) //bits - 1 #define _SIGN(N) ((N)>>(_B)) #define _ABS(N) ((N)^_SIGN(N)) #define _CLIP(N,R) ((_ABS((N)+(R))-_ABS((N)-(R)+1))/2) lots of instructions though, (should be 12) you might want to use a branch (4 inst) if the chip does branching OK. |
|||
| ^ | Joined: 07 Dec 2004 Member: #50793 Location: Vancouver, Canada | ||
|
|||
aciddose wrote: "Likey for stability reasons." actually that function adjusts the amplitude of the feedback to account for group-delay in the filter. each integrator introduces one sample of delay in a digital filter (generally) and this means the maximum frequency of the filter is (samplerate/4). "stability" actually is another issue, and the practical range of a filter like this is actually (samplerate/6.5), due to numerical stability issues. (classic newton issue.) What I meant was that the point at which resonance occurs in your filter, and the SVF, and the moog variations you'll find online, doesnt stay fixed at the 3db point. (or 12 db in 4 pole ect) The gain at which resonance occurs varies with cutoff frequency. So you have to adjust the resonance gain in respect to frequency in order to keep the the resonance steady, and to stop it tipping over into a chaotic exploding filter. This is not instability because of numerical issues, truncation / rounding or such like. This is instability because mapping of the input parameters to the actual coeficients took them into unstable teritory. I mean you only have to go from an overall feedback gain of 0.99 to 1.01, to go from a 40db resonant peak, to broken tweeters and bleeding eardrums. The problem is that the resonance & frequency controls are never completely uncoupled. At least not in any of the filters whose code you'll find online. For example the way you tap the second pole to grab a highpass from it results in a filter that looses overall gain as it gets near to nyquist. Which actualy means the 3db point of the first pole and the 3db point of the highpass tap off the 2nd pole actualy start to drift apart the nearer you get to nyquist. Add into that mix the extra phase shift of the 1 sample delay, and the gain needed for a certain level of resonance is no longer the same across all frequencys. |
|||
| ^ | Joined: 09 Dec 2003 Member: #10919 | ||
|
|||
I ran the formulas for calculating the aciddose's filter in Excel:
f = 1.0 - exp(-2*pi * hz/rate); q = resonance + resonance / (1.0 - f); Freq f q Resonance 0 0 1.5 0.75 500 0.068759647 1.555377471 1000 0.132791405 1.614843827 1500 0.192420362 1.678700978 2000 0.247949252 1.747273126 2500 0.299659996 1.82090841 3000 0.347815128 1.899980676 3500 0.392659129 1.98489137 4000 0.434419673 2.076071584 4500 0.473308777 2.173984238 5000 0.509523879 2.279126431 5500 0.543248844 2.39203197 6000 0.574654892 2.513274072 6500 0.603901472 2.643468283 7000 0.631137067 2.783275595 7500 0.656499952 2.933405808 8000 0.680118894 3.094621129 8500 0.702113806 3.267740045 9000 0.722596355 3.453641479 9500 0.741670532 3.653269247 10000 0.759433175 3.867636857 The sample rate is 44100. What I notice is that q increases as cutoff frequency increases. nollock wrote: What I meant was that the point at which resonance occurs in your filter, and the SVF, and the moog variations you'll find online, doesnt stay fixed at the 3db point. (or 12 db in 4 pole ect) The gain at which resonance occurs varies with cutoff frequency. So you have to adjust the resonance gain in respect to frequency in order to keep the the resonance steady, and to stop it tipping over into a chaotic exploding filter. So the formula is designed so that q will increase the resonance gain with respect to the cutoff frequency to keep the overall resonance gain even? I've used this filter quite a bit. Can someone enlighten me as to how this formula: q = resonance + resonance / (1.0 - f); is arrived at? Could be the answer is over my head, but I'd love to hear it anyway. |
|||
| ^ | Joined: 03 Dec 2006 Member: #131095 | ||
|
|||
Leslie Sanford wrote: So the formula is designed so that q will increase the resonance gain with respect to the cutoff frequency to keep the overall resonance gain even? Yes. Although the problem is different with different filters. The basic issue is that it's the phase of the feedback that defines where the resonance peaks. With positive feedback the peak will be where the feeback signal is in phase (phase = 0, 2PI, 4PI ect), with negative feeback it is where the feedback signal is out of phase (phase = PI, 3PI, 5PI ect) But that point doesnt stay at a fixed gain. With ADs filter, it moves to lower gain as cuttoff increases so you need to bump the resonance up to compensate. With the 4 pole moog variants it increases gain with higher cutoff. This is basicly because as cuttoff frequency increases, the one sample delay in the feedback path add's more and more phase shift, so the point at which the total pahse shift = PI starts to lag behind the 12db point of the filter. ADs filter is a bit more complicated as it's a bandpass feedback, and the highpass off the 2nd pole causes different gain issues. So it's a combination of the filters phase/magnitude not tracking properly, and of the extra phase shift from the delay in the feedback. Quote: I've used this filter quite a bit. Can someone enlighten me as to how this formula: q = resonance + resonance / (1.0 - f); is arrived at? Could be the answer is over my head, but I'd love to hear it anyway. I dont know how AD came up with that, but I've been using pole/zero analysis to map the phase/gain which is then used to generate lookup tables. By that i mean I wrote a program that that does all the number crunching. It locates where the resonance occurs and what the overall gain in the feedback path is at that point. Thats basicly what it does anyway. |
|||
| ^ | Joined: 09 Dec 2003 Member: #10919 | ||
|
|||
aciddose wrote: btw, i think the "theoretical" frequency limit of a filter like this without oversampling is sr/[2pi].
the "practical" limit however is like i said, sr/[6.5]. Well, you can take it higher, but once you put in clipping, the aliasing starts causing trouble. Pink has essentially a tweaked version (more non-linearities and some minor tweaks) and oversamples by two times (with crappy filtering); at 44.1kHz it'll lose self oscillation at around 6k or so which means around sr/(7.35). It's damped down on purpose though, but back when I played with it, there was simply no reasonable way to make it track properly much higher so who cares. It's a nice filter though; here is a old test of my somewhat tweaked version in self-oscillation, with some white noise added (it would self-oscillate just as well without, but then it wouldn't sound so much like a whistle; live played from keyboard with oscillators fully turned off). |
|||
| ^ | Joined: 11 Feb 2006 Member: #97939 Location: Helsinki, Finland |
![]() |
All times are GMT - 8 Hours | |
|
Printable version |
||
![]() Previous Topic Next Topic |
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum |
Disclaimer: All communications made available as part of this forum and any opinions, advice, statements, views or other information expressed in this forum are solely provided by, and the responsibility of, the person posting such communication and not of kvraudio.com (unless kvraudio.com is specifically identified as the author of the communication).
Powered by phpBB © phpBB Group














