Hi all,
Here is my first attempt at making a resonant lowpass filter using cpole~ and czero~ objects. It's the first version I've made which actually sounds halfway towards what I want to achieve, which is a decent diode-ladder or transistor-ladder filter emulation. I want to make this using only vanilla objects, particularly rpole~, cpole~ etc. so that they can be ultra-portable and signal-controlled. Also, http://www.timstinchcombe.co.uk/index.php?pge=poles#diode
Does anyone else have any ideas, or patches we can share?
Ed Gemnotes-0.1alpha: Live music notation for Pure Data http://sharktracks.co.uk/
De: "Ed Kelly" morph_2016@yahoo.co.uk
Hi all,
Here is my first attempt at making a resonant lowpass filter using cpole~ and czero~ objects. It's the first version I've made which actually sounds halfway towards what I want to achieve, which is a decent diode-ladder or transistor-ladder filter emulation. I want to make this using only vanilla objects, particularly rpole~, cpole~ etc. so that they can be ultra-portable and signal-controlled. Also, http://www.timstinchcombe.co.uk/index.php?pge=poles#diode
Does anyone else have any ideas, or patches we can share?
Ed Gemnotes-0.1alpha: Live music notation for Pure Data http://sharktracks.co.uk/
hello,
using biquad~ gives very nice results for resonant filtering, ggee audio filters show how it sounds. It should be possible to use vanilla's audio math objects only for the biquad mathematical functions instead of an external.
On 2/2/12, Patrice Colet colet.patrice@free.fr wrote:
De: "Ed Kelly" morph_2016@yahoo.co.uk
Hi all,
Here is my first attempt at making a resonant lowpass filter using cpole~ and czero~ objects. It's the first version I've made which actually sounds halfway towards what I want to achieve, which is a decent diode-ladder or transistor-ladder filter emulation. I want to make this using only vanilla objects, particularly rpole~, cpole~ etc. so that they can be ultra-portable and signal-controlled. Also, http://www.timstinchcombe.co.uk/index.php?pge=poles#diode
Does anyone else have any ideas, or patches we can share?
Ed
Gemnotes-0.1alpha: Live music notation for Pure Data http://sharktracks.co.uk/
hello,
using biquad~ gives very nice results for resonant filtering, ggee audio filters show how it sounds. It should be possible to use vanilla's audio math objects only for the biquad mathematical functions instead of an external.
Hi Ed, Patrice
This patch ds~ (damped sines) uses the biquad. It works as a resonant filter--I like to feed it impulses. The arguments to the patch are frequency and the number of ms to decay 10 dB ( I think). Copied below. Chuck
#N canvas 0 0 337 561 10; #X obj 12 384 biquad~; #X obj 57 351 pack f f f f f; #X obj 145 188 exp; #X obj 156 98 * 44.1; #X text 209 96 ms to samples; #X obj 156 119 t b f; #X obj 145 154 / 44100; #X msg 91 118 -2.30259; #X obj 145 219 t f f; #X obj 17 148 * 6.28319; #X obj 63 208 sin; #X obj 26 210 cos; #X obj 60 257 * 2; #X obj 45 290 * 1; #X obj 92 256 t f f; #X obj 92 279 * 1; #X obj 82 313 * -1; #X msg 132 302 0; #X obj 166 303 * 1; #X msg 199 302 0; #X obj 32 119 / 44100; #X obj 34 180 t f f; #X text 176 189 a; #X text 13 229 cos and sin of b; #X obj 32 78 unpack f f; #X obj 56 460 outlet~; #X obj 11 31 inlet~; #X obj 73 32 inlet; #X obj 158 8 loadbang; #X obj 158 53 $1; #X obj 188 53 $2; #X obj 158 30 t b b; #X obj 124 75 pack 100 10; #X connect 0 0 25 0; #X connect 1 0 0 0; #X connect 2 0 8 0; #X connect 3 0 5 0; #X connect 5 0 7 0; #X connect 5 1 6 1; #X connect 6 0 2 0; #X connect 7 0 6 0; #X connect 8 0 12 0; #X connect 8 1 14 0; #X connect 8 1 17 0; #X connect 8 1 19 0; #X connect 8 1 18 1; #X connect 9 0 21 0; #X connect 10 0 18 0; #X connect 11 0 13 0; #X connect 12 0 13 1; #X connect 13 0 1 0; #X connect 14 0 15 0; #X connect 14 1 15 1; #X connect 15 0 16 0; #X connect 16 0 1 1; #X connect 17 0 1 2; #X connect 18 0 1 3; #X connect 19 0 1 4; #X connect 20 0 9 0; #X connect 21 0 11 0; #X connect 21 1 10 0; #X connect 24 0 20 0; #X connect 24 1 3 0; #X connect 26 0 0 0; #X connect 27 0 24 0; #X connect 28 0 31 0; #X connect 29 0 32 0; #X connect 30 0 32 1; #X connect 31 0 29 0; #X connect 31 1 30 0; #X connect 32 0 24 0;
Le 2012-02-02 à 12:50:00, Patrice Colet a écrit :
De: "Ed Kelly" morph_2016@yahoo.co.uk Here is my first attempt at making a resonant lowpass filter using cpole~ and czero~ objects.
using biquad~ gives very nice results for resonant filtering, ggee audio filters show how it sounds. It should be possible to use vanilla's audio math objects only for the biquad mathematical functions instead of an external.
[biquad~] is actually a shortcut for a certain set of special cases of having (up to) two [cpole~] and two [czero~] at once.
It's related to how quadratics like ax²+bx+c can't be factorised into e(x-f)(x-g) in real space because you need negative square roots to make it always factorisable, otherwise the squareroot fails when b²-4ac < 0, which is also the condition for resonance ; yet e(x-f)(x-g) in complex space also covers things that are impossible in real ax²+bx+c.
So a real ax²+bx+c is something between a pair of [rpole~] and a pair of [cpole~]. It's equivalent to a pair of [cpole~] in which you force two numbers to be the same, and two other numbers to be negatives of each other.
When you have a pair of [rpole~], it's like specifying f and g as real numbers, and thus being unable to construct any «irreducible» quadratics (b²<4ac). the numbers that are negatives of each other are the ± square roots : ± sqrt(4ac-b²)/2a.
(I hope I didn't make a mistake, and if I did, I'd like to know)
| Mathieu BOUCHARD ----- téléphone : +1.514.383.3801 ----- Montréal, QC
Le 2012-02-02 à 11:40:00, Mathieu Bouchard a écrit :
So a real ax²+bx+c is something between a pair of [rpole~] and a pair of [cpole~]. It's equivalent to a pair of [cpole~] in which you force two numbers to be the same, and two other numbers to be negatives of each other.
Actually, [bp~] is pretty much a 2-pole resonant real filter, right ? The input parameters f (centre freq) and s (sampling rate) and Q are transformed like this :
ω = 2πf/s r = 1-ω/Q a = -r² b = 2r*cos(ω) c = 1 (an overall gain is applied separately, which is like scaling a,b,c all at once)
however, in this case, b²-4ac = 4r²*(1+cos²(ω)) is always positive, so it does not cover the unfactorisable cases, which have to be done using [cpole~] or [biquad~] (whichever is more efficient). It seems that [bp~] is a mere combination of a [lop~], a [hip~] and a [*~] (plus the calculation of their coefficients).
I'm still learning about this topic... so, again, I might be saying something wrong in there.
| Mathieu BOUCHARD ----- téléphone : +1.514.383.3801 ----- Montréal, QC
On Thu, Feb 2, 2012 at 1:37 PM, Mathieu Bouchard matju@artengine.ca wrote:
Le 2012-02-02 à 11:40:00, Mathieu Bouchard a écrit : Actually, [bp~] is pretty much a 2-pole resonant real filter, right ?
Yep. Both poles sit right on top of each other along the real axis.
The input parameters f (centre freq) and s (sampling rate) and Q are transformed like this :
ω = 2πf/s r = 1-ω/Q a = -r² b = 2r*cos(ω) c = 1 (an overall gain is applied separately, which is like scaling a,b,c all at once)
I don't think this is entirely accurate. I think a and c should be switched here, though of course when finding b²-4ac that doesn't really matter. Also, when applying a gain to a recursive filter, it's not really the same as scaling all the coefficients. If you were to scale them first, then the gain would affect the feedback portions of the filter. Applying the gain after means the feedback samples are not scaled by the gain.
If you think of it in terms of its transfer function, it would look more like this:
H(z) = g*(1 / (1 - 2r*cos(ω)*(z^-1) + r^2 * z(^-2) ))
Looking at it that way, the gain simply becomes the numerator and does not affect the feedback coefficients in the denominator. This equates to simply scaling the input of the filter.
It seems that [bp~] is a mere combination of a [lop~], a [hip~] and a [*~] (plus the calculation of their coefficients).
But [hip~] isn't an all-pole filter. It has a zero at DC.
.mmb
-- Mike Moser-Booth - mmoserbooth@gmail.com Master's Student in Music Technology Schulich School of Music, McGill University Centre for Interdisciplinary Research in Music Media and Technology
"If you think education is expensive, try ignorance" -Derek Bok
Le 2012-02-02 à 19:13:00, Mike Moser-Booth a écrit :
a = -r² b = 2r*cos(ω) c = 1 (an overall gain is applied separately, which is like scaling a,b,c all at once)
I don't think this is entirely accurate. I think a and c should be switched here, though of course when finding b²-4ac that doesn't really matter.
It depends whether you write ax²+bx+c or a+bx+cx². Both forms are convenient, and the latter expands better in cases of variable degrees (letters don't get renamed when adding a term), but the former is more common for cases that have only a degree fixed at 2 or 3.
Also, when applying a gain to a recursive filter, it's not really the same as scaling all the coefficients. If you were to scale them first, then the gain would affect the feedback portions of the filter. Applying the gain after means the feedback samples are not scaled by the gain.
Those filters are all linear. This means that you can effectively commute them with a constant gain [*~] without any difference. However, it will make a difference when the gain of [*~] changes quickly while the main input changes too.
If you think of it in terms of its transfer function, it would look more like this: H(z) = g*(1 / (1 - 2r*cos(ω)*(z^-1) + r^2 * z(^-2) ))
Well, I was thinking of it in terms of 1/H(z) or 1/gH(z).
But are you sure that you got the signs right in the denominator ?
It seems that [bp~] is a mere combination of a [lop~], a [hip~] and a [*~] (plus the calculation of their coefficients).
But [hip~] isn't an all-pole filter. It has a zero at DC.
oops.
| Mathieu BOUCHARD ----- téléphone : +1.514.383.3801 ----- Montréal, QC
On Sun, Feb 19, 2012 at 1:04 PM, Mathieu Bouchard matju@artengine.ca wrote:
Le 2012-02-02 à 19:13:00, Mike Moser-Booth a écrit :
I don't think this is entirely accurate. I think a and c should be switched here, though of course when finding b²-4ac that doesn't really matter.
It depends whether you write ax²+bx+c or a+bx+cx². Both forms are convenient, and the latter expands better in cases of variable degrees (letters don't get renamed when adding a term), but the former is more common for cases that have only a degree fixed at 2 or 3.
Ah, okay.
Also, when applying a gain to a recursive filter, it's not really the same as scaling all the coefficients. If you were to scale them first, then the gain would affect the feedback portions of the filter. Applying the gain after means the feedback samples are not scaled by the gain.
Those filters are all linear. This means that you can effectively commute them with a constant gain [*~] without any difference. However, it will make a difference when the gain of [*~] changes quickly while the main input changes too.
Right. I was just saying that, if you separate the gain from the filter, the gain has to be applied at the input or the output. It's a single operation. So if you incorporate it into the filter, scaling the feedback coefficients has the effect of making it multiple operations. Or at least that's how I understand it, anyway.
At any rate, the only reason I picked up on that in your previous email is because I wanted to plot the frequency response of [bp~], and at first I just applied the gain to all the coefficients without thinking about. It didn't work. Then I remembered the gain should just be applied to the FIR part of the filter, and it worked fine.
If you think of it in terms of its transfer function, it would look more like this: H(z) = g*(1 / (1 - 2r*cos(ω)*(z^-1) + r^2 * z(^-2) ))
Well, I was thinking of it in terms of 1/H(z) or 1/gH(z).
But are you sure that you got the signs right in the denominator ?
Pretty sure, though I mess that up all the time. Aren't you supposed change the signs of the feedback coefficients when z-transforming the difference equation?
.mmb
Le 2012-02-19 à 14:08:00, Mike Moser-Booth a écrit :
Pretty sure, though I mess that up all the time. Aren't you supposed change the signs of the feedback coefficients when z-transforming the difference equation?
Why would you change the signs of a and b but not c ?
(Was I giving the formula relative to ax²+bx+c=0 or did I assume ax²+bx=c by accident ?)
| Mathieu BOUCHARD ----- téléphone : +1.514.383.3801 ----- Montréal, QC
On Sun, Feb 19, 2012 at 4:54 PM, Mathieu Bouchard matju@artengine.ca wrote:
Why would you change the signs of a and b but not c ?
(Was I giving the formula relative to ax²+bx+c=0 or did I assume ax²+bx=c by accident ?)
I think it has to do with where c is in the difference equation:
c*y[n] = g*x[n] + a*y[n-1] + b*y[n-2]
Julius Smith explains it better than I could: https://ccrma.stanford.edu/~jos/fp2/Z_Transform_Difference_Equations.html
.mmb
Le 2012-02-19 à 17:48:00, Mike Moser-Booth a écrit :
On Sun, Feb 19, 2012 at 4:54 PM, Mathieu Bouchard matju@artengine.ca wrote:
Why would you change the signs of a and b but not c ? (Was I giving the formula relative to ax²+bx+c=0 or did I assume ax²+bx=c by accident ?)
I think it has to do with where c is in the difference equation: c*y[n] = g*x[n] + a*y[n-1] + b*y[n-2]
This equation uses a for the middle term (y[n-1]) ? Weird.
I'd expect b to go with y[n-1], whereas a and c would go with either y[n] or y[n-2]...
BTW, the equations I used are things that I reconstituted from the source code of [biquad~] in pd/src/d_filter.c. They don't come from manuals.
| Mathieu BOUCHARD ----- téléphone : +1.514.383.3801 ----- Montréal, QC
On Sun, Feb 19, 2012 at 6:12 PM, Mathieu Bouchard matju@artengine.ca wrote:
Le 2012-02-19 à 17:48:00, Mike Moser-Booth a écrit :
On Sun, Feb 19, 2012 at 4:54 PM, Mathieu Bouchard matju@artengine.ca wrote:
Why would you change the signs of a and b but not c ? (Was I giving the formula relative to ax²+bx+c=0 or did I assume ax²+bx=c by accident ?)
I think it has to do with where c is in the difference equation: c*y[n] = g*x[n] + a*y[n-1] + b*y[n-2]
This equation uses a for the middle term (y[n-1]) ? Weird.
I'd expect b to go with y[n-1], whereas a and c would go with either y[n] or y[n-2]...
Sorry, I kind of confused myself. I'm used to thinking of the coefficients as a_0, a_1, etc. You're right, b should go with y[n-1], and the one that should go with y[n] is which ever one is equal to 1, which would be c if you think of it as a + bx + cx^2, not ax^2 + bx + c.
To clarify, think of the z-transform of the filter as H(z) = 1/A(z), where A(z) = 1 - 2r*cos(ω)*z^-1 + r^2*z^-2. If we decide c=1, b=2r*cos(ω), and a=r^2, we have A(z) = c - bz^-1 + az^-2. In order to apply the quadratic formula, those exponents need to be positive, so you have to multiply by (z^2)/(z^2), which leaves you with H(z) = z^2 / (cz^2 - bz +a).
That's what I meant earlier when I said a and c should be switched, and I thought you were trying to say that you were thinking in terms of a + bx +cx^2. ;-)
BTW, the equations I used are things that I reconstituted from the source code of [biquad~] in pd/src/d_filter.c. They don't come from manuals.
You mean for [bp~]? The equation used for [biquad~] is in the helpfile, if I'm not mistaken. But, yeah, that's what I'm going off of, too.
btw, you wouldn't happen to know where the source for [vcf~] is, would you? I'd like to know how that one works as well, but I can't find it.
.mmb
Le 2012-02-19 à 22:31:00, Mike Moser-Booth a écrit :
To clarify, think of the z-transform of the filter as H(z) = 1/A(z), where A(z) = 1 - 2r*cos(ω)*z^-1 + r^2*z^-2. If we decide c=1, b=2r*cos(ω), and a=r^2, we have A(z) = c - bz^-1 + az^-2. In order to apply the quadratic formula, those exponents need to be positive, so you have to multiply by (z^2)/(z^2), which leaves you with H(z) = z^2 / (cz^2 - bz +a).
Alternately, with a backwards z transform, they're already positive, but then you get a backwards transfer function.
code of [biquad~] in pd/src/d_filter.c. They don't come from manuals.
You mean for [bp~]?
Yes. Dumb mistake.
btw, you wouldn't happen to know where the source for [vcf~] is, would you? I'd like to know how that one works as well, but I can't find it.
Curiously (but not interestingly), it's in d_osc.c instead of d_filter.c. This makes no sense and you shouldn't try to make sense of it. Just use grep or any other means to search multiple files for a word, and you'll find anything.
| Mathieu BOUCHARD ----- téléphone : +1.514.383.3801 ----- Montréal, QC
On Sun, Feb 19, 2012 at 10:41 PM, Mathieu Bouchard matju@artengine.ca wrote:
Curiously (but not interestingly), it's in d_osc.c instead of d_filter.c. This makes no sense and you shouldn't try to make sense of it. Just use grep or any other means to search multiple files for a word, and you'll find anything.
I assure you, I won't try to make sense of it. ;-)
Never used grep before. Thanks!
.mmb
On Thu, Feb 02, 2012 at 03:32:00AM +0000, Ed Kelly wrote:
Here is my first attempt at making a resonant lowpass filter using cpole~ and czero~ objects. It's the first version I've made which actually sounds halfway towards what I want to achieve, which is a decent diode-ladder or transistor-ladder filter emulation. I want to make this using only vanilla objects, particularly rpole~, cpole~ etc. so that they can be ultra-portable and signal-controlled. Also, http://www.timstinchcombe.co.uk/index.php?pge=poles#diode
Does anyone else have any ideas, or patches we can share?
Most filters in the rj library (https://github.com/rjdj/rjlib) use a similar approach. They even include a biquad-clone written with elementary filters. Some are modelled after the classic reson-filters used since CSound times.
Frank Barknecht Do You RjDj.me? _ ______footils.org__
Le 2012-02-03 à 09:46:00, Frank Barknecht a écrit :
Most filters in the rj library (https://github.com/rjdj/rjlib) use a similar approach. They even include a biquad-clone written with elementary filters.
Why would you clone biquad using elementary filters ? Is it just to show that it's possible, or is it to make it fully signal-rate ?
| Mathieu BOUCHARD ----- téléphone : +1.514.383.3801 ----- Montréal, QC
On Sun, Feb 19, 2012 at 11:33:28AM -0500, Mathieu Bouchard wrote:
Le 2012-02-03 à 09:46:00, Frank Barknecht a écrit :
Most filters in the rj library (https://github.com/rjdj/rjlib) use a
similar approach. They even include a biquad-clone written with
elementary filters.Why would you clone biquad using elementary filters ? Is it just to show
that it's possible, or is it to make it fully signal-rate ?
I made it "half signal-rate": The object accepts signal parameters, but these are just linearly interpolated internally, i.e. they don't move correctly "on a circle".
Frank Barknecht Do You RjDj.me? _ ______footils.org__
Le 2012-02-24 à 09:07:00, Frank Barknecht a écrit :
I made it "half signal-rate": The object accepts signal parameters, but these are just linearly interpolated internally, i.e. they don't move correctly "on a circle".
If you interpolate, it means that you are doing something at non-signal rate. What is it that makes you having to interpolate a signal parameter that is already at the same rate as the main input ?
| Mathieu BOUCHARD ----- téléphone : +1.514.383.3801 ----- Montréal, QC
On Fri, Feb 24, 2012 at 12:46:13PM -0500, Mathieu Bouchard wrote:
Le 2012-02-24 à 09:07:00, Frank Barknecht a écrit :
I made it "half signal-rate": The object accepts signal parameters, but these are just linearly interpolated internally, i.e. they don't move
correctly "on a circle".If you interpolate, it means that you are doing something at non-signal
rate. What is it that makes you having to interpolate a signal parameter
that is already at the same rate as the main input ?
Ah, sorry - I was completely wrong in my explanation. Now I checked: [e_beequad] linearily interpolates between parameter settings that are set at *message* rate. The original [biquad~] simply jumps to new settings.
Frank Barknecht Do You RjDj.me? _ ______footils.org__