aboutsummaryrefslogtreecommitdiff
path: root/cyclone/sickle/buffir.c
diff options
context:
space:
mode:
authorN.N. <krzyszcz@users.sourceforge.net>2003-09-05 10:03:46 +0000
committerN.N. <krzyszcz@users.sourceforge.net>2003-09-05 10:03:46 +0000
commit53f05d96ff8e49c87977fa91a06ebade8893606e (patch)
tree51bd07eb57c532e61515fb85a0fcd83698054854 /cyclone/sickle/buffir.c
parent672477f94d2d0701f75f2546ad79980dc9ac8543 (diff)
*** empty log message ***
svn path=/trunk/externals/miXed/; revision=931
Diffstat (limited to 'cyclone/sickle/buffir.c')
-rw-r--r--cyclone/sickle/buffir.c213
1 files changed, 213 insertions, 0 deletions
diff --git a/cyclone/sickle/buffir.c b/cyclone/sickle/buffir.c
new file mode 100644
index 0000000..0551501
--- /dev/null
+++ b/cyclone/sickle/buffir.c
@@ -0,0 +1,213 @@
+/* Copyright (c) 2003 krzYszcz and others.
+ * For information on usage and redistribution, and for a DISCLAIMER OF ALL
+ * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
+
+#include <string.h>
+#include "m_pd.h"
+#include "common/loud.h"
+#include "sickle/sic.h"
+#include "sickle/arsic.h"
+
+#define BUFFIR_DEFSIZE 0 /* CHECKED */
+#define BUFFIR_MAXSIZE 128
+
+typedef struct _buffir
+{
+ t_arsic x_arsic;
+ t_pd *x_offinlet;
+ t_pd *x_sizinlet;
+ t_float *x_lohead;
+ t_float *x_hihead;
+ int x_histsize;
+ t_float *x_histlo;
+ t_float *x_histhi;
+ t_float x_histini[2 * BUFFIR_MAXSIZE];
+} t_buffir;
+
+static t_class *buffir_class;
+
+static void buffir_setrange(t_buffir *x, t_floatarg f1, t_floatarg f2)
+{
+ int off = (int)f1;
+ int siz = (int)f2;
+ if (off < 0)
+ off = 0;
+ if (siz <= 0)
+ siz = BUFFIR_DEFSIZE;
+ if (siz > x->x_histsize)
+ {
+ int newsize, pos = x->x_lohead - x->x_histlo;
+ int oldbytes = x->x_histsize * sizeof(*x->x_histlo);
+ static int warned = 0;
+ if (!warned)
+ {
+ loud_incompatible(buffir_class, "stretching history buffer");
+ warned = 1;
+ }
+ newsize = x->x_histsize * 2;
+ while (newsize < siz) newsize *= 2;
+ if (x->x_histlo == x->x_histini)
+ {
+ if (!(x->x_histlo = getbytes(2 * newsize * sizeof(*x->x_histlo))))
+ x->x_histlo = x->x_histini;
+ else
+ {
+ x->x_histhi = x->x_histlo + newsize;
+ memcpy(x->x_histhi + pos - x->x_histsize,
+ x->x_lohead, oldbytes);
+ x->x_lohead = x->x_histlo + pos;
+ x->x_hihead = x->x_histhi + pos;
+ x->x_histsize = newsize;
+ }
+ }
+ else
+ {
+ if (!(x->x_histlo =
+ resizebytes(x->x_histlo, 2 * oldbytes,
+ 2 * newsize * sizeof(*x->x_histlo))))
+ {
+ x->x_histsize = BUFFIR_MAXSIZE;
+ x->x_histlo = x->x_histini;
+ memset(x->x_histlo, 0,
+ 2 * x->x_histsize * sizeof(*x->x_histlo));
+ x->x_lohead = x->x_histlo;
+ x->x_hihead = x->x_histhi = x->x_histlo + x->x_histsize;
+ }
+ else
+ {
+ x->x_histhi = x->x_histlo + newsize;
+ memcpy(x->x_histhi + pos - x->x_histsize,
+ x->x_lohead, oldbytes);
+ x->x_lohead = x->x_histlo + pos;
+ x->x_hihead = x->x_histhi + pos;
+ x->x_histsize = newsize;
+ }
+ }
+ }
+ pd_float(x->x_offinlet, off);
+ pd_float(x->x_sizinlet, siz);
+}
+
+static void buffir_clear(t_buffir *x)
+{
+ memset(x->x_histlo, 0, 2 * x->x_histsize * sizeof(*x->x_histlo));
+ x->x_lohead = x->x_histlo;
+ x->x_hihead = x->x_histhi = x->x_histlo + x->x_histsize;
+}
+
+static void buffir_set(t_buffir *x, t_symbol *s, t_floatarg f1, t_floatarg f2)
+{
+ arsic_setarray((t_arsic *)x, s, 1);
+ buffir_setrange(x, f1, f2);
+}
+
+static t_int *buffir_perform(t_int *w)
+{
+ t_arsic *sic = (t_arsic *)(w[1]);
+ t_buffir *x = (t_buffir *)sic;
+ int nblock = (int)(w[2]);
+ t_float *xin = (t_float *)(w[3]);
+ t_float *out = (t_float *)(w[6]);
+ t_float *lohead = x->x_lohead;
+ t_float *hihead = x->x_hihead;
+ if (sic->s_playable)
+ {
+ t_float *oin = (t_float *)(w[4]);
+ t_float *sin = (t_float *)(w[5]);
+ int vecsize = sic->s_vecsize;
+ t_float *vec = sic->s_vectors[0]; /* playable implies nonzero (mono) */
+ int histsize = x->x_histsize;
+ while (nblock--)
+ {
+ /* CHECKME every sample or once per block.
+ If once per block, then LATER think about performance. */
+ /* CHECKME rounding */
+ int off = (int)*oin++;
+ int npoints = (int)*sin++;
+ if (off < 0)
+ off = 0;
+ if (npoints > histsize)
+ npoints = histsize;
+ if (npoints > vecsize - off)
+ npoints = vecsize - off;
+ if (npoints > 0)
+ {
+ t_float *coefp = vec + off;
+ t_float *hp = hihead;
+ t_float sum = 0.;
+ *lohead++ = *hihead++ = *xin++;
+ while (npoints--)
+ sum += *coefp++ * *hp--;
+ *out++ = sum;
+ }
+ else
+ {
+ *lohead++ = *hihead++ = *xin++;
+ *out++ = 0.;
+ }
+ if (lohead >= x->x_histhi)
+ {
+ lohead = x->x_histlo;
+ hihead = x->x_histhi;
+ }
+ }
+ }
+ else while (nblock--)
+ {
+ *lohead++ = *hihead++ = *xin++;
+ *out++ = 0.;
+ if (lohead >= x->x_histhi)
+ {
+ lohead = x->x_histlo;
+ hihead = x->x_histhi;
+ }
+ }
+ x->x_lohead = lohead;
+ x->x_hihead = hihead;
+ return (w + 7);
+}
+
+static void buffir_dsp(t_buffir *x, t_signal **sp)
+{
+ arsic_dsp((t_arsic *)x, sp, buffir_perform, 1);
+}
+
+static void buffir_free(t_buffir *x)
+{
+ if (x->x_histlo != x->x_histini)
+ freebytes(x->x_histlo, 2 * x->x_histsize * sizeof(*x->x_histlo));
+ arsic_free((t_arsic *)x);
+}
+
+static void *buffir_new(t_symbol *s, t_floatarg f1, t_floatarg f2)
+{
+ /* CHECKME always the first channel used. */
+ /* three auxiliary signals: main, offset and size inputs */
+ t_buffir *x = (t_buffir *)arsic_new(buffir_class, s, 0, 0, 3);
+ if (x)
+ {
+ arsic_setminsize((t_arsic *)x, 1);
+ x->x_offinlet = (t_pd *)sic_newinlet((t_sic *)x, f1);
+ x->x_sizinlet = (t_pd *)sic_newinlet((t_sic *)x, f2);
+ outlet_new((t_object *)x, &s_signal);
+ x->x_histsize = BUFFIR_MAXSIZE;
+ x->x_histlo = x->x_histini;
+ buffir_clear(x);
+ buffir_setrange(x, f1, f2);
+ }
+ return (x);
+}
+
+void buffir_tilde_setup(void)
+{
+ buffir_class = class_new(gensym("buffir~"),
+ (t_newmethod)buffir_new,
+ (t_method)buffir_free,
+ sizeof(t_buffir), 0,
+ A_DEFSYM, A_DEFFLOAT, A_DEFFLOAT, 0);
+ arsic_setup(buffir_class, buffir_dsp, SIC_FLOATTOSIGNAL);
+ class_addmethod(buffir_class, (t_method)buffir_clear,
+ gensym("clear"), 0);
+ class_addmethod(buffir_class, (t_method)buffir_set,
+ gensym("set"), A_SYMBOL, A_DEFFLOAT, A_DEFFLOAT, 0);
+}