From a7e6303e3e7e87bf90b21821d2e419ed4799783c Mon Sep 17 00:00:00 2001 From: musil Date: Fri, 28 Jun 2013 17:25:22 +0000 Subject: initial check in of double precision library of iem svn path=/trunk/externals/iem/iem_dp/; revision=17167 --- src/delay~~.c | 390 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 390 insertions(+) create mode 100755 src/delay~~.c (limited to 'src/delay~~.c') 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 -- cgit v1.2.1