Because we are using PI * fc/fs here, the maximum value which gets input to the tan function is PI/2 ... which sadly results in +inf. Using 2x oversampling you can go very safely up to outputRate/2 (which equals PI/4 and tan(PI/4)==1).antto wrote:tan(pi*fc/fs)
tan() grows to +inf then goes from -inf back to +inf .. is that correct?!
or is this meant to work only _with_ oversampling?
Integrator filter with delayless feedback path
-
- KVRist
- Topic Starter
- 239 posts since 22 Jan, 2007 from Germany
Last edited by neotec on Thu Nov 17, 2011 10:12 am, edited 1 time in total.
... when time becomes a loop ...
---
Intel i7 3770k @3.5GHz, 16GB RAM, Windows 7 / Ubuntu 16.04, Cubase Artist, Reaktor 6, Superior Drummer 3, M-Audio Audiophile 2496, Akai MPK-249, Roland TD-11KV+
---
Intel i7 3770k @3.5GHz, 16GB RAM, Windows 7 / Ubuntu 16.04, Cubase Artist, Reaktor 6, Superior Drummer 3, M-Audio Audiophile 2496, Akai MPK-249, Roland TD-11KV+
- KVRAF
- 8476 posts since 12 Feb, 2006 from Helsinki, Finland
Yeah it's correct. It becomes +inf at pi/2 which is when fc/fs=1/2 ie Nyquist.antto wrote:tan(pi*fc/fs)
tan() grows to +inf then goes from -inf back to +inf .. is that correct?!
or is this meant to work only _with_ oversampling?
What's going on here is that bilinear transform maps the (analog) infinite frequency to the Nyquist frequency, so if we want to have cutoff at Nyquist, we must design an analog prototype that would have cutoff at infinity.
- KVRAF
- 12615 posts since 7 Dec, 2004
yes, that's correct.antto wrote:tan() grows to +inf then goes from -inf back to +inf .. is that correct?!
Free plug-ins for Windows, MacOS and Linux. Xhip Synthesizer v8.0 and Xhip Effects Bundle v6.7.
The coder's credo: We believe our work is neither clever nor difficult; it is done because we thought it would be easy.
Work less; get more done.
The coder's credo: We believe our work is neither clever nor difficult; it is done because we thought it would be easy.
Work less; get more done.
- KVRAF
- 2569 posts since 4 Sep, 2006 from 127.0.0.1
oh, excuse me, i was plotting the tan() with my curve plotter set to x[0,5] which made it cycle more times
now looking at it correctly, where fc/fs goes to 0.5 as it should, it only reaches +inf at nyquist
2x oversampling would make it only reach 1.0
so uhm..
i understand the idea i think..
for a more complex filter like a ladder
the feedback value comes from the 4th stage (aka output)
to reduce this - oversampling can be used to make this 1 sample delay "smaller" (as duration)
the real analog filter also has such delay but is so small..
an insane factor of oversampling would make the filter work, but will introduce precision problems at low freqs..
the KeepTopology stuff to me looks like an "adaptive" amount of reducing the delay
i still don't understand exactly how it works..
i have a feedback compressor which also suffers from this 1 sample delay, i think i'll be able to make it delayless after examining the one-pole code here ^
now looking at it correctly, where fc/fs goes to 0.5 as it should, it only reaches +inf at nyquist
2x oversampling would make it only reach 1.0
so uhm..
this is the 1st order LP filter (aka R-C filter) ?neotec wrote: transformed into a delayless one pole lowpass:and 'f' is now:Code: Select all
pin = in - (f * in + buf) / (1 + f) out = buf + f * pin buf = f * pin + outCode: Select all
f = tan(PI * fc / fs)
i understand the idea i think..
for a more complex filter like a ladder
the feedback value comes from the 4th stage (aka output)
to reduce this - oversampling can be used to make this 1 sample delay "smaller" (as duration)
the real analog filter also has such delay but is so small..
an insane factor of oversampling would make the filter work, but will introduce precision problems at low freqs..
the KeepTopology stuff to me looks like an "adaptive" amount of reducing the delay
i still don't understand exactly how it works..
i have a feedback compressor which also suffers from this 1 sample delay, i think i'll be able to make it delayless after examining the one-pole code here ^
It doesn't matter how it sounds..
..as long as it has BASS and it's LOUD!
irc.libera.chat >>> #kvr
..as long as it has BASS and it's LOUD!
irc.libera.chat >>> #kvr
-
- KVRist
- Topic Starter
- 239 posts since 22 Jan, 2007 from Germany
The idea is more or less simple, antto:antto wrote:i still don't understand exactly how it works..
i have a feedback compressor which also suffers from this 1 sample delay, i think i'll be able to make it delayless after examining the one-pole code here ^
Consider an analogue lowpass filter build using an integrator and a negative feedback loop:
Code: Select all
in >---[-]--[Integrator]---+--> out
| |
| |
|--------<---------|
Code: Select all
out = integrator(in - lastOut)This would be the naive digital implementation (based on the equation above) where you can clearly see our unit delay:
Code: Select all
in >---[-]--[Integrator]---+--> out
| |
| |
|---<--[z^-1]--<---|
And now we apply this for our Integrator filter:
A bilinear integrator is given by:
Code: Select all
out = buf + f * input
buf = f * input + outNow we make it a lowpass filter:
Code: Select all
// out = integrator(in - lastOut)
iin = input - lastOut
out = buf + f * iin
buf = f * iin + outCode: Select all
iin = input - outCode: Select all
I. Our input and output calculation
iin = input - out
out = buf + f * iin
II. Replace 'iin' in 'out' equation
out = buf + f * (input - out)
III. Solve for out
out = buf + f * input - f * out
out + f * out = buf + f * input
out * (1 + f) = buf + f * input
out = (buf + f * input) / (1 + f)Code: Select all
iin = input - ((buf + f * input) / (1 + f))
out = buf + f * iin
buf = f * iin + outYou can of course drop the 'out' calculation in the LPF above and only use the predicted value:
Code: Select all
out = (buf + f * input) / (1 + f);
buf = f * (input - out) + out
Last edited by neotec on Thu Nov 17, 2011 3:52 pm, edited 2 times in total.
... when time becomes a loop ...
---
Intel i7 3770k @3.5GHz, 16GB RAM, Windows 7 / Ubuntu 16.04, Cubase Artist, Reaktor 6, Superior Drummer 3, M-Audio Audiophile 2496, Akai MPK-249, Roland TD-11KV+
---
Intel i7 3770k @3.5GHz, 16GB RAM, Windows 7 / Ubuntu 16.04, Cubase Artist, Reaktor 6, Superior Drummer 3, M-Audio Audiophile 2496, Akai MPK-249, Roland TD-11KV+
- KVRAF
- 8476 posts since 12 Feb, 2006 from Helsinki, Finland
Not really. Let's treat state as constant first and we have output=filter(input+k*output) for some value of input and k (and constant state). The output is an unknown, for which we want to find a solution. If the filter is linear it's easy enough to solve this directly.antto wrote: the KeepTopology stuff to me looks like an "adaptive" amount of reducing the delay
The iterative version finds an approximate solution by relying on the idea that when we calculate the output with some initial guess as the feedback, we'll get a better estimate than our initial guess. We then repeat this until the last guess and calculated result are close enough to each other, at which point we can consider them equal.
Once we have solved the output we don't need any delay in the feedback loop anymore, and we'll just calculate the filter for the purpose of updating state variables (though you could solve for new values of those as well if you wanted).
edit: seems I was too slow on this
- KVRAF
- 2569 posts since 4 Sep, 2006 from 127.0.0.1
so, here "buf" is actually the output, right?Code: Select all
out = (buf + f * input) / (1 + f); buf = f * (input - out) + out
"out" is predicted "current" output sample?
It doesn't matter how it sounds..
..as long as it has BASS and it's LOUD!
irc.libera.chat >>> #kvr
..as long as it has BASS and it's LOUD!
irc.libera.chat >>> #kvr
- KVRAF
- 8476 posts since 12 Feb, 2006 from Helsinki, Finland
No. Buf is the delay of the integrator. Out is the solution for the output (ie "predicted" output).antto wrote: so, here "buf" is actually the output, right?
"out" is predicted "current" output sample?
The whole thing is about calculating the output before actually doing any filtering. We don't need the filtering to get the output. We just need to know the state of the filter and the input. Once we have BOTH input and output, we can figure out how to update the state of the filter (so we can then process the next sample) but it's not necessary to actually calculate the filter just to know what the output will be.
- KVRAF
- 2569 posts since 4 Sep, 2006 from 127.0.0.1
uhm, so this isn't the whole filter, just the "y0" prediction
the whole filter would then be:
or am i wrong again? 
the whole filter would then be:
Code: Select all
// x0 == input
out = (buf + f * input) / (1 + f);
buf = f * (input - out) + out;
// -----------
y0 = out; // predicted
y0 = x0 + f * (y0 - x0); // 1st order LPF
// filter output is now y0
It doesn't matter how it sounds..
..as long as it has BASS and it's LOUD!
irc.libera.chat >>> #kvr
..as long as it has BASS and it's LOUD!
irc.libera.chat >>> #kvr
-
- KVRist
- Topic Starter
- 239 posts since 22 Jan, 2007 from Germany
These two lines is the whole one pole lowpass filter:antto wrote:or am i wrong again?
Code: Select all
double lowpass1pole(double input)
{
out = (buf + f * input) / (1 + f);
buf = f * (input - out) + out
return out;
}
... when time becomes a loop ...
---
Intel i7 3770k @3.5GHz, 16GB RAM, Windows 7 / Ubuntu 16.04, Cubase Artist, Reaktor 6, Superior Drummer 3, M-Audio Audiophile 2496, Akai MPK-249, Roland TD-11KV+
---
Intel i7 3770k @3.5GHz, 16GB RAM, Windows 7 / Ubuntu 16.04, Cubase Artist, Reaktor 6, Superior Drummer 3, M-Audio Audiophile 2496, Akai MPK-249, Roland TD-11KV+
-
- KVRAF
- 7578 posts since 17 Feb, 2005
I am somewhat ignorant when it comes to the inner workings of filters, but I am interested in these non-linear stages. Are these implemented between poles as waveshaping functions, and normalized?
- KVRAF
- 12615 posts since 7 Dec, 2004
the more interesting shaping goes on applied to the delta values inside the "poles" rather than between them.
generally it's implemented as naive waveshapers between, though, yes.
generally it's implemented as naive waveshapers between, though, yes.
Free plug-ins for Windows, MacOS and Linux. Xhip Synthesizer v8.0 and Xhip Effects Bundle v6.7.
The coder's credo: We believe our work is neither clever nor difficult; it is done because we thought it would be easy.
Work less; get more done.
The coder's credo: We believe our work is neither clever nor difficult; it is done because we thought it would be easy.
Work less; get more done.
-
- KVRist
- Topic Starter
- 239 posts since 22 Jan, 2007 from Germany
I'm currently very happy with just shaping the state variables (buffers I called them). Using this approach gives great results (IMHO) while preserving the predictability of the system.
Although wave shaping the state variables still messes around with resonance gain and (depending on the shaper) even cutoff.
Nevertheless using this feedback solving approach I now got a cool 24dB lowpass, 12dB SVF and even a 24dB SVF (using Linkwitz-Riley crossover). All of those are prefectly tuned and self oscillate ... that's all I need
The 24dB SVF is a bit overkill because you have 4 feedback paths and I will probably just cascade 2 12dB SVFs to have a 24dB, I mainly did it as a prove of concept.
One thing that still bothers me is that you can't just do 'input - LPF24dB(input)' and have a cool HPF (the frequency response is far from correct then). So far I didn't had success creating a real 24dB HPF using integrator high passes and get the same resonance behaviour as in the low pass version. I just fail on solving the high pass feedback equations^^
Here's the 24dB SVF in pseudo DSP block diagram (just FYI):
Although wave shaping the state variables still messes around with resonance gain and (depending on the shaper) even cutoff.
Nevertheless using this feedback solving approach I now got a cool 24dB lowpass, 12dB SVF and even a 24dB SVF (using Linkwitz-Riley crossover). All of those are prefectly tuned and self oscillate ... that's all I need
The 24dB SVF is a bit overkill because you have 4 feedback paths and I will probably just cascade 2 12dB SVFs to have a 24dB, I mainly did it as a prove of concept.
One thing that still bothers me is that you can't just do 'input - LPF24dB(input)' and have a cool HPF (the frequency response is far from correct then). So far I didn't had success creating a real 24dB HPF using integrator high passes and get the same resonance behaviour as in the low pass version. I just fail on solving the high pass feedback equations^^
Here's the 24dB SVF in pseudo DSP block diagram (just FYI):
Code: Select all
HP
|
in-->-(+)--+-[i0]-+-[i1]-+-[i2]-+-[i3]-+->LP
| | | | |
(+)--(*-a)--| | | |
| | | |
(+)-----(*-r)------|--BP | |
| | |
(+)--------(*-a)----------| |
| |
(+)-----------(*-1)--------------|
i0..3 bilinear integrators (f = tan(PI*fc/fs))
a = 2*sqrt(2)
r = 2 / q
q >= 0.5... when time becomes a loop ...
---
Intel i7 3770k @3.5GHz, 16GB RAM, Windows 7 / Ubuntu 16.04, Cubase Artist, Reaktor 6, Superior Drummer 3, M-Audio Audiophile 2496, Akai MPK-249, Roland TD-11KV+
---
Intel i7 3770k @3.5GHz, 16GB RAM, Windows 7 / Ubuntu 16.04, Cubase Artist, Reaktor 6, Superior Drummer 3, M-Audio Audiophile 2496, Akai MPK-249, Roland TD-11KV+
- KVRAF
- 12615 posts since 7 Dec, 2004
of course, that should bother anyone. that's because the output phase isn't correct using this method.neotec wrote:One thing that still bothers me is that you can't just do 'input - LPF24dB(input)' and have a cool HPF (the frequency response is far from correct then).
that's a simple fact of life. analog filters deal with this by not bothering to deal with it. just retune the scale and offset to get as close to what you want as you can. remaining error is just that, remaining error.neotec wrote:Although wave shaping the state variables still messes around with resonance gain and (depending on the shaper) even cutoff.
Free plug-ins for Windows, MacOS and Linux. Xhip Synthesizer v8.0 and Xhip Effects Bundle v6.7.
The coder's credo: We believe our work is neither clever nor difficult; it is done because we thought it would be easy.
Work less; get more done.
The coder's credo: We believe our work is neither clever nor difficult; it is done because we thought it would be easy.
Work less; get more done.
-
- KVRist
- Topic Starter
- 239 posts since 22 Jan, 2007 from Germany
The phase is correct. If it wouldn't be, the resonance peaks wouldn't occur perfectly at 'fc' (for all 'fc'). I've plotted the 4th order ladder filter, -180° at fc, -90° at fc*0.4 ... works as expected (compared to a bode plot of a 'perfect' 4th order lowpass filter).aciddose wrote:of course, that should bother anyone. that's because the output phase isn't correct using this method.
... when time becomes a loop ...
---
Intel i7 3770k @3.5GHz, 16GB RAM, Windows 7 / Ubuntu 16.04, Cubase Artist, Reaktor 6, Superior Drummer 3, M-Audio Audiophile 2496, Akai MPK-249, Roland TD-11KV+
---
Intel i7 3770k @3.5GHz, 16GB RAM, Windows 7 / Ubuntu 16.04, Cubase Artist, Reaktor 6, Superior Drummer 3, M-Audio Audiophile 2496, Akai MPK-249, Roland TD-11KV+
