1 /* (C) Guenter Geiger <geiger@epy.co.at> */
8 #pragma warning( disable : 4244 )
9 #pragma warning( disable : 4305 )
12 /* ------------------------ hlshelf ----------------------------- */
16 #define M_PI 3.141593f
20 #define MAX_GAIN 120.0f
22 static t_class
*hlshelf_class
;
25 typedef struct _hlshelf
39 int hlshelf_check_stability(t_float fb1
,
45 float discriminant
= fb1
* fb1
+ 4 * fb2
;
47 if (discriminant
< 0) /* imaginary roots -- resonant filter */
49 /* they're conjugates so we just check that the product
51 if (fb2
>= -1.0f
) goto stable
;
55 /* check that the parabola 1 - fb1 x - fb2 x^2 has a
56 vertex between -1 and 1, and that it's nonnegative
57 at both ends, which implies both roots are in [1-,1]. */
58 if (fb1
<= 2.0f
&& fb1
>= -2.0f
&&
59 1.0f
- fb1
-fb2
>= 0 && 1.0f
+ fb1
- fb2
>= 0)
68 void hlshelf_check(t_hlshelf
*x
)
71 if(x
->s_gain0
- x
->s_gain1
> MAX_GAIN
) {
72 x
->s_gain0
= x
->s_gain1
+ MAX_GAIN
;
73 post("setting gain0 to %f",x
->s_gain0
);
77 if(x
->s_gain1
> MAX_GAIN
) {
78 x
->s_gain1
= MAX_GAIN
;
79 post("setting gain1 to %f",x
->s_gain1
);
82 if(x
->s_gain2
- x
->s_gain1
> MAX_GAIN
) {
83 x
->s_gain2
= x
->s_gain1
+ MAX_GAIN
;
84 post("setting gain2 to %f",x
->s_gain2
);
87 /* constrain: 0 <= x->s_ltransfq < x->s_htransfq. */
88 x
->s_ltransfq
= (x
->s_ltransfq
< x
->s_htransfq
) ? x
->s_ltransfq
: x
->s_htransfq
- 0.5f
;
90 if (x
->s_ltransfq
< 0) x
->s_ltransfq
= 0.0f
;
92 x
->s_lradians
= M_PI
* x
->s_ltransfq
/ x
->s_rate
;
93 x
->s_hradians
= M_PI
* (0.5f
- (x
->s_htransfq
/ x
->s_rate
));
98 void hlshelf_bang(t_hlshelf
*x
)
101 float c0
, c1
, c2
, d0
, d1
, d2
; /* output coefs */
102 float a1
, a2
, b1
, b2
, g1
, g2
; /* temp coefs */
108 xf
= 0.5 * 0.115129255 * (double)(x
->s_gain0
- x
->s_gain1
); /* ln(10) / 20 = 0.115129255 */
109 if(xf
< -200.) /* exp(x) -> 0 */
117 double t
= tan(x
->s_lradians
);
122 a1
= (r
- 1) / (r
+ 1);
123 b1
= (kr
- 1) / (kr
+ 1);
124 g1
= (kr
+ 1) / (r
+ 1);
128 xf
= 0.5 * 0.115129255 * (double)(x
->s_gain2
- x
->s_gain1
); /* ln(10) / 20 = 0.115129255 */
129 if(xf
< -200.) /* exp(x) -> 0 */
137 double t
= tan(x
->s_hradians
);
142 a2
= (1 - r
) / (1 + r
);
143 b2
= (1 - kr
) / (1 + kr
);
144 g2
= (1 + kr
) / (1 + r
);
148 c0
= g1
* g2
* (float)(exp((double)(x
->s_gain1
) * 0.05f
* 2.302585093f
)); ;
155 if (!hlshelf_check_stability(-c1
/d0
,-c2
/d0
,d0
/d0
,d1
/d0
,d2
/d0
)) {
156 post("hlshelf: filter unstable -> resetting");
162 SETFLOAT(at
+1,-c2
/d0
);
163 SETFLOAT(at
+2,d0
/d0
);
164 SETFLOAT(at
+3,d1
/d0
);
165 SETFLOAT(at
+4,d2
/d0
);
167 outlet_list(x
->x_obj
.ob_outlet
,&s_list
,5,at
);
170 void hlshelf_float(t_hlshelf
*x
,t_floatarg f
)
177 static void *hlshelf_new(t_symbol
* s
,t_int argc
, t_atom
* at
)
179 t_hlshelf
*x
= (t_hlshelf
*)pd_new(hlshelf_class
);
180 t_float k0
= atom_getfloat(at
);
181 t_float k1
= atom_getfloat(at
+1);
182 t_float k2
= atom_getfloat(at
+2);
183 t_float f1
= atom_getfloat(at
+3);
184 t_float f2
= atom_getfloat(at
+4);
187 f1
= atom_getfloat(at
);
188 f2
= atom_getfloat(at
);
190 if ((f1
== 0.0f
&& f2
== 0.0f
) || f1
> f2
){ /* all gains = 0db */
195 if (f1
< 0) f1
= 0.0f
;
196 if (f2
> SRATE
) f2
= .5f
*SRATE
;
198 x
->s_rate
= SRATE
; /* srate default */
203 x
->s_ltransfq
= 0.0f
;
204 x
->s_htransfq
= SRATE
/2;
206 x
->s_lradians
= M_PI
* x
->s_ltransfq
/ x
->s_rate
;
207 x
->s_hradians
= M_PI
* (0.5f
- (x
->s_htransfq
/ x
->s_rate
));
209 floatinlet_new(&x
->x_obj
, &x
->s_gain1
);
210 floatinlet_new(&x
->x_obj
, &x
->s_gain2
);
211 floatinlet_new(&x
->x_obj
, &x
->s_ltransfq
);
212 floatinlet_new(&x
->x_obj
, &x
->s_htransfq
);
213 outlet_new(&x
->x_obj
, &s_list
);
218 void hlshelf_setup(void)
220 hlshelf_class
= class_new(gensym("hlshelf"), (t_newmethod
)hlshelf_new
, 0,
221 sizeof(t_hlshelf
), 0, A_GIMME
, 0);
222 class_addbang(hlshelf_class
,hlshelf_bang
);
223 class_addfloat(hlshelf_class
,hlshelf_float
);
227 /* (C) Guenter Geiger <geiger@epy.co.at> */
234 #pragma warning( disable : 4244 )
235 #pragma warning( disable : 4305 )
238 /* ------------------------ hlshelf ----------------------------- */
242 #define M_PI 3.141593f
245 #define SRATE 44100.0
246 #define MAX_GAIN 120.0f
248 static t_class
*hlshelf_class
;
251 typedef struct _hlshelf
265 int hlshelf_check_stability(t_float fb1
,
271 float discriminant
= fb1
* fb1
+ 4 * fb2
;
273 if (discriminant
< 0) /* imaginary roots -- resonant filter */
275 /* they're conjugates so we just check that the product
277 if (fb2
>= -1.0f
) goto stable
;
279 else /* real roots */
281 /* check that the parabola 1 - fb1 x - fb2 x^2 has a
282 vertex between -1 and 1, and that it's nonnegative
283 at both ends, which implies both roots are in [1-,1]. */
284 if (fb1
<= 2.0f
&& fb1
>= -2.0f
&&
285 1.0f
- fb1
-fb2
>= 0 && 1.0f
+ fb1
- fb2
>= 0)
294 void hlshelf_check(t_hlshelf
*x
)
297 if(x
->s_gain0
- x
->s_gain1
> MAX_GAIN
) {
298 x
->s_gain0
= x
->s_gain1
+ MAX_GAIN
;
299 post("setting gain0 to %f",x
->s_gain0
);
303 if(x
->s_gain1
> MAX_GAIN
) {
304 x
->s_gain1
= MAX_GAIN
;
305 post("setting gain1 to %f",x
->s_gain1
);
308 if(x
->s_gain2
- x
->s_gain1
> MAX_GAIN
) {
309 x
->s_gain2
= x
->s_gain1
+ MAX_GAIN
;
310 post("setting gain2 to %f",x
->s_gain2
);
313 /* constrain: 0 <= x->s_ltransfq < x->s_htransfq. */
314 x
->s_ltransfq
= (x
->s_ltransfq
< x
->s_htransfq
) ? x
->s_ltransfq
: x
->s_htransfq
- 0.5f
;
316 if (x
->s_ltransfq
< 0) x
->s_ltransfq
= 0.0f
;
318 x
->s_lradians
= M_PI
* x
->s_ltransfq
/ x
->s_rate
;
319 x
->s_hradians
= M_PI
* (0.5f
- (x
->s_htransfq
/ x
->s_rate
));
324 void hlshelf_bang(t_hlshelf
*x
)
327 float c0
, c1
, c2
, d0
, d1
, d2
; /* output coefs */
328 float a1
, a2
, b1
, b2
, g1
, g2
; /* temp coefs */
334 xf
= 0.5 * 0.115129255 * (double)(x
->s_gain0
- x
->s_gain1
); /* ln(10) / 20 = 0.115129255 */
335 if(xf
< -200.) /* exp(x) -> 0 */
343 double t
= tan(x
->s_lradians
);
348 a1
= (r
- 1) / (r
+ 1);
349 b1
= (kr
- 1) / (kr
+ 1);
350 g1
= (kr
+ 1) / (r
+ 1);
354 xf
= 0.5 * 0.115129255 * (double)(x
->s_gain2
- x
->s_gain1
); /* ln(10) / 20 = 0.115129255 */
355 if(xf
< -200.) /* exp(x) -> 0 */
363 double t
= tan(x
->s_hradians
);
368 a2
= (1 - r
) / (1 + r
);
369 b2
= (1 - kr
) / (1 + kr
);
370 g2
= (1 + kr
) / (1 + r
);
374 c0
= g1
* g2
* (float)(exp((double)(x
->s_gain1
) * 0.05f
* 2.302585093f
)); ;
381 if (!hlshelf_check_stability(-c1
/d0
,-c2
/d0
,d0
/d0
,d1
/d0
,d2
/d0
)) {
382 post("hlshelf: filter unstable -> resetting");
388 SETFLOAT(at
+1,-c2
/d0
);
389 SETFLOAT(at
+2,d0
/d0
);
390 SETFLOAT(at
+3,d1
/d0
);
391 SETFLOAT(at
+4,d2
/d0
);
393 outlet_list(x
->x_obj
.ob_outlet
,&s_list
,5,at
);
396 void hlshelf_float(t_hlshelf
*x
,t_floatarg f
)
403 static void *hlshelf_new(t_symbol
* s
,t_int argc
, t_atom
* at
)
405 t_hlshelf
*x
= (t_hlshelf
*)pd_new(hlshelf_class
);
406 t_float k0
= atom_getfloat(at
);
407 t_float k1
= atom_getfloat(at
+1);
408 t_float k2
= atom_getfloat(at
+2);
409 t_float f1
= atom_getfloat(at
+3);
410 t_float f2
= atom_getfloat(at
+4);
413 f1
= atom_getfloat(at
);
414 f2
= atom_getfloat(at
);
416 if ((f1
== 0.0f
&& f2
== 0.0f
) || f1
> f2
){ /* all gains = 0db */
421 if (f1
< 0) f1
= 0.0f
;
422 if (f2
> SRATE
) f2
= .5f
*SRATE
;
424 x
->s_rate
= SRATE
; /* srate default */
429 x
->s_ltransfq
= 0.0f
;
430 x
->s_htransfq
= SRATE
/2;
432 x
->s_lradians
= M_PI
* x
->s_ltransfq
/ x
->s_rate
;
433 x
->s_hradians
= M_PI
* (0.5f
- (x
->s_htransfq
/ x
->s_rate
));
435 floatinlet_new(&x
->x_obj
, &x
->s_gain1
);
436 floatinlet_new(&x
->x_obj
, &x
->s_gain2
);
437 floatinlet_new(&x
->x_obj
, &x
->s_ltransfq
);
438 floatinlet_new(&x
->x_obj
, &x
->s_htransfq
);
439 outlet_new(&x
->x_obj
, &s_list
);
444 void hlshelf_setup(void)
446 hlshelf_class
= class_new(gensym("hlshelf"), (t_newmethod
)hlshelf_new
, 0,
447 sizeof(t_hlshelf
), 0, A_GIMME
, 0);
448 class_addbang(hlshelf_class
,hlshelf_bang
);
449 class_addfloat(hlshelf_class
,hlshelf_float
);