aboutsummaryrefslogtreecommitdiff
path: root/source/prevl.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/prevl.c')
-rw-r--r--source/prevl.c161
1 files changed, 161 insertions, 0 deletions
diff --git a/source/prevl.c b/source/prevl.c
new file mode 100644
index 0000000..2ba39ce
--- /dev/null
+++ b/source/prevl.c
@@ -0,0 +1,161 @@
+#include "defines.h"
+
+/*--------------- prevl ---------------*/
+
+static t_class *prevl_class;
+
+typedef struct _prevl
+{
+ t_object x_obj;
+ float m_lo;
+ float m_hi;
+ int m_buffer_size;
+ int m_buffer_index;
+ float *m_buffer; // circular buffer
+} t_prevl;
+
+
+static void prevl_perform_float(t_prevl *x, t_float f)
+{
+ int index;
+ index=x->m_buffer_index+1;
+ index=(index==x->m_buffer_size)?0:index;
+ x->m_buffer_index=index;
+ x->m_buffer[index]=f;
+}
+
+static void prevl_bang(t_prevl *x)
+{
+ int lo,hi,n,index,size;
+ t_atom *ap,*app;
+ float *buffer, *bp;
+
+ lo=(int)x->m_lo;
+ hi=(int)x->m_hi;
+
+ n=hi-lo;
+ size=x->m_buffer_size;
+ index=x->m_buffer_index;
+ ap = (t_atom *)getbytes(sizeof(t_atom)*n);
+ app=ap;
+ buffer=x->m_buffer;
+ bp=buffer+index-lo;
+ bp=(bp>=buffer)?bp:bp+size; // wrap
+
+ if (bp-buffer>=n)
+ { // no wrap-around needed
+ index=n;
+ while(index--){
+ SETFLOAT(app, *bp--);
+ app++;
+ }
+// post("not wrapped, app-ap=%i",app-ap);
+ }
+ else // need to wrap
+ {
+ int ps, nn;
+ ps = bp-buffer;
+ nn=n;
+// post(" nn=%i",nn);
+ for(;ps>=0;ps--) // don't we miss one sample in signal???
+ {
+// post("ps=%i",ps);
+ SETFLOAT(app, buffer[ps]);
+ app++;
+ nn--;
+ }
+ ps=size-1;
+// post(" nn=%i",nn);
+ for(;nn>0;nn--)
+ {
+// post("ps=%i",ps);
+ SETFLOAT(app, buffer[ps--]);
+ app++;
+ }
+
+ }
+
+ outlet_list(x->x_obj.ob_outlet,gensym("list"),n,ap);
+ freebytes(ap, sizeof(t_atom)*n);
+}
+
+static void prevl_clear(t_prevl *x)
+{
+ int i,s;
+ float *f;
+ f=x->m_buffer;
+ s=x->m_buffer_size;
+ for (i=0;i<s;i++)
+ *f++=0.0f;
+}
+
+static void prevl_set(t_prevl *x, t_float lo, t_float hi, t_float size)
+{
+ if (size<1)
+ {
+ size=1;
+ post("prevl: size is minimum 1...");
+ }
+ if (hi>size)
+ {
+ post("prevl: higher bound cannot be higher than the buffer size...");
+ hi=size;
+ }
+ if (lo<0)
+ {
+ post("prevl: lower bound cannot be negative...");
+ lo=0;
+ }
+ if (hi<1)
+ {
+ post("prevl: higher bound cannot be smaller than one...");
+ hi=1;
+ }
+ if (hi<=lo)
+ {
+ post("prevl: higher bound must be higher than lower bound...");
+ lo=hi-1.0f;
+ }
+
+ freebytes(x->m_buffer, x->m_buffer_size);
+
+ x->m_hi=(float)((int)hi);
+ x->m_lo=(float)((int)lo);
+ x->m_buffer_size=(int)size;
+ x->m_buffer = (float*)getbytes(sizeof(float)*x->m_buffer_size);
+ prevl_clear(x);
+ x->m_buffer_index=0;
+}
+
+static void *prevl_new(t_float lo, t_float hi, t_float size)
+{
+ t_prevl *x=(t_prevl *)pd_new(prevl_class);
+ outlet_new(&x->x_obj, gensym("list"));
+ x->m_buffer_size=0;
+ x->m_buffer=0;
+ prevl_set(x, lo, hi, size);
+
+ floatinlet_new(&x->x_obj, &x->m_lo);
+ floatinlet_new(&x->x_obj, &x->m_hi);
+
+ return (void *)x;
+}
+
+static void prevl_free(t_prevl *x)
+{
+ freebytes(x->m_buffer, x->m_buffer_size);
+}
+
+void prevl_setup(void)
+{
+ prevl_class = class_new(gensym("prevl"),
+ (t_newmethod)prevl_new, (t_method)prevl_free,
+ sizeof(t_prevl),
+ CLASS_DEFAULT,
+ A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT,0);
+
+ class_addmethod(prevl_class, (t_method)prevl_clear, gensym("clear"),0);
+ class_addfloat(prevl_class, (t_method)prevl_perform_float);
+ class_addbang(prevl_class, (t_method)prevl_bang);
+}
+