summaryrefslogtreecommitdiff
path: root/apps/plugins/pdbox/PDa/extra/hlshelf.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/pdbox/PDa/extra/hlshelf.c')
-rw-r--r--apps/plugins/pdbox/PDa/extra/hlshelf.c452
1 files changed, 452 insertions, 0 deletions
diff --git a/apps/plugins/pdbox/PDa/extra/hlshelf.c b/apps/plugins/pdbox/PDa/extra/hlshelf.c
new file mode 100644
index 0000000000..46190c9b7c
--- /dev/null
+++ b/apps/plugins/pdbox/PDa/extra/hlshelf.c
@@ -0,0 +1,452 @@
1/* (C) Guenter Geiger <geiger@epy.co.at> */
2
3
4#include <m_pd.h>
5#include <math.h>
6
7#ifdef NT
8#pragma warning( disable : 4244 )
9#pragma warning( disable : 4305 )
10#endif
11
12/* ------------------------ hlshelf ----------------------------- */
13
14
15#ifndef M_PI
16#define M_PI 3.141593f
17#endif
18
19#define SRATE 44100.0
20#define MAX_GAIN 120.0f
21
22static t_class *hlshelf_class;
23
24
25typedef struct _hlshelf
26{
27 t_object x_obj;
28 float s_rate;
29 float s_gain0;
30 float s_gain1;
31 float s_gain2;
32 float s_ltransfq;
33 float s_htransfq;
34 float s_lradians;
35 float s_hradians;
36} t_hlshelf;
37
38
39int hlshelf_check_stability(t_float fb1,
40 t_float fb2,
41 t_float ff1,
42 t_float ff2,
43 t_float ff3)
44{
45 float discriminant = fb1 * fb1 + 4 * fb2;
46
47 if (discriminant < 0) /* imaginary roots -- resonant filter */
48 {
49 /* they're conjugates so we just check that the product
50 is less than one */
51 if (fb2 >= -1.0f) goto stable;
52 }
53 else /* real roots */
54 {
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)
60 goto stable;
61 }
62 return 0;
63stable:
64 return 1;
65}
66
67
68void hlshelf_check(t_hlshelf *x)
69{
70
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);
74 }
75
76
77 if(x->s_gain1 > MAX_GAIN) {
78 x->s_gain1 = MAX_GAIN;
79 post("setting gain1 to %f",x->s_gain1);
80 }
81
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);
85 }
86
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;
89
90 if (x->s_ltransfq < 0) x->s_ltransfq = 0.0f;
91
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));
94
95}
96
97
98void hlshelf_bang(t_hlshelf *x)
99{
100 t_atom at[6];
101 float c0, c1, c2, d0, d1, d2; /* output coefs */
102 float a1, a2, b1, b2, g1, g2; /* temp coefs */
103 double xf;
104
105 hlshelf_check(x);
106
107 /* low shelf */
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 */
110 {
111 a1 = 1.0f;
112 b1 = -1.0f;
113 g1 = 0.0f;
114 }
115 else
116 {
117 double t = tan(x->s_lradians);
118 double e = exp(xf);
119 double r = t / e;
120 double kr = t * e;
121
122 a1 = (r - 1) / (r + 1);
123 b1 = (kr - 1) / (kr + 1);
124 g1 = (kr + 1) / (r + 1);
125 }
126
127 /* high shelf */
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 */
130 {
131 a2 = -1.0f;
132 b2 = 1.0f;
133 g2 = 0.0f;
134 }
135 else
136 {
137 double t = tan(x->s_hradians);
138 double e = exp(xf);
139 double r = t / e;
140 double kr = t * e;
141
142 a2 = (1 - r) / (1 + r);
143 b2 = (1 - kr) / (1 + kr);
144 g2 = (1 + kr) / (1 + r);
145 }
146
147 /* form product */
148 c0 = g1 * g2 * (float)(exp((double)(x->s_gain1) * 0.05f * 2.302585093f)); ;
149 c1 = a1 + a2;
150 c2 = a1 * a2;
151 d0 = 1.0f;
152 d1 = b1 + b2;
153 d2 = b1 * b2;
154
155 if (!hlshelf_check_stability(-c1/d0,-c2/d0,d0/d0,d1/d0,d2/d0)) {
156 post("hlshelf: filter unstable -> resetting");
157 c0=1.;c1=0.;c2=0.;
158 d0=1.;d1=0.;d2=0.;
159 }
160
161 SETFLOAT(at,-c1/d0);
162 SETFLOAT(at+1,-c2/d0);
163 SETFLOAT(at+2,d0/d0);
164 SETFLOAT(at+3,d1/d0);
165 SETFLOAT(at+4,d2/d0);
166
167 outlet_list(x->x_obj.ob_outlet,&s_list,5,at);
168}
169
170void hlshelf_float(t_hlshelf *x,t_floatarg f)
171{
172 x->s_gain0 = f;
173 hlshelf_bang(x);
174}
175
176
177static void *hlshelf_new(t_symbol* s,t_int argc, t_atom* at)
178{
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);
185
186
187 f1 = atom_getfloat(at);
188 f2 = atom_getfloat(at);
189
190 if ((f1 == 0.0f && f2 == 0.0f) || f1 > f2){ /* all gains = 0db */
191 f1 = 150.0f;
192 f2 = 5000.0f;
193 }
194
195 if (f1 < 0) f1 = 0.0f;
196 if (f2 > SRATE) f2 = .5f*SRATE;
197
198 x->s_rate = SRATE; /* srate default */
199 x->s_gain0 = k0;
200 x->s_gain1 = k1;
201 x->s_gain2 = k2;
202
203 x->s_ltransfq = 0.0f;
204 x->s_htransfq = SRATE/2;
205
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));
208
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);
214
215 return (x);
216}
217
218void hlshelf_setup(void)
219{
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);
224}
225
226
227/* (C) Guenter Geiger <geiger@epy.co.at> */
228
229
230#include <m_pd.h>
231#include <math.h>
232
233#ifdef NT
234#pragma warning( disable : 4244 )
235#pragma warning( disable : 4305 )
236#endif
237
238/* ------------------------ hlshelf ----------------------------- */
239
240
241#ifndef M_PI
242#define M_PI 3.141593f
243#endif
244
245#define SRATE 44100.0
246#define MAX_GAIN 120.0f
247
248static t_class *hlshelf_class;
249
250
251typedef struct _hlshelf
252{
253 t_object x_obj;
254 float s_rate;
255 float s_gain0;
256 float s_gain1;
257 float s_gain2;
258 float s_ltransfq;
259 float s_htransfq;
260 float s_lradians;
261 float s_hradians;
262} t_hlshelf;
263
264
265int hlshelf_check_stability(t_float fb1,
266 t_float fb2,
267 t_float ff1,
268 t_float ff2,
269 t_float ff3)
270{
271 float discriminant = fb1 * fb1 + 4 * fb2;
272
273 if (discriminant < 0) /* imaginary roots -- resonant filter */
274 {
275 /* they're conjugates so we just check that the product
276 is less than one */
277 if (fb2 >= -1.0f) goto stable;
278 }
279 else /* real roots */
280 {
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)
286 goto stable;
287 }
288 return 0;
289stable:
290 return 1;
291}
292
293
294void hlshelf_check(t_hlshelf *x)
295{
296
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);
300 }
301
302
303 if(x->s_gain1 > MAX_GAIN) {
304 x->s_gain1 = MAX_GAIN;
305 post("setting gain1 to %f",x->s_gain1);
306 }
307
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);
311 }
312
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;
315
316 if (x->s_ltransfq < 0) x->s_ltransfq = 0.0f;
317
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));
320
321}
322
323
324void hlshelf_bang(t_hlshelf *x)
325{
326 t_atom at[6];
327 float c0, c1, c2, d0, d1, d2; /* output coefs */
328 float a1, a2, b1, b2, g1, g2; /* temp coefs */
329 double xf;
330
331 hlshelf_check(x);
332
333 /* low shelf */
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 */
336 {
337 a1 = 1.0f;
338 b1 = -1.0f;
339 g1 = 0.0f;
340 }
341 else
342 {
343 double t = tan(x->s_lradians);
344 double e = exp(xf);
345 double r = t / e;
346 double kr = t * e;
347
348 a1 = (r - 1) / (r + 1);
349 b1 = (kr - 1) / (kr + 1);
350 g1 = (kr + 1) / (r + 1);
351 }
352
353 /* high shelf */
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 */
356 {
357 a2 = -1.0f;
358 b2 = 1.0f;
359 g2 = 0.0f;
360 }
361 else
362 {
363 double t = tan(x->s_hradians);
364 double e = exp(xf);
365 double r = t / e;
366 double kr = t * e;
367
368 a2 = (1 - r) / (1 + r);
369 b2 = (1 - kr) / (1 + kr);
370 g2 = (1 + kr) / (1 + r);
371 }
372
373 /* form product */
374 c0 = g1 * g2 * (float)(exp((double)(x->s_gain1) * 0.05f * 2.302585093f)); ;
375 c1 = a1 + a2;
376 c2 = a1 * a2;
377 d0 = 1.0f;
378 d1 = b1 + b2;
379 d2 = b1 * b2;
380
381 if (!hlshelf_check_stability(-c1/d0,-c2/d0,d0/d0,d1/d0,d2/d0)) {
382 post("hlshelf: filter unstable -> resetting");
383 c0=1.;c1=0.;c2=0.;
384 d0=1.;d1=0.;d2=0.;
385 }
386
387 SETFLOAT(at,-c1/d0);
388 SETFLOAT(at+1,-c2/d0);
389 SETFLOAT(at+2,d0/d0);
390 SETFLOAT(at+3,d1/d0);
391 SETFLOAT(at+4,d2/d0);
392
393 outlet_list(x->x_obj.ob_outlet,&s_list,5,at);
394}
395
396void hlshelf_float(t_hlshelf *x,t_floatarg f)
397{
398 x->s_gain0 = f;
399 hlshelf_bang(x);
400}
401
402
403static void *hlshelf_new(t_symbol* s,t_int argc, t_atom* at)
404{
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);
411
412
413 f1 = atom_getfloat(at);
414 f2 = atom_getfloat(at);
415
416 if ((f1 == 0.0f && f2 == 0.0f) || f1 > f2){ /* all gains = 0db */
417 f1 = 150.0f;
418 f2 = 5000.0f;
419 }
420
421 if (f1 < 0) f1 = 0.0f;
422 if (f2 > SRATE) f2 = .5f*SRATE;
423
424 x->s_rate = SRATE; /* srate default */
425 x->s_gain0 = k0;
426 x->s_gain1 = k1;
427 x->s_gain2 = k2;
428
429 x->s_ltransfq = 0.0f;
430 x->s_htransfq = SRATE/2;
431
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));
434
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);
440
441 return (x);
442}
443
444void hlshelf_setup(void)
445{
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);
450}
451
452