aboutsummaryrefslogtreecommitdiff
path: root/src/vline~~.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/vline~~.c')
-rwxr-xr-xsrc/vline~~.c220
1 files changed, 220 insertions, 0 deletions
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);
+}