aboutsummaryrefslogtreecommitdiff
path: root/cyclone/sickle
diff options
context:
space:
mode:
Diffstat (limited to 'cyclone/sickle')
-rw-r--r--cyclone/sickle/Clip.c59
-rw-r--r--cyclone/sickle/Line.c299
-rw-r--r--cyclone/sickle/Makefile3
-rw-r--r--cyclone/sickle/Makefile.objects11
-rw-r--r--cyclone/sickle/Makefile.sources67
-rw-r--r--cyclone/sickle/Scope.c1043
-rw-r--r--cyclone/sickle/Snapshot.c161
-rw-r--r--cyclone/sickle/abs.c42
-rw-r--r--cyclone/sickle/acos.c48
-rw-r--r--cyclone/sickle/acosh.c48
-rw-r--r--cyclone/sickle/allpass.c153
-rw-r--r--cyclone/sickle/allsickles.c134
-rw-r--r--cyclone/sickle/asin.c48
-rw-r--r--cyclone/sickle/asinh.c48
-rw-r--r--cyclone/sickle/atan.c48
-rw-r--r--cyclone/sickle/atan2.c53
-rw-r--r--cyclone/sickle/atanh.c48
-rw-r--r--cyclone/sickle/average.c194
-rw-r--r--cyclone/sickle/avg.c62
-rw-r--r--cyclone/sickle/bitand.c144
-rw-r--r--cyclone/sickle/bitnot.c66
-rw-r--r--cyclone/sickle/bitor.c144
-rw-r--r--cyclone/sickle/bitshift.c130
-rw-r--r--cyclone/sickle/bitxor.c144
-rw-r--r--cyclone/sickle/capture.c408
-rw-r--r--cyclone/sickle/cartopol.c79
-rw-r--r--cyclone/sickle/change.c52
-rw-r--r--cyclone/sickle/click.c119
-rw-r--r--cyclone/sickle/comb.c162
-rw-r--r--cyclone/sickle/cosh.c48
-rw-r--r--cyclone/sickle/cosx.c51
-rw-r--r--cyclone/sickle/count.c145
-rw-r--r--cyclone/sickle/cycle.c173
-rw-r--r--cyclone/sickle/delay.c101
-rw-r--r--cyclone/sickle/delta.c52
-rw-r--r--cyclone/sickle/deltaclip.c67
-rw-r--r--cyclone/sickle/edge.c106
-rw-r--r--cyclone/sickle/frameaccum.c71
-rw-r--r--cyclone/sickle/framedelta.c76
-rw-r--r--cyclone/sickle/index.c107
-rw-r--r--cyclone/sickle/kink.c62
-rw-r--r--cyclone/sickle/linedrive.c73
-rw-r--r--cyclone/sickle/log.c74
-rw-r--r--cyclone/sickle/lookup.c94
-rw-r--r--cyclone/sickle/minmax.c78
-rw-r--r--cyclone/sickle/peakamp.c107
-rw-r--r--cyclone/sickle/peek.c147
-rw-r--r--cyclone/sickle/phasewrap.c131
-rw-r--r--cyclone/sickle/play.c122
-rw-r--r--cyclone/sickle/poltocar.c79
-rw-r--r--cyclone/sickle/pow.c54
-rw-r--r--cyclone/sickle/rampsmooth.c206
-rw-r--r--cyclone/sickle/rand.c95
-rw-r--r--cyclone/sickle/record.c242
-rw-r--r--cyclone/sickle/sah.c70
-rw-r--r--cyclone/sickle/sickle.c93
-rw-r--r--cyclone/sickle/sinh.c48
-rw-r--r--cyclone/sickle/sinx.c51
-rw-r--r--cyclone/sickle/slide.c77
-rw-r--r--cyclone/sickle/spike.c109
-rw-r--r--cyclone/sickle/tanh.c48
-rw-r--r--cyclone/sickle/tanx.c51
-rw-r--r--cyclone/sickle/train.c117
-rw-r--r--cyclone/sickle/trapezoid.c105
-rw-r--r--cyclone/sickle/triangle.c95
-rw-r--r--cyclone/sickle/vectral.c235
-rw-r--r--cyclone/sickle/wave.c161
67 files changed, 7838 insertions, 0 deletions
diff --git a/cyclone/sickle/Clip.c b/cyclone/sickle/Clip.c
new file mode 100644
index 0000000..2888be1
--- /dev/null
+++ b/cyclone/sickle/Clip.c
@@ -0,0 +1,59 @@
+/* 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. */
+
+/* Clip~ substitution is needed to handle signal input for lo and hi */
+
+#include "m_pd.h"
+#include "sickle/sic.h"
+
+#define CLIP_DEFLO 0.
+#define CLIP_DEFHI 0.
+
+typedef t_sic t_clip;
+static t_class *clip_class;
+
+static t_int *clip_perform(t_int *w)
+{
+ int nblock = (int)(w[1]);
+ t_float *in1 = (t_float *)(w[2]);
+ t_float *in2 = (t_float *)(w[3]);
+ t_float *in3 = (t_float *)(w[4]);
+ t_float *out = (t_float *)(w[5]);
+ while (nblock--)
+ {
+ float f = *in1++;
+ float lo = *in2++;
+ float hi = *in3++;
+ if (f < lo)
+ *out++ = lo;
+ else if (f > hi)
+ *out++ = hi;
+ else
+ *out++ = f;
+ }
+ return (w + 6);
+}
+
+static void clip_dsp(t_clip *x, t_signal **sp)
+{
+ dsp_add(clip_perform, 5, sp[0]->s_n,
+ sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec);
+}
+
+static void *clip_new(t_symbol *s, int ac, t_atom *av)
+{
+ t_clip *x = (t_clip *)pd_new(clip_class);
+ sic_inlet((t_sic *)x, 1, CLIP_DEFLO, 0, ac, av);
+ sic_inlet((t_sic *)x, 2, CLIP_DEFHI, 1, ac, av);
+ outlet_new((t_object *)x, &s_signal);
+ return (x);
+}
+
+void Clip_tilde_setup(void)
+{
+ clip_class = class_new(gensym("Clip~"),
+ (t_newmethod)clip_new, 0,
+ sizeof(t_clip), 0, A_GIMME, 0);
+ sic_setup(clip_class, clip_dsp, SIC_FLOATTOSIGNAL);
+}
diff --git a/cyclone/sickle/Line.c b/cyclone/sickle/Line.c
new file mode 100644
index 0000000..f1d2b18
--- /dev/null
+++ b/cyclone/sickle/Line.c
@@ -0,0 +1,299 @@
+/* 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 "common/grow.h"
+#include "common/loud.h"
+#include "sickle/sic.h"
+
+//#define LINE_DEBUG
+
+#ifndef PD_BADFLOAT
+#define PD_BADFLOAT(f) ((((*(unsigned int*)&(f))&0x7f800000)==0) || \
+ (((*(unsigned int*)&(f))&0x7f800000)==0x7f800000))
+#endif
+
+#define LINE_INISIZE 64 /* LATER rethink */
+#define LINE_MAXSIZE 64
+
+typedef struct _lineseg
+{
+ float s_target;
+ float s_delta;
+} t_lineseg;
+
+typedef struct _line
+{
+ t_sic x_sic;
+ float x_value;
+ float x_target;
+ float x_delta;
+ int x_deltaset;
+ float x_inc;
+ float x_biginc;
+ float x_ksr;
+ int x_nleft;
+ int x_retarget;
+ int x_size; /* as allocated */
+ int x_nsegs; /* as used */
+ t_lineseg *x_curseg;
+ t_lineseg *x_segs;
+ t_lineseg x_segini[LINE_INISIZE];
+ t_clock *x_clock;
+ t_outlet *x_bangout;
+#ifdef LINE_DEBUG
+ int dbg_nretargets;
+ int dbg_exitpoint;
+ int dbg_npoints;
+#endif
+} t_line;
+
+static t_class *line_class;
+
+static void line_tick(t_line *x)
+{
+ outlet_bang(x->x_bangout);
+#ifdef LINE_DEBUG
+ post("exit point %d, after %d retarget calls",
+ x->dbg_exitpoint, x->dbg_nretargets);
+ post("at value %g, after last %d npoints, with inc %g, biginc %g",
+ x->x_value, x->dbg_npoints, x->x_inc, x->x_biginc);
+ x->dbg_nretargets = x->dbg_exitpoint = x->dbg_npoints = 0;
+#endif
+}
+
+static t_int *line_perform(t_int *w)
+{
+ t_line *x = (t_line *)(w[1]);
+ t_float *out = (t_float *)(w[2]);
+ int nblock = (int)(w[3]);
+ int nxfer = x->x_nleft;
+ float curval = x->x_value;
+ float inc = x->x_inc;
+ float biginc = x->x_biginc;
+ if (PD_BADFLOAT(curval)) /* LATER rethink */
+ curval = x->x_value = 0;
+retarget:
+ if (x->x_retarget)
+ {
+ float target = x->x_curseg->s_target;
+ float delta = x->x_curseg->s_delta;
+ int npoints = delta * x->x_ksr + 0.5; /* LATER rethink */
+#ifdef LINE_DEBUG
+ x->dbg_nretargets++;
+#endif
+ x->x_nsegs--;
+ x->x_curseg++;
+ while (npoints <= 0)
+ {
+ curval = x->x_value = target;
+ if (x->x_nsegs)
+ {
+ target = x->x_curseg->s_target;
+ delta = x->x_curseg->s_delta;
+ npoints = delta * x->x_ksr + 0.5; /* LATER rethink */
+ x->x_nsegs--;
+ x->x_curseg++;
+ }
+ else
+ {
+ while (nblock--) *out++ = curval;
+ x->x_nleft = 0;
+#ifdef LINE_DEBUG
+ x->dbg_exitpoint = 1;
+#endif
+ clock_delay(x->x_clock, 0);
+ x->x_retarget = 0;
+ return (w + 4);
+ }
+ }
+ nxfer = x->x_nleft = npoints;
+ inc = x->x_inc = (target - x->x_value) / (float)npoints;
+ x->x_biginc = (int)(w[3]) * inc;
+ biginc = nblock * inc;
+ x->x_target = target;
+ x->x_retarget = 0;
+#ifdef LINE_DEBUG
+ x->dbg_npoints = npoints;
+#endif
+ }
+ if (nxfer >= nblock)
+ {
+ if ((x->x_nleft -= nblock) == 0)
+ {
+ if (x->x_nsegs) x->x_retarget = 1;
+ else
+ {
+#ifdef LINE_DEBUG
+ x->dbg_exitpoint = 2;
+#endif
+ clock_delay(x->x_clock, 0);
+ }
+ x->x_value = x->x_target;
+ }
+ else x->x_value += biginc;
+ while (nblock--)
+ *out++ = curval, curval += inc;
+ }
+ else if (nxfer > 0)
+ {
+ nblock -= nxfer;
+ do
+ *out++ = curval, curval += inc;
+ while (--nxfer);
+ curval = x->x_value = x->x_target;
+ if (x->x_nsegs)
+ {
+ x->x_retarget = 1;
+ goto retarget;
+ }
+ else
+ {
+ while (nblock--) *out++ = curval;
+ x->x_nleft = 0;
+#ifdef LINE_DEBUG
+ x->dbg_exitpoint = 3;
+#endif
+ clock_delay(x->x_clock, 0);
+ }
+ }
+ else while (nblock--) *out++ = curval;
+ return (w + 4);
+}
+
+static void line_float(t_line *x, t_float f)
+{
+ if (x->x_deltaset)
+ {
+ x->x_deltaset = 0;
+ x->x_target = f;
+ x->x_nsegs = 1;
+ x->x_curseg = x->x_segs;
+ x->x_curseg->s_target = f;
+ x->x_curseg->s_delta = x->x_delta;
+ x->x_retarget = 1;
+ }
+ else
+ {
+ x->x_value = x->x_target = f;
+ x->x_nsegs = 0;
+ x->x_curseg = 0;
+ x->x_nleft = 0;
+ x->x_retarget = 0;
+ }
+}
+
+static void line_ft1(t_line *x, t_floatarg f)
+{
+ x->x_delta = f;
+ x->x_deltaset = (f > 0);
+}
+
+static void line_list(t_line *x, t_symbol *s, int ac, t_atom *av)
+{
+ int natoms, nsegs, odd;
+ t_atom *ap;
+ t_lineseg *segp;
+ for (natoms = 0, ap = av; natoms < ac; natoms++, ap++)
+ if (ap->a_type != A_FLOAT) break; /* CHECKME */
+ if (!natoms)
+ return; /* CHECKME */
+ odd = natoms % 2;
+ nsegs = natoms / 2;
+ if (odd) nsegs++;
+ if (nsegs > x->x_size)
+ {
+ int ns = nsegs;
+ x->x_segs = grow_nodata(&ns, &x->x_size, x->x_segs,
+ LINE_INISIZE, x->x_segini,
+ sizeof(*x->x_segs));
+ if (ns < nsegs)
+ {
+ natoms = ns * 2;
+ nsegs = ns;
+ }
+ }
+ x->x_nsegs = nsegs;
+#ifdef LINE_DEBUG
+ post("%d segments:", x->x_nsegs);
+#endif
+ segp = x->x_segs;
+ if (odd) nsegs--;
+ while (nsegs--)
+ {
+ segp->s_target = av++->a_w.w_float;
+ segp->s_delta = av++->a_w.w_float;
+#ifdef LINE_DEBUG
+ post("%g %g", segp->s_target, segp->s_delta);
+#endif
+ segp++;
+ }
+ if (odd)
+ {
+ segp->s_target = av->a_w.w_float;
+ segp->s_delta = 0;
+#ifdef LINE_DEBUG
+ post("%g %g", segp->s_target, segp->s_delta);
+#endif
+ }
+ x->x_deltaset = 0;
+ x->x_target = x->x_segs->s_target;
+ x->x_curseg = x->x_segs;
+ x->x_retarget = 1;
+}
+
+/* CHECKED no stop, pity... */
+#if 0
+static void line_stop(t_line *x)
+{
+ x->x_target = x->x_value;
+ x->x_nleft = 0;
+ x->x_retarget = 0;
+ x->x_nsegs = 0;
+ x->x_curseg = 0;
+}
+#endif
+
+static void line_dsp(t_line *x, t_signal **sp)
+{
+ dsp_add(line_perform, 3, x, sp[0]->s_vec, sp[0]->s_n);
+ x->x_ksr = sp[0]->s_sr * 0.001;
+}
+
+static void line_free(t_line *x)
+{
+ if (x->x_segs != x->x_segini)
+ freebytes(x->x_segs, x->x_size * sizeof(*x->x_segs));
+ if (x->x_clock) clock_free(x->x_clock);
+}
+
+static void *line_new(t_floatarg f)
+{
+ t_line *x = (t_line *)pd_new(line_class);
+ x->x_value = x->x_target = f;
+ x->x_deltaset = 0;
+ x->x_nleft = 0;
+ x->x_retarget = 0;
+ x->x_size = LINE_INISIZE;
+ x->x_nsegs = 0;
+ x->x_segs = x->x_segini;
+ x->x_curseg = 0;
+ inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft1"));
+ outlet_new((t_object *)x, &s_signal);
+ x->x_bangout = outlet_new((t_object *)x, &s_bang);
+ x->x_clock = clock_new(x, (t_method)line_tick);
+ return (x);
+}
+
+void Line_tilde_setup(void)
+{
+ line_class = class_new(gensym("Line~"),
+ (t_newmethod)line_new, 0,
+ sizeof(t_line), 0, A_DEFFLOAT, 0);
+ sic_setup(line_class, line_dsp, SIC_NOMAINSIGNALIN);
+ class_addfloat(line_class, line_float);
+ class_addlist(line_class, line_list);
+ class_addmethod(line_class, (t_method)line_ft1,
+ gensym("ft1"), A_FLOAT, 0);
+}
diff --git a/cyclone/sickle/Makefile b/cyclone/sickle/Makefile
new file mode 100644
index 0000000..61aa444
--- /dev/null
+++ b/cyclone/sickle/Makefile
@@ -0,0 +1,3 @@
+ROOT_DIR = ../..
+redefault: allsickles.c default
+include $(ROOT_DIR)/Makefile.common
diff --git a/cyclone/sickle/Makefile.objects b/cyclone/sickle/Makefile.objects
new file mode 100644
index 0000000..2edb12c
--- /dev/null
+++ b/cyclone/sickle/Makefile.objects
@@ -0,0 +1,11 @@
+SHARED_OBJECTS = \
+unstable/forky.o \
+unstable/fragile.o \
+common/loud.o \
+common/grow.o \
+common/vefl.o \
+common/binport.o \
+common/port.o \
+hammer/file.o \
+sickle/sic.o \
+sickle/arsic.o
diff --git a/cyclone/sickle/Makefile.sources b/cyclone/sickle/Makefile.sources
new file mode 100644
index 0000000..e807a06
--- /dev/null
+++ b/cyclone/sickle/Makefile.sources
@@ -0,0 +1,67 @@
+CX_SOURCES = \
+sickle.c
+
+OTHER_SOURCES = \
+allsickles.c \
+abs.c \
+acos.c \
+acosh.c \
+allpass.c \
+asin.c \
+asinh.c \
+atan.c \
+atan2.c \
+atanh.c \
+average.c \
+avg.c \
+bitand.c \
+bitnot.c \
+bitor.c \
+bitshift.c \
+bitxor.c \
+capture.c \
+cartopol.c \
+change.c \
+click.c \
+Clip.c \
+comb.c \
+cosh.c \
+cosx.c \
+count.c \
+cycle.c \
+delay.c \
+delta.c \
+deltaclip.c \
+edge.c \
+frameaccum.c \
+framedelta.c \
+index.c \
+kink.c \
+Line.c \
+linedrive.c \
+log.c \
+lookup.c \
+minmax.c \
+peakamp.c \
+peek.c \
+phasewrap.c \
+play.c \
+poltocar.c \
+pow.c \
+rand.c \
+rampsmooth.c \
+record.c \
+sah.c \
+Scope.c \
+sinh.c \
+sinx.c \
+slide.c \
+Snapshot.c \
+spike.c \
+tanh.c \
+tanx.c \
+train.c \
+trapezoid.c \
+triangle.c \
+vectral.c \
+wave.c
diff --git a/cyclone/sickle/Scope.c b/cyclone/sickle/Scope.c
new file mode 100644
index 0000000..75e825d
--- /dev/null
+++ b/cyclone/sickle/Scope.c
@@ -0,0 +1,1043 @@
+/* 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. */
+
+/* LATER cache gui commands */
+/* LATER think about resizing scheme. Currently mouse events are not bound
+ to any part of Scope~'s 'widget' as such, but to a special item, which is
+ created only for a selected Scope~. For the other scheme see the 'comment'
+ class (no indicator there, though -- neither a handle, nor a pointer change).
+ One way or the other, the traffic from the gui layer should be kept possibly
+ low, at least in run-mode. */
+
+#include <stdio.h>
+#include <string.h>
+#include "m_pd.h"
+#include "g_canvas.h"
+#include "common/loud.h"
+#include "common/grow.h"
+#include "unstable/forky.h"
+#include "sickle/sic.h"
+
+//#define SCOPE_DEBUG
+
+/* these are powers of 2 + margins */
+#define SCOPE_DEFWIDTH 130 /* CHECKED */
+#define SCOPE_MINWIDTH 66
+#define SCOPE_DEFHEIGHT 130 /* CHECKED */
+#define SCOPE_MINHEIGHT 34
+#define SCOPE_DEFPERIOD 256
+#define SCOPE_MINPERIOD 2
+#define SCOPE_MAXPERIOD 8092
+#define SCOPE_DEFBUFSIZE 128
+#define SCOPE_MINBUFSIZE 8
+#define SCOPE_MAXBUFSIZE 800 /* LATER rethink */
+#define SCOPE_WARNBUFSIZE 256
+#define SCOPE_DEFMINVAL -1.
+#define SCOPE_DEFMAXVAL 1.
+#define SCOPE_DEFDELAY 0
+#define SCOPE_MINDELAY 0
+#define SCOPE_TRIGLINEMODE 0
+#define SCOPE_TRIGUPMODE 1
+#define SCOPE_TRIGDOWNMODE 2
+#define SCOPE_DEFTRIGMODE SCOPE_TRIGLINEMODE
+#define SCOPE_MINTRIGMODE SCOPE_TRIGLINEMODE
+#define SCOPE_MAXTRIGMODE SCOPE_TRIGDOWNMODE
+#define SCOPE_DEFTRIGLEVEL 0.
+#define SCOPE_MINCOLOR 0
+#define SCOPE_MAXCOLOR 255
+#define SCOPE_DEFFGRED 102
+#define SCOPE_DEFFGGREEN 255
+#define SCOPE_DEFFGBLUE 51
+#define SCOPE_DEFBGRED 135
+#define SCOPE_DEFBGGREEN 135
+#define SCOPE_DEFBGBLUE 135
+#define SCOPE_SELCOLOR "#8080ff" /* a bit lighter shade of blue */
+#define SCOPE_FGWIDTH 0.7 /* line width is float */
+#define SCOPE_GRIDWIDTH 0.9
+#define SCOPE_SELBDWIDTH 3.0
+#define SCOPEHANDLE_WIDTH 10 /* item size is int */
+#define SCOPEHANDLE_HEIGHT 10
+/* these are performance-related hacks, LATER investigate */
+#define SCOPE_GUICHUNKMONO 16
+#define SCOPE_GUICHUNKXY 32
+
+typedef struct _scope
+{
+ t_sic x_sic;
+ t_glist *x_glist;
+ t_canvas *x_canvas; /* also an 'isvised' flag */
+ char x_tag[64];
+ char x_fgtag[64];
+ char x_bgtag[64];
+ char x_gridtag[64];
+ int x_width;
+ int x_height;
+ float x_minval;
+ float x_maxval;
+ int x_delay;
+ int x_trigmode;
+ float x_triglevel;
+ unsigned char x_fgred;
+ unsigned char x_fggreen;
+ unsigned char x_fgblue;
+ unsigned char x_bgred;
+ unsigned char x_bggreen;
+ unsigned char x_bgblue;
+ int x_xymode;
+ float *x_xbuffer;
+ float *x_ybuffer;
+ float x_xbufini[SCOPE_DEFBUFSIZE];
+ float x_ybufini[SCOPE_DEFBUFSIZE];
+ int x_allocsize;
+ int x_bufsize;
+ int x_bufphase;
+ int x_period;
+ int x_phase;
+ int x_precount;
+ int x_retrigger;
+ float x_ksr;
+ float x_currx;
+ float x_curry;
+ float x_trigx;
+ int x_frozen;
+ t_clock *x_clock;
+ t_pd *x_handle;
+} t_scope;
+
+typedef struct _scopehandle
+{
+ t_pd h_pd;
+ t_scope *h_master;
+ t_symbol *h_bindsym;
+ char h_pathname[64];
+ char h_outlinetag[64];
+ int h_dragon;
+ int h_dragx;
+ int h_dragy;
+} t_scopehandle;
+
+static t_class *scope_class;
+static t_class *scopehandle_class;
+
+static void scope_clear(t_scope *x, int withdelay)
+{
+ x->x_bufphase = 0;
+ x->x_phase = 0;
+ x->x_precount = (withdelay ? (int)(x->x_delay * x->x_ksr) : 0);
+ /* CHECKED delay does not matter (refman is wrong) */
+ x->x_retrigger = (x->x_trigmode != SCOPE_TRIGLINEMODE);
+ x->x_trigx = x->x_triglevel;
+}
+
+static t_int *scope_monoperform(t_int *w)
+{
+ t_scope *x = (t_scope *)(w[1]);
+ int bufphase = x->x_bufphase;
+ int bufsize = x->x_bufsize;
+ if (bufphase < bufsize)
+ {
+ int nblock = (int)(w[2]);
+ if (x->x_precount >= nblock)
+ x->x_precount -= nblock;
+ else
+ {
+ t_float *in = (t_float *)(w[3]);
+ int phase = x->x_phase;
+ int period = x->x_period;
+ float *bp1 = x->x_xbuffer + bufphase;
+ float *bp2 = x->x_ybuffer + bufphase;
+ float currx = x->x_currx;
+ if (x->x_precount > 0)
+ {
+ nblock -= x->x_precount;
+ in += x->x_precount;
+ x->x_precount = 0;
+ }
+ while (x->x_retrigger)
+ {
+ float triglevel = x->x_triglevel;
+ if (x->x_trigmode == SCOPE_TRIGUPMODE)
+ {
+ if (x->x_trigx < triglevel)
+ {
+ while (nblock--) if (*in++ >= triglevel)
+ {
+ x->x_retrigger = 0;
+ break;
+ }
+ }
+ else while (nblock--) if (*in++ < triglevel)
+ {
+ x->x_trigx = triglevel - 1.;
+ break;
+ }
+ }
+ else
+ {
+ if (x->x_trigx > triglevel)
+ {
+ while (nblock--) if (*in++ <= triglevel)
+ {
+ x->x_retrigger = 0;
+ break;
+ }
+ }
+ else while (nblock--) if (*in++ > triglevel)
+ {
+ x->x_trigx = triglevel + 1.;
+ break;
+ }
+ }
+ if (nblock <= 0)
+ return (w + 4);
+ }
+ while (nblock--)
+ {
+ if (phase)
+ {
+ float f = *in++;
+ /* CHECKED */
+ if ((currx < 0 && (f < currx || f > -currx)) ||
+ (currx > 0 && (f > currx || f < -currx)))
+ currx = f;
+ }
+ else currx = *in++;
+ if (currx != currx)
+ currx = 0.; /* CHECKED NaNs bashed to zeros */
+ if (++phase == period)
+ {
+ phase = 0;
+ if (++bufphase == bufsize)
+ {
+ *bp1 = *bp2 = currx;
+ clock_delay(x->x_clock, 0);
+ break;
+ }
+ else *bp1++ = *bp2++ = currx;
+ }
+ }
+ x->x_currx = currx;
+ x->x_bufphase = bufphase;
+ x->x_phase = phase;
+ }
+ }
+ return (w + 4);
+}
+
+static t_int *scope_xyperform(t_int *w)
+{
+ t_scope *x = (t_scope *)(w[1]);
+ int bufphase = x->x_bufphase;
+ int bufsize = x->x_bufsize;
+ if (bufphase < bufsize)
+ {
+ int nblock = (int)(w[2]);
+ if (x->x_precount >= nblock)
+ x->x_precount -= nblock;
+ else
+ {
+ t_float *in1 = (t_float *)(w[3]);
+ t_float *in2 = (t_float *)(w[4]);
+ int phase = x->x_phase;
+ int period = x->x_period;
+ float freq = 1. / period;
+ float *bp1 = x->x_xbuffer + bufphase;
+ float *bp2 = x->x_ybuffer + bufphase;
+ float currx = x->x_currx;
+ float curry = x->x_curry;
+ if (x->x_precount > 0)
+ {
+ nblock -= x->x_precount;
+ in1 += x->x_precount;
+ in2 += x->x_precount;
+ x->x_precount = 0;
+ }
+ if (x->x_retrigger)
+ {
+ /* CHECKME and FIXME */
+ x->x_retrigger = 0;
+ }
+ while (nblock--)
+ {
+ if (phase)
+ {
+ /* CHECKME */
+ currx += *in1++;
+ curry += *in2++;
+ }
+ else
+ {
+ currx = *in1++;
+ curry = *in2++;
+ }
+ if (currx != currx)
+ currx = 0.; /* CHECKME NaNs bashed to zeros */
+ if (curry != curry)
+ curry = 0.; /* CHECKME NaNs bashed to zeros */
+ if (++phase == period)
+ {
+ phase = 0;
+ if (++bufphase == bufsize)
+ {
+ *bp1 = currx * freq;
+ *bp2 = curry * freq;
+ clock_delay(x->x_clock, 0);
+ break;
+ }
+ else
+ {
+ *bp1++ = currx * freq;
+ *bp2++ = curry * freq;
+ }
+ }
+ }
+ x->x_currx = currx;
+ x->x_curry = curry;
+ x->x_bufphase = bufphase;
+ x->x_phase = phase;
+ }
+ }
+ return (w + 5);
+}
+
+static void scope_setxymode(t_scope *x, int xymode);
+
+static void scope_dsp(t_scope *x, t_signal **sp)
+{
+ x->x_ksr = sp[0]->s_sr * 0.001;
+ scope_setxymode(x,
+ forky_hasfeeders((t_object *)x, x->x_glist, 1, &s_signal));
+ if (x->x_xymode)
+ dsp_add(scope_xyperform, 4, x, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec);
+ else
+ dsp_add(scope_monoperform, 3, x, sp[0]->s_n, sp[0]->s_vec);
+}
+
+static t_canvas *scope_getcanvas(t_scope *x, t_glist *glist)
+{
+ if (glist != x->x_glist)
+ {
+ bug("scope_getcanvas");
+ x->x_glist = glist;
+ }
+ return (x->x_canvas = glist_getcanvas(glist));
+}
+
+/* answers the question: ``can we draw and where to?'' */
+static t_canvas *scope_isvisible(t_scope *x)
+{
+ return (glist_isvisible(x->x_glist) ? x->x_canvas : 0);
+}
+
+static void scope_period(t_scope *x, t_symbol *s, int ac, t_atom *av)
+{
+ t_float period = (s ? x->x_period : SCOPE_DEFPERIOD);
+ int result = loud_floatarg(*(t_pd *)x, (s ? 0 : 2), ac, av, &period,
+ SCOPE_MINPERIOD, SCOPE_MAXPERIOD,
+ /* LATER rethink warning rules */
+ (s ? LOUD_CLIP : LOUD_CLIP | LOUD_WARN),
+ (s ? 0 : LOUD_WARN), "samples per element");
+ if (!s || result == LOUD_ARGOK || result == LOUD_ARGOVER)
+ {
+ x->x_period = (int)period;
+ scope_clear(x, 0);
+ }
+}
+
+static void scope_float(t_scope *x, t_float f)
+{
+ t_atom at;
+ SETFLOAT(&at, f);
+ scope_period(x, &s_float, 1, &at);
+}
+
+static void scope_bufsize(t_scope *x, t_symbol *s, int ac, t_atom *av)
+{
+ t_float bufsize = (s ? x->x_bufsize : SCOPE_DEFBUFSIZE);
+ int result = loud_floatarg(*(t_pd *)x, (s ? 0 : 4), ac, av, &bufsize,
+ SCOPE_MINBUFSIZE, SCOPE_WARNBUFSIZE,
+ /* LATER rethink warning rules */
+ (s ? LOUD_CLIP : LOUD_CLIP | LOUD_WARN),
+ (s ? 0 : LOUD_WARN), "display elements");
+ if (result == LOUD_ARGOVER)
+ {
+ bufsize = (s ? x->x_bufsize : SCOPE_DEFBUFSIZE);
+ result = loud_floatarg(*(t_pd *)x, (s ? 0 : 4), ac, av, &bufsize,
+ 0, SCOPE_MAXBUFSIZE, 0, LOUD_CLIP | LOUD_WARN,
+ "display elements");
+ }
+ if (!s)
+ {
+ x->x_allocsize = SCOPE_DEFBUFSIZE;
+ x->x_bufsize = 0;
+ x->x_xbuffer = x->x_xbufini;
+ x->x_ybuffer = x->x_ybufini;
+ }
+ if (!s || result == LOUD_ARGOK)
+ {
+ int newsize = (int)bufsize;
+ if (newsize > x->x_allocsize)
+ {
+ int nrequested = newsize;
+ int allocsize = x->x_allocsize;
+ int oldsize = x->x_bufsize;
+ x->x_xbuffer = grow_withdata(&nrequested, &oldsize,
+ &allocsize, x->x_xbuffer,
+ SCOPE_DEFBUFSIZE, x->x_xbufini,
+ sizeof(*x->x_xbuffer));
+ if (nrequested == newsize)
+ {
+ allocsize = x->x_allocsize;
+ oldsize = x->x_bufsize;
+ x->x_ybuffer = grow_withdata(&nrequested, &oldsize,
+ &allocsize, x->x_ybuffer,
+ SCOPE_DEFBUFSIZE, x->x_ybufini,
+ sizeof(*x->x_ybuffer));
+ }
+ if (nrequested == newsize)
+ {
+ x->x_allocsize = allocsize;
+ x->x_bufsize = newsize;
+ }
+ else
+ {
+ if (x->x_xbuffer != x->x_xbufini)
+ freebytes(x->x_xbuffer,
+ x->x_allocsize * sizeof(*x->x_xbuffer));
+ if (x->x_ybuffer != x->x_ybufini)
+ freebytes(x->x_ybuffer,
+ x->x_allocsize * sizeof(*x->x_ybuffer));
+ x->x_allocsize = SCOPE_DEFBUFSIZE;
+ x->x_bufsize = SCOPE_DEFBUFSIZE;
+ x->x_xbuffer = x->x_xbufini;
+ x->x_ybuffer = x->x_ybufini;
+ }
+ }
+ else x->x_bufsize = newsize;
+ scope_clear(x, 0);
+ }
+}
+
+static void scope_range(t_scope *x, t_symbol *s, int ac, t_atom *av)
+{
+ t_float minval = (s ? x->x_minval : SCOPE_DEFMINVAL);
+ t_float maxval = (s ? x->x_maxval : SCOPE_DEFMAXVAL);
+ loud_floatarg(*(t_pd *)x, (s ? 0 : 5), ac, av, &minval, 0, 0, 0, 0, 0);
+ loud_floatarg(*(t_pd *)x, (s ? 1 : 6), ac, av, &maxval, 0, 0, 0, 0, 0);
+ /* CHECKME swapping, ignoring if equal */
+ if (minval < maxval)
+ {
+ x->x_minval = minval;
+ x->x_maxval = maxval;
+ }
+ else if (minval > maxval)
+ {
+ x->x_minval = maxval;
+ x->x_maxval = minval;
+ }
+ else if (!s)
+ {
+ x->x_minval = SCOPE_DEFMINVAL;
+ x->x_maxval = SCOPE_DEFMAXVAL;
+ }
+}
+
+static void scope_delay(t_scope *x, t_symbol *s, int ac, t_atom *av)
+{
+ t_float delay = (s ? x->x_delay : SCOPE_DEFDELAY);
+ int result = loud_floatarg(*(t_pd *)x, (s ? 0 : 7), ac, av, &delay,
+ SCOPE_MINDELAY, 0,
+ LOUD_CLIP | LOUD_WARN, 0, "delay");
+ if (!s || result == LOUD_ARGOK)
+ x->x_delay = delay;
+}
+
+static void scope_trigger(t_scope *x, t_symbol *s, int ac, t_atom *av)
+{
+ t_float trigmode = (s ? x->x_trigmode : SCOPE_DEFTRIGMODE);
+ loud_floatarg(*(t_pd *)x, (s ? 0 : 9), ac, av, &trigmode,
+ SCOPE_MINTRIGMODE, SCOPE_MAXTRIGMODE,
+ LOUD_CLIP | LOUD_WARN, LOUD_CLIP | LOUD_WARN,
+ "trigger mode");
+ x->x_trigmode = (int)trigmode;
+ if (x->x_trigmode == SCOPE_TRIGLINEMODE)
+ x->x_retrigger = 0;
+}
+
+static void scope_triglevel(t_scope *x, t_symbol *s, int ac, t_atom *av)
+{
+ t_float triglevel = (s ? x->x_triglevel : SCOPE_DEFTRIGLEVEL);
+ loud_floatarg(*(t_pd *)x, (s ? 0 : 10), ac, av, &triglevel, 0, 0, 0, 0, 0);
+ x->x_triglevel = triglevel;
+}
+
+static void scope_frgb(t_scope *x, t_symbol *s, int ac, t_atom *av)
+{
+ t_float fgred = (s ? x->x_fgred : SCOPE_DEFFGRED);
+ t_float fggreen = (s ? x->x_fggreen : SCOPE_DEFFGGREEN);
+ t_float fgblue = (s ? x->x_fgblue : SCOPE_DEFFGBLUE);
+ t_canvas *cv;
+ loud_floatarg(*(t_pd *)x, (s ? 0 : 11), ac, av, &fgred,
+ SCOPE_MINCOLOR, SCOPE_MAXCOLOR,
+ LOUD_CLIP | LOUD_WARN, LOUD_CLIP | LOUD_WARN, "color");
+ loud_floatarg(*(t_pd *)x, (s ? 1 : 12), ac, av, &fggreen,
+ SCOPE_MINCOLOR, SCOPE_MAXCOLOR,
+ LOUD_CLIP | LOUD_WARN, LOUD_CLIP | LOUD_WARN, "color");
+ loud_floatarg(*(t_pd *)x, (s ? 2 : 13), ac, av, &fgblue,
+ SCOPE_MINCOLOR, SCOPE_MAXCOLOR,
+ LOUD_CLIP | LOUD_WARN, LOUD_CLIP | LOUD_WARN, "color");
+ x->x_fgred = (int)fgred;
+ x->x_fggreen = (int)fggreen;
+ x->x_fgblue = (int)fgblue;
+ if (cv = scope_isvisible(x))
+ sys_vgui(".x%x.c itemconfigure %s -fill #%2.2x%2.2x%2.2x\n",
+ cv, x->x_fgtag, x->x_fgred, x->x_fggreen, x->x_fgblue);
+}
+
+static void scope_brgb(t_scope *x, t_symbol *s, int ac, t_atom *av)
+{
+ t_float bgred = (s ? x->x_bgred : SCOPE_DEFBGRED);
+ t_float bggreen = (s ? x->x_bggreen : SCOPE_DEFBGGREEN);
+ t_float bgblue = (s ? x->x_bgblue : SCOPE_DEFBGBLUE);
+ t_canvas *cv;
+ loud_floatarg(*(t_pd *)x, (s ? 0 : 14), ac, av, &bgred,
+ SCOPE_MINCOLOR, SCOPE_MAXCOLOR,
+ LOUD_CLIP | LOUD_WARN, LOUD_CLIP | LOUD_WARN, "color");
+ loud_floatarg(*(t_pd *)x, (s ? 1 : 15), ac, av, &bggreen,
+ SCOPE_MINCOLOR, SCOPE_MAXCOLOR,
+ LOUD_CLIP | LOUD_WARN, LOUD_CLIP | LOUD_WARN, "color");
+ loud_floatarg(*(t_pd *)x, (s ? 2 : 16), ac, av, &bgblue,
+ SCOPE_MINCOLOR, SCOPE_MAXCOLOR,
+ LOUD_CLIP | LOUD_WARN, LOUD_CLIP | LOUD_WARN, "color");
+ x->x_bgred = (int)bgred;
+ x->x_bggreen = (int)bggreen;
+ x->x_bgblue = (int)bgblue;
+ if (cv = scope_isvisible(x))
+ sys_vgui(".x%x.c itemconfigure %s -fill #%2.2x%2.2x%2.2x\n",
+ cv, x->x_bgtag, x->x_bgred, x->x_bggreen, x->x_bgblue);
+}
+
+static void scope_getrect(t_gobj *z, t_glist *glist,
+ int *xp1, int *yp1, int *xp2, int *yp2)
+{
+ t_scope *x = (t_scope *)z;
+ float x1, y1, x2, y2;
+ x1 = text_xpix((t_text *)x, glist);
+ y1 = text_ypix((t_text *)x, glist);
+ x2 = x1 + x->x_width;
+ y2 = y1 + x->x_height;
+ *xp1 = x1;
+ *yp1 = y1;
+ *xp2 = x2;
+ *yp2 = y2;
+}
+
+static void scope_displace(t_gobj *z, t_glist *glist, int dx, int dy)
+{
+ t_scope *x = (t_scope *)z;
+ t_text *t = (t_text *)z;
+ t->te_xpix += dx;
+ t->te_ypix += dy;
+ if (glist_isvisible(glist))
+ {
+ t_canvas *cv = scope_getcanvas(x, glist);
+ sys_vgui(".x%x.c move %s %d %d\n", cv, x->x_tag, dx, dy);
+ canvas_fixlinesfor(cv, t);
+ }
+}
+
+static void scope_select(t_gobj *z, t_glist *glist, int state)
+{
+ t_scope *x = (t_scope *)z;
+ t_canvas *cv = scope_getcanvas(x, glist);
+ t_scopehandle *sh = (t_scopehandle *)x->x_handle;
+ if (state)
+ {
+ int x1, y1, x2, y2;
+ scope_getrect(z, glist, &x1, &y1, &x2, &y2);
+
+ sys_vgui(".x%x.c itemconfigure %s -outline blue -width %f -fill %s\n",
+ cv, x->x_bgtag, SCOPE_SELBDWIDTH, SCOPE_SELCOLOR);
+
+ sys_vgui("canvas %s -width %d -height %d -bg #fedc00 -bd 0\n",
+ sh->h_pathname, SCOPEHANDLE_WIDTH, SCOPEHANDLE_HEIGHT);
+ sys_vgui(".x%x.c create window %f %f -anchor nw\
+ -width %d -height %d -window %s -tags %s\n",
+ cv, x2 - (SCOPEHANDLE_WIDTH - SCOPE_SELBDWIDTH),
+ y2 - (SCOPEHANDLE_HEIGHT - SCOPE_SELBDWIDTH),
+ SCOPEHANDLE_WIDTH, SCOPEHANDLE_HEIGHT,
+ sh->h_pathname, x->x_tag);
+ sys_vgui("bind %s <Button> {pd [concat %s _click 1 \\;]}\n",
+ sh->h_pathname, sh->h_bindsym->s_name);
+ sys_vgui("bind %s <ButtonRelease> {pd [concat %s _click 0 \\;]}\n",
+ sh->h_pathname, sh->h_bindsym->s_name);
+ sys_vgui("bind %s <Motion> {pd [concat %s _motion %%x %%y \\;]}\n",
+ sh->h_pathname, sh->h_bindsym->s_name);
+ }
+ else
+ {
+ sys_vgui(".x%x.c itemconfigure %s -outline black -width %f\
+ -fill #%2.2x%2.2x%2.2x\n", cv, x->x_bgtag, SCOPE_GRIDWIDTH,
+ x->x_bgred, x->x_bggreen, x->x_bgblue);
+ sys_vgui("destroy %s\n", sh->h_pathname);
+ }
+}
+
+static void scope_delete(t_gobj *z, t_glist *glist)
+{
+ canvas_deletelinesfor(glist, (t_text *)z);
+}
+
+static void scope_drawfgmono(t_scope *x, t_canvas *cv,
+ int x1, int y1, int x2, int y2)
+{
+ int i;
+ float dx, dy, xx, yy, sc;
+ float *bp;
+ dx = (float)(x2 - x1) / (float)x->x_bufsize;
+ sc = ((float)x->x_height - 2.) / (float)(x->x_maxval - x->x_minval);
+ sys_vgui(".x%x.c create line \\\n", cv);
+ for (i = 0, xx = x1, bp = x->x_xbuffer;
+ i < x->x_bufsize; i++, xx += dx, bp++)
+ {
+ yy = (y2 - 1) - sc * (*bp - x->x_minval);
+#ifndef SCOPE_DEBUG
+ if (yy > y2) yy = y2; else if (yy < y1) yy = y1;
+#endif
+ sys_vgui("%d %d \\\n", (int)xx, (int)yy);
+ }
+ sys_vgui("-fill #%2.2x%2.2x%2.2x -width %f -tags {%s %s}\n",
+ x->x_fgred, x->x_fggreen, x->x_fgblue,
+ SCOPE_FGWIDTH, x->x_fgtag, x->x_tag);
+
+ /* margin lines: masking overflows, so that they appear as gaps,
+ rather than clipped signal values, LATER rethink */
+ sys_vgui(".x%x.c create line %d %d %d %d\
+ -fill #%2.2x%2.2x%2.2x -width %f -tags {%s %s}\n",
+ cv, x1, y1, x2, y1, x->x_bgred, x->x_bggreen, x->x_bgblue,
+ 1., x->x_fgtag, x->x_tag);
+ sys_vgui(".x%x.c create line %d %d %d %d\
+ -fill #%2.2x%2.2x%2.2x -width %f -tags {%s %s}\n",
+ cv, x1, y2, x2, y2, x->x_bgred, x->x_bggreen, x->x_bgblue,
+ 1., x->x_fgtag, x->x_tag);
+}
+
+static void scope_drawfgxy(t_scope *x, t_canvas *cv,
+ int x1, int y1, int x2, int y2)
+{
+ int nleft = x->x_bufsize;
+ float *xbp = x->x_xbuffer, *ybp = x->x_ybuffer;
+ char chunk[200 * SCOPE_GUICHUNKXY]; /* LATER estimate */
+ char *chunkp = chunk;
+ char cmd1[64], cmd2[64];
+ float xx, yy, xsc, ysc;
+ xx = yy = 0;
+ /* subtract 1-pixel margins, see below */
+ xsc = ((float)x->x_width - 2.) / (float)(x->x_maxval - x->x_minval);
+ ysc = ((float)x->x_height - 2.) / (float)(x->x_maxval - x->x_minval);
+ sprintf(cmd1, ".x%x.c create line", (int)cv);
+ sprintf(cmd2, "-fill #%2.2x%2.2x%2.2x -width %f -tags {%s %s}\n ",
+ x->x_fgred, x->x_fggreen, x->x_fgblue,
+ SCOPE_FGWIDTH, x->x_fgtag, x->x_tag);
+ while (nleft > SCOPE_GUICHUNKXY)
+ {
+ int i = SCOPE_GUICHUNKXY;
+ while (i--)
+ {
+ float oldx = xx, oldy = yy, dx, dy;
+ xx = x1 + xsc * (*xbp++ - x->x_minval);
+ yy = y2 - ysc * (*ybp++ - x->x_minval);
+ /* using 1-pixel margins */
+ dx = (xx > oldx ? 1. : -1.);
+ dy = (yy > oldy ? 1. : -1.);
+#ifndef SCOPE_DEBUG
+ if (xx < x1 || xx > x2 || yy < y1 || yy > y2)
+ continue;
+#endif
+ sprintf(chunkp, "%s %d %d %d %d %s", cmd1,
+ (int)(xx - dx), (int)(yy - dy),
+ (int)(xx + dx), (int)(yy + dy), cmd2);
+ chunkp += strlen(chunkp);
+ }
+ if (chunkp > chunk)
+ sys_gui(chunk);
+ chunkp = chunk;
+ nleft -= SCOPE_GUICHUNKXY;
+ }
+ while (nleft--)
+ {
+ float oldx = xx, oldy = yy, dx, dy;
+ xx = x1 + xsc * (*xbp++ - x->x_minval);
+ yy = y2 - ysc * (*ybp++ - x->x_minval);
+ /* using 1-pixel margins */
+ dx = (xx > oldx ? 1. : -1.);
+ dy = (yy > oldy ? 1. : -1.);
+#ifndef SCOPE_DEBUG
+ if (xx < x1 || xx > x2 || yy < y1 || yy > y2)
+ continue;
+#endif
+ sprintf(chunkp, "%s %d %d %d %d %s", cmd1,
+ (int)(xx - dx), (int)(yy - dy),
+ (int)(xx + dx), (int)(yy + dy), cmd2);
+ chunkp += strlen(chunkp);
+ }
+ if (chunkp > chunk)
+ sys_gui(chunk);
+}
+
+static void scope_drawbg(t_scope *x, t_canvas *cv,
+ int x1, int y1, int x2, int y2)
+{
+ int i;
+ float dx, dy, xx, yy;
+ dx = (x2 - x1) * 0.125;
+ dy = (y2 - y1) * 0.25;
+ sys_vgui(".x%x.c create rectangle %d %d %d %d\
+ -fill #%2.2x%2.2x%2.2x -width %f -tags {%s %s}\n",
+ cv, x1, y1, x2, y2,
+ x->x_bgred, x->x_bggreen, x->x_bgblue,
+ SCOPE_GRIDWIDTH, x->x_bgtag, x->x_tag);
+ for (i = 0, xx = x1 + dx; i < 7; i++, xx += dx)
+ sys_vgui(".x%x.c create line %f %d %f %d\
+ -width %f -tags {%s %s}\n", cv, xx, y1, xx, y2,
+ SCOPE_GRIDWIDTH, x->x_gridtag, x->x_tag);
+ for (i = 0, yy = y1 + dy; i < 3; i++, yy += dy)
+ sys_vgui(".x%x.c create line %d %f %d %f\
+ -width %f -tags {%s %s}\n", cv, x1, yy, x2, yy,
+ SCOPE_GRIDWIDTH, x->x_gridtag, x->x_tag);
+}
+
+static void scope_drawmono(t_scope *x, t_canvas *cv)
+{
+ int x1, y1, x2, y2;
+ scope_getrect((t_gobj *)x, x->x_glist, &x1, &y1, &x2, &y2);
+ scope_drawbg(x, cv, x1, y1, x2, y2);
+ scope_drawfgmono(x, cv, x1, y1, x2, y2);
+}
+
+static void scope_redrawmono(t_scope *x, t_canvas *cv)
+{
+ int nleft = x->x_bufsize;
+ float *bp = x->x_xbuffer;
+ char chunk[32 * SCOPE_GUICHUNKMONO]; /* LATER estimate */
+ char *chunkp = chunk;
+ int x1, y1, x2, y2;
+ float dx, dy, xx, yy, sc;
+ scope_getrect((t_gobj *)x, x->x_glist, &x1, &y1, &x2, &y2);
+ dx = (float)(x2 - x1) / (float)x->x_bufsize;
+ sc = ((float)x->x_height - 2.) / (float)(x->x_maxval - x->x_minval);
+ xx = x1;
+ sys_vgui(".x%x.c coords %s \\\n", cv, x->x_fgtag);
+ while (nleft > SCOPE_GUICHUNKMONO)
+ {
+ int i = SCOPE_GUICHUNKMONO;
+ while (i--)
+ {
+ yy = (y2 - 1) - sc * (*bp++ - x->x_minval);
+#ifndef SCOPE_DEBUG
+ if (yy > y2) yy = y2; else if (yy < y1) yy = y1;
+#endif
+ sprintf(chunkp, "%d %d ", (int)xx, (int)yy);
+ chunkp += strlen(chunkp);
+ xx += dx;
+ }
+ strcpy(chunkp, "\\\n");
+ sys_gui(chunk);
+ chunkp = chunk;
+ nleft -= SCOPE_GUICHUNKMONO;
+ }
+ while (nleft--)
+ {
+ yy = (y2 - 1) - sc * (*bp++ - x->x_minval);
+#ifndef SCOPE_DEBUG
+ if (yy > y2) yy = y2; else if (yy < y1) yy = y1;
+#endif
+ sprintf(chunkp, "%d %d ", (int)xx, (int)yy);
+ chunkp += strlen(chunkp);
+ xx += dx;
+ }
+ strcpy(chunkp, "\n");
+ sys_gui(chunk);
+}
+
+static void scope_drawxy(t_scope *x, t_canvas *cv)
+{
+ int x1, y1, x2, y2;
+ scope_getrect((t_gobj *)x, x->x_glist, &x1, &y1, &x2, &y2);
+ scope_drawbg(x, cv, x1, y1, x2, y2);
+ scope_drawfgxy(x, cv, x1, y1, x2, y2);
+}
+
+static void scope_redrawxy(t_scope *x, t_canvas *cv)
+{
+ int x1, y1, x2, y2;
+ scope_getrect((t_gobj *)x, x->x_glist, &x1, &y1, &x2, &y2);
+ sys_vgui(".x%x.c delete %s\n", cv, x->x_fgtag);
+ scope_drawfgxy(x, cv, x1, y1, x2, y2);
+}
+
+static void scope_revis(t_scope *x, t_canvas *cv)
+{
+ sys_vgui(".x%x.c delete %s\n", cv, x->x_tag);
+ if (x->x_xymode)
+ scope_drawxy(x, cv);
+ else
+ scope_drawmono(x, cv);
+}
+
+static void scope_vis(t_gobj *z, t_glist *glist, int vis)
+{
+ t_scope *x = (t_scope *)z;
+ t_text *t = (t_text *)z;
+ t_canvas *cv = scope_getcanvas(x, glist);
+ if (vis)
+ {
+ t_scopehandle *sh = (t_scopehandle *)x->x_handle;
+#ifndef PD_MINOR_VERSION
+ rtext_new(glist, t, glist->gl_editor->e_rtext, 0);
+#endif
+ sprintf(sh->h_pathname, ".x%x.h%x", (int)cv, (int)sh);
+ if (x->x_xymode)
+ scope_drawxy(x, cv);
+ else
+ scope_drawmono(x, cv);
+ }
+ else
+ {
+#ifndef PD_MINOR_VERSION
+ t_rtext *rt = glist_findrtext(glist, t);
+ if (rt) rtext_free(rt);
+#endif
+ sys_vgui(".x%x.c delete %s\n", cv, x->x_tag);
+ x->x_canvas = 0;
+ }
+}
+
+static int scope_click(t_gobj *z, t_glist *glist,
+ int xpix, int ypix, int shift, int alt, int dbl,
+ int doit)
+{
+ t_scope *x = (t_scope *)z;
+ x->x_frozen = doit;
+ return (CURSOR_RUNMODE_CLICKME);
+}
+
+/* CHECKED there is only one copy of state variables,
+ the same, whether modified with messages, or in the inspector */
+static void scope_save(t_gobj *z, t_binbuf *b)
+{
+ t_scope *x = (t_scope *)z;
+ t_text *t = (t_text *)x;
+ binbuf_addv(b, "ssiisiiiiiffififiiiiiii;", gensym("#X"), gensym("obj"),
+ (int)t->te_xpix, (int)t->te_ypix,
+ gensym("Scope~"),
+ x->x_width, x->x_height, x->x_period, 3, x->x_bufsize,
+ x->x_minval, x->x_maxval, x->x_delay, 0.,
+ x->x_trigmode, x->x_triglevel,
+ x->x_fgred, x->x_fggreen, x->x_fgblue,
+ x->x_bgred, x->x_bggreen, x->x_bgblue, 0);
+}
+
+static t_widgetbehavior scope_widgetbehavior =
+{
+ scope_getrect,
+ scope_displace,
+ scope_select,
+ 0,
+ scope_delete,
+ scope_vis,
+ scope_click,
+ scope_save,
+ 0
+};
+
+static void scope_setxymode(t_scope *x, int xymode)
+{
+ if (xymode != x->x_xymode)
+ {
+ t_canvas *cv;
+ if (cv = scope_isvisible(x))
+ {
+ sys_vgui(".x%x.c delete %s\n", cv, x->x_fgtag);
+ if (!xymode)
+ {
+ int x1, y1, x2, y2;
+ scope_getrect((t_gobj *)x, x->x_glist, &x1, &y1, &x2, &y2);
+ scope_drawfgmono(x, cv, x1, y1, x2, y2);
+ }
+ }
+ x->x_xymode = xymode;
+ scope_clear(x, 0);
+ }
+}
+
+static void scope_tick(t_scope *x)
+{
+ t_canvas *cv;
+ if (!x->x_frozen && (cv = scope_isvisible(x)))
+ {
+ if (x->x_xymode)
+ scope_redrawxy(x, cv);
+ else
+ scope_redrawmono(x, cv);
+ }
+ scope_clear(x, 1);
+}
+
+static void scopehandle__clickhook(t_scopehandle *sh, t_floatarg f)
+{
+ int newstate = (int)f;
+ if (sh->h_dragon && newstate == 0)
+ {
+ t_scope *x = sh->h_master;
+ t_canvas *cv;
+ x->x_width += sh->h_dragx;
+ x->x_height += sh->h_dragy;
+ if (cv = scope_isvisible(x))
+ {
+ sys_vgui(".x%x.c delete %s\n", cv, sh->h_outlinetag);
+ scope_revis(x, cv);
+ sys_vgui("destroy %s\n", sh->h_pathname);
+ scope_select((t_gobj *)x, x->x_glist, 1);
+ canvas_fixlinesfor(x->x_glist, (t_text *)x); /* 2nd inlet */
+ }
+ }
+ else if (!sh->h_dragon && newstate)
+ {
+ t_scope *x = sh->h_master;
+ t_canvas *cv;
+ if (cv = scope_isvisible(x))
+ {
+ int x1, y1, x2, y2;
+ scope_getrect((t_gobj *)x, x->x_glist, &x1, &y1, &x2, &y2);
+ sys_vgui("lower %s\n", sh->h_pathname);
+ sys_vgui(".x%x.c create rectangle %d %d %d %d\
+ -outline blue -width %f -tags %s\n",
+ cv, x1, y1, x2, y2, SCOPE_SELBDWIDTH, sh->h_outlinetag);
+ }
+ sh->h_dragx = 0;
+ sh->h_dragy = 0;
+ }
+ sh->h_dragon = newstate;
+}
+
+static void scopehandle__motionhook(t_scopehandle *sh,
+ t_floatarg f1, t_floatarg f2)
+{
+ if (sh->h_dragon)
+ {
+ t_scope *x = sh->h_master;
+ int dx = (int)f1, dy = (int)f2;
+ int x1, y1, x2, y2, newx, newy;
+ scope_getrect((t_gobj *)x, x->x_glist, &x1, &y1, &x2, &y2);
+ newx = x2 + dx;
+ newy = y2 + dy;
+ if (newx > x1 + SCOPE_MINWIDTH && newy > y1 + SCOPE_MINHEIGHT)
+ {
+ t_canvas *cv;
+ if (cv = scope_isvisible(x))
+ sys_vgui(".x%x.c coords %s %d %d %d %d\n",
+ cv, sh->h_outlinetag, x1, y1, newx, newy);
+ sh->h_dragx = dx;
+ sh->h_dragy = dy;
+ }
+ }
+}
+
+static void scope_free(t_scope *x)
+{
+ if (x->x_clock) clock_free(x->x_clock);
+ if (x->x_xbuffer != x->x_xbufini)
+ freebytes(x->x_xbuffer, x->x_allocsize * sizeof(*x->x_xbuffer));
+ if (x->x_ybuffer != x->x_ybufini)
+ freebytes(x->x_ybuffer, x->x_allocsize * sizeof(*x->x_ybuffer));
+ if (x->x_handle)
+ {
+ pd_unbind(x->x_handle, ((t_scopehandle *)x->x_handle)->h_bindsym);
+ pd_free(x->x_handle);
+ }
+}
+
+static void *scope_new(t_symbol *s, int ac, t_atom *av)
+{
+ t_scope *x = (t_scope *)pd_new(scope_class);
+ t_scopehandle *sh;
+ t_float width = SCOPE_DEFWIDTH;
+ t_float height = SCOPE_DEFHEIGHT;
+ char buf[64];
+ x->x_glist = canvas_getcurrent();
+ x->x_canvas = 0;
+ loud_floatarg(*(t_pd *)x, 0, ac, av, &width,
+ SCOPE_MINWIDTH, 0,
+ LOUD_CLIP | LOUD_WARN, 0, "width");
+ x->x_width = (int)width;
+ loud_floatarg(*(t_pd *)x, 1, ac, av, &height,
+ SCOPE_MINHEIGHT, 0,
+ LOUD_CLIP | LOUD_WARN, 0, "height");
+ x->x_height = (int)height;
+ scope_period(x, 0, ac, av);
+ /* CHECKME 6th argument (default 3 for mono, 1 for xy */
+ scope_bufsize(x, 0, ac, av);
+ scope_range(x, 0, ac, av);
+ scope_delay(x, 0, ac, av);
+ /* CHECKME 11th argument (default 0.) */
+ scope_trigger(x, 0, ac, av);
+ scope_triglevel(x, 0, ac, av);
+ scope_frgb(x, 0, ac, av);
+ scope_brgb(x, 0, ac, av);
+ /* CHECKME last argument (default 0) */
+
+ sprintf(x->x_tag, "all%x", (int)x);
+ sprintf(x->x_bgtag, "bg%x", (int)x);
+ sprintf(x->x_gridtag, "gr%x", (int)x);
+ sprintf(x->x_fgtag, "fg%x", (int)x);
+ x->x_xymode = 0;
+ x->x_ksr = sys_getsr() * 0.001; /* redundant */
+ x->x_frozen = 0;
+ inlet_new((t_object *)x, (t_pd *)x, &s_signal, &s_signal);
+ x->x_clock = clock_new(x, (t_method)scope_tick);
+ scope_clear(x, 0);
+
+ x->x_handle = pd_new(scopehandle_class);
+ sh = (t_scopehandle *)x->x_handle;
+ sh->h_master = x;
+ sprintf(buf, "_h%x", (int)sh);
+ pd_bind(x->x_handle, sh->h_bindsym = gensym(buf));
+ sprintf(sh->h_outlinetag, "h%x", (int)sh);
+ sh->h_dragon = 0;
+ return (x);
+}
+
+void Scope_tilde_setup(void)
+{
+ scope_class = class_new(gensym("Scope~"),
+ (t_newmethod)scope_new,
+ (t_method)scope_free,
+ sizeof(t_scope), 0, A_GIMME, 0);
+ sic_setup(scope_class, scope_dsp, scope_float);
+ class_addmethod(scope_class, (t_method)scope_bufsize,
+ gensym("bufsize"), A_GIMME, 0);
+ class_addmethod(scope_class, (t_method)scope_range,
+ gensym("range"), A_GIMME, 0);
+ class_addmethod(scope_class, (t_method)scope_delay,
+ gensym("delay"), A_GIMME, 0);
+ class_addmethod(scope_class, (t_method)scope_trigger,
+ gensym("trigger"), A_GIMME, 0);
+ class_addmethod(scope_class, (t_method)scope_triglevel,
+ gensym("triglevel"), A_GIMME, 0);
+ class_addmethod(scope_class, (t_method)scope_frgb,
+ gensym("frgb"), A_GIMME, 0);
+ class_addmethod(scope_class, (t_method)scope_brgb,
+ gensym("brgb"), A_GIMME, 0);
+ class_addmethod(scope_class, (t_method)scope_click,
+ gensym("click"),
+ A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0);
+ class_setwidget(scope_class, &scope_widgetbehavior);
+ scopehandle_class = class_new(gensym("_scopehandle"), 0, 0,
+ sizeof(t_scopehandle), CLASS_PD, 0);
+ class_addmethod(scopehandle_class, (t_method)scopehandle__clickhook,
+ gensym("_click"), A_FLOAT, 0);
+ class_addmethod(scopehandle_class, (t_method)scopehandle__motionhook,
+ gensym("_motion"), A_FLOAT, A_FLOAT, 0);
+}
diff --git a/cyclone/sickle/Snapshot.c b/cyclone/sickle/Snapshot.c
new file mode 100644
index 0000000..7c7e974
--- /dev/null
+++ b/cyclone/sickle/Snapshot.c
@@ -0,0 +1,161 @@
+/* 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"
+
+/* CHECKME for a fixed minimum deltime, if any (5ms for c74's metro) */
+
+typedef struct _snapshot
+{
+ t_sic x_sic;
+ t_float x_value;
+ int x_rqoffset; /* requested */
+ int x_offset; /* effective (truncated) */
+ int x_stopped;
+ int x_on; /* !stopped && deltime > 0 */
+ float x_deltime;
+ int x_npoints;
+ int x_nleft;
+ int x_nblock;
+ float x_ksr;
+ t_clock *x_clock;
+} t_snapshot;
+
+static t_class *snapshot_class;
+
+static void snapshot_tick(t_snapshot *x)
+{
+ outlet_float(((t_object *)x)->ob_outlet, x->x_value);
+}
+
+static void snapshot_bang(t_snapshot *x)
+{
+ outlet_float(((t_object *)x)->ob_outlet, x->x_value);
+}
+
+static void snapshot_correct(t_snapshot *x)
+{
+ int wason = x->x_on;
+ x->x_offset =
+ (x->x_rqoffset < x->x_nblock ? x->x_rqoffset : x->x_nblock - 1);
+ x->x_npoints = x->x_deltime * x->x_ksr - x->x_nblock + x->x_offset;
+ if (x->x_on = (!x->x_stopped && x->x_deltime > 0.))
+ {
+ if (!wason) x->x_nleft = x->x_offset; /* CHECKME */
+ }
+ else if (wason) clock_unset(x->x_clock);
+}
+
+static void snapshot_start(t_snapshot *x)
+{
+ x->x_stopped = 0;
+ if (!x->x_on && x->x_deltime > 0.) /* CHECKED no default */
+ {
+ x->x_nleft = x->x_offset; /* CHECKME */
+ x->x_on = 1;
+ }
+}
+
+static void snapshot_stop(t_snapshot *x)
+{
+ x->x_stopped = 1;
+ if (x->x_on)
+ {
+ clock_unset(x->x_clock);
+ x->x_on = 0;
+ }
+}
+
+static void snapshot_float(t_snapshot *x, t_float f)
+{
+ /* CHECKED nonzero/zero, CHECKED incompatible: int only (float ignored) */
+ if (f != 0.)
+ snapshot_start(x);
+ else
+ snapshot_stop(x);
+}
+
+static void snapshot_ft1(t_snapshot *x, t_floatarg f)
+{
+ x->x_deltime = (f > 0. ? f : 0.); /* CHECKED */
+ /* CHECKED setting deltime to a positive value starts the clock
+ only if it was stopped by setting deltime to zero */
+ snapshot_correct(x);
+}
+
+static void snapshot_offset(t_snapshot *x, t_floatarg f)
+{
+ int i = (int)f; /* CHECKME */
+ x->x_rqoffset = (i >= 0 ? i : 0); /* CHECKME */
+ /* CHECKME if the change has an effect prior to next dsp_add call */
+ snapshot_correct(x);
+}
+
+static t_int *snapshot_perform(t_int *w)
+{
+ t_snapshot *x = (t_snapshot *)(w[1]);
+ t_float *in = (t_float *)(w[2]);
+ x->x_value = in[x->x_offset];
+ if (x->x_on)
+ {
+ /* CHECKME nleft vs offset */
+ if (x->x_nleft < x->x_nblock)
+ {
+ clock_delay(x->x_clock, 0);
+ x->x_nleft = x->x_npoints;
+ }
+ else x->x_nleft -= x->x_nblock;
+ }
+ return (w + 3);
+}
+
+static void snapshot_dsp(t_snapshot *x, t_signal **sp)
+{
+ x->x_nblock = sp[0]->s_n;
+ x->x_ksr = sp[0]->s_sr * 0.001;
+ snapshot_correct(x);
+ x->x_nleft = x->x_offset; /* CHECKME */
+ dsp_add(snapshot_perform, 2, x, sp[0]->s_vec);
+}
+
+static void snapshot_free(t_snapshot *x)
+{
+ if (x->x_clock) clock_free(x->x_clock);
+}
+
+static void *snapshot_new(t_floatarg f1, t_floatarg f2)
+{
+ t_snapshot *x = (t_snapshot *)pd_new(snapshot_class);
+ x->x_stopped = 0; /* CHECKED */
+ x->x_on = 0;
+ x->x_value = 0;
+ x->x_nblock = 64; /* redundant */
+ x->x_ksr = 44.1; /* redundant */
+ inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft1"));
+ outlet_new((t_object *)x, &s_float);
+ x->x_clock = clock_new(x, (t_method)snapshot_tick);
+ snapshot_offset(x, f2); /* CHECKME (this is fixed at nblock-1 in Pd) */
+ snapshot_ft1(x, f1);
+ return (x);
+}
+
+void Snapshot_tilde_setup(void)
+{
+ snapshot_class = class_new(gensym("Snapshot~"),
+ (t_newmethod)snapshot_new,
+ (t_method)snapshot_free,
+ sizeof(t_snapshot), 0,
+ A_DEFFLOAT, A_DEFFLOAT, 0);
+ sic_setup(snapshot_class, snapshot_dsp, snapshot_float);
+ class_addbang(snapshot_class, snapshot_bang);
+ class_addmethod(snapshot_class, (t_method)snapshot_ft1,
+ gensym("ft1"), A_FLOAT, 0);
+ class_addmethod(snapshot_class, (t_method)snapshot_offset,
+ gensym("offset"), A_FLOAT, 0);
+ class_addmethod(snapshot_class, (t_method)snapshot_start,
+ gensym("start"), 0);
+ class_addmethod(snapshot_class, (t_method)snapshot_stop,
+ gensym("stop"), 0);
+}
diff --git a/cyclone/sickle/abs.c b/cyclone/sickle/abs.c
new file mode 100644
index 0000000..cde26a5
--- /dev/null
+++ b/cyclone/sickle/abs.c
@@ -0,0 +1,42 @@
+/* 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"
+
+typedef t_sic t_abs;
+static t_class *abs_class;
+
+static t_int *abs_perform(t_int *w)
+{
+ int nblock = (int)(w[1]);
+ t_float *in = (t_float *)(w[2]);
+ t_float *out = (t_float *)(w[3]);
+ while (nblock--)
+ {
+ float f = *in++;
+ *out++ = (f >= 0 ? f : -f);
+ }
+ return (w + 4);
+}
+
+static void abs_dsp(t_abs *x, t_signal **sp)
+{
+ dsp_add(abs_perform, 3, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec);
+}
+
+static void *abs_new(void)
+{
+ t_abs *x = (t_abs *)pd_new(abs_class);
+ outlet_new((t_object *)x, &s_signal);
+ return (x);
+}
+
+void abs_tilde_setup(void)
+{
+ abs_class = class_new(gensym("abs~"),
+ (t_newmethod)abs_new, 0,
+ sizeof(t_abs), 0, 0);
+ sic_setup(abs_class, abs_dsp, SIC_FLOATTOSIGNAL);
+}
diff --git a/cyclone/sickle/acos.c b/cyclone/sickle/acos.c
new file mode 100644
index 0000000..1dd5719
--- /dev/null
+++ b/cyclone/sickle/acos.c
@@ -0,0 +1,48 @@
+/* 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 <math.h>
+#include "m_pd.h"
+#include "sickle/sic.h"
+
+#if defined(NT) || defined(MACOSX)
+/* cf pd/src/x_arithmetic.c */
+#define acosf acos
+#endif
+
+typedef t_sic t_acos;
+static t_class *acos_class;
+
+static t_int *acos_perform(t_int *w)
+{
+ int nblock = (int)(w[1]);
+ t_float *in = (t_float *)(w[2]);
+ t_float *out = (t_float *)(w[3]);
+ while (nblock--)
+ {
+ float f = *in++;
+ *out++ = acosf(f); /* CHECKED no protection against NaNs */
+ }
+ return (w + 4);
+}
+
+static void acos_dsp(t_acos *x, t_signal **sp)
+{
+ dsp_add(acos_perform, 3, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec);
+}
+
+static void *acos_new(void)
+{
+ t_acos *x = (t_acos *)pd_new(acos_class);
+ outlet_new((t_object *)x, &s_signal);
+ return (x);
+}
+
+void acos_tilde_setup(void)
+{
+ acos_class = class_new(gensym("acos~"),
+ (t_newmethod)acos_new, 0,
+ sizeof(t_acos), 0, 0);
+ sic_setup(acos_class, acos_dsp, SIC_FLOATTOSIGNAL);
+}
diff --git a/cyclone/sickle/acosh.c b/cyclone/sickle/acosh.c
new file mode 100644
index 0000000..392ad97
--- /dev/null
+++ b/cyclone/sickle/acosh.c
@@ -0,0 +1,48 @@
+/* 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 <math.h>
+#include "m_pd.h"
+#include "sickle/sic.h"
+
+/* LATER ask about osx */
+#if defined(NT) || defined(MACOSX)
+#define acoshf(x) (log(x + sqrt(x * x - 1)))
+#endif
+
+typedef t_sic t_acosh;
+static t_class *acosh_class;
+
+static t_int *acosh_perform(t_int *w)
+{
+ int nblock = (int)(w[1]);
+ t_float *in = (t_float *)(w[2]);
+ t_float *out = (t_float *)(w[3]);
+ while (nblock--)
+ {
+ float f = *in++;
+ *out++ = acoshf(f); /* CHECKME no protection against NaNs */
+ }
+ return (w + 4);
+}
+
+static void acosh_dsp(t_acosh *x, t_signal **sp)
+{
+ dsp_add(acosh_perform, 3, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec);
+}
+
+static void *acosh_new(void)
+{
+ t_acosh *x = (t_acosh *)pd_new(acosh_class);
+ outlet_new((t_object *)x, &s_signal);
+ return (x);
+}
+
+void acosh_tilde_setup(void)
+{
+ acosh_class = class_new(gensym("acosh~"),
+ (t_newmethod)acosh_new, 0,
+ sizeof(t_acosh), 0, 0);
+ sic_setup(acosh_class, acosh_dsp, SIC_FLOATTOSIGNAL);
+}
diff --git a/cyclone/sickle/allpass.c b/cyclone/sickle/allpass.c
new file mode 100644
index 0000000..761d0cc
--- /dev/null
+++ b/cyclone/sickle/allpass.c
@@ -0,0 +1,153 @@
+/* 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 <string.h>
+#include "m_pd.h"
+#include "sickle/sic.h"
+
+typedef struct _allpass
+{
+ t_sic x_sic;
+ float x_sr;
+ float x_ksr;
+ t_float *x_buf;
+ int x_bufsize; /* as allocated */
+ int x_maxsize; /* as used */
+ float x_maxdelay; /* same in ms */
+ int x_phase; /* writing head */
+} t_allpass;
+
+static t_class *allpass_class;
+
+/* maximum delay defaults to 50 ms (cycling has 10 ms here) */
+#define ALLPASS_DEFMAXDELAY 50.0
+
+/* LATER choose the best way (compare with comb~) */
+#define ALLPASS_MAXFEEDBACK 0.999
+
+static void allpass_clear(t_allpass *x)
+{
+ memset(x->x_buf, 0, x->x_maxsize * sizeof(*x->x_buf));
+ x->x_phase = 0;
+}
+
+static void allpass_resize(t_allpass *x, int newsize)
+{
+ if (newsize > 0 && newsize != x->x_maxsize)
+ {
+ if (newsize > x->x_bufsize)
+ {
+ x->x_buf = resizebytes(x->x_buf,
+ x->x_bufsize * sizeof(*x->x_buf),
+ newsize * sizeof(*x->x_buf));
+ /* LATER test for failure */
+ x->x_bufsize = newsize;
+ }
+ x->x_maxsize = newsize;
+ }
+ allpass_clear(x);
+}
+
+static t_int *allpass_perform(t_int *w)
+{
+ t_allpass *x = (t_allpass *)(w[1]);
+ int nblock = (int)(w[2]);
+ t_float *xin = (t_float *)(w[3]);
+ t_float *din = (t_float *)(w[4]);
+ t_float *gin = (t_float *)(w[5]);
+ t_float *out = (t_float *)(w[6]);
+ t_float *buf = x->x_buf;
+ int maxsize = x->x_maxsize;
+ int guardpoint = maxsize - 1;
+ float ksr = x->x_ksr;
+ int wph = x->x_phase;
+ while (nblock--)
+ { /* TDFII scheme */
+ float xn = *xin++;
+ float delsize = ksr * *din++;
+ float gain = *gin++;
+ float yn;
+ float rph; /* reading head */
+ if (gain < -ALLPASS_MAXFEEDBACK) gain = -ALLPASS_MAXFEEDBACK;
+ else if (gain > ALLPASS_MAXFEEDBACK) gain = ALLPASS_MAXFEEDBACK;
+ yn = -gain * xn;
+ if (delsize > 0)
+ {
+ int ndx;
+ float val;
+ rph = wph - (delsize > guardpoint ? guardpoint : delsize);
+ if (rph < 0) rph += guardpoint;
+ ndx = (int)rph;
+ val = buf[ndx];
+ /* ``a cheezy linear interpolation'' ala msp,
+ (vd~ uses 4-point interpolation...) */
+ yn += val + (buf[ndx+1] - val) * (rph - ndx);
+ }
+ *out++ = yn;
+ if (wph == guardpoint)
+ {
+ buf[wph] = *buf = xn + gain * yn;
+ wph = 1;
+ }
+ else buf[wph++] = xn + gain * yn;
+ }
+ x->x_phase = wph;
+ return (w + 7);
+}
+
+static void allpass_dsp(t_allpass *x, t_signal **sp)
+{
+ float sr = sp[0]->s_sr;
+ if (sr != x->x_sr)
+ {
+ x->x_sr = sr;
+ x->x_ksr = sr * 0.001;
+ allpass_resize(x, x->x_ksr * x->x_maxdelay);
+ }
+ else allpass_clear(x);
+ dsp_add(allpass_perform, 6, x, sp[0]->s_n,
+ sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec);
+}
+
+static void *allpass_new(t_floatarg f1, t_floatarg f2, t_floatarg f3)
+{
+ t_allpass *x;
+ float maxdelay = (f1 > 0 ? f1 : ALLPASS_DEFMAXDELAY);
+ float sr = sys_getsr();
+ float ksr = sr * 0.001;
+ int bufsize = ksr * maxdelay;
+ t_float *buf = (t_float *)getbytes(bufsize * sizeof(*buf));
+ if (!buf)
+ return (0);
+ x = (t_allpass *)pd_new(allpass_class);
+ x->x_maxdelay = maxdelay;
+ x->x_sr = sr;
+ x->x_ksr = ksr;
+ x->x_bufsize = x->x_maxsize = bufsize;
+ x->x_buf = buf;
+ if (f2 < 0) f2 = 0;
+ if (f3 < -ALLPASS_MAXFEEDBACK) f3 = -ALLPASS_MAXFEEDBACK;
+ else if (f3 > ALLPASS_MAXFEEDBACK) f3 = ALLPASS_MAXFEEDBACK;
+ sic_newinlet((t_sic *)x, f2);
+ sic_newinlet((t_sic *)x, f3);
+ outlet_new((t_object *)x, &s_signal);
+ allpass_clear(x);
+ return (x);
+}
+
+static void allpass_free(t_allpass *x)
+{
+ if (x->x_buf) freebytes(x->x_buf, x->x_bufsize * sizeof(*x->x_buf));
+}
+
+void allpass_tilde_setup(void)
+{
+ allpass_class = class_new(gensym("allpass~"),
+ (t_newmethod)allpass_new,
+ (t_method)allpass_free,
+ sizeof(t_allpass), 0,
+ A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0);
+ sic_setup(allpass_class, allpass_dsp, SIC_FLOATTOSIGNAL);
+ class_addmethod(allpass_class, (t_method)allpass_clear, gensym("clear"), 0);
+}
diff --git a/cyclone/sickle/allsickles.c b/cyclone/sickle/allsickles.c
new file mode 100644
index 0000000..624a48d
--- /dev/null
+++ b/cyclone/sickle/allsickles.c
@@ -0,0 +1,134 @@
+// Do not edit this file, run "make" instead.
+
+/* 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. */
+
+void Clip_tilde_setup(void);
+void Line_tilde_setup(void);
+void Scope_tilde_setup(void);
+void Snapshot_tilde_setup(void);
+void abs_tilde_setup(void);
+void acos_tilde_setup(void);
+void acosh_tilde_setup(void);
+void allpass_tilde_setup(void);
+void asin_tilde_setup(void);
+void asinh_tilde_setup(void);
+void atan_tilde_setup(void);
+void atan2_tilde_setup(void);
+void atanh_tilde_setup(void);
+void average_tilde_setup(void);
+void avg_tilde_setup(void);
+void bitand_tilde_setup(void);
+void bitnot_tilde_setup(void);
+void bitor_tilde_setup(void);
+void bitshift_tilde_setup(void);
+void bitxor_tilde_setup(void);
+void capture_tilde_setup(void);
+void cartopol_tilde_setup(void);
+void change_tilde_setup(void);
+void click_tilde_setup(void);
+void comb_tilde_setup(void);
+void cosh_tilde_setup(void);
+void cosx_tilde_setup(void);
+void count_tilde_setup(void);
+void cycle_tilde_setup(void);
+void delay_tilde_setup(void);
+void delta_tilde_setup(void);
+void deltaclip_tilde_setup(void);
+void edge_tilde_setup(void);
+void frameaccum_tilde_setup(void);
+void framedelta_tilde_setup(void);
+void index_tilde_setup(void);
+void kink_tilde_setup(void);
+void linedrive_setup(void);
+void log_tilde_setup(void);
+void lookup_tilde_setup(void);
+void minmax_tilde_setup(void);
+void peakamp_tilde_setup(void);
+void peek_tilde_setup(void);
+void phasewrap_tilde_setup(void);
+void play_tilde_setup(void);
+void poltocar_tilde_setup(void);
+void pow_tilde_setup(void);
+void rampsmooth_tilde_setup(void);
+void rand_tilde_setup(void);
+void record_tilde_setup(void);
+void sah_tilde_setup(void);
+void sinh_tilde_setup(void);
+void sinx_tilde_setup(void);
+void slide_tilde_setup(void);
+void spike_tilde_setup(void);
+void tanh_tilde_setup(void);
+void tanx_tilde_setup(void);
+void train_tilde_setup(void);
+void trapezoid_tilde_setup(void);
+void triangle_tilde_setup(void);
+void vectral_tilde_setup(void);
+void wave_tilde_setup(void);
+
+void allsickles_setup(void)
+{
+ Clip_tilde_setup();
+ Line_tilde_setup();
+ Scope_tilde_setup();
+ Snapshot_tilde_setup();
+ abs_tilde_setup();
+ acos_tilde_setup();
+ acosh_tilde_setup();
+ allpass_tilde_setup();
+ asin_tilde_setup();
+ asinh_tilde_setup();
+ atan_tilde_setup();
+ atan2_tilde_setup();
+ atanh_tilde_setup();
+ average_tilde_setup();
+ avg_tilde_setup();
+ bitand_tilde_setup();
+ bitnot_tilde_setup();
+ bitor_tilde_setup();
+ bitshift_tilde_setup();
+ bitxor_tilde_setup();
+ capture_tilde_setup();
+ cartopol_tilde_setup();
+ change_tilde_setup();
+ click_tilde_setup();
+ comb_tilde_setup();
+ cosh_tilde_setup();
+ cosx_tilde_setup();
+ count_tilde_setup();
+ cycle_tilde_setup();
+ delay_tilde_setup();
+ delta_tilde_setup();
+ deltaclip_tilde_setup();
+ edge_tilde_setup();
+ frameaccum_tilde_setup();
+ framedelta_tilde_setup();
+ index_tilde_setup();
+ kink_tilde_setup();
+ linedrive_setup();
+ log_tilde_setup();
+ lookup_tilde_setup();
+ minmax_tilde_setup();
+ peakamp_tilde_setup();
+ peek_tilde_setup();
+ phasewrap_tilde_setup();
+ play_tilde_setup();
+ poltocar_tilde_setup();
+ pow_tilde_setup();
+ rampsmooth_tilde_setup();
+ rand_tilde_setup();
+ record_tilde_setup();
+ sah_tilde_setup();
+ sinh_tilde_setup();
+ sinx_tilde_setup();
+ slide_tilde_setup();
+ spike_tilde_setup();
+ tanh_tilde_setup();
+ tanx_tilde_setup();
+ train_tilde_setup();
+ trapezoid_tilde_setup();
+ triangle_tilde_setup();
+ vectral_tilde_setup();
+ wave_tilde_setup();
+}
diff --git a/cyclone/sickle/asin.c b/cyclone/sickle/asin.c
new file mode 100644
index 0000000..05e5c28
--- /dev/null
+++ b/cyclone/sickle/asin.c
@@ -0,0 +1,48 @@
+/* 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 <math.h>
+#include "m_pd.h"
+#include "sickle/sic.h"
+
+#if defined(NT) || defined(MACOSX)
+/* cf pd/src/x_arithmetic.c */
+#define asinf asin
+#endif
+
+typedef t_sic t_asin;
+static t_class *asin_class;
+
+static t_int *asin_perform(t_int *w)
+{
+ int nblock = (int)(w[1]);
+ t_float *in = (t_float *)(w[2]);
+ t_float *out = (t_float *)(w[3]);
+ while (nblock--)
+ {
+ float f = *in++;
+ *out++ = asinf(f); /* CHECKME no protection against NaNs */
+ }
+ return (w + 4);
+}
+
+static void asin_dsp(t_asin *x, t_signal **sp)
+{
+ dsp_add(asin_perform, 3, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec);
+}
+
+static void *asin_new(void)
+{
+ t_asin *x = (t_asin *)pd_new(asin_class);
+ outlet_new((t_object *)x, &s_signal);
+ return (x);
+}
+
+void asin_tilde_setup(void)
+{
+ asin_class = class_new(gensym("asin~"),
+ (t_newmethod)asin_new, 0,
+ sizeof(t_asin), 0, 0);
+ sic_setup(asin_class, asin_dsp, SIC_FLOATTOSIGNAL);
+}
diff --git a/cyclone/sickle/asinh.c b/cyclone/sickle/asinh.c
new file mode 100644
index 0000000..931cb1f
--- /dev/null
+++ b/cyclone/sickle/asinh.c
@@ -0,0 +1,48 @@
+/* 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 <math.h>
+#include "m_pd.h"
+#include "sickle/sic.h"
+
+/* LATER ask about osx */
+#if defined(NT) || defined(MACOSX)
+#define asinhf(x) (log(x + sqrt(x * x + 1)))
+#endif
+
+typedef t_sic t_asinh;
+static t_class *asinh_class;
+
+static t_int *asinh_perform(t_int *w)
+{
+ int nblock = (int)(w[1]);
+ t_float *in = (t_float *)(w[2]);
+ t_float *out = (t_float *)(w[3]);
+ while (nblock--)
+ {
+ float f = *in++;
+ *out++ = asinhf(f); /* CHECKME no protection against NaNs */
+ }
+ return (w + 4);
+}
+
+static void asinh_dsp(t_asinh *x, t_signal **sp)
+{
+ dsp_add(asinh_perform, 3, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec);
+}
+
+static void *asinh_new(void)
+{
+ t_asinh *x = (t_asinh *)pd_new(asinh_class);
+ outlet_new((t_object *)x, &s_signal);
+ return (x);
+}
+
+void asinh_tilde_setup(void)
+{
+ asinh_class = class_new(gensym("asinh~"),
+ (t_newmethod)asinh_new, 0,
+ sizeof(t_asinh), 0, 0);
+ sic_setup(asinh_class, asinh_dsp, SIC_FLOATTOSIGNAL);
+}
diff --git a/cyclone/sickle/atan.c b/cyclone/sickle/atan.c
new file mode 100644
index 0000000..f541fa4
--- /dev/null
+++ b/cyclone/sickle/atan.c
@@ -0,0 +1,48 @@
+/* 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 <math.h>
+#include "m_pd.h"
+#include "sickle/sic.h"
+
+#if defined(NT) || defined(MACOSX)
+/* cf pd/src/x_arithmetic.c */
+#define atanf atan
+#endif
+
+typedef t_sic t_atan;
+static t_class *atan_class;
+
+static t_int *atan_perform(t_int *w)
+{
+ int nblock = (int)(w[1]);
+ t_float *in = (t_float *)(w[2]);
+ t_float *out = (t_float *)(w[3]);
+ while (nblock--)
+ {
+ float f = *in++;
+ *out++ = atanf(f); /* CHECKME no protection against NaNs */
+ }
+ return (w + 4);
+}
+
+static void atan_dsp(t_atan *x, t_signal **sp)
+{
+ dsp_add(atan_perform, 3, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec);
+}
+
+static void *atan_new(void)
+{
+ t_atan *x = (t_atan *)pd_new(atan_class);
+ outlet_new((t_object *)x, &s_signal);
+ return (x);
+}
+
+void atan_tilde_setup(void)
+{
+ atan_class = class_new(gensym("atan~"),
+ (t_newmethod)atan_new, 0,
+ sizeof(t_atan), 0, 0);
+ sic_setup(atan_class, atan_dsp, SIC_FLOATTOSIGNAL);
+}
diff --git a/cyclone/sickle/atan2.c b/cyclone/sickle/atan2.c
new file mode 100644
index 0000000..171fc17
--- /dev/null
+++ b/cyclone/sickle/atan2.c
@@ -0,0 +1,53 @@
+/* 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 <math.h>
+#include "m_pd.h"
+#include "sickle/sic.h"
+
+#if defined(NT) || defined(MACOSX)
+/* cf pd/src/x_arithmetic.c */
+#define atan2f atan2
+#endif
+
+typedef t_sic t_atan2;
+static t_class *atan2_class;
+
+static t_int *atan2_perform(t_int *w)
+{
+ int nblock = (int)(w[1]);
+ t_float *in1 = (t_float *)(w[2]);
+ t_float *in2 = (t_float *)(w[3]);
+ t_float *out = (t_float *)(w[4]);
+ while (nblock--)
+ {
+ float f1 = *in1++;
+ float f2 = *in2++;
+ /* CHECKED arg order, range (radians) */
+ *out++ = atan2f(f1, f2);
+ }
+ return (w + 5);
+}
+
+static void atan2_dsp(t_atan2 *x, t_signal **sp)
+{
+ dsp_add(atan2_perform, 4, sp[0]->s_n,
+ sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec);
+}
+
+static void *atan2_new(t_floatarg f)
+{
+ t_atan2 *x = (t_atan2 *)pd_new(atan2_class);
+ sic_newinlet((t_sic *)x, f); /* CHECKED x-value argument */
+ outlet_new((t_object *)x, &s_signal);
+ return (x);
+}
+
+void atan2_tilde_setup(void)
+{
+ atan2_class = class_new(gensym("atan2~"),
+ (t_newmethod)atan2_new, 0,
+ sizeof(t_atan2), 0, A_DEFFLOAT, 0);
+ sic_setup(atan2_class, atan2_dsp, SIC_FLOATTOSIGNAL);
+}
diff --git a/cyclone/sickle/atanh.c b/cyclone/sickle/atanh.c
new file mode 100644
index 0000000..464f955
--- /dev/null
+++ b/cyclone/sickle/atanh.c
@@ -0,0 +1,48 @@
+/* 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 <math.h>
+#include "m_pd.h"
+#include "sickle/sic.h"
+
+/* LATER ask about osx */
+#if defined(NT) || defined(MACOSX)
+#define atanhf(x) (log((1 + x) / (1 - x)) * 0.5)
+#endif
+
+typedef t_sic t_atanh;
+static t_class *atanh_class;
+
+static t_int *atanh_perform(t_int *w)
+{
+ int nblock = (int)(w[1]);
+ t_float *in = (t_float *)(w[2]);
+ t_float *out = (t_float *)(w[3]);
+ while (nblock--)
+ {
+ float f = *in++;
+ *out++ = atanhf(f); /* CHECKME no protection against NaNs */
+ }
+ return (w + 4);
+}
+
+static void atanh_dsp(t_atanh *x, t_signal **sp)
+{
+ dsp_add(atanh_perform, 3, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec);
+}
+
+static void *atanh_new(void)
+{
+ t_atanh *x = (t_atanh *)pd_new(atanh_class);
+ outlet_new((t_object *)x, &s_signal);
+ return (x);
+}
+
+void atanh_tilde_setup(void)
+{
+ atanh_class = class_new(gensym("atanh~"),
+ (t_newmethod)atanh_new, 0,
+ sizeof(t_atanh), 0, 0);
+ sic_setup(atanh_class, atanh_dsp, SIC_FLOATTOSIGNAL);
+}
diff --git a/cyclone/sickle/average.c b/cyclone/sickle/average.c
new file mode 100644
index 0000000..ea330c1
--- /dev/null
+++ b/cyclone/sickle/average.c
@@ -0,0 +1,194 @@
+/* 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. */
+
+/* CHECKME no reset after changing of a window size? */
+/* CHECKME overlap */
+
+#include <math.h>
+#include "m_pd.h"
+#include "sickle/sic.h"
+
+#if defined(NT) || defined(MACOSX)
+/* cf pd/src/x_arithmetic.c */
+#define sqrtf sqrt
+#endif
+
+#define AVERAGE_DEFNPOINTS 100 /* CHECKME */
+#define AVERAGE_DEFMODE AVERAGE_BIPOLAR
+enum { AVERAGE_BIPOLAR, AVERAGE_ABSOLUTE, AVERAGE_RMS };
+
+typedef struct _average
+{
+ t_sic x_sic;
+ int x_mode;
+ float (*x_sumfn)(t_float*, int, float);
+ int x_phase;
+ int x_npoints;
+ float x_result;
+ float x_accum;
+ t_clock *x_clock;
+} t_average;
+
+static t_class *average_class;
+
+static void average_tick(t_average *x)
+{
+ outlet_float(((t_object *)x)->ob_outlet, x->x_result);
+}
+
+static float average_bipolarsum(t_float *in, int nxfer, float accum)
+{
+ while (nxfer--)
+ accum += *in++;
+ return (accum);
+}
+
+static float average_absolutesum(t_float *in, int nxfer, float accum)
+{
+ while (nxfer--)
+ {
+ float f = *in++;
+ accum += (f >= 0 ? f : -f);
+ }
+ return (accum);
+}
+
+static float average_rmssum(t_float *in, int nxfer, float accum)
+{
+ while (nxfer--)
+ {
+ float f = *in++;
+ accum += f * f;
+ }
+ return (accum);
+}
+
+static void average_setmode(t_average *x, int mode)
+{
+ if (mode == AVERAGE_BIPOLAR)
+ x->x_sumfn = average_bipolarsum;
+ else if (mode == AVERAGE_ABSOLUTE)
+ x->x_sumfn = average_absolutesum;
+ else if (mode == AVERAGE_RMS)
+ x->x_sumfn = average_rmssum;
+ else
+ {
+ bug("average_setmode");
+ return;
+ }
+ x->x_mode = mode;
+ x->x_phase = x->x_npoints;
+ x->x_accum = 0;
+}
+
+static void average_float(t_average *x, t_float f)
+{
+ int i = (int)f; /* CHECKME noninteger */
+ if (i > 0) /* CHECKME */
+ {
+ x->x_npoints = i;
+ x->x_phase = x->x_npoints;
+ x->x_accum = 0;
+ }
+}
+
+static void average_bipolar(t_average *x)
+{
+ average_setmode(x, AVERAGE_BIPOLAR);
+}
+
+static void average_absolute(t_average *x)
+{
+ average_setmode(x, AVERAGE_ABSOLUTE);
+}
+
+static void average_rms(t_average *x)
+{
+ average_setmode(x, AVERAGE_RMS);
+}
+
+static t_int *average_perform(t_int *w)
+{
+ t_average *x = (t_average *)(w[1]);
+ int nblock = (int)(w[2]);
+ t_float *in = (t_float *)(w[3]);
+ float (*sumfn)(t_float*, int, float) = x->x_sumfn;
+ int phase = x->x_phase;
+ if (phase <= nblock)
+ {
+ float accum = (*sumfn)(in, phase, x->x_accum);
+ nblock -= phase;
+ if (x->x_mode == AVERAGE_RMS)
+ /* CHECKME scaling and FIXME */
+ x->x_result = sqrtf(accum / x->x_npoints);
+ else
+ x->x_result = accum / x->x_npoints;
+ clock_delay(x->x_clock, 0);
+ x->x_accum = 0;
+ if (nblock < x->x_npoints)
+ x->x_phase = x->x_npoints - nblock;
+ else
+ {
+ x->x_phase = x->x_npoints;
+ return (w + 4);
+ }
+ }
+ else x->x_phase -= nblock;
+ x->x_accum = (*sumfn)(in, nblock, x->x_accum);
+ return (w + 4);
+}
+
+static void average_dsp(t_average *x, t_signal **sp)
+{
+ dsp_add(average_perform, 3, x, sp[0]->s_n, sp[0]->s_vec);
+}
+
+static void average_free(t_average *x)
+{
+ if (x->x_clock) clock_free(x->x_clock);
+}
+
+static void *average_new(t_symbol *s, t_floatarg f)
+{
+ t_average *x = (t_average *)pd_new(average_class);
+ int i = (int)f; /* CHECKME noninteger */
+ int mode;
+ /* CHECKED it looks like memory is allocated for the entire window,
+ in tune with the refman's note about ``maximum averaging interval'' --
+ needed for dynamic control over window size, or what? LATER rethink */
+ x->x_npoints = (i > 0 ? /* CHECKME */
+ i : AVERAGE_DEFNPOINTS);
+ if (s == gensym("bipolar"))
+ mode = AVERAGE_BIPOLAR;
+ else if (s == gensym("absolute"))
+ mode = AVERAGE_ABSOLUTE;
+ else if (s == gensym("rms"))
+ mode = AVERAGE_RMS;
+ else
+ {
+ mode = AVERAGE_DEFMODE;
+ /* CHECKME a warning if (s && s != &s_) */
+ }
+ average_setmode(x, mode);
+ /* CHECKME if not x->x_phase = 0 */
+ outlet_new((t_object *)x, &s_float);
+ x->x_clock = clock_new(x, (t_method)average_tick);
+ return (x);
+}
+
+void average_tilde_setup(void)
+{
+ average_class = class_new(gensym("average~"),
+ (t_newmethod)average_new,
+ (t_method)average_free,
+ sizeof(t_average), 0,
+ A_DEFFLOAT, A_DEFSYM, 0);
+ sic_setup(average_class, average_dsp, average_float);
+ class_addmethod(average_class, (t_method)average_bipolar,
+ gensym("bipolar"), 0);
+ class_addmethod(average_class, (t_method)average_absolute,
+ gensym("absolute"), 0);
+ class_addmethod(average_class, (t_method)average_rms,
+ gensym("rms"), 0);
+}
diff --git a/cyclone/sickle/avg.c b/cyclone/sickle/avg.c
new file mode 100644
index 0000000..2ad214a
--- /dev/null
+++ b/cyclone/sickle/avg.c
@@ -0,0 +1,62 @@
+/* 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"
+
+typedef struct _avg
+{
+ t_sic x_sic;
+ float x_count;
+ float x_accum;
+} t_avg;
+
+static t_class *avg_class;
+
+static void avg_bang(t_avg *x)
+{
+ outlet_float(((t_object *)x)->ob_outlet,
+ (x->x_count ? x->x_accum / x->x_count : 0));
+ x->x_count = 0;
+ x->x_accum = 0;
+}
+
+static t_int *avg_perform(t_int *w)
+{
+ t_avg *x = (t_avg *)(w[1]);
+ int nblock = (int)(w[2]);
+ t_float *in = (t_float *)(w[3]);
+ float accum = 0;
+ x->x_count += nblock; /* LATER consider blockcount++ */
+ while (nblock--)
+ {
+ float f = *in++;
+ accum += (f >= 0 ? f : -f);
+ }
+ x->x_accum += accum;
+ return (w + 4);
+}
+
+static void avg_dsp(t_avg *x, t_signal **sp)
+{
+ dsp_add(avg_perform, 3, x, sp[0]->s_n, sp[0]->s_vec);
+}
+
+static void *avg_new(void)
+{
+ t_avg *x = (t_avg *)pd_new(avg_class);
+ outlet_new((t_object *)x, &s_float);
+ x->x_count = 0;
+ x->x_accum = 0;
+ return (x);
+}
+
+void avg_tilde_setup(void)
+{
+ avg_class = class_new(gensym("avg~"),
+ (t_newmethod)avg_new, 0,
+ sizeof(t_avg), 0, 0);
+ sic_setup(avg_class, avg_dsp, SIC_FLOATTOSIGNAL);
+ class_addbang(avg_class, avg_bang);
+}
diff --git a/cyclone/sickle/bitand.c b/cyclone/sickle/bitand.c
new file mode 100644
index 0000000..a7cfeb7
--- /dev/null
+++ b/cyclone/sickle/bitand.c
@@ -0,0 +1,144 @@
+/* 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. */
+
+/* FIXME find a way of setting a 32-bit mask in an argument */
+
+#include "m_pd.h"
+#include "unstable/forky.h"
+#include "sickle/sic.h"
+
+typedef struct _bitand
+{
+ t_sic x_sic;
+ t_glist *x_glist;
+ t_int x_mask; /* set by a 'bits' message or a creation argument */
+ int x_mode;
+ int x_convert1;
+} t_bitand;
+
+static t_class *bitand_class;
+
+static t_int *bitand_perform(t_int *w)
+{
+ t_bitand *x = (t_bitand *)(w[1]);
+ int nblock = (int)(w[2]);
+ t_float *in1 = (t_float *)(w[3]);
+ t_float *in2 = (t_float *)(w[4]);
+ t_float *out = (t_float *)(w[5]);
+ t_int mask = x->x_mask;
+ switch (x->x_mode)
+ {
+ /* LATER think about performance */
+ case 0:
+ /* CHECKED */
+ while (nblock--)
+ {
+ t_int i = ((*(t_int *)(t_float *)in1++) &
+ (*(t_int *)(t_float *)in2++));
+ *out++ = *(t_float *)&i;
+ }
+ break;
+ case 1:
+ /* CHECKED */
+ while (nblock--)
+ {
+ t_int i = (((t_int)*in1++) &
+ ((t_int)*in2++));
+ *out++ = (t_float)i;
+ }
+ break;
+ case 2:
+ /* CHECKED */
+ while (nblock--)
+ {
+ t_int i = (*(t_int *)(t_float *)in1++) & ((t_int)*in2++);
+ *out++ = *(t_float *)&i;
+ }
+ break;
+ case 3:
+ /* CHECKED */
+ while (nblock--)
+ {
+ t_int i = ((t_int)*in1++) & (*(t_int *)(t_float *)in2++);
+ *out++ = (t_float)i;
+ }
+ break;
+ }
+ return (w + 6);
+}
+
+static t_int *bitand_perform_noin2(t_int *w)
+{
+ t_bitand *x = (t_bitand *)(w[1]);
+ int nblock = (int)(w[2]);
+ t_float *in = (t_float *)(w[3]);
+ t_float *out = (t_float *)(w[4]);
+ t_int mask = x->x_mask;
+ /* LATER think about performance */
+ if (x->x_convert1) while (nblock--)
+ {
+ /* CHECKED */
+ t_int i = ((t_int)*in++) & mask;
+ *out++ = (t_float)i;
+ }
+ else while (nblock--)
+ {
+ /* CHECKED */
+ t_int i = (*(t_int *)(t_float *)in++) & mask;
+ *out++ = *(t_float *)&i;
+ }
+ return (w + 5);
+}
+
+static void bitand_dsp(t_bitand *x, t_signal **sp)
+{
+ if (forky_hasfeeders((t_object *)x, x->x_glist, 1, 0))
+ /* use the mask set by a second inlet's signal or float,
+ CHECKED (incompatible) second inlet's int is persistent */
+ dsp_add(bitand_perform, 5, x, sp[0]->s_n, sp[0]->s_vec,
+ sp[1]->s_vec, sp[2]->s_vec);
+ else /* use the mask set by a 'bits' message or a creation argument */
+ dsp_add(bitand_perform_noin2, 4, x, sp[0]->s_n, sp[0]->s_vec,
+ sp[1]->s_vec);
+}
+
+static void bitand_bits(t_bitand *x, t_symbol *s, int ac, t_atom *av)
+{
+ x->x_mask = forky_getbitmask(ac, av);
+}
+
+static void bitand_mode(t_bitand *x, t_floatarg f)
+{
+ int i = (int)f;
+ if (i < 0)
+ i = 0; /* CHECKED */
+ else if (i > 3)
+ i = 3; /* CHECKED */
+ x->x_mode = i;
+ x->x_convert1 = (x->x_mode == 1 || x->x_mode == 3);
+}
+
+static void *bitand_new(t_floatarg f1, t_floatarg f2)
+{
+ t_bitand *x = (t_bitand *)pd_new(bitand_class);
+ x->x_glist = canvas_getcurrent();
+ inlet_new((t_object *)x, (t_pd *)x, &s_signal, &s_signal);
+ outlet_new((t_object *)x, &s_signal);
+ x->x_mask = (t_int)f1; /* FIXME (how?) */
+ bitand_mode(x, f2);
+ return (x);
+}
+
+void bitand_tilde_setup(void)
+{
+ bitand_class = class_new(gensym("bitand~"),
+ (t_newmethod)bitand_new, 0,
+ sizeof(t_bitand), 0,
+ A_DEFFLOAT, A_DEFFLOAT, 0);
+ sic_setup(bitand_class, bitand_dsp, SIC_FLOATTOSIGNAL);
+ class_addmethod(bitand_class, (t_method)bitand_bits,
+ gensym("bits"), A_GIMME, 0);
+ class_addmethod(bitand_class, (t_method)bitand_mode,
+ gensym("mode"), A_FLOAT, 0);
+}
diff --git a/cyclone/sickle/bitnot.c b/cyclone/sickle/bitnot.c
new file mode 100644
index 0000000..c2929e8
--- /dev/null
+++ b/cyclone/sickle/bitnot.c
@@ -0,0 +1,66 @@
+/* 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"
+
+typedef struct _bitnot
+{
+ t_sic x_sic;
+ int x_convert1;
+} t_bitnot;
+
+static t_class *bitnot_class;
+
+static t_int *bitnot_perform(t_int *w)
+{
+ t_bitnot *x = (t_bitnot *)(w[1]);
+ int nblock = (int)(w[2]);
+ t_float *in = (t_float *)(w[3]);
+ t_float *out = (t_float *)(w[4]);
+ /* LATER think about performance */
+ if (x->x_convert1) while (nblock--)
+ {
+ /* CHECKME */
+ t_int i = ~((t_int)*in++);
+ *out++ = (t_float)i;
+ }
+ else while (nblock--)
+ {
+ /* CHECKME */
+ t_int i = ~(*(t_int *)(t_float *)in++);
+ *out++ = *(t_float *)&i;
+ }
+ return (w + 5);
+}
+
+static void bitnot_dsp(t_bitnot *x, t_signal **sp)
+{
+ dsp_add(bitnot_perform, 4, x, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec);
+}
+
+static void bitnot_mode(t_bitnot *x, t_floatarg f)
+{
+ int i = (int)f;
+ x->x_convert1 = (i > 0); /* CHECKME */
+}
+
+static void *bitnot_new(t_floatarg f)
+{
+ t_bitnot *x = (t_bitnot *)pd_new(bitnot_class);
+ outlet_new((t_object *)x, &s_signal);
+ bitnot_mode(x, f);
+ return (x);
+}
+
+void bitnot_tilde_setup(void)
+{
+ bitnot_class = class_new(gensym("bitnot~"),
+ (t_newmethod)bitnot_new, 0,
+ sizeof(t_bitnot), 0,
+ A_DEFFLOAT, 0);
+ sic_setup(bitnot_class, bitnot_dsp, SIC_FLOATTOSIGNAL);
+ class_addmethod(bitnot_class, (t_method)bitnot_mode,
+ gensym("mode"), A_FLOAT, 0);
+}
diff --git a/cyclone/sickle/bitor.c b/cyclone/sickle/bitor.c
new file mode 100644
index 0000000..e5c887b
--- /dev/null
+++ b/cyclone/sickle/bitor.c
@@ -0,0 +1,144 @@
+/* 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. */
+
+/* FIXME find a way of setting a 32-bit mask in an argument */
+
+#include "m_pd.h"
+#include "unstable/forky.h"
+#include "sickle/sic.h"
+
+typedef struct _bitor
+{
+ t_sic x_sic;
+ t_glist *x_glist;
+ t_int x_mask; /* set by a 'bits' message or a creation argument */
+ int x_mode;
+ int x_convert1;
+} t_bitor;
+
+static t_class *bitor_class;
+
+static t_int *bitor_perform(t_int *w)
+{
+ t_bitor *x = (t_bitor *)(w[1]);
+ int nblock = (int)(w[2]);
+ t_float *in1 = (t_float *)(w[3]);
+ t_float *in2 = (t_float *)(w[4]);
+ t_float *out = (t_float *)(w[5]);
+ t_int mask = x->x_mask;
+ switch (x->x_mode)
+ {
+ /* LATER think about performance */
+ case 0:
+ /* CHECKED */
+ while (nblock--)
+ {
+ t_int i = ((*(t_int *)(t_float *)in1++) |
+ (*(t_int *)(t_float *)in2++));
+ *out++ = *(t_float *)&i;
+ }
+ break;
+ case 1:
+ /* CHECKED */
+ while (nblock--)
+ {
+ t_int i = (((t_int)*in1++) |
+ ((t_int)*in2++));
+ *out++ = (t_float)i;
+ }
+ break;
+ case 2:
+ /* CHECKED */
+ while (nblock--)
+ {
+ t_int i = (*(t_int *)(t_float *)in1++) | ((t_int)*in2++);
+ *out++ = *(t_float *)&i;
+ }
+ break;
+ case 3:
+ /* CHECKED */
+ while (nblock--)
+ {
+ t_int i = ((t_int)*in1++) | (*(t_int *)(t_float *)in2++);
+ *out++ = (t_float)i;
+ }
+ break;
+ }
+ return (w + 6);
+}
+
+static t_int *bitor_perform_noin2(t_int *w)
+{
+ t_bitor *x = (t_bitor *)(w[1]);
+ int nblock = (int)(w[2]);
+ t_float *in = (t_float *)(w[3]);
+ t_float *out = (t_float *)(w[4]);
+ t_int mask = x->x_mask;
+ /* LATER think about performance */
+ if (x->x_convert1) while (nblock--)
+ {
+ /* CHECKED */
+ t_int i = ((t_int)*in++) | mask;
+ *out++ = (t_float)i;
+ }
+ else while (nblock--)
+ {
+ /* CHECKED */
+ t_int i = (*(t_int *)(t_float *)in++) | mask;
+ *out++ = *(t_float *)&i;
+ }
+ return (w + 5);
+}
+
+static void bitor_dsp(t_bitor *x, t_signal **sp)
+{
+ if (forky_hasfeeders((t_object *)x, x->x_glist, 1, 0))
+ /* use the mask set by a second inlet's signal or float,
+ CHECKED (incompatible) second inlet's int is persistent */
+ dsp_add(bitor_perform, 5, x, sp[0]->s_n, sp[0]->s_vec,
+ sp[1]->s_vec, sp[2]->s_vec);
+ else /* use the mask set by a 'bits' message or a creation argument */
+ dsp_add(bitor_perform_noin2, 4, x, sp[0]->s_n, sp[0]->s_vec,
+ sp[1]->s_vec);
+}
+
+static void bitor_bits(t_bitor *x, t_symbol *s, int ac, t_atom *av)
+{
+ x->x_mask = forky_getbitmask(ac, av);
+}
+
+static void bitor_mode(t_bitor *x, t_floatarg f)
+{
+ int i = (int)f;
+ if (i < 0)
+ i = 0; /* CHECKED */
+ else if (i > 3)
+ i = 3; /* CHECKED */
+ x->x_mode = i;
+ x->x_convert1 = (x->x_mode == 1 || x->x_mode == 3);
+}
+
+static void *bitor_new(t_floatarg f1, t_floatarg f2)
+{
+ t_bitor *x = (t_bitor *)pd_new(bitor_class);
+ x->x_glist = canvas_getcurrent();
+ inlet_new((t_object *)x, (t_pd *)x, &s_signal, &s_signal);
+ outlet_new((t_object *)x, &s_signal);
+ x->x_mask = (t_int)f1; /* FIXME (how?) */
+ bitor_mode(x, f2);
+ return (x);
+}
+
+void bitor_tilde_setup(void)
+{
+ bitor_class = class_new(gensym("bitor~"),
+ (t_newmethod)bitor_new, 0,
+ sizeof(t_bitor), 0,
+ A_DEFFLOAT, A_DEFFLOAT, 0);
+ sic_setup(bitor_class, bitor_dsp, SIC_FLOATTOSIGNAL);
+ class_addmethod(bitor_class, (t_method)bitor_bits,
+ gensym("bits"), A_GIMME, 0);
+ class_addmethod(bitor_class, (t_method)bitor_mode,
+ gensym("mode"), A_FLOAT, 0);
+}
diff --git a/cyclone/sickle/bitshift.c b/cyclone/sickle/bitshift.c
new file mode 100644
index 0000000..db30fcd
--- /dev/null
+++ b/cyclone/sickle/bitshift.c
@@ -0,0 +1,130 @@
+/* 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. */
+
+/* When bit-shifting 32-bit values, gcc (intel?) bashes the second operand
+ modulo 32. In msp x << 32 gives 0, x >> 32 gives a propagated sign bit
+ (as expected). Mimicking that is clumsy. LATER consider making the calcs
+ more generic (use long long values?) */
+
+#include "m_pd.h"
+#include "sickle/sic.h"
+
+//#define BITSHIFT_DEBUG
+
+typedef struct _bitshift
+{
+ t_sic x_sic;
+ int x_convert1;
+ int x_lshift;
+ int x_rshift;
+ int x_lover;
+} t_bitshift;
+
+static t_class *bitshift_class;
+
+static t_int *bitshift_perform(t_int *w)
+{
+ t_bitshift *x = (t_bitshift *)(w[1]);
+ int nblock = (int)(w[2]);
+ t_float *in = (t_float *)(w[3]);
+ t_float *out = (t_float *)(w[4]);
+ /* LATER think about performance */
+ if (x->x_lshift)
+ {
+ unsigned int shift = x->x_lshift;
+ if (x->x_convert1) while (nblock--)
+ {
+ /* CHECKED */
+ t_int i = ((t_int)*in++ << shift);
+ *out++ = (t_float)i;
+ }
+ else while (nblock--)
+ {
+ /* CHECKED */
+ t_int i = (*(t_int *)(t_float *)in++ << shift);
+ *out++ = *(t_float *)&i;
+ }
+ }
+ else if (x->x_rshift)
+ {
+ unsigned int shift = x->x_rshift;
+ if (x->x_convert1) while (nblock--)
+ {
+ /* CHECKME */
+ t_int i = ((t_int)*in++ >> shift);
+ *out++ = (t_float)i;
+ }
+ else while (nblock--)
+ {
+ /* CHECKME */
+ t_int i = (*(t_int *)(t_float *)in++ >> shift);
+ *out++ = *(t_float *)&i;
+ }
+ }
+ else if (x->x_lover)
+ while (nblock--) *out++ = 0; /* CHECKED both modes */
+ else
+ while (nblock--) *out++ = *in++; /* CHECKED both modes */
+ return (w + 5);
+}
+
+static void bitshift_dsp(t_bitshift *x, t_signal **sp)
+{
+ dsp_add(bitshift_perform, 4, x, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec);
+}
+
+static void bitshift_mode(t_bitshift *x, t_floatarg f)
+{
+ int i = (int)f;
+ x->x_convert1 = (i > 0); /* CHECKED */
+}
+
+static void bitshift_shift(t_bitshift *x, t_floatarg f)
+{
+ int i = (int)f;
+ int nbits = sizeof(t_int) * 8;
+ x->x_lshift = x->x_rshift = 0;
+ x->x_lover = 0;
+ if (i > 0)
+ {
+#ifdef BITSHIFT_DEBUG
+ post("%.8x << %d == %.8x, %.8x << %d == %.8x",
+ 1, i, 1 << i, -1, i, -1 << i);
+#endif
+ if (i < nbits)
+ x->x_lshift = i;
+ else
+ x->x_lover = 1;
+ }
+ else if (i < 0)
+ {
+#ifdef BITSHIFT_DEBUG
+ post("%.8x >> %d == %.8x, %.8x >> %d == %.8x",
+ 0x7fffffff, -i, 0x7fffffff >> -i, -1, -i, -1 >> -i);
+#endif
+ x->x_rshift = (i <= -nbits ? nbits - 1 : -i);
+ }
+}
+
+static void *bitshift_new(t_floatarg f1, t_floatarg f2)
+{
+ t_bitshift *x = (t_bitshift *)pd_new(bitshift_class);
+ outlet_new((t_object *)x, &s_signal);
+ bitshift_shift(x, f1);
+ bitshift_mode(x, f2);
+ return (x);
+}
+
+void bitshift_tilde_setup(void)
+{
+ bitshift_class = class_new(gensym("bitshift~"),
+ (t_newmethod)bitshift_new, 0,
+ sizeof(t_bitshift), 0,
+ A_DEFFLOAT, A_DEFFLOAT, 0);
+ sic_setup(bitshift_class, bitshift_dsp, SIC_FLOATTOSIGNAL);
+ class_addmethod(bitshift_class, (t_method)bitshift_mode,
+ gensym("mode"), A_FLOAT, 0);
+ class_addmethod(bitshift_class, (t_method)bitshift_shift,
+ gensym("shift"), A_FLOAT, 0);
+}
diff --git a/cyclone/sickle/bitxor.c b/cyclone/sickle/bitxor.c
new file mode 100644
index 0000000..ce54843
--- /dev/null
+++ b/cyclone/sickle/bitxor.c
@@ -0,0 +1,144 @@
+/* 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. */
+
+/* FIXME find a way of setting a 32-bit mask in an argument */
+
+#include "m_pd.h"
+#include "unstable/forky.h"
+#include "sickle/sic.h"
+
+typedef struct _bitxor
+{
+ t_sic x_sic;
+ t_glist *x_glist;
+ t_int x_mask; /* set by a 'bits' message or a creation argument */
+ int x_mode;
+ int x_convert1;
+} t_bitxor;
+
+static t_class *bitxor_class;
+
+static t_int *bitxor_perform(t_int *w)
+{
+ t_bitxor *x = (t_bitxor *)(w[1]);
+ int nblock = (int)(w[2]);
+ t_float *in1 = (t_float *)(w[3]);
+ t_float *in2 = (t_float *)(w[4]);
+ t_float *out = (t_float *)(w[5]);
+ t_int mask = x->x_mask;
+ switch (x->x_mode)
+ {
+ /* LATER think about performance */
+ case 0:
+ /* CHECKED */
+ while (nblock--)
+ {
+ t_int i = ((*(t_int *)(t_float *)in1++) ^
+ (*(t_int *)(t_float *)in2++));
+ *out++ = *(t_float *)&i;
+ }
+ break;
+ case 1:
+ /* CHECKED */
+ while (nblock--)
+ {
+ t_int i = (((t_int)*in1++) ^
+ ((t_int)*in2++));
+ *out++ = (t_float)i;
+ }
+ break;
+ case 2:
+ /* CHECKED */
+ while (nblock--)
+ {
+ t_int i = (*(t_int *)(t_float *)in1++) ^ ((t_int)*in2++);
+ *out++ = *(t_float *)&i;
+ }
+ break;
+ case 3:
+ /* CHECKED */
+ while (nblock--)
+ {
+ t_int i = ((t_int)*in1++) ^ (*(t_int *)(t_float *)in2++);
+ *out++ = (t_float)i;
+ }
+ break;
+ }
+ return (w + 6);
+}
+
+static t_int *bitxor_perform_noin2(t_int *w)
+{
+ t_bitxor *x = (t_bitxor *)(w[1]);
+ int nblock = (int)(w[2]);
+ t_float *in = (t_float *)(w[3]);
+ t_float *out = (t_float *)(w[4]);
+ t_int mask = x->x_mask;
+ /* LATER think about performance */
+ if (x->x_convert1) while (nblock--)
+ {
+ /* CHECKED */
+ t_int i = ((t_int)*in++) ^ mask;
+ *out++ = (t_float)i;
+ }
+ else while (nblock--)
+ {
+ /* CHECKED */
+ t_int i = (*(t_int *)(t_float *)in++) ^ mask;
+ *out++ = *(t_float *)&i;
+ }
+ return (w + 5);
+}
+
+static void bitxor_dsp(t_bitxor *x, t_signal **sp)
+{
+ if (forky_hasfeeders((t_object *)x, x->x_glist, 1, 0))
+ /* use the mask set by a second inlet's signal or float,
+ CHECKED (incompatible) second inlet's int is persistent */
+ dsp_add(bitxor_perform, 5, x, sp[0]->s_n, sp[0]->s_vec,
+ sp[1]->s_vec, sp[2]->s_vec);
+ else /* use the mask set by a 'bits' message or a creation argument */
+ dsp_add(bitxor_perform_noin2, 4, x, sp[0]->s_n, sp[0]->s_vec,
+ sp[1]->s_vec);
+}
+
+static void bitxor_bits(t_bitxor *x, t_symbol *s, int ac, t_atom *av)
+{
+ x->x_mask = forky_getbitmask(ac, av);
+}
+
+static void bitxor_mode(t_bitxor *x, t_floatarg f)
+{
+ int i = (int)f;
+ if (i < 0)
+ i = 0; /* CHECKED */
+ else if (i > 3)
+ i = 3; /* CHECKED */
+ x->x_mode = i;
+ x->x_convert1 = (x->x_mode == 1 || x->x_mode == 3);
+}
+
+static void *bitxor_new(t_floatarg f1, t_floatarg f2)
+{
+ t_bitxor *x = (t_bitxor *)pd_new(bitxor_class);
+ x->x_glist = canvas_getcurrent();
+ inlet_new((t_object *)x, (t_pd *)x, &s_signal, &s_signal);
+ outlet_new((t_object *)x, &s_signal);
+ x->x_mask = (t_int)f1; /* FIXME (how?) */
+ bitxor_mode(x, f2);
+ return (x);
+}
+
+void bitxor_tilde_setup(void)
+{
+ bitxor_class = class_new(gensym("bitxor~"),
+ (t_newmethod)bitxor_new, 0,
+ sizeof(t_bitxor), 0,
+ A_DEFFLOAT, A_DEFFLOAT, 0);
+ sic_setup(bitxor_class, bitxor_dsp, SIC_FLOATTOSIGNAL);
+ class_addmethod(bitxor_class, (t_method)bitxor_bits,
+ gensym("bits"), A_GIMME, 0);
+ class_addmethod(bitxor_class, (t_method)bitxor_mode,
+ gensym("mode"), A_FLOAT, 0);
+}
diff --git a/cyclone/sickle/capture.c b/cyclone/sickle/capture.c
new file mode 100644
index 0000000..089c21e
--- /dev/null
+++ b/cyclone/sickle/capture.c
@@ -0,0 +1,408 @@
+/* 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. */
+
+/* CHECKME list of indices */
+
+#include <stdio.h>
+#include "m_pd.h"
+#include "g_canvas.h"
+#include "common/loud.h"
+#include "hammer/file.h"
+#include "sickle/sic.h"
+
+#define CAPTURE_DEFSIZE 4096
+#define CAPTURE_DEFPRECISION 4
+#define CAPTURE_MAXPRECISION 99 /* format array protection */
+#define CAPTURE_MAXINDICES 4096 /* FIXME */
+
+typedef struct _capture
+{
+ t_sic x_sic;
+ t_glist *x_glist;
+ char x_mode; /* 'f' for first or 0 for last */
+ int x_precision;
+ char x_format[8];
+ char *x_indices;
+ int x_szindices; /* size of x_indices array */
+ int x_nindices; /* number of reported indices */
+ int x_nblock;
+ float *x_buffer;
+ int x_bufsize;
+ int x_count;
+ int x_head;
+ t_hammerfile *x_filehandle;
+} t_capture;
+
+static t_class *capture_class;
+
+static void capture_clear(t_capture *x)
+{
+ x->x_count = 0;
+ x->x_head = 0;
+}
+
+static int capture_formatfloat(t_capture *x, float f, char *buf, int col,
+ int maxcol)
+{
+ char *bp = buf;
+ int cnt = 0;
+ if (col > 0)
+ *bp++ = ' ', cnt++;
+ if (x->x_precision)
+ cnt += sprintf(bp, x->x_format, f);
+ else
+ cnt += sprintf(bp, "%d", (int)f);
+ if (col + cnt > maxcol)
+ buf[0] = '\n', col = cnt;
+ else
+ col += cnt;
+ return (col);
+}
+
+static int capture_writefloat(t_capture *x, float f, char *buf, int col,
+ FILE *fp)
+{
+ /* CHECKME linebreaks */
+ col = capture_formatfloat(x, f, buf, col, 80);
+ return (fputs(buf, fp) < 0 ? -1 : col);
+}
+
+static void capture_dowrite(t_capture *x, t_symbol *fn)
+{
+ FILE *fp = 0;
+ int count = x->x_count;
+ char buf[MAXPDSTRING];
+ canvas_makefilename(glist_getcanvas(x->x_glist),
+ fn->s_name, buf, MAXPDSTRING);
+ if (fp = fopen(buf, "w")) /* LATER ask if overwriting, CHECKME */
+ {
+ int col = 0;
+ if (x->x_mode == 'f' || count < x->x_bufsize)
+ {
+ float *bp = x->x_buffer;
+ while (count--)
+ if ((col = capture_writefloat(x, *bp++, buf, col, fp)) < 0)
+ goto fail;
+ }
+ else
+ {
+ float *bp = x->x_buffer + x->x_head;
+ count = x->x_bufsize - x->x_head;
+ while (count--)
+ if ((col = capture_writefloat(x, *bp++, buf, col, fp)) < 0)
+ goto fail;
+ bp = x->x_buffer;
+ count = x->x_head;
+ while (count--)
+ if ((col = capture_writefloat(x, *bp++, buf, col, fp)) < 0)
+ goto fail;
+ }
+ if (col) fputc('\n', fp);
+ fclose(fp);
+ return;
+ }
+fail:
+ if (fp) fclose(fp);
+ loud_syserror((t_pd *)x, 0);
+}
+
+static void capture_writehook(t_pd *z, t_symbol *fn, int ac, t_atom *av)
+{
+ capture_dowrite((t_capture *)z, fn);
+}
+
+static void capture_write(t_capture *x, t_symbol *s)
+{
+ if (s && s != &s_)
+ capture_dowrite(x, s);
+ else
+ hammerpanel_save(x->x_filehandle, 0, 0);
+}
+
+static int capture_appendfloat(t_capture *x, float f, char *buf,
+ int col, int linebreak)
+{
+ /* CHECKME 80 columns */
+ col = capture_formatfloat(x, f, buf, col, 80);
+ hammereditor_append(x->x_filehandle, buf);
+ if (linebreak)
+ {
+ if (col)
+ {
+ hammereditor_append(x->x_filehandle, "\n\n");
+ col = 0;
+ }
+ else hammereditor_append(x->x_filehandle, "\n");
+ }
+ return (col);
+}
+
+/* CHECKED blank line between blocks */
+static void capture_open(t_capture *x)
+{
+ int count = x->x_count;
+ char buf[MAXPDSTRING];
+ int nindices = (x->x_nindices > 0 ? x->x_nindices : x->x_nblock);
+ hammereditor_open(x->x_filehandle, "Signal Capture"); /* CHECKED */
+ if (x->x_mode == 'f' || count < x->x_bufsize)
+ {
+ float *bp = x->x_buffer;
+ int col = 0, i;
+ for (i = 1; i <= count; i++)
+ col = capture_appendfloat(x, *bp++, buf, col,
+ ((i % nindices) == 0));
+ }
+ else
+ {
+ float *bp = x->x_buffer + x->x_head;
+ int col = 0, i = x->x_bufsize;
+ count = x->x_bufsize - x->x_head;
+ while (count--)
+ col = capture_appendfloat(x, *bp++, buf, col,
+ ((--i % nindices) == 0));
+ bp = x->x_buffer;
+ count = x->x_head;
+ while (count--)
+ col = capture_appendfloat(x, *bp++, buf, col,
+ ((count % nindices) == 0));
+ }
+}
+
+static void capture_wclose(t_capture *x)
+{
+ hammereditor_close(x->x_filehandle, 0);
+}
+
+static void capture_click(t_capture *x, t_floatarg xpos, t_floatarg ypos,
+ t_floatarg shift, t_floatarg ctrl, t_floatarg alt)
+{
+ capture_open(x);
+}
+
+static t_int *capture_perform_first(t_int *w)
+{
+ t_capture *x = (t_capture *)(w[1]);
+ int count = x->x_count;
+ int bufsize = x->x_bufsize;
+ if (count < bufsize)
+ {
+ t_float *in = (t_float *)(w[2]);
+ int nblock = (int)(w[3]);
+ float *bp = x->x_buffer + count;
+ char *ndxp = x->x_indices;
+ if (nblock > x->x_szindices)
+ nblock = x->x_szindices;
+ while (nblock--)
+ {
+ if (*ndxp++)
+ {
+ *bp++ = *in++;
+ if (++count == bufsize)
+ break;
+ }
+ else in++;
+ }
+ x->x_count = count;
+ }
+ return (w + 4);
+}
+
+static t_int *capture_perform_allfirst(t_int *w)
+{
+ t_capture *x = (t_capture *)(w[1]);
+ int count = x->x_count;
+ int bufsize = x->x_bufsize;
+ if (count < bufsize)
+ {
+ t_float *in = (t_float *)(w[2]);
+ int nblock = (int)(w[3]);
+ float *bp = x->x_buffer + count;
+ while (nblock--)
+ {
+ *bp++ = *in++;
+ if (++count == bufsize)
+ break;
+ }
+ x->x_count = count;
+ }
+ return (w + 4);
+}
+
+static t_int *capture_perform_last(t_int *w)
+{
+ t_capture *x = (t_capture *)(w[1]);
+ t_float *in = (t_float *)(w[2]);
+ int nblock = (int)(w[3]);
+ float *buffer = x->x_buffer;
+ int bufsize = x->x_bufsize;
+ int count = x->x_count;
+ int head = x->x_head;
+ char *ndxp = x->x_indices;
+ if (nblock > x->x_szindices)
+ nblock = x->x_szindices;
+ while (nblock--)
+ {
+ if (*ndxp++)
+ {
+ buffer[head++] = *in++;
+ if (head >= bufsize)
+ head = 0;
+ if (count < bufsize)
+ count++;
+ }
+ else in++;
+ }
+ x->x_count = count;
+ x->x_head = head;
+ return (w + 4);
+}
+
+static t_int *capture_perform_alllast(t_int *w)
+{
+ t_capture *x = (t_capture *)(w[1]);
+ t_float *in = (t_float *)(w[2]);
+ int nblock = (int)(w[3]);
+ float *buffer = x->x_buffer;
+ int bufsize = x->x_bufsize;
+ int count = x->x_count;
+ int head = x->x_head;
+ while (nblock--)
+ {
+ buffer[head++] = *in++;
+ if (head >= bufsize)
+ head = 0;
+ if (count < bufsize)
+ count++;
+ }
+ x->x_count = count;
+ x->x_head = head;
+ return (w + 4);
+}
+
+static void capture_dsp(t_capture *x, t_signal **sp)
+{
+ x->x_nblock = sp[0]->s_n;
+ if (x->x_indices)
+ dsp_add((x->x_mode == 'f' ?
+ capture_perform_first : capture_perform_last),
+ 3, x, sp[0]->s_vec, sp[0]->s_n);
+ else
+ dsp_add((x->x_mode == 'f' ?
+ capture_perform_allfirst : capture_perform_alllast),
+ 3, x, sp[0]->s_vec, sp[0]->s_n);
+}
+
+static void capture_free(t_capture *x)
+{
+ hammerfile_free(x->x_filehandle);
+ if (x->x_indices)
+ freebytes(x->x_indices, x->x_szindices * sizeof(*x->x_indices));
+ if (x->x_buffer)
+ freebytes(x->x_buffer, x->x_bufsize * sizeof(*x->x_buffer));
+}
+
+static void *capture_new(t_symbol *s, int ac, t_atom *av)
+{
+ t_capture *x = 0;
+ char mode = 0;
+ int precision = -1;
+ float *buffer;
+ int bufsize = 0;
+ char *indices = 0;
+ int szindices = 0, nindices = -1;
+ if (ac && av->a_type == A_SYMBOL)
+ {
+ t_symbol *s = av->a_w.w_symbol;
+ if (s && *s->s_name == 'f') /* CHECKME */
+ mode = 'f';
+ ac--; av++;
+ }
+ if (ac && av->a_type == A_FLOAT)
+ {
+ bufsize = (int)av->a_w.w_float; /* CHECKME */
+ ac--; av++;
+ if (ac && av->a_type == A_FLOAT)
+ {
+ int i;
+ t_atom *ap;
+ precision = (int)av->a_w.w_float; /* CHECKME */
+ ac--; av++;
+ for (i = 0, ap = av; i < ac; i++, ap++)
+ {
+ if (ap->a_type == A_FLOAT)
+ {
+ int ndx = (int)ap->a_w.w_float;
+ /* CHECKME noninteger, negative */
+ ndx++;
+ if (ndx >= CAPTURE_MAXINDICES)
+ {
+ /* CHECKME complaint */
+ szindices = CAPTURE_MAXINDICES;
+ break;
+ }
+ else if (ndx > szindices)
+ szindices = ndx;
+ }
+ else break; /* CHECKME */
+ }
+ if (szindices && (indices = getbytes(szindices * sizeof(*indices))))
+ {
+ nindices = 0;
+ while (i--)
+ {
+ int ndx = (int)av++->a_w.w_float;
+ /* CHECKME noninteger */
+ if (ndx >= 0 && ndx < szindices)
+ indices[ndx] = 1, nindices++;
+ }
+ }
+ }
+ }
+ if (bufsize <= 0) /* CHECKME */
+ bufsize = CAPTURE_DEFSIZE;
+ if (buffer = getbytes(bufsize * sizeof(*buffer)))
+ {
+ x = (t_capture *)pd_new(capture_class);
+ x->x_glist = canvas_getcurrent();
+ x->x_mode = mode;
+ if (precision < 0) /* CHECKME */
+ precision = CAPTURE_DEFPRECISION;
+ else if (precision > CAPTURE_MAXPRECISION) /* CHECKME */
+ precision = CAPTURE_MAXPRECISION;
+ if (x->x_precision = precision)
+ sprintf(x->x_format, "%%.%dg", precision);
+ x->x_indices = indices;
+ x->x_szindices = szindices;
+ x->x_nindices = nindices;
+ x->x_nblock = 64; /* redundant */
+ x->x_buffer = buffer;
+ x->x_bufsize = bufsize;
+ x->x_filehandle = hammerfile_new((t_pd *)x, 0, 0, capture_writehook, 0);
+ capture_clear(x);
+ }
+ else if (indices)
+ freebytes(indices, szindices * sizeof(*indices));
+ return (x);
+}
+
+void capture_tilde_setup(void)
+{
+ capture_class = class_new(gensym("capture~"),
+ (t_newmethod)capture_new,
+ (t_method)capture_free,
+ sizeof(t_capture), 0, A_GIMME, 0);
+ sic_setup(capture_class, capture_dsp, SIC_FLOATTOSIGNAL);
+ class_addmethod(capture_class, (t_method)capture_clear,
+ gensym("clear"), 0);
+ class_addmethod(capture_class, (t_method)capture_write,
+ gensym("write"), A_DEFSYM, 0);
+ class_addmethod(capture_class, (t_method)capture_open,
+ gensym("open"), 0);
+ class_addmethod(capture_class, (t_method)capture_wclose,
+ gensym("wclose"), 0);
+ class_addmethod(capture_class, (t_method)capture_click,
+ gensym("click"),
+ A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0);
+ hammerfile_setup(capture_class, 0);
+}
diff --git a/cyclone/sickle/cartopol.c b/cyclone/sickle/cartopol.c
new file mode 100644
index 0000000..4c25797
--- /dev/null
+++ b/cyclone/sickle/cartopol.c
@@ -0,0 +1,79 @@
+/* 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 <math.h>
+#include "m_pd.h"
+#include "unstable/fragile.h"
+#include "sickle/sic.h"
+
+#if defined(NT) || defined(MACOSX)
+/* cf pd/src/x_arithmetic.c */
+#define atan2f atan2
+#define hypotf hypot
+#endif
+
+typedef struct _cartopol
+{
+ t_sic x_sic;
+ t_outlet *x_out2;
+} t_cartopol;
+
+static t_class *cartopol_class;
+
+static t_int *cartopol_perform(t_int *w)
+{
+ int nblock = (int)(w[1]);
+ t_float *in1 = (t_float *)(w[2]);
+ t_float *in2 = (t_float *)(w[3]);
+ t_float *out1 = (t_float *)(w[4]);
+ t_float *out2 = (t_float *)(w[5]);
+ while (nblock--)
+ {
+ float rl = *in1++, im = -*in2++; /* CHECKED */
+ *out1++ = hypotf(rl, im);
+ *out2++ = atan2f(im, rl);
+ }
+ return (w + 6);
+}
+
+static t_int *cartopol_perform_nophase(t_int *w)
+{
+ int nblock = (int)(w[1]);
+ t_float *in1 = (t_float *)(w[2]);
+ t_float *in2 = (t_float *)(w[3]);
+ t_float *out1 = (t_float *)(w[4]);
+ while (nblock--)
+ {
+ float rl = *in1++, im = -*in2++; /* CHECKED */
+ *out1++ = hypotf(rl, im);
+ }
+ return (w + 5);
+}
+
+static void cartopol_dsp(t_cartopol *x, t_signal **sp)
+{
+ if (fragile_outlet_connections(x->x_out2))
+ dsp_add(cartopol_perform, 5, sp[0]->s_n, sp[0]->s_vec,
+ sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec);
+ else
+ dsp_add(cartopol_perform_nophase, 4, sp[0]->s_n, sp[0]->s_vec,
+ sp[1]->s_vec, sp[2]->s_vec);
+}
+
+static void *cartopol_new(void)
+{
+ t_cartopol *x = (t_cartopol *)pd_new(cartopol_class);
+ inlet_new((t_object *)x, (t_pd *)x, &s_signal, &s_signal);
+ outlet_new((t_object *)x, &s_signal);
+ x->x_out2 = outlet_new((t_object *)x, &s_signal);
+ return (x);
+}
+
+void cartopol_tilde_setup(void)
+{
+ cartopol_class = class_new(gensym("cartopol~"),
+ (t_newmethod)cartopol_new, 0,
+ sizeof(t_cartopol), 0, 0);
+ sic_setup(cartopol_class, cartopol_dsp, SIC_FLOATTOSIGNAL);
+}
diff --git a/cyclone/sickle/change.c b/cyclone/sickle/change.c
new file mode 100644
index 0000000..fffc43a
--- /dev/null
+++ b/cyclone/sickle/change.c
@@ -0,0 +1,52 @@
+/* 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"
+
+typedef struct _change
+{
+ t_sic x_sic;
+ t_float x_last;
+} t_change;
+
+static t_class *change_class;
+
+static t_int *change_perform(t_int *w)
+{
+ t_change *x = (t_change *)(w[1]);
+ int nblock = (int)(w[2]);
+ t_float *in = (t_float *)(w[3]);
+ t_float *out = (t_float *)(w[4]);
+ t_float last = x->x_last;
+ while (nblock--)
+ {
+ t_float f = *in++;
+ *out++ = (f > last ? 1. : (f < last ? -1. : 0.));
+ last = f;
+ }
+ x->x_last = last;
+ return (w + 5);
+}
+
+static void change_dsp(t_change *x, t_signal **sp)
+{
+ dsp_add(change_perform, 4, x, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec);
+}
+
+static void *change_new(void)
+{
+ t_change *x = (t_change *)pd_new(change_class);
+ outlet_new((t_object *)x, &s_signal);
+ x->x_last = 0; /* CHECKME startup conditions */
+ return (x);
+}
+
+void change_tilde_setup(void)
+{
+ change_class = class_new(gensym("change~"),
+ (t_newmethod)change_new, 0,
+ sizeof(t_change), 0, 0);
+ sic_setup(change_class, change_dsp, SIC_FLOATTOSIGNAL);
+}
diff --git a/cyclone/sickle/click.c b/cyclone/sickle/click.c
new file mode 100644
index 0000000..5734cfd
--- /dev/null
+++ b/cyclone/sickle/click.c
@@ -0,0 +1,119 @@
+/* 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 "common/grow.h"
+#include "sickle/sic.h"
+
+#define CLICK_INISIZE 16 /* LATER rethink */
+
+typedef struct _click
+{
+ t_sic x_sic;
+ int x_nsamples; /* as used */
+ int x_bufsize; /* as allocated */
+ t_float *x_buffer;
+ t_float x_bufini[CLICK_INISIZE];
+ int x_nleft;
+ t_float *x_head;
+} t_click;
+
+static t_class *click_class;
+
+static void click_bang(t_click *x)
+{
+ x->x_nleft = x->x_nsamples;
+ x->x_head = x->x_buffer;
+}
+
+static void click_set(t_click *x, t_symbol *s, int ac, t_atom *av)
+{
+ int i, nsamples = 0;
+ t_atom *ap;
+ t_float *bp;
+ for (i = 0, ap = av; i < ac; i++, ap++)
+ {
+ if (ap->a_type == A_FLOAT) nsamples++;
+ /* CHECKED no restrictions (refman's error about 0.0-1.0 range)
+ CHECKED nonnumeric atoms silently ignored */
+ }
+ if (nsamples > x->x_bufsize)
+ x->x_buffer = grow_nodata(&nsamples, &x->x_bufsize, x->x_buffer,
+ CLICK_INISIZE, x->x_bufini,
+ sizeof(*x->x_buffer));
+ if (nsamples)
+ {
+ x->x_nsamples = nsamples;
+ bp = x->x_buffer;
+ while (nsamples--) *bp++ = av++->a_w.w_float;
+ }
+ else x->x_nsamples = 0; /* CHECKED, need to 'set 1' explicitly */
+ x->x_nleft = 0;
+ x->x_head = x->x_buffer;
+}
+
+static t_int *click_perform(t_int *w)
+{
+ t_click *x = (t_click *)(w[1]);
+ int nblock = (int)(w[2]);
+ t_float *out = (t_float *)(w[3]);
+ if (x->x_nleft)
+ {
+ int nleft = x->x_nleft;
+ t_float *head = x->x_head;
+ if (nleft >= nblock)
+ {
+ x->x_nleft -= nblock;
+ while (nblock--) *out++ = *head++;
+ x->x_head = head;
+ }
+ else
+ {
+ nblock -= nleft;
+ while (nleft--) *out++ = *head++;
+ while (nblock--) *out++ = 0.;
+ x->x_nleft = 0;
+ x->x_head = x->x_buffer;
+ }
+ }
+ else while (nblock--) *out++ = 0.;
+ return (w + 4);
+}
+
+static void click_dsp(t_click *x, t_signal **sp)
+{
+ dsp_add(click_perform, 3, x, sp[0]->s_n, sp[0]->s_vec);
+}
+
+static void click_free(t_click *x)
+{
+ if (x->x_buffer != x->x_bufini)
+ freebytes(x->x_buffer, x->x_bufsize * sizeof(*x->x_buffer));
+}
+
+static void *click_new(t_symbol *s, int ac, t_atom *av)
+{
+ t_click *x = (t_click *)pd_new(click_class);
+ x->x_nsamples = 1; /* CHECKED */
+ x->x_bufsize = CLICK_INISIZE;
+ x->x_buffer = x->x_bufini;
+ x->x_buffer[0] = 1.; /* CHECKED */
+ x->x_nleft = 0;
+ x->x_head = x->x_buffer;
+ outlet_new((t_object *)x, &s_signal);
+ if (ac) click_set(x, 0, ac, av);
+ return (x);
+}
+
+void click_tilde_setup(void)
+{
+ click_class = class_new(gensym("click~"),
+ (t_newmethod)click_new,
+ (t_method)click_free,
+ sizeof(t_click), 0, A_GIMME, 0);
+ sic_setup(click_class, click_dsp, SIC_NOMAINSIGNALIN);
+ class_addbang(click_class, click_bang);
+ class_addmethod(click_class, (t_method)click_set,
+ gensym("set"), A_GIMME, 0);
+}
diff --git a/cyclone/sickle/comb.c b/cyclone/sickle/comb.c
new file mode 100644
index 0000000..8d4c8b3
--- /dev/null
+++ b/cyclone/sickle/comb.c
@@ -0,0 +1,162 @@
+/* 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 <string.h>
+#include "m_pd.h"
+#include "sickle/sic.h"
+
+typedef struct _comb
+{
+ t_sic x_sic;
+ float x_sr;
+ float x_ksr;
+ t_float *x_buf;
+ int x_bufsize; /* as allocated */
+ int x_maxsize; /* as used */
+ float x_maxdelay; /* same in ms */
+ int x_phase; /* writing head */
+} t_comb;
+
+static t_class *comb_class;
+
+/* maximum delay defaults to 50 ms (cycling has 10 ms here) */
+#define COMB_DEFMAXDELAY 50.0
+
+/* LATER choose the best way. From msp help patch:
+ no clipping is done on a, b, or c coefficient input */
+#define COMB_MAXFEEDBACK 0.999
+
+static void comb_clear(t_comb *x)
+{
+ memset(x->x_buf, 0, x->x_maxsize * sizeof(*x->x_buf));
+ x->x_phase = 0;
+}
+
+static void comb_resize(t_comb *x, int newsize)
+{
+ if (newsize > 0 && newsize != x->x_maxsize)
+ {
+ if (newsize > x->x_bufsize)
+ {
+ x->x_buf = resizebytes(x->x_buf,
+ x->x_bufsize * sizeof(*x->x_buf),
+ newsize * sizeof(*x->x_buf));
+ /* LATER test for failure */
+ x->x_bufsize = newsize;
+ }
+ x->x_maxsize = newsize;
+ }
+ comb_clear(x);
+}
+
+static t_int *comb_perform(t_int *w)
+{
+ t_comb *x = (t_comb *)(w[1]);
+ int nblock = (int)(w[2]);
+ t_float *xin = (t_float *)(w[3]);
+ t_float *din = (t_float *)(w[4]);
+ t_float *ain = (t_float *)(w[5]);
+ t_float *bin = (t_float *)(w[6]);
+ t_float *cin = (t_float *)(w[7]);
+ t_float *out = (t_float *)(w[8]);
+ t_float *buf = x->x_buf;
+ int maxsize = x->x_maxsize;
+ int guardpoint = maxsize - 1;
+ float ksr = x->x_ksr;
+ int wph = x->x_phase;
+ while (nblock--)
+ { /* TDFII scheme is used. Do not forget, that any signal value
+ read after writing to out has to be saved beforehand. */
+ float xn = *xin++;
+ float delsize = ksr * *din++;
+ float bgain = *bin++;
+ float cgain = *cin++;
+ float yn = *ain++ * xn;
+ float rph; /* reading head */
+ if (cgain < -COMB_MAXFEEDBACK) cgain = -COMB_MAXFEEDBACK;
+ else if (cgain > COMB_MAXFEEDBACK) cgain = COMB_MAXFEEDBACK;
+ if (delsize > 1.0)
+ {
+ int ndx;
+ float val;
+ rph = wph - (delsize > guardpoint ? guardpoint : delsize);
+ if (rph < 0) rph += guardpoint;
+ ndx = (int)rph;
+ val = buf[ndx];
+ /* ``a cheezy linear interpolation'' ala msp,
+ (vd~ uses 4-point interpolation...) */
+ yn += val + (buf[ndx+1] - val) * (rph - ndx);
+ }
+ *out++ = yn;
+ if (wph == guardpoint)
+ {
+ buf[wph] = *buf = bgain * xn + cgain * yn;
+ wph = 1;
+ }
+ else buf[wph++] = bgain * xn + cgain * yn;
+ }
+ x->x_phase = wph;
+ return (w + 9);
+}
+
+static void comb_dsp(t_comb *x, t_signal **sp)
+{
+ float sr = sp[0]->s_sr;
+ if (sr != x->x_sr)
+ {
+ x->x_sr = sr;
+ x->x_ksr = sr * 0.001;
+ comb_resize(x, x->x_ksr * x->x_maxdelay);
+ }
+ else comb_clear(x);
+ dsp_add(comb_perform, 8, x, sp[0]->s_n,
+ sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec,
+ sp[3]->s_vec, sp[4]->s_vec, sp[5]->s_vec);
+}
+
+static void *comb_new(t_floatarg f1, t_floatarg f2,
+ t_floatarg f3, t_floatarg f4, t_floatarg f5)
+{
+ t_comb *x;
+ float maxdelay = (f1 > 0 ? f1 : COMB_DEFMAXDELAY);
+ float sr = sys_getsr();
+ float ksr = sr * 0.001;
+ int bufsize = ksr * maxdelay;
+ t_float *buf = (t_float *)getbytes(bufsize * sizeof(*buf));
+ if (!buf)
+ return (0);
+ x = (t_comb *)pd_new(comb_class);
+ x->x_maxdelay = maxdelay;
+ x->x_sr = sr;
+ x->x_ksr = ksr;
+ x->x_bufsize = x->x_maxsize = bufsize;
+ x->x_buf = buf;
+ if (f2 < 0) f2 = 0;
+ if (f5 < -COMB_MAXFEEDBACK) f5 = -COMB_MAXFEEDBACK;
+ else if (f5 > COMB_MAXFEEDBACK) f5 = COMB_MAXFEEDBACK;
+ sic_newinlet((t_sic *)x, f2);
+ sic_newinlet((t_sic *)x, f3);
+ sic_newinlet((t_sic *)x, f4);
+ sic_newinlet((t_sic *)x, f5);
+ outlet_new((t_object *)x, &s_signal);
+ comb_clear(x);
+ return (x);
+}
+
+static void comb_free(t_comb *x)
+{
+ if (x->x_buf) freebytes(x->x_buf, x->x_bufsize * sizeof(*x->x_buf));
+}
+
+void comb_tilde_setup(void)
+{
+ comb_class = class_new(gensym("comb~"),
+ (t_newmethod)comb_new,
+ (t_method)comb_free,
+ sizeof(t_comb), 0,
+ A_DEFFLOAT, A_DEFFLOAT,
+ A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0);
+ sic_setup(comb_class, comb_dsp, SIC_FLOATTOSIGNAL);
+ class_addmethod(comb_class, (t_method)comb_clear, gensym("clear"), 0);
+}
diff --git a/cyclone/sickle/cosh.c b/cyclone/sickle/cosh.c
new file mode 100644
index 0000000..ae5f8cb
--- /dev/null
+++ b/cyclone/sickle/cosh.c
@@ -0,0 +1,48 @@
+/* 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 <math.h>
+#include "m_pd.h"
+#include "sickle/sic.h"
+
+#if defined(NT) || defined(MACOSX)
+/* cf pd/src/x_arithmetic.c */
+#define coshf cosh
+#endif
+
+typedef t_sic t_cosh;
+static t_class *cosh_class;
+
+static t_int *cosh_perform(t_int *w)
+{
+ int nblock = (int)(w[1]);
+ t_float *in = (t_float *)(w[2]);
+ t_float *out = (t_float *)(w[3]);
+ while (nblock--)
+ {
+ float f = *in++;
+ *out++ = coshf(f); /* CHECKME no protection against overflow */
+ }
+ return (w + 4);
+}
+
+static void cosh_dsp(t_cosh *x, t_signal **sp)
+{
+ dsp_add(cosh_perform, 3, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec);
+}
+
+static void *cosh_new(void)
+{
+ t_cosh *x = (t_cosh *)pd_new(cosh_class);
+ outlet_new((t_object *)x, &s_signal);
+ return (x);
+}
+
+void cosh_tilde_setup(void)
+{
+ cosh_class = class_new(gensym("cosh~"),
+ (t_newmethod)cosh_new, 0,
+ sizeof(t_cosh), 0, 0);
+ sic_setup(cosh_class, cosh_dsp, SIC_FLOATTOSIGNAL);
+}
diff --git a/cyclone/sickle/cosx.c b/cyclone/sickle/cosx.c
new file mode 100644
index 0000000..b368559
--- /dev/null
+++ b/cyclone/sickle/cosx.c
@@ -0,0 +1,51 @@
+/* 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 <math.h>
+#include "m_pd.h"
+#include "sickle/sic.h"
+
+/* by definition, this is just an interface to the -lm call
+ (do not use costable) */
+
+#if defined(NT) || defined(MACOSX)
+/* cf pd/src/x_arithmetic.c */
+#define cosf cos
+#endif
+
+typedef t_sic t_cosx;
+static t_class *cosx_class;
+
+static t_int *cosx_perform(t_int *w)
+{
+ int nblock = (int)(w[1]);
+ t_float *in = (t_float *)(w[2]);
+ t_float *out = (t_float *)(w[3]);
+ while (nblock--)
+ {
+ float f = *in++;
+ *out++ = cosf(f);
+ }
+ return (w + 4);
+}
+
+static void cosx_dsp(t_cosx *x, t_signal **sp)
+{
+ dsp_add(cosx_perform, 3, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec);
+}
+
+static void *cosx_new(void)
+{
+ t_cosx *x = (t_cosx *)pd_new(cosx_class);
+ outlet_new((t_object *)x, &s_signal);
+ return (x);
+}
+
+void cosx_tilde_setup(void)
+{
+ cosx_class = class_new(gensym("cosx~"),
+ (t_newmethod)cosx_new, 0,
+ sizeof(t_cosx), 0, 0);
+ sic_setup(cosx_class, cosx_dsp, SIC_FLOATTOSIGNAL);
+}
diff --git a/cyclone/sickle/count.c b/cyclone/sickle/count.c
new file mode 100644
index 0000000..b2ed2cd
--- /dev/null
+++ b/cyclone/sickle/count.c
@@ -0,0 +1,145 @@
+/* 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"
+
+typedef struct _count
+{
+ t_sic x_sic;
+ int x_min;
+ int x_max;
+ int x_limit;
+ int x_on;
+ int x_autoreset;
+ int x_count; /* MAYBE use 64 bits (if 13.5 hours is not enough...) */
+} t_count;
+
+static t_class *count_class;
+
+static void count_min(t_count *x, t_floatarg f)
+{
+ x->x_min = (int)f;
+}
+
+static void count_max(t_count *x, t_floatarg f)
+{
+ x->x_max = (int)f;
+ /* MAYBE use 64 bits */
+ x->x_limit = (x->x_max == 0 ? 0x7fffffff
+ : x->x_max - 1); /* CHECKED */
+}
+
+static void count_autoreset(t_count *x, t_floatarg f)
+{
+ x->x_autoreset = (f != 0);
+}
+
+static void count_bang(t_count *x)
+{
+ x->x_count = x->x_min;
+ x->x_on = 1;
+}
+
+static void count_float(t_count *x, t_floatarg f)
+{
+ x->x_count = x->x_min = (int)f;
+ x->x_on = 1;
+}
+
+static void count_list(t_count *x, t_symbol *s, int ac, t_atom *av)
+{
+ int i;
+ if (ac > 4) ac = 4;
+ for (i = 0; i < ac; i++)
+ if (av[i].a_type != A_FLOAT) break;
+ switch (i)
+ {
+ case 4:
+ count_autoreset(x, av[3].a_w.w_float);
+ case 3:
+ x->x_on = (av[2].a_w.w_float != 0);
+ case 2:
+ count_max(x, av[1].a_w.w_float);
+ case 1:
+ count_min(x, av[0].a_w.w_float);
+ default:
+ x->x_count = x->x_min;
+ }
+}
+
+static void count_set(t_count *x, t_symbol s, int ac, t_atom *av)
+{
+ if (av[0].a_type == A_FLOAT) count_min(x, av[0].a_w.w_float);
+ if (av[1].a_type == A_FLOAT) count_max(x, av[1].a_w.w_float);
+}
+
+static void count_stop(t_count *x)
+{
+ x->x_count = x->x_min;
+ x->x_on = 0;
+}
+
+static t_int *count_perform(t_int *w)
+{
+ t_count *x = (t_count *)(w[1]);
+ int nblock = (int)(w[2]);
+ t_float *out = (t_float *)(w[3]);
+ int count = x->x_count;
+ int limit = x->x_limit;
+ if (x->x_on)
+ {
+ while (nblock--)
+ {
+ if (count > limit) count = x->x_min;
+ *out++ = (t_float)count++;
+ }
+ }
+ else
+ while (nblock--) *out++ = count;
+ x->x_count = count;
+ return (w + 4);
+}
+
+static void count_dsp(t_count *x, t_signal **sp)
+{
+ if (x->x_autoreset) count_bang(x);
+ dsp_add(count_perform, 3, x, sp[0]->s_n, sp[0]->s_vec);
+}
+
+static void *count_new(t_floatarg minval, t_floatarg maxval,
+ t_floatarg onflag, t_floatarg autoflag)
+{
+ t_count *x = (t_count *)pd_new(count_class);
+ count_min(x, minval);
+ count_max(x, maxval);
+ x->x_on = (onflag != 0);
+ count_autoreset(x, autoflag);
+ x->x_count = x->x_min;
+ inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft1"));
+ outlet_new((t_object *)x, &s_signal);
+ return (x);
+}
+
+void count_tilde_setup(void)
+{
+ count_class = class_new(gensym("count~"),
+ (t_newmethod)count_new, 0,
+ sizeof(t_count), 0,
+ A_DEFFLOAT, A_DEFFLOAT,
+ A_DEFFLOAT, A_DEFFLOAT, 0);
+ sic_setup(count_class, count_dsp, SIC_NOMAINSIGNALIN);
+ class_addbang(count_class, count_bang);
+ class_addfloat(count_class, count_float);
+ class_addlist(count_class, count_list);
+ class_addmethod(count_class, (t_method)count_max,
+ gensym("ft1"), A_FLOAT, 0);
+ class_addmethod(count_class, (t_method)count_autoreset,
+ gensym("autoreset"), A_FLOAT, 0);
+ class_addmethod(count_class, (t_method)count_min,
+ gensym("min"), A_FLOAT, 0);
+ class_addmethod(count_class, (t_method)count_set,
+ gensym("set"), A_GIMME, 0);
+ class_addmethod(count_class, (t_method)count_stop, gensym("stop"), 0);
+}
diff --git a/cyclone/sickle/cycle.c b/cyclone/sickle/cycle.c
new file mode 100644
index 0000000..01500ba
--- /dev/null
+++ b/cyclone/sickle/cycle.c
@@ -0,0 +1,173 @@
+/* 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 <string.h>
+#include "m_pd.h"
+#include "shared.h"
+#include "common/loud.h"
+#include "common/vefl.h"
+#include "sickle/sic.h"
+
+#define CYCLE_TABSIZE 512
+
+typedef struct _cycle
+{
+ t_sic x_sic;
+ double x_phase;
+ double x_conv;
+ t_symbol *x_name;
+ int x_offset;
+ t_float *x_table;
+ t_float *x_costable;
+ t_float x_usertable[CYCLE_TABSIZE + 1];
+} t_cycle;
+
+static t_class *cycle_class;
+
+static void cycle_gettable(t_cycle *x)
+{
+ x->x_table = 0;
+ if (x->x_name)
+ {
+ int tabsize = 0;
+ t_float *table = vefl_get(x->x_name, &tabsize, 1, (t_pd *)x);
+ /* CHECKED buffer is copied */
+ if (table)
+ {
+ int indx = x->x_offset + CYCLE_TABSIZE;
+ t_float *ptr = x->x_usertable + CYCLE_TABSIZE;
+ if (indx == tabsize)
+ {
+ *ptr-- = *table;
+ indx--;
+ }
+ if (indx < tabsize)
+ {
+ table += indx;
+ indx -= x->x_offset;
+ while (indx--) *ptr-- = *table--;
+ x->x_table = x->x_usertable;
+ }
+ /* CHECKED else no complaint */
+ }
+ }
+ else x->x_table = x->x_costable;
+ if (!x->x_table)
+ {
+ /* CHECKED (incompatible) cycle~ is disabled -- garbage is output */
+ x->x_table = x->x_usertable;
+ memset(x->x_table, 0, (CYCLE_TABSIZE + 1) * sizeof(*x->x_table));
+ }
+}
+
+static void cycle_set(t_cycle *x, t_symbol *s, t_floatarg f)
+{
+ if (s && s != &s_)
+ {
+ x->x_name = s;
+ if ((x->x_offset = (int)f) < 0)
+ x->x_offset = 0;
+ }
+ else x->x_name = 0;
+ cycle_gettable(x);
+}
+
+static t_int *cycle_perform(t_int *w)
+{
+ t_cycle *x = (t_cycle *)(w[1]);
+ int nblock = (int)(w[2]);
+ t_float *in1 = (t_float *)(w[3]);
+ t_float *in2 = (t_float *)(w[4]);
+ t_float *out = (t_float *)(w[5]);
+ t_float *tab = x->x_table;
+ t_float *addr, f1, f2, frac;
+ double dphase = x->x_phase + SHARED_UNITBIT32;
+ double conv = x->x_conv;
+ int32 normhipart;
+ t_shared_wrappy wrappy;
+
+ wrappy.w_d = SHARED_UNITBIT32;
+ normhipart = wrappy.w_i[SHARED_HIOFFSET];
+
+ wrappy.w_d = dphase + CYCLE_TABSIZE * *in2++; /* CHECKED */
+ dphase += *in1++ * conv;
+ addr = tab + (wrappy.w_i[SHARED_HIOFFSET] & (CYCLE_TABSIZE-1));
+ wrappy.w_i[SHARED_HIOFFSET] = normhipart;
+ frac = wrappy.w_d - SHARED_UNITBIT32;
+
+ while (--nblock)
+ {
+ wrappy.w_d = dphase + CYCLE_TABSIZE * *in2++; /* CHECKED */
+ dphase += *in1++ * conv;
+ f1 = addr[0];
+ f2 = addr[1];
+ addr = tab + (wrappy.w_i[SHARED_HIOFFSET] & (CYCLE_TABSIZE-1));
+ wrappy.w_i[SHARED_HIOFFSET] = normhipart;
+ *out++ = f1 + frac * (f2 - f1);
+ frac = wrappy.w_d - SHARED_UNITBIT32;
+ }
+ f1 = addr[0];
+ f2 = addr[1];
+ *out++ = f1 + frac * (f2 - f1);
+
+ wrappy.w_d = SHARED_UNITBIT32 * CYCLE_TABSIZE;
+ normhipart = wrappy.w_i[SHARED_HIOFFSET];
+ wrappy.w_d = dphase + (SHARED_UNITBIT32 * CYCLE_TABSIZE - SHARED_UNITBIT32);
+ wrappy.w_i[SHARED_HIOFFSET] = normhipart;
+ x->x_phase = wrappy.w_d - (SHARED_UNITBIT32 * CYCLE_TABSIZE);
+ return (w + 6);
+}
+
+static void cycle_dsp(t_cycle *x, t_signal **sp)
+{
+ cycle_gettable(x);
+ x->x_conv = CYCLE_TABSIZE / sp[0]->s_sr;
+ dsp_add(cycle_perform, 5, x, sp[0]->s_n,
+ sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec);
+}
+
+static void *cycle_new(t_symbol *s, int ac, t_atom *av)
+{
+ t_cycle *x = (t_cycle *)pd_new(cycle_class);
+ int i = (ac && av->a_type == A_FLOAT ? 1 : 0);
+ int tabsize = CYCLE_TABSIZE;
+ x->x_costable = sic_makecostable(&tabsize);
+ if (tabsize != CYCLE_TABSIZE)
+ {
+ bug("cycle_new");
+ pd_free((t_pd *)x);
+ return (0);
+ }
+ if (ac && av->a_type == A_FLOAT)
+ {
+ sic_inlet((t_sic *)x, 0, 0, 0, ac, av);
+ ac--, av++;
+ }
+ sic_newinlet((t_sic *)x, 0);
+ outlet_new((t_object *)x, &s_signal);
+ x->x_offset = 0;
+ if (ac && av->a_type == A_SYMBOL)
+ {
+ x->x_name = av->a_w.w_symbol;
+ ac--, av++;
+ if (ac && av->a_type == A_FLOAT)
+ if ((x->x_offset = (int)av->a_w.w_float) < 0)
+ x->x_offset = 0;
+ }
+ else x->x_name = 0;
+ x->x_table = 0;
+ x->x_phase = 0.;
+ x->x_conv = 0.;
+ return (x);
+}
+
+void cycle_tilde_setup(void)
+{
+ cycle_class = class_new(gensym("cycle~"),
+ (t_newmethod)cycle_new, 0,
+ sizeof(t_cycle), 0, A_GIMME, 0);
+ sic_setup(cycle_class, cycle_dsp, SIC_FLOATTOSIGNAL);
+ class_addmethod(cycle_class, (t_method)cycle_set,
+ gensym("set"), A_DEFSYMBOL, A_DEFFLOAT, 0);
+}
diff --git a/cyclone/sickle/delay.c b/cyclone/sickle/delay.c
new file mode 100644
index 0000000..b0ddd9d
--- /dev/null
+++ b/cyclone/sickle/delay.c
@@ -0,0 +1,101 @@
+/* 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 <string.h>
+#include "m_pd.h"
+#include "sickle/sic.h"
+
+typedef struct _delay
+{
+ t_sic x_sic;
+ t_float *x_buf;
+ t_float *x_bufend;
+ t_float *x_whead;
+ int x_maxsize;
+ int x_delsize;
+} t_delay;
+
+static t_class *delay_class;
+
+#define DELAY_DEFMAXSIZE 512
+
+static void delay_ft1(t_delay *x, t_floatarg f)
+{
+ x->x_delsize = (f > 0 ? (int)f : 0);
+ if (x->x_delsize > x->x_maxsize)
+ x->x_delsize = x->x_maxsize; /* CHECKED */
+ /* CHECKED: all buffered values should be available */
+}
+
+static t_int *delay_perform(t_int *w)
+{
+ t_delay *x = (t_delay *)(w[1]);
+ int nblock = (int)(w[2]);
+ t_float *in = (t_float *)(w[3]);
+ t_float *out = (t_float *)(w[4]);
+ t_float *buf = x->x_buf;
+ t_float *ep = x->x_bufend;
+ t_float *wp = x->x_whead;
+ if (x->x_delsize)
+ {
+ t_float *rp = wp - x->x_delsize;
+ if (rp < buf) rp += x->x_maxsize;
+ while (nblock--)
+ {
+ float f = *in++;
+ *out++ = *rp;
+ if (rp++ == ep) rp = buf;
+ *wp = f;
+ if (wp++ == ep) wp = buf;
+ }
+ }
+ else while (nblock--)
+ {
+ *out++ = *wp = *in++;
+ if (wp++ == ep) wp = buf;
+ }
+ x->x_whead = wp;
+ return (w + 5);
+}
+
+static void delay_dsp(t_delay *x, t_signal **sp)
+{
+ memset(x->x_buf, 0, x->x_maxsize * sizeof(*x->x_buf)); /* CHECKED */
+ x->x_whead = x->x_buf;
+ dsp_add(delay_perform, 4, x, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec);
+}
+
+static void *delay_new(t_floatarg f1, t_floatarg f2)
+{
+ t_delay *x;
+ int maxsize = (f1 > 0 ? (int)f1 : DELAY_DEFMAXSIZE);
+ t_float *buf = (t_float *)getbytes(maxsize * sizeof(*buf));
+ if (!buf)
+ return (0);
+ x = (t_delay *)pd_new(delay_class);
+ x->x_maxsize = maxsize;
+ x->x_buf = x->x_whead = buf;
+ x->x_bufend = buf + maxsize - 1;
+ x->x_delsize = (f2 > 0 ? (int)f2 : 0);
+ if (x->x_delsize > maxsize)
+ x->x_delsize = maxsize;
+ inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft1"));
+ outlet_new((t_object *)x, &s_signal);
+ return (x);
+}
+
+static void delay_free(t_delay *x)
+{
+ if (x->x_buf) freebytes(x->x_buf, x->x_maxsize * sizeof(*x->x_buf));
+}
+
+void delay_tilde_setup(void)
+{
+ delay_class = class_new(gensym("delay~"),
+ (t_newmethod)delay_new, (t_method)delay_free,
+ sizeof(t_delay), 0, A_DEFFLOAT, A_DEFFLOAT, 0);
+ sic_setup(delay_class, delay_dsp, SIC_FLOATTOSIGNAL);
+ class_addmethod(delay_class, (t_method)delay_ft1,
+ gensym("ft1"), A_FLOAT, 0);
+}
diff --git a/cyclone/sickle/delta.c b/cyclone/sickle/delta.c
new file mode 100644
index 0000000..145d6b7
--- /dev/null
+++ b/cyclone/sickle/delta.c
@@ -0,0 +1,52 @@
+/* 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"
+
+typedef struct _delta
+{
+ t_sic x_sic;
+ t_float x_last;
+} t_delta;
+
+static t_class *delta_class;
+
+static t_int *delta_perform(t_int *w)
+{
+ t_delta *x = (t_delta *)(w[1]);
+ int nblock = (int)(w[2]);
+ t_float *in = (t_float *)(w[3]);
+ t_float *out = (t_float *)(w[4]);
+ t_float last = x->x_last;
+ while (nblock--)
+ {
+ t_float f = *in++;
+ *out++ = f - last;
+ last = f;
+ }
+ x->x_last = last;
+ return (w + 5);
+}
+
+static void delta_dsp(t_delta *x, t_signal **sp)
+{
+ dsp_add(delta_perform, 4, x, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec);
+}
+
+static void *delta_new(void)
+{
+ t_delta *x = (t_delta *)pd_new(delta_class);
+ outlet_new((t_object *)x, &s_signal);
+ x->x_last = 0;
+ return (x);
+}
+
+void delta_tilde_setup(void)
+{
+ delta_class = class_new(gensym("delta~"),
+ (t_newmethod)delta_new, 0,
+ sizeof(t_delta), 0, 0);
+ sic_setup(delta_class, delta_dsp, SIC_FLOATTOSIGNAL);
+}
diff --git a/cyclone/sickle/deltaclip.c b/cyclone/sickle/deltaclip.c
new file mode 100644
index 0000000..89c9321
--- /dev/null
+++ b/cyclone/sickle/deltaclip.c
@@ -0,0 +1,67 @@
+/* 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 "shared.h"
+#include "sickle/sic.h"
+
+#define DELTACLIP_DEFLO 0.
+#define DELTACLIP_DEFHI 0.
+
+typedef struct _deltaclip
+{
+ t_sic x_sic;
+ t_float x_last;
+} t_deltaclip;
+
+static t_class *deltaclip_class;
+
+static t_int *deltaclip_perform(t_int *w)
+{
+ t_deltaclip *x = (t_deltaclip *)(w[1]);
+ int nblock = (int)(w[2]);
+ t_float *in1 = (t_float *)(w[3]);
+ t_float *in2 = (t_float *)(w[4]);
+ t_float *in3 = (t_float *)(w[5]);
+ t_float *out = (t_float *)(w[6]);
+ t_float last = x->x_last;
+ while (nblock--)
+ {
+ float f = *in1++;
+ float delta = f - last;
+ float lo = *in2++;
+ float hi = *in3++;
+ if (delta < lo)
+ f = last + lo;
+ else if (delta > hi)
+ f = last + hi;
+ *out++ = last = f;
+ }
+ x->x_last = last;
+ return (w + 7);
+}
+
+static void deltaclip_dsp(t_deltaclip *x, t_signal **sp)
+{
+ dsp_add(deltaclip_perform, 6, x, sp[0]->s_n,
+ sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec);
+}
+
+static void *deltaclip_new(t_symbol *s, int ac, t_atom *av)
+{
+ t_deltaclip *x = (t_deltaclip *)pd_new(deltaclip_class);
+ sic_inlet((t_sic *)x, 1, DELTACLIP_DEFLO, 0, ac, av);
+ sic_inlet((t_sic *)x, 2, DELTACLIP_DEFHI, 1, ac, av);
+ outlet_new((t_object *)x, &s_signal);
+ x->x_last = 0;
+ return (x);
+}
+
+void deltaclip_tilde_setup(void)
+{
+ deltaclip_class = class_new(gensym("deltaclip~"),
+ (t_newmethod)deltaclip_new, 0,
+ sizeof(t_deltaclip), 0, A_GIMME, 0);
+ sic_setup(deltaclip_class, deltaclip_dsp, SIC_FLOATTOSIGNAL);
+}
diff --git a/cyclone/sickle/edge.c b/cyclone/sickle/edge.c
new file mode 100644
index 0000000..b206f6b
--- /dev/null
+++ b/cyclone/sickle/edge.c
@@ -0,0 +1,106 @@
+/* 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"
+
+typedef struct _edge
+{
+ t_sic x_sic;
+ t_float x_last;
+ int x_zeroleft;
+ int x_zerohit;
+ t_outlet *x_out2;
+ t_clock *x_clock;
+} t_edge;
+
+static t_class *edge_class;
+
+static void edge_tick(t_edge *x)
+{
+ /* CHECKED both may fire simultaneously */
+ if (x->x_zeroleft)
+ {
+ outlet_bang(((t_object *)x)->ob_outlet);
+ x->x_zeroleft = 0;
+ }
+ if (x->x_zerohit)
+ {
+ outlet_bang(x->x_out2);
+ x->x_zerohit = 0;
+ }
+}
+
+static t_int *edge_perform(t_int *w)
+{
+ t_edge *x = (t_edge *)(w[1]);
+ int nblock = (int)(w[2]);
+ t_float *in = (t_float *)(w[3]);
+ t_float last = x->x_last;
+ while (nblock--)
+ {
+ float f = *in++;
+ if (last == 0.)
+ {
+ if (f != 0.)
+ {
+ x->x_zeroleft = 1;
+ if (x->x_zerohit)
+ {
+ clock_delay(x->x_clock, 0);
+ x->x_last = in[nblock - 1];
+ return (w + 4);
+ }
+ }
+ }
+ else
+ {
+ if (f == 0.)
+ {
+ x->x_zerohit = 1;
+ if (x->x_zeroleft)
+ {
+ clock_delay(x->x_clock, 0);
+ x->x_last = in[nblock - 1];
+ return (w + 4);
+ }
+ }
+ }
+ last = f;
+ }
+ if (x->x_zeroleft || x->x_zerohit) clock_delay(x->x_clock, 0);
+ x->x_last = last;
+ return (w + 4);
+}
+
+static void edge_dsp(t_edge *x, t_signal **sp)
+{
+ dsp_add(edge_perform, 3, x, sp[0]->s_n, sp[0]->s_vec);
+}
+
+static void edge_free(t_edge *x)
+{
+ if (x->x_clock) clock_free(x->x_clock);
+}
+
+static void *edge_new(t_floatarg f)
+{
+ t_edge *x = (t_edge *)pd_new(edge_class);
+ x->x_last = 0.; /* CHECKED fires at startup */
+ x->x_zeroleft = x->x_zerohit = 0;
+ outlet_new((t_object *)x, &s_bang);
+ x->x_out2 = outlet_new((t_object *)x, &s_bang);
+ x->x_clock = clock_new(x, (t_method)edge_tick);
+ return (x);
+}
+
+void edge_tilde_setup(void)
+{
+ edge_class = class_new(gensym("edge~"),
+ (t_newmethod)edge_new,
+ (t_method)edge_free,
+ sizeof(t_edge), 0,
+ A_DEFFLOAT, 0);
+ sic_setup(edge_class, edge_dsp, SIC_FLOATTOSIGNAL);
+}
diff --git a/cyclone/sickle/frameaccum.c b/cyclone/sickle/frameaccum.c
new file mode 100644
index 0000000..6038ae5
--- /dev/null
+++ b/cyclone/sickle/frameaccum.c
@@ -0,0 +1,71 @@
+/* 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 <string.h>
+#include "m_pd.h"
+#include "common/grow.h"
+#include "sickle/sic.h"
+
+#define FRAMEACCUM_INISIZE 512
+
+typedef struct _frameaccum
+{
+ t_sic x_sic;
+ int x_size;
+ t_float *x_frame;
+ t_float x_frameini[FRAMEACCUM_INISIZE];
+} t_frameaccum;
+
+static t_class *frameaccum_class;
+
+static t_int *frameaccum_perform(t_int *w)
+{
+ int nblock = (int)(w[1]);
+ t_float *frame = (t_float *)(w[2]);
+ t_float *in = (t_float *)(w[3]);
+ t_float *out = (t_float *)(w[4]);
+ while (nblock--) *out++ = (*frame++ += *in++);
+ return (w + 5);
+}
+
+static void frameaccum_dsp(t_frameaccum *x, t_signal **sp)
+{
+ int nblock = sp[0]->s_n;
+ if (nblock > x->x_size)
+ x->x_frame = grow_nodata(&nblock, &x->x_size, x->x_frame,
+ FRAMEACCUM_INISIZE, x->x_frameini,
+ sizeof(*x->x_frame));
+ memset(x->x_frame, 0, nblock * sizeof(*x->x_frame)); /* CHECKED */
+ dsp_add(frameaccum_perform, 4, nblock, x->x_frame,
+ sp[0]->s_vec, sp[1]->s_vec);
+}
+
+static void frameaccum_free(t_frameaccum *x)
+{
+ if (x->x_frame != x->x_frameini)
+ freebytes(x->x_frame, x->x_size * sizeof(*x->x_frame));
+}
+
+static void *frameaccum_new(t_symbol *s, int ac, t_atom *av)
+{
+ t_frameaccum *x = (t_frameaccum *)pd_new(frameaccum_class);
+ int size;
+ x->x_size = FRAMEACCUM_INISIZE;
+ x->x_frame = x->x_frameini;
+ if ((size = sys_getblksize()) > FRAMEACCUM_INISIZE)
+ x->x_frame = grow_nodata(&size, &x->x_size, x->x_frame,
+ FRAMEACCUM_INISIZE, x->x_frameini,
+ sizeof(*x->x_frame));
+ outlet_new((t_object *)x, &s_signal);
+ return (x);
+}
+
+void frameaccum_tilde_setup(void)
+{
+ frameaccum_class = class_new(gensym("frameaccum~"),
+ (t_newmethod)frameaccum_new,
+ (t_method)frameaccum_free,
+ sizeof(t_frameaccum), 0, 0);
+ sic_setup(frameaccum_class, frameaccum_dsp, SIC_FLOATTOSIGNAL);
+}
diff --git a/cyclone/sickle/framedelta.c b/cyclone/sickle/framedelta.c
new file mode 100644
index 0000000..b898444
--- /dev/null
+++ b/cyclone/sickle/framedelta.c
@@ -0,0 +1,76 @@
+/* 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 <string.h>
+#include "m_pd.h"
+#include "common/grow.h"
+#include "sickle/sic.h"
+
+#define FRAMEDELTA_INISIZE 512
+
+typedef struct _framedelta
+{
+ t_sic x_sic;
+ int x_size;
+ t_float *x_frame;
+ t_float x_frameini[FRAMEDELTA_INISIZE];
+} t_framedelta;
+
+static t_class *framedelta_class;
+
+static t_int *framedelta_perform(t_int *w)
+{
+ int nblock = (int)(w[1]);
+ t_float *frame = (t_float *)(w[2]);
+ t_float *in = (t_float *)(w[3]);
+ t_float *out = (t_float *)(w[4]);
+ while (nblock--)
+ {
+ float f = *in++;
+ *out++ = f - *frame; /* CHECKME */
+ *frame++ = f;
+ }
+ return (w + 5);
+}
+
+static void framedelta_dsp(t_framedelta *x, t_signal **sp)
+{
+ int nblock = sp[0]->s_n;
+ if (nblock > x->x_size)
+ x->x_frame = grow_nodata(&nblock, &x->x_size, x->x_frame,
+ FRAMEDELTA_INISIZE, x->x_frameini,
+ sizeof(*x->x_frame));
+ memset(x->x_frame, 0, nblock * sizeof(*x->x_frame)); /* CHECKME */
+ dsp_add(framedelta_perform, 4, nblock, x->x_frame,
+ sp[0]->s_vec, sp[1]->s_vec);
+}
+
+static void framedelta_free(t_framedelta *x)
+{
+ if (x->x_frame != x->x_frameini)
+ freebytes(x->x_frame, x->x_size * sizeof(*x->x_frame));
+}
+
+static void *framedelta_new(t_symbol *s, int ac, t_atom *av)
+{
+ t_framedelta *x = (t_framedelta *)pd_new(framedelta_class);
+ int size;
+ x->x_size = FRAMEDELTA_INISIZE;
+ x->x_frame = x->x_frameini;
+ if ((size = sys_getblksize()) > FRAMEDELTA_INISIZE)
+ x->x_frame = grow_nodata(&size, &x->x_size, x->x_frame,
+ FRAMEDELTA_INISIZE, x->x_frameini,
+ sizeof(*x->x_frame));
+ outlet_new((t_object *)x, &s_signal);
+ return (x);
+}
+
+void framedelta_tilde_setup(void)
+{
+ framedelta_class = class_new(gensym("framedelta~"),
+ (t_newmethod)framedelta_new,
+ (t_method)framedelta_free,
+ sizeof(t_framedelta), 0, 0);
+ sic_setup(framedelta_class, framedelta_dsp, SIC_FLOATTOSIGNAL);
+}
diff --git a/cyclone/sickle/index.c b/cyclone/sickle/index.c
new file mode 100644
index 0000000..036e6fb
--- /dev/null
+++ b/cyclone/sickle/index.c
@@ -0,0 +1,107 @@
+/* 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. */
+
+/* LATER: 'click' method */
+
+#include <string.h>
+#include "m_pd.h"
+#include "sickle/sic.h"
+#include "sickle/arsic.h"
+
+#define INDEX_MAXCHANNELS 4 /* LATER implement arsic resizing feature */
+
+typedef struct _index
+{
+ t_arsic x_arsic;
+ int x_maxchannels;
+ int x_effchannel; /* effective channel (clipped reqchannel) */
+ int x_reqchannel; /* requested channel */
+} t_index;
+
+static t_class *index_class;
+
+static void index_set(t_index *x, t_symbol *s)
+{
+ arsic_setarray((t_arsic *)x, s, 1);
+}
+
+static t_int *index_perform(t_int *w)
+{
+ t_arsic *sic = (t_arsic *)(w[1]);
+ int nblock = (int)(w[2]);
+ t_float *out = (t_float *)(w[4]);
+ if (sic->s_playable)
+ {
+ t_index *x = (t_index *)sic;
+ t_float *xin = (t_float *)(w[3]);
+ int index, maxindex = sic->s_vecsize - 1;
+ t_float *vp = sic->s_vectors[x->x_effchannel];
+ if (vp) /* handle array swapping on the fly via ft1 */
+ {
+ while (nblock--)
+ {
+ index = (int)(*xin++ + 0.5);
+ if (index < 0)
+ index = 0;
+ else if (index > maxindex)
+ index = maxindex;
+ *out++ = vp[index];
+ }
+ }
+ else while (nblock--) *out++ = 0;
+ }
+ else while (nblock--) *out++ = 0;
+ return (w + 5);
+}
+
+static void index_ft1(t_index *x, t_floatarg f)
+{
+ if ((x->x_reqchannel = (f > 1 ? (int)f - 1 : 0)) > x->x_maxchannels)
+ x->x_effchannel = x->x_maxchannels - 1;
+ else
+ x->x_effchannel = x->x_reqchannel;
+}
+
+static void index_dsp(t_index *x, t_signal **sp)
+{
+ t_arsic *sic = (t_arsic *)x;
+ arsic_dsp(sic, sp, index_perform, sic->s_mononame != 0);
+}
+
+static void index_free(t_index *x)
+{
+ arsic_free((t_arsic *)x);
+}
+
+static void *index_new(t_symbol *s, t_floatarg f)
+{
+ int ch = (f > 0 ? (int)f : 0);
+ /* two signals: index input, value output */
+ t_index *x = (t_index *)arsic_new(index_class, s,
+ (ch ? INDEX_MAXCHANNELS : 0), 2, 0);
+ if (x)
+ {
+ if (ch > INDEX_MAXCHANNELS)
+ ch = INDEX_MAXCHANNELS;
+ x->x_maxchannels = (ch ? INDEX_MAXCHANNELS : 1);
+ x->x_effchannel = x->x_reqchannel = (ch ? ch - 1 : 0);
+ inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft1"));
+ outlet_new((t_object *)x, &s_signal);
+ }
+ return (x);
+}
+
+void index_tilde_setup(void)
+{
+ index_class = class_new(gensym("index~"),
+ (t_newmethod)index_new,
+ (t_method)index_free,
+ sizeof(t_index), 0,
+ A_DEFSYM, A_DEFFLOAT, 0);
+ arsic_setup(index_class, index_dsp, SIC_FLOATTOSIGNAL);
+ class_addmethod(index_class, (t_method)index_set,
+ gensym("set"), A_SYMBOL, 0);
+ class_addmethod(index_class, (t_method)index_ft1,
+ gensym("ft1"), A_FLOAT, 0);
+}
diff --git a/cyclone/sickle/kink.c b/cyclone/sickle/kink.c
new file mode 100644
index 0000000..86bc81d
--- /dev/null
+++ b/cyclone/sickle/kink.c
@@ -0,0 +1,62 @@
+/* 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. */
+
+/* CHECKED negative float in 2nd inlet: "illegal slope value %f",
+ but no complaints for signal input -- this is impossible in Pd.
+ The only thing we could do (and a bit stupid one) would be to
+ clock this exception out from the perf routine. */
+
+#include "m_pd.h"
+#include "sickle/sic.h"
+
+#define KINK_DEFSLOPE 1.0
+
+typedef t_sic t_kink;
+static t_class *kink_class;
+
+static t_int *kink_perform(t_int *w)
+{
+ int nblock = (int)(w[1]);
+ t_float *in1 = (t_float *)(w[2]);
+ t_float *in2 = (t_float *)(w[3]);
+ t_float *out = (t_float *)(w[4]);
+ while (nblock--)
+ {
+ float iph = *in1++;
+ float slope = *in2++;
+ float oph = iph * slope;
+ if (oph > .5)
+ {
+ slope = 1. / (slope + slope); /* x(y=.5) */
+ if (slope == 1.)
+ *out++ = 0; /* CHECKED */
+ else
+ *out++ = (iph - slope) / (2. - (slope + slope)) + .5;
+ }
+ else *out++ = oph;
+ }
+ return (w + 5);
+}
+
+static void kink_dsp(t_kink *x, t_signal **sp)
+{
+ dsp_add(kink_perform, 4, sp[0]->s_n,
+ sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec);
+}
+
+static void *kink_new(t_symbol *s, int ac, t_atom *av)
+{
+ t_kink *x = (t_kink *)pd_new(kink_class);
+ sic_inlet((t_sic *)x, 1, KINK_DEFSLOPE, 0, ac, av);
+ outlet_new((t_object *)x, &s_signal);
+ return (x);
+}
+
+void kink_tilde_setup(void)
+{
+ kink_class = class_new(gensym("kink~"),
+ (t_newmethod)kink_new, 0,
+ sizeof(t_kink), 0, A_GIMME, 0);
+ sic_setup(kink_class, kink_dsp, SIC_FLOATTOSIGNAL);
+}
diff --git a/cyclone/sickle/linedrive.c b/cyclone/sickle/linedrive.c
new file mode 100644
index 0000000..8b133ab
--- /dev/null
+++ b/cyclone/sickle/linedrive.c
@@ -0,0 +1,73 @@
+/* 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. */
+
+/* CHECKME polarity */
+
+#include <math.h>
+#include "m_pd.h"
+
+#if defined(NT) || defined(MACOSX)
+#define logf log
+#define expf exp
+#endif
+
+static t_class *linedrive_class;
+
+typedef struct _linedrive
+{
+ t_object x_ob;
+ t_float x_maxin;
+ t_float x_maxout;
+ t_float x_expcoef;
+ t_float x_lincoef;
+ t_atom x_vec[2];
+ int x_linear;
+} t_linedrive;
+
+static void linedrive_float(t_linedrive *x, t_floatarg f)
+{
+ float outval = f - x->x_maxin;
+ if (outval >= 0)
+ outval = x->x_maxout; /* CHECKED */
+ else if (x->x_linear)
+ outval = x->x_maxout + outval * x->x_lincoef;
+ else
+ outval = expf(outval * x->x_expcoef) * x->x_maxout;
+ SETFLOAT(x->x_vec, outval);
+ outlet_list(((t_object *)x)->ob_outlet, 0, 2, x->x_vec);
+}
+
+static void *linedrive_new(t_floatarg maxin, t_floatarg maxout,
+ t_floatarg curve, t_floatarg deltime)
+{
+ t_linedrive *x = (t_linedrive *)pd_new(linedrive_class);
+ x->x_maxin = (maxin < 1.0e-20f && maxin > -1e-20f ? 0 : maxin);
+ x->x_maxout = maxout;
+ if (curve < 1.0e-20f) curve = 1.0; /* a bug in msp? */
+ if (curve == 1.0)
+ {
+ x->x_expcoef = 0;
+ x->x_lincoef = (x->x_maxin == 0 ? 0 : x->x_maxout / x->x_maxin);
+ x->x_linear = 1;
+ }
+ else {
+ x->x_expcoef = logf(curve);
+ x->x_lincoef = 0;
+ x->x_linear = 0;
+ }
+ SETFLOAT(&x->x_vec[1], deltime); /* CHECKED: any value accepted */
+ floatinlet_new((t_object *)x, &x->x_vec[1].a_w.w_float);
+ outlet_new((t_object *)x, &s_list);
+ return (x);
+}
+
+void linedrive_setup(void)
+{
+ linedrive_class = class_new(gensym("linedrive"),
+ (t_newmethod)linedrive_new, 0,
+ sizeof(t_linedrive), 0,
+ A_DEFFLOAT, A_DEFFLOAT,
+ A_DEFFLOAT, A_DEFFLOAT, 0);
+ class_addfloat(linedrive_class, linedrive_float);
+}
diff --git a/cyclone/sickle/log.c b/cyclone/sickle/log.c
new file mode 100644
index 0000000..74e3e40
--- /dev/null
+++ b/cyclone/sickle/log.c
@@ -0,0 +1,74 @@
+/* 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 <math.h>
+#include "m_pd.h"
+#include "sickle/sic.h"
+
+#if defined(NT) || defined(MACOSX)
+/* cf pd/src/x_arithmetic.c */
+#define logf log
+#endif
+
+#define LOG_MININPUT 1e-10 /* CHECKED */
+
+typedef struct _log
+{
+ t_sic x_sic;
+ t_float x_rcplogbase; /* LATER consider using double (and log()) */
+} t_log;
+
+static t_class *log_class;
+
+static void log_ft1(t_log *x, t_floatarg f)
+{
+ x->x_rcplogbase = (f == 0. ? 1. : /* CHECKED no protection against NaNs */
+ (f == 1. ? 0. : /* CHECKED */
+ 1. / logf(f)));
+}
+
+static t_int *log_perform(t_int *w)
+{
+ int nblock = (int)(w[1]);
+ t_float *in = (t_float *)(w[2]);
+ t_float *out = (t_float *)(w[3]);
+ t_float rcplogbase = *(t_float *)(w[4]);
+ if (rcplogbase != 0.)
+ {
+ while (nblock--)
+ {
+ float f = *in++;
+ if (f < LOG_MININPUT)
+ f = LOG_MININPUT; /* CHECKED */
+ *out++ = logf(f) * rcplogbase;
+ }
+ }
+ else while (nblock--) *out++ = 0.;
+ return (w + 5);
+}
+
+static void log_dsp(t_log *x, t_signal **sp)
+{
+ dsp_add(log_perform, 4, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec,
+ &x->x_rcplogbase);
+}
+
+static void *log_new(t_floatarg f)
+{
+ t_log *x = (t_log *)pd_new(log_class);
+ inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft1"));
+ outlet_new((t_object *)x, &s_signal);
+ log_ft1(x, f);
+ return (x);
+}
+
+void log_tilde_setup(void)
+{
+ log_class = class_new(gensym("log~"),
+ (t_newmethod)log_new, 0,
+ sizeof(t_log), 0, A_DEFFLOAT, 0);
+ sic_setup(log_class, log_dsp, SIC_FLOATTOSIGNAL);
+ class_addmethod(log_class, (t_method)log_ft1,
+ gensym("ft1"), A_FLOAT, 0);
+}
diff --git a/cyclone/sickle/lookup.c b/cyclone/sickle/lookup.c
new file mode 100644
index 0000000..1c6a8af
--- /dev/null
+++ b/cyclone/sickle/lookup.c
@@ -0,0 +1,94 @@
+/* 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. */
+
+/* LATER reconsider making float/int conversions
+ more compatible (and less useful). */
+
+#include "m_pd.h"
+#include "sickle/sic.h"
+#include "sickle/arsic.h"
+
+typedef t_arsic t_lookup;
+static t_class *lookup_class;
+
+#define LOOKUP_DEFSIZE 512
+
+static void lookup_set(t_lookup *x, t_symbol *s)
+{
+ arsic_setarray((t_arsic *)x, s, 1);
+}
+
+static t_int *lookup_perform(t_int *w)
+{
+ t_arsic *sic = (t_arsic *)(w[1]);
+ int nblock = (int)(w[2]);
+ t_float *out = (t_float *)(w[6]);
+ if (sic->s_playable)
+ {
+ t_float *xin = (t_float *)(w[3]);
+ 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) */
+ while (nblock--)
+ {
+ float off = *oin++; /* msp: converted to int (if not a signal) */
+ int siz = (int)*sin++ - 1; /* msp: converted to int (signal too) */
+ float pos = (siz > 0 ? off + siz * (*xin++ + 1.0) * 0.5 : off);
+ int ndx = (int)pos;
+ int ndx1 = ndx + 1;
+ if (ndx1 > 0 && ndx1 < vecsize)
+ {
+ float val = vec[ndx];
+ *out++ = val + (vec[ndx1] - val) * (pos - ndx);
+ }
+ /* CHECKED: */
+ else if (ndx1 == 0) *out++ = *vec * (pos + 1.0);
+ else if (ndx1 == vecsize) *out++ = vec[ndx] * (ndx1 - pos);
+ else *out++ = 0;
+ }
+ }
+ else while (nblock--) *out++ = 0;
+ return (w + 7);
+}
+
+static void lookup_dsp(t_lookup *x, t_signal **sp)
+{
+ arsic_dsp((t_arsic *)x, sp, lookup_perform, 1);
+}
+
+static void lookup_free(t_lookup *x)
+{
+ arsic_free((t_arsic *)x);
+}
+
+static void *lookup_new(t_symbol *s, t_floatarg f1, t_floatarg f2)
+{
+ /* CHECKED: lookup~ always uses the first channel in a multi-channel buffer~
+ (as the refman says). */
+ /* three auxiliary signals: amplitude, offset and size inputs */
+ t_lookup *x = (t_lookup *)arsic_new(lookup_class, s, 0, 0, 3);
+ if (x)
+ {
+ arsic_setminsize((t_arsic *)x, 2);
+ if (f1 < 0) f1 = 0;
+ if (f2 <= 0) f2 = LOOKUP_DEFSIZE;
+ sic_newinlet((t_sic *)x, f1);
+ sic_newinlet((t_sic *)x, f2);
+ outlet_new((t_object *)x, &s_signal);
+ }
+ return (x);
+}
+
+void lookup_tilde_setup(void)
+{
+ lookup_class = class_new(gensym("lookup~"),
+ (t_newmethod)lookup_new,
+ (t_method)lookup_free,
+ sizeof(t_lookup), 0,
+ A_DEFSYM, A_DEFFLOAT, A_DEFFLOAT, 0);
+ arsic_setup(lookup_class, lookup_dsp, SIC_FLOATTOSIGNAL);
+ class_addmethod(lookup_class, (t_method)lookup_set,
+ gensym("set"), A_SYMBOL, 0);
+}
diff --git a/cyclone/sickle/minmax.c b/cyclone/sickle/minmax.c
new file mode 100644
index 0000000..5bd0e39
--- /dev/null
+++ b/cyclone/sickle/minmax.c
@@ -0,0 +1,78 @@
+/* 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"
+
+typedef struct _minmax
+{
+ t_sic x_sic;
+ t_float x_min;
+ t_float x_max;
+ t_outlet *x_minout;
+ t_outlet *x_maxout;
+} t_minmax;
+
+static t_class *minmax_class;
+
+static void minmax_bang(t_minmax *x)
+{
+ outlet_float(x->x_maxout, x->x_max);
+ outlet_float(x->x_minout, x->x_min);
+}
+
+static void minmax_reset(t_minmax *x)
+{
+ x->x_min = x->x_max = 0; /* CHECKME */
+}
+
+static t_int *minmax_perform(t_int *w)
+{
+ t_minmax *x = (t_minmax *)(w[1]);
+ int nblock = (int)(w[2]);
+ t_float *in = (t_float *)(w[3]);
+ t_float *outmin = (t_float *)(w[4]);
+ t_float *outmax = (t_float *)(w[5]);
+ t_float fmin = x->x_min;
+ t_float fmax = x->x_max;
+ while (nblock--)
+ {
+ t_float f = *in++;
+ if (f < fmin) fmin = f;
+ else if (f > fmax) fmax = f;
+ *outmin++ = fmin;
+ *outmax++ = fmax;
+ }
+ x->x_min = fmin;
+ x->x_max = fmax;
+ return (w + 6);
+}
+
+static void minmax_dsp(t_minmax *x, t_signal **sp)
+{
+ dsp_add(minmax_perform, 5, x, sp[0]->s_n, sp[0]->s_vec,
+ sp[1]->s_vec, sp[2]->s_vec);
+}
+
+static void *minmax_new(void)
+{
+ t_minmax *x = (t_minmax *)pd_new(minmax_class);
+ outlet_new((t_object *)x, &s_signal);
+ outlet_new((t_object *)x, &s_signal);
+ x->x_minout = outlet_new((t_object *)x, &s_float);
+ x->x_maxout = outlet_new((t_object *)x, &s_float);
+ minmax_reset(x);
+ return (x);
+}
+
+void minmax_tilde_setup(void)
+{
+ minmax_class = class_new(gensym("minmax~"),
+ (t_newmethod)minmax_new, 0,
+ sizeof(t_minmax), 0, 0);
+ sic_setup(minmax_class, minmax_dsp, SIC_FLOATTOSIGNAL);
+ class_addbang(minmax_class, minmax_bang);
+ class_addmethod(minmax_class, (t_method)minmax_reset,
+ gensym("reset"), 0);
+}
diff --git a/cyclone/sickle/peakamp.c b/cyclone/sickle/peakamp.c
new file mode 100644
index 0000000..67d1093
--- /dev/null
+++ b/cyclone/sickle/peakamp.c
@@ -0,0 +1,107 @@
+/* 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"
+
+typedef struct _peakamp
+{
+ t_sic x_sic;
+ t_float x_value;
+ int x_nwait;
+ int x_nleft;
+ int x_precount;
+ float x_waittime;
+ float x_ksr;
+ t_clock *x_clock;
+} t_peakamp;
+
+static t_class *peakamp_class;
+
+static void peakamp_tick(t_peakamp *x)
+{
+ outlet_float(((t_object *)x)->ob_outlet, x->x_value);
+ x->x_value = 0;
+ if ((x->x_nleft = x->x_nwait - x->x_precount) < 0) /* CHECKME */
+ x->x_nleft = 0;
+}
+
+static void peakamp_bang(t_peakamp *x)
+{
+ peakamp_tick(x); /* CHECKME */
+}
+
+static void peakamp_ft1(t_peakamp *x, t_floatarg f)
+{
+ if ((x->x_waittime = f) < 0.)
+ x->x_waittime = 0.;
+ if ((x->x_nwait = (int)(x->x_waittime * x->x_ksr)) < 0)
+ x->x_nwait = 0;
+}
+
+static t_int *peakamp_perform(t_int *w)
+{
+ t_peakamp *x = (t_peakamp *)(w[1]);
+ int nblock = (int)(w[2]);
+ t_float *in = (t_float *)(w[3]);
+ t_float value = x->x_value;
+ if (x->x_nwait)
+ {
+ if (x->x_nleft < nblock)
+ {
+ clock_delay(x->x_clock, 0);
+ x->x_precount = nblock - x->x_nleft;
+ x->x_nleft = 0; /* LATER rethink */
+ }
+ else x->x_nleft -= nblock;
+ }
+ while (nblock--)
+ {
+ t_float f = *in++;
+ if (f > value)
+ value = f;
+ else if (f < -value)
+ value = -f;
+ }
+ x->x_value = value;
+ return (w + 4);
+}
+
+static void peakamp_dsp(t_peakamp *x, t_signal **sp)
+{
+ x->x_ksr = sp[0]->s_sr * 0.001;
+ x->x_nwait = (int)(x->x_waittime * x->x_ksr);
+ dsp_add(peakamp_perform, 3, x, sp[0]->s_n, sp[0]->s_vec);
+}
+
+static void peakamp_free(t_peakamp *x)
+{
+ if (x->x_clock) clock_free(x->x_clock);
+}
+
+static void *peakamp_new(t_floatarg f)
+{
+ t_peakamp *x = (t_peakamp *)pd_new(peakamp_class);
+ x->x_value = 0.;
+ x->x_nleft = 0;
+ x->x_ksr = sys_getsr() * 0.001;
+ peakamp_ft1(x, f);
+ inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft1"));
+ outlet_new((t_object *)x, &s_float);
+ x->x_clock = clock_new(x, (t_method)peakamp_tick);
+ return (x);
+}
+
+void peakamp_tilde_setup(void)
+{
+ peakamp_class = class_new(gensym("peakamp~"),
+ (t_newmethod)peakamp_new,
+ (t_method)peakamp_free,
+ sizeof(t_peakamp), 0,
+ A_DEFFLOAT, 0);
+ sic_setup(peakamp_class, peakamp_dsp, SIC_FLOATTOSIGNAL);
+ class_addbang(peakamp_class, peakamp_bang);
+ class_addmethod(peakamp_class, (t_method)peakamp_ft1,
+ gensym("ft1"), A_FLOAT, 0);
+}
diff --git a/cyclone/sickle/peek.c b/cyclone/sickle/peek.c
new file mode 100644
index 0000000..7397577
--- /dev/null
+++ b/cyclone/sickle/peek.c
@@ -0,0 +1,147 @@
+/* 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. */
+
+/* LATER: 'click' method */
+
+#include <string.h>
+#include "m_pd.h"
+#include "sickle/sic.h"
+#include "sickle/arsic.h"
+
+#define PEEK_MAXCHANNELS 4 /* LATER implement arsic resizing feature */
+
+typedef struct _peek
+{
+ t_arsic x_arsic;
+ int x_maxchannels;
+ int x_effchannel; /* effective channel (clipped reqchannel) */
+ int x_reqchannel; /* requested channel */
+ int x_clipmode;
+ int x_pokemode;
+ t_float x_value;
+ t_clock *x_clock;
+ double x_clocklasttick;
+ int x_clockset;
+} t_peek;
+
+static t_class *peek_class;
+
+static void peek_tick(t_peek *x)
+{
+ arsic_redraw((t_arsic *)x); /* LATER redraw only dirty channel(s!) */
+ x->x_clockset = 0;
+ x->x_clocklasttick = clock_getsystime();
+}
+
+static void peek_set(t_peek *x, t_symbol *s)
+{
+ arsic_setarray((t_arsic *)x, s, 1);
+}
+
+#define peek_doclip(f) (f < -1. ? -1. : (f > 1. ? 1. : f))
+
+/* CHECKED refman error: ``if the number received in the left inlet
+ specifies a sample index that does not exist in the buffer~ object's
+ currently allocated memory, nothing happens.'' This is plainly wrong,
+ at least for max/msp 4.0.7 bundle: the index is clipped (just like
+ in tabread/tabwrite). As a kind of an experiment, lets make this
+ the refman's way... */
+static void peek_float(t_peek *x, t_float f)
+{
+ t_arsic *sic = (t_arsic *)x;
+ t_float *vp;
+ arsic_validate(sic, 0); /* LATER rethink (efficiency, and complaining) */
+ if (vp = sic->s_vectors[x->x_effchannel])
+ {
+ int ndx = (int)f;
+ if (vp && ndx >= 0 && ndx < sic->s_vecsize)
+ {
+ if (x->x_pokemode)
+ {
+ double timesince;
+ t_float f = x->x_value;
+ vp[ndx] = (x->x_clipmode ? peek_doclip(f) : f);
+ x->x_pokemode = 0;
+ timesince = clock_gettimesince(x->x_clocklasttick);
+ if (timesince > 1000) peek_tick(x);
+ else if (!x->x_clockset)
+ {
+ clock_delay(x->x_clock, 1000 - timesince);
+ x->x_clockset = 1;
+ }
+ }
+ /* CHECKED: output not clipped */
+ else outlet_float(((t_object *)x)->ob_outlet, vp[ndx]);
+ }
+ }
+}
+
+static void peek_ft1(t_peek *x, t_floatarg f)
+{
+ x->x_value = f;
+ x->x_pokemode = 1;
+ /* CHECKED: poke-mode is reset only after receiving left inlet input
+ -- it is kept across 'ft2', 'clip', and 'set' inputs. */
+}
+
+static void peek_ft2(t_peek *x, t_floatarg f)
+{
+ if ((x->x_reqchannel = (f > 1 ? (int)f - 1 : 0)) > x->x_maxchannels)
+ x->x_effchannel = x->x_maxchannels - 1;
+ else
+ x->x_effchannel = x->x_reqchannel;
+}
+
+static void peek_clip(t_peek *x, t_floatarg f)
+{
+ x->x_clipmode = ((int)f != 0);
+}
+
+static void peek_free(t_peek *x)
+{
+ if (x->x_clock) clock_free(x->x_clock);
+ arsic_free((t_arsic *)x);
+}
+
+static void *peek_new(t_symbol *s, t_floatarg f1, t_floatarg f2)
+{
+ int ch = (f1 > 0 ? (int)f1 : 0);
+ t_peek *x = (t_peek *)arsic_new(peek_class, s,
+ (ch ? PEEK_MAXCHANNELS : 0), 0, 0);
+ if (x)
+ {
+ if (ch > PEEK_MAXCHANNELS)
+ ch = PEEK_MAXCHANNELS;
+ x->x_maxchannels = (ch ? PEEK_MAXCHANNELS : 1);
+ x->x_effchannel = x->x_reqchannel = (ch ? ch - 1 : 0);
+ /* CHECKED (refman error) clipping is disabled by default */
+ x->x_clipmode = ((int)f2 != 0);
+ x->x_pokemode = 0;
+ inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft1"));
+ inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft2"));
+ outlet_new((t_object *)x, &s_float);
+ x->x_clock = clock_new(x, (t_method)peek_tick);
+ x->x_clocklasttick = clock_getsystime();
+ x->x_clockset = 0;
+ }
+ return (x);
+}
+
+void peek_tilde_setup(void)
+{
+ peek_class = class_new(gensym("peek~"),
+ (t_newmethod)peek_new,
+ (t_method)peek_free,
+ sizeof(t_peek), 0,
+ A_DEFSYM, A_DEFFLOAT, A_DEFFLOAT, 0);
+ class_addfloat(peek_class, peek_float);
+ class_addmethod(peek_class, (t_method)peek_set,
+ gensym("set"), A_SYMBOL, 0);
+ class_addmethod(peek_class, (t_method)peek_ft1,
+ gensym("ft1"), A_FLOAT, 0);
+ class_addmethod(peek_class, (t_method)peek_ft2,
+ gensym("ft2"), A_FLOAT, 0);
+ class_addmethod(peek_class, (t_method)peek_clip,
+ gensym("clip"), A_FLOAT, 0);
+}
diff --git a/cyclone/sickle/phasewrap.c b/cyclone/sickle/phasewrap.c
new file mode 100644
index 0000000..535d5e8
--- /dev/null
+++ b/cyclone/sickle/phasewrap.c
@@ -0,0 +1,131 @@
+/* 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 <math.h>
+#include "m_pd.h"
+#include "shared.h"
+#include "sickle/sic.h"
+
+typedef struct _phasewrap
+{
+ t_sic x_sic;
+ int x_algo;
+} t_phasewrap;
+
+static t_class *phasewrap_class;
+
+static t_int *phasewrap_perform(t_int *w)
+{
+ int nblock = (int)(w[1]);
+ t_float *in = (t_float *)(w[2]);
+ t_float *out = (t_float *)(w[3]);
+ t_shared_wrappy wrappy;
+ while (nblock--)
+ {
+ /* FIXME here we have pi -> pi, 3pi -> -pi, -pi -> -pi, -3pi -> pi,
+ while in msp it is pi -> -pi, 3pi -> -pi, -pi -> pi, -3pi -> pi */
+
+ double dnorm = *in++ * (1. / SHARED_2PI);
+ wrappy.w_d = dnorm + SHARED_UNITBIT0;
+ /* Speeding up the int-to-double conversion below would be nice,
+ but all attempts failed. Even this is slower (which works only
+ for nonnegative input):
+
+ wrappy.w_i[SHARED_HIOFFSET] = SHARED_UNITBIT0_HIPART;
+ *out++ = (dnorm - (wrappy.w_d - SHARED_UNITBIT0)) * SHARED_2PI;
+ */
+ dnorm -= wrappy.w_i[SHARED_LOWOFFSET];
+ *out++ = dnorm * SHARED_2PI;
+ }
+ return (w + 4);
+}
+
+/* This is the slowest algo. It is slower than fmod in all cases,
+ except for input being zero. */
+static t_int *phasewrap_perform1(t_int *w)
+{
+ int nblock = (int)(w[1]);
+ t_float *in = (t_float *)(w[2]);
+ t_float *out = (t_float *)(w[3]);
+ while (nblock--)
+ {
+ float f = *in++;
+ double dnorm;
+ if (f < -SHARED_PI)
+ {
+ dnorm = (double)f * (1. / SHARED_2PI) + .5;
+ *out++ = (dnorm - (int)dnorm) * SHARED_2PI + SHARED_PI;
+ }
+ else if (f > SHARED_PI)
+ {
+ dnorm = (double)f * (1. / SHARED_2PI) + .5;
+ *out++ = (dnorm - (int)dnorm) * SHARED_2PI - SHARED_PI;
+ }
+ else *out++ = f;
+ }
+ return (w + 4);
+}
+
+static t_int *phasewrap_perform2(t_int *w)
+{
+ int nblock = (int)(w[1]);
+ t_float *in = (t_float *)(w[2]);
+ t_float *out = (t_float *)(w[3]);
+ while (nblock--)
+ {
+ double dnorm = *in++ + SHARED_PI;
+ if (dnorm < 0)
+ *out++ = SHARED_PI - fmod(-dnorm, SHARED_2PI);
+ else
+ *out++ = fmod(dnorm, SHARED_2PI) - SHARED_PI;
+ }
+ return (w + 4);
+}
+
+static void phasewrap_dsp(t_phasewrap *x, t_signal **sp)
+{
+ switch (x->x_algo)
+ {
+ case 1:
+ dsp_add(phasewrap_perform1, 3, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec);
+ break;
+ case 2:
+ dsp_add(phasewrap_perform2, 3, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec);
+ break;
+ default:
+ dsp_add(phasewrap_perform, 3, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec);
+ }
+}
+
+static void phasewrap__algo(t_phasewrap *x, t_floatarg f)
+{
+ x->x_algo = f;
+}
+
+static void *phasewrap_new(t_symbol *s, int ac, t_atom *av)
+{
+ t_phasewrap *x = (t_phasewrap *)pd_new(phasewrap_class);
+ if (s == gensym("_phasewrap1~"))
+ x->x_algo = 1;
+ else if (s == gensym("_phasewrap2~"))
+ x->x_algo = 2;
+ else
+ x->x_algo = 0;
+ outlet_new((t_object *)x, &s_signal);
+ return (x);
+}
+
+void phasewrap_tilde_setup(void)
+{
+ phasewrap_class = class_new(gensym("phasewrap~"),
+ (t_newmethod)phasewrap_new, 0,
+ sizeof(t_phasewrap), 0, A_GIMME, 0);
+ class_addcreator((t_newmethod)phasewrap_new,
+ gensym("_phasewrap1~"), A_GIMME, 0);
+ class_addcreator((t_newmethod)phasewrap_new,
+ gensym("_phasewrap2~"), A_GIMME, 0);
+ sic_setup(phasewrap_class, phasewrap_dsp, SIC_FLOATTOSIGNAL);
+ class_addmethod(phasewrap_class, (t_method)phasewrap__algo,
+ gensym("_algo"), A_FLOAT, 0);
+}
diff --git a/cyclone/sickle/play.c b/cyclone/sickle/play.c
new file mode 100644
index 0000000..9d2c303
--- /dev/null
+++ b/cyclone/sickle/play.c
@@ -0,0 +1,122 @@
+/* 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 <string.h>
+#include "m_pd.h"
+#include "sickle/sic.h"
+#include "sickle/arsic.h"
+
+/* CHECKME (the refman): if the buffer~ has more channels, channels are mixed */
+
+typedef t_arsic t_play;
+static t_class *play_class;
+
+static void play_set(t_play *x, t_symbol *s)
+{
+ arsic_setarray((t_arsic *)x, s, 1);
+}
+
+/* LATER optimize */
+static t_int *play_perform(t_int *w)
+{
+ t_arsic *sic = (t_arsic *)(w[1]);
+ int nblock = (int)(w[2]);
+ int nch = sic->s_nchannels;
+ t_int *outp = w + 4;
+ if (sic->s_playable)
+ {
+ t_play *x = (t_play *)sic;
+ t_float *xin = (t_float *)(w[3]);
+ int vecsize = sic->s_vecsize;
+ t_float **vectable = sic->s_vectors;
+ float ksr = sic->s_ksr;
+ int nointerp = 0;
+ int maxindex = (nointerp ? vecsize - 1 : vecsize - 3);
+ int iblock;
+
+ for (iblock = 0; iblock < nblock; iblock++)
+ {
+ float phase = *xin++ * ksr;
+ int ndx;
+ int ch = nch;
+ float frac, a, b, c, d, cminusb;
+ if (phase < 0 || phase > maxindex)
+ phase = 0; /* CHECKED: a value 0, not ndx 0 */
+ ndx = (int)phase;
+ /* CHECKME: what kind of interpolation? (CHECKED: multi-point) */
+ if (ndx < 1)
+ ndx = 1, frac = 0;
+ else if (ndx > maxindex)
+ ndx = maxindex, frac = 1;
+ else frac = phase - ndx;
+ while (ch--)
+ {
+ t_float *vp = vectable[ch];
+ t_float *out = (t_float *)(outp[ch]);
+ if (vp)
+ {
+ vp += ndx;
+ a = vp[-1];
+ b = vp[0];
+ c = vp[1];
+ d = vp[2];
+ cminusb = c-b;
+ out[iblock] = b + frac * (
+ cminusb - 0.1666667f * (1. - frac) * (
+ (d - a - 3.0f * cminusb) * frac
+ + (d + 2.0f * a - 3.0f * b)
+ )
+ );
+ }
+ else out[iblock] = 0;
+ }
+ }
+ }
+ else
+ {
+ int ch = nch;
+ while (ch--)
+ {
+ t_float *out = (t_float *)outp[ch];
+ int n = nblock;
+ while (n--) *out++ = 0;
+ }
+ }
+ return (w + sic->s_nperfargs + 1);
+}
+
+static void play_dsp(t_play *x, t_signal **sp)
+{
+ arsic_dsp((t_arsic *)x, sp, play_perform, 1);
+}
+
+static void play_free(t_play *x)
+{
+ arsic_free((t_arsic *)x);
+}
+
+static void *play_new(t_symbol *s, t_floatarg f)
+{
+ /* one auxiliary signal: position input */
+ t_play *x = (t_play *)arsic_new(play_class, s, (int)f, 0, 1);
+ if (x)
+ {
+ int nch = arsic_getnchannels((t_arsic *)x);
+ while (nch--)
+ outlet_new((t_object *)x, &s_signal);
+ }
+ return (x);
+}
+
+void play_tilde_setup(void)
+{
+ play_class = class_new(gensym("play~"),
+ (t_newmethod)play_new,
+ (t_method)play_free,
+ sizeof(t_play), 0,
+ A_DEFSYM, A_DEFFLOAT, 0);
+ arsic_setup(play_class, play_dsp, SIC_FLOATTOSIGNAL);
+ class_addmethod(play_class, (t_method)play_set,
+ gensym("set"), A_SYMBOL, 0);
+}
diff --git a/cyclone/sickle/poltocar.c b/cyclone/sickle/poltocar.c
new file mode 100644
index 0000000..8d7f94c
--- /dev/null
+++ b/cyclone/sickle/poltocar.c
@@ -0,0 +1,79 @@
+/* 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 <math.h>
+#include "m_pd.h"
+#include "unstable/fragile.h"
+#include "sickle/sic.h"
+
+#if defined(NT) || defined(MACOSX)
+/* cf pd/src/x_arithmetic.c */
+#define sinf sin
+#define cosf cos
+#endif
+
+typedef struct _poltocar
+{
+ t_sic x_sic;
+ t_outlet *x_out2;
+} t_poltocar;
+
+static t_class *poltocar_class;
+
+static t_int *poltocar_perform(t_int *w)
+{
+ int nblock = (int)(w[1]);
+ t_float *in1 = (t_float *)(w[2]);
+ t_float *in2 = (t_float *)(w[3]);
+ t_float *out1 = (t_float *)(w[4]);
+ t_float *out2 = (t_float *)(w[5]);
+ while (nblock--)
+ {
+ float am = *in1++, ph = *in2++;
+ *out1++ = am * cosf(ph);
+ *out2++ = -am * sinf(ph); /* CHECKED */
+ }
+ return (w + 6);
+}
+
+static t_int *poltocar_perform_noimag(t_int *w)
+{
+ int nblock = (int)(w[1]);
+ t_float *in1 = (t_float *)(w[2]);
+ t_float *in2 = (t_float *)(w[3]);
+ t_float *out1 = (t_float *)(w[4]);
+ while (nblock--)
+ {
+ float am = *in1++, ph = *in2++;
+ *out1++ = am * cosf(ph);
+ }
+ return (w + 5);
+}
+
+static void poltocar_dsp(t_poltocar *x, t_signal **sp)
+{
+ if (fragile_outlet_connections(x->x_out2))
+ dsp_add(poltocar_perform, 5, sp[0]->s_n, sp[0]->s_vec,
+ sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec);
+ else
+ dsp_add(poltocar_perform_noimag, 4, sp[0]->s_n, sp[0]->s_vec,
+ sp[1]->s_vec, sp[2]->s_vec);
+}
+
+static void *poltocar_new(void)
+{
+ t_poltocar *x = (t_poltocar *)pd_new(poltocar_class);
+ inlet_new((t_object *)x, (t_pd *)x, &s_signal, &s_signal);
+ outlet_new((t_object *)x, &s_signal);
+ x->x_out2 = outlet_new((t_object *)x, &s_signal);
+ return (x);
+}
+
+void poltocar_tilde_setup(void)
+{
+ poltocar_class = class_new(gensym("poltocar~"),
+ (t_newmethod)poltocar_new, 0,
+ sizeof(t_poltocar), 0, 0);
+ sic_setup(poltocar_class, poltocar_dsp, SIC_FLOATTOSIGNAL);
+}
diff --git a/cyclone/sickle/pow.c b/cyclone/sickle/pow.c
new file mode 100644
index 0000000..11cd508
--- /dev/null
+++ b/cyclone/sickle/pow.c
@@ -0,0 +1,54 @@
+/* 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 <math.h>
+#include "m_pd.h"
+#include "sickle/sic.h"
+
+#if defined(NT) || defined(MACOSX)
+/* cf pd/src/x_arithmetic.c */
+#define powf pow
+#endif
+
+typedef t_sic t_pow;
+static t_class *pow_class;
+
+static t_int *pow_perform(t_int *w)
+{
+ int nblock = (int)(w[1]);
+ t_float *in1 = (t_float *)(w[2]);
+ t_float *in2 = (t_float *)(w[3]);
+ t_float *out = (t_float *)(w[4]);
+ while (nblock--)
+ {
+ float f1 = *in1++;
+ float f2 = *in2++;
+ /* CHECKED arg order, no protection against NaNs (negative base),
+ under-, and overflows */
+ *out++ = powf(f2, f1);
+ }
+ return (w + 5);
+}
+
+static void pow_dsp(t_pow *x, t_signal **sp)
+{
+ dsp_add(pow_perform, 4, sp[0]->s_n,
+ sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec);
+}
+
+static void *pow_new(t_floatarg f)
+{
+ t_pow *x = (t_pow *)pd_new(pow_class);
+ sic_newinlet((t_sic *)x, f); /* CHECKED default 0 */
+ outlet_new((t_object *)x, &s_signal);
+ return (x);
+}
+
+void pow_tilde_setup(void)
+{
+ pow_class = class_new(gensym("pow~"),
+ (t_newmethod)pow_new, 0,
+ sizeof(t_pow), 0, A_DEFFLOAT, 0);
+ sic_setup(pow_class, pow_dsp, SIC_FLOATTOSIGNAL);
+}
diff --git a/cyclone/sickle/rampsmooth.c b/cyclone/sickle/rampsmooth.c
new file mode 100644
index 0000000..c2023d8
--- /dev/null
+++ b/cyclone/sickle/rampsmooth.c
@@ -0,0 +1,206 @@
+/* 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 RAMPSMOOTH_GEOMETRIC /* geometric series (same as slide~) CHECKED */
+#ifndef RAMPSMOOTH_GEOMETRIC
+#define RAMPSMOOTH_LINEAR
+#endif
+#define RAMPSMOOTH_DEFNUP 0.
+#define RAMPSMOOTH_DEFNDOWN 0.
+
+typedef struct _rampsmooth
+{
+ t_sic x_sic;
+ int x_nup;
+ int x_ndown;
+ double x_upcoef;
+ double x_downcoef;
+ t_float x_last;
+#ifdef RAMPSMOOTH_LINEAR
+ t_float x_target;
+ double x_incr;
+ int x_nleft;
+#endif
+} t_rampsmooth;
+
+static t_class *rampsmooth_class;
+
+#ifdef RAMPSMOOTH_LINEAR
+/* this is a true linear ramper */
+static t_int *rampsmooth_perform(t_int *w)
+{
+ t_rampsmooth *x = (t_rampsmooth *)(w[1]);
+ int nblock = (int)(w[2]);
+ t_float *in = (t_float *)(w[3]);
+ t_float *out = (t_float *)(w[4]);
+ t_float last = x->x_last;
+ t_float target = x->x_target;
+ double incr = x->x_incr;
+ int nleft = x->x_nleft;
+ while (nblock--)
+ {
+ t_float f = *in++;
+ if (f != target)
+ {
+ target = f;
+ if (f > last)
+ {
+ if (x->x_nup > 1)
+ {
+ incr = (f - last) * x->x_upcoef;
+ nleft = x->x_nup;
+ *out++ = (last += incr);
+ continue;
+ }
+ }
+ else if (f < last)
+ {
+ if (x->x_ndown > 1)
+ {
+ incr = (f - last) * x->x_downcoef;
+ nleft = x->x_ndown;
+ *out++ = (last += incr);
+ continue;
+ }
+ }
+ incr = 0.;
+ nleft = 0;
+ *out++ = last = f;
+ }
+ else if (nleft > 0)
+ {
+ *out++ = (last += incr);
+ if (--nleft == 0)
+ {
+ incr = 0.;
+ last = target;
+ }
+ }
+ else *out++ = target;
+ }
+ x->x_last = last;
+ x->x_target = target;
+ x->x_incr = incr;
+ x->x_nleft = nleft;
+ return (w + 5);
+}
+
+#else
+
+/* this ramper generates a geometric series output for a single step input */
+static t_int *rampsmooth_perform(t_int *w)
+{
+ t_rampsmooth *x = (t_rampsmooth *)(w[1]);
+ int nblock = (int)(w[2]);
+ t_float *in = (t_float *)(w[3]);
+ t_float *out = (t_float *)(w[4]);
+ t_float last = x->x_last;
+ while (nblock--)
+ {
+ t_float f = *in++;
+ if (f > last)
+ {
+ if (x->x_nup > 1)
+ {
+ *out++ = (last += (f - last) * x->x_upcoef);
+ continue;
+ }
+ }
+ else if (f < last)
+ {
+ if (x->x_ndown > 1)
+ {
+ *out++ = (last += (f - last) * x->x_downcoef);
+ continue;
+ }
+ }
+ *out++ = last = f;
+ }
+ x->x_last = last;
+ return (w + 5);
+}
+#endif
+
+static void rampsmooth_dsp(t_rampsmooth *x, t_signal **sp)
+{
+ dsp_add(rampsmooth_perform, 4, x, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec);
+}
+
+static void rampsmooth_rampup(t_rampsmooth *x, t_floatarg f)
+{
+ int i = (int)f;
+ if (i > 1) /* CHECKME if 1 and 0 differ in any way */
+ {
+ x->x_nup = i;
+ x->x_upcoef = 1. / (float)i;
+ }
+ else
+ {
+ x->x_nup = 0;
+ x->x_upcoef = 0.;
+ }
+}
+
+static void rampsmooth_rampdown(t_rampsmooth *x, t_floatarg f)
+{
+ int i = (int)f;
+ if (i > 1) /* CHECKME if 1 and 0 differ in any way */
+ {
+ x->x_ndown = i;
+ x->x_downcoef = 1. / (float)i;
+ }
+ else
+ {
+ x->x_ndown = 0;
+ x->x_downcoef = 0.;
+ }
+}
+
+/* CHECKED */
+static void rampsmooth_ramp(t_rampsmooth *x, t_floatarg f)
+{
+ rampsmooth_rampup(x, f);
+ rampsmooth_rampdown(x, f);
+}
+
+static void *rampsmooth_new(t_symbol *s, int ac, t_atom *av)
+{
+ t_rampsmooth *x = (t_rampsmooth *)pd_new(rampsmooth_class);
+ float f1 = RAMPSMOOTH_DEFNUP;
+ float f2 = RAMPSMOOTH_DEFNDOWN;
+ if (ac && av->a_type == A_FLOAT)
+ {
+ f1 = av->a_w.w_float;
+ ac--; av++;
+ if (ac && av->a_type == A_FLOAT)
+ f2 = av->a_w.w_float;
+ }
+ rampsmooth_rampup(x, f1);
+ rampsmooth_rampdown(x, f2);
+ x->x_last = 0.;
+#ifdef RAMPSMOOTH_LINEAR
+ x->x_target = 0.;
+ x->x_incr = 0.;
+ x->x_nleft = 0;
+#endif
+ outlet_new((t_object *)x, &s_signal);
+ return (x);
+}
+
+void rampsmooth_tilde_setup(void)
+{
+ rampsmooth_class = class_new(gensym("rampsmooth~"),
+ (t_newmethod)rampsmooth_new, 0,
+ sizeof(t_rampsmooth), 0, A_GIMME, 0);
+ sic_setup(rampsmooth_class, rampsmooth_dsp, SIC_FLOATTOSIGNAL);
+ class_addmethod(rampsmooth_class, (t_method)rampsmooth_rampup,
+ gensym("rampup"), A_FLOAT, 0);
+ class_addmethod(rampsmooth_class, (t_method)rampsmooth_rampdown,
+ gensym("rampdown"), A_FLOAT, 0);
+ class_addmethod(rampsmooth_class, (t_method)rampsmooth_ramp,
+ gensym("ramp"), A_FLOAT, 0);
+}
diff --git a/cyclone/sickle/rand.c b/cyclone/sickle/rand.c
new file mode 100644
index 0000000..146cbc9
--- /dev/null
+++ b/cyclone/sickle/rand.c
@@ -0,0 +1,95 @@
+/* Copyright (c) 1997-2003 Miller Puckette, krzYszcz, and others.
+ * For information on usage and redistribution, and for a DISCLAIMER OF ALL
+ * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
+
+/* This is a compilation of phasor~ and noise~ code from d_osc.c. */
+
+#include "m_pd.h"
+#include "shared.h"
+#include "sickle/sic.h"
+
+typedef struct _rand
+{
+ t_sic x_sic;
+ t_float x_rate;
+ double x_lastphase;
+ double x_nextphase;
+ float x_rcpsr;
+ int x_state;
+ float x_target;
+ float x_scaling; /* LATER use phase increment */
+} t_rand;
+
+static t_class *rand_class;
+
+static t_int *rand_perform(t_int *w)
+{
+ t_rand *x = (t_rand *)(w[1]);
+ int nblock = (int)(w[2]);
+ t_float *rin = (t_float *)(w[3]);
+ t_float *out = (t_float *)(w[4]);
+ double lastph = x->x_lastphase;
+ double ph = x->x_nextphase;
+ double tfph = ph + SHARED_UNITBIT32;
+ t_shared_wrappy wrappy;
+ int32 normhipart;
+ float rcpsr = x->x_rcpsr;
+ float target = x->x_target;
+ float scaling = x->x_scaling;
+
+ wrappy.w_d = SHARED_UNITBIT32;
+ normhipart = wrappy.w_i[SHARED_HIOFFSET];
+
+ while (nblock--)
+ {
+ float rate = *rin++;
+ if (ph > lastph)
+ {
+ int state = x->x_state;
+ float newtarget = ((float)((state & 0x7fffffff) - 0x40000000))
+ * (float)(1.0 / 0x40000000);
+ x->x_state = state * 435898247 + 382842987;
+ x->x_scaling = scaling = target - newtarget;
+ x->x_target = target = newtarget;
+ }
+ *out++ = ph * scaling + target;
+ lastph = ph;
+ if (rate > 0) rate = -rate;
+ tfph += rate * rcpsr;
+ wrappy.w_d = tfph;
+ wrappy.w_i[SHARED_HIOFFSET] = normhipart;
+ ph = wrappy.w_d - SHARED_UNITBIT32;
+ }
+ x->x_lastphase = lastph;
+ x->x_nextphase = ph;
+ return (w + 5);
+}
+
+static void rand_dsp(t_rand *x, t_signal **sp)
+{
+ x->x_rcpsr = 1. / sp[0]->s_sr;
+ dsp_add(rand_perform, 4, x, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec);
+}
+
+static void *rand_new(t_floatarg inirate)
+{
+ t_rand *x = (t_rand *)pd_new(rand_class);
+ /* borrowed from d_osc.c, LATER rethink */
+ static int init = 307;
+ x->x_state = (init *= 1319);
+ x->x_lastphase = 0.;
+ x->x_nextphase = 1.; /* start from 0, force retargetting */
+ x->x_target = x->x_scaling = 0;
+ x->x_rate = (inirate > 0 ? -inirate : 0);
+ outlet_new((t_object *)x, &s_signal);
+ return (x);
+}
+
+void rand_tilde_setup(void)
+{
+ rand_class = class_new(gensym("rand~"),
+ (t_newmethod)rand_new, 0,
+ sizeof(t_rand), 0,
+ A_DEFFLOAT, 0);
+ sic_setup(rand_class, rand_dsp, SIC_FLOATTOSIGNAL);
+}
diff --git a/cyclone/sickle/record.c b/cyclone/sickle/record.c
new file mode 100644
index 0000000..ba2e3b5
--- /dev/null
+++ b/cyclone/sickle/record.c
@@ -0,0 +1,242 @@
+/* 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 <string.h>
+#include "m_pd.h"
+#include "shared.h"
+#include "sickle/sic.h"
+#include "sickle/arsic.h"
+
+typedef struct _record
+{
+ t_arsic x_arsic;
+ float x_startpoint; /* the inputs */
+ float x_endpoint;
+ int x_appendmode;
+ int x_loopmode;
+ int x_startindex;
+ int x_endindex; /* (one past last record position) */
+ int x_pauseindex;
+ int x_phase; /* writing head */
+ float x_sync;
+ float x_syncincr;
+ int x_isrunning; /* to know if sync should be 0.0 or 1.0 */
+ t_clock *x_clock;
+} t_record;
+
+static t_class *record_class;
+
+static void record_tick(t_record *x)
+{
+ arsic_redraw((t_arsic *)x);
+}
+
+static void record_setsync(t_record *x)
+{
+ /* CHECKED: clipped to array size -- using indices, not points */
+ float range = (float)(x->x_endindex - x->x_startindex);
+ int phase = x->x_phase;
+ if (phase == SHARED_INT_MAX || range < 1.0)
+ {
+ x->x_sync = (x->x_isrunning ? 1.0 : 0); /* CHECKED */
+ x->x_syncincr = 0;
+ }
+ else
+ {
+ x->x_sync = (float)(phase - x->x_startindex) / range;
+ x->x_syncincr = 1.0 / range;
+ }
+}
+
+static void record_mstoindex(t_record *x)
+{
+ t_arsic *sic = (t_arsic *)x;
+ x->x_startindex = (int)(x->x_startpoint * sic->s_ksr);
+ if (x->x_startindex < 0)
+ x->x_startindex = 0; /* CHECKED */
+ x->x_endindex = (int)(x->x_endpoint * sic->s_ksr);
+ if (x->x_endindex > sic->s_vecsize
+ || x->x_endindex <= 0)
+ x->x_endindex = sic->s_vecsize; /* CHECKED (both ways) */
+ record_setsync(x);
+}
+
+static void record_set(t_record *x, t_symbol *s)
+{
+ arsic_setarray((t_arsic *)x, s, 1);
+ record_mstoindex(x);
+}
+
+static void record_startpoint(t_record *x, t_floatarg f)
+{
+ x->x_startpoint = f;
+ record_mstoindex(x);
+}
+
+static void record_endpoint(t_record *x, t_floatarg f)
+{
+ x->x_endpoint = f;
+ record_mstoindex(x);
+}
+
+static void record_float(t_record *x, t_float f)
+{
+ if (x->x_isrunning = (f != 0))
+ {
+ /* CHECKED: no (re)start in append mode */
+ /* LATER consider restart if x->x_pauseindex == SHARED_INT_MAX */
+ x->x_phase = x->x_appendmode ? x->x_pauseindex : x->x_startindex;
+ if (x->x_phase >= x->x_endindex) x->x_phase = SHARED_INT_MAX;
+ }
+ else if (x->x_phase != SHARED_INT_MAX) /* CHECKED: no rewind */
+ {
+ record_tick(x);
+ x->x_pauseindex = x->x_phase;
+ x->x_phase = SHARED_INT_MAX;
+ }
+ record_setsync(x);
+}
+
+static void record_append(t_record *x, t_floatarg f)
+{
+ if (f != 0)
+ {
+ x->x_appendmode = 1; /* CHECKED: always allow appending */
+ }
+ else x->x_appendmode = 0;
+}
+
+static void record_loop(t_record *x, t_floatarg f)
+{
+ x->x_loopmode = (f != 0);
+}
+
+static t_int *record_perform(t_int *w)
+{
+ t_arsic *sic = (t_arsic *)(w[1]);
+ int nblock = (int)(w[2]);
+ int nch = sic->s_nchannels;
+ t_float *out = (t_float *)(w[3 + nch]);
+ t_record *x = (t_record *)sic;
+ int phase = x->x_phase;
+ int endphase = x->x_endindex;
+ float sync = x->x_sync;
+ if (sic->s_playable && endphase > phase)
+ {
+ int vecsize = sic->s_vecsize;
+ float syncincr = x->x_syncincr;
+ int ch, over, i, nxfer;
+loopover:
+ if ((nxfer = endphase - phase) > nblock)
+ {
+ nxfer = nblock;
+ over = 0;
+ }
+ else over = 1;
+ ch = nch;
+ while (ch--)
+ {
+ t_float *vp = sic->s_vectors[ch];
+ if (vp)
+ {
+ t_float *ip = (t_float *)(w[3 + ch]);
+ vp += phase;
+ i = nxfer;
+ /* LATER consider handling under and overflows */
+ while (i--) *vp++ = *ip++;
+ }
+ }
+ i = nxfer;
+ while (i--)
+ {
+ *out++ = sync;
+ sync += syncincr;
+ }
+ if (over)
+ {
+ nblock -= nxfer;
+ if (x->x_loopmode
+ && (phase = x->x_startindex) < endphase)
+ {
+ x->x_phase = phase;
+ x->x_sync = sync = 0;
+ if (nblock > 0) goto loopover;
+ goto done;
+ }
+ clock_delay(x->x_clock, 0);
+ /* CHECKED: no restart in append mode */
+ x->x_pauseindex = SHARED_INT_MAX;
+ x->x_phase = SHARED_INT_MAX;
+ x->x_sync = 1.0;
+ x->x_syncincr = 0;
+ }
+ else
+ {
+ x->x_phase += nxfer;
+ x->x_sync = sync;
+ goto done;
+ }
+ }
+ while (nblock--) *out++ = sync;
+done:
+ return (w + sic->s_nperfargs + 1);
+}
+
+static void record_dsp(t_record *x, t_signal **sp)
+{
+ arsic_dsp((t_arsic *)x, sp, record_perform, 1);
+ record_mstoindex(x);
+}
+
+static void record_free(t_record *x)
+{
+ arsic_free((t_arsic *)x);
+ if (x->x_clock) clock_free(x->x_clock);
+}
+
+static void *record_new(t_symbol *s, t_floatarg f)
+{
+ /* one auxiliary signal: sync output */
+ t_record *x = (t_record *)arsic_new(record_class, s, (int)f, 0, 1);
+ if (x)
+ {
+ int nch = arsic_getnchannels((t_arsic *)x);
+ arsic_setminsize((t_arsic *)x, 2);
+ x->x_startpoint = 0;
+ x->x_endpoint = 0;
+ x->x_appendmode = 0;
+ x->x_loopmode = 0;
+ x->x_pauseindex = SHARED_INT_MAX;
+ x->x_phase = SHARED_INT_MAX;
+ x->x_isrunning = 0;
+ record_mstoindex(x);
+ x->x_clock = clock_new(x, (t_method)record_tick);
+ while (--nch)
+ inlet_new((t_object *)x, (t_pd *)x, &s_signal, &s_signal);
+ inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft-2"));
+ inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft-1"));
+ outlet_new((t_object *)x, &s_signal);
+ }
+ return (x);
+}
+
+void record_tilde_setup(void)
+{
+ record_class = class_new(gensym("record~"),
+ (t_newmethod)record_new,
+ (t_method)record_free,
+ sizeof(t_record), 0,
+ A_DEFSYM, A_DEFFLOAT, 0);
+ arsic_setup(record_class, record_dsp, record_float);
+ class_addmethod(record_class, (t_method)record_startpoint,
+ gensym("ft-2"), A_FLOAT, 0);
+ class_addmethod(record_class, (t_method)record_endpoint,
+ gensym("ft-1"), A_FLOAT, 0);
+ class_addmethod(record_class, (t_method)record_append,
+ gensym("append"), A_FLOAT, 0);
+ class_addmethod(record_class, (t_method)record_loop,
+ gensym("loop"), A_FLOAT, 0);
+ class_addmethod(record_class, (t_method)record_set,
+ gensym("set"), A_SYMBOL, 0);
+}
diff --git a/cyclone/sickle/sah.c b/cyclone/sickle/sah.c
new file mode 100644
index 0000000..afac1e0
--- /dev/null
+++ b/cyclone/sickle/sah.c
@@ -0,0 +1,70 @@
+/* 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"
+
+typedef struct _sah
+{
+ t_sic x_sic;
+ t_float x_threshold;
+ t_float x_lastin;
+ t_float x_lastout;
+} t_sah;
+
+static t_class *sah_class;
+
+static t_int *sah_perform(t_int *w)
+{
+ t_sah *x = (t_sah *)(w[1]);
+ int nblock = (t_int)(w[2]);
+ t_float *in1 = (t_float *)(w[3]);
+ t_float *in2 = (t_float *)(w[4]);
+ t_float *out = (t_float *)(w[5]);
+ t_float threshold = x->x_threshold;
+ t_float lastin = x->x_lastin;
+ t_float lastout = x->x_lastout;
+ while (nblock--)
+ {
+ float f = *in2++;
+ if (lastin <= threshold && f > threshold) /* CHECKME <=, > */
+ lastout = *in1;
+ in1++;
+ lastin = f;
+ *out++ = lastout;
+ }
+ x->x_lastin = lastin;
+ x->x_lastout = lastout;
+ return (w + 6);
+}
+
+static void sah_dsp(t_sah *x, t_signal **sp)
+{
+ dsp_add(sah_perform, 5, x, sp[0]->s_n,
+ sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec);
+}
+
+static void sah_float(t_sah *x, t_float f)
+{
+ x->x_threshold = f;
+}
+
+static void *sah_new(t_floatarg f)
+{
+ t_sah *x = (t_sah *)pd_new(sah_class);
+ x->x_threshold = f;
+ x->x_lastin = 0;
+ x->x_lastout = 0;
+ inlet_new((t_object *)x, (t_pd *)x, &s_signal, &s_signal);
+ outlet_new((t_object *)x, &s_signal);
+ return (x);
+}
+
+void sah_tilde_setup(void)
+{
+ sah_class = class_new(gensym("sah~"),
+ (t_newmethod)sah_new, 0,
+ sizeof(t_sah), 0, A_DEFFLOAT, 0);
+ sic_setup(sah_class, sah_dsp, sah_float);
+}
diff --git a/cyclone/sickle/sickle.c b/cyclone/sickle/sickle.c
new file mode 100644
index 0000000..765209a
--- /dev/null
+++ b/cyclone/sickle/sickle.c
@@ -0,0 +1,93 @@
+/* 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 <stdio.h>
+#include "m_pd.h"
+#include "unstable/fragile.h"
+#include "common/loud.h"
+#include "common/port.h"
+#include "hammer/file.h"
+#include "../build_counter"
+void allsickles_setup(void);
+
+typedef struct _sickle
+{
+ t_object x_ob;
+ t_symbol *x_dir;
+ t_hammerfile *x_filehandle;
+} t_sickle;
+
+static t_class *sickle_class;
+static int sickle_firstndx;
+static int sickle_lastndx;
+
+static void sickle_readhook(t_pd *z, t_symbol *fn, int ac, t_atom *av)
+{
+ import_max(fn->s_name, "");
+}
+
+static void sickle_import(t_sickle *x, t_symbol *fn, t_symbol *dir)
+{
+ if (fn && fn != &s_)
+ {
+ if (!dir || dir == &s_) dir = x->x_dir;
+ import_max(fn->s_name, (dir && dir != &s_) ? dir->s_name : "");
+ }
+ else
+ hammerpanel_open(x->x_filehandle);
+}
+
+static void sickle_click(t_sickle *x, t_floatarg xpos, t_floatarg ypos,
+ t_floatarg shift, t_floatarg ctrl, t_floatarg alt)
+{
+ sickle_import(x, 0, 0);
+}
+
+static void sickle_bang(t_sickle *x)
+{
+ fragile_class_printnames("sickle classes are: ",
+ sickle_firstndx, sickle_lastndx);
+}
+
+static void sickle_free(t_sickle *x)
+{
+ hammerfile_free(x->x_filehandle);
+}
+
+static void *sickle_new(t_symbol *s)
+{
+ t_sickle *x = (t_sickle *)pd_new(sickle_class);
+ x->x_filehandle = hammerfile_new((t_pd *)x, 0, sickle_readhook, 0, 0);
+ x->x_dir = (s && s != &s_ ? s : canvas_getdir(x->x_filehandle->f_canvas));
+ return (x);
+}
+
+void sickle_setup(void)
+{
+ if (canvas_getcurrent())
+ {
+ /* Loading the library by object creation is banned, because of a danger
+ of having some of the classes already loaded. LATER rethink. */
+ loud_error(0, "apparently an attempt to create a 'sickle' object");
+ loud_errand(0, "without having sickle library preloaded");
+ return;
+ }
+ if (!zgetfn(&pd_objectmaker, gensym("cyclone")))
+ post("this is sickle %s, %s %s build",
+ CYCLONE_VERSION, loud_ordinal(CYCLONE_BUILD), CYCLONE_RELEASE);
+ sickle_class = class_new(gensym("sickle"),
+ (t_newmethod)sickle_new,
+ (t_method)sickle_free,
+ sizeof(t_sickle), 0, A_DEFSYM, 0);
+ class_addbang(sickle_class, sickle_bang);
+ class_addmethod(sickle_class, (t_method)sickle_import,
+ gensym("import"), A_DEFSYM, A_DEFSYM, 0);
+ class_addmethod(sickle_class, (t_method)sickle_click,
+ gensym("click"),
+ A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0);
+ hammerfile_setup(sickle_class, 0);
+ sickle_firstndx = fragile_class_count();
+ allsickles_setup();
+ sickle_lastndx = fragile_class_count() - 1;
+}
diff --git a/cyclone/sickle/sinh.c b/cyclone/sickle/sinh.c
new file mode 100644
index 0000000..523c28a
--- /dev/null
+++ b/cyclone/sickle/sinh.c
@@ -0,0 +1,48 @@
+/* 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 <math.h>
+#include "m_pd.h"
+#include "sickle/sic.h"
+
+#if defined(NT) || defined(MACOSX)
+/* cf pd/src/x_arithmetic.c */
+#define sinhf sinh
+#endif
+
+typedef t_sic t_sinh;
+static t_class *sinh_class;
+
+static t_int *sinh_perform(t_int *w)
+{
+ int nblock = (int)(w[1]);
+ t_float *in = (t_float *)(w[2]);
+ t_float *out = (t_float *)(w[3]);
+ while (nblock--)
+ {
+ float f = *in++;
+ *out++ = sinhf(f); /* CHECKME no protection against overflow */
+ }
+ return (w + 4);
+}
+
+static void sinh_dsp(t_sinh *x, t_signal **sp)
+{
+ dsp_add(sinh_perform, 3, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec);
+}
+
+static void *sinh_new(void)
+{
+ t_sinh *x = (t_sinh *)pd_new(sinh_class);
+ outlet_new((t_object *)x, &s_signal);
+ return (x);
+}
+
+void sinh_tilde_setup(void)
+{
+ sinh_class = class_new(gensym("sinh~"),
+ (t_newmethod)sinh_new, 0,
+ sizeof(t_sinh), 0, 0);
+ sic_setup(sinh_class, sinh_dsp, SIC_FLOATTOSIGNAL);
+}
diff --git a/cyclone/sickle/sinx.c b/cyclone/sickle/sinx.c
new file mode 100644
index 0000000..b303024
--- /dev/null
+++ b/cyclone/sickle/sinx.c
@@ -0,0 +1,51 @@
+/* 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 <math.h>
+#include "m_pd.h"
+#include "sickle/sic.h"
+
+/* by definition, this is just an interface to the -lm call
+ (do not use costable) */
+
+#if defined(NT) || defined(MACOSX)
+/* cf pd/src/x_arithmetic.c */
+#define sinf sin
+#endif
+
+typedef t_sic t_sinx;
+static t_class *sinx_class;
+
+static t_int *sinx_perform(t_int *w)
+{
+ int nblock = (int)(w[1]);
+ t_float *in = (t_float *)(w[2]);
+ t_float *out = (t_float *)(w[3]);
+ while (nblock--)
+ {
+ float f = *in++;
+ *out++ = sinf(f);
+ }
+ return (w + 4);
+}
+
+static void sinx_dsp(t_sinx *x, t_signal **sp)
+{
+ dsp_add(sinx_perform, 3, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec);
+}
+
+static void *sinx_new(void)
+{
+ t_sinx *x = (t_sinx *)pd_new(sinx_class);
+ outlet_new((t_object *)x, &s_signal);
+ return (x);
+}
+
+void sinx_tilde_setup(void)
+{
+ sinx_class = class_new(gensym("sinx~"),
+ (t_newmethod)sinx_new, 0,
+ sizeof(t_sinx), 0, 0);
+ sic_setup(sinx_class, sinx_dsp, SIC_FLOATTOSIGNAL);
+}
diff --git a/cyclone/sickle/slide.c b/cyclone/sickle/slide.c
new file mode 100644
index 0000000..92001b2
--- /dev/null
+++ b/cyclone/sickle/slide.c
@@ -0,0 +1,77 @@
+/* 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 SLIDE_DEFUP 1.
+#define SLIDE_DEFDN 1.
+
+typedef struct _slide
+{
+ t_sic x_sic;
+ t_float x_last;
+} t_slide;
+
+static t_class *slide_class;
+
+static t_int *slide_perform(t_int *w)
+{
+ t_slide *x = (t_slide *)(w[1]);
+ int nblock = (int)(w[2]);
+ t_float *in1 = (t_float *)(w[3]);
+ t_float *in2 = (t_float *)(w[4]);
+ t_float *in3 = (t_float *)(w[5]);
+ t_float *out = (t_float *)(w[6]);
+ t_float last = x->x_last;
+ while (nblock--)
+ {
+ float f = *in1++;
+ if (f > last)
+ {
+ float up = *in2++;
+ if (up > 1.) /* CHECKED */
+ last += (f - last) / up;
+ else
+ last = f;
+ in3++;
+ }
+ else if (f < last)
+ {
+ float dn = *in3++;
+ if (dn > 1.) /* CHECKED */
+ last += (f - last) / dn;
+ else
+ last = f;
+ in2++;
+ }
+ *out++ = last;
+ }
+ x->x_last = last;
+ return (w + 7);
+}
+
+static void slide_dsp(t_slide *x, t_signal **sp)
+{
+ dsp_add(slide_perform, 6, x, sp[0]->s_n,
+ sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec);
+}
+
+static void *slide_new(t_symbol *s, int ac, t_atom *av)
+{
+ t_slide *x = (t_slide *)pd_new(slide_class);
+ sic_inlet((t_sic *)x, 1, SLIDE_DEFUP, 0, ac, av);
+ sic_inlet((t_sic *)x, 2, SLIDE_DEFDN, 1, ac, av);
+ outlet_new((t_object *)x, &s_signal);
+ x->x_last = 0;
+ return (x);
+}
+
+void slide_tilde_setup(void)
+{
+ slide_class = class_new(gensym("slide~"),
+ (t_newmethod)slide_new, 0,
+ sizeof(t_slide), 0, A_GIMME, 0);
+ sic_setup(slide_class, slide_dsp, SIC_FLOATTOSIGNAL);
+}
diff --git a/cyclone/sickle/spike.c b/cyclone/sickle/spike.c
new file mode 100644
index 0000000..13f9361
--- /dev/null
+++ b/cyclone/sickle/spike.c
@@ -0,0 +1,109 @@
+/* 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"
+
+typedef struct _spike
+{
+ t_sic x_sic;
+ t_float x_last;
+ int x_count;
+ int x_precount;
+ int x_nwait;
+ float x_waittime;
+ float x_ksr;
+ float x_rcpksr;
+ t_clock *x_clock;
+} t_spike;
+
+static t_class *spike_class;
+
+static void spike_tick(t_spike *x)
+{
+ outlet_float(((t_object *)x)->ob_outlet, x->x_count * x->x_rcpksr);
+ x->x_count = x->x_precount;
+}
+
+static void spike_ft1(t_spike *x, t_floatarg f)
+{
+ if ((x->x_waittime = f) < 0.)
+ x->x_waittime = 0.;
+ x->x_nwait = (int)(x->x_waittime * x->x_ksr);
+}
+
+static t_int *spike_perform(t_int *w)
+{
+ t_spike *x = (t_spike *)(w[1]);
+ int nblock = (int)(w[2]);
+ t_float *in = (t_float *)(w[3]);
+ t_float last = x->x_last;
+ int count = x->x_count;
+ int nwait = x->x_nwait;
+ if (count + nblock > nwait)
+ {
+ /* LATER efficiency tricks */
+ while (nblock--)
+ {
+ float f = *in++;
+ if (last == 0. && f != 0. /* CHECKED zero-to-nonzero */
+ && count /* CHECKED no firing at startup */
+ && count >= nwait)
+ {
+ clock_delay(x->x_clock, 0);
+ x->x_last = in[nblock - 1];
+ x->x_count = count;
+ x->x_precount = nblock;
+ return (w + 4);
+ }
+ count++;
+ last = f;
+ }
+ x->x_last = last;
+ x->x_count = count;
+ }
+ else
+ {
+ x->x_last = in[nblock - 1];
+ x->x_count += nblock;
+ }
+ return (w + 4);
+}
+
+static void spike_dsp(t_spike *x, t_signal **sp)
+{
+ x->x_ksr = sp[0]->s_sr * 0.001;
+ x->x_rcpksr = 1000.0 / sp[0]->s_sr;
+ x->x_nwait = (int)(x->x_waittime * x->x_ksr);
+ dsp_add(spike_perform, 3, x, sp[0]->s_n, sp[0]->s_vec);
+}
+
+static void spike_free(t_spike *x)
+{
+ if (x->x_clock) clock_free(x->x_clock);
+}
+
+static void *spike_new(t_floatarg f)
+{
+ t_spike *x = (t_spike *)pd_new(spike_class);
+ x->x_last = 0.;
+ x->x_ksr = sys_getsr() * 0.001;
+ spike_ft1(x, f);
+ inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft1"));
+ outlet_new((t_object *)x, &s_float);
+ x->x_clock = clock_new(x, (t_method)spike_tick);
+ return (x);
+}
+
+void spike_tilde_setup(void)
+{
+ spike_class = class_new(gensym("spike~"),
+ (t_newmethod)spike_new,
+ (t_method)spike_free,
+ sizeof(t_spike), 0,
+ A_DEFFLOAT, 0);
+ sic_setup(spike_class, spike_dsp, SIC_FLOATTOSIGNAL);
+ class_addmethod(spike_class, (t_method)spike_ft1,
+ gensym("ft1"), A_FLOAT, 0);
+}
diff --git a/cyclone/sickle/tanh.c b/cyclone/sickle/tanh.c
new file mode 100644
index 0000000..7473dcf
--- /dev/null
+++ b/cyclone/sickle/tanh.c
@@ -0,0 +1,48 @@
+/* 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 <math.h>
+#include "m_pd.h"
+#include "sickle/sic.h"
+
+#if defined(NT) || defined(MACOSX)
+/* cf pd/src/x_arithmetic.c */
+#define tanhf tanh
+#endif
+
+typedef t_sic t_tanh;
+static t_class *tanh_class;
+
+static t_int *tanh_perform(t_int *w)
+{
+ int nblock = (int)(w[1]);
+ t_float *in = (t_float *)(w[2]);
+ t_float *out = (t_float *)(w[3]);
+ while (nblock--)
+ {
+ float f = *in++;
+ *out++ = tanhf(f); /* CHECKME no protection against overflow */
+ }
+ return (w + 4);
+}
+
+static void tanh_dsp(t_tanh *x, t_signal **sp)
+{
+ dsp_add(tanh_perform, 3, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec);
+}
+
+static void *tanh_new(void)
+{
+ t_tanh *x = (t_tanh *)pd_new(tanh_class);
+ outlet_new((t_object *)x, &s_signal);
+ return (x);
+}
+
+void tanh_tilde_setup(void)
+{
+ tanh_class = class_new(gensym("tanh~"),
+ (t_newmethod)tanh_new, 0,
+ sizeof(t_tanh), 0, 0);
+ sic_setup(tanh_class, tanh_dsp, SIC_FLOATTOSIGNAL);
+}
diff --git a/cyclone/sickle/tanx.c b/cyclone/sickle/tanx.c
new file mode 100644
index 0000000..d2a1102
--- /dev/null
+++ b/cyclone/sickle/tanx.c
@@ -0,0 +1,51 @@
+/* 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 <math.h>
+#include "m_pd.h"
+#include "sickle/sic.h"
+
+/* by definition, this is just an interface to the -lm call
+ (do not use costable) */
+
+#if defined(NT) || defined(MACOSX)
+/* cf pd/src/x_arithmetic.c */
+#define tanf tan
+#endif
+
+typedef t_sic t_tanx;
+static t_class *tanx_class;
+
+static t_int *tanx_perform(t_int *w)
+{
+ int nblock = (int)(w[1]);
+ t_float *in = (t_float *)(w[2]);
+ t_float *out = (t_float *)(w[3]);
+ while (nblock--)
+ {
+ float f = *in++;
+ *out++ = tanf(f);
+ }
+ return (w + 4);
+}
+
+static void tanx_dsp(t_tanx *x, t_signal **sp)
+{
+ dsp_add(tanx_perform, 3, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec);
+}
+
+static void *tanx_new(void)
+{
+ t_tanx *x = (t_tanx *)pd_new(tanx_class);
+ outlet_new((t_object *)x, &s_signal);
+ return (x);
+}
+
+void tanx_tilde_setup(void)
+{
+ tanx_class = class_new(gensym("tanx~"),
+ (t_newmethod)tanx_new, 0,
+ sizeof(t_tanx), 0, 0);
+ sic_setup(tanx_class, tanx_dsp, SIC_FLOATTOSIGNAL);
+}
diff --git a/cyclone/sickle/train.c b/cyclone/sickle/train.c
new file mode 100644
index 0000000..b07ba9a
--- /dev/null
+++ b/cyclone/sickle/train.c
@@ -0,0 +1,117 @@
+/* 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 "shared.h"
+#include "sickle/sic.h"
+
+#define TRAIN_DEFPERIOD 1000
+#define TRAIN_DEFWIDTH 0.5
+#define TRAIN_DEFOFFSET 0
+
+typedef struct _train
+{
+ t_sic x_sic;
+ int x_on;
+ double x_phase;
+ float x_rcpksr;
+ t_outlet *x_bangout;
+ t_clock *x_clock;
+} t_train;
+
+static t_class *train_class;
+
+static void train_tick(t_train *x)
+{
+ outlet_bang(x->x_bangout);
+}
+
+static t_int *train_perform(t_int *w)
+{
+ t_train *x = (t_train *)(w[1]);
+ int nblock = (int)(w[2]);
+ t_float *in1 = (t_float *)(w[3]);
+ t_float *in2 = (t_float *)(w[4]);
+ t_float *in3 = (t_float *)(w[5]);
+ t_float *out = (t_float *)(w[6]);
+ float rcpksr = x->x_rcpksr;
+ double ph = x->x_phase;
+ double tfph = ph + SHARED_UNITBIT32;
+ t_shared_wrappy wrappy;
+ int32 normhipart;
+ int on = x->x_on;
+ int edge = 0;
+
+ wrappy.w_d = SHARED_UNITBIT32;
+ normhipart = wrappy.w_i[SHARED_HIOFFSET];
+
+ while (nblock--)
+ {
+ double onph, offph;
+ float period = *in1++;
+
+ wrappy.w_d = *in3++ + SHARED_UNITBIT32;
+ wrappy.w_i[SHARED_HIOFFSET] = normhipart;
+ onph = wrappy.w_d - SHARED_UNITBIT32;
+
+ wrappy.w_d = onph + *in2++ + SHARED_UNITBIT32;
+ wrappy.w_i[SHARED_HIOFFSET] = normhipart;
+ offph = wrappy.w_d - SHARED_UNITBIT32;
+
+ if (offph > onph ? ph < offph && ph >= onph : ph < offph || ph >= onph)
+ {
+ if (!on) on = edge = 1;
+ *out++ = 1.;
+ }
+ else
+ {
+ on = 0;
+ *out++ = 0.;
+ }
+ if (period > rcpksr) /* LATER rethink */
+ tfph += rcpksr / period; /* LATER revisit (profiling?) */
+ wrappy.w_d = tfph;
+ wrappy.w_i[SHARED_HIOFFSET] = normhipart;
+ ph = wrappy.w_d - SHARED_UNITBIT32;
+ }
+ x->x_phase = ph;
+ x->x_on = on;
+ if (edge) clock_delay(x->x_clock, 0);
+ return (w + 7);
+}
+
+static void train_dsp(t_train *x, t_signal **sp)
+{
+ x->x_rcpksr = 1000. / sp[0]->s_sr;
+ dsp_add(train_perform, 6, x, sp[0]->s_n,
+ sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec);
+}
+
+static void train_free(t_train *x)
+{
+ if (x->x_clock) clock_free(x->x_clock);
+}
+
+static void *train_new(t_symbol *s, int ac, t_atom *av)
+{
+ t_train *x = (t_train *)pd_new(train_class);
+ x->x_on = 0;
+ x->x_phase = 0;
+ sic_inlet((t_sic *)x, 0, TRAIN_DEFPERIOD, 0, ac, av);
+ sic_inlet((t_sic *)x, 1, TRAIN_DEFWIDTH, 1, ac, av);
+ sic_inlet((t_sic *)x, 2, TRAIN_DEFOFFSET, 2, ac, av);
+ outlet_new((t_object *)x, &s_signal);
+ x->x_bangout = outlet_new((t_object *)x, &s_bang);
+ x->x_clock = clock_new(x, (t_method)train_tick);
+ return (x);
+}
+
+void train_tilde_setup(void)
+{
+ train_class = class_new(gensym("train~"),
+ (t_newmethod)train_new,
+ (t_method)train_free,
+ sizeof(t_train), 0, A_GIMME, 0);
+ sic_setup(train_class, train_dsp, SIC_FLOATTOSIGNAL);
+}
diff --git a/cyclone/sickle/trapezoid.c b/cyclone/sickle/trapezoid.c
new file mode 100644
index 0000000..b33cb02
--- /dev/null
+++ b/cyclone/sickle/trapezoid.c
@@ -0,0 +1,105 @@
+/* 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 TRAPEZOID_DEFUP 0.1 /* a bug? */
+#define TRAPEZOID_DEFDN 0.9 /* a bug? */
+#define TRAPEZOID_DEFLO 0.0
+#define TRAPEZOID_DEFHI 1.0
+
+typedef struct _trapezoid
+{
+ t_sic x_sic;
+ float x_low;
+ float x_range;
+} t_trapezoid;
+
+static t_class *trapezoid_class;
+
+static void trapezoid_lo(t_trapezoid *x, t_floatarg f)
+{
+ float high = x->x_low + x->x_range;
+ x->x_low = f;
+ x->x_range = high - x->x_low;
+}
+
+static void trapezoid_hi(t_trapezoid *x, t_floatarg f)
+{
+ x->x_range = f - x->x_low;
+}
+
+/* LATER optimize */
+static t_int *trapezoid_perform(t_int *w)
+{
+ t_trapezoid *x = (t_trapezoid *)(w[1]);
+ int nblock = (int)(w[2]);
+ t_float *in1 = (t_float *)(w[3]);
+ t_float *in2 = (t_float *)(w[4]);
+ t_float *in3 = (t_float *)(w[5]);
+ t_float *out = (t_float *)(w[6]);
+ float low = x->x_low;
+ float range = x->x_range;
+ while (nblock--)
+ {
+ float ph = *in1++;
+ float upph = *in2++;
+ float dnph = *in3++;
+ /* CHECKED ph wrapped */
+ if (ph < 0.)
+ ph -= (int)ph - 1.;
+ else if (ph > 1.)
+ ph -= (int)ph;
+ /* CHECKED upph, dnph clipped */
+ if (upph < 0.)
+ upph = 0.;
+ else if (upph > 1.) /* CHECKME */
+ upph = 1.;
+ if (dnph < upph)
+ dnph = upph;
+ else if (dnph > 1.)
+ dnph = 1.;
+
+ if (ph < upph)
+ ph /= upph;
+ else if (ph < dnph)
+ ph = 1.;
+ else if (dnph < 1.)
+ ph = (1. - ph) / (1. - dnph);
+ else
+ ph = 0.;
+ *out++ = low + ph * range;
+ }
+ return (w + 7);
+}
+
+static void trapezoid_dsp(t_trapezoid *x, t_signal **sp)
+{
+ dsp_add(trapezoid_perform, 6, x, sp[0]->s_n,
+ sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec);
+}
+
+static void *trapezoid_new(t_symbol *s, int ac, t_atom *av)
+{
+ t_trapezoid *x = (t_trapezoid *)pd_new(trapezoid_class);
+ sic_inlet((t_sic *)x, 1, TRAPEZOID_DEFUP, 0, ac, av);
+ sic_inlet((t_sic *)x, 2, TRAPEZOID_DEFDN, 1, ac, av);
+ outlet_new((t_object *)x, &s_signal);
+ x->x_low = TRAPEZOID_DEFLO;
+ x->x_range = (TRAPEZOID_DEFHI - TRAPEZOID_DEFLO);
+ return (x);
+}
+
+void trapezoid_tilde_setup(void)
+{
+ trapezoid_class = class_new(gensym("trapezoid~"),
+ (t_newmethod)trapezoid_new, 0,
+ sizeof(t_trapezoid), 0, A_GIMME, 0);
+ sic_setup(trapezoid_class, trapezoid_dsp, SIC_FLOATTOSIGNAL);
+ class_addmethod(trapezoid_class, (t_method)trapezoid_lo,
+ gensym("lo"), A_DEFFLOAT, 0); /* CHECKME */
+ class_addmethod(trapezoid_class, (t_method)trapezoid_hi,
+ gensym("hi"), A_DEFFLOAT, 0); /* CHECKME */
+}
diff --git a/cyclone/sickle/triangle.c b/cyclone/sickle/triangle.c
new file mode 100644
index 0000000..703e5ba
--- /dev/null
+++ b/cyclone/sickle/triangle.c
@@ -0,0 +1,95 @@
+/* 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 TRIANGLE_DEFPHASE 0.5
+#define TRIANGLE_DEFLO -1.0
+#define TRIANGLE_DEFHI 1.0
+
+typedef struct _triangle
+{
+ t_sic x_sic;
+ float x_low;
+ float x_range;
+} t_triangle;
+
+static t_class *triangle_class;
+
+static void triangle_lo(t_triangle *x, t_floatarg f)
+{
+ float high = x->x_low + x->x_range;
+ x->x_low = f;
+ x->x_range = high - x->x_low;
+}
+
+static void triangle_hi(t_triangle *x, t_floatarg f)
+{
+ x->x_range = f - x->x_low;
+}
+
+/* LATER optimize */
+static t_int *triangle_perform(t_int *w)
+{
+ t_triangle *x = (t_triangle *)(w[1]);
+ int nblock = (int)(w[2]);
+ t_float *in1 = (t_float *)(w[3]);
+ t_float *in2 = (t_float *)(w[4]);
+ t_float *out = (t_float *)(w[5]);
+ float low = x->x_low;
+ float range = x->x_range;
+ while (nblock--)
+ {
+ float ph = *in1++;
+ float peakph = *in2++;
+ /* CHECKED ph wrapped */
+ if (ph < 0.)
+ ph -= (int)ph - 1.;
+ else if (ph > 1.)
+ ph -= (int)ph;
+ /* CHECKED peakph clipped */
+ if (peakph < 0.)
+ peakph = 0.;
+ else if (peakph > 1.)
+ peakph = 1.;
+
+ if (ph < peakph)
+ ph /= peakph;
+ else if (peakph < 1.)
+ ph = (1. - ph) / (1. - peakph);
+ else
+ ph = 0.;
+ *out++ = low + ph * range;
+ }
+ return (w + 6);
+}
+
+static void triangle_dsp(t_triangle *x, t_signal **sp)
+{
+ dsp_add(triangle_perform, 5, x, sp[0]->s_n,
+ sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec);
+}
+
+static void *triangle_new(t_symbol *s, int ac, t_atom *av)
+{
+ t_triangle *x = (t_triangle *)pd_new(triangle_class);
+ sic_inlet((t_sic *)x, 1, TRIANGLE_DEFPHASE, 0, ac, av);
+ outlet_new((t_object *)x, &s_signal);
+ x->x_low = TRIANGLE_DEFLO;
+ x->x_range = (TRIANGLE_DEFHI - TRIANGLE_DEFLO);
+ return (x);
+}
+
+void triangle_tilde_setup(void)
+{
+ triangle_class = class_new(gensym("triangle~"),
+ (t_newmethod)triangle_new, 0,
+ sizeof(t_triangle), 0, A_GIMME, 0);
+ sic_setup(triangle_class, triangle_dsp, SIC_FLOATTOSIGNAL);
+ class_addmethod(triangle_class, (t_method)triangle_lo,
+ gensym("lo"), A_DEFFLOAT, 0); /* CHECKED */
+ class_addmethod(triangle_class, (t_method)triangle_hi,
+ gensym("hi"), A_DEFFLOAT, 0); /* CHECKED */
+}
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);
+}
diff --git a/cyclone/sickle/wave.c b/cyclone/sickle/wave.c
new file mode 100644
index 0000000..7804c88
--- /dev/null
+++ b/cyclone/sickle/wave.c
@@ -0,0 +1,161 @@
+/* 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 <string.h>
+#include "m_pd.h"
+#include "sickle/sic.h"
+#include "sickle/arsic.h"
+
+/* CHECKME (the refman): the extra channels are not played */
+
+typedef struct _wave
+{
+ t_arsic x_arsic;
+ int x_nointerp;
+} t_wave;
+
+static t_class *wave_class;
+
+static void wave_interp(t_wave *x, t_floatarg f)
+{
+ x->x_nointerp = (f == 0);
+ arsic_setminsize((t_arsic *)x, (x->x_nointerp ? 1 : 4));
+ arsic_check((t_arsic *)x);
+}
+
+static void wave_set(t_wave *x, t_symbol *s)
+{
+ arsic_setarray((t_arsic *)x, s, 1);
+}
+
+static t_int *wave_perform(t_int *w)
+{
+ t_arsic *sic = (t_arsic *)(w[1]);
+ int nblock = (int)(w[2]);
+ int nch = sic->s_nchannels;
+ t_int *outp = w + 6;
+ if (sic->s_playable)
+ {
+ t_wave *x = (t_wave *)sic;
+ t_float *xin = (t_float *)(w[3]);
+ t_float *sin = (t_float *)(w[4]);
+ t_float *ein = (t_float *)(w[5]);
+ int vecsize = sic->s_vecsize;
+ t_float **vectable = sic->s_vectors;
+ float ksr = sic->s_ksr;
+ int nointerp = x->x_nointerp;
+ int maxindex = (nointerp ? vecsize - 1 : vecsize - 3);
+ int iblock;
+
+ for (iblock = 0; iblock < nblock; iblock++)
+ {
+ float spos = *sin++ * ksr;
+ float xpos = *ein++ * ksr;
+ /* msp seems to be buggy here, but CHECKME again */
+ int siz = (int)((xpos > 0 ? xpos : maxindex) - spos);
+ float phase = *xin++;
+ int ndx;
+ int ch = nch;
+ /* CHECKED: phase is clipped, not wrapped */
+ if (phase < 0) phase = 0;
+ else if (phase > 1.0) phase = 1.0;
+ xpos = (siz > 0 ? spos + siz * phase : spos);
+ ndx = (int)xpos;
+ if (nointerp)
+ {
+ if (ndx < 0) ndx = 0;
+ else if (ndx > maxindex) ndx = maxindex;
+ while (ch--)
+ {
+ t_float *vp = vectable[ch];
+ t_float *out = (t_float *)(outp[ch]);
+ out[iblock] = (vp ? vp[ndx] : 0);
+ }
+ }
+ else
+ {
+ float frac, a, b, c, d, cminusb;
+ if (ndx < 1)
+ ndx = 1, frac = 0;
+ else if (ndx > maxindex)
+ ndx = maxindex, frac = 1;
+ else frac = xpos - ndx;
+ while (ch--)
+ {
+ t_float *vp = vectable[ch];
+ t_float *out = (t_float *)(outp[ch]);
+ if (vp)
+ {
+ vp += ndx;
+ a = vp[-1];
+ b = vp[0];
+ c = vp[1];
+ d = vp[2];
+ cminusb = c-b;
+ out[iblock] = b + frac * (
+ cminusb - 0.1666667f * (1. - frac) * (
+ (d - a - 3.0f * cminusb) * frac
+ + (d + 2.0f * a - 3.0f * b)
+ )
+ );
+ }
+ else out[iblock] = 0;
+ }
+ }
+ }
+ }
+ else
+ {
+ int ch = nch;
+ while (ch--)
+ {
+ t_float *out = (t_float *)outp[ch];
+ int n = nblock;
+ while (n--) *out++ = 0;
+ }
+ }
+ return (w + sic->s_nperfargs + 1);
+}
+
+static void wave_dsp(t_wave *x, t_signal **sp)
+{
+ arsic_dsp((t_arsic *)x, sp, wave_perform, 1);
+}
+
+static void wave_free(t_wave *x)
+{
+ arsic_free((t_arsic *)x);
+}
+
+static void *wave_new(t_symbol *s, t_floatarg f1, t_floatarg f2, t_floatarg f3)
+{
+ /* three auxiliary signals: phase, clipstart, and clipend inputs */
+ t_wave *x = (t_wave *)arsic_new(wave_class, s, (int)f3, 0, 3);
+ if (x)
+ {
+ int nch = arsic_getnchannels((t_arsic *)x);
+ if (f1 < 0) f1 = 0;
+ if (f2 < 0) f2 = 0;
+ sic_newinlet((t_sic *)x, f1);
+ sic_newinlet((t_sic *)x, f2);
+ while (nch--)
+ outlet_new((t_object *)x, &s_signal);
+ wave_interp(x, 1);
+ }
+ return (x);
+}
+
+void wave_tilde_setup(void)
+{
+ wave_class = class_new(gensym("wave~"),
+ (t_newmethod)wave_new,
+ (t_method)wave_free,
+ sizeof(t_wave), 0,
+ A_DEFSYM, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0);
+ arsic_setup(wave_class, wave_dsp, SIC_FLOATTOSIGNAL);
+ class_addmethod(wave_class, (t_method)wave_set,
+ gensym("set"), A_SYMBOL, 0);
+ class_addmethod(wave_class, (t_method)wave_interp,
+ gensym("interp"), A_FLOAT, 0);
+}