aboutsummaryrefslogtreecommitdiff
path: root/source/deltas.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/deltas.c')
-rw-r--r--source/deltas.c181
1 files changed, 181 insertions, 0 deletions
diff --git a/source/deltas.c b/source/deltas.c
new file mode 100644
index 0000000..edc3cb0
--- /dev/null
+++ b/source/deltas.c
@@ -0,0 +1,181 @@
+#include "defines.h"
+
+/*--------------- deltas ---------------*/
+
+static t_class *deltas_class;
+
+typedef struct _deltas
+{
+ t_object x_obj;
+ float m_lo;
+ float m_hi;
+ int m_buffer_size;
+ int m_buffer_index;
+ float *m_buffer; // circular buffer
+} t_deltas;
+
+
+static void deltas_perform_float(t_deltas *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 deltas_bang(t_deltas *x)
+{
+ int lo,hi,n,index,size;
+ t_atom *ap,*app;
+ float last;
+ 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;
+ last=buffer[index];
+ 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, last-*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, last-buffer[ps]);
+ app++;
+ nn--;
+ }
+ ps=size-1;
+// post(" nn=%i",nn);
+ for(;nn>0;nn--)
+ {
+// post("ps=%i",ps);
+ SETFLOAT(app, last-buffer[ps--]);
+ app++;
+ }
+
+/*
+ int i2;
+ index=bp-buffer;
+ i2=index;
+ post("first part %i",index);
+ while(index--){
+ SETFLOAT(app, last-*bp--);
+ app++;
+ }
+ index=n-i2;
+ post("2nd part %i",index);
+ bp=buffer+size-1;
+ while(index--){
+ SETFLOAT(app, last-*bp--);
+ app++;
+ }
+*/
+// post("wrapped, app-ap=%i",app-ap);
+ }
+
+ outlet_list(x->x_obj.ob_outlet,gensym("list"),n,ap);
+ freebytes(ap, sizeof(t_atom)*n);
+}
+
+static void deltas_clear(t_deltas *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 deltas_set(t_deltas *x, t_float lo, t_float hi, t_float size)
+{
+ if (size<1)
+ {
+ size=1;
+ post("deltas: size is minimum 1...");
+ }
+ if (hi>size)
+ {
+ post("deltas: higher bound cannot be higher than the buffer size...");
+ hi=size;
+ }
+ if (lo<0)
+ {
+ post("deltas: lower bound cannot be negative...");
+ lo=0;
+ }
+ if (hi<1)
+ {
+ post("deltas: higher bound cannot be smaller than one...");
+ hi=1;
+ }
+ if (hi<=lo)
+ {
+ post("deltas: 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);
+ deltas_clear(x);
+ x->m_buffer_index=0;
+}
+
+static void *deltas_new(t_float lo, t_float hi, t_float size)
+{
+ t_deltas *x=(t_deltas *)pd_new(deltas_class);
+ outlet_new(&x->x_obj, gensym("list"));
+ x->m_buffer_size=0;
+ x->m_buffer=0;
+ deltas_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 deltas_free(t_deltas *x)
+{
+ freebytes(x->m_buffer, x->m_buffer_size);
+}
+
+void deltas_setup(void)
+{
+ deltas_class = class_new(gensym("deltas"),
+ (t_newmethod)deltas_new, (t_method)deltas_free,
+ sizeof(t_deltas),
+ CLASS_DEFAULT,
+ A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT,0);
+
+ class_addmethod(deltas_class, (t_method)deltas_clear, gensym("clear"),0);
+ class_addfloat(deltas_class, (t_method)deltas_perform_float);
+ class_addbang(deltas_class, (t_method)deltas_bang);
+}
+