aboutsummaryrefslogtreecommitdiff
path: root/src/delay~~.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/delay~~.c')
-rwxr-xr-xsrc/delay~~.c390
1 files changed, 390 insertions, 0 deletions
diff --git a/src/delay~~.c b/src/delay~~.c
new file mode 100755
index 0000000..41930f7
--- /dev/null
+++ b/src/delay~~.c
@@ -0,0 +1,390 @@
+/* Copyright (c) 1997-1999 Miller Puckette.
+* For information on usage and redistribution, and for a DISCLAIMER OF ALL
+* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
+
+#include "m_pd.h"
+#include "iemlib.h"
+#include "iem_dp.h"
+
+#define DEFDELVS_TT 64 /* LATER get this from canvas at DSP time */
+#define XTRASAMPS_TT 4
+#define SAMPBLK_TT 4
+
+/* ----------------------------- delwrite~~ ----------------------------- */
+
+typedef struct delwrite_tilde_tilde_ctl
+ {
+ int c_n;
+ t_sample *c_vec;
+ int c_phase;
+ } t_delwrite_tilde_tilde_ctl;
+
+typedef struct _delwrite_tilde_tilde
+ {
+ t_object x_obj;
+ t_symbol *x_sym;
+ double x_deltime;
+ t_delwrite_tilde_tilde_ctl x_cspace;
+ int x_sortno; /* DSP sort number at which this was last put on chain */
+ int x_rsortno; /* DSP sort # for first delread or write in chain */
+ int x_vecsize; /* vector size for delread~ to use */
+ t_float x_f;
+ } t_delwrite_tilde_tilde;
+
+//extern static int delread_zero;
+
+static t_class *delwrite_tilde_tilde_class;
+
+static void delwrite_tilde_tilde_updatesr (t_delwrite_tilde_tilde *x, t_float sr) /* added by Mathieu Bouchard */
+{
+ int nsamps = (int)(x->x_deltime * (double)sr * (double)(0.001));
+ if (nsamps < 1) nsamps = 1;
+ nsamps += ((- nsamps) & (SAMPBLK_TT - 1));
+ nsamps += DEFDELVS_TT;
+ if(x->x_cspace.c_n != nsamps)
+ {
+ x->x_cspace.c_vec = (t_sample *)resizebytes(x->x_cspace.c_vec,
+ (x->x_cspace.c_n + XTRASAMPS_TT) * sizeof(t_sample),
+ (nsamps + XTRASAMPS_TT) * sizeof(t_sample));
+ x->x_cspace.c_n = nsamps;
+ x->x_cspace.c_phase = XTRASAMPS_TT;
+ }
+}
+
+ /* routine to check that all delwrites/delreads/vds have same vecsize */
+static void delwrite_tilde_tilde_checkvecsize(t_delwrite_tilde_tilde *x, int vecsize)
+{
+ if (x->x_rsortno != ugen_getsortno())
+ {
+ x->x_vecsize = vecsize;
+ x->x_rsortno = ugen_getsortno();
+ }
+ /*
+ LATER this should really check sample rate and blocking, once that is
+ supported. Probably we don't actually care about vecsize.
+ For now just suppress this check. */
+#if 0
+ else if (vecsize != x->x_vecsize)
+ pd_error(x, "delread/delwrite/vd vector size mismatch");
+#endif
+}
+
+static void *delwrite_tilde_tilde_new(t_symbol *s, t_floatarg coarse_msec, t_floatarg fine_msec)
+{
+ t_delwrite_tilde_tilde *x = (t_delwrite_tilde_tilde *)pd_new(delwrite_tilde_tilde_class);
+
+ if(!*s->s_name)
+ s = gensym("delwrite~~");
+
+ pd_bind(&x->x_obj.ob_pd, s);
+ x->x_sym = s;
+ x->x_deltime = iem_dp_calc_sum(coarse_msec, fine_msec);
+ x->x_cspace.c_n = 0;
+ x->x_cspace.c_vec = (t_sample *)getbytes(XTRASAMPS_TT * sizeof(t_sample));
+ x->x_sortno = 0;
+ x->x_vecsize = 0;
+ x->x_f = 0;
+ return (x);
+}
+
+static t_int *delwrite_tilde_tilde_perform(t_int *w)
+{
+ t_float *in = (t_float *)(w[1]);
+ t_delwrite_tilde_tilde_ctl *c = (t_delwrite_tilde_tilde_ctl *)(w[2]);
+ int n = (int)(w[3]);
+ int phase = c->c_phase, nsamps = c->c_n;
+ t_sample *vp = c->c_vec, *bp = vp + phase, *ep = vp + (c->c_n + XTRASAMPS_TT);
+
+ phase += n;
+ while (n--)
+ {
+ t_sample f = *in++;
+ if(IEM_DENORMAL(f))
+ f = 0;
+ *bp++ = f;
+ if (bp == ep)
+ {
+ vp[0] = ep[-4];
+ vp[1] = ep[-3];
+ vp[2] = ep[-2];
+ vp[3] = ep[-1];
+ bp = vp + XTRASAMPS_TT;
+ phase -= nsamps;
+ }
+ }
+ c->c_phase = phase;
+ return (w+4);
+}
+
+static void delwrite_tilde_tilde_dsp(t_delwrite_tilde_tilde *x, t_signal **sp)
+{
+ dsp_add(delwrite_tilde_tilde_perform, 3, sp[0]->s_vec, &x->x_cspace, sp[0]->s_n);
+ x->x_sortno = ugen_getsortno();
+ delwrite_tilde_tilde_checkvecsize(x, sp[0]->s_n);
+ delwrite_tilde_tilde_updatesr(x, sp[0]->s_sr);
+}
+
+static void delwrite_tilde_tilde_free(t_delwrite_tilde_tilde *x)
+{
+ pd_unbind(&x->x_obj.ob_pd, x->x_sym);
+ freebytes(x->x_cspace.c_vec,
+ (x->x_cspace.c_n + XTRASAMPS_TT) * sizeof(t_sample));
+}
+
+static void delwrite_tilde_tilde_setup(void)
+{
+ delwrite_tilde_tilde_class = class_new(gensym("delwrite~~"),
+ (t_newmethod)delwrite_tilde_tilde_new, (t_method)delwrite_tilde_tilde_free,
+ sizeof(t_delwrite_tilde_tilde), 0, A_DEFSYM, A_DEFFLOAT, A_DEFFLOAT, 0);
+ CLASS_MAINSIGNALIN(delwrite_tilde_tilde_class, t_delwrite_tilde_tilde, x_f);
+ class_addmethod(delwrite_tilde_tilde_class, (t_method)delwrite_tilde_tilde_dsp,
+ gensym("dsp"), 0);
+}
+
+/* ----------------------------- delread~~ ----------------------------- */
+static t_class *delread_tilde_tilde_class;
+
+typedef struct _delread_tilde_tilde
+ {
+ t_object x_obj;
+ t_symbol *x_sym;
+ t_float x_fine;
+ double x_deltime; /* delay in msec */
+ int x_delsamps; /* delay in samples */
+ t_float x_sr; /* samples per msec */
+ t_float x_n; /* vector size */
+ int x_zerodel; /* 0 or vecsize depending on read/write order */
+ } t_delread_tilde_tilde;
+
+static void delread_tilde_tilde_list(t_delread_tilde_tilde *x, t_symbol *s, int ac, t_atom *av);
+
+static void *delread_tilde_tilde_new(t_symbol *s, int ac, t_atom *av)
+{
+ t_symbol *delname;
+ t_delread_tilde_tilde *x = (t_delread_tilde_tilde *)pd_new(delread_tilde_tilde_class);
+
+ if((ac > 0) && IS_A_SYMBOL(av, 0))
+ delname = atom_getsymbolarg(0, ac, av);
+ else
+ delname = &s_;
+ x->x_sym = delname;
+ x->x_sr = 1;
+ x->x_n = 1;
+ x->x_zerodel = 0;
+ delread_tilde_tilde_list(x, &s_list, ac-1, av+1);
+ floatinlet_new(&x->x_obj, &x->x_fine);
+ outlet_new(&x->x_obj, &s_signal);
+ return (x);
+}
+
+static void delread_tilde_tilde_list(t_delread_tilde_tilde *x, t_symbol *s, int ac, t_atom *av)
+{
+ t_float coarse, fine;
+ t_delwrite_tilde_tilde *delwriter = (t_delwrite_tilde_tilde *)pd_findbyclass(x->x_sym, delwrite_tilde_tilde_class);
+
+ if((ac > 0) && (IS_A_FLOAT(av, 0)))
+ coarse = atom_getfloatarg(0, ac, av);
+ else
+ coarse = 0.0;
+ if((ac > 1) && (IS_A_FLOAT(av, 1)))
+ fine = atom_getfloatarg(1, ac, av);
+ else
+ fine = 0.0;
+ x->x_deltime = iem_dp_calc_sum(coarse, fine);
+ if(delwriter)
+ {
+ int delsize = delwriter->x_cspace.c_n;
+
+ x->x_delsamps = (int)(0.5 + (double)x->x_sr * x->x_deltime) + x->x_n - x->x_zerodel;
+ if(x->x_delsamps < x->x_n)
+ x->x_delsamps = x->x_n;
+ else if(x->x_delsamps > delwriter->x_cspace.c_n - DEFDELVS_TT)
+ x->x_delsamps = delwriter->x_cspace.c_n - DEFDELVS_TT;
+ }
+}
+
+static void delread_tilde_tilde_double(t_delread_tilde_tilde *x, double d)
+{
+ t_delwrite_tilde_tilde *delwriter = (t_delwrite_tilde_tilde *)pd_findbyclass(x->x_sym, delwrite_tilde_tilde_class);
+
+ x->x_deltime = d;
+ if(delwriter)
+ {
+ int delsize = delwriter->x_cspace.c_n;
+
+ x->x_delsamps = (int)(0.5 + (double)x->x_sr * x->x_deltime) + x->x_n - x->x_zerodel;
+ if(x->x_delsamps < x->x_n)
+ x->x_delsamps = x->x_n;
+ else if(x->x_delsamps > delwriter->x_cspace.c_n - DEFDELVS_TT)
+ x->x_delsamps = delwriter->x_cspace.c_n - DEFDELVS_TT;
+ }
+}
+
+static void delread_tilde_tilde_float(t_delread_tilde_tilde *x, t_float coarse)
+{
+ t_delwrite_tilde_tilde *delwriter = (t_delwrite_tilde_tilde *)pd_findbyclass(x->x_sym, delwrite_tilde_tilde_class);
+
+ x->x_deltime = iem_dp_calc_sum(coarse, x->x_fine);
+ if(delwriter)
+ {
+ int delsize = delwriter->x_cspace.c_n;
+
+ x->x_delsamps = (int)(0.5 + (double)x->x_sr * x->x_deltime) + x->x_n - x->x_zerodel;
+ if(x->x_delsamps < x->x_n)
+ x->x_delsamps = x->x_n;
+ else if(x->x_delsamps > delwriter->x_cspace.c_n - DEFDELVS_TT)
+ x->x_delsamps = delwriter->x_cspace.c_n - DEFDELVS_TT;
+ }
+}
+
+static t_int *delread_tilde_tilde_perform(t_int *w)
+{
+ t_sample *out = (t_float *)(w[1]);
+ t_delwrite_tilde_tilde_ctl *c = (t_delwrite_tilde_tilde_ctl *)(w[2]);
+ int delsamps = *(int *)(w[3]);
+ int n = (int)(w[4]);
+ int phase = c->c_phase - delsamps, nsamps = c->c_n;
+ t_sample *vp = c->c_vec, *bp, *ep = vp + (c->c_n + XTRASAMPS_TT);
+
+ if(phase < 0)
+ phase += nsamps;
+ bp = vp + phase;
+ while(n--)
+ {
+ *out++ = *bp++;
+ if(bp == ep)
+ bp -= nsamps;
+ }
+ return (w+5);
+}
+
+static void delread_tilde_tilde_dsp(t_delread_tilde_tilde *x, t_signal **sp)
+{
+ t_delwrite_tilde_tilde *delwriter = (t_delwrite_tilde_tilde *)pd_findbyclass(x->x_sym, delwrite_tilde_tilde_class);
+ x->x_sr = sp[0]->s_sr * 0.001;
+ x->x_n = sp[0]->s_n;
+ if(delwriter)
+ {
+ delwrite_tilde_tilde_checkvecsize(delwriter, sp[0]->s_n);
+ x->x_zerodel = (delwriter->x_sortno == ugen_getsortno() ?
+ 0 : delwriter->x_vecsize);
+ delread_tilde_tilde_double(x, x->x_deltime);
+ dsp_add(delread_tilde_tilde_perform, 4,
+ sp[0]->s_vec, &delwriter->x_cspace, &x->x_delsamps, sp[0]->s_n);
+ }
+ else if (*x->x_sym->s_name)
+ error("delread~~: %s: no such delwrite~~",x->x_sym->s_name);
+}
+
+static void delread_tilde_tilde_setup(void)
+{
+ delread_tilde_tilde_class = class_new(gensym("delread~~"),
+ (t_newmethod)delread_tilde_tilde_new, 0,
+ sizeof(t_delread_tilde_tilde), 0, A_GIMME, 0);
+ class_addmethod(delread_tilde_tilde_class, (t_method)delread_tilde_tilde_dsp,
+ gensym("dsp"), 0);
+ class_addfloat(delread_tilde_tilde_class, (t_method)delread_tilde_tilde_float);
+}
+
+/* ----------------------------- vd~~ ----------------------------- */
+static t_class *vd_tilde_tilde_class;
+
+typedef struct _vd_tilde_tilde
+ {
+ t_object x_obj;
+ t_symbol *x_sym;
+ t_float x_sr; /* samples per msec */
+ int x_zerodel; /* 0 or vecsize depending on read/write order */
+ t_float x_f;
+ } t_vd_tilde_tilde;
+
+static void *vd_tilde_tilde_new(t_symbol *s)
+{
+ t_vd_tilde_tilde *x = (t_vd_tilde_tilde *)pd_new(vd_tilde_tilde_class);
+
+ if(!*s->s_name)
+ s = gensym("vd~~");
+ x->x_sym = s;
+ x->x_sr = 1;
+ x->x_zerodel = 0;
+ inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal);
+ outlet_new(&x->x_obj, &s_signal);
+ x->x_f = 0;
+ return (x);
+}
+
+static t_int *vd_tilde_tilde_perform(t_int *w)
+{
+ t_sample *cin = (t_sample *)(w[1]);
+ t_sample *fin = (t_sample *)(w[2]);
+ t_sample *out = (t_sample *)(w[3]);
+ t_delwrite_tilde_tilde_ctl *ctl = (t_delwrite_tilde_tilde_ctl *)(w[4]);
+ t_vd_tilde_tilde *x = (t_vd_tilde_tilde *)(w[5]);
+ int n = (int)(w[6]);
+
+ int nsamps = ctl->c_n;
+ double limit = (double)nsamps - (double)n - 1.0;
+ t_sample fn = n-1;
+ t_sample *vp = ctl->c_vec, *bp, *wp = vp + ctl->c_phase;
+ t_sample zerodel = x->x_zerodel;
+ while (n--)
+ {
+ double delsamps = (double)x->x_sr * iem_dp_calc_sum(*cin++, *fin++) - (double)zerodel;
+ t_sample frac;
+ int idelsamps;
+ t_sample a, b, c, d, cminusb;
+
+ if(delsamps < 1.00001)
+ delsamps = 1.00001;
+ if(delsamps > limit)
+ delsamps = limit;
+ delsamps += (double)fn;
+ fn = fn - 1.0f;
+ idelsamps = (int)delsamps;
+ frac = (t_sample)(delsamps - (double)idelsamps);
+ bp = wp - idelsamps;
+ if(bp < vp + 4)
+ bp += nsamps;
+ d = bp[-3];
+ c = bp[-2];
+ b = bp[-1];
+ a = bp[0];
+ cminusb = c - b;
+ *out++ = b + frac * ( cminusb - 0.1666667f * (1.-frac) *
+ ( (d - a - 3.0f * cminusb) * frac + (d + 2.0f*a - 3.0f*b) ) );
+ }
+ return (w+7);
+}
+
+static void vd_tilde_tilde_dsp(t_vd_tilde_tilde *x, t_signal **sp)
+{
+ t_delwrite_tilde_tilde *delwriter = (t_delwrite_tilde_tilde *)pd_findbyclass(x->x_sym, delwrite_tilde_tilde_class);
+ x->x_sr = sp[0]->s_sr * 0.001;
+ if(delwriter)
+ {
+ delwrite_tilde_tilde_checkvecsize(delwriter, sp[0]->s_n);
+ x->x_zerodel = (delwriter->x_sortno == ugen_getsortno() ?
+ 0 : delwriter->x_vecsize);
+ dsp_add(vd_tilde_tilde_perform, 6, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec,
+ &delwriter->x_cspace, x, sp[0]->s_n);
+ }
+ else
+ error("vd~~: %s: no such delwrite~~", x->x_sym->s_name);
+}
+
+static void vd_tilde_tilde_setup(void)
+{
+ vd_tilde_tilde_class = class_new(gensym("vd~~"), (t_newmethod)vd_tilde_tilde_new, 0,
+ sizeof(t_vd_tilde_tilde), 0, A_DEFSYM, 0);
+ class_addmethod(vd_tilde_tilde_class, (t_method)vd_tilde_tilde_dsp, gensym("dsp"), 0);
+ CLASS_MAINSIGNALIN(vd_tilde_tilde_class, t_vd_tilde_tilde, x_f);
+}
+
+/********************/
+
+void delay_tilde_tilde_setup(void)
+{
+ delwrite_tilde_tilde_setup();
+ delread_tilde_tilde_setup();
+ vd_tilde_tilde_setup();
+} \ No newline at end of file