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.c228
1 files changed, 1 insertions, 227 deletions
diff --git a/apps/plugins/pdbox/PDa/extra/hlshelf.c b/apps/plugins/pdbox/PDa/extra/hlshelf.c
index 46190c9b7c..242a2e625f 100644
--- a/apps/plugins/pdbox/PDa/extra/hlshelf.c
+++ b/apps/plugins/pdbox/PDa/extra/hlshelf.c
@@ -223,230 +223,4 @@ void hlshelf_setup(void)
223 class_addfloat(hlshelf_class,hlshelf_float); 223 class_addfloat(hlshelf_class,hlshelf_float);
224} 224}
225 225
226 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