aboutsummaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/Makefile11
-rw-r--r--modules/abs.c64
-rw-r--r--modules/bdiag.c272
-rw-r--r--modules/bfft.c304
-rw-r--r--modules/cheby.c138
-rw-r--r--modules/diag.c218
-rw-r--r--modules/dist.c262
-rw-r--r--modules/dwt.c893
-rw-r--r--modules/dynwav.c318
-rw-r--r--modules/ead.c153
-rw-r--r--modules/eadsr.c171
-rw-r--r--modules/ear.c134
-rw-r--r--modules/ffpoly.c173
-rw-r--r--modules/fwarp.c61
-rw-r--r--modules/lattice.c143
-rw-r--r--modules/matrix.c154
-rw-r--r--modules/permut.c177
-rw-r--r--modules/qmult.c165
-rw-r--r--modules/qnorm.c137
-rw-r--r--modules/ramp.c118
-rw-r--r--modules/ratio.c66
-rw-r--r--modules/statwav.c149
-rw-r--r--modules/tabreadmix.c271
-rw-r--r--modules/xfm.c271
24 files changed, 4823 insertions, 0 deletions
diff --git a/modules/Makefile b/modules/Makefile
new file mode 100644
index 0000000..4e1cabd
--- /dev/null
+++ b/modules/Makefile
@@ -0,0 +1,11 @@
+include ../Makefile.config
+
+current: ead.o ear.o eadsr.o dist.o tabreadmix.o xfm.o qmult.o qnorm.o \
+ cheby.o abs.o ramp.o dwt.o bfft.o dynwav.o statwav.o bdiag.o \
+ diag.o matrix.o permut.o lattice.o ratio.o ffpoly.o fwarp.o
+
+
+clean:
+ rm -f *.o
+ rm -f *~
+
diff --git a/modules/abs.c b/modules/abs.c
new file mode 100644
index 0000000..4d8b8eb
--- /dev/null
+++ b/modules/abs.c
@@ -0,0 +1,64 @@
+/*
+ * abs.c - computes absolute value of a signal
+ * Copyright (c) 2000-2003 by Tom Schouten
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "m_pd.h"
+#include <math.h>
+
+/* ------------------------- abs~ -------------------------- */
+static t_class *abs_class;
+
+typedef struct _abs
+{
+ t_object x_obj;
+} t_abs;
+
+static t_int *abs_perform(t_int *w)
+{
+ t_abs *x = (t_abs *)(w[1]);
+ t_float *in = (t_float *)(w[2]);
+ t_float *out = (t_float *)(w[3]);
+ int n = (int)(w[4]);
+ while (n--)
+ {
+ float f = *in++;
+ if (f < 0) f = -f;
+ *out++ = f;
+ }
+ return (w+5);
+}
+
+static void abs_dsp(t_abs *x, t_signal **sp)
+{
+ dsp_add(abs_perform, 4, x, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
+}
+
+static void *abs_new(void)
+{
+ t_abs *x = (t_abs *)pd_new(abs_class);
+ outlet_new(&x->x_obj, &s_signal);
+ return (x);
+}
+
+void abs_tilde_setup(void)
+{
+ abs_class = class_new(gensym("abs~"), (t_newmethod)abs_new, 0,
+ sizeof(t_abs), 0, A_NULL);
+ class_addmethod(abs_class, (t_method)nullfn, &s_signal, A_NULL);
+ class_addmethod(abs_class, (t_method)abs_dsp, gensym("dsp"), A_NULL);
+}
diff --git a/modules/bdiag.c b/modules/bdiag.c
new file mode 100644
index 0000000..37a0349
--- /dev/null
+++ b/modules/bdiag.c
@@ -0,0 +1,272 @@
+/*
+ * bdiag.c - block diagonal state space system
+ * treats input dsp block as n parallel signals
+ *
+ * s1 = (a * s1) + (b * s2) + u1;
+ * s2 = (a * s2) - (b * s1) + u2;
+ *
+ * Copyright (c) 2000-2003 by Tom Schouten
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#include "m_pd.h"
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define MAXORDER 64
+
+typedef struct bdiagctl
+{
+ t_float *c_state;
+ t_float *c_eigen;
+ t_int c_order;
+} t_bdiagctl;
+
+typedef struct bdiag
+{
+ t_object x_obj;
+ t_float x_f;
+ t_bdiagctl x_ctl;
+} t_bdiag;
+
+
+static float randfloat(void){
+ float r = rand ();
+ r /= (RAND_MAX/2);
+ r -= 1;
+ return r;
+
+}
+
+static void bdiag_random(t_bdiag *x)
+{
+ int i;
+
+ for (i=0; i<x->x_ctl.c_order; i++)
+ {
+ x->x_ctl.c_state[i] = randfloat();
+ }
+
+}
+
+
+static void bdiag_reset(t_bdiag *x)
+{
+ int i;
+
+ for (i=0; i<x->x_ctl.c_order; i++)
+ {
+ x->x_ctl.c_state[i] = 0;
+ }
+
+}
+
+
+
+
+
+
+static void bdiag_eigen(t_bdiag *x, t_floatarg index, t_floatarg aval, t_floatarg bval)
+{
+ int i = (int)index;
+ if (i<0) return;
+ if (i>=x->x_ctl.c_order/2) return;
+ x->x_ctl.c_eigen[2*i+0] = aval;
+ x->x_ctl.c_eigen[2*i+1] = bval;
+
+}
+
+/* set decay time and frequency of pole at index */
+static void bdiag_timefreq(t_bdiag *x, t_floatarg index, t_floatarg time, t_floatarg freq)
+{
+ float r,a,b,n;
+ float sr = sys_getsr() / (float)x->x_ctl.c_order;
+
+ /* time in ms */
+ time *= 0.001;
+
+ if (time < 0.0f) time = 0.0f;
+ r = pow(0.001f, 1.0f / (time * sr));
+ if (r < 0.0f) r = 0.0f;
+ if (r > 1.0f) r = 1.0f;
+
+ a = cos(2*M_PI*freq/sr);
+ b = sin(2*M_PI*freq/sr);
+
+ /* normalize to be sure */
+ n = 1.0f / sqrt(a*a + b*b);
+ a *= n;
+ b *= n;
+
+ bdiag_eigen(x, index, r*a, r*b);
+}
+
+static void bdiag_preset(t_bdiag *x, t_floatarg preset)
+{
+ int p = preset;
+ int i;
+ float a, b, w, r;
+
+ switch(p){
+ case 0:
+ post("preset 0");
+ for (i=0; i<x->x_ctl.c_order/2; i++){
+ w = randfloat() * .001;
+ r = 1. - (((float)i + 1.)/1000.);
+ a = cos(w) * r;
+ b = sin(w) * r;
+ post("%f %f %f %f", w, r, a, b);
+ bdiag_eigen(x,i,a,b);
+ }
+ break;
+ case 1:
+ default:
+ break;
+
+ }
+}
+
+static t_int *bdiag_perform(t_int *w)
+{
+
+
+ t_float *in = (float *)(w[3]);
+ t_float *out = (float *)(w[4]);
+ t_bdiagctl *ctl = (t_bdiagctl *)(w[1]);
+
+ t_float *eigen = ctl->c_eigen;
+ t_float *state = ctl->c_state;
+ t_int n = (t_int)(w[2]);
+
+ t_float u1,u2,a,b,s1,s2,s1new,s2new;
+
+ int i;
+
+ for (i=0; i<n; i+=2)
+ {
+ u1 = *in++;
+ u2 = *in++;
+ a = *eigen++; /* real part */
+ b = *eigen++; /* imag part */
+ s1 = state[0];
+ s2 = state[1];
+
+
+ s1new = (a * s1) - (b * s2) + u1; /* update state */
+ s2new = (a * s2) + (b * s1) + u2;
+
+ *state++ = s1new; /* store state */
+ *state++ = s2new;
+
+ *out++ = s1new; /* output state */
+ *out++ = s2new;
+ }
+
+ return (w+5);
+}
+
+
+static void bdiag_dsp(t_bdiag *x, t_signal **sp)
+{
+
+ int n = sp[0]->s_n;
+ int i;
+
+ if (n == 1)
+ {
+ post("bdiag: doesnt work with blocksize == 1");
+ dsp_add_copy(sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
+ }
+ else
+ {
+ if (x->x_ctl.c_order != n)
+ {
+ if (x->x_ctl.c_state) free(x->x_ctl.c_state);
+ if (x->x_ctl.c_eigen) free(x->x_ctl.c_eigen);
+
+ x->x_ctl.c_state = (t_float *)malloc(n*sizeof(t_float));
+ x->x_ctl.c_eigen = (t_float *)malloc(n*sizeof(t_float));
+
+ for(i=0;i<n;i++)
+ {
+ x->x_ctl.c_state[i] = 0;
+ x->x_ctl.c_eigen[i] = 0;
+ }
+
+ x->x_ctl.c_order = n;
+ }
+
+
+ dsp_add(bdiag_perform, 4, &x->x_ctl, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec);
+ }
+
+}
+
+static void bdiag_free(t_bdiag *x)
+{
+
+ if (x->x_ctl.c_state) free(x->x_ctl.c_state);
+ if (x->x_ctl.c_eigen) free(x->x_ctl.c_eigen);
+
+
+}
+
+t_class *bdiag_class;
+
+
+static void *bdiag_new(t_floatarg permute)
+{
+ t_bdiag *x = (t_bdiag *)pd_new(bdiag_class);
+ int i, n=64;
+
+ outlet_new(&x->x_obj, gensym("signal"));
+
+ x->x_ctl.c_state = (t_float *)malloc(n*sizeof(t_float));
+ x->x_ctl.c_eigen = (t_float *)malloc(n*sizeof(t_float));
+
+ for(i=0;i<n;i++)
+ {
+ x->x_ctl.c_state[i] = 0;
+ x->x_ctl.c_eigen[i] = 0;
+ }
+
+ x->x_ctl.c_order = n;
+
+
+ return (void *)x;
+
+
+}
+
+
+void bdiag_tilde_setup(void)
+{
+ //post("bdiag~ v0.1");
+ bdiag_class = class_new(gensym("bdiag~"), (t_newmethod)bdiag_new,
+ (t_method)bdiag_free, sizeof(t_bdiag), 0, A_DEFFLOAT, 0);
+ CLASS_MAINSIGNALIN(bdiag_class, t_bdiag, x_f);
+ class_addmethod(bdiag_class, (t_method)bdiag_random, gensym("random"), 0);
+ class_addmethod(bdiag_class, (t_method)bdiag_random, gensym("bang"), 0);
+ class_addmethod(bdiag_class, (t_method)bdiag_reset, gensym("reset"), 0);
+ class_addmethod(bdiag_class, (t_method)bdiag_dsp, gensym("dsp"), 0);
+
+ class_addmethod(bdiag_class, (t_method)bdiag_eigen, gensym("eigen"), A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0);
+ class_addmethod(bdiag_class, (t_method)bdiag_timefreq, gensym("timefreq"), A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0);
+ class_addmethod(bdiag_class, (t_method)bdiag_preset, gensym("preset"), A_DEFFLOAT, 0);
+}
+
diff --git a/modules/bfft.c b/modules/bfft.c
new file mode 100644
index 0000000..76b0254
--- /dev/null
+++ b/modules/bfft.c
@@ -0,0 +1,304 @@
+/*
+ * bfft.c - code for fourrier transform
+ * data organization is in (real, imag) pairs
+ * the first 2 components are (DC, NY)
+ * Copyright (c) 2000-2003 by Tom Schouten
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#include "m_pd.h"
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define MAXORDER 64
+
+typedef struct bfftctl
+{
+ t_int c_levels;
+ char c_name[16];
+ t_int *c_clutter;
+ t_int *c_unclutter;
+} t_bfftctl;
+
+typedef struct bfft
+{
+ t_object x_obj;
+ t_float x_f;
+ t_bfftctl x_ctl;
+} t_bfft;
+
+t_class *bfft_class, *ibfft_class, *fht_class;
+
+
+static inline void bfft_perform_permutation(t_float *S, int n, t_int *f)
+{
+ t_int k,l;
+ t_float swap;
+ for(k=0; k<n; k++)
+ {
+ l = f[k];
+ while (l<k) l = f[l];
+ swap = S[k];
+ S[k] = S[l];
+ S[l] = swap;
+ }
+}
+
+static void bfft_permutation(t_bfft *x, t_int n){
+
+ t_bfftctl *ctl = &x->x_ctl;
+ int i;
+
+ if (ctl->c_clutter) free(ctl->c_clutter);
+ if (ctl->c_unclutter) free(ctl->c_unclutter);
+
+ ctl->c_clutter = (t_int *)malloc(n*sizeof(t_int));
+ ctl->c_unclutter = (t_int *)malloc(n*sizeof(t_int));
+
+
+ ctl->c_unclutter[0] = 0;
+ ctl->c_unclutter[1] = n/2;
+ for (i=1; i<n/2; i++){
+ ctl->c_unclutter[2*i] = i;
+ ctl->c_unclutter[2*i+1] = n-i;
+ }
+
+ for(i=0; i<n; i++)
+ ctl->c_clutter[ctl->c_unclutter[i]] = i;
+
+ return;
+
+ /* debug */
+ /* for(k=0; k<n; k++)
+ ** printf("clutter[%d] = %d\n", k, ctl->c_clutter[k]);
+ ** for(k=0; k<n; k++)
+ ** printf("unclutter[%d] = %d\n", k, ctl->c_unclutter[k]);
+ **
+ ** exit(1);
+ */
+}
+
+
+
+static t_int *bfft_perform(t_int *w)
+{
+
+
+ t_float *in = (float *)(w[3]);
+ t_float *out = (float *)(w[4]);
+ t_bfftctl *ctl = (t_bfftctl *)(w[1]);
+ t_int n = (t_int)(w[2]);
+ t_float scale = sqrt(1.0f / (float)(n));
+
+ mayer_fht(out, n);
+ bfft_perform_permutation(out, n, ctl->c_unclutter);
+
+ while (n--) *out++ *= scale;
+
+ return (w+5);
+}
+
+
+
+
+static t_int *ibfft_perform(t_int *w)
+{
+
+
+ t_float *in = (float *)(w[3]);
+ t_float *out = (float *)(w[4]);
+ t_bfftctl *ctl = (t_bfftctl *)(w[1]);
+ t_int n = (t_int)(w[2]);
+ t_float scale = sqrt(1.0f / (float)(n));
+
+
+ bfft_perform_permutation(out, n, ctl->c_clutter);
+ mayer_fht(out, n);
+ while (n--) *out++ *= scale;
+
+
+ return (w+5);
+}
+
+
+static t_int *fht_perform(t_int *w)
+{
+
+
+ t_float *in = (float *)(w[3]);
+ t_float *out = (float *)(w[4]);
+ t_bfftctl *ctl = (t_bfftctl *)(w[1]);
+
+
+ t_int n = (t_int)(w[2]);
+
+ mayer_fht(out, n);
+
+ return (w+5);
+}
+
+
+static void bfft_dsp(t_bfft *x, t_signal **sp)
+{
+
+ int n = sp[0]->s_n;
+ t_float *in = sp[0]->s_vec;
+ t_float *out = sp[1]->s_vec;
+
+ bfft_permutation(x, n);
+
+ if (in != out)
+ {
+ dsp_add_copy(in,out,n);
+ in = out;
+ }
+
+ dsp_add(bfft_perform, 4, &x->x_ctl, n, in, out);
+
+}
+
+static void ibfft_dsp(t_bfft *x, t_signal **sp)
+{
+
+ int n = sp[0]->s_n;
+ t_float *in = sp[0]->s_vec;
+ t_float *out = sp[1]->s_vec;
+
+ bfft_permutation(x, n);
+
+ if (in != out)
+ {
+ dsp_add_copy(in,out,n);
+ in = out;
+ }
+
+ dsp_add(ibfft_perform, 4, &x->x_ctl, n, in, out);
+
+}
+
+static void fht_dsp(t_bfft *x, t_signal **sp)
+{
+
+ int n = sp[0]->s_n;
+ t_float *in = sp[0]->s_vec;
+ t_float *out = sp[1]->s_vec;
+
+
+ if (in != out)
+ {
+ dsp_add_copy(in,out,n);
+ in = out;
+ }
+
+ dsp_add(fht_perform, 4, &x->x_ctl, n, in, out);
+
+}
+
+
+
+static void bfft_free(t_bfft *x)
+{
+
+ if (x->x_ctl.c_clutter) free(x->x_ctl.c_clutter);
+ if (x->x_ctl.c_unclutter) free(x->x_ctl.c_unclutter);
+
+}
+
+
+
+
+static void *bfft_new(void)
+{
+ t_bfft *x = (t_bfft *)pd_new(bfft_class);
+ int i;
+
+ outlet_new(&x->x_obj, gensym("signal"));
+
+
+ sprintf(x->x_ctl.c_name,"bfft");
+
+ x->x_ctl.c_clutter = NULL;
+ x->x_ctl.c_unclutter = NULL;
+
+ return (void *)x;
+
+
+}
+
+static void *ibfft_new(void)
+{
+ t_bfft *x = (t_bfft *)pd_new(ibfft_class);
+ int i;
+
+ outlet_new(&x->x_obj, gensym("signal"));
+
+
+ x->x_ctl.c_clutter = NULL;
+ x->x_ctl.c_unclutter = NULL;
+
+ sprintf(x->x_ctl.c_name,"ibfft");
+
+ return (void *)x;
+}
+
+static void *fht_new(void)
+{
+ t_bfft *x = (t_bfft *)pd_new(fht_class);
+ int i;
+
+ outlet_new(&x->x_obj, gensym("signal"));
+
+
+ x->x_ctl.c_clutter = NULL;
+ x->x_ctl.c_unclutter = NULL;
+
+ sprintf(x->x_ctl.c_name,"fht");
+
+ return (void *)x;
+}
+
+
+
+
+void bfft_tilde_setup(void)
+{
+ //post("bfft~ v0.1");
+ bfft_class = class_new(gensym("bfft~"), (t_newmethod)bfft_new,
+ (t_method)bfft_free, sizeof(t_bfft), 0, 0);
+ CLASS_MAINSIGNALIN(bfft_class, t_bfft, x_f);
+ class_addmethod(bfft_class, (t_method)bfft_dsp, gensym("dsp"), 0);
+
+
+
+ ibfft_class = class_new(gensym("ibfft~"), (t_newmethod)ibfft_new,
+ (t_method)bfft_free, sizeof(t_bfft), 0, 0);
+
+ CLASS_MAINSIGNALIN(ibfft_class, t_bfft, x_f);
+ class_addmethod(ibfft_class, (t_method)ibfft_dsp, gensym("dsp"), 0);
+
+
+
+ fht_class = class_new(gensym("fht~"), (t_newmethod)fht_new,
+ (t_method)bfft_free, sizeof(t_bfft), 0, 0);
+
+ CLASS_MAINSIGNALIN(fht_class, t_bfft, x_f);
+ class_addmethod(fht_class, (t_method)fht_dsp, gensym("dsp"), 0);
+
+
+
+}
diff --git a/modules/cheby.c b/modules/cheby.c
new file mode 100644
index 0000000..2c32d68
--- /dev/null
+++ b/modules/cheby.c
@@ -0,0 +1,138 @@
+/*
+ * cheby.c - chebychev polynomial evaluation
+ * Copyright (c) 2000-2003 by Tom Schouten
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "m_pd.h"
+#include <math.h>
+
+
+#define MAX_ORDER 1024
+#define DEFAULT_ORDER 4
+
+typedef struct chebyctl
+{
+ t_float c_gain[MAX_ORDER];
+ t_int c_order;
+} t_chebyctl;
+
+typedef struct cheby
+{
+ t_object x_obj;
+ t_float x_f;
+ t_chebyctl x_ctl;
+} t_cheby;
+
+static void cheby_bang(t_cheby *x)
+{
+
+}
+
+static void cheby_coef(t_cheby *x, t_floatarg coef, t_floatarg f)
+{
+ int i = (int)coef;
+ if ((i > 0) && (i < x->x_ctl.c_order + 1)){
+ x->x_ctl.c_gain[i-1] = f;
+ /* post("cheby: harmonic %d set to %f", i, f); */
+ }
+}
+
+
+static t_int *cheby_perform(t_int *w)
+{
+
+
+ t_float *in = (float *)(w[3]);
+ t_float *out = (float *)(w[4]);
+ t_chebyctl *ctl = (t_chebyctl *)(w[1]);
+ t_float *gain = ctl->c_gain;
+ t_int i;
+ t_int n = (t_int)(w[2]), k;
+ t_float x,y,t1,t2,t,acc;
+
+
+ for (i = 0; i < n; i++)
+ {
+ x = *in++;
+
+ gain = ctl->c_gain;
+ t2 = 1; /* T_0 */
+ t1 = x; /* T_1 */
+
+ acc = *gain++ * x; /* a_1 T_1 */
+ for (k=2; k<=ctl->c_order; k++){
+ t = 2*x*t1 - t2; /* T_k = 2 x T_{k-1} - T_{k-2} */
+ acc += *gain++ * t; /* a_k T_k */
+ t2 = t1;
+ t1 = t;
+ }
+
+ *out++ = acc;
+
+ }
+
+
+ return (w+5);
+}
+
+static void cheby_dsp(t_cheby *x, t_signal **sp)
+{
+ dsp_add(cheby_perform, 4, &x->x_ctl, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec);
+
+}
+static void cheby_free(void)
+{
+
+}
+
+t_class *cheby_class;
+
+static void *cheby_new(t_floatarg order_f)
+{
+ int i;
+ int order = (int)order_f;
+
+ t_cheby *x = (t_cheby *)pd_new(cheby_class);
+ outlet_new(&x->x_obj, gensym("signal"));
+
+ if (order < 1) order = DEFAULT_ORDER; /* default */
+ if (order > MAX_ORDER) order = MAX_ORDER; /* maximum */
+
+
+ //post("cheby: order = %d", order);
+
+ x->x_ctl.c_order = order;
+ cheby_coef(x, 1, 1);
+ for (i=2; i<order+1; i++){
+ cheby_coef(x, 0, i);
+ }
+
+ return (void *)x;
+}
+
+void cheby_tilde_setup(void)
+{
+ //post("cheby~ v0.1");
+ cheby_class = class_new(gensym("cheby~"), (t_newmethod)cheby_new,
+ (t_method)cheby_free, sizeof(t_cheby), 0, A_DEFFLOAT, 0);
+ CLASS_MAINSIGNALIN(cheby_class, t_cheby, x_f);
+ class_addmethod(cheby_class, (t_method)cheby_bang, gensym("bang"), 0);
+ class_addmethod(cheby_class, (t_method)cheby_dsp, gensym("dsp"), 0);
+ class_addmethod(cheby_class, (t_method)cheby_coef, gensym("coef"), A_DEFFLOAT, A_DEFFLOAT, 0);
+
+}
+
diff --git a/modules/diag.c b/modules/diag.c
new file mode 100644
index 0000000..5f7fe36
--- /dev/null
+++ b/modules/diag.c
@@ -0,0 +1,218 @@
+/*
+ * diag.c - diagonal state space system.
+ * treats input dsp block as n parallel signals
+ *
+ * s1 = (a * s1) + (b * s2) + u1;
+ * s2 = (a * s2) - (b * s1) + u2;
+ *
+ * Copyright (c) 2000-2003 by Tom Schouten
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "m_pd.h"
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define MAXORDER 64
+
+typedef struct diagctl
+{
+ t_float *c_state;
+ t_float *c_eigen;
+ t_int c_order;
+} t_diagctl;
+
+typedef struct diag
+{
+ t_object x_obj;
+ t_float x_f;
+ t_diagctl x_ctl;
+} t_diag;
+
+
+static float randfloat(void){
+ float r = rand ();
+ r /= (RAND_MAX/2);
+ r -= 1;
+ return r;
+
+}
+
+static void diag_eigen(t_diag *x, t_floatarg index, t_floatarg val)
+{
+ int i = (int)index;
+ if (i<0) return;
+ if (i>=x->x_ctl.c_order) return;
+ x->x_ctl.c_eigen[i] = val;
+}
+
+/* set decay time of pole at index */
+static void diag_time(t_diag *x, t_floatarg index, t_floatarg time)
+{
+ float r;
+
+ /* time in ms */
+ time *= 0.001;
+
+ if (time < 0.0f) time = 0.0f;
+ r = pow(0.001f, (float)x->x_ctl.c_order / (time * sys_getsr()));
+ if (r < 0.0f) r = 0.0f;
+ if (r > 1.0f) r = 1.0f;
+
+ diag_eigen(x, index, r);
+}
+
+
+
+static void diag_reset(t_diag *x)
+{
+ int i;
+
+ for (i=0; i<x->x_ctl.c_order; i++)
+ {
+ x->x_ctl.c_state[i] = 0;
+ }
+
+}
+
+static void diag_random(t_diag *x)
+{
+ int i;
+
+ for (i=0; i<x->x_ctl.c_order; i++)
+ {
+ x->x_ctl.c_state[i] = randfloat();
+ }
+
+}
+
+
+
+static t_int *diag_perform(t_int *w)
+{
+
+
+ t_float *in = (float *)(w[3]);
+ t_float *out = (float *)(w[4]);
+ t_diagctl *ctl = (t_diagctl *)(w[1]);
+
+ t_float *eigen = ctl->c_eigen;
+ t_float *state = ctl->c_state;
+ t_int n = (t_int)(w[2]);
+
+ t_float x;
+
+ int i;
+
+ for (i=0; i<n; i++)
+ {
+ x = *in;
+ *state += x;
+ *state *= *eigen;
+ *out = *state;
+
+ in++;
+ out++;
+ state++;
+ eigen++;
+ }
+
+
+
+ return (w+5);
+}
+
+
+static void diag_dsp(t_diag *x, t_signal **sp)
+{
+
+ int n = sp[0]->s_n;
+ int i;
+
+ if (x->x_ctl.c_order != n)
+ {
+ if (x->x_ctl.c_state) free(x->x_ctl.c_state);
+ if (x->x_ctl.c_eigen) free(x->x_ctl.c_eigen);
+
+ x->x_ctl.c_state = (t_float *)malloc(n*sizeof(t_float));
+ x->x_ctl.c_eigen = (t_float *)malloc(n*sizeof(t_float));
+
+ for(i=0;i<n;i++)
+ {
+ x->x_ctl.c_state[i] = 0;
+ x->x_ctl.c_eigen[i] = 0;
+ }
+
+ x->x_ctl.c_order = n;
+ }
+
+
+
+ dsp_add(diag_perform, 4, &x->x_ctl, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec);
+
+}
+
+static void diag_free(t_diag *x)
+{
+
+ if (x->x_ctl.c_state) free(x->x_ctl.c_state);
+ if (x->x_ctl.c_eigen) free(x->x_ctl.c_eigen);
+
+
+}
+
+t_class *diag_class;
+
+
+static void *diag_new(t_floatarg permute)
+{
+ t_diag *x = (t_diag *)pd_new(diag_class);
+ int i, n=64;
+
+ outlet_new(&x->x_obj, gensym("signal"));
+
+ x->x_ctl.c_state = (t_float *)malloc(n*sizeof(t_float));
+ x->x_ctl.c_eigen = (t_float *)malloc(n*sizeof(t_float));
+
+ for(i=0;i<n;i++)
+ {
+ x->x_ctl.c_state[i] = 0;
+ x->x_ctl.c_eigen[i] = 0;
+ }
+
+ x->x_ctl.c_order = n;
+
+
+ return (void *)x;
+}
+
+
+void diag_tilde_setup(void)
+{
+ //post("diag~ v0.1");
+ diag_class = class_new(gensym("diag~"), (t_newmethod)diag_new,
+ (t_method)diag_free, sizeof(t_diag), 0, A_DEFFLOAT, 0);
+ CLASS_MAINSIGNALIN(diag_class, t_diag, x_f);
+ class_addmethod(diag_class, (t_method)diag_dsp, gensym("dsp"), 0);
+ class_addmethod(diag_class, (t_method)diag_reset, gensym("reset"), 0);
+ class_addmethod(diag_class, (t_method)diag_random, gensym("random"), 0);
+ class_addmethod(diag_class, (t_method)diag_random, gensym("bang"), 0);
+ class_addmethod(diag_class, (t_method)diag_eigen, gensym("eigen"), A_DEFFLOAT, A_DEFFLOAT, 0);
+ class_addmethod(diag_class, (t_method)diag_time, gensym("time"), A_DEFFLOAT, A_DEFFLOAT, 0);
+
+}
+
diff --git a/modules/dist.c b/modules/dist.c
new file mode 100644
index 0000000..578e2ef
--- /dev/null
+++ b/modules/dist.c
@@ -0,0 +1,262 @@
+/*
+ * dist.c - wave shaping extern
+ * Copyright (c) 2000-2003 by Tom Schouten
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "extlib_util.h"
+
+
+#define CLIP 0
+#define INVERSE 1
+#define INVERSESQ 2
+#define INVERSECUB 3
+#define RAT1 4
+#define RAT2 5
+#define FULLRECT 6
+#define HALFRECT 7
+#define PULSE 8
+#define NEWTON1 9
+#define UPPERCLIP 10
+
+
+
+
+typedef struct distctl
+{
+ t_float c_gain;
+ t_float c_delay;
+ char c_type;
+} t_distctl;
+
+typedef struct dist
+{
+ t_object x_obj;
+ t_float x_f;
+ t_distctl x_ctl;
+} t_dist;
+
+void dist_bang(t_dist *x)
+{
+
+}
+
+void dist_gain(t_dist *x, t_floatarg f)
+{
+ x->x_ctl.c_gain = f;
+
+}
+
+
+static t_int *dist_perform(t_int *w)
+{
+
+
+ t_float *in = (float *)(w[3]);
+ t_float *out = (float *)(w[4]);
+ t_distctl *ctl = (t_distctl *)(w[1]);
+ t_float gain = ctl->c_gain;
+ t_int i;
+ t_int n = (t_int)(w[2]);
+ t_float x,y,v;
+ t_float z = ctl->c_delay;
+
+ switch(ctl->c_type){
+ case CLIP:
+ for (i = 0; i < n; i++)
+ {
+ x = *in++ * gain;
+ x = (x > 1) ? ( 1.) : x;
+ x = (x < -1) ? (-1.) : x;
+ *out++ = 0.9999 * x;
+
+ }
+ break;
+
+ case INVERSE:
+ for (i = 0; i < n; i++)
+ {
+ x = *in++ * gain;
+ x = (x > 1) ? (2. - 1/x) : x;
+ x = (x < -1) ? (-2. - 1/x) : x;
+ *out++ = x/2.0001;
+
+ }
+ break;
+
+ case INVERSESQ:
+ for (i = 0; i < n; i++)
+ {
+ x = *in++ * gain;
+ x = (x > 1) ? (2. - 1/x) : x;
+ x = (x < -1) ? (-2. - 1/x) : x;
+ x /= 2;
+ *out++ = 1.999*x*x-1;
+
+ }
+ break;
+
+ case INVERSECUB:
+ for (i = 0; i < n; i++)
+ {
+ x = *in++ * gain;
+ x = (x > 1) ? (2. - 1/x) : x;
+ x = (x < -1) ? (-2. - 1/x) : x;
+ x /= 2;
+ *out++ = .9999 * x*x*x;
+
+ }
+ break;
+
+ case RAT1: /*(2*d./((1+(d).^2)))*/
+ for (i = 0; i < n; i++)
+ {
+ x = *in++ * gain;
+ y = (1. + x*x);
+ x = 1.9999*x/y;
+ *out++ = x;
+ }
+ break;
+
+ case RAT2: /*(2*d./((1+(d).^16)))*/
+ for (i = 0; i < n; i++)
+ {
+ x = *in++ * gain;
+ y = x*x;
+ y *= y;
+ y *= y;
+ y *= y;
+ y = (1. + y);
+ x = 1.2*x/y;
+ *out++ = x;
+ }
+ break;
+
+ case FULLRECT:
+ for (i = 0; i < n; i++)
+ {
+ x = *in++ * gain;
+ x = (x>0) ? x : -x;
+ x = (x>1) ? 1 : x;
+ *out++ = 1.9999*(x-.5);
+ }
+ break;
+
+ case HALFRECT:
+ for (i = 0; i < n; i++)
+ {
+ x = *in++ * gain;
+ x = (x>0) ? x : 0;
+ x = (x>1) ? 1 : x;
+ *out++ = 1.9999*(x-.5);
+ }
+ break;
+
+ case PULSE:
+ for (i = 0; i < n; i++)
+ {
+ x = *in++ * gain;
+ y = (x>0) ? (1):(-1);
+ x = (z*y > 0) ? (0) : (y);
+ *out++ = .9999 * x;
+ z = x;
+
+ }
+ ctl->c_delay = z;
+ break;
+
+ case NEWTON1:
+ for (i = 0; i < n; i++)
+ {
+ x = *in++ * gain;
+ y = 1./(1.+x*x);
+
+ z = .5;
+ z = .5*(y/z + z);
+ z = .5*(y/z + z);
+ z = .5*(y/z + z);
+
+ /* z = .5*(y/z + z);
+ * z = .5*(y/z + z);
+ * z = .5*(y/z + z);
+ */
+
+ *out++ = x * z;
+
+ }
+ ctl->c_delay = z;
+ break;
+
+ case UPPERCLIP:
+ for (i = 0; i < n; i++)
+ {
+ x = *in++ * gain;
+
+ x = (x < 0.0f) ? 0.0f : x;
+ x = (x > 0.9999f) ? 0.9999f : x;
+
+ *out++ = x;
+
+ }
+ break;
+
+ default:
+
+ for (i = 0; i < n; i++) *out++ = *in++;
+ break;
+
+ }
+
+ return (w+5);
+}
+
+static void dist_dsp(t_dist *x, t_signal **sp)
+{
+ dsp_add(dist_perform, 4, &x->x_ctl, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec);
+
+}
+void dist_free(void)
+{
+
+}
+
+t_class *dist_class;
+
+void *dist_new(t_floatarg type)
+{
+ t_dist *x = (t_dist *)pd_new(dist_class);
+ inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("gain"));
+ outlet_new(&x->x_obj, gensym("signal"));
+
+ dist_gain(x, 1);
+ x->x_ctl.c_type = (char)type;
+ x->x_ctl.c_delay = 0;
+
+ return (void *)x;
+}
+
+void dist_tilde_setup(void)
+{
+ //post("dist~ v0.1");
+ dist_class = class_new(gensym("dist~"), (t_newmethod)dist_new,
+ (t_method)dist_free, sizeof(t_dist), 0, A_DEFFLOAT, 0);
+ CLASS_MAINSIGNALIN(dist_class, t_dist, x_f);
+ class_addmethod(dist_class, (t_method)dist_bang, gensym("bang"), 0);
+ class_addmethod(dist_class, (t_method)dist_dsp, gensym("dsp"), 0);
+ class_addmethod(dist_class, (t_method)dist_gain, gensym("gain"), A_FLOAT, 0);
+
+}
+
diff --git a/modules/dwt.c b/modules/dwt.c
new file mode 100644
index 0000000..caa75ff
--- /dev/null
+++ b/modules/dwt.c
@@ -0,0 +1,893 @@
+/*
+ * dwt.c - code for discrete wavelet transform
+ * (symmetric interpolating biorthogonal wavelets using the lifting transform)
+ * Copyright (c) 2000-2003 by Tom Schouten
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#include "m_pd.h"
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define MAXORDER 64
+
+typedef enum{DWT,IDWT,DWT16,IDWT16} t_dwttype;
+
+typedef struct dwtctl
+{
+ t_float c_update[MAXORDER];
+ t_float c_predict[MAXORDER];
+ t_int c_nupdate;
+ t_int c_npredict;
+ t_int c_levels;
+ t_int c_fakein;
+ t_float c_fakeval;
+ t_int c_mask;
+ char c_name[16];
+ t_int *c_clutter;
+ t_int *c_unclutter;
+ t_int c_permute;
+ t_dwttype c_type;
+} t_dwtctl;
+
+typedef struct dwt
+{
+ t_object x_obj;
+ t_float x_f;
+ t_dwtctl x_ctl;
+} t_dwt;
+
+
+static void dwt_even(t_dwt *x, t_floatarg f)
+{
+ int k = (int)f;
+ int i, j;
+ float *p = x->x_ctl.c_predict;
+ float *u = x->x_ctl.c_update;
+ float l, xi, xj;
+
+ if ((k>0) && (k<MAXORDER/2))
+ {
+ for (i=0; i<k; i++){
+ l = 1;
+ xi = 1+2*i;
+ for (j=0; j<k; j++)
+ {
+ xj = 1+2*j;
+ if (i != j) l /= (1 - ((xi*xi) / (xj*xj)));
+ }
+ l *= .5;
+
+ p[k-i-1] = l;
+ p[k+i] = l;
+ u[k-i-1] = l/2;
+ u[k+i] = l/2;
+ }
+
+ x->x_ctl.c_npredict = 2*k;
+ x->x_ctl.c_nupdate = 2*k;
+ }
+}
+
+static void dwt_wavelet(t_dwt *x, t_floatarg f)
+{
+ int k = (int)f;
+ t_float *p = x->x_ctl.c_predict;
+ t_float *u = x->x_ctl.c_update;
+ t_int *np = &x->x_ctl.c_npredict;
+ t_int *nu = &x->x_ctl.c_nupdate;
+
+ switch(k)
+ {
+ default:
+ case 1: /* haar */
+ *np = *nu = 2; /* actual order is one */
+ p[0] = 1;
+ p[1] = 0;
+ u[0] = 0;
+ u[1] = .5;
+ break;
+
+ case 2: /* hat */
+ case 3:
+ *np = *nu = 2;
+ p[0] = .5;
+ p[1] = .5;
+ u[0] = .25;
+ u[1] = .25;
+ break;
+
+ case 4: /* N = 4, N~ = 4 */
+ case 5:
+ *np = *nu = 4;
+ p[0] = -0.0625;
+ p[1] = 0.5625;
+ p[2] = 0.5625;
+ p[3] = -0.0625;
+ u[0] = -0.03125;
+ u[1] = 0.28125;
+ u[2] = 0.28125;
+ u[3] = -0.03125;
+ break;
+
+ case 6:
+ case 7:
+ *np = *nu = 6;
+ p[0] = 0.01171875000000;
+ p[1] = -0.09765625000000;
+ p[2] = 0.58593750000000;
+ p[3] = 0.58593750000000;
+ p[4] = -0.09765625000000;
+ p[5] = 0.01171875000000;
+ u[0] = 0.00585937500000;
+ u[1] = -0.04882812500000;
+ u[2] = 0.29296875000000;
+ u[3] = 0.29296875000000;
+ u[4] = -0.04882812500000;
+ u[5] = 0.00585937500000;
+ break;
+ }
+}
+
+static inline void dwt_perform_permutation(t_float *S, int n, t_int *f)
+{
+ t_int k,l;
+ t_float swap;
+ for(k=0; k<n; k++)
+ {
+ l = f[k];
+ while (l<k) l = f[l];
+ swap = S[k];
+ S[k] = S[l];
+ S[l] = swap;
+ }
+}
+
+static void dwt_permutation(t_dwt *x, t_int n){
+
+ t_dwtctl *ctl = &x->x_ctl;
+ t_int k, L=0, l, start, power;
+ t_int nsave = n;
+
+ while(nsave>>=1) L++;
+
+ if (ctl->c_clutter) free(ctl->c_clutter);
+ if (ctl->c_unclutter) free(ctl->c_unclutter);
+
+ ctl->c_clutter = (t_int *)malloc(n*sizeof(t_int));
+ ctl->c_unclutter = (t_int *)malloc(n*sizeof(t_int));
+
+
+ for(l = L, start = n/2, power=1; l>0; l--, start /=2, power *=2)
+ {
+ for(k=0; k<start; k++)
+ {
+ ctl->c_unclutter[start+k] = (1 + 2*k) * power;
+ }
+ }
+ ctl->c_unclutter[0] = 0;
+
+ for(k=0; k<n; k++)
+ ctl->c_clutter[ctl->c_unclutter[k]] = k;
+
+ return;
+
+ /* debug */
+ for(k=0; k<n; k++)
+ printf("clutter[%d] = %d\n", k, ctl->c_clutter[k]);
+ for(k=0; k<n; k++)
+ printf("unclutter[%d] = %d\n", k, ctl->c_unclutter[k]);
+
+ exit(1);
+}
+
+
+
+static void idwt_coef(t_dwt *x, t_floatarg index, t_floatarg value)
+{
+ x->x_ctl.c_fakein = (int)index;
+ x->x_ctl.c_fakeval = value;
+
+}
+
+static void dwt_print(t_dwt *x)
+{
+ int i;
+
+ printf("%s: predict: [ ", x->x_ctl.c_name);
+ for (i=0; i<x->x_ctl.c_npredict; i++) printf("%f ", x->x_ctl.c_predict[i]);
+ printf("], ");
+
+ printf("update: [ ");
+ for (i=0; i<x->x_ctl.c_nupdate; i++) printf("%f ", x->x_ctl.c_update[i]);
+ printf("]\n");
+
+
+
+}
+
+
+static void dwt_filter(t_dwt *x, t_symbol *s, int argc, t_atom *argv)
+{
+ int invalid_argument = 0;
+ int i;
+
+ char *name = x->x_ctl.c_name;
+
+ float *pfilter = x->x_ctl.c_predict;
+ float *ufilter = x->x_ctl.c_update;
+ float *mask = NULL;
+
+ int *length = NULL;
+ float sum = 0;
+
+ if (s == gensym("predict"))
+ {
+ mask = pfilter;
+ length = &(x->x_ctl.c_npredict);
+ }
+ else if (s == gensym("update"))
+ {
+ mask = ufilter;
+ length = &(x->x_ctl.c_nupdate);
+ }
+ else if (s == gensym("mask"))
+ {
+ mask = NULL;
+ }
+ else
+ {
+ return;
+ }
+
+ if (argc >= MAXORDER) post("%s: error, maximum order exceeded.",name);
+ else if ((x->x_ctl.c_type == DWT16 || x->x_ctl.c_type == IDWT16 ) && (argc != 16))
+ post("%s: error, need to have 16 coefficients.",name);
+ else if (argc == 0) post("%s: no arguments given.",name);
+ else if (argc & 1) post("%s: error, only an even number of coefficients is allowed.", name);
+ else
+ {
+ for (i=0; i<argc; i++){
+ if (argv[i].a_type != A_FLOAT )
+ {
+ invalid_argument = 1;
+ break;
+ }
+ }
+
+ if (invalid_argument) post("%s: invalid argument, must be a number.", name);
+ else
+ {
+ if (mask) /* one of update / predict */
+ {
+ for (i=0; i<argc; i++) mask[i] = argv[i].a_w.w_float;
+ *length = argc;
+ }
+ else /* both + normalization */
+ {
+ for (i=0; i<argc; i++) sum += argv[i].a_w.w_float;
+ for (i=0; i<argc; i++)
+ {
+ pfilter[i] = argv[i].a_w.w_float / sum;
+ ufilter[i] = argv[i].a_w.w_float / (sum*2);
+ }
+ x->x_ctl.c_npredict = argc;
+ x->x_ctl.c_nupdate = argc;
+ }
+ }
+
+ }
+
+}
+
+
+
+static inline void dwtloop(float *vector,
+ int source,
+ int dest,
+ int increment,
+ int backup,
+ int numcoef,
+ int mask,
+ float *filter,
+ int filtlength,
+ float sign)
+{
+
+ int k,m;
+ float acc;
+
+ for (k = 0; k < numcoef; k++)
+ {
+ acc = 0;
+ for (m = 0; m < filtlength; m++)
+ {
+
+ acc += filter[m] * vector[source];
+ source += increment;
+ source &= mask;
+ }
+ vector[dest] += sign * acc;
+ dest += increment;
+ source -= backup;
+ source &= mask;
+ }
+
+}
+
+static inline void dwtloop16(float *vector,
+ int source,
+ int dest,
+ int increment,
+ int backup,
+ int numcoef,
+ int mask,
+ float *filter,
+ int filtlength, /* ignored, set to 16 */
+ float sign)
+{
+
+ int k,m;
+ float acc;
+
+ for (k = 0; k < numcoef; k++)
+ {
+ acc = 0;
+
+ acc += filter[0] * vector[source];
+ source += increment;
+ source &= mask;
+
+ acc += filter[1] * vector[source];
+ source += increment;
+ source &= mask;
+
+ acc += filter[2] * vector[source];
+ source += increment;
+ source &= mask;
+
+ acc += filter[3] * vector[source];
+ source += increment;
+ source &= mask;
+
+ acc += filter[4] * vector[source];
+ source += increment;
+ source &= mask;
+
+ acc += filter[5] * vector[source];
+ source += increment;
+ source &= mask;
+
+ acc += filter[6] * vector[source];
+ source += increment;
+ source &= mask;
+
+ acc += filter[7] * vector[source];
+ source += increment;
+ source &= mask;
+
+ acc += filter[8] * vector[source];
+ source += increment;
+ source &= mask;
+
+ acc += filter[9] * vector[source];
+ source += increment;
+ source &= mask;
+
+ acc += filter[10] * vector[source];
+ source += increment;
+ source &= mask;
+
+ acc += filter[11] * vector[source];
+ source += increment;
+ source &= mask;
+
+ acc += filter[12] * vector[source];
+ source += increment;
+ source &= mask;
+
+ acc += filter[13] * vector[source];
+ source += increment;
+ source &= mask;
+
+ acc += filter[14] * vector[source];
+ source += increment;
+ source &= mask;
+
+ acc += filter[15] * vector[source];
+ source += increment;
+ source &= mask;
+
+ vector[dest] += sign * acc;
+ dest += increment;
+ source -= backup;
+ source &= mask;
+ }
+
+}
+
+
+
+
+
+static t_int *dwt_perform(t_int *w)
+{
+
+
+ t_float *in = (float *)(w[3]);
+ t_float *out = (float *)(w[4]);
+ t_dwtctl *ctl = (t_dwtctl *)(w[1]);
+
+
+ t_int n = (t_int)(w[2]);
+
+ int i;
+
+ int numcoef = n/2;
+ /* int source_u = ((1 - ctl->c_nupdate)/2 - 1);
+ * int source_p = ((1 - ctl->c_npredict)/2);
+ */
+ int source_u = ((2 - ctl->c_nupdate) - 1);
+ int source_p = ((2 - ctl->c_npredict));
+ int increment = 2;
+ int dest = 1;
+ int backup_u = (ctl->c_nupdate-1)*2;
+ int backup_p = (ctl->c_npredict-1)*2;
+
+ /* copy input to output */
+ if (in != out)
+ for (i=0; i<n; i++) out[i]=in[i];
+
+
+ /* fake input */
+ /* for (i=0; i<n; i++) out[i]=0; out[n/8]=1;*/
+
+
+
+ /* backward transform */
+
+
+ /* iterate over all levels */
+ for (i=0; i < ctl->c_levels; i++){
+
+
+ /* foreward predict */
+ dwtloop(out, (source_p & (n-1)), dest, increment, backup_p, numcoef, n-1, ctl->c_predict, ctl->c_npredict, -1);
+
+
+ /* foreward update */
+ dwtloop(out, (source_u & (n-1)), 0, increment, backup_u, numcoef, n-1, ctl->c_update, ctl->c_nupdate, +1);
+
+
+ /* update control parameters */
+ numcoef /= 2;
+ source_p *= 2;
+ source_u *= 2;
+ backup_p *= 2;
+ backup_u *= 2;
+ increment *= 2;
+ dest *= 2;
+ }
+
+ if (ctl->c_permute)
+ dwt_perform_permutation(out, n, ctl->c_unclutter);
+
+
+ return (w+5);
+}
+
+
+
+
+static t_int *idwt_perform(t_int *w)
+{
+
+
+ t_float *in = (float *)(w[3]);
+ t_float *out = (float *)(w[4]);
+ t_dwtctl *ctl = (t_dwtctl *)(w[1]);
+
+
+ t_int n = (t_int)(w[2]);
+
+ int i;
+
+ int numcoef = 1;
+ int source_u = ((2 - ctl->c_nupdate) - 1) * (n/2);
+ int source_p = ((2 - ctl->c_npredict)) * (n/2);
+ int increment = n;
+ int dest = n/2;
+ int backup_u = (ctl->c_nupdate-1)*n;
+ int backup_p = (ctl->c_npredict-1)*n;
+ int fake_in = ctl->c_fakein;
+ float fake_val = ctl->c_fakeval;
+
+ /* copy input to output */
+ if (in != out)
+ for (i=0; i<n; i++) out[i]=in[i];
+
+
+ /* fake input */
+
+ if ((fake_in >= 0) && (fake_in<n)){
+ for (i=0; i<n; i++) out[i]=0;
+ out[fake_in]=fake_val;
+ }
+
+
+ if (ctl->c_permute)
+ dwt_perform_permutation(out, n, ctl->c_clutter);
+
+
+ /* backward transform */
+
+
+ /* iterate over all levels */
+ for (i=0; i < ctl->c_levels; i++){
+
+ /* backward update */
+ dwtloop(out, (source_u & (n-1)), 0, increment, backup_u, numcoef, n-1, ctl->c_update, ctl->c_nupdate, -1);
+
+
+ /* backward predict */
+ dwtloop(out, (source_p & (n-1)), dest, increment, backup_p, numcoef, n-1, ctl->c_predict, ctl->c_npredict, +1);
+
+ /* update control parameters */
+ numcoef *= 2;
+ source_p /= 2;
+ source_u /= 2;
+ backup_p /= 2;
+ backup_u /= 2;
+ increment /= 2;
+ dest /= 2;
+ }
+
+
+
+ return (w+5);
+}
+
+static t_int *dwt16_perform(t_int *w)
+{
+
+
+ t_float *in = (float *)(w[3]);
+ t_float *out = (float *)(w[4]);
+ t_dwtctl *ctl = (t_dwtctl *)(w[1]);
+
+
+ t_int n = (t_int)(w[2]);
+
+ int i;
+
+ int numcoef = n/2;
+ /* int source_u = ((1 - ctl->c_nupdate)/2 - 1);
+ * int source_p = ((1 - ctl->c_npredict)/2);
+ */
+ int source_u = ((2 - ctl->c_nupdate) - 1);
+ int source_p = ((2 - ctl->c_npredict));
+ int increment = 2;
+ int dest = 1;
+ int backup_u = (ctl->c_nupdate-1)*2;
+ int backup_p = (ctl->c_npredict-1)*2;
+
+ /* copy input to output */
+ if (in != out)
+ for (i=0; i<n; i++) out[i]=in[i];
+
+
+ /* fake input */
+ /* for (i=0; i<n; i++) out[i]=0; out[n/8]=1;*/
+
+
+
+ /* backward transform */
+
+
+ /* iterate over all levels */
+ for (i=0; i < ctl->c_levels; i++){
+
+
+ /* foreward predict */
+ dwtloop16(out, (source_p & (n-1)), dest, increment, backup_p, numcoef, n-1, ctl->c_predict, 16, -1);
+
+
+ /* foreward update */
+ dwtloop16(out, (source_u & (n-1)), 0, increment, backup_u, numcoef, n-1, ctl->c_update, 16, +1);
+
+
+ /* update control parameters */
+ numcoef /= 2;
+ source_p *= 2;
+ source_u *= 2;
+ backup_p *= 2;
+ backup_u *= 2;
+ increment *= 2;
+ dest *= 2;
+ }
+
+ if (ctl->c_permute)
+ dwt_perform_permutation(out, n, ctl->c_unclutter);
+
+
+ return (w+5);
+}
+
+
+
+
+static t_int *idwt16_perform(t_int *w)
+{
+
+
+ t_float *in = (float *)(w[3]);
+ t_float *out = (float *)(w[4]);
+ t_dwtctl *ctl = (t_dwtctl *)(w[1]);
+
+
+ t_int n = (t_int)(w[2]);
+
+ int i;
+
+ int numcoef = 1;
+ int source_u = ((2 - ctl->c_nupdate) - 1) * (n/2);
+ int source_p = ((2 - ctl->c_npredict)) * (n/2);
+ int increment = n;
+ int dest = n/2;
+ int backup_u = (ctl->c_nupdate-1)*n;
+ int backup_p = (ctl->c_npredict-1)*n;
+ int fake_in = ctl->c_fakein;
+ float fake_val = ctl->c_fakeval;
+
+ /* copy input to output */
+ if (in != out)
+ for (i=0; i<n; i++) out[i]=in[i];
+
+
+ /* fake input */
+
+ if ((fake_in >= 0) && (fake_in<n)){
+ for (i=0; i<n; i++) out[i]=0;
+ out[fake_in]=fake_val;
+ }
+
+
+ if (ctl->c_permute)
+ dwt_perform_permutation(out, n, ctl->c_clutter);
+
+
+ /* backward transform */
+
+
+ /* iterate over all levels */
+ for (i=0; i < ctl->c_levels; i++){
+
+ /* backward update */
+ dwtloop16(out, (source_u & (n-1)), 0, increment, backup_u, numcoef, n-1, ctl->c_update, 16, -1);
+
+
+ /* backward predict */
+ dwtloop16(out, (source_p & (n-1)), dest, increment, backup_p, numcoef, n-1, ctl->c_predict, 16, +1);
+
+ /* update control parameters */
+ numcoef *= 2;
+ source_p /= 2;
+ source_u /= 2;
+ backup_p /= 2;
+ backup_u /= 2;
+ increment /= 2;
+ dest /= 2;
+ }
+
+
+
+ return (w+5);
+}
+
+
+
+static void dwt_dsp(t_dwt *x, t_signal **sp)
+{
+
+ int n = sp[0]->s_n;
+ int ln = 0;
+
+ dwt_permutation(x, n);
+
+ x->x_ctl.c_mask = n-1;
+ while (n >>= 1) ln++;
+ x->x_ctl.c_levels = ln;
+
+ switch(x->x_ctl.c_type){
+ case DWT:
+ dsp_add(dwt_perform, 4, &x->x_ctl, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec);
+ break;
+ case IDWT:
+ dsp_add(idwt_perform, 4, &x->x_ctl, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec);
+ break;
+ case DWT16:
+ dsp_add(dwt16_perform, 4, &x->x_ctl, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec);
+ break;
+ case IDWT16:
+ dsp_add(idwt16_perform, 4, &x->x_ctl, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec);
+ break;
+
+
+ }
+}
+
+
+void dwt_free(t_dwt *x)
+{
+
+ if (x->x_ctl.c_clutter) free(x->x_ctl.c_clutter);
+ if (x->x_ctl.c_unclutter) free(x->x_ctl.c_unclutter);
+
+
+}
+
+t_class *dwt_class, *idwt_class, *dwt16_class, *idwt16_class;
+
+
+static void dwt_reset(t_dwt *x)
+{
+ bzero(x->x_ctl.c_update, 16*sizeof(t_float));
+ bzero(x->x_ctl.c_predict, 16*sizeof(t_float));
+
+ x->x_ctl.c_update[7] = .25;
+ x->x_ctl.c_update[8] = .25;
+ x->x_ctl.c_nupdate = 16;
+
+ x->x_ctl.c_predict[7] = .5;
+ x->x_ctl.c_predict[8] = .5;
+ x->x_ctl.c_npredict = 16;
+
+ x->x_ctl.c_fakein = -1;
+ x->x_ctl.c_fakeval = 0;
+
+}
+
+
+static void *dwt_new_common(t_floatarg permute)
+{
+ t_dwt *x = (t_dwt *)pd_new(dwt_class);
+ int i;
+
+ outlet_new(&x->x_obj, gensym("signal"));
+
+ /* init data */
+ dwt_reset(x);
+
+ x->x_ctl.c_clutter = NULL;
+ x->x_ctl.c_unclutter = NULL;
+ x->x_ctl.c_permute = (t_int) permute;
+
+ return (void *)x;
+
+
+}
+
+static void *dwt_new(t_floatarg permute)
+{
+ t_dwt *x = dwt_new_common(permute);
+ sprintf(x->x_ctl.c_name,"dwt");
+ x->x_ctl.c_type = DWT;
+ return (void *)x;
+}
+
+
+static void *idwt_new(t_floatarg permute)
+{
+ t_dwt *x = dwt_new_common(permute);
+ sprintf(x->x_ctl.c_name,"idwt");
+ x->x_ctl.c_type = IDWT;
+ return (void *)x;
+}
+
+static void *dwt16_new(t_floatarg permute)
+{
+ t_dwt *x = dwt_new_common(permute);
+ sprintf(x->x_ctl.c_name,"dwt16");
+ x->x_ctl.c_type = DWT16;
+ return (void *)x;
+}
+
+
+static void *idwt16_new(t_floatarg permute)
+{
+ t_dwt *x = dwt_new_common(permute);
+ sprintf(x->x_ctl.c_name,"idwt16");
+ x->x_ctl.c_type = IDWT16;
+ return (void *)x;
+}
+
+
+void dwt_tilde_setup(void)
+{
+ //post("dwt~ v0.1");
+
+
+ dwt_class = class_new(gensym("dwt~"), (t_newmethod)dwt_new,
+ (t_method)dwt_free, sizeof(t_dwt), 0, A_DEFFLOAT, 0);
+ CLASS_MAINSIGNALIN(dwt_class, t_dwt, x_f);
+ class_addmethod(dwt_class, (t_method)dwt_print, gensym("print"), 0);
+ class_addmethod(dwt_class, (t_method)dwt_reset, gensym("reset"), 0);
+ class_addmethod(dwt_class, (t_method)dwt_dsp, gensym("dsp"), 0);
+
+ class_addmethod(dwt_class, (t_method)dwt_filter, gensym("predict"), A_GIMME, 0);
+ class_addmethod(dwt_class, (t_method)dwt_filter, gensym("update"), A_GIMME, 0);
+ class_addmethod(dwt_class, (t_method)dwt_filter, gensym("mask"), A_GIMME, 0);
+
+ class_addmethod(dwt_class, (t_method)dwt_even, gensym("even"), A_DEFFLOAT, 0);
+ class_addmethod(dwt_class, (t_method)idwt_coef, gensym("coef"), A_DEFFLOAT, A_DEFFLOAT, 0);
+
+
+
+ /*class_addmethod(dwt_class, (t_method)dwt_wavelet, gensym("wavelet"), A_DEFFLOAT, 0); */
+
+
+ idwt_class = class_new(gensym("idwt~"), (t_newmethod)idwt_new,
+ (t_method)dwt_free, sizeof(t_dwt), 0, A_DEFFLOAT, 0);
+
+ CLASS_MAINSIGNALIN(idwt_class, t_dwt, x_f);
+ class_addmethod(idwt_class, (t_method)dwt_print, gensym("print"), 0);
+ class_addmethod(idwt_class, (t_method)dwt_dsp, gensym("dsp"), 0);
+
+ class_addmethod(idwt_class, (t_method)dwt_filter, gensym("predict"), A_GIMME, 0);
+ class_addmethod(idwt_class, (t_method)dwt_filter, gensym("update"), A_GIMME, 0);
+ class_addmethod(idwt_class, (t_method)dwt_filter, gensym("mask"), A_GIMME, 0);
+
+ class_addmethod(idwt_class, (t_method)idwt_coef, gensym("coef"), A_DEFFLOAT, A_DEFFLOAT, 0);
+
+ class_addmethod(idwt_class, (t_method)dwt_even, gensym("even"), A_DEFFLOAT, 0);
+
+
+
+ dwt16_class = class_new(gensym("dwt16~"), (t_newmethod)dwt16_new,
+ (t_method)dwt_free, sizeof(t_dwt), 0, A_DEFFLOAT, 0);
+ CLASS_MAINSIGNALIN(dwt16_class, t_dwt, x_f);
+ class_addmethod(dwt16_class, (t_method)dwt_print, gensym("print"), 0);
+ class_addmethod(dwt16_class, (t_method)dwt_reset, gensym("reset"), 0);
+ class_addmethod(dwt16_class, (t_method)dwt_dsp, gensym("dsp"), 0);
+
+ class_addmethod(dwt16_class, (t_method)dwt_filter, gensym("predict"), A_GIMME, 0);
+ class_addmethod(dwt16_class, (t_method)dwt_filter, gensym("update"), A_GIMME, 0);
+ class_addmethod(dwt16_class, (t_method)dwt_filter, gensym("mask"), A_GIMME, 0);
+
+
+
+
+ idwt16_class = class_new(gensym("idwt16~"), (t_newmethod)idwt16_new,
+ (t_method)dwt_free, sizeof(t_dwt), 0, A_DEFFLOAT, 0);
+
+ CLASS_MAINSIGNALIN(idwt16_class, t_dwt, x_f);
+ class_addmethod(idwt16_class, (t_method)dwt_print, gensym("print"), 0);
+ class_addmethod(idwt16_class, (t_method)dwt_dsp, gensym("dsp"), 0);
+
+ class_addmethod(idwt16_class, (t_method)dwt_filter, gensym("predict"), A_GIMME, 0);
+ class_addmethod(idwt16_class, (t_method)dwt_filter, gensym("update"), A_GIMME, 0);
+ class_addmethod(idwt16_class, (t_method)dwt_filter, gensym("mask"), A_GIMME, 0);
+
+ class_addmethod(idwt16_class, (t_method)idwt_coef, gensym("coef"), A_DEFFLOAT, A_DEFFLOAT, 0);
+
+
+
+
+}
+
diff --git a/modules/dynwav.c b/modules/dynwav.c
new file mode 100644
index 0000000..0ff75f3
--- /dev/null
+++ b/modules/dynwav.c
@@ -0,0 +1,318 @@
+/*
+ * dynwav.c - dynamic wavetable oscillator
+ * data organization is in (real, imag) pairs
+ * the first 2 components are (DC, NY)
+ * Copyright (c) 2000-2003 by Tom Schouten
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#include "m_pd.h"
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define MAXORDER 1024
+
+typedef struct dynwavctl
+{
+ t_float *c_buf1; /* current */
+ t_float *c_buf2; /* old */
+ t_int c_order;
+
+} t_dynwavctl;
+
+typedef struct dynwav
+{
+ t_object x_obj;
+ t_float x_f;
+ t_dynwavctl x_ctl;
+} t_dynwav;
+
+
+static t_int *dynwav_perform(t_int *w)
+{
+
+
+ t_float *wave = (float *)(w[3]);
+ t_float *freq = (float *)(w[4]);
+ t_float *out = (float *)(w[5]);
+ t_dynwavctl *ctl = (t_dynwavctl *)(w[1]);
+ t_int n = (t_int)(w[2]);
+
+ t_float *buf, *dbuf, *swap;
+
+ int i;
+ int mask = n-1;
+
+
+ /* swap buffer pointers */
+ swap = ctl->c_buf1; /* this is the last one stored */
+ buf = ctl->c_buf1 = ctl->c_buf2; /* put oldest in newest to overwrite */
+ dbuf = ctl->c_buf2 = swap; /* put last one in oldest */
+
+
+ if (buf && dbuf)
+ {
+
+ /* store input wavetable in buffer */
+ memcpy(buf, wave, n*sizeof(t_float));
+
+
+ for (i = 0; i < n; i++)
+ {
+ float findex = *freq++ * (t_float)n;
+ int index = findex;
+ float frac, a, b, c, d, cminusb, q, r;
+ int ia, ib, ic, id;
+
+ frac = findex - index;
+
+ ia = (index-1) & mask;
+ ib = (index ) & mask;
+ ic = (index+1) & mask;
+ id = (index+2) & mask;
+
+ q = i+1;
+ q /= n;
+
+ r = n-1-i;
+ r /= n;
+
+ /* get 4 points, wrap index */
+ a = q * buf[ia] + r * dbuf[ia];
+ b = q * buf[ib] + r * dbuf[ib];
+ c = q * buf[ic] + r * dbuf[ic];
+ d = q * buf[id] + r * dbuf[id];
+
+ cminusb = c-b;
+ *out++ = b + frac * (cminusb - 0.5f * (frac-1.) *
+ ((a - d + 3.0f * cminusb) * frac +
+ (b - a - cminusb)));
+ }
+
+ }
+ return (w+6);
+}
+
+static t_int *dynwav_perform_8point(t_int *w) /* werkt nog nie tegoei */
+{
+
+
+ t_float *wave = (float *)(w[3]);
+ t_float *freq = (float *)(w[4]);
+ t_float *out = (float *)(w[5]);
+ t_dynwavctl *ctl = (t_dynwavctl *)(w[1]);
+ t_int n = (t_int)(w[2]);
+
+ t_float *buf, *dbuf, *swap;
+
+ int i;
+ int mask = n-1;
+
+
+ /* swap buffer pointers */
+ swap = ctl->c_buf1; /* this is the last one stored */
+ buf = ctl->c_buf1 = ctl->c_buf2; /* put oldest in newest to overwrite */
+ dbuf = ctl->c_buf2 = swap; /* put last one in oldest */
+
+
+ if (buf && dbuf)
+ {
+
+ /* const float N1 = 1 / ( 2 * (1-(1/9)) * (1-(1/25)) * (1-(1/49)) );
+ ** const float N2 = 1 / ( (1-(9)) * 2 * (1-(9/25)) * (1-(9/49)) );
+ ** const float N3 = 1 / ( (1-(25)) * (1-(25/9)) * 2 * (1-(25/49)) );
+ ** const float N4 = 1 / ( (1-(49)) * (1-(49/9)) * (1-(49/25)) * 2 );
+ */
+
+ const float N1 = 0.59814453125;
+ const float N2 = -0.11962890625;
+ const float N3 = 0.02392578125;
+ const float N4 = -0.00244140625;
+
+
+ /* store input wavetable in buffer */
+ memcpy(buf, wave, n*sizeof(t_float));
+
+
+ for (i = 0; i < n; i++)
+ {
+ float findex = *freq++ * (t_float)n;
+ int index = findex;
+ float frac, q, r, fm, fp, fe, fo;
+ float x1, x2, x3, x4;
+ float g1, g2, g3, g4;
+ float gg, g2g3g4, g1g3g4, g1g2g4, g1g2g3;
+ float acc;
+ int im, ip;
+
+ frac = 2 *(findex - index) - 1;
+
+ x1 = frac;
+ x2 = frac/3;
+ x3 = frac/5;
+ x4 = frac/7;
+
+ g1 = 1 - x1*x1;
+ g2 = 1 - x2*x2;
+ g3 = 1 - x3*x3;
+ g4 = 1 - x4*x4;
+
+ gg = g3 * g4;
+ g2g3g4 = g2 * gg; /* 1 */
+ g1g3g4 = g1 * gg; /* 2 */
+ gg = g1 * g2;
+ g1g2g4 = g4 * gg; /* 3 */
+ g1g2g3 = g3 * gg; /* 4 */
+
+
+ /* triangle interpolation between current and past wavetable*/
+ q = i+1;
+ q /= n;
+
+ r = n-1-i;
+ r /= n;
+
+
+ /* 1, -1*/
+ im = (index ) & mask;
+ ip = (index+1) & mask;
+ fm = q * buf[im] + r * dbuf[im];
+ fp = q * buf[ip] + r * dbuf[ip];
+ fe = fp + fm;
+ fo = fp - fm;
+
+ acc = N1 * g2g3g4 * (fe + x1*fo);
+
+ /* 2, -2 */
+ im = (index-1) & mask;
+ ip = (index+2) & mask;
+ fm = q * buf[im] + r * dbuf[im];
+ fp = q * buf[ip] + r * dbuf[ip];
+ fe = fp + fm;
+ fo = fp - fm;
+
+ acc += N2 * g1g3g4 * (fe + x2*fo);
+
+ /* 3, -3 */
+ im = (index-2) & mask;
+ ip = (index+3) & mask;
+ fm = q * buf[im] + r * dbuf[im];
+ fp = q * buf[ip] + r * dbuf[ip];
+ fe = fp + fm;
+ fo = fp - fm;
+
+ acc += N3 * g1g2g4 * (fe + x3*fo);
+
+ /* 4, -4 */
+ im = (index-3) & mask;
+ ip = (index+4) & mask;
+ fm = q * buf[im] + r * dbuf[im];
+ fp = q * buf[ip] + r * dbuf[ip];
+ fe = fp + fm;
+ fo = fp - fm;
+
+ acc += N4 * g1g2g3 * (fe + x4*fo);
+
+
+ *out++ = acc;
+
+ }
+
+ }
+ return (w+6);
+}
+
+
+static void dynwav_dsp(t_dynwav *x, t_signal **sp)
+{
+ int n = sp[0]->s_n;
+ int k;
+
+ if (x->x_ctl.c_order != n)
+ {
+ if (x->x_ctl.c_buf1) free (x->x_ctl.c_buf1);
+ if (x->x_ctl.c_buf2) free (x->x_ctl.c_buf2);
+
+ x->x_ctl.c_buf1 = (t_float *)malloc(n*sizeof(t_float));
+ x->x_ctl.c_buf2 = (t_float *)malloc(n*sizeof(t_float));
+
+ for(k=0; k<n; k++)
+ {
+ x->x_ctl.c_buf1[k] = 0;
+ x->x_ctl.c_buf2[k] = 0;
+ }
+
+ x->x_ctl.c_order = n;
+ }
+
+
+ dsp_add(dynwav_perform_8point, 5, &x->x_ctl, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec);
+
+
+}
+static void dynwav_free(t_dynwav *x)
+{
+
+ if (x->x_ctl.c_buf1) free (x->x_ctl.c_buf1);
+ if (x->x_ctl.c_buf2) free (x->x_ctl.c_buf2);
+
+}
+
+t_class *dynwav_class;
+
+static void *dynwav_new(t_floatarg order)
+{
+ t_dynwav *x = (t_dynwav *)pd_new(dynwav_class);
+ int iorder = (int)order;
+ int i, n=64, k;
+
+ /* in 2 */
+ inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("signal"), gensym("signal"));
+
+ /* out 1 */
+ outlet_new(&x->x_obj, gensym("signal"));
+
+
+
+ /* init data */
+ x->x_ctl.c_buf1 = (t_float *)malloc(n*sizeof(t_float));
+ x->x_ctl.c_buf2 = (t_float *)malloc(n*sizeof(t_float));
+
+ for(k=0; k<n; k++)
+ {
+ x->x_ctl.c_buf1[k] = 0;
+ x->x_ctl.c_buf2[k] = 0;
+ }
+
+ x->x_ctl.c_order = n;
+
+ return (void *)x;
+}
+
+void dynwav_tilde_setup(void)
+{
+ //post("dynwav~ v0.1");
+ dynwav_class = class_new(gensym("dynwav~"), (t_newmethod)dynwav_new,
+ (t_method)dynwav_free, sizeof(t_dynwav), 0, A_DEFFLOAT, 0);
+ CLASS_MAINSIGNALIN(dynwav_class, t_dynwav, x_f);
+ class_addmethod(dynwav_class, (t_method)dynwav_dsp, gensym("dsp"), 0);
+
+
+}
+
diff --git a/modules/ead.c b/modules/ead.c
new file mode 100644
index 0000000..8b93faa
--- /dev/null
+++ b/modules/ead.c
@@ -0,0 +1,153 @@
+/*
+ * ead.c - exponential attack decay envelope
+ * Copyright (c) 2000-2003 by Tom Schouten
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "extlib_util.h"
+
+/* pointer to */
+t_class *ead_class;
+
+
+/* state data fpr attack/decay dsp plugin */
+typedef struct eadctl
+{
+ t_float c_attack;
+ t_float c_decay;
+ t_float c_state;
+ t_float c_target;
+} t_eadctl;
+
+
+/* object data structure */
+typedef struct ead
+{
+ t_object x_obj;
+ t_eadctl x_ctl;
+} t_ead;
+
+
+
+static void ead_attack(t_ead *x, t_floatarg f)
+{
+ x->x_ctl.c_attack = milliseconds_2_one_minus_realpole(f);
+}
+
+static void ead_decay(t_ead *x, t_floatarg f)
+{
+ x->x_ctl.c_decay = milliseconds_2_one_minus_realpole(f);
+}
+
+static void ead_start(t_ead *x)
+{
+ x->x_ctl.c_target = 1;
+}
+
+
+/* dsp callback function, not a method */
+static t_int *ead_perform(t_int *w)
+{
+
+ /* interprete arguments */
+ t_float *out = (float *)(w[3]);
+ t_eadctl *ctl = (t_eadctl *)(w[1]);
+ t_float attack = ctl->c_attack;
+ t_float decay = ctl->c_decay;
+ t_float state = ctl->c_state;
+ t_float target = ctl->c_target;
+ t_int n = (t_int)(w[2]);
+
+ t_int i;
+
+
+ /* A/D code */
+
+ if (target == 1)
+ /* attack phase */
+ {
+ for (i = 0; i < n; i++)
+ {
+ *out++ = state;
+ state += attack*(1 - state);
+ }
+ if (state > ENVELOPE_MAX)
+ ctl->c_target = 0;
+ }
+
+ else
+ /* decay phase */
+ for (i = 0; i < n; i++)
+ {
+ *out++ = state;
+ state -= decay*state;
+ }
+
+ ctl->c_state = state;
+
+ return (w+4); /* pd quirk: pointer for sequencer */
+}
+
+
+static void ead_dsp(t_ead *x, t_signal **sp)
+{
+ dsp_add(ead_perform, 3, &x->x_ctl, sp[0]->s_n, sp[0]->s_vec);
+}
+
+/* destructor */
+static void ead_free(void)
+{
+
+}
+
+
+
+/* constructor */
+static void *ead_new(t_floatarg attack, t_floatarg decay, t_floatarg sustain, t_floatarg release)
+{
+ /* create instance */
+ t_ead *x = (t_ead *)pd_new(ead_class);
+ /* create new inlets, convert incoming message float to attack/decay */
+ inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("attack"));
+ inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("decay"));
+ /* create a dsp outlet */
+ outlet_new(&x->x_obj, gensym("signal"));
+
+ /* initialize */
+ x->x_ctl.c_state = 0;
+ x->x_ctl.c_target = 0;
+ ead_attack(x, attack);
+ ead_decay(x, decay);
+
+ /* return instance */
+ return (void *)x;
+}
+
+void ead_tilde_setup(void)
+{
+ //post("ead~ v0.1");
+
+ ead_class = class_new(gensym("ead~"), (t_newmethod)ead_new,
+ (t_method)ead_free, sizeof(t_ead), 0, A_DEFFLOAT, A_DEFFLOAT, 0);
+
+
+ class_addmethod(ead_class, (t_method)ead_start, gensym("start"), 0);
+ class_addmethod(ead_class, (t_method)ead_start, gensym("bang"), 0);
+ class_addmethod(ead_class, (t_method)ead_dsp, gensym("dsp"), 0);
+ class_addmethod(ead_class, (t_method)ead_attack, gensym("attack"), A_FLOAT, 0);
+ class_addmethod(ead_class, (t_method)ead_decay, gensym("decay"), A_FLOAT, 0);
+}
+
diff --git a/modules/eadsr.c b/modules/eadsr.c
new file mode 100644
index 0000000..0e0b9db
--- /dev/null
+++ b/modules/eadsr.c
@@ -0,0 +1,171 @@
+/*
+ * eadsr.c - exponential attack decay sustain release envelope
+ * Copyright (c) 2000-2003 by Tom Schouten
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "extlib_util.h"
+
+typedef struct eadsrctl
+{
+ t_float c_attack;
+ t_float c_decay;
+ t_float c_sustain;
+ t_float c_release;
+ t_float c_state;
+ t_float c_target;
+} t_eadsrctl;
+
+typedef struct eadsr
+{
+ t_object x_obj;
+ t_float x_sr;
+ t_eadsrctl x_ctl;
+} t_eadsr;
+
+void eadsr_attack(t_eadsr *x, t_floatarg f)
+{
+ x->x_ctl.c_attack = milliseconds_2_one_minus_realpole(f);
+}
+
+void eadsr_decay(t_eadsr *x, t_floatarg f)
+{
+ x->x_ctl.c_decay = milliseconds_2_one_minus_realpole(f);
+}
+
+void eadsr_sustain(t_eadsr *x, t_floatarg f)
+{
+ if (f>ENVELOPE_MAX) f = ENVELOPE_MAX;
+ if (f<ENVELOPE_MIN) f = ENVELOPE_MIN;
+
+ x->x_ctl.c_sustain = f;
+}
+
+void eadsr_release(t_eadsr *x, t_floatarg f)
+{
+ x->x_ctl.c_release = milliseconds_2_one_minus_realpole(f);
+
+}
+
+void eadsr_start(t_eadsr *x)
+{
+ x->x_ctl.c_target = 1;
+
+}
+
+void eadsr_stop(t_eadsr *x)
+{
+ x->x_ctl.c_target = 0;
+
+}
+
+static t_int *eadsr_perform(t_int *w)
+{
+ t_float *out = (float *)(w[3]);
+ t_eadsrctl *ctl = (t_eadsrctl *)(w[1]);
+ t_float attack = ctl->c_attack;
+ t_float decay = ctl->c_decay;
+ t_float sustain = ctl->c_sustain;
+ t_float release = ctl->c_release;
+ t_float state = ctl->c_state;
+ t_float target = ctl->c_target;
+ t_int n = (t_int)(w[2]);
+
+ t_int i;
+
+
+ if (target == 1)
+ /* attack phase */
+ {
+ for (i = 0; i < n; i++)
+ {
+ *out++ = state;
+ state += attack*(1 - state);
+ }
+ if (state > ENVELOPE_MAX)
+ ctl->c_target = sustain;
+ }
+
+ else if (target == 0)
+ /* release phase */
+ for (i = 0; i < n; i++)
+ {
+ *out++ = state;
+ state -= release*state;
+ }
+
+ else
+ /* decay phase */
+ for (i = 0; i < n; i++)
+ {
+ *out++ = state;
+ state -= decay*(state-sustain);
+ }
+
+ ctl->c_state = state;
+ return (w+4);
+}
+
+static void eadsr_dsp(t_eadsr *x, t_signal **sp)
+{
+ x->x_sr = sp[0]->s_sr;
+ dsp_add(eadsr_perform, 3, &x->x_ctl, sp[0]->s_n, sp[0]->s_vec);
+
+}
+void eadsr_free(void)
+{
+
+}
+
+t_class *eadsr_class;
+
+void *eadsr_new(t_floatarg attack, t_floatarg decay, t_floatarg sustain, t_floatarg release)
+{
+ t_eadsr *x = (t_eadsr *)pd_new(eadsr_class);
+ inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("attack"));
+ inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("decay"));
+ inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("sustain"));
+ inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("release"));
+ outlet_new(&x->x_obj, gensym("signal"));
+
+ x->x_ctl.c_state = 0;
+ x->x_ctl.c_target = 0;
+ eadsr_attack(x, attack);
+ eadsr_decay(x, decay);
+ eadsr_sustain(x, sustain);
+ eadsr_release(x, release);
+
+
+ return (void *)x;
+}
+
+void eadsr_tilde_setup(void)
+{
+ //post("eadsr~ v0.1");
+ eadsr_class = class_new(gensym("eadsr~"), (t_newmethod)eadsr_new,
+ (t_method)eadsr_free, sizeof(t_eadsr), 0, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0);
+ class_addmethod(eadsr_class, (t_method)eadsr_start, gensym("start"), 0);
+ class_addmethod(eadsr_class, (t_method)eadsr_start, gensym("bang"), 0);
+ class_addmethod(eadsr_class, (t_method)eadsr_stop, gensym("stop"), 0);
+ class_addmethod(eadsr_class, (t_method)eadsr_dsp, gensym("dsp"), 0);
+ class_addmethod(eadsr_class, (t_method)eadsr_attack, gensym("attack"), A_FLOAT, 0);
+ class_addmethod(eadsr_class, (t_method)eadsr_decay, gensym("decay"), A_FLOAT, 0);
+ class_addmethod(eadsr_class, (t_method)eadsr_sustain, gensym("sustain"), A_FLOAT, 0);
+ class_addmethod(eadsr_class, (t_method)eadsr_release, gensym("release"), A_FLOAT, 0);
+
+
+}
+
diff --git a/modules/ear.c b/modules/ear.c
new file mode 100644
index 0000000..efe9b3f
--- /dev/null
+++ b/modules/ear.c
@@ -0,0 +1,134 @@
+/*
+ * ear.c - exponential attack release envelope
+ * Copyright (c) 2000-2003 by Tom Schouten
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "extlib_util.h"
+
+typedef struct earctl
+{
+ t_float c_attack;
+ t_float c_release;
+ t_float c_state;
+ t_float c_target;
+} t_earctl;
+
+typedef struct ear
+{
+ t_object x_obj;
+ t_float x_sr;
+ t_earctl x_ctl;
+} t_ear;
+
+void ear_attack(t_ear *x, t_floatarg f)
+{
+ x->x_ctl.c_attack = milliseconds_2_one_minus_realpole(f);
+}
+
+void ear_release(t_ear *x, t_floatarg f)
+{
+ x->x_ctl.c_release = milliseconds_2_one_minus_realpole(f);
+}
+
+void ear_start(t_ear *x)
+{
+ x->x_ctl.c_target = 1;
+
+}
+
+void ear_stop(t_ear *x)
+{
+ x->x_ctl.c_target = 0;
+
+}
+
+static t_int *ear_perform(t_int *w)
+{
+ t_float *out = (float *)(w[3]);
+ t_earctl *ctl = (t_earctl *)(w[1]);
+ t_float attack = ctl->c_attack;
+ t_float release = ctl->c_release;
+ t_float state = ctl->c_state;
+ t_float target = ctl->c_target;
+ t_int n = (t_int)(w[2]);
+
+ t_int i;
+
+ if (target) /* attack phase */
+ for (i = 0; i < n; i++)
+ {
+ *out++ = state;
+ state += attack*(1 - state);
+ }
+ else /* release phase */
+ for (i = 0; i < n; i++)
+ {
+ *out++ = state;
+ state -= release*state;
+ }
+
+ ctl->c_state = state;
+ return (w+4);
+}
+
+static void ear_dsp(t_ear *x, t_signal **sp)
+{
+ x->x_sr = sp[0]->s_sr;
+ dsp_add(ear_perform, 3, &x->x_ctl, sp[0]->s_n, sp[0]->s_vec);
+
+}
+void ear_free(void)
+{
+
+}
+
+
+t_class *ear_class; /* attack - release */
+
+void *ear_new(t_floatarg attack, t_floatarg release)
+{
+ t_ear *x = (t_ear *)pd_new(ear_class);
+ inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("attack"));
+ inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("release"));
+ outlet_new(&x->x_obj, gensym("signal"));
+
+ ear_attack(x,attack);
+ ear_release(x,release);
+ x->x_ctl.c_state = 0;
+ x->x_ctl.c_target = 0;
+
+ return (void *)x;
+}
+
+
+void ear_tilde_setup(void)
+{
+ //post("ear~ v0.1");
+ ear_class = class_new(gensym("ear~"), (t_newmethod)ear_new,
+ (t_method)ear_free, sizeof(t_ear), 0, A_DEFFLOAT, A_DEFFLOAT, 0);
+ class_addmethod(ear_class, (t_method)ear_start, gensym("start"), 0);
+ class_addmethod(ear_class, (t_method)ear_start, gensym("bang"), 0);
+ class_addmethod(ear_class, (t_method)ear_stop, gensym("stop"), 0);
+ class_addmethod(ear_class, (t_method)ear_dsp, gensym("dsp"), 0);
+ class_addmethod(ear_class,
+ (t_method)ear_attack, gensym("attack"), A_FLOAT, 0);
+ class_addmethod(ear_class,
+ (t_method)ear_release, gensym("release"), A_FLOAT, 0);
+
+
+}
+
diff --git a/modules/ffpoly.c b/modules/ffpoly.c
new file mode 100644
index 0000000..023f29d
--- /dev/null
+++ b/modules/ffpoly.c
@@ -0,0 +1,173 @@
+/*
+ * ffpoly.c - compute a finite field polynomial
+ * Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org>
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+
+#include "m_pd.h"
+#include <stdlib.h>
+
+
+
+
+typedef struct ffpoly_struct
+{
+ t_object x_obj;
+ t_float x_f;
+
+ t_outlet *x_outlet;
+ t_int *x_coef;
+ t_int x_poly_order;
+ t_int x_field_order;
+
+ t_int x_lastpackedcoef;
+
+
+
+} t_ffpoly;
+
+
+
+
+static void ffpoly_compute(t_ffpoly *x, t_floatarg fcoef)
+{
+ int in = (int)fcoef;
+ int fo = x->x_field_order;
+ int po = x->x_poly_order;
+ int* c = x->x_coef;
+ int i, out;
+
+ in %= fo;
+ if (in < 0) in += fo;
+
+ out = c[po];
+ for (i=po-1; i>=0; i--){
+ out *= in;
+ out += c[i];
+ out %= fo;
+ }
+
+
+ outlet_float(x->x_outlet, (float)out);
+}
+
+
+/* this sets all coefficients given one float */
+static void ffpoly_coefficients(t_ffpoly *x, t_floatarg fcoef)
+{
+ int coef = (int)fcoef;
+ int i;
+ if (coef < 0) coef = -coef;
+
+ x->x_lastpackedcoef = coef;
+
+ for (i=0; i<x->x_poly_order + 1; i++){
+ x->x_coef[i] = coef % x->x_field_order;
+ coef = coef / x->x_field_order;
+ }
+
+
+}
+
+/* this sets one coefficient */
+static void ffpoly_coef(t_ffpoly *x, t_floatarg index, t_floatarg val)
+{
+ int i = (int)index;
+ int v = (int)val;
+ if (i<0) return;
+ if (i>x->x_poly_order) return;
+
+ v %= x->x_field_order;
+ if (v<0) v += x->x_field_order;
+
+ x->x_coef[i] = v;
+
+
+}
+
+static void ffpoly_fieldorder(t_ffpoly *x, t_floatarg ffieldorder)
+{
+ int i;
+ int order = (int)ffieldorder;
+ if (order < 2) order = 2;
+ x->x_field_order = order;
+
+ for (i=0; i<x->x_poly_order+1; i++)
+ x->x_coef[i] %= x->x_field_order;
+
+ //ffpoly_coefficients(x, x->x_lastpackedcoef);
+}
+
+static void ffpoly_free(t_ffpoly *x)
+{
+ free (x->x_coef);
+}
+
+t_class *ffpoly_class;
+
+
+
+static void *ffpoly_new(t_floatarg fpolyorder, t_floatarg ffieldorder)
+{
+ t_int polyorder = (int)fpolyorder;
+ t_int fieldorder = (int)ffieldorder;
+
+ t_ffpoly *x = (t_ffpoly *)pd_new(ffpoly_class);
+
+ if (polyorder < 1) polyorder = 1;
+ if (fieldorder < 2) fieldorder = 2;
+
+ x->x_poly_order = polyorder;
+ x->x_field_order = fieldorder;
+
+ x->x_coef = (int *)malloc((x->x_poly_order + 1) * sizeof(int));
+
+ /* set poly to f(x) = x */
+ ffpoly_coefficients(x, x->x_field_order);
+
+ x->x_outlet = outlet_new(&x->x_obj, &s_float);
+
+ return (void *)x;
+}
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+void ffpoly_setup(void)
+{
+
+
+ ffpoly_class = class_new(gensym("ffpoly"), (t_newmethod)ffpoly_new,
+ (t_method)ffpoly_free, sizeof(t_ffpoly), 0, A_DEFFLOAT, A_DEFFLOAT, A_NULL);
+
+ class_addmethod(ffpoly_class, (t_method)ffpoly_coefficients, gensym("coefficients"), A_FLOAT, A_NULL);
+
+ class_addmethod(ffpoly_class, (t_method)ffpoly_coef, gensym("coef"), A_FLOAT, A_FLOAT, A_NULL);
+ class_addmethod(ffpoly_class, (t_method)ffpoly_fieldorder, gensym("order"), A_FLOAT, A_NULL);
+ class_addfloat(ffpoly_class, (t_method)ffpoly_compute);
+
+
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/modules/fwarp.c b/modules/fwarp.c
new file mode 100644
index 0000000..28fe024
--- /dev/null
+++ b/modules/fwarp.c
@@ -0,0 +1,61 @@
+/*
+ * fwarp.c - converts a frequency to a "standard" tangent warped freq
+ * Copyright (c) 2000-2003 by Tom Schouten
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#include "m_pd.h"
+#include <math.h>
+
+#define SEQL 16
+
+
+typedef struct fwarp
+{
+ t_object t_ob;
+ t_outlet *x_out;
+} t_fwarp;
+
+static void fwarp_float(t_fwarp *x, t_floatarg f)
+{
+ float twopi = 2.0f * M_PI;
+ float sr = sys_getsr();
+ f /= sr;
+ f = tan(twopi * f) / twopi;
+ outlet_float(x->x_out, f * sr);
+}
+
+static void fwarp_free(void)
+{
+}
+
+t_class *fwarp_class;
+
+static void *fwarp_new(void)
+{
+ t_fwarp *x = (t_fwarp *)pd_new(fwarp_class);
+ x->x_out = outlet_new(&x->t_ob, gensym("float"));
+ return (void *)x;
+}
+
+void fwarp_setup(void)
+{
+ fwarp_class = class_new(gensym("fwarp"), (t_newmethod)fwarp_new,
+ (t_method)fwarp_free, sizeof(t_fwarp), 0, 0);
+ class_addfloat(fwarp_class, fwarp_float);
+}
+
diff --git a/modules/lattice.c b/modules/lattice.c
new file mode 100644
index 0000000..9403393
--- /dev/null
+++ b/modules/lattice.c
@@ -0,0 +1,143 @@
+/*
+ * lattice.c - a lattice filter for pd
+ * Copyright (c) 2000-2003 by Tom Schouten
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+
+#include "m_pd.h"
+#include <math.h>
+
+#define maxorder 1024
+
+typedef struct latticesegment
+{
+ t_float delay; // delay element
+ t_float rc; // reflection coefficient
+} t_latticesegment;
+
+typedef struct latticectl
+{
+ t_latticesegment c_segment[maxorder]; // array of lattice segment data
+ t_int c_segments;
+} t_latticectl;
+
+typedef struct lattice
+{
+ t_object x_obj;
+ t_float x_f;
+ t_latticectl x_ctl;
+} t_lattice;
+
+
+
+static t_int *lattice_perform(t_int *w)
+{
+
+
+ t_float *in = (float *)(w[3]);
+ t_float *out = (float *)(w[4]);
+ t_latticectl *ctl = (t_latticectl *)(w[1]);
+ t_int i,j;
+ t_int n = (t_int)(w[2]);
+ t_float x,rc,d;
+
+ t_latticesegment* seg = ctl->c_segment;
+ t_int segments = ctl->c_segments;
+ for (i=0; i<n; i++)
+ {
+ x = *in++;
+ // section 0
+ rc = seg[0].rc;
+ x += seg[0].delay * rc;
+
+ // section 1 to segments-1
+ for (j=1; j < segments; j++)
+ {
+ rc = seg[j].rc;
+ d = seg[j].delay;
+ x += d * rc;
+ seg[j-1].delay = d - rc * x;
+ }
+ // stub
+ seg[segments-1].delay = x;
+
+ *out++ = x;
+ }
+
+ return (w+5);
+}
+
+static void lattice_dsp(t_lattice *x, t_signal **sp)
+{
+ dsp_add(lattice_perform, 4, &x->x_ctl, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec);
+
+}
+static void lattice_free(void)
+{
+
+}
+
+t_class *lattice_class;
+
+static void lattice_rc(t_lattice *x, t_float segment, t_float refco)
+{
+ t_int seg = (t_float)segment;
+ if ((seg >= 0) && (seg < x->x_ctl.c_segments)){
+ if (refco > 1.0f) refco = 1.0f;
+ if (refco < -1.0f) refco = -1.0f;
+ x->x_ctl.c_segment[seg].rc = refco;
+ }
+}
+
+static void lattice_reset(t_lattice *x)
+{
+ t_float* buf = (t_float *)x->x_ctl.c_segment;
+ t_int n = x->x_ctl.c_segments;
+ t_int i;
+ for (i=0; i<n; i++) buf[i]=0;
+}
+
+static void *lattice_new(t_floatarg segments)
+{
+ t_lattice *x = (t_lattice *)pd_new(lattice_class);
+ t_int seg = (t_int)segments;
+
+ outlet_new(&x->x_obj, gensym("signal"));
+
+ if (seg < 1) seg = 1;
+ if (seg > maxorder) seg = maxorder;
+
+ x->x_ctl.c_segments = seg;
+
+ lattice_reset(x);
+
+ return (void *)x;
+}
+
+void lattice_tilde_setup(void)
+{
+ //post("lattice~ v0.1");
+ lattice_class = class_new(gensym("lattice~"), (t_newmethod)lattice_new,
+ (t_method)lattice_free, sizeof(t_lattice), 0, A_DEFFLOAT, 0);
+ CLASS_MAINSIGNALIN(lattice_class, t_lattice, x_f);
+ class_addmethod(lattice_class, (t_method)lattice_dsp, gensym("dsp"), 0);
+ class_addmethod(lattice_class, (t_method)lattice_reset, gensym("reset"), 0);
+ class_addmethod(lattice_class, (t_method)lattice_rc, gensym("rc"), A_FLOAT, A_FLOAT, 0);
+
+}
+
diff --git a/modules/matrix.c b/modules/matrix.c
new file mode 100644
index 0000000..6fd55b7
--- /dev/null
+++ b/modules/matrix.c
@@ -0,0 +1,154 @@
+/*
+ * matrix.c - applies a matrix transform to a signal block
+ * intended for spectral processing, dynwav
+ *
+ * Copyright (c) 2000-2003 by Tom Schouten
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "m_pd.h"
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define MAXORDER 1024
+
+typedef struct matrixctl
+{
+ t_float *c_A; /* matrix */
+ t_float *c_x; /* vector */
+ t_int c_order;
+
+} t_matrixctl;
+
+typedef struct matrix
+{
+ t_object x_obj;
+ t_float x_f;
+ t_matrixctl x_ctl;
+} t_matrix;
+
+static void matrix_load(t_matrix *x, t_symbol *s)
+{
+ FILE *matrix;
+
+ if(s && s->s_name)
+ {
+ post("matrix: loading %s",s->s_name);
+ if(matrix = fopen(s->s_name, "r"))
+ {
+ int n = x->x_ctl.c_order;
+ fread(x->x_ctl.c_A, sizeof(float), n*n, matrix);
+ }
+ else post("matrix: error, cant open file.");
+ }
+}
+
+
+static t_int *matrix_perform(t_int *w)
+{
+
+
+ t_float *in = (float *)(w[3]);
+ t_float *out = (float *)(w[4]);
+ t_matrixctl *ctl = (t_matrixctl *)(w[1]);
+ t_int n = (t_int)(w[2]);
+
+ t_int i,j;
+ t_float *A = ctl->c_A;
+ t_float *x = ctl->c_x;
+
+ if (in == out) /* store input if ness. */
+ {
+ memcpy(x, in, sizeof(t_float)*n);
+ in = x;
+ }
+ bzero(out, sizeof(t_float)*n); /* init output */
+
+ for (j=0; j<n; j++)
+ for (i=0; i<n; i++)
+ out[i] += A[i+j*n] * in[j];
+
+ return (w+5);
+}
+
+static void matrix_dsp(t_matrix *x, t_signal **sp)
+{
+ int n = sp[0]->s_n;
+ int k,i;
+
+ if (x->x_ctl.c_order != n)
+ {
+ if (x->x_ctl.c_A) free (x->x_ctl.c_A);
+
+ x->x_ctl.c_A = (t_float *)calloc(n*n,sizeof(t_float));
+ x->x_ctl.c_x = (t_float *)calloc(n,sizeof(t_float));
+ x->x_ctl.c_order = n;
+ }
+
+ for (i=0;i<n;i++) x->x_ctl.c_A[i] = 1;
+
+ dsp_add(matrix_perform, 4, &x->x_ctl, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec);
+
+
+}
+static void matrix_free(t_matrix *x)
+{
+
+ if (x->x_ctl.c_A) free (x->x_ctl.c_A);
+ if (x->x_ctl.c_x) free (x->x_ctl.c_x);
+
+}
+
+t_class *matrix_class;
+
+static void *matrix_new(t_floatarg order)
+{
+ t_matrix *x = (t_matrix *)pd_new(matrix_class);
+ int iorder = (int)order;
+ int i, n=64, k;
+
+
+ /* out 1 */
+ outlet_new(&x->x_obj, gensym("signal"));
+
+
+
+ /* init data */
+
+ x->x_ctl.c_A = (t_float *)calloc(n*n,sizeof(t_float));
+ x->x_ctl.c_x = (t_float *)calloc(n,sizeof(t_float));
+
+
+ for (i=0;i<n;i++) x->x_ctl.c_A[i] = 1;
+ x->x_ctl.c_order = n;
+
+ return (void *)x;
+}
+
+void matrix_tilde_setup(void)
+{
+ //post("matrix~ v0.1");
+ matrix_class = class_new(gensym("matrix~"), (t_newmethod)matrix_new,
+ (t_method)matrix_free, sizeof(t_matrix), 0, A_DEFFLOAT, 0);
+ CLASS_MAINSIGNALIN(matrix_class, t_matrix, x_f);
+ class_addmethod(matrix_class, (t_method)matrix_dsp, gensym("dsp"), 0);
+ class_addmethod(matrix_class, (t_method)matrix_load, gensym("load"), A_SYMBOL,0);
+
+
+}
+
diff --git a/modules/permut.c b/modules/permut.c
new file mode 100644
index 0000000..bc143d2
--- /dev/null
+++ b/modules/permut.c
@@ -0,0 +1,177 @@
+/*
+ * permut.c - applies a (random) permutation on a signal block
+ * intended for spectral processing, dynwav
+ *
+ * Copyright (c) 2000-2003 by Tom Schouten
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#include "m_pd.h"
+#include <math.h>
+#include <stdlib.h>
+
+
+
+typedef struct permutctl
+{
+ char c_type;
+ int *c_permutationtable;
+ int c_blocksize;
+} t_permutctl;
+
+typedef struct permut
+{
+ t_object x_obj;
+ t_float x_f;
+ t_permutctl x_ctl;
+} t_permut;
+
+
+static inline void permut_perform_permutation(t_float *S, int n, t_int *f)
+{
+ t_int k,l;
+ t_float swap;
+ for(k=0; k<n; k++)
+ {
+ l = f[k];
+ while (l<k) l = f[l];
+ swap = S[k];
+ S[k] = S[l];
+ S[l] = swap;
+ }
+}
+
+
+static void permut_random(t_permut *x, t_floatarg seed)
+{
+ int i,j;
+ int N = x->x_ctl.c_blocksize;
+ int mask = N-1;
+ int *p = x->x_ctl.c_permutationtable;
+ int r, last = 0;
+
+ srand(* ((unsigned int *)(&seed)));
+
+ if(p)
+ {
+ p[0] = rand() & mask;
+ for (i=1;i<N;i++)
+ {
+ r = rand() & mask;
+ j = 0;
+ while(j<i)
+ {
+ if (p[j] == r)
+ {
+ r = (r + 1) & mask;
+ j = 0;
+ }
+ else j++;
+ }
+ p[i] = r;
+
+ }
+ }
+}
+
+static void permut_bang(t_permut *x)
+{
+ unsigned int r = rand();
+ permut_random(x, *((float *)(&r)));
+}
+
+static void permut_resize_table(t_permut *x, int size)
+{
+ if (x->x_ctl.c_blocksize != size)
+ {
+ if (x->x_ctl.c_permutationtable)
+ free(x->x_ctl.c_permutationtable);
+ x->x_ctl.c_permutationtable = (int *)malloc(sizeof(int)*size);
+ x->x_ctl.c_blocksize = size;
+
+ /* make sure it's initialized */
+ permut_bang(x);
+
+
+ }
+}
+
+
+
+
+static t_int *permut_perform(t_int *w)
+{
+
+
+ t_float *in = (float *)(w[3]);
+ t_float *out = (float *)(w[4]);
+ t_permutctl *ctl = (t_permutctl *)(w[1]);
+ t_int i;
+ t_int n = (t_int)(w[2]);
+ t_float x,y;
+ t_int *p = ctl->c_permutationtable;
+
+
+ if (in != out)
+ for (i=0; i<n; i++) out[i] = in[i];
+
+
+ permut_perform_permutation(out, n, p);
+
+ return (w+5);
+}
+
+static void permut_dsp(t_permut *x, t_signal **sp)
+{
+ permut_resize_table(x, sp[0]->s_n);
+ dsp_add(permut_perform, 4, &x->x_ctl, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec);
+
+}
+
+static void permut_free(t_permut *x)
+{
+ if (x->x_ctl.c_permutationtable) free(x->x_ctl.c_permutationtable);
+
+}
+
+t_class *permut_class;
+
+static void *permut_new(void)
+{
+ t_permut *x = (t_permut *)pd_new(permut_class);
+ outlet_new(&x->x_obj, gensym("signal"));
+
+ x->x_ctl.c_permutationtable = 0;
+ x->x_ctl.c_blocksize = 0;
+ permut_resize_table(x, 64);
+ permut_random(x, 0);
+
+ return (void *)x;
+}
+
+void permut_tilde_setup(void)
+{
+ //post("permut~ v0.1");
+ permut_class = class_new(gensym("permut~"), (t_newmethod)permut_new,
+ (t_method)permut_free, sizeof(t_permut), 0, A_DEFFLOAT, 0);
+ CLASS_MAINSIGNALIN(permut_class, t_permut, x_f);
+ class_addmethod(permut_class, (t_method)permut_random, gensym("random"), A_FLOAT, 0);
+ class_addmethod(permut_class, (t_method)permut_bang, gensym("bang"), 0);
+ class_addmethod(permut_class, (t_method)permut_dsp, gensym("dsp"), 0);
+
+}
+
diff --git a/modules/qmult.c b/modules/qmult.c
new file mode 100644
index 0000000..94766e1
--- /dev/null
+++ b/modules/qmult.c
@@ -0,0 +1,165 @@
+/*
+ * qmult.c - quaternion multiplication dsp object
+ * Copyright (c) 2000-2003 by Tom Schouten
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "m_pd.h"
+#include <math.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+
+
+typedef struct qmultctl
+{
+ t_float *c_inputleft[4];
+ t_float *c_inputright[4];
+ t_float *c_output[4];
+} t_qmultctl;
+
+typedef struct qmult
+{
+ t_object x_obj;
+ t_float x_f;
+ t_qmultctl x_ctl;
+} t_qmult;
+
+
+static t_int *qmult_perform(t_int *word)
+{
+
+
+
+ t_qmultctl *ctl = (t_qmultctl *)(word[1]);
+ t_int n = (t_int)(word[2]);
+ t_int i;
+
+ t_float *in0l = ctl->c_inputleft[0];
+ t_float *in1l = ctl->c_inputleft[1];
+ t_float *in2l = ctl->c_inputleft[2];
+ t_float *in3l = ctl->c_inputleft[3];
+
+ t_float *in0r = ctl->c_inputright[0];
+ t_float *in1r = ctl->c_inputright[1];
+ t_float *in2r = ctl->c_inputright[2];
+ t_float *in3r = ctl->c_inputright[3];
+
+ t_float *out0 = ctl->c_output[0];
+ t_float *out1 = ctl->c_output[1];
+ t_float *out2 = ctl->c_output[2];
+ t_float *out3 = ctl->c_output[3];
+
+ t_float wl, xl, yl, zl;
+ t_float wr, xr, yr, zr;
+ t_float w, x, y, z;
+
+ for (i=0;i<n;i++)
+ {
+
+ /* read input quaternions */
+ wl = *in0l++;
+ xl = *in1l++;
+ yl = *in2l++;
+ zl = *in3l++;
+
+ wr = *in0r++;
+ xr = *in1r++;
+ yr = *in2r++;
+ zr = *in3r++;
+
+
+ /* multiply quaternions */
+ w = wl * wr;
+ x = wl * xr;
+ y = wl * yr;
+ z = wl * zr;
+
+ w -= xl * xr;
+ x += xl * wr;
+ y -= xl * zr;
+ z += xl * yr;
+
+ w -= yl * yr;
+ x += yl * zr;
+ y += yl * wr;
+ z -= yl * xr;
+
+ w -= zl * zr;
+ x -= zl * yr;
+ y += zl * xr;
+ z += zl * wr;
+
+
+
+ /* write output quaternion */
+ *out0++ = w;
+ *out1++ = x;
+ *out2++ = y;
+ *out3++ = z;
+ }
+
+
+ return (word+3);
+}
+
+
+
+static void qmult_dsp(t_qmult *x, t_signal **sp)
+{
+
+ int i;
+ for (i=0;i<4;i++)
+ {
+ x->x_ctl.c_inputleft[i] = sp[i]->s_vec;
+ x->x_ctl.c_inputright[i] = sp[i+4]->s_vec;
+ x->x_ctl.c_output[i] = sp[i+8]->s_vec;
+ }
+
+ dsp_add(qmult_perform, 2, &x->x_ctl, sp[0]->s_n);
+
+
+}
+
+
+static void qmult_free(t_qmult *x)
+{
+
+}
+
+t_class *qmult_class;
+
+static void *qmult_new(t_floatarg channels)
+{
+ int i;
+ t_qmult *x = (t_qmult *)pd_new(qmult_class);
+
+ for (i=1;i<8;i++) inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("signal"), gensym("signal"));
+ for (i=0;i<4;i++) outlet_new(&x->x_obj, gensym("signal"));
+
+ return (void *)x;
+}
+
+void qmult_tilde_setup(void)
+{
+ //post("qmult~ v0.1");
+ qmult_class = class_new(gensym("qmult~"), (t_newmethod)qmult_new,
+ (t_method)qmult_free, sizeof(t_qmult), 0, 0);
+ CLASS_MAINSIGNALIN(qmult_class, t_qmult, x_f);
+ class_addmethod(qmult_class, (t_method)qmult_dsp, gensym("dsp"), 0);
+
+}
+
diff --git a/modules/qnorm.c b/modules/qnorm.c
new file mode 100644
index 0000000..e826b1b
--- /dev/null
+++ b/modules/qnorm.c
@@ -0,0 +1,137 @@
+/*
+ * qnorm.c - quaternion normalization dsp object
+ * Copyright (c) 2000-2003 by Tom Schouten
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "m_pd.h"
+#include <math.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+
+
+typedef struct qnormctl
+{
+ t_float *c_input[4];
+ t_float *c_output[4];
+} t_qnormctl;
+
+typedef struct qnorm
+{
+ t_object x_obj;
+ t_float x_f;
+ t_qnormctl x_ctl;
+} t_qnorm;
+
+
+static t_int *qnorm_perform(t_int *word)
+{
+
+
+
+ t_qnormctl *ctl = (t_qnormctl *)(word[1]);
+ t_int n = (t_int)(word[2]);
+ t_int i;
+
+ t_float *in0 = ctl->c_input[0];
+ t_float *in1 = ctl->c_input[1];
+ t_float *in2 = ctl->c_input[2];
+ t_float *in3 = ctl->c_input[3];
+
+ t_float *out0 = ctl->c_output[0];
+ t_float *out1 = ctl->c_output[1];
+ t_float *out2 = ctl->c_output[2];
+ t_float *out3 = ctl->c_output[3];
+
+ t_float w, x, y, z;
+ t_float norm;
+ t_float inorm;
+
+ for (i=0;i<n;i++)
+ {
+
+ /* read input */
+ w = *in0++;
+ x = *in1++;
+ y = *in2++;
+ z = *in3++;
+
+ /* transform */
+ norm = w * w;
+ norm += x * x;
+ norm += y * y;
+ norm += z * z;
+
+ inorm = (norm == 0.0f) ? (0.0f) : (1.0f / sqrt(norm));
+
+ /* write output */
+ *out0++ = w * inorm;
+ *out1++ = x * inorm;
+ *out2++ = y * inorm;
+ *out3++ = z * inorm;
+ }
+
+
+ return (word+3);
+}
+
+
+
+static void qnorm_dsp(t_qnorm *x, t_signal **sp)
+{
+
+ int i;
+ for (i=0;i<4;i++)
+ {
+ x->x_ctl.c_input[i] = sp[i]->s_vec;
+ x->x_ctl.c_output[i] = sp[i+4]->s_vec;
+ }
+
+ dsp_add(qnorm_perform, 2, &x->x_ctl, sp[0]->s_n);
+
+
+}
+
+
+static void qnorm_free(t_qnorm *x)
+{
+
+}
+
+t_class *qnorm_class;
+
+static void *qnorm_new(t_floatarg channels)
+{
+ int i;
+ t_qnorm *x = (t_qnorm *)pd_new(qnorm_class);
+
+ for (i=1;i<4;i++) inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("signal"), gensym("signal"));
+ for (i=0;i<4;i++) outlet_new(&x->x_obj, gensym("signal"));
+
+ return (void *)x;
+}
+
+void qnorm_tilde_setup(void)
+{
+ //post("qnorm~ v0.1");
+ qnorm_class = class_new(gensym("qnorm~"), (t_newmethod)qnorm_new,
+ (t_method)qnorm_free, sizeof(t_qnorm), 0, 0);
+ CLASS_MAINSIGNALIN(qnorm_class, t_qnorm, x_f);
+ class_addmethod(qnorm_class, (t_method)qnorm_dsp, gensym("dsp"), 0);
+
+}
+
diff --git a/modules/ramp.c b/modules/ramp.c
new file mode 100644
index 0000000..ad13582
--- /dev/null
+++ b/modules/ramp.c
@@ -0,0 +1,118 @@
+/*
+ * ramp.c - retriggerable counter for dsp signals
+ * Copyright (c) 2000-2003 by Tom Schouten
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#include "m_pd.h"
+#include <math.h>
+
+
+typedef struct rampctl
+{
+ t_float c_offset;
+ t_float c_looppoint;
+} t_rampctl;
+
+typedef struct ramp
+{
+ t_object x_obj;
+ t_float x_f;
+ t_rampctl x_ctl;
+} t_ramp;
+
+
+void ramp_offset(t_ramp *x, t_floatarg f)
+{
+
+ x->x_ctl.c_offset = f;
+
+}
+
+void ramp_looppoint(t_ramp *x, t_floatarg f)
+{
+
+ x->x_ctl.c_looppoint = f;
+
+}
+
+
+void ramp_bang(t_ramp *x)
+{
+ ramp_offset(x, 0);
+
+}
+
+
+
+static t_int *ramp_perform(t_int *w)
+{
+
+
+ t_float *out = (float *)(w[3]);
+ t_rampctl *ctl = (t_rampctl *)(w[1]);
+ t_int i;
+ t_int n = (t_int)(w[2]);
+ t_float x;
+
+
+
+ x = ctl->c_offset;
+
+ for (i = 0; i < n; i++)
+ {
+ *out++ = (float)x++;
+ }
+
+ ctl->c_offset = x; /* save state */
+
+
+ return (w+4);
+}
+
+static void ramp_dsp(t_ramp *x, t_signal **sp)
+{
+ dsp_add(ramp_perform, 3, &x->x_ctl, sp[0]->s_n, sp[0]->s_vec);
+
+}
+void ramp_free(void)
+{
+
+}
+
+t_class *ramp_class;
+
+void *ramp_new(void)
+{
+ t_ramp *x = (t_ramp *)pd_new(ramp_class);
+ /* inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("looppoint"));*/
+ outlet_new(&x->x_obj, gensym("signal"));
+
+ ramp_bang(x);
+ return (void *)x;
+}
+
+void ramp_tilde_setup(void)
+{
+ //post("ramp~ v0.1");
+ ramp_class = class_new(gensym("ramp~"), (t_newmethod)ramp_new,
+ (t_method)ramp_free, sizeof(t_ramp), 0, 0);
+ class_addmethod(ramp_class, (t_method)ramp_bang, gensym("bang"), 0);
+ class_addmethod(ramp_class, (t_method)ramp_dsp, gensym("dsp"), 0);
+ class_addfloat(ramp_class, (t_method)ramp_offset);
+}
+
diff --git a/modules/ratio.c b/modules/ratio.c
new file mode 100644
index 0000000..777f2b9
--- /dev/null
+++ b/modules/ratio.c
@@ -0,0 +1,66 @@
+/*
+ * ratio.c - multiplies by 2^k such that output is between 1 and 2
+ * Copyright (c) 2000-2003 by Tom Schouten
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#include "m_pd.h"
+
+#define SEQL 16
+
+typedef struct{
+} t_ratio_data;
+
+typedef struct ratio
+{
+ t_object t_ob;
+ t_outlet *x_out;
+ t_ratio_data x_c;
+} t_ratio;
+
+static void ratio_float(t_ratio *x, t_floatarg f)
+{
+ f = (f<0)?(-f):(f);
+ if (f)
+ {
+ while (f < 1.0f) f *= 2.0f;
+ while (f >= 2.0f) f *= 0.5f;
+ }
+ outlet_float(x->x_out, f);
+
+}
+
+static void ratio_free(void)
+{
+}
+
+t_class *ratio_class;
+
+static void *ratio_new(void)
+{
+ t_ratio *x = (t_ratio *)pd_new(ratio_class);
+ x->x_out = outlet_new(&x->t_ob, gensym("float"));
+ return (void *)x;
+}
+
+void ratio_setup(void)
+{
+ ratio_class = class_new(gensym("ratio"), (t_newmethod)ratio_new,
+ (t_method)ratio_free, sizeof(t_ratio), 0, 0);
+ class_addfloat(ratio_class, ratio_float);
+}
+
diff --git a/modules/statwav.c b/modules/statwav.c
new file mode 100644
index 0000000..52c6a0b
--- /dev/null
+++ b/modules/statwav.c
@@ -0,0 +1,149 @@
+/*
+ * dynwav.c - static wavetable oscillator (scale + tabread)
+ * data organization is in (real, imag) pairs
+ * the first 2 components are (DC, NY)
+ * Copyright (c) 2000-2003 by Tom Schouten
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "m_pd.h"
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static t_class *statwav_tilde_class;
+
+typedef struct _statwav_tilde
+{
+ t_object x_obj;
+ int x_npoints;
+ float *x_vec;
+ t_symbol *x_arrayname;
+ float x_f;
+} t_statwav_tilde;
+
+static void *statwav_tilde_new(t_symbol *s)
+{
+ t_statwav_tilde *x = (t_statwav_tilde *)pd_new(statwav_tilde_class);
+ x->x_arrayname = s;
+ x->x_vec = 0;
+ outlet_new(&x->x_obj, gensym("signal"));
+ x->x_f = 0;
+ return (x);
+}
+
+static t_int *statwav_tilde_perform(t_int *w)
+{
+ t_statwav_tilde *x = (t_statwav_tilde *)(w[1]);
+ t_float *in = (t_float *)(w[2]);
+ t_float *out = (t_float *)(w[3]);
+ int n = (int)(w[4]);
+ float maxindex;
+ int imaxindex;
+ float *buf = x->x_vec, *fp;
+ int i;
+
+ maxindex = x->x_npoints;
+ imaxindex = x->x_npoints;
+
+ if (!buf) goto zero;
+
+
+ for (i = 0; i < n; i++)
+ {
+ float phase = *in++;
+ float modphase = phase - (int)phase;
+ float findex = modphase * maxindex;
+ int index = findex;
+ int ia, ib, ic, id;
+ float frac, a, b, c, d, cminusb;
+ static int count;
+
+
+ frac = findex - index;
+ ia = (imaxindex+index-1) % imaxindex;
+ ib = index;
+ ic = (index+1) % imaxindex;
+ id = (index+2) % imaxindex;
+
+ a = buf[ia];
+ b = buf[ib];
+ c = buf[ic];
+ d = buf[id];
+ /* if (!i && !(count++ & 1023))
+ post("fp = %lx, shit = %lx, b = %f", fp, buf->b_shit, b); */
+ cminusb = c-b;
+
+ *out++ = b + frac * (
+ cminusb - 0.5f * (frac-1.) * (
+ (a - d + 3.0f * cminusb) * frac + (b - a - cminusb)
+ )
+ );
+ }
+
+ return (w+5);
+ zero:
+ while (n--) *out++ = 0;
+
+ return (w+5);
+}
+
+static void statwav_tilde_set(t_statwav_tilde *x, t_symbol *s)
+{
+ t_garray *a;
+
+ x->x_arrayname = s;
+ if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class)))
+ {
+ if (*s->s_name)
+ error("statwav~: %s: no such array", x->x_arrayname->s_name);
+ x->x_vec = 0;
+ }
+ else if (!garray_getfloatarray(a, &x->x_npoints, &x->x_vec))
+ {
+ error("%s: bad template for statwav~", x->x_arrayname->s_name);
+ x->x_vec = 0;
+ }
+ else garray_usedindsp(a);
+}
+
+static void statwav_tilde_dsp(t_statwav_tilde *x, t_signal **sp)
+{
+ statwav_tilde_set(x, x->x_arrayname);
+
+ dsp_add(statwav_tilde_perform, 4, x,
+ sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
+
+}
+
+static void statwav_tilde_free(t_statwav_tilde *x)
+{
+}
+
+void statwav_tilde_setup(void)
+{
+ //post("statwav~ v0.1");
+ statwav_tilde_class = class_new(gensym("statwav~"),
+ (t_newmethod)statwav_tilde_new, (t_method)statwav_tilde_free,
+ sizeof(t_statwav_tilde), 0, A_DEFSYM, 0);
+ CLASS_MAINSIGNALIN(statwav_tilde_class, t_statwav_tilde, x_f);
+ class_addmethod(statwav_tilde_class, (t_method)statwav_tilde_dsp,
+ gensym("dsp"), 0);
+ class_addmethod(statwav_tilde_class, (t_method)statwav_tilde_set,
+ gensym("set"), A_SYMBOL, 0);
+}
+
diff --git a/modules/tabreadmix.c b/modules/tabreadmix.c
new file mode 100644
index 0000000..91181c5
--- /dev/null
+++ b/modules/tabreadmix.c
@@ -0,0 +1,271 @@
+/*
+ * tabreadmix.c - an overlap add tabread~ clone
+ * Copyright (c) 2000-2003 by Tom Schouten
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "extlib_util.h"
+
+/******************** tabreadmix~ ***********************/
+
+static t_class *tabreadmix_tilde_class;
+
+typedef struct _tabreadmix_tilde
+{
+ t_object x_obj;
+ int x_npoints;
+ float *x_vec;
+ t_symbol *x_arrayname;
+ float x_f;
+
+ /* file position vars */
+ int x_currpos;
+ int x_prevpos;
+
+ /* cross fader state vars */
+ int x_xfade_size;
+ int x_xfade_phase;
+ float x_xfade_cos;
+ float x_xfade_sin;
+ float x_xfade_state_c;
+ float x_xfade_state_s;
+
+} t_tabreadmix_tilde;
+
+
+
+inline void tabreadmix_tilde_wrapindices(t_tabreadmix_tilde *x)
+{
+ int max;
+
+ /* modulo */
+ x->x_currpos %= x->x_npoints;
+ x->x_prevpos %= x->x_npoints;
+
+ /* make sure 0<=..<x->x_npoints */
+ //if (x->x_currpos < 0) x->x_currpos += x->x_npoints;
+ //if (x->x_prevpos < 0) x->x_prevpos += x->x_npoints;
+ x->x_currpos += (x->x_currpos < 0) * x->x_npoints;
+ x->x_prevpos += (x->x_prevpos < 0) * x->x_npoints;
+
+}
+
+
+
+#define min(x,y) ((x)<(y)?(x):(y))
+
+static t_int *tabreadmix_tilde_perform(t_int *w)
+{
+ t_tabreadmix_tilde *x = (t_tabreadmix_tilde *)(w[1]);
+ t_float *pos = (t_float *)(w[2]);
+ t_float *out = (t_float *)(w[3]);
+ int n = (int)(w[4]);
+ int maxxindex;
+ float *buf = x->x_vec;
+ int i;
+ float currgain, prevgain;
+ float c,s;
+ int chunk;
+ int leftover;
+ int newpos = (int)*pos;
+
+ maxxindex = x->x_npoints;
+ if (!buf) goto zero;
+ if (maxxindex <= 0) goto zero;
+
+
+ while (n){
+
+ /* process as much data as possible */
+ leftover = x->x_xfade_size - x->x_xfade_phase;
+ chunk = min(n, leftover);
+
+ for (i = 0; i < chunk; i++){
+ /* compute crossfade gains from oscillator state */
+ currgain = 0.5f - x->x_xfade_state_c;
+ prevgain = 0.5f + x->x_xfade_state_c;
+
+ /* check indices & wrap */
+ tabreadmix_tilde_wrapindices(x);
+
+ /* mix and write */
+ newpos = (int)(*pos++);
+ *out++ = currgain * buf[x->x_currpos++] + prevgain * buf[x->x_prevpos++];
+
+ /* advance oscillator */
+ c = x->x_xfade_state_c * x->x_xfade_cos - x->x_xfade_state_s * x->x_xfade_sin;
+ s = x->x_xfade_state_c * x->x_xfade_sin + x->x_xfade_state_s * x->x_xfade_cos;
+ x->x_xfade_state_c = c;
+ x->x_xfade_state_s = s;
+ }
+
+ /* update indices */
+ x->x_xfade_phase += chunk;
+ n -= chunk;
+ //pos += chunk;
+
+ /* check if prev chunk is finished */
+ if (x->x_xfade_size == x->x_xfade_phase){
+ x->x_prevpos = x->x_currpos;
+ x->x_currpos = newpos;
+ x->x_xfade_state_c = 0.5f;
+ x->x_xfade_state_s = 0.0f;
+ x->x_xfade_phase = 0;
+ }
+
+ }
+
+ /* return if we ran out of data */
+ return (w+5);
+
+
+ zero:
+ while (n--) *out++ = 0;
+ return (w+5);
+}
+
+
+static void tabreadmix_tilde_blocksize(t_tabreadmix_tilde *x, t_float size)
+{
+ double prev_phase;
+ int max;
+ float fmax = (float)x->x_npoints * 0.5f;
+
+ if (size < 1.0) size = 1.0;
+
+ prev_phase = (double)x->x_xfade_phase;
+ prev_phase *= size;
+ prev_phase /= (double)x->x_xfade_size;
+
+
+ /* preserve the crossfader state */
+ x->x_xfade_phase = (int)prev_phase;
+ x->x_xfade_size = (int)size;
+
+
+ x->x_xfade_cos = cos(M_PI / (float)x->x_xfade_size);
+ x->x_xfade_sin = sin(M_PI / (float)x->x_xfade_size);
+
+
+ /* make sure indices are inside array */
+ if (x->x_npoints == 0){
+ x->x_currpos = 0;
+ x->x_prevpos = 0;
+ }
+
+ //else tabreadmix_tilde_wrapindices(x);
+
+
+
+}
+
+void tabreadmix_tilde_pitch(t_tabreadmix_tilde *x, t_float f)
+{
+ if (f < 1) f = 1;
+
+ tabreadmix_tilde_blocksize(x, sys_getsr() / f);
+}
+
+void tabreadmix_tilde_chunks(t_tabreadmix_tilde *x, t_float f)
+{
+ if (f < 1.0f) f = 1.0f;
+ tabreadmix_tilde_blocksize(x, (float)x->x_npoints / f);
+}
+
+void tabreadmix_tilde_bang(t_tabreadmix_tilde *x, t_float f)
+{
+ //trigger a chunk reset on next dsp call
+ x->x_xfade_phase = x->x_xfade_size;
+}
+
+void tabreadmix_tilde_set(t_tabreadmix_tilde *x, t_symbol *s)
+{
+ t_garray *a;
+
+ x->x_arrayname = s;
+ if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class)))
+ {
+ if (*s->s_name)
+ error("tabreadmix~: %s: no such array", x->x_arrayname->s_name);
+ x->x_vec = 0;
+ }
+ else if (!garray_getfloatarray(a, &x->x_npoints, &x->x_vec))
+ {
+ error("%s: bad template for tabreadmix~", x->x_arrayname->s_name);
+ x->x_vec = 0;
+ }
+ else garray_usedindsp(a);
+
+ /* make sure indices are inside array */
+ if (x->x_npoints == 0){
+ x->x_currpos = 0;
+ x->x_prevpos = 0;
+ }
+
+ //else tabreadmix_tilde_wrapindices(x);
+
+}
+
+static void tabreadmix_tilde_dsp(t_tabreadmix_tilde *x, t_signal **sp)
+{
+ tabreadmix_tilde_set(x, x->x_arrayname);
+
+ dsp_add(tabreadmix_tilde_perform, 4, x,
+ sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
+
+}
+
+static void tabreadmix_tilde_free(t_tabreadmix_tilde *x)
+{
+}
+
+static void *tabreadmix_tilde_new(t_symbol *s)
+{
+ t_tabreadmix_tilde *x = (t_tabreadmix_tilde *)pd_new(tabreadmix_tilde_class);
+ x->x_arrayname = s;
+ x->x_vec = 0;
+ inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("blocksize"));
+ outlet_new(&x->x_obj, gensym("signal"));
+ x->x_f = 0;
+ x->x_xfade_phase = 0;
+ x->x_xfade_size = 1024;
+ x->x_currpos = 0;
+ x->x_prevpos = 0;
+ x->x_xfade_state_c = 0.5f;
+ x->x_xfade_state_s = 0.0f;
+ tabreadmix_tilde_blocksize(x, 1024);
+ return (x);
+}
+
+void tabreadmix_tilde_setup(void)
+{
+ tabreadmix_tilde_class = class_new(gensym("tabreadmix~"),
+ (t_newmethod)tabreadmix_tilde_new, (t_method)tabreadmix_tilde_free,
+ sizeof(t_tabreadmix_tilde), 0, A_DEFSYM, 0);
+ CLASS_MAINSIGNALIN(tabreadmix_tilde_class, t_tabreadmix_tilde, x_f);
+ class_addmethod(tabreadmix_tilde_class, (t_method)tabreadmix_tilde_dsp,
+ gensym("dsp"), 0);
+ class_addmethod(tabreadmix_tilde_class, (t_method)tabreadmix_tilde_set,
+ gensym("set"), A_SYMBOL, 0);
+ class_addmethod(tabreadmix_tilde_class, (t_method)tabreadmix_tilde_blocksize,
+ gensym("blocksize"), A_FLOAT, 0);
+ class_addmethod(tabreadmix_tilde_class, (t_method)tabreadmix_tilde_pitch,
+ gensym("pitch"), A_FLOAT, 0);
+ class_addmethod(tabreadmix_tilde_class, (t_method)tabreadmix_tilde_chunks,
+ gensym("chunks"), A_FLOAT, 0);
+ class_addmethod(tabreadmix_tilde_class, (t_method)tabreadmix_tilde_bang,
+ gensym("bang"), 0);
+}
diff --git a/modules/xfm.c b/modules/xfm.c
new file mode 100644
index 0000000..63c79ab
--- /dev/null
+++ b/modules/xfm.c
@@ -0,0 +1,271 @@
+/*
+ * xfm.c - cross frequency modulation object
+ * Copyright (c) 2000-2003 by Tom Schouten
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+/*
+coupled fm. osc state equations:
+
+phasor for system i =
+
+ [ 1 -phi ]
+(1+phi^2)^(1/2) * [ phi 1 ]
+
+
+with phi = 2*pi*(freq_base + freq_mod * out_other) / sr
+
+
+ideal phasor would be
+
+[ cos(phi) - sin(phi) ]
+[ sin(phi) cos(phi) ]
+
+
+this means frequencies are warped:
+
+2*pi*f_real = atan(2*pi*f)
+
+some (possible) enhancements:
+ + add an integrator to get phase modulation
+ + undo the frequency warping
+
+*/
+
+#include "m_pd.h"
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define SINSAMPLES 512
+#define MYPI 3.1415927
+
+
+#define DISTORTED 0
+#define NORMALIZED 1
+
+
+typedef struct xfmctl
+{
+ //t_float c_sintab[SINSAMPLES + 1];
+ t_float c_x1, c_y1; /* state osc 1 */
+ t_float c_x2, c_y2; /* state osc 2 */
+ t_int c_type; /* type of algo */
+
+} t_xfmctl;
+
+typedef struct xfm
+{
+ t_object x_obj;
+ t_float x_f;
+ t_xfmctl x_ctl;
+} t_xfm;
+
+void xfm_type(t_xfm *x, t_float f)
+{
+ int t = (int)f;
+
+ if (t == DISTORTED) x->x_ctl.c_type = t;
+ if (t == NORMALIZED) x->x_ctl.c_type = t;
+
+}
+
+
+static inline t_float xfm_sat(t_float x)
+{
+ const float max = 1;
+ const float min = -1;
+
+ x = (x > max) ? (max) : (x);
+ x = (x < min) ? (min) : (x);
+
+ return(x);
+}
+
+static t_int *xfm_perform(t_int *w)
+{
+
+
+ t_float *inA = (float *)(w[3]);
+ t_float *inB = (float *)(w[4]);
+ t_float *fbA = (float *)(w[5]);
+ t_float *fbB = (float *)(w[6]);
+ t_float *outA = (float *)(w[7]);
+ t_float *outB = (float *)(w[8]);
+ t_xfmctl *ctl = (t_xfmctl *)(w[1]);
+ t_int n = (t_int)(w[2]);
+ //t_float *tab = ctl->c_sintab;
+
+ t_float x1 = ctl->c_x1, y1 = ctl->c_y1, z1, dx1, dy1, inv_norm1;
+ t_float x2 = ctl->c_x2, y2 = ctl->c_y2, z2, dx2, dy2, inv_norm2;
+
+ t_float scale = 2 * M_PI / sys_getsr();
+
+ t_int i;
+
+ switch(ctl->c_type){
+ default:
+ case DISTORTED:
+
+ /* this is a 4 degree of freedom hyperchaotic system */
+ /* two coupled saturated unstable oscillators */
+
+ for (i=0; i<n; i++){
+ /* osc 1 */
+ z1 = scale * (x2 * (*fbA++) + (*inA++));
+
+ dx1 = x1 - z1*y1;
+ dy1 = y1 + z1*x1;
+
+ x1 = xfm_sat(dx1);
+ y1 = xfm_sat(dy1);
+
+ /* osc 2*/
+ z2 = scale * (x1 * (*fbB++) + (*inB++));
+
+ dx2 = x2 - z2*y2;
+ dy2 = y2 + z2*x2;
+
+ x2 = xfm_sat(dx2);
+ y2 = xfm_sat(dy2);
+
+ /* output */
+ (*outA++) = x1;
+ (*outB++) = x2;
+
+ }
+ break;
+
+ case NORMALIZED:
+
+ /* this is a an effective 2 degree of freedom quasiperiodic system */
+ /* two coupled stable oscillators */
+
+ for (i=0; i<n; i++){
+
+ /* osc 1 */
+ z1 = scale * (x2 * (*fbA++) + (*inA++));
+
+ dx1 = x1 - z1*y1;
+ dy1 = y1 + z1*x1;
+ inv_norm1 = 1.0f / hypot(dx1, dy1);
+
+
+ /* osc 2*/
+ z2 = scale * (x1 * (*fbB++) + (*inB++));
+
+ dx2 = x2 - z2*y2;
+ dy2 = y2 + z2*x2;
+ inv_norm2 = 1.0f / hypot(dx2, dy2);
+
+ /* renormalize */
+ x1 = dx1 * inv_norm1;
+ y1 = dy1 * inv_norm1;
+ x2 = dx2 * inv_norm2;
+ y2 = dy2 * inv_norm2;
+
+ /* output */
+ (*outA++) = x1;
+ (*outB++) = x2;
+ }
+ break;
+ }
+
+ ctl->c_x1 = x1;
+ ctl->c_y1 = y1;
+ ctl->c_x2 = x2;
+ ctl->c_y2 = y2;
+
+ return (w+9);
+}
+
+static void xfm_dsp(t_xfm *x, t_signal **sp)
+{
+ int n = sp[0]->s_n;
+ int k;
+
+
+ dsp_add(xfm_perform,
+ 8,
+ &x->x_ctl,
+ sp[0]->s_n,
+ sp[0]->s_vec,
+ sp[1]->s_vec,
+ sp[2]->s_vec,
+ sp[3]->s_vec,
+ sp[4]->s_vec,
+ sp[5]->s_vec);
+
+
+}
+static void xfm_free(t_xfm *x)
+{
+
+
+}
+
+
+
+
+static void xfm_reset(t_xfm *x)
+{
+ x->x_ctl.c_x1 = 1;
+ x->x_ctl.c_y1 = 0;
+ x->x_ctl.c_x2 = 1;
+ x->x_ctl.c_y2 = 0;
+
+}
+
+
+t_class *xfm_class;
+
+static void *xfm_new(t_floatarg algotype)
+{
+ t_xfm *x = (t_xfm *)pd_new(xfm_class);
+
+ /* ins */
+ inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("signal"), gensym("signal"));
+ inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("signal"), gensym("signal"));
+ inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("signal"), gensym("signal"));
+
+ /* outs */
+ outlet_new(&x->x_obj, gensym("signal"));
+ outlet_new(&x->x_obj, gensym("signal"));
+
+
+
+ /* init data */
+ xfm_reset(x);
+ xfm_type(x, algotype);
+
+ return (void *)x;
+}
+
+void xfm_tilde_setup(void)
+{
+ //post("xfm~ v0.1");
+ xfm_class = class_new(gensym("xfm~"), (t_newmethod)xfm_new,
+ (t_method)xfm_free, sizeof(t_xfm), 0, A_DEFFLOAT, 0);
+ CLASS_MAINSIGNALIN(xfm_class, t_xfm, x_f);
+ class_addmethod(xfm_class, (t_method)xfm_type, gensym("type"), A_FLOAT, 0);
+ class_addmethod(xfm_class, (t_method)xfm_dsp, gensym("dsp"), 0);
+ class_addmethod(xfm_class, (t_method)xfm_reset, gensym("reset"), 0);
+
+
+}
+