From fc3d3c0a4f110a23335398c327ac0a4fc949d5cb Mon Sep 17 00:00:00 2001 From: Guenter Geiger Date: Mon, 17 Jun 2002 10:13:57 +0000 Subject: This commit was generated by cvs2svn to compensate for changes in r12, which included commits to RCS files with non-trunk default branches. svn path=/trunk/externals/ggee/; revision=13 --- filters/Makefile | 50 ++++++++++++ filters/bandpass.c | 86 ++++++++++++++++++++ filters/bandpass.pd | 38 +++++++++ filters/equalizer.c | 89 ++++++++++++++++++++ filters/equalizer.pd | 39 +++++++++ filters/filters.h | 74 +++++++++++++++++ filters/filtgain.pd | 74 +++++++++++++++++ filters/highpass.c | 87 ++++++++++++++++++++ filters/highpass.pd | 35 ++++++++ filters/highshelf.c | 90 ++++++++++++++++++++ filters/highshelf.pd | 39 +++++++++ filters/hlshelf.c | 226 +++++++++++++++++++++++++++++++++++++++++++++++++++ filters/hlshelf.pd | 34 ++++++++ filters/lowpass.c | 89 ++++++++++++++++++++ filters/lowpass.pd | 35 ++++++++ filters/lowshelf.c | 91 +++++++++++++++++++++ filters/lowshelf.pd | 39 +++++++++ filters/moog~.c | 182 +++++++++++++++++++++++++++++++++++++++++ filters/moog~.pd | 39 +++++++++ filters/notch.c | 89 ++++++++++++++++++++ filters/notch.pd | 35 ++++++++ 21 files changed, 1560 insertions(+) create mode 100755 filters/Makefile create mode 100755 filters/bandpass.c create mode 100755 filters/bandpass.pd create mode 100755 filters/equalizer.c create mode 100755 filters/equalizer.pd create mode 100755 filters/filters.h create mode 100755 filters/filtgain.pd create mode 100755 filters/highpass.c create mode 100755 filters/highpass.pd create mode 100755 filters/highshelf.c create mode 100755 filters/highshelf.pd create mode 100755 filters/hlshelf.c create mode 100755 filters/hlshelf.pd create mode 100755 filters/lowpass.c create mode 100755 filters/lowpass.pd create mode 100755 filters/lowshelf.c create mode 100755 filters/lowshelf.pd create mode 100755 filters/moog~.c create mode 100755 filters/moog~.pd create mode 100755 filters/notch.c create mode 100755 filters/notch.pd (limited to 'filters') diff --git a/filters/Makefile b/filters/Makefile new file mode 100755 index 0000000..f002498 --- /dev/null +++ b/filters/Makefile @@ -0,0 +1,50 @@ +current: nt + + +# TARGETS += stk + +VERSION = \"0.24\" + +.SUFFIXES: .dll .obj +# ----------------------- NT ---------------------------- + +NTOBJECTS = *.obj +NTDLLS = *.dll + +PDNTCFLAGS = /W3 /WX /DNT /DPD /nologo + +PDNTINCLUDE = /I. /I..\..\pd\src +ProgramFiles = C:\Program Files +PDNTLDIR = "$(ProgramFiles)\Microsoft Visual Studio\Vc98\lib" +#PDNTLDIR = "C:\Programme\Msdev\Vc98\lib" + +PDNTLIB = $(PDNTLDIR)\libc.lib \ + $(PDNTLDIR)\oldnames.lib \ + $(PDNTLDIR)\wsock32.lib \ + $(PDNTLDIR)\kernel32.lib \ + $(PDNTLDIR)\uuid.lib \ + ..\..\pd\bin\pd.lib + +nt: $(NTOBJECTS) + -link /dll $(PDNTLIB) bandpass.obj /export:bandpass_setup + -link /dll $(PDNTLIB) highpass.obj /export:highpass_setup + -link /dll $(PDNTLIB) highshelf.obj /export:highshelf_setup + -link /dll $(PDNTLIB) hlshelf.obj /export:hlshelf_setup + -link /dll $(PDNTLIB) lowpass.obj /export:lowpass_setup + -link /dll $(PDNTLIB) notch.obj /export:notch_setup + -link /dll $(PDNTLIB) equalizer.obj /export:equalizer_setup + + +clean: + del *.obj + del *.dll + + +.c.obj: + -cl $(PDNTCFLAGS) $(PDNTINCLUDE) /c $*.c + +.obj.dll: + + + + diff --git a/filters/bandpass.c b/filters/bandpass.c new file mode 100755 index 0000000..c4c2e13 --- /dev/null +++ b/filters/bandpass.c @@ -0,0 +1,86 @@ + +/* (C) Guenter Geiger */ + + +/* + + These filter coefficients computations are taken from + http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt + + written by Robert Bristow-Johnson + +*/ + +#include +#ifdef NT +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif +#include +#include "filters.h" + +/* ------------------- bandpass ----------------------------*/ + +static t_class *bandpass_class; + +void bandpass_bang(t_rbjfilter *x) +{ + t_atom at[5]; + t_float omega = e_omega(x->x_freq,x->x_rate); + t_float alpha = e_alpha(x->x_bw* 0.01,omega); + t_float b1 = 0.; + t_float b0 = alpha; + t_float b2 = -alpha; + t_float a0 = 1 + alpha; + t_float a1 = -2.*cos(omega); + t_float a2 = 1 - alpha; + +/* post("bang %f %f %f",x->x_freq, x->x_gain, x->x_bw); */ + + if (!check_stability(-a1/a0,-a2/a0,b0/a0,b1/a0,b2/a0)) { + post("bandpass: filter unstable -> resetting"); + a0=1.;a1=0.;a2=0.; + b0=1.;b1=0.;b2=0.; + } + + SETFLOAT(at,-a1/a0); + SETFLOAT(at+1,-a2/a0); + SETFLOAT(at+2,b0/a0); + SETFLOAT(at+3,b1/a0); + SETFLOAT(at+4,b2/a0); + + outlet_list(x->x_obj.ob_outlet,&s_list,5,at); +} + + +void bandpass_float(t_rbjfilter *x,t_floatarg f) +{ + x->x_freq = f; + bandpass_bang(x); +} + + +static void *bandpass_new(t_floatarg f,t_floatarg bw) +{ + t_rbjfilter *x = (t_rbjfilter *)pd_new(bandpass_class); + + x->x_rate = 44100.0; + outlet_new(&x->x_obj,&s_float); +/* floatinlet_new(&x->x_obj, &x->x_gain); */ + floatinlet_new(&x->x_obj, &x->x_bw); + if (f > 0.) x->x_freq = f; + if (bw > 0.) x->x_bw = bw; + return (x); +} + + +void bandpass_setup(void) +{ + bandpass_class = class_new(gensym("bandpass"), (t_newmethod)bandpass_new, 0, + sizeof(t_rbjfilter), 0,A_DEFFLOAT,A_DEFFLOAT,0); + class_addbang(bandpass_class,bandpass_bang); + class_addfloat(bandpass_class,bandpass_float); +} + + + diff --git a/filters/bandpass.pd b/filters/bandpass.pd new file mode 100755 index 0000000..73cace4 --- /dev/null +++ b/filters/bandpass.pd @@ -0,0 +1,38 @@ +#N canvas 295 68 622 469 10; +#X obj 77 199 print; +#X floatatom 77 114 0 0 0; +#X floatatom 139 114 0 0 0; +#X msg 360 109 \; paint 0; +#X obj 164 196 filtgain; +#X msg 91 138 bang; +#X text 139 93 bandwidth (0 - 100); +#X text 6 334 See also:; +#X obj 72 335 bandpass; +#X obj 139 336 notch; +#X obj 195 337 lowpass; +#X obj 247 336 highpass; +#X obj 247 358 equalizer; +#X obj 72 357 highshelf; +#X obj 139 357 lowshelf; +#X obj 195 357 hlshelf; +#X text 75 226 These filters are all controlled by a bandwidth which +is expressed in octaves. A bandwidth of 100 is equivalent to one octave. +; +#X text 358 25 click first; +#X text 186 159 click on filtgain to view frequency plot; +#X text 76 12 Bandpass coefficients for biquad~; +#X text 70 26 ===================================; +#X text 6 393 (C) Guenter Geiger 2000; +#X text 75 92 frequency; +#X text 75 268 Attention \, only the left inlet triggers new coefficients +for biquad~; +#X obj 77 160 bandpass 4000 33; +#X obj 33 114 r doit; +#X msg 360 45 \; pd dsp 1 \; paint 1 \; doit bang \;; +#X connect 1 0 24 0; +#X connect 2 0 24 1; +#X connect 2 0 5 0; +#X connect 5 0 24 0; +#X connect 24 0 0 0; +#X connect 24 0 4 0; +#X connect 25 0 5 0; diff --git a/filters/equalizer.c b/filters/equalizer.c new file mode 100755 index 0000000..80d8410 --- /dev/null +++ b/filters/equalizer.c @@ -0,0 +1,89 @@ +/* (C) Guenter Geiger */ + + +/* + + These filter coefficients computations are taken from + http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt + + written by Robert Bristow-Johnson + +*/ + +#include +#ifdef NT +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif +#include +#include "filters.h" + + + +/* ------------------- equ ----------------------------*/ +static t_class *equ_class; + +void equ_bang(t_rbjfilter *x) +{ + t_atom at[5]; + t_float omega = e_omega(x->x_freq,x->x_rate); + t_float alpha = e_alpha(x->x_bw*0.01,omega); + t_float b0 = 1 + alpha*e_A(x->x_gain); + t_float b1 = -2.*cos(omega); + t_float b2 = 1; + t_float a0 = 1 + alpha; + t_float a1 = -2.*cos(omega); + t_float a2 = 1 - alpha; + +/* post("bang %f %f %f",x->x_freq, x->x_gain, x->x_bw);*/ + + if (!check_stability(-a1/a0,-a2/a0,b0/a0,b1/a0,b2/a0)) { + post("equ: filter unstable -> resetting"); + a0=1.;a1=0.;a2=0.; + b0=1.;b1=0.;b2=0.; + } + + SETFLOAT(at,-a1/a0); + SETFLOAT(at+1,-a2/a0); + SETFLOAT(at+2,b0/a0); + SETFLOAT(at+3,b1/a0); + SETFLOAT(at+4,b2/a0); + + outlet_list(x->x_obj.ob_outlet,&s_list,5,at); +} + + +void equ_float(t_rbjfilter *x,t_floatarg f) +{ + x->x_freq = f; + equ_bang(x); +} + + +static void *equ_new(t_floatarg f,t_floatarg g,t_floatarg bw) +{ + t_rbjfilter *x = (t_rbjfilter *)pd_new(equ_class); + + x->x_rate = 44100.0; + outlet_new(&x->x_obj,&s_float); + floatinlet_new(&x->x_obj, &x->x_gain); + floatinlet_new(&x->x_obj, &x->x_bw); + if (f > 0.) x->x_freq = f; + if (bw > 0.) x->x_bw = bw; + if (g != 0.) x->x_gain = g; + return (x); +} + + +void equalizer_setup(void) +{ + equ_class = class_new(gensym("equalizer"), (t_newmethod)equ_new, 0, + sizeof(t_rbjfilter), 0,A_DEFFLOAT,A_DEFFLOAT,A_DEFFLOAT,0); + class_addbang(equ_class,equ_bang); + class_addfloat(equ_class,equ_float); +} + + + + + diff --git a/filters/equalizer.pd b/filters/equalizer.pd new file mode 100755 index 0000000..05f7c56 --- /dev/null +++ b/filters/equalizer.pd @@ -0,0 +1,39 @@ +#N canvas 561 126 620 459 10; +#X obj 77 182 print; +#X floatatom 77 114; +#X floatatom 186 112; +#X msg 360 117 \; paint 0; +#X obj 159 175 filtgain; +#X msg 91 138 bang; +#X text 186 91 bandwidth (0 - 100); +#X text 6 334 See also:; +#X obj 72 335 bandpass; +#X obj 139 336 notch; +#X obj 195 337 lowpass; +#X obj 247 336 highpass; +#X obj 247 358 equalizer; +#X obj 72 357 highshelf; +#X obj 139 357 lowshelf; +#X obj 195 357 hlshelf; +#X text 75 226 These filters are all controlled by a bandwidth which is expressed in octaves. A bandwidth of 100 is equivalent to one octave.; +#X text 358 25 click first; +#X text 200 158 click on filtgain to view frequency plot; +#X text 6 393 (C) Guenter Geiger 2000; +#X text 75 92 frequency; +#X text 75 268 Attention \, only the left inlet triggers new coefficients for biquad~; +#X floatatom 129 113; +#X text 138 92 gain; +#X text 71 26 ==============================================; +#X text 76 12 Parametric Equalizer coefficients for biquad~; +#X obj 77 160 equalizer 5000 70 8; +#X obj 31 114 r doit; +#X msg 360 45 \; pd dsp 1 \; paint 1 \; doit bang \;; +#X connect 1 0 26 0; +#X connect 2 0 5 0; +#X connect 2 0 26 2; +#X connect 5 0 26 0; +#X connect 22 0 5 0; +#X connect 22 0 26 1; +#X connect 26 0 0 0; +#X connect 26 0 4 0; +#X connect 27 0 26 0; diff --git a/filters/filters.h b/filters/filters.h new file mode 100755 index 0000000..6ff7962 --- /dev/null +++ b/filters/filters.h @@ -0,0 +1,74 @@ +/* + + These filter coefficients computations are taken from + http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt + + written by Robert Bristow-Johnson + +*/ + + +#ifndef __GGEE_FILTERS_H__ +#define __GGEE_FILTERS_H__ + + + +#ifndef M_PI +#define M_PI 3.141593f +#endif + + +#include +#define LN2 0.69314718 +#define e_A(g) (pow(10,(g/40.))) +#define e_omega(f,r) (2.0*M_PI*f/r) +#define e_alpha(bw,omega) (sin(omega)*sinh(LN2/2. * bw * omega/sin(omega))) +#define e_beta(a,S) (sqrt((a*a + 1)/(S) - (a-1)*(a-1))) + + + + +typedef struct _rbjfilter +{ + t_object x_obj; + t_float x_rate; + t_float x_freq; + t_float x_gain; + t_float x_bw; +} t_rbjfilter; + + +static int check_stability(t_float fb1, + t_float fb2, + t_float ff1, + t_float ff2, + t_float ff3) +{ + float discriminant = fb1 * fb1 + 4 * fb2; + + if (discriminant < 0) /* imaginary roots -- resonant filter */ + { + /* they're conjugates so we just check that the product + is less than one */ + if (fb2 >= -1.0f) goto stable; + } + else /* real roots */ + { + /* check that the parabola 1 - fb1 x - fb2 x^2 has a + vertex between -1 and 1, and that it's nonnegative + at both ends, which implies both roots are in [1-,1]. */ + if (fb1 <= 2.0f && fb1 >= -2.0f && + 1.0f - fb1 -fb2 >= 0 && 1.0f + fb1 - fb2 >= 0) + goto stable; + } + return 0; +stable: + return 1; +} + + + + + + +#endif diff --git a/filters/filtgain.pd b/filters/filtgain.pd new file mode 100755 index 0000000..b276a52 --- /dev/null +++ b/filters/filtgain.pd @@ -0,0 +1,74 @@ +#N canvas 178 144 702 459 10; +#X obj 38 342 biquad~; +#X obj 38 316 osc~ 220; +#X obj 118 340 env~; +#X floatatom 38 297; +#X obj 38 419 dac~; +#X obj 193 428 tabwrite array1; +#X obj 325 400 int; +#X obj 350 401 + 1; +#X msg 296 399 0; +#X obj 193 410 float; +#X obj 218 372 t b f; +#X obj 38 398 *~; +#X obj 61 399 dbtorms; +#X floatatom 368 359; +#X obj 296 418 sel 500; +#X obj 38 277 * 40; +#X obj 325 380 metro 10; +#X obj 325 359 r paint; +#X obj 61 381 r volume; +#X obj 38 7 inlet; +#X floatatom 194 368; +#X floatatom 279 360; +#X obj 118 360 - 100; +#X obj 118 382 * 0.01; +#X graph graph2 0 -1 500 1 148 253 648 113; +#X array array1 500 float; +#X pop; +#X msg 273 272 5000; +#X msg 273 82 5000; +#X msg 398 82 10000; +#X msg 398 272 10000; +#X msg 173 83 1000; +#X msg 173 271 1000; +#X text 105 6 subpatch used in filter externals see; +#X obj 347 12 bandpass; +#X obj 414 13 notch; +#X obj 470 14 lowpass; +#X obj 522 13 highpass; +#X obj 522 35 equalizer; +#X obj 347 34 highshelf; +#X obj 414 34 lowshelf; +#X obj 470 34 hlshelf; +#X connect 0 0 2 0; +#X connect 0 0 11 0; +#X connect 1 0 0 0; +#X connect 2 0 22 0; +#X connect 3 0 1 0; +#X connect 6 0 7 0; +#X connect 6 0 10 0; +#X connect 6 0 14 0; +#X connect 6 0 15 0; +#X connect 7 0 6 1; +#X connect 8 0 6 0; +#X connect 9 0 5 0; +#X connect 10 0 9 0; +#X connect 10 1 5 1; +#X connect 11 0 4 0; +#X connect 11 0 4 1; +#X connect 12 0 11 1; +#X connect 13 0 16 1; +#X connect 14 0 8 0; +#X connect 15 0 3 0; +#X connect 16 0 6 0; +#X connect 17 0 16 0; +#X connect 18 0 12 0; +#X connect 19 0 0 0; +#X connect 20 0 5 0; +#X connect 21 0 5 1; +#X connect 22 0 23 0; +#X connect 23 0 9 1; +#X connect 26 0 25 0; +#X connect 27 0 28 0; +#X connect 29 0 30 0; diff --git a/filters/highpass.c b/filters/highpass.c new file mode 100755 index 0000000..e7e0443 --- /dev/null +++ b/filters/highpass.c @@ -0,0 +1,87 @@ +/* (C) Guenter Geiger */ + + +/* + + These filter coefficients computations are taken from + http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt + + written by Robert Bristow-Johnson + +*/ + +#include +#ifdef NT +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif +#include +#include "filters.h" + + +/* ------------------- highpass ----------------------------*/ + +static t_class *highpass_class; + +void highpass_bang(t_rbjfilter *x) +{ + t_atom at[5]; + t_float omega = e_omega(x->x_freq,x->x_rate); + t_float alpha = e_alpha(x->x_bw* 0.01,omega); + t_float b1 = -(1 + cos(omega)); + t_float b0 = -b1/2.; + t_float b2 = b0; + t_float a0 = 1 + alpha; + t_float a1 = -2.*cos(omega); + t_float a2 = 1 - alpha; + +/* post("bang %f %f %f",x->x_freq, x->x_gain, x->x_bw); */ + + if (!check_stability(-a1/a0,-a2/a0,b0/a0,b1/a0,b2/a0)) { + post("highpass: filter unstable -> resetting"); + a0=1.;a1=0.;a2=0.; + b0=1.;b1=0.;b2=0.; + } + + SETFLOAT(at,-a1/a0); + SETFLOAT(at+1,-a2/a0); + SETFLOAT(at+2,b0/a0); + SETFLOAT(at+3,b1/a0); + SETFLOAT(at+4,b2/a0); + + outlet_list(x->x_obj.ob_outlet,&s_list,5,at); +} + + +void highpass_float(t_rbjfilter *x,t_floatarg f) +{ + x->x_freq = f; + highpass_bang(x); +} + + +static void *highpass_new(t_floatarg f,t_floatarg bw) +{ + t_rbjfilter *x = (t_rbjfilter *)pd_new(highpass_class); + + x->x_rate = 44100.0; + outlet_new(&x->x_obj,&s_float); +/* floatinlet_new(&x->x_obj, &x->x_gain); */ + floatinlet_new(&x->x_obj, &x->x_bw); + if (f > 0.) x->x_freq = f; + if (bw > 0.) x->x_bw = bw; + return (x); +} + + +void highpass_setup(void) +{ + highpass_class = class_new(gensym("highpass"), (t_newmethod)highpass_new, 0, + sizeof(t_rbjfilter), 0,A_DEFFLOAT,A_DEFFLOAT,0); + class_addbang(highpass_class,highpass_bang); + class_addfloat(highpass_class,highpass_float); +} + + + + diff --git a/filters/highpass.pd b/filters/highpass.pd new file mode 100755 index 0000000..e953888 --- /dev/null +++ b/filters/highpass.pd @@ -0,0 +1,35 @@ +#N canvas 365 183 620 463 10; +#X obj 77 182 print; +#X floatatom 77 114; +#X floatatom 168 115; +#X msg 360 109 \; paint 0; +#X obj 159 175 filtgain; +#X msg 91 138 bang; +#X text 168 94 bandwidth (0 - 100); +#X text 6 334 See also:; +#X obj 72 335 bandpass; +#X obj 139 336 notch; +#X obj 195 337 lowpass; +#X obj 247 336 highpass; +#X obj 247 358 equalizer; +#X obj 72 357 highshelf; +#X obj 139 357 lowshelf; +#X obj 195 357 hlshelf; +#X text 75 226 These filters are all controlled by a bandwidth which is expressed in octaves. A bandwidth of 100 is equivalent to one octave.; +#X text 358 25 click first; +#X text 182 148 click on filtgain to view frequency plot; +#X text 70 26 ===================================; +#X text 6 393 (C) Guenter Geiger 2000; +#X text 75 92 frequency; +#X text 75 268 Attention \, only the left inlet triggers new coefficients for biquad~; +#X text 76 12 Highpass coefficients for biquad~; +#X obj 77 160 highpass 4000 33; +#X obj 34 113 r doit; +#X msg 360 45 \; pd dsp 1 \; paint 1 \; doit bang \;; +#X connect 1 0 24 0; +#X connect 2 0 5 0; +#X connect 2 0 24 1; +#X connect 5 0 24 0; +#X connect 24 0 0 0; +#X connect 24 0 4 0; +#X connect 25 0 24 0; diff --git a/filters/highshelf.c b/filters/highshelf.c new file mode 100755 index 0000000..ee6006c --- /dev/null +++ b/filters/highshelf.c @@ -0,0 +1,90 @@ +/* (C) Guenter Geiger */ + + +/* + + These filter coefficients computations are taken from + http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt + + written by Robert Bristow-Johnson + +*/ + +#include +#ifdef NT +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif +#include +#include "filters.h" + + +/* ------------------- highshelf ----------------------------*/ + +static t_class *highshelf_class; + +void highshelf_bang(t_rbjfilter *x) +{ + t_atom at[5]; + t_float omega = e_omega(x->x_freq,x->x_rate); + t_float A = e_A(x->x_gain); + t_float cs = cos(omega); + t_float sn = sin(omega); + t_float beta = e_beta(A,x->x_bw* 0.01); + + t_float b0 = A*((A+1) + (A-1)*cs + beta*sn); + t_float b1 =-2.*A*((A-1) + (A+1)*cs); + t_float b2 = A*((A+1) + (A-1)*cs - beta*sn); + t_float a0 = ((A+1) - (A-1)*cs + beta*sn); + t_float a1 = 2.*((A-1) - (A+1)*cs); + t_float a2 = ((A+1) - (A-1)*cs - beta*sn); + +/* post("bang %f %f %f",x->x_freq, x->x_gain, x->x_bw);*/ + + if (!check_stability(-a1/a0,-a2/a0,b0/a0,b1/a0,b2/a0)) { + post("highshelf: filter unstable -> resetting"); + a0=1.;a1=0.;a2=0.; + b0=1.;b1=0.;b2=0.; + } + + SETFLOAT(at,-a1/a0); + SETFLOAT(at+1,-a2/a0); + SETFLOAT(at+2,b0/a0); + SETFLOAT(at+3,b1/a0); + SETFLOAT(at+4,b2/a0); + + outlet_list(x->x_obj.ob_outlet,&s_list,5,at); +} + + +void highshelf_float(t_rbjfilter *x,t_floatarg f) +{ + x->x_freq = f; + highshelf_bang(x); +} + + +static void *highshelf_new(t_floatarg f,t_floatarg g,t_floatarg bw) +{ + t_rbjfilter *x = (t_rbjfilter *)pd_new(highshelf_class); + + x->x_rate = 44100.0; + outlet_new(&x->x_obj,&s_float); + floatinlet_new(&x->x_obj, &x->x_gain); + floatinlet_new(&x->x_obj, &x->x_bw); + if (f > 0.) x->x_freq = f; + if (bw > 0.) x->x_bw = bw; + if (g != 0.) x->x_gain = g; + return (x); +} + + +void highshelf_setup(void) +{ + highshelf_class = class_new(gensym("highshelf"), (t_newmethod)highshelf_new, 0, + sizeof(t_rbjfilter), 0,A_DEFFLOAT,A_DEFFLOAT,A_DEFFLOAT,0); + class_addbang(highshelf_class,highshelf_bang); + class_addfloat(highshelf_class,highshelf_float); +} + + diff --git a/filters/highshelf.pd b/filters/highshelf.pd new file mode 100755 index 0000000..be2a577 --- /dev/null +++ b/filters/highshelf.pd @@ -0,0 +1,39 @@ +#N canvas 310 193 620 455 10; +#X obj 77 182 print; +#X floatatom 77 114; +#X floatatom 186 112; +#X msg 360 117 \; paint 0; +#X obj 159 175 filtgain; +#X msg 91 138 bang; +#X text 6 334 See also:; +#X obj 72 335 bandpass; +#X obj 139 336 notch; +#X obj 195 337 lowpass; +#X obj 247 336 highpass; +#X obj 247 358 equalizer; +#X obj 72 357 highshelf; +#X obj 139 357 lowshelf; +#X obj 195 357 hlshelf; +#X text 75 226 These filters are all controlled by a bandwidth which is expressed in octaves. A bandwidth of 100 is equivalent to one octave.; +#X text 358 25 click first; +#X text 208 159 click on filtgain to view frequency plot; +#X text 6 393 (C) Guenter Geiger 2000; +#X text 75 92 frequency; +#X text 75 268 Attention \, only the left inlet triggers new coefficients for biquad~; +#X floatatom 129 113; +#X text 138 92 gain; +#X text 71 26 ==============================================; +#X text 186 91 slope (0 - 100); +#X text 76 12 Highshelf coefficients for biquad~; +#X obj 77 160 highshelf 5000 70 100; +#X obj 30 113 r doit; +#X msg 360 45 \; pd dsp 1 \; paint 1 \; doit bang \;; +#X connect 1 0 26 0; +#X connect 2 0 5 0; +#X connect 2 0 26 2; +#X connect 5 0 26 0; +#X connect 21 0 5 0; +#X connect 21 0 26 1; +#X connect 26 0 0 0; +#X connect 26 0 4 0; +#X connect 27 0 26 0; diff --git a/filters/hlshelf.c b/filters/hlshelf.c new file mode 100755 index 0000000..a2189d7 --- /dev/null +++ b/filters/hlshelf.c @@ -0,0 +1,226 @@ +/* (C) Guenter Geiger */ + + +#include +#include + +#ifdef NT +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif + +/* ------------------------ hlshelf ----------------------------- */ + + +#ifndef M_PI +#define M_PI 3.141593f +#endif + +#define SRATE 44100.0 +#define MAX_GAIN 120.0f + +static t_class *hlshelf_class; + + +typedef struct _hlshelf +{ + t_object x_obj; + float s_rate; + float s_gain0; + float s_gain1; + float s_gain2; + float s_ltransfq; + float s_htransfq; + float s_lradians; + float s_hradians; +} t_hlshelf; + + +int hlshelf_check_stability(t_float fb1, + t_float fb2, + t_float ff1, + t_float ff2, + t_float ff3) +{ + float discriminant = fb1 * fb1 + 4 * fb2; + + if (discriminant < 0) /* imaginary roots -- resonant filter */ + { + /* they're conjugates so we just check that the product + is less than one */ + if (fb2 >= -1.0f) goto stable; + } + else /* real roots */ + { + /* check that the parabola 1 - fb1 x - fb2 x^2 has a + vertex between -1 and 1, and that it's nonnegative + at both ends, which implies both roots are in [1-,1]. */ + if (fb1 <= 2.0f && fb1 >= -2.0f && + 1.0f - fb1 -fb2 >= 0 && 1.0f + fb1 - fb2 >= 0) + goto stable; + } + return 0; +stable: + return 1; +} + + +void hlshelf_check(t_hlshelf *x) +{ + + if(x->s_gain0 - x->s_gain1 > MAX_GAIN) { + x->s_gain0 = x->s_gain1 + MAX_GAIN; + post("setting gain0 to %f",x->s_gain0); + } + + + if(x->s_gain1 > MAX_GAIN) { + x->s_gain1 = MAX_GAIN; + post("setting gain1 to %f",x->s_gain1); + } + + if(x->s_gain2 - x->s_gain1 > MAX_GAIN) { + x->s_gain2 = x->s_gain1 + MAX_GAIN; + post("setting gain2 to %f",x->s_gain2); + } + + /* constrain: 0 <= x->s_ltransfq < x->s_htransfq. */ + x->s_ltransfq = (x->s_ltransfq < x->s_htransfq) ? x->s_ltransfq : x->s_htransfq - 0.5f; + + if (x->s_ltransfq < 0) x->s_ltransfq = 0.0f; + + x->s_lradians = M_PI * x->s_ltransfq / x->s_rate; + x->s_hradians= M_PI * (0.5f - (x->s_htransfq / x->s_rate)); + +} + + +void hlshelf_bang(t_hlshelf *x) +{ + t_atom at[6]; + float c0, c1, c2, d0, d1, d2; /* output coefs */ + float a1, a2, b1, b2, g1, g2; /* temp coefs */ + double xf; + + hlshelf_check(x); + + /* low shelf */ + xf = 0.5 * 0.115129255 * (double)(x->s_gain0 - x->s_gain1); /* ln(10) / 20 = 0.115129255 */ + if(xf < -200.) /* exp(x) -> 0 */ + { + a1 = 1.0f; + b1 = -1.0f; + g1 = 0.0f; + } + else + { + double t = tan(x->s_lradians); + double e = exp(xf); + double r = t / e; + double kr = t * e; + + a1 = (r - 1) / (r + 1); + b1 = (kr - 1) / (kr + 1); + g1 = (kr + 1) / (r + 1); + } + + /* high shelf */ + xf = 0.5 * 0.115129255 * (double)(x->s_gain2 - x->s_gain1); /* ln(10) / 20 = 0.115129255 */ + if(xf < -200.) /* exp(x) -> 0 */ + { + a2 = -1.0f; + b2 = 1.0f; + g2 = 0.0f; + } + else + { + double t = tan(x->s_hradians); + double e = exp(xf); + double r = t / e; + double kr = t * e; + + a2 = (1 - r) / (1 + r); + b2 = (1 - kr) / (1 + kr); + g2 = (1 + kr) / (1 + r); + } + + /* form product */ + c0 = g1 * g2 * (float)(exp((double)(x->s_gain1) * 0.05f * 2.302585093f)); ; + c1 = a1 + a2; + c2 = a1 * a2; + d0 = 1.0f; + d1 = b1 + b2; + d2 = b1 * b2; + + if (!hlshelf_check_stability(-c1/d0,-c2/d0,d0/d0,d1/d0,d2/d0)) { + post("hlshelf: filter unstable -> resetting"); + c0=1.;c1=0.;c2=0.; + d0=1.;d1=0.;d2=0.; + } + + SETFLOAT(at,-c1/d0); + SETFLOAT(at+1,-c2/d0); + SETFLOAT(at+2,d0/d0); + SETFLOAT(at+3,d1/d0); + SETFLOAT(at+4,d2/d0); + + outlet_list(x->x_obj.ob_outlet,&s_list,5,at); +} + +void hlshelf_float(t_hlshelf *x,t_floatarg f) +{ + x->s_gain0 = f; + hlshelf_bang(x); +} + + +static void *hlshelf_new(t_symbol* s,t_int argc, t_atom* at) +{ + t_hlshelf *x = (t_hlshelf *)pd_new(hlshelf_class); + t_float k0 = atom_getfloat(at); + t_float k1 = atom_getfloat(at+1); + t_float k2 = atom_getfloat(at+2); + t_float f1 = atom_getfloat(at+3); + t_float f2 = atom_getfloat(at+4); + + + f1 = atom_getfloat(at); + f2 = atom_getfloat(at); + + if ((f1 == 0.0f && f2 == 0.0f) || f1 > f2){ /* all gains = 0db */ + f1 = 150.0f; + f2 = 5000.0f; + } + + if (f1 < 0) f1 = 0.0f; + if (f2 > SRATE) f2 = .5f*SRATE; + + x->s_rate = SRATE; /* srate default */ + x->s_gain0 = k0; + x->s_gain1 = k1; + x->s_gain2 = k2; + + x->s_ltransfq = 0.0f; + x->s_htransfq = SRATE/2; + + x->s_lradians = M_PI * x->s_ltransfq / x->s_rate; + x->s_hradians= M_PI * (0.5f - (x->s_htransfq / x->s_rate)); + + floatinlet_new(&x->x_obj, &x->s_gain1); + floatinlet_new(&x->x_obj, &x->s_gain2); + floatinlet_new(&x->x_obj, &x->s_ltransfq); + floatinlet_new(&x->x_obj, &x->s_htransfq); + outlet_new(&x->x_obj, &s_list); + + return (x); +} + +void hlshelf_setup(void) +{ + hlshelf_class = class_new(gensym("hlshelf"), (t_newmethod)hlshelf_new, 0, + sizeof(t_hlshelf), 0, A_GIMME, 0); + class_addbang(hlshelf_class,hlshelf_bang); + class_addfloat(hlshelf_class,hlshelf_float); +} + + diff --git a/filters/hlshelf.pd b/filters/hlshelf.pd new file mode 100755 index 0000000..0e5251d --- /dev/null +++ b/filters/hlshelf.pd @@ -0,0 +1,34 @@ +#N canvas 365 183 620 471 10; +#X obj 77 182 print; +#X floatatom 77 114; +#X floatatom 139 114; +#X msg 360 109 \; paint 0; +#X obj 159 175 filtgain; +#X text 139 93 bandwidth (0 - 100); +#X text 6 334 See also:; +#X obj 72 335 bandpass; +#X obj 139 336 notch; +#X obj 195 337 lowpass; +#X obj 247 336 highpass; +#X obj 247 358 equalizer; +#X obj 72 357 highshelf; +#X obj 139 357 lowshelf; +#X obj 195 357 hlshelf; +#X text 75 226 These filters are all controlled by a bandwidth which is expressed in octaves. A bandwidth of 100 is equivalent to one octave.; +#X text 358 25 click first; +#X text 158 159 click on filtgain to view frequency plot; +#X text 76 12 Bandpass coefficients for biquad~; +#X text 70 26 ===================================; +#X text 6 393 (C) Guenter Geiger 2000; +#X text 75 92 frequency; +#X text 75 268 Attention \, only the left inlet triggers new coefficients for biquad~; +#X obj 77 61 r freq; +#X obj 139 61 r bw; +#X msg 360 45 \; pd dsp 1 \; paint 1 \; freq 4000 \; bw 33; +#X obj 77 160 hlshelf; +#X connect 1 0 26 0; +#X connect 2 0 26 1; +#X connect 23 0 1 0; +#X connect 24 0 2 0; +#X connect 26 0 0 0; +#X connect 26 0 4 0; diff --git a/filters/lowpass.c b/filters/lowpass.c new file mode 100755 index 0000000..4e1b2b9 --- /dev/null +++ b/filters/lowpass.c @@ -0,0 +1,89 @@ +/* (C) Guenter Geiger */ + + +/* + + These filter coefficients computations are taken from + http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt + + written by Robert Bristow-Johnson + +*/ + +#include +#ifdef NT +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif +#include +#include "filters.h" + + + +/* ------------------- lowpass ----------------------------*/ + +static t_class *lowpass_class; + +void lowpass_bang(t_rbjfilter *x) +{ + t_atom at[5]; + t_float omega = e_omega(x->x_freq,x->x_rate); + t_float alpha = e_alpha(x->x_bw*0.01,omega); + t_float b1 = 1 - cos(omega); + t_float b0 = b1/2.; + t_float b2 = b0; + t_float a0 = 1 + alpha; + t_float a1 = -2.*cos(omega); + t_float a2 = 1 - alpha; + +/* post("bang %f %f %f",x->x_freq, x->x_gain, x->x_bw); */ + + if (!check_stability(-a1/a0,-a2/a0,b0/a0,b1/a0,b2/a0)) { + post("lowpass: filter unstable -> resetting"); + a0=1.;a1=0.;a2=0.; + b0=1.;b1=0.;b2=0.; + } + + SETFLOAT(at,-a1/a0); + SETFLOAT(at+1,-a2/a0); + SETFLOAT(at+2,b0/a0); + SETFLOAT(at+3,b1/a0); + SETFLOAT(at+4,b2/a0); + + outlet_list(x->x_obj.ob_outlet,&s_list,5,at); +} + + +void lowpass_float(t_rbjfilter *x,t_floatarg f) +{ + x->x_freq = f; + lowpass_bang(x); +} + + +static void *lowpass_new(t_floatarg f,t_floatarg bw) +{ + t_rbjfilter *x = (t_rbjfilter *)pd_new(lowpass_class); + + x->x_rate = 44100.0; + outlet_new(&x->x_obj,&s_float); +/* floatinlet_new(&x->x_obj, &x->x_gain); */ + floatinlet_new(&x->x_obj, &x->x_bw); + + if (f > 0.) x->x_freq = f; + if (bw > 0.) x->x_bw = bw; + return (x); +} + + +void lowpass_setup(void) +{ + lowpass_class = class_new(gensym("lowpass"), (t_newmethod)lowpass_new, 0, + sizeof(t_rbjfilter), 0,A_DEFFLOAT,A_DEFFLOAT,0); + class_addbang(lowpass_class,lowpass_bang); + class_addfloat(lowpass_class,lowpass_float); +} + + + + diff --git a/filters/lowpass.pd b/filters/lowpass.pd new file mode 100755 index 0000000..9d15c16 --- /dev/null +++ b/filters/lowpass.pd @@ -0,0 +1,35 @@ +#N canvas 365 183 620 467 10; +#X obj 77 182 print; +#X floatatom 77 114; +#X floatatom 162 114; +#X msg 360 109 \; paint 0; +#X obj 159 175 filtgain; +#X msg 91 138 bang; +#X text 139 93 bandwidth (0 - 100); +#X text 6 334 See also:; +#X obj 72 335 bandpass; +#X obj 139 336 notch; +#X obj 195 337 lowpass; +#X obj 247 336 highpass; +#X obj 247 358 equalizer; +#X obj 72 357 highshelf; +#X obj 139 357 lowshelf; +#X obj 195 357 hlshelf; +#X text 75 226 These filters are all controlled by a bandwidth which is expressed in octaves. A bandwidth of 100 is equivalent to one octave.; +#X text 358 25 click first; +#X text 175 159 click on filtgain to view frequency plot; +#X text 70 26 ===================================; +#X text 6 393 (C) Guenter Geiger 2000; +#X text 75 92 frequency; +#X text 75 268 Attention \, only the left inlet triggers new coefficients for biquad~; +#X text 71 12 Lowpass coefficients for biquad~; +#X msg 360 45 \; pd dsp 1 \; paint 1 \; doit bang \;; +#X obj 32 114 r doit; +#X obj 77 160 lowpass 4000 33; +#X connect 1 0 26 0; +#X connect 2 0 5 0; +#X connect 2 0 26 1; +#X connect 5 0 26 0; +#X connect 25 0 26 0; +#X connect 26 0 0 0; +#X connect 26 0 4 0; diff --git a/filters/lowshelf.c b/filters/lowshelf.c new file mode 100755 index 0000000..dd925dc --- /dev/null +++ b/filters/lowshelf.c @@ -0,0 +1,91 @@ +/* (C) Guenter Geiger */ + + +/* + + These filter coefficients computations are taken from + http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt + + written by Robert Bristow-Johnson + +*/ + +#include +#ifdef NT +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif +#include +#include "filters.h" + + + +/* ------------------- lowshelf ----------------------------*/ + +static t_class *lowshelf_class; + +void lowshelf_bang(t_rbjfilter *x) +{ + t_atom at[5]; + t_float omega = e_omega(x->x_freq,x->x_rate); + t_float A = e_A(x->x_gain); + t_float cs = cos(omega); + t_float sn = sin(omega); + t_float beta = e_beta(A,x->x_bw*0.01); + + t_float b0 = A*((A+1) - (A-1)*cs + beta*sn); + t_float b1 = 2.*A*((A-1) - (A+1)*cs); + t_float b2 = A*((A+1) - (A-1)*cs - beta*sn); + t_float a0 = ((A+1) + (A-1)*cs + beta*sn); + t_float a1 = -2.*((A-1) + (A+1)*cs); + t_float a2 = ((A+1) + (A-1)*cs - beta*sn); + +/* post("bang %f %f %f",x->x_freq, x->x_gain, x->x_bw); */ + + if (!check_stability(-a1/a0,-a2/a0,b0/a0,b1/a0,b2/a0)) { + post("lowshelf: filter unstable -> resetting"); + a0=1.;a1=0.;a2=0.; + b0=1.;b1=0.;b2=0.; + } + + SETFLOAT(at,-a1/a0); + SETFLOAT(at+1,-a2/a0); + SETFLOAT(at+2,b0/a0); + SETFLOAT(at+3,b1/a0); + SETFLOAT(at+4,b2/a0); + + outlet_list(x->x_obj.ob_outlet,&s_list,5,at); +} + + +void lowshelf_float(t_rbjfilter *x,t_floatarg f) +{ + x->x_freq = f; + lowshelf_bang(x); +} + + +static void *lowshelf_new(t_floatarg f,t_floatarg g,t_floatarg bw) +{ + t_rbjfilter *x = (t_rbjfilter *)pd_new(lowshelf_class); + + x->x_rate = 44100.0; + outlet_new(&x->x_obj,&s_float); + floatinlet_new(&x->x_obj, &x->x_gain); + floatinlet_new(&x->x_obj, &x->x_bw); + if (f > 0.) x->x_freq = f; + if (bw > 0.) x->x_bw = bw; + if (g != 0.) x->x_gain = g; + return (x); +} + + +void lowshelf_setup(void) +{ + lowshelf_class = class_new(gensym("lowshelf"), (t_newmethod)lowshelf_new, 0, + sizeof(t_rbjfilter), 0,A_DEFFLOAT,A_DEFFLOAT,A_DEFFLOAT,0); + class_addbang(lowshelf_class,lowshelf_bang); + class_addfloat(lowshelf_class,lowshelf_float); +} + + diff --git a/filters/lowshelf.pd b/filters/lowshelf.pd new file mode 100755 index 0000000..140c754 --- /dev/null +++ b/filters/lowshelf.pd @@ -0,0 +1,39 @@ +#N canvas 365 183 620 459 10; +#X obj 77 182 print; +#X floatatom 77 114; +#X floatatom 192 113; +#X msg 360 117 \; paint 0; +#X obj 159 175 filtgain; +#X msg 91 138 bang; +#X text 6 334 See also:; +#X obj 72 335 bandpass; +#X obj 139 336 notch; +#X obj 195 337 lowpass; +#X obj 247 336 highpass; +#X obj 247 358 equalizer; +#X obj 72 357 highshelf; +#X obj 139 357 lowshelf; +#X obj 195 357 hlshelf; +#X text 75 226 These filters are all controlled by a bandwidth which is expressed in octaves. A bandwidth of 100 is equivalent to one octave.; +#X text 358 25 click first; +#X text 211 159 click on filtgain to view frequency plot; +#X text 6 393 (C) Guenter Geiger 2000; +#X text 75 92 frequency; +#X text 75 268 Attention \, only the left inlet triggers new coefficients for biquad~; +#X floatatom 129 113; +#X text 138 92 gain; +#X text 71 26 ==============================================; +#X text 192 92 slope (0 - 100); +#X text 76 12 Lowshelf coefficients for biquad~; +#X obj 31 113 r doit; +#X msg 360 45 \; pd dsp 1 \; paint 1 \; doit bang \;; +#X obj 77 160 lowshelf 4000 50 100; +#X connect 1 0 28 0; +#X connect 2 0 5 0; +#X connect 2 0 28 2; +#X connect 5 0 28 0; +#X connect 21 0 5 0; +#X connect 21 0 28 1; +#X connect 26 0 28 0; +#X connect 28 0 0 0; +#X connect 28 0 4 0; diff --git a/filters/moog~.c b/filters/moog~.c new file mode 100755 index 0000000..924ff31 --- /dev/null +++ b/filters/moog~.c @@ -0,0 +1,182 @@ +/* (C) Guenter Geiger */ + + +#include "math.h" +#include + +/* ----------------------------- moog ----------------------------- */ +static t_class *moog_class; + + +typedef struct _moog +{ + t_object x_obj; + t_pd in2; + t_float x_1,x_2,x_3,x_4; + t_float y_1,y_2,y_3,y_4; +} t_moog; + +static void moog_reset(t_moog *x) +{ + x->x_1 = x->x_2 = x->x_3 = x->x_4 = 0.0; + x->y_1 = x->y_2 = x->y_3 = x->y_4 = 0.0; + +} + + + +static void *moog_new(t_symbol *s, int argc, t_atom *argv) +{ + if (argc > 1) post("moog~: extra arguments ignored"); + { + t_moog *x = (t_moog *)pd_new(moog_class); + outlet_new(&x->x_obj, &s_signal); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); + inlet_new(&x->x_obj, &x->in2, &s_signal, &s_signal); + moog_reset(x); + return (x); + } + + +} + + + +static t_float calc_k(t_float f,t_float k) { + if (k>4.) k =4.; + if (k < 0.) k = 0.; + if (f <= 3800) return k; + k = k - 0.5*((f-3800)/4300); + return k; +} + +t_int *moog_perform(t_int *w) +{ + t_moog* x = (t_moog*) (w[1]); + t_float *in1 = (t_float *)(w[2]); + t_float *p = (t_float *)(w[3]); + t_float *k = (t_float *)(w[4]); + + t_float *out = (t_float *)(w[5]); + int n = (int)(w[6]); + float in; + float pt,pt1; + + float x1 = x->x_1; + float x2 = x->x_2; + float x3 = x->x_3; + float x4 = x->x_4; + float y1 = x->y_1; + float y2 = x->y_2; + float y3 = x->y_3; + float y4 = x->y_4; + + + while (n--) { + if (*p > 8140) *p = 8140.; + *k = calc_k(*p,*k); + pt =*p; + pt1=(pt+1)*0.76923077; + in = *in1++ - *k*y4; + y1 = (pt1)*in + 0.3*x1 - pt*y1; + x1 = in; + y2 = (pt1)*y1 + 0.3*x2 - pt*y2; + x2 = y1; + y3 = (pt1)*y2 + 0.3 *x3 - pt*y3; + x3 = y2; + y4 = (pt1)*y3 + 0.3*x4 - pt*y4; + x4 = y3; + *out++ = y4; + } + + + x->y_1 = y1; + x->y_2 = y2; + x->y_3 = y3; + x->y_4 = y4; + x->x_1 = x1; + x->x_2 = x2; + x->x_3 = x3; + x->x_4 = x4; + + return (w+7); +} + + +#define CLIP(x) x = ((x) > 1.0 ? (1.0) : (x)) + +t_int *moog_perf8(t_int *w) +{ + t_moog* x = (t_moog*) (w[1]); + t_float *in1 = (t_float *)(w[2]); + t_float *p = (t_float *)(w[3]); + t_float *k = (t_float *)(w[4]); + t_float *out = (t_float *)(w[5]); + int n = (int)(w[6]); + + t_float x1 = x->x_1; + t_float x2 = x->x_2; + t_float x3 = x->x_3; + t_float x4 = x->x_4; + t_float y1 = x->y_1; + t_float y2 = x->y_2; + t_float y3 = x->y_3; + t_float y4 = x->y_4; + t_float temp,temp2; + t_float pt,pt1; + t_float in; + + while (n--) { + if (*p > 8140.) *p = 8140.; + *k = calc_k(*p,*k); + + pt =*p* 0.01*0.0140845 - 0.9999999f; + pt1=(pt+1.0)*0.76923077; + in = *in1++ - *k*y4; + y1 = pt1*(in + 0.3*x1) - pt*y1; + x1 = in; + y2 = pt1*(y1 + 0.3*x2) - pt*y2; + x2 = y1; + y3 = pt1*(y2 + 0.3*x3) - pt*y3; + x3 = y2; + y4 = pt1*(y3 + 0.3*x4) - pt*y4; + x4 = y3; + *out++ = y4; + + p++;k++; + } + + x->y_1 = y1; + x->y_2 = y2; + x->y_3 = y3; + x->y_4 = y4; + x->x_1 = x1; + x->x_2 = x2; + x->x_3 = x3; + x->x_4 = x4; + + return (w+7); +} + +void dsp_add_moog(t_moog *x, t_sample *in1, t_sample *in2, t_sample *in3, t_sample *out, int n) +{ + if (n&7) + dsp_add(moog_perform, 6,(t_int)x, in1,in2,in3, out, n); + else + dsp_add(moog_perf8, 6,(t_int) x, in1, in2, in3, out, n); +} + +static void moog_dsp(t_moog *x, t_signal **sp) +{ + dsp_add_moog(x,sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec,sp[0]->s_n); +} + + +void moog_tilde_setup(void) +{ + moog_class = class_new(gensym("moog~"), (t_newmethod)moog_new, 0, + sizeof(t_moog), 0, A_GIMME, 0); + class_addmethod(moog_class, nullfn, gensym("signal"), 0); + class_addmethod(moog_class, (t_method)moog_reset, gensym("reset"), 0); + class_addmethod(moog_class, (t_method)moog_dsp, gensym("dsp"), A_NULL); +} diff --git a/filters/moog~.pd b/filters/moog~.pd new file mode 100755 index 0000000..7e0139b --- /dev/null +++ b/filters/moog~.pd @@ -0,0 +1,39 @@ +#N canvas 225 113 568 397 10; +#X obj 186 210 moog~; +#X obj 178 288 dac~; +#X floatatom 226 163 5 0 0; +#X floatatom 183 104 5 0 0; +#X floatatom 25 113 5 0 0; +#X obj 238 237 env~; +#X floatatom 238 257 5 0 0; +#X obj 186 257 *~ 0.1; +#X msg 182 163 reset; +#X obj 116 105 +~ 1; +#X floatatom 116 63 5 0 0; +#X floatatom 180 128 5 0 0; +#X obj 116 146 +~ 100; +#X obj 116 84 osc~ 0.25; +#X obj 116 125 *~ 2000; +#X obj 226 182 sig~ 3; +#X obj 25 139 phasor~ 110; +#X msg 249 52 \; pd dsp 1 \;; +#X text 17 7 A signal controlled "moog" resonant lowpass; +#X text 272 163 Q (1-4); +#X text 61 46 resonance freq modulation; +#X connect 0 0 5 0; +#X connect 0 0 7 0; +#X connect 2 0 15 0; +#X connect 3 0 14 1; +#X connect 4 0 16 0; +#X connect 5 0 6 0; +#X connect 7 0 1 0; +#X connect 7 0 1 1; +#X connect 8 0 0 0; +#X connect 9 0 14 0; +#X connect 10 0 13 0; +#X connect 11 0 12 1; +#X connect 12 0 0 1; +#X connect 13 0 9 0; +#X connect 14 0 12 0; +#X connect 15 0 0 2; +#X connect 16 0 0 0; diff --git a/filters/notch.c b/filters/notch.c new file mode 100755 index 0000000..ab11a7a --- /dev/null +++ b/filters/notch.c @@ -0,0 +1,89 @@ +/* (C) Guenter Geiger */ + + +/* + + These filter coefficients computations are taken from + http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt + + written by Robert Bristow-Johnson + +*/ + +#include +#ifdef NT +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif +#include +#include "filters.h" + + + +/* ------------------- notch ----------------------------*/ + +static t_class *notch_class; + +void notch_bang(t_rbjfilter *x) +{ + t_atom at[5]; + t_float omega = e_omega(x->x_freq,x->x_rate); + t_float alpha = e_alpha(x->x_bw* 0.01,omega); + t_float b1 = -2.*cos(omega); + t_float b0 = 1; + t_float b2 = b0; + t_float a0 = 1 + alpha; + t_float a1 = -2.*cos(omega); + t_float a2 = 1 - alpha; + +/* post("bang %f %f %f",x->x_freq, x->x_gain, x->x_bw); */ + + if (!check_stability(-a1/a0,-a2/a0,b0/a0,b1/a0,b2/a0)) { + post("notch: filter unstable -> resetting"); + a0=1.;a1=0.;a2=0.; + b0=1.;b1=0.;b2=0.; + } + + SETFLOAT(at,-a1/a0); + SETFLOAT(at+1,-a2/a0); + SETFLOAT(at+2,b0/a0); + SETFLOAT(at+3,b1/a0); + SETFLOAT(at+4,b2/a0); + + outlet_list(x->x_obj.ob_outlet,&s_list,5,at); +} + + +void notch_float(t_rbjfilter *x,t_floatarg f) +{ + x->x_freq = f; + notch_bang(x); +} + + +static void *notch_new(t_floatarg f,t_floatarg bw) +{ + t_rbjfilter *x = (t_rbjfilter *)pd_new(notch_class); + + x->x_rate = 44100.0; + outlet_new(&x->x_obj,&s_float); +/* floatinlet_new(&x->x_obj, &x->x_gain); */ + floatinlet_new(&x->x_obj, &x->x_bw); + if (f > 0.) x->x_freq = f; + if (bw > 0.) x->x_bw = bw; + return (x); +} + + +void notch_setup(void) +{ + notch_class = class_new(gensym("notch"), (t_newmethod)notch_new, 0, + sizeof(t_rbjfilter), 0,A_DEFFLOAT,A_DEFFLOAT,0); + class_addbang(notch_class,notch_bang); + class_addfloat(notch_class,notch_float); +} + + + + + diff --git a/filters/notch.pd b/filters/notch.pd new file mode 100755 index 0000000..a65d9c4 --- /dev/null +++ b/filters/notch.pd @@ -0,0 +1,35 @@ +#N canvas 363 47 620 467 10; +#X obj 77 182 print; +#X floatatom 77 114; +#X floatatom 150 114; +#X msg 360 109 \; paint 0; +#X obj 159 175 filtgain; +#X msg 91 138 bang; +#X text 150 93 bandwidth (0 - 100); +#X text 6 334 See also:; +#X obj 72 335 bandpass; +#X obj 139 336 notch; +#X obj 195 337 lowpass; +#X obj 247 336 highpass; +#X obj 247 358 equalizer; +#X obj 72 357 highshelf; +#X obj 139 357 lowshelf; +#X obj 195 357 hlshelf; +#X text 75 226 These filters are all controlled by a bandwidth which is expressed in octaves. A bandwidth of 100 is equivalent to one octave.; +#X text 358 25 click first; +#X text 165 159 click on filtgain to view frequency plot; +#X text 70 26 ===================================; +#X text 6 393 (C) Guenter Geiger 2000; +#X text 75 92 frequency; +#X text 75 268 Attention \, only the left inlet triggers new coefficients for biquad~; +#X text 72 13 Notch coefficients for biquad~; +#X msg 360 46 \; pd dsp 1 \; paint 1 \; doit bang \;; +#X obj 35 114 r doit; +#X obj 77 160 notch 4000 33; +#X connect 1 0 26 0; +#X connect 2 0 5 0; +#X connect 2 0 26 1; +#X connect 5 0 26 0; +#X connect 25 0 26 0; +#X connect 26 0 0 0; +#X connect 26 0 4 0; -- cgit v1.2.1