From f165693257282af828dee26de69b1d38fe0221c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juha=20Vehvil=C3=A4inen?= Date: Sun, 6 Oct 2002 05:14:51 +0000 Subject: This commit was generated by cvs2svn to compensate for changes in r159, which included commits to RCS files with non-trunk default branches. svn path=/trunk/externals/svf~/; revision=160 --- svf~/Makefile | 75 +++++++++++++++++++++++++ svf~/README.txt | 5 ++ svf~/help-svf~.pd | 137 ++++++++++++++++++++++++++++++++++++++++++++++ svf~/svf~.c | 161 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 378 insertions(+) create mode 100644 svf~/Makefile create mode 100644 svf~/README.txt create mode 100644 svf~/help-svf~.pd create mode 100644 svf~/svf~.c diff --git a/svf~/Makefile b/svf~/Makefile new file mode 100644 index 0000000..6ea6e28 --- /dev/null +++ b/svf~/Makefile @@ -0,0 +1,75 @@ +current: + echo make pd_linux, pd_nt, pd_irix5, or pd_irix6 + +clean: ; rm -f *.pd_linux *.o + +# ----------------------- NT ----------------------- + +pd_nt: svf~.dll + +.SUFFIXES: .dll + +PDNTCFLAGS = /W3 /WX /DNT /DPD /nologo +VC="C:\Program Files\Microsoft Visual Studio\Vc98" + +PDNTINCLUDE = /I. /I\tcl\include /I\ftp\pd\src /I$(VC)\include + +PDNTLDIR = $(VC)\lib +PDNTLIB = $(PDNTLDIR)\libc.lib \ + $(PDNTLDIR)\oldnames.lib \ + $(PDNTLDIR)\kernel32.lib \ + \ftp\pd\bin\pd.lib + +.c.dll: + cl $(PDNTCFLAGS) $(PDNTINCLUDE) /c $*.c + link /dll /export:$*_setup $*.obj $(PDNTLIB) + +# ----------------------- IRIX 5.x ----------------------- + +pd_irix5: svf~.pd_irix5 + +.SUFFIXES: .pd_irix5 + +SGICFLAGS5 = -o32 -DPD -DUNIX -DIRIX -O2 + + +SGIINCLUDE = -I../../src/ + +.c.pd_irix5: + cc $(SGICFLAGS5) $(SGIINCLUDE) -o $*.o -c $*.c + ld -elf -shared -rdata_shared -o $*.pd_irix5 $*.o + rm $*.o + +# ----------------------- IRIX 6.x ----------------------- + +pd_irix6: svf~.pd_irix6 + +.SUFFIXES: .pd_irix6 + +SGICFLAGS6 = -n32 -DPD -DUNIX -DIRIX -DN32 -woff 1080,1064,1185 \ + -OPT:roundoff=3 -OPT:IEEE_arithmetic=3 -OPT:cray_ivdep=true \ + -Ofast=ip32 + +.c.pd_irix6: + cc $(SGICFLAGS6) $(SGIINCLUDE) -o $*.o -c $*.c + ld -IPA -n32 -shared -rdata_shared -o $*.pd_irix6 $*.o + rm $*.o + +# ----------------------- LINUX i386 ----------------------- + +pd_linux: svf~.pd_linux + +.SUFFIXES: .pd_linux + +LINUXCFLAGS = -DPD -O6 -funroll-loops -fomit-frame-pointer \ + -Wall -W -Wshadow -Wstrict-prototypes -Werror \ + -Wno-unused -Wno-parentheses -Wno-switch + +LINUXINCLUDE = -I/usr/local/lib/pd/include + +.c.pd_linux: + cc $(LINUXCFLAGS) $(LINUXINCLUDE) -o $*.o -c $*.c + ld -export_dynamic -shared -o $*.pd_linux $*.o -lc -lm + strip --strip-unneeded $*.pd_linux + rm $*.o + diff --git a/svf~/README.txt b/svf~/README.txt new file mode 100644 index 0000000..81538b7 --- /dev/null +++ b/svf~/README.txt @@ -0,0 +1,5 @@ +This is a signal-controlled port of Steve Harris' state variable filter +LADSPA plugin (http://plugin.org.uk). + +bsaylor@macalester.edu +http://www.macalester.edu/~bsaylor diff --git a/svf~/help-svf~.pd b/svf~/help-svf~.pd new file mode 100644 index 0000000..39c8cbf --- /dev/null +++ b/svf~/help-svf~.pd @@ -0,0 +1,137 @@ +#N canvas 10 20 762 475 10; +#X obj 170 445 dac~; +#X obj 7 369 phasor~; +#X floatatom 7 347 5 0 0; +#X obj 145 329 sig~; +#X obj 190 329 sig~; +#X obj 97 257 mtof; +#X obj 97 120 vsl 15 128 16 135 0 0 empty empty empty 0 -8 0 8 -262144 +-1 -1 0 1; +#X obj 145 120 vsl 15 128 0 1 0 0 empty empty empty 0 -8 0 8 -262144 +-1 -1 0 1; +#X obj 190 119 vsl 15 128 0 1 0 0 empty empty empty 0 -8 0 8 -262144 +-1 -1 0 1; +#X obj 97 329 line~; +#X msg 97 306 \$1 100; +#X floatatom 200 281 5 0 0; +#X floatatom 155 281 5 0 0; +#X floatatom 97 281 7 0 0; +#X msg 361 123 low; +#X msg 361 147 high; +#X msg 361 171 band; +#X msg 361 195 notch; +#X msg 361 219 peak; +#X obj 7 303 loadbang; +#N canvas 4 20 608 388 hanning-table 0; +#X obj 92 206 phasor~; +#X obj 92 234 cos~; +#X obj 23 328 tabwrite~ hanning; +#X obj 30 252 -~; +#X obj 28 218 sig~ 1; +#X msg 37 180 0; +#X text 141 13 CALCULATE HANNING; +#X text 141 27 WINDOW TABLE; +#N canvas 0 0 450 300 graph1 0; +#X array hanning 512 float 0; +#X coords 0 1 511 0 256 128 1; +#X restore 305 93 graph; +#X obj 93 171 sig~; +#X text 24 354 sample rate / window size; +#X msg 23 144 bang; +#X obj 66 269 sig~ 0.5; +#X obj 49 300 *~; +#X obj 67 96 samplerate~; +#X obj 25 53 t b f; +#X obj 25 8 loadbang; +#X msg 25 31 512; +#X obj 94 131 / 512; +#X connect 0 0 1 0; +#X connect 1 0 3 1; +#X connect 3 0 13 0; +#X connect 4 0 3 0; +#X connect 5 0 0 1; +#X connect 9 0 0 0; +#X connect 11 0 2 0; +#X connect 11 0 5 0; +#X connect 12 0 13 1; +#X connect 13 0 2 0; +#X connect 14 0 18 0; +#X connect 15 0 14 0; +#X connect 15 0 11 0; +#X connect 15 1 18 1; +#X connect 16 0 17 0; +#X connect 17 0 15 0; +#X connect 18 0 9 0; +#X restore 13 430 pd hanning-table; +#N canvas 10 112 328 354 fft-analysis 0; +#X obj 69 15 inlet~; +#X obj 43 74 rfft~; +#X obj 37 123 *~; +#X obj 81 124 *~; +#X obj 49 167 +~; +#X obj 49 196 sqrt~; +#X obj 27 297 tabsend~ response; +#X obj 171 209 block~ 512 2; +#X obj 182 61 tabreceive~ hanning; +#X obj 164 99 *~; +#X obj 69 36 /~ 8; +#X obj 51 249 clip~ 0 1; +#X connect 0 0 10 0; +#X connect 1 0 2 0; +#X connect 1 0 2 1; +#X connect 1 1 3 0; +#X connect 1 1 3 1; +#X connect 2 0 4 0; +#X connect 3 0 4 1; +#X connect 4 0 5 0; +#X connect 5 0 11 0; +#X connect 8 0 9 1; +#X connect 9 0 1 0; +#X connect 10 0 9 0; +#X connect 11 0 6 0; +#X restore 216 421 pd fft-analysis; +#N canvas 0 0 450 300 graph1 0; +#X array response 256 float 0; +#X coords 0 1 255 0 256 140 1; +#X restore 478 10 graph; +#X msg 7 325 110; +#X text 5 1 svf~ - state-variable filter; +#X text 146 99 q; +#X text 171 100 resonance; +#X text 67 100 frequency; +#X text 331 100 filter type; +#X obj 200 387 svf~ low; +#X text 8 28 A port of Steve Harris' LADSPA plugin; +#X text 6 45 (http://plugin.org.uk); +#X text 325 313 Notes:; +#X text 338 334 'q' controls the filter resonance. The resonance input +is for 'extra' resonance.. :); +#X text 400 171 <- keep q below 0.1; +#X text 339 370 The filters don't use the same scale for frequency. +Bandpass frequency seems to be in Hz. If the frequency is set too high +\, LOUD aliasing is produced.; +#X text 339 418 The bandpass filter is very sensitive to q - normal +range is 0 to 0.1.; +#X connect 1 0 29 0; +#X connect 2 0 1 0; +#X connect 3 0 29 2; +#X connect 4 0 29 3; +#X connect 5 0 13 0; +#X connect 6 0 5 0; +#X connect 7 0 3 0; +#X connect 7 0 12 0; +#X connect 8 0 4 0; +#X connect 8 0 11 0; +#X connect 9 0 29 1; +#X connect 10 0 9 0; +#X connect 13 0 10 0; +#X connect 14 0 29 0; +#X connect 15 0 29 0; +#X connect 16 0 29 0; +#X connect 17 0 29 0; +#X connect 18 0 29 0; +#X connect 19 0 23 0; +#X connect 23 0 2 0; +#X connect 29 0 0 0; +#X connect 29 0 0 1; +#X connect 29 0 21 0; diff --git a/svf~/svf~.c b/svf~/svf~.c new file mode 100644 index 0000000..5958641 --- /dev/null +++ b/svf~/svf~.c @@ -0,0 +1,161 @@ +/* + * copyright Steve Harris, Ben Saylor + * see GPL.txt + */ + +#include +#include +#include "m_pd.h" + +#ifdef NT +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif + +// Number of filter oversamples +#define F_R 3 + +// Denormalise floats, only actually needed for PIII and very recent PowerPC +#define FLUSH_TO_ZERO(fv) (((*(unsigned int*)&(fv))&0x7f800000)==0)?0.0f:(fv) + +/* pd's samplerate */ +float fs; + +static t_class *svf_class; + +typedef struct _svf +{ + t_object x_obj; + float f; // 2.0*sin(PI*fs/(fc*r)); + float q; // 2.0*cos(pow(q, 0.1)*PI*0.5); + float qnrm; // sqrt(m/2.0f+0.01f); + float h; // high pass output + float b; // band pass output + float l; // low pass output + float p; // peaking output (allpass with resonance) + float n; // notch output + float *op; // pointer to output value +} t_svf; + +/* Store data in SVF struct, takes the sampling frequency, cutoff frequency + and Q, and fills in the structure passed */ +//static inline void setup_svf(sv_filter *sv, float fs, float fc, float q, int t) { +static inline void setup_svf(t_svf *sv, float fc, float q) { + sv->f = 2.0f * sin(M_PI * fc / (float)(fs * F_R)); + sv->q = 2.0f * cos(pow(q, 0.1f) * M_PI * 0.5f); + sv->qnrm = sqrt(sv->q/2.0+0.01); +} + +/* Run one sample through the SV filter. Filter is by andy@vellocet */ +static inline float run_svf(t_svf *sv, float in) { + float out; + int i; + + in = sv->qnrm * in ; + for (i=0; i < F_R; i++) { + // only needed for pentium chips + in = FLUSH_TO_ZERO(in); + sv->l = FLUSH_TO_ZERO(sv->l); + // very slight waveshape for extra stability + sv->b = sv->b - sv->b * sv->b * sv->b * 0.001f; + + // regular state variable code here + // the notch and peaking outputs are optional + sv->h = in - sv->l - sv->q * sv->b; + sv->b = sv->b + sv->f * sv->h; + sv->l = sv->l + sv->f * sv->b; + sv->n = sv->l + sv->h; + sv->p = sv->l - sv->h; + + out = *(sv->op); + in = out; + } + + return out; +} + +static void svf_setstate_LP(t_svf *sv) +{ + sv->op = &(sv->l); +} + +static void svf_setstate_HP(t_svf *sv) +{ + sv->op = &(sv->h); +} + +static void svf_setstate_BP(t_svf *sv) +{ + sv->op = &(sv->b); +} + +static void svf_setstate_BR(t_svf *sv) +{ + sv->op = &(sv->n); +} + +static void svf_setstate_AP(t_svf *sv) +{ + sv->op = &(sv->p); +} + +static t_int *svf_perform(t_int *w) +{ + t_svf *obj = (t_svf *)(w[1]); + t_float *in = (t_float *)(w[2]); + t_float *freq = (t_float *)(w[3]); + t_float *q = (t_float *)(w[4]); + t_float *res = (t_float *)(w[5]); + t_float *out = (t_float *)(w[6]); + int n = (int)(w[7]); + while (n--) { + float f = *(in++); + setup_svf(obj, *(freq++), *(q++)); + *(out++) = run_svf(obj, f + ((obj->b) * (*(res++)))); + } + return (w+8); +} + +static void svf_dsp(t_svf *x, t_signal **sp) +{ + dsp_add(svf_perform, 7, x, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, sp[4]->s_vec, sp[0]->s_n); +} + +static void *svf_new(t_symbol *s, int argc, t_atom *argv) +{ + char string[11]; + t_svf *x = (t_svf *)pd_new(svf_class); + + svf_setstate_LP(x); + if (argc > 0) { + atom_string(argv, string, 10); + if (!strcmp(string, "high")) + svf_setstate_HP(x); + if (!strcmp(string, "band")) + svf_setstate_BP(x); + if (!strcmp(string, "notch")) + svf_setstate_BR(x); + if (!strcmp(string, "peak")) + svf_setstate_AP(x); + } + + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); + outlet_new(&x->x_obj, gensym("signal")); + return (x); +} + +void svf_tilde_setup(void) +{ + fs = sys_getsr(); + svf_class = class_new(gensym("svf~"), (t_newmethod)svf_new, 0, sizeof(t_svf), 0, A_GIMME, 0); + class_sethelpsymbol(svf_class, gensym("help-svf~.pd")); + class_addmethod(svf_class, nullfn, gensym("signal"), 0); + class_addmethod(svf_class, (t_method)svf_dsp, gensym("dsp"), 0); + class_addmethod(svf_class, (t_method)svf_setstate_LP, gensym("low"), 0); + class_addmethod(svf_class, (t_method)svf_setstate_HP, gensym("high"), 0); + class_addmethod(svf_class, (t_method)svf_setstate_BP, gensym("band"), 0); + class_addmethod(svf_class, (t_method)svf_setstate_BR, gensym("notch"), 0); + class_addmethod(svf_class, (t_method)svf_setstate_AP, gensym("peak"), 0); +} -- cgit v1.2.1