/* For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. iem_t3_lib written by Gerhard Eckel, Thomas Musil, Copyright (c) IEM KUG Graz Austria 2000 - 2006 */ #include "m_pd.h" #include "iemlib.h" /* -------------------------- t3_line~ ------------------------------ */ static t_class *t3_line_tilde_class; typedef struct _t3_line_tilde { t_object x_obj; t_clock *x_clock; t_float *x_beg; double x_cur_val; double x_dst_val; double x_inlet_val; double x_inc64; double x_inc; double x_ms2samps; double x_ticks2ms; double x_inlet_time; double x_dst_time; int x_cur_samps; int x_dur_samps; int x_n; int x_t3_bang_samps; int x_transient; } t_t3_line_tilde; static void t3_line_tilde_nontransient(t_float *vec, t_t3_line_tilde *x, int n) { int cur_samps = x->x_cur_samps, i; double inc = x->x_inc; double cur_val = x->x_cur_val; if(cur_samps) { if(cur_samps > n) { x->x_cur_samps -= n; while(n--) { cur_val += inc; *vec++ = (t_float)cur_val; } x->x_cur_val += x->x_inc64; } else if(cur_samps == n) { x->x_cur_samps = 0; while(n--) { cur_val += inc; *vec++ = (t_float)cur_val; } x->x_cur_val = x->x_dst_val; } else { for(i=0; ix_cur_val = cur_val = x->x_dst_val; for(i=cur_samps; ix_cur_samps = 0; } } else { while(n--) *vec++ = (t_float)cur_val; } } static t_int *t3_line_tilde_perform(t_int *w) { t_float *out = (t_float *)(w[1]); t_t3_line_tilde *x = (t_t3_line_tilde *)(w[2]); int n = (int)(w[3]); if(x->x_transient) { t_float *trans = x->x_beg; while(n--) *out++ = *trans++; x->x_transient = 0; } else t3_line_tilde_nontransient(out, x, n); return(w+4); } static void t3_line_tilde_tick(t_t3_line_tilde *x) { t_float *trans = x->x_beg; int n = x->x_n, t3_bang_samps, cur_samps, i; double inc, cur_val; if(!x->x_transient) t3_line_tilde_nontransient(trans, x, n); t3_bang_samps = x->x_t3_bang_samps; x->x_dst_val = x->x_inlet_val; if(x->x_inlet_time <= 0.0) { x->x_inlet_time = 0.0; x->x_dst_time = 0.0; x->x_dur_samps = 0; x->x_cur_samps = 0; cur_val = x->x_cur_val = x->x_dst_val; for(i=t3_bang_samps; ix_dst_time = x->x_inlet_time; x->x_inlet_time = 0.0; cur_samps = (int)(x->x_dst_time * x->x_ms2samps); if(!cur_samps) cur_samps = 1; x->x_dur_samps = cur_samps; x->x_cur_samps = cur_samps; cur_val = x->x_cur_val = (double)trans[t3_bang_samps]; inc = x->x_inc = (x->x_dst_val - cur_val)/(double)cur_samps; x->x_inc64 = (double)x->x_n * inc; diff = n - t3_bang_samps; if(cur_samps > diff) { for(i=t3_bang_samps; ix_cur_val += (double)diff * inc; x->x_cur_samps -= diff; } else if(cur_samps == diff) { for(i=t3_bang_samps; ix_cur_val = x->x_dst_val; x->x_cur_samps = 0; } else { end = t3_bang_samps + cur_samps; for(i=t3_bang_samps; ix_cur_val = x->x_dst_val; x->x_cur_samps = 0; for(i=end; ix_transient = 1; } static void t3_line_tilde_list(t_t3_line_tilde *x, t_symbol *s, int ac, t_atom *av) { if((ac >= 2)&&IS_A_FLOAT(av,0)&&IS_A_FLOAT(av,1)) { int t3_bang_samps, ticks; double time; x->x_inlet_val = (double)atom_getfloatarg(1, ac, av); t3_bang_samps = (int)((t_float)atom_getfloatarg(0, ac, av)*x->x_ms2samps); if(t3_bang_samps < 0) t3_bang_samps = 0; ticks = t3_bang_samps / x->x_n; x->x_t3_bang_samps = t3_bang_samps - x->x_n * ticks; if((ac >= 3)&&IS_A_FLOAT(av,2)) { time = (double)atom_getfloatarg(2, ac, av); if(time < 0.0) time = 0.0; x->x_inlet_time = time; } if(ticks < 1) t3_line_tilde_tick(x); else clock_delay(x->x_clock, (double)ticks * x->x_ticks2ms); } } static void t3_line_tilde_ft1(t_t3_line_tilde *x, t_float time) { if(time < 0.0) time = 0.0; x->x_inlet_time = (double)time; } static void t3_line_tilde_stop(t_t3_line_tilde *x) { clock_unset(x->x_clock); x->x_cur_samps = x->x_dur_samps = x->x_transient = 0; x->x_inc = x->x_inc64 = x->x_inlet_time = x->x_dst_time = 0.0; } static void t3_line_tilde_dsp(t_t3_line_tilde *x, t_signal **sp) { int i; t_float val, *trans; if(sp[0]->s_n > x->x_n) { freebytes(x->x_beg, x->x_n*sizeof(t_float)); x->x_n = (int)sp[0]->s_n; x->x_beg = (t_float *)getbytes(x->x_n*sizeof(t_float)); } else x->x_n = (int)sp[0]->s_n; i = x->x_n; val = x->x_cur_val; trans = x->x_beg; while(i--) *trans++ = val; x->x_ms2samps = 0.001*(double)sp[0]->s_sr; x->x_ticks2ms = (double)x->x_n / x->x_ms2samps; dsp_add(t3_line_tilde_perform, 3, sp[0]->s_vec, x, sp[0]->s_n); } static void t3_line_tilde_free(t_t3_line_tilde *x) { if(x->x_beg) freebytes(x->x_beg, x->x_n*sizeof(t_float)); clock_free(x->x_clock); } static void *t3_line_tilde_new(t_floatarg init_val) { t_t3_line_tilde *x = (t_t3_line_tilde *)pd_new(t3_line_tilde_class); int i; x->x_n = (int)sys_getblksize(); x->x_beg = (t_float *)getbytes(x->x_n*sizeof(t_float)); x->x_inlet_val = x->x_cur_val = x->x_dst_val = init_val; x->x_t3_bang_samps = x->x_cur_samps = x->x_dur_samps = x->x_transient = 0; x->x_inlet_time = x->x_dst_time = 0.0; x->x_inc64 = x->x_inc = 0.0; x->x_ms2samps = 0.001 * (double)sys_getsr(); x->x_ticks2ms = (double)x->x_n / x->x_ms2samps; x->x_clock = clock_new(x, (t_method)t3_line_tilde_tick); outlet_new(&x->x_obj, &s_signal); inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("ft1")); return (x); } void t3_line_tilde_setup(void) { t3_line_tilde_class = class_new(gensym("t3_line~"), (t_newmethod)t3_line_tilde_new, (t_method)t3_line_tilde_free, sizeof(t_t3_line_tilde), 0, A_DEFFLOAT, 0); class_addmethod(t3_line_tilde_class, (t_method)t3_line_tilde_dsp, gensym("dsp"), 0); class_addmethod(t3_line_tilde_class, (t_method)t3_line_tilde_stop, gensym("stop"), 0); class_addmethod(t3_line_tilde_class, (t_method)t3_line_tilde_ft1, gensym("ft1"), A_FLOAT, 0); class_addlist(t3_line_tilde_class, (t_method)t3_line_tilde_list); // class_sethelpsymbol(t3_line_tilde_class, gensym("iemhelp/help-t3_line~")); }