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/vline~~.c | 220 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 220 insertions(+) create mode 100755 src/vline~~.c (limited to 'src/vline~~.c') diff --git a/src/vline~~.c b/src/vline~~.c new file mode 100755 index 0000000..204724d --- /dev/null +++ b/src/vline~~.c @@ -0,0 +1,220 @@ +/* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. + +iem_dp written by IOhannes m zmoelnig, Thomas Musil, Copyright (c) IEM KUG Graz Austria 1999 - 2007 */ +/* double precision library */ + +#include "m_pd.h" +#include "iemlib.h" +#include "iem_dp.h" + + +/* -------------------------- vline~~ ------------------------------ */ +/* based on miller's vline~ which is part of pd */ + +static t_class *vline_tilde_tilde_class; + +typedef struct _vseg_tt +{ + double s_targettime; + double s_starttime; + double s_target; + struct _vseg_tt *s_next; +} t_vseg_tt; + +typedef struct _vline_tilde_tilde +{ + t_object x_obj; + double x_value; + double x_inc; + double x_referencetime; + double x_samppermsec; + double x_msecpersamp; + double x_targettime; + double x_target; + t_float x_inlet2_fine_target; + t_float x_inlet3_coarse_ramp_duration; + t_float x_inlet4_fine_ramp_duration; + t_float x_inlet5_coarse_delay; + t_float x_inlet6_fine_delay; + t_vseg_tt *x_list; +} t_vline_tilde_tilde; + +static t_int *vline_tilde_tilde_perform(t_int *w) +{ + t_vline_tilde_tilde *x = (t_vline_tilde_tilde *)(w[1]); + t_float *out_float_cast = (t_float *)(w[2]); + t_float *out_residual = (t_float *)(w[3]); + t_float f_val; + int n = (int)(w[4]), i; + double d_val = x->x_value; + double inc = x->x_inc; + double msecpersamp = x->x_msecpersamp; + double samppermsec = x->x_samppermsec; + double timenow = clock_gettimesince(x->x_referencetime) - (double)n * msecpersamp; + t_vseg_tt *seg_list = x->x_list; + + for(i = 0; i < n; i++) + { + double timenext = timenow + msecpersamp; +checknext_tt: + if(seg_list) + { + /* has starttime elapsed? If so update value and increment */ + if(seg_list->s_starttime < timenext) + { + if(x->x_targettime <= timenext) + d_val = x->x_target, inc = 0; + /* if zero-length segment bash output value */ + if(seg_list->s_targettime <= seg_list->s_starttime) + { + d_val = seg_list->s_target; + inc = 0; + } + else + { + double incpermsec = (seg_list->s_target - d_val)/(seg_list->s_targettime - seg_list->s_starttime); + + d_val += incpermsec * (timenext - seg_list->s_starttime); + inc = incpermsec * msecpersamp; + } + x->x_inc = inc; + x->x_target = seg_list->s_target; + x->x_targettime = seg_list->s_targettime; + x->x_list = seg_list->s_next; + t_freebytes(seg_list, sizeof(*seg_list)); + seg_list = x->x_list; + goto checknext_tt; + } + } + if(x->x_targettime <= timenext) + { + d_val = x->x_target; + inc = x->x_inc = 0; + x->x_targettime = 1e20; + } + f_val = iem_dp_cast_to_float(d_val); + *out_residual++ = iem_dp_calc_residual(d_val, f_val); + *out_float_cast++ = f_val; + d_val += inc; + timenow = timenext; + } + x->x_value = d_val; + return (w+5); +} + +static void vline_tilde_tilde_stop(t_vline_tilde_tilde *x) +{ + t_vseg_tt *s1, *s2; + + for (s1 = x->x_list; s1; s1 = s2) + s2 = s1->s_next, t_freebytes(s1, sizeof(*s1)); + x->x_list = 0; + x->x_inc = 0; + x->x_inlet2_fine_target = x->x_inlet3_coarse_ramp_duration = 0; + x->x_inlet4_fine_ramp_duration = x->x_inlet5_coarse_delay = x->x_inlet6_fine_delay = 0; + x->x_target = x->x_value; + x->x_targettime = 1e20; +} + +static void vline_tilde_tilde_float(t_vline_tilde_tilde *x, t_float inlet1_coarse_target) /* coarse target value */ +{ + double timenow = clock_gettimesince(x->x_referencetime); + double inlet12_target = iem_dp_calc_sum(inlet1_coarse_target, x->x_inlet2_fine_target); + double inlet34_ramp_duration = iem_dp_calc_sum(x->x_inlet3_coarse_ramp_duration, x->x_inlet4_fine_ramp_duration); + double inlet56_delay = iem_dp_calc_sum(x->x_inlet5_coarse_delay, x->x_inlet6_fine_delay); + double starttime = timenow + inlet56_delay; + t_vseg_tt *s1, *s2, *deletefrom = 0, *snew; + + if(inlet34_ramp_duration < 0) + inlet34_ramp_duration = 0; + +/* if (PD_BIGORSMALL(inlet12_target)) + inlet12_target = 0; */ + + /* negative delay input means stop and jump immediately to new value */ + if (inlet56_delay < 0) + { + x->x_value = inlet12_target; + vline_tilde_tilde_stop(x); + return; + } + snew = (t_vseg_tt *)t_getbytes(sizeof(*snew)); + /* check if we supplant the first item in the list. We supplant + an item by having an earlier starttime, or an equal starttime unless + the equal one was instantaneous and the new one isn't (in which case + we'll do a jump-and-slide starting at that time.) */ + if (!x->x_list || x->x_list->s_starttime > starttime || + (x->x_list->s_starttime == starttime && + (x->x_list->s_targettime > x->x_list->s_starttime || inlet34_ramp_duration <= 0))) + { + deletefrom = x->x_list; + x->x_list = snew; + } + else + { + for (s1 = x->x_list; s2 = s1->s_next; s1 = s2) + { + if (s2->s_starttime > starttime || + (s2->s_starttime == starttime && + (s2->s_targettime > s2->s_starttime || inlet34_ramp_duration <= 0))) + { + deletefrom = s2; + s1->s_next = snew; + goto vl_didit_tt; + } + } + s1->s_next = snew; + deletefrom = 0; +vl_didit_tt: ; + } + while (deletefrom) + { + s1 = deletefrom->s_next; + t_freebytes(deletefrom, sizeof(*deletefrom)); + deletefrom = s1; + } + snew->s_next = 0; + snew->s_target = inlet12_target; + snew->s_starttime = starttime; + snew->s_targettime = starttime + inlet34_ramp_duration; + x->x_inlet3_coarse_ramp_duration = x->x_inlet4_fine_ramp_duration = 0; + x->x_inlet5_coarse_delay = x->x_inlet6_fine_delay = 0; +} + +static void vline_tilde_tilde_dsp(t_vline_tilde_tilde *x, t_signal **sp) +{ + dsp_add(vline_tilde_tilde_perform, 4, x, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n); + x->x_samppermsec = ((double)(sp[0]->s_sr)) / 1000.0; + x->x_msecpersamp = ((double)1000.0) / sp[0]->s_sr; +} + +static void *vline_tilde_tilde_new(t_floatarg init_val) +{ + t_vline_tilde_tilde *x = (t_vline_tilde_tilde *)pd_new(vline_tilde_tilde_class); + + outlet_new(&x->x_obj, gensym("signal")); + outlet_new(&x->x_obj, gensym("signal")); + floatinlet_new(&x->x_obj, &x->x_inlet2_fine_target); + floatinlet_new(&x->x_obj, &x->x_inlet3_coarse_ramp_duration); + floatinlet_new(&x->x_obj, &x->x_inlet4_fine_ramp_duration); + floatinlet_new(&x->x_obj, &x->x_inlet5_coarse_delay); + floatinlet_new(&x->x_obj, &x->x_inlet6_fine_delay); + x->x_inlet2_fine_target = x->x_inlet3_coarse_ramp_duration = 0; + x->x_inlet4_fine_ramp_duration = x->x_inlet5_coarse_delay = x->x_inlet6_fine_delay = 0; + x->x_value = x->x_inc = 0; + x->x_referencetime = clock_getlogicaltime(); + x->x_list = 0; + x->x_samppermsec = 0; + x->x_targettime = 1e20; + return (x); +} + +void vline_tilde_tilde_setup(void) +{ + vline_tilde_tilde_class = class_new(gensym("vline~~"), (t_newmethod)vline_tilde_tilde_new, + (t_method)vline_tilde_tilde_stop, sizeof(t_vline_tilde_tilde), 0, 0); + class_addfloat(vline_tilde_tilde_class, (t_method)vline_tilde_tilde_float); + class_addmethod(vline_tilde_tilde_class, (t_method)vline_tilde_tilde_dsp, gensym("dsp"), 0); + class_addmethod(vline_tilde_tilde_class, (t_method)vline_tilde_tilde_stop, gensym("stop"), 0); +} -- cgit v1.2.1