aboutsummaryrefslogtreecommitdiff
path: root/src/iemlib1/siglp1_t.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/iemlib1/siglp1_t.c')
-rw-r--r--src/iemlib1/siglp1_t.c219
1 files changed, 219 insertions, 0 deletions
diff --git a/src/iemlib1/siglp1_t.c b/src/iemlib1/siglp1_t.c
new file mode 100644
index 0000000..060d988
--- /dev/null
+++ b/src/iemlib1/siglp1_t.c
@@ -0,0 +1,219 @@
+/* For information on usage and redistribution, and for a DISCLAIMER OF ALL
+* WARRANTIES, see the file, "LICENSE.txt," in this distribution.
+
+iemlib1 written by Thomas Musil, Copyright (c) IEM KUG Graz Austria 2000 - 2003 */
+
+#ifdef NT
+#pragma warning( disable : 4244 )
+#pragma warning( disable : 4305 )
+#endif
+
+
+#include "m_pd.h"
+#include "iemlib.h"
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+
+
+/* -- lp1_t~ - slow dynamic lowpass-filter 1. order with tau input --- */
+
+typedef struct siglp1_t
+{
+ t_object x_obj;
+ float yn1;
+ float c0;
+ float c1;
+ float sr;
+ float cur_t;
+ float delta_t;
+ float end_t;
+ float ticks_per_interpol_time;
+ float rcp_ticks;
+ float interpol_time;
+ int ticks;
+ int counter_t;
+ float x_msi;
+} t_siglp1_t;
+
+t_class *siglp1_t_class;
+
+static void siglp1_t_dsp_tick(t_siglp1_t *x)
+{
+ if(x->counter_t)
+ {
+ if(x->counter_t <= 1)
+ {
+ x->cur_t = x->end_t;
+ x->counter_t = 0;
+ }
+ else
+ {
+ x->counter_t--;
+ x->cur_t += x->delta_t;
+ }
+ if(x->cur_t == 0.0f)
+ x->c1 = 0.0f;
+ else
+ x->c1 = exp((x->sr)/x->cur_t);
+ x->c0 = 1.0f - x->c1;
+ }
+}
+
+static t_int *siglp1_t_perform(t_int *w)
+{
+ float *in = (float *)(w[1]);
+ float *out = (float *)(w[2]);
+ t_siglp1_t *x = (t_siglp1_t *)(w[3]);
+ int i, n = (t_int)(w[4]);
+ float yn0, yn1=x->yn1;
+ float c0=x->c0, c1=x->c1;
+
+ siglp1_t_dsp_tick(x);
+ for(i=0; i<n; i++)
+ {
+ yn0 = (*in++)*c0 + yn1*c1;
+ *out++ = yn0;
+ yn1 = yn0;
+ }
+ /* NAN protect */
+ if(PD_BADFLOAT(yn1))
+ yn1 = 0.0f;
+ x->yn1 = yn1;
+ return(w+5);
+}
+
+static t_int *siglp1_t_perf8(t_int *w)
+{
+ float *in = (float *)(w[1]);
+ float *out = (float *)(w[2]);
+ t_siglp1_t *x = (t_siglp1_t *)(w[3]);
+ int i, n = (t_int)(w[4]);
+ float yn[9];
+ float c0=x->c0, c1=x->c1;
+
+ siglp1_t_dsp_tick(x);
+ yn[0] = x->yn1;
+ for(i=0; i<n; i+=8, in+=8, out+=8)
+ {
+ yn[1] = in[0]*c0 + yn[0]*c1;
+ out[0] = yn[1];
+ yn[2] = in[1]*c0 + yn[1]*c1;
+ out[1] = yn[2];
+ yn[3] = in[2]*c0 + yn[2]*c1;
+ out[2] = yn[3];
+ yn[4] = in[3]*c0 + yn[3]*c1;
+ out[3] = yn[4];
+ yn[5] = in[4]*c0 + yn[4]*c1;
+ out[4] = yn[5];
+ yn[6] = in[5]*c0 + yn[5]*c1;
+ out[5] = yn[6];
+ yn[7] = in[6]*c0 + yn[6]*c1;
+ out[6] = yn[7];
+ yn[8] = in[7]*c0 + yn[7]*c1;
+ out[7] = yn[8];
+ yn[0] = yn[8];
+ }
+ /* NAN protect */
+ if(PD_BADFLOAT(yn[0]))
+ yn[0] = 0.0f;
+
+ x->yn1 = yn[0];
+ return(w+5);
+}
+
+static void siglp1_t_ft2(t_siglp1_t *x, t_floatarg t)
+{
+ int i = (int)((x->ticks_per_interpol_time)*t);
+
+ x->interpol_time = t;
+ if(i <= 0)
+ i = 1;
+ x->ticks = i;
+ x->rcp_ticks = 1.0f / (float)i;
+}
+
+static void siglp1_t_ft1(t_siglp1_t *x, t_floatarg time_const)
+{
+ if(time_const < 0.0f)
+ time_const = 0.0f;
+ if(time_const != x->cur_t)
+ {
+ x->end_t = time_const;
+ x->counter_t = x->ticks;
+ x->delta_t = (time_const - x->cur_t) * x->rcp_ticks;
+ }
+}
+
+static void siglp1_t_dsp(t_siglp1_t *x, t_signal **sp)
+{
+ int i, n=(int)sp[0]->s_n;
+
+ x->sr = -1000.0f / (float)(sp[0]->s_sr);
+ x->ticks_per_interpol_time = 0.001f * (float)(sp[0]->s_sr) / (float)n;
+ i = (int)((x->ticks_per_interpol_time)*(x->interpol_time));
+ if(i <= 0)
+ i = 1;
+ x->ticks = i;
+ x->rcp_ticks = 1.0f / (float)i;
+ if(x->cur_t == 0.0f)
+ x->c1 = 0.0f;
+ else
+ x->c1 = exp((x->sr)/x->cur_t);
+ x->c0 = 1.0f - x->c1;
+ if(n&7)
+ dsp_add(siglp1_t_perform, 4, sp[0]->s_vec, sp[1]->s_vec, x, n);
+ else
+ dsp_add(siglp1_t_perf8, 4, sp[0]->s_vec, sp[1]->s_vec, x, n);
+}
+
+static void *siglp1_t_new(t_symbol *s, int argc, t_atom *argv)
+{
+ t_siglp1_t *x = (t_siglp1_t *)pd_new(siglp1_t_class);
+ int i;
+ float time_const=0.0f, interpol=0.0f;
+
+ inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("ft1"));
+ inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("ft2"));
+ outlet_new(&x->x_obj, &s_signal);
+ x->x_msi = 0;
+ x->counter_t = 1;
+ x->delta_t = 0.0f;
+ x->interpol_time = 0.0f;
+ x->yn1 = 0.0f;
+ x->sr = -1.0f / 44.1f;
+ if((argc >= 1)&&IS_A_FLOAT(argv,0))
+ time_const = (float)atom_getfloatarg(0, argc, argv);
+ if((argc >= 2)&&IS_A_FLOAT(argv,1))
+ interpol = (float)atom_getfloatarg(1, argc, argv);
+ if(time_const < 0.0f)
+ time_const = 0.0f;
+ x->cur_t = time_const;
+ if(time_const == 0.0f)
+ x->c1 = 0.0f;
+ else
+ x->c1 = exp((x->sr)/time_const);
+ x->c0 = 1.0f - x->c1;
+ if(interpol < 0.0f)
+ interpol = 0.0f;
+ x->interpol_time = interpol;
+ x->ticks_per_interpol_time = 0.5f;
+ i = (int)((x->ticks_per_interpol_time)*(x->interpol_time));
+ if(i <= 0)
+ i = 1;
+ x->ticks = i;
+ x->rcp_ticks = 1.0f / (float)i;
+ x->end_t = x->cur_t;
+ return (x);
+}
+
+void siglp1_t_setup(void)
+{
+ siglp1_t_class = class_new(gensym("lp1_t~"), (t_newmethod)siglp1_t_new,
+ 0, sizeof(t_siglp1_t), 0, A_GIMME, 0);
+ CLASS_MAINSIGNALIN(siglp1_t_class, t_siglp1_t, x_msi);
+ class_addmethod(siglp1_t_class, (t_method)siglp1_t_dsp, gensym("dsp"), 0);
+ class_addmethod(siglp1_t_class, (t_method)siglp1_t_ft1, gensym("ft1"), A_FLOAT, 0);
+ class_addmethod(siglp1_t_class, (t_method)siglp1_t_ft2, gensym("ft2"), A_FLOAT, 0);
+ class_sethelpsymbol(siglp1_t_class, gensym("iemhelp/help-lp1_t~"));
+}