aboutsummaryrefslogtreecommitdiff
path: root/cyclone/sickle/vectral.c
diff options
context:
space:
mode:
Diffstat (limited to 'cyclone/sickle/vectral.c')
-rw-r--r--cyclone/sickle/vectral.c235
1 files changed, 235 insertions, 0 deletions
diff --git a/cyclone/sickle/vectral.c b/cyclone/sickle/vectral.c
new file mode 100644
index 0000000..b9cdf69
--- /dev/null
+++ b/cyclone/sickle/vectral.c
@@ -0,0 +1,235 @@
+/* Copyright (c) 2002-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 "m_pd.h"
+#include "sickle/sic.h"
+
+#define VECTRAL_DEFSIZE 512
+
+struct _vectral;
+typedef void (*t_vectral_perform)(struct _vectral *, int,
+ t_float *, t_float *, t_float *, t_float *);
+
+typedef struct _vectral
+{
+ t_sic x_sic;
+ t_vectral_perform x_perform;
+ int x_bufsize;
+ t_float *x_buffer;
+ t_float *x_lastframe;
+ /* rampsmooth and slide state */
+ double x_upcoef;
+ double x_downcoef;
+ /* deltaclip state */
+ float x_lo;
+ float x_hi;
+} t_vectral;
+
+static t_class *vectral_class;
+
+/* LATER after any modification make sure about syncing other variants
+ of perform routine to the bypassing version */
+/* this is: for i in [0..nblock) buf[in2[i]] = in3[i], out[i] = buf[in1[i]] */
+static void vectral_perform_bypass(t_vectral *x, int nblock,
+ t_float *in1, t_float *in2, t_float *in3,
+ t_float *out)
+{
+ t_float *buf = x->x_buffer;
+ int bufsize = x->x_bufsize;
+ t_float *last = x->x_lastframe;
+ int blocksize = nblock;
+ while (nblock--)
+ {
+ int indx = (int)*in2++;
+ /* CHECKED buffer not zeroed out (the buffer's garbage remains) */
+ if (indx >= 0 && indx < bufsize)
+ buf[indx] = *in3;
+ in3++;
+ }
+ while (blocksize--)
+ {
+ int ondx = (int)*in1++;
+ if (ondx >= 0 && ondx < bufsize)
+ *out++ = *last++ = buf[ondx];
+ else
+ /* CHECKED garbage in the output vector is cleared */
+ *out++ = *last++ = 0.;
+ }
+}
+
+/* this one is used for rampsmooth mode as well (see rampsmooth.c)
+ LATER recheck */
+static void vectral_perform_slide(t_vectral *x, int nblock,
+ t_float *in1, t_float *in2, t_float *in3,
+ t_float *out)
+{
+ t_float *buf = x->x_buffer;
+ int bufsize = x->x_bufsize;
+ double upcoef = x->x_upcoef;
+ double downcoef = x->x_downcoef;
+ t_float *last = x->x_lastframe;
+ int blocksize = nblock;
+ while (nblock--)
+ {
+ int indx = (int)*in2++;
+ if (indx >= 0 && indx < bufsize)
+ buf[indx] = *in3;
+ in3++;
+ }
+ while (blocksize--)
+ {
+ int ondx = (int)*in1++;
+ if (ondx >= 0 && ondx < bufsize)
+ {
+ /* CHECKME what is smoothed, and FIXME */
+ float delta = buf[ondx] - *last;
+ *out++ =
+ (*last++ += (delta > 0 ? delta * upcoef : delta * downcoef));
+ }
+ else *out++ = *last++ = 0.;
+ }
+}
+
+static void vectral_perform_clip(t_vectral *x, int nblock,
+ t_float *in1, t_float *in2, t_float *in3,
+ t_float *out)
+{
+ t_float *buf = x->x_buffer;
+ int bufsize = x->x_bufsize;
+ float lo = x->x_lo;
+ float hi = x->x_hi;
+ t_float *last = x->x_lastframe;
+ int blocksize = nblock;
+ while (nblock--)
+ {
+ int indx = (int)*in2++;
+ if (indx >= 0 && indx < bufsize)
+ buf[indx] = *in3;
+ in3++;
+ }
+ while (blocksize--)
+ {
+ int ondx = (int)*in1++;
+ if (ondx >= 0 && ondx < bufsize)
+ {
+ /* CHECKME what is smoothed, and FIXME */
+ float delta = buf[ondx] - *last;
+ if (delta < lo)
+ *out++ = (*last++ += lo);
+ else if (delta > hi)
+ *out++ = (*last++ += hi);
+ else
+ *out++ = *last++ = buf[ondx];
+ }
+ else *out++ = *last++ = 0.;
+ }
+}
+
+static t_int *vectral_perform(t_int *w)
+{
+ t_vectral *x = (t_vectral *)(w[1]);
+ (*x->x_perform)(x, (int)(w[2]), (t_float *)(w[3]), (t_float *)(w[4]),
+ (t_float *)(w[5]), (t_float *)(w[6]));
+ return (w + 7);
+}
+
+static void vectral_dsp(t_vectral *x, t_signal **sp)
+{
+ int nblock = sp[0]->s_n;
+ if (nblock > x->x_bufsize)
+ nblock = x->x_bufsize; /* CHECKME */
+ dsp_add(vectral_perform, 6, x, nblock,
+ sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec);
+}
+
+static void vectral_rampsmooth(t_vectral *x, t_symbol *s, int ac, t_atom *av)
+{
+ if (ac && av->a_type == A_FLOAT)
+ {
+ int i;
+ x->x_upcoef = ((i = (int)av->a_w.w_float) > 1 ? 1. / (double)i : 1.);
+ ac--; av++;
+ if (ac && av->a_type == A_FLOAT)
+ x->x_downcoef =
+ ((i = (int)av->a_w.w_float) > 1 ? 1. / (double)i : 1.);
+ else
+ x->x_downcoef = 1.; /* CHECKED */
+ x->x_perform = vectral_perform_slide; /* see above */
+ }
+ else x->x_perform = vectral_perform_bypass; /* CHECKED */
+}
+
+static void vectral_slide(t_vectral *x, t_symbol *s, int ac, t_atom *av)
+{
+ if (ac && av->a_type == A_FLOAT)
+ {
+ double d;
+ x->x_upcoef = ((d = av->a_w.w_float) > 1. ? 1. / d : 1.);
+ ac--; av++;
+ if (ac && av->a_type == A_FLOAT)
+ x->x_downcoef = ((d = av->a_w.w_float) > 1. ? 1. / d : 1.);
+ else
+ x->x_downcoef = 1.; /* CHECKED */
+ x->x_perform = vectral_perform_slide;
+ }
+ else x->x_perform = vectral_perform_bypass; /* CHECKED */
+}
+
+/* CHECKED 'deltaclip <hi> <lo>' (deltaclip~'s args are swapped) */
+static void vectral_deltaclip(t_vectral *x, t_symbol *s, int ac, t_atom *av)
+{
+ if (ac && av->a_type == A_FLOAT)
+ {
+ x->x_hi = av->a_w.w_float;
+ ac--; av++;
+ if (ac && av->a_type == A_FLOAT)
+ x->x_lo = av->a_w.w_float;
+ else
+ x->x_lo = 0.; /* CHECKED */
+ }
+ else x->x_lo = x->x_hi = 0.; /* CHECKED */
+ x->x_perform = vectral_perform_clip;
+}
+
+static void vectral_free(t_vectral *x)
+{
+ if (x->x_buffer)
+ freebytes(x->x_buffer, x->x_bufsize * sizeof(*x->x_buffer));
+ if (x->x_lastframe)
+ freebytes(x->x_lastframe, x->x_bufsize * sizeof(*x->x_lastframe));
+}
+
+static void *vectral_new(t_floatarg f)
+{
+ t_vectral *x = (t_vectral *)pd_new(vectral_class);
+ int i = (int)f;
+ x->x_bufsize = (i > 0 ? i : VECTRAL_DEFSIZE);
+ if (!(x->x_buffer = getbytes(x->x_bufsize * sizeof(*x->x_buffer))))
+ goto failure;
+ if (!(x->x_lastframe = getbytes(x->x_bufsize * sizeof(*x->x_lastframe))))
+ goto failure;
+ x->x_perform = vectral_perform_bypass;
+ inlet_new((t_object *)x, (t_pd *)x, &s_signal, &s_signal);
+ inlet_new((t_object *)x, (t_pd *)x, &s_signal, &s_signal);
+ outlet_new((t_object *)x, &s_signal);
+ return (x);
+failure:
+ pd_free((t_pd *)x);
+ return (0);
+}
+
+void vectral_tilde_setup(void)
+{
+ vectral_class = class_new(gensym("vectral~"),
+ (t_newmethod)vectral_new,
+ (t_method)vectral_free,
+ sizeof(t_vectral), 0, A_DEFFLOAT, 0);
+ sic_setup(vectral_class, vectral_dsp, SIC_FLOATTOSIGNAL);
+ class_addmethod(vectral_class, (t_method)vectral_rampsmooth,
+ gensym("rampsmooth"), A_GIMME, 0);
+ class_addmethod(vectral_class, (t_method)vectral_slide,
+ gensym("slide"), A_GIMME, 0);
+ class_addmethod(vectral_class, (t_method)vectral_deltaclip,
+ gensym("deltaclip"), A_GIMME, 0);
+}