From e35e02331589e993df65856ddacd5a99f936a99e 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/bsaylor/; revision=160 --- aenv~.c | 166 ++++++++++++++++++++++++++++++++++++++++++++++++++++ help/help-svf~.pd | 137 +++++++++++++++++++++++++++++++++++++++++++ help/help-zhzxh~.pd | 39 ++++++++++++ help/mtosr.pd | 11 ++++ help/susloop~.pd | 102 ++++++++++++++++++++++++++++++++ susloop~.c | 149 ++++++++++++++++++++++++++++++++++++++++++++++ svf~.c | 161 ++++++++++++++++++++++++++++++++++++++++++++++++++ zhzxh~.c | 83 ++++++++++++++++++++++++++ 8 files changed, 848 insertions(+) create mode 100644 aenv~.c create mode 100644 help/help-svf~.pd create mode 100644 help/help-zhzxh~.pd create mode 100644 help/mtosr.pd create mode 100644 help/susloop~.pd create mode 100644 susloop~.c create mode 100644 svf~.c create mode 100644 zhzxh~.c diff --git a/aenv~.c b/aenv~.c new file mode 100644 index 0000000..691e305 --- /dev/null +++ b/aenv~.c @@ -0,0 +1,166 @@ +/* Copyright 2002 Benjamin R. Saylor + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "m_pd.h" + +#ifdef NT +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif + +enum { ATTACK, DECAY, RELEASE, LINEAR, LOGARITHMIC }; +#define THRESHOLD 0.99 +#define SCALE 4600.0 +#define CLIP(x) ((x < 0.1) ? 0.1 : x) +#define IS_DENORMAL(f) (((*(unsigned int *)&(f))&0x7f800000) == 0) + +static t_class *aenv_class; + +typedef struct _aenv { + t_object x_obj; + t_float srate; + t_float a; + t_float d; + t_float s; + t_float r; + t_float lastval; + int stage; + int attacktype; +} t_aenv; + +static t_int *aenv_perform(t_int *w) +{ + t_aenv *x = (t_aenv *)(w[1]); + t_float *out = (t_float *)(w[2]); + int n = (int)(w[3]); + + t_float lastval = x->lastval; + t_float a, d, s, r; + + switch (x->stage) { + case ATTACK: + if (x->attacktype == LINEAR) { + a = 1000 / (x->a * x->srate); + while (n--) { + *out = lastval + a; + lastval = *(out++); + if (lastval > THRESHOLD) { + x->stage = DECAY; + break; + } + } + } else { + a = SCALE / (CLIP(x->a) * x->srate); + while (n--) { + *out = lastval + a * (1 - lastval); + lastval = *(out++); + if (lastval > THRESHOLD) { + x->stage = DECAY; + break; + } + } + } + case DECAY: + d = SCALE / (CLIP(x->d) * x->srate); + s = x->s; + while (n-- > 0) { + *out = lastval - d * (lastval - s); + if (IS_DENORMAL(*out)) *out = 0.0; + lastval = *(out++); + } + break; + case RELEASE: + r = SCALE / (CLIP(x->r) * x->srate); + while (n--) { + *out = lastval - r * lastval; + if (IS_DENORMAL(*out)) *out = 0.0; + lastval = *(out++); + } + } + + x->lastval = lastval; + + return (w+4); +} + +static void aenv_dsp(t_aenv *x, t_signal **sp) +{ + dsp_add(aenv_perform, 3, x, sp[0]->s_vec, sp[0]->s_n); +} + +static void aenv_float(t_aenv *x, t_float f) +{ + if (f == 0) + x->stage = RELEASE; + else + x->stage = ATTACK; +} + +static void *aenv_new(t_symbol *s, int argc, t_atom *argv) +{ + t_aenv *x = (t_aenv *)pd_new(aenv_class); + floatinlet_new(&x->x_obj, &x->a); + floatinlet_new(&x->x_obj, &x->d); + floatinlet_new(&x->x_obj, &x->s); + floatinlet_new(&x->x_obj, &x->r); + outlet_new(&x->x_obj, gensym("signal")); + + x->srate = sys_getsr(); + x->a = 500; + x->d = 500; + x->s = 0.5; + x->r = 500; + x->lastval = 0; + x->stage = RELEASE; + x->attacktype = LOGARITHMIC; + + if (argc == 4) { + x->a = atom_getfloat(argv); + x->d = atom_getfloat(argv+1); + x->s = atom_getfloat(argv+2); + x->r = atom_getfloat(argv+3); + } + + return (x); +} + +static void aenv_lina(t_aenv *x) +{ + x->attacktype = LINEAR; +} + +static void aenv_loga(t_aenv *x) +{ + x->attacktype = LOGARITHMIC; +} + +static void aenv_zero(t_aenv *x) +{ + x->stage = RELEASE; + x->lastval = 0.0; +} + +void aenv_tilde_setup(void) +{ + aenv_class = class_new(gensym("aenv~"), (t_newmethod)aenv_new, 0, sizeof(t_aenv), 0, A_GIMME, 0); + class_sethelpsymbol(aenv_class, gensym("help-aenv~.pd")); + class_addmethod(aenv_class, (t_method)aenv_dsp, gensym("dsp"), 0); + class_addfloat(aenv_class, (t_method)aenv_float); + class_addmethod(aenv_class, (t_method)aenv_lina, gensym("lina"), 0); + class_addmethod(aenv_class, (t_method)aenv_loga, gensym("loga"), 0); + class_addmethod(aenv_class, (t_method)aenv_zero, gensym("zero"), 0); +} diff --git a/help/help-svf~.pd b/help/help-svf~.pd new file mode 100644 index 0000000..39c8cbf --- /dev/null +++ b/help/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/help/help-zhzxh~.pd b/help/help-zhzxh~.pd new file mode 100644 index 0000000..9b5f26a --- /dev/null +++ b/help/help-zhzxh~.pd @@ -0,0 +1,39 @@ +#N canvas 12 60 418 347 10; +#X floatatom 127 195 5 0 0; +#X obj 76 307 dac~; +#X obj 78 277 *~; +#X obj 13 123 readsf~; +#X msg 36 94 1; +#X floatatom 99 46 5 0 0; +#X obj 130 183 hsl 128 8 0 2500 0 1 empty empty tone -2 -6 0 8 -262144 +-1 -1 8200 1; +#X obj 78 220 zhzxh~; +#X msg 13 56 open \$1; +#X obj 136 244 vsl 8 64 0 1 0 1 empty empty empty 0 -8 0 8 -262144 +-1 -1 4200 1; +#X text 163 25 http://www.macalester.edu/~bsaylor; +#X text 160 9 Ben Saylor ; +#X obj 13 31 openpanel; +#X obj 13 8 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 -1 +; +#X obj 105 120 *~; +#X obj 155 94 tgl 15 1 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1 +; +#X obj 99 67 mtof; +#X obj 99 93 osc~ 50; +#X connect 0 0 7 1; +#X connect 2 0 1 0; +#X connect 2 0 1 1; +#X connect 3 0 7 0; +#X connect 4 0 3 0; +#X connect 5 0 16 0; +#X connect 6 0 0 0; +#X connect 7 0 2 0; +#X connect 8 0 3 0; +#X connect 9 0 2 1; +#X connect 12 0 8 0; +#X connect 13 0 12 0; +#X connect 14 0 7 0; +#X connect 15 0 14 1; +#X connect 16 0 17 0; +#X connect 17 0 14 0; diff --git a/help/mtosr.pd b/help/mtosr.pd new file mode 100644 index 0000000..0807e69 --- /dev/null +++ b/help/mtosr.pd @@ -0,0 +1,11 @@ +#N canvas 0 0 450 300 10; +#X obj 38 57 mtof; +#X obj 38 33 inlet; +#X obj 38 82 expr \$1 / 261.626 * $f1; +#X obj 38 106 outlet; +#X text 74 249 creation argument: samplerate at middle C.; +#X text 25 190 takes midi note value and converts to a samplerate for +sample playback.; +#X connect 0 0 2 0; +#X connect 1 0 0 0; +#X connect 2 0 3 0; diff --git a/help/susloop~.pd b/help/susloop~.pd new file mode 100644 index 0000000..bce3791 --- /dev/null +++ b/help/susloop~.pd @@ -0,0 +1,102 @@ +#N canvas 236 83 735 643 10; +#N canvas 0 0 450 300 graph1 0; +#X array sample 86754 float 0; +#X coords 0 1 86753 -1 200 64 1; +#X restore 441 412 graph; +#X obj 480 341 soundfiler; +#X msg 480 315 read -resize \$1 sample; +#X obj 480 289 openpanel; +#X obj 480 267 bng 15 250 50 0 empty empty empty 20 8 0 8 -262144 -1 +-1; +#X obj 8 513 dac~; +#X floatatom 69 489 5 0 0; +#X obj 69 513 / 100; +#X obj 8 450 tabread4~ sample; +#X obj 8 481 *~; +#X floatatom 127 272 5 0 0; +#X obj 127 310 mtosr 44100; +#X msg 17 271 type 0; +#X msg 17 299 type 1; +#X msg 176 272 44100; +#X floatatom 322 380 5 0 0; +#X floatatom 179 380 6 0 0; +#X floatatom 245 380 6 0 0; +#X obj 88 271 bng 15 250 50 0 empty empty empty 20 8 0 8 -262144 -1 +-1; +#X text 514 265 <- load a sample; +#X text 421 230 Ben Saylor - bsaylor@macalester.edu; +#X msg 124 489 70; +#X obj 156 489 loadbang; +#X text 54 45 optional creation args:; +#X text 239 45 [loopstart loopend [looptype [startpos]]]; +#X text 172 336 loopstart; +#X text 242 337 loopend; +#X text 319 338 startpos; +#X text 38 154 is 0 for a forward loop (default) and 1 for +a pingpong loop.; +#X text 40 193 Playback speed is in samples/sec - send a float or signal +to the left inlet.; +#X text 10 7 susloop~ - another phase generator for sample looping +; +#X obj 127 414 susloop~ 4000 12000; +#X text 37 94 When the left inlet gets a bang \, the phase output will +start at (defaults to 0) \, continue until it reaches +\, and then start looping between and .; +#X floatatom 480 366 5 0 0; +#X obj 442 480 hsl 200 15 0 1 0 0 empty empty loop_start 10 8 0 8 -195568 +-33289 -33289 13700 0; +#X obj 442 499 hsl 200 15 0 1 0 0 empty empty loop_end 10 8 0 8 -233017 +-1 -1 16900 0; +#X obj 250 565 *; +#X obj 293 565 *; +#X obj 293 589 int; +#X obj 250 589 int; +#X obj 531 366 s filesize; +#X obj 266 501 r filesize; +#X obj 229 616 s lstart; +#X obj 293 615 s lend; +#X obj 245 356 r lend; +#X obj 179 358 r lstart; +#X obj 442 516 hsl 200 15 0 1 0 0 empty empty start 10 8 0 8 -262144 +-1 -1 0 0; +#X obj 346 567 *; +#X obj 346 591 int; +#X obj 346 616 s start; +#X obj 322 356 r start; +#X connect 1 0 33 0; +#X connect 1 0 40 0; +#X connect 2 0 1 0; +#X connect 3 0 2 0; +#X connect 4 0 3 0; +#X connect 6 0 7 0; +#X connect 7 0 9 1; +#X connect 8 0 9 0; +#X connect 9 0 5 0; +#X connect 9 0 5 1; +#X connect 10 0 11 0; +#X connect 11 0 31 0; +#X connect 12 0 31 0; +#X connect 13 0 31 0; +#X connect 14 0 31 0; +#X connect 15 0 31 3; +#X connect 16 0 31 1; +#X connect 17 0 31 2; +#X connect 18 0 31 0; +#X connect 21 0 7 0; +#X connect 22 0 21 0; +#X connect 31 0 8 0; +#X connect 34 0 36 0; +#X connect 35 0 37 0; +#X connect 36 0 39 0; +#X connect 37 0 38 0; +#X connect 38 0 43 0; +#X connect 39 0 42 0; +#X connect 41 0 36 1; +#X connect 41 0 37 1; +#X connect 41 0 47 1; +#X connect 44 0 17 0; +#X connect 45 0 16 0; +#X connect 46 0 47 0; +#X connect 47 0 48 0; +#X connect 48 0 49 0; +#X connect 50 0 15 0; diff --git a/susloop~.c b/susloop~.c new file mode 100644 index 0000000..bdde314 --- /dev/null +++ b/susloop~.c @@ -0,0 +1,149 @@ +/* Copyright 2002 Benjamin R. Saylor + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "m_pd.h" + +static t_class *susloop_class; + +static t_float pdsr; /* pd's sample rate */ + +typedef struct _susloop { + t_object x_obj; + t_float a; /* beginning of loop */ + t_float b; /* end of loop */ + t_float startpos; /* start offset */ + t_float pos; /* position in sample */ + t_float direction; /* for pingpong loops */ + t_float f; /* dummy for when input is float instead of signal */ + void (*susloop_func)(t_int *x, t_float *in, t_float *out, int n); /* can be forward or pingpong */ +} t_susloop; + +static void susloop_forward(t_int *x, t_float *in, t_float *out, int n) +{ + t_float sr; + t_float p = ((t_susloop *)x)->pos; + t_float a = ((t_susloop *)x)->a; + t_float b = ((t_susloop *)x)->b; + + while (n--) { + sr = *in; + if (p > b) { + p = a + (p - b); + } + *out = p; + p += sr/pdsr; + in++; + out++; + } + + ((t_susloop *)x)->pos = p; +} + +static void susloop_pingpong(t_int *x, t_float *in, t_float *out, int n) +{ + t_float sr; + t_float p = ((t_susloop *)x)->pos; + t_float a = ((t_susloop *)x)->a; + t_float b = ((t_susloop *)x)->b; + t_float d = ((t_susloop *)x)->direction; + + while (n--) { + sr = *in; + if (p > b) { + p = b - (p - b); + d = -1; + } else if (p < a && d < 0) { + p = a + (a - p); + d = 1; + } + *out = p; + p += d*(sr/pdsr); + in++; + out++; + } + + ((t_susloop *)x)->pos = p; + ((t_susloop *)x)->direction = d; +} + +static t_int *susloop_perform(t_int *w) +{ + ((t_susloop *)w[1])->susloop_func((t_int *)w[1], (t_float *)(w[2]), (t_float *)(w[3]), (int)(w[4])); + return (w+5); +} + +static void susloop_dsp(t_susloop *x, t_signal **sp) +{ + dsp_add(susloop_perform, 4, x, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n); +} + +static void *susloop_new(t_symbol *s, int argc, t_atom *argv) +{ + t_susloop *x = (t_susloop *)pd_new(susloop_class); + int looptype = 0; + x->a = x->b = x->startpos = 0; + x->direction = 1; + x->susloop_func = susloop_forward; + + switch (argc) { + case 4: + x->startpos = atom_getfloat(argv+3); + case 3: + looptype = atom_getint(argv+2); + if (looptype == 0) + x->susloop_func = susloop_forward; + else + x->susloop_func = susloop_pingpong; + case 2: + x->a = atom_getfloat(argv); + x->b = atom_getfloat(argv+1); + } + + floatinlet_new(&x->x_obj, &x->a); + floatinlet_new(&x->x_obj, &x->b); + floatinlet_new(&x->x_obj, &x->startpos); + outlet_new(&x->x_obj, gensym("signal")); + return (x); +} + +static void susloop_bang(t_susloop *x) +{ + x->pos = x->startpos; + x->direction = 1; +} + +static void susloop_setfunc(t_susloop *x, t_floatarg type) +{ + if (type == 1) { + x->direction = 1; + x->susloop_func = susloop_pingpong; + } else + x->susloop_func = susloop_forward; +} + +void susloop_tilde_setup(void) +{ + pdsr = sys_getsr(); + susloop_class = class_new(gensym("susloop~"), (t_newmethod)susloop_new, 0, sizeof(t_susloop), 0, A_GIMME, 0); + class_addbang(susloop_class, susloop_bang); + /* + class_addmethod(susloop_class, nullfn, gensym("signal"), 0); + */ + CLASS_MAINSIGNALIN(susloop_class, t_susloop, f); + class_addmethod(susloop_class, (t_method)susloop_dsp, gensym("dsp"), 0); + class_addmethod(susloop_class, (t_method)susloop_setfunc, gensym("type"), A_DEFFLOAT, 0); +} diff --git a/svf~.c b/svf~.c new file mode 100644 index 0000000..5958641 --- /dev/null +++ b/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); +} diff --git a/zhzxh~.c b/zhzxh~.c new file mode 100644 index 0000000..59a80d2 --- /dev/null +++ b/zhzxh~.c @@ -0,0 +1,83 @@ +/* Copyright 2002 Benjamin R. Saylor + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "m_pd.h" + +#ifdef NT +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif + +static t_class *zhzxh_class; + +typedef struct _zhzxh { + t_object x_obj; + t_float slope; + t_float lastval; + t_float srate; + t_float f; +} t_zhzxh; + +static t_int *zhzxh_perform(t_int *w) +{ + t_zhzxh *x = (t_zhzxh *)(w[1]); + t_float *in = (t_float *)(w[2]); + t_float *out = (t_float *)(w[3]); + int n = (int)(w[4]); + t_float f; + + t_float lastval = x->lastval; + t_float delta = x->slope / x->srate; + + while (n--) { + f = *(in++); + if (lastval < f) + *out = lastval + delta; + else + *out = lastval - delta; + lastval = *(out++); + } + + x->lastval = lastval; + + return (w+5); +} + +static void zhzxh_dsp(t_zhzxh *x, t_signal **sp) +{ + dsp_add(zhzxh_perform, 4, x, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n); +} + +static void *zhzxh_new(t_symbol *s, int argc, t_atom *argv) +{ + t_zhzxh *x = (t_zhzxh *)pd_new(zhzxh_class); + x->slope = 1; + x->lastval = 0; + x->srate = sys_getsr(); + floatinlet_new(&x->x_obj, &x->slope); + outlet_new(&x->x_obj, gensym("signal")); + + return (x); +} + +void zhzxh_tilde_setup(void) +{ + zhzxh_class = class_new(gensym("zhzxh~"), (t_newmethod)zhzxh_new, 0, sizeof(t_zhzxh), 0, A_GIMME, 0); + class_sethelpsymbol(zhzxh_class, gensym("help-zhzxh~.pd")); + CLASS_MAINSIGNALIN(zhzxh_class, t_zhzxh, f); + class_addmethod(zhzxh_class, (t_method)zhzxh_dsp, gensym("dsp"), 0); +} -- cgit v1.2.1