aboutsummaryrefslogtreecommitdiff
path: root/cyclone
diff options
context:
space:
mode:
Diffstat (limited to 'cyclone')
-rw-r--r--cyclone/Makefile2
-rw-r--r--cyclone/Makefile.dirs2
-rw-r--r--cyclone/Makefile.objects24
-rw-r--r--cyclone/Makefile.sources191
-rw-r--r--cyclone/build_counter3
-rw-r--r--cyclone/cyclone-all.exclude9
-rw-r--r--cyclone/cyclone-shared.include35
-rw-r--r--cyclone/cyclone-test.exclude4
-rw-r--r--cyclone/cyclone-vicious.exclude3
-rw-r--r--cyclone/hammer/Append.c207
-rw-r--r--cyclone/hammer/Borax.c177
-rw-r--r--cyclone/hammer/Bucket.c137
-rw-r--r--cyclone/hammer/Clip.c149
-rw-r--r--cyclone/hammer/Decode.c110
-rw-r--r--cyclone/hammer/Histo.c103
-rw-r--r--cyclone/hammer/Makefile3
-rw-r--r--cyclone/hammer/Makefile.objects14
-rw-r--r--cyclone/hammer/Makefile.sources80
-rw-r--r--cyclone/hammer/MouseState.c153
-rw-r--r--cyclone/hammer/Peak.c63
-rw-r--r--cyclone/hammer/TogEdge.c71
-rw-r--r--cyclone/hammer/Trough.c63
-rw-r--r--cyclone/hammer/Uzi.c108
-rw-r--r--cyclone/hammer/accum.c68
-rw-r--r--cyclone/hammer/acos.c48
-rw-r--r--cyclone/hammer/active.c55
-rw-r--r--cyclone/hammer/allhammers.c160
-rw-r--r--cyclone/hammer/anal.c108
-rw-r--r--cyclone/hammer/asin.c48
-rw-r--r--cyclone/hammer/bangbang.c73
-rw-r--r--cyclone/hammer/bondo.c394
-rw-r--r--cyclone/hammer/buddy.c253
-rw-r--r--cyclone/hammer/capture.c291
-rw-r--r--cyclone/hammer/cartopol.c44
-rw-r--r--cyclone/hammer/coll.c1597
-rw-r--r--cyclone/hammer/comment.c835
-rw-r--r--cyclone/hammer/cosh.c48
-rw-r--r--cyclone/hammer/counter.c399
-rw-r--r--cyclone/hammer/cycle.c153
-rw-r--r--cyclone/hammer/decide.c75
-rw-r--r--cyclone/hammer/drunk.c140
-rw-r--r--cyclone/hammer/flush.c79
-rw-r--r--cyclone/hammer/forward.c71
-rw-r--r--cyclone/hammer/fromsymbol.c88
-rw-r--r--cyclone/hammer/funbuff.c521
-rw-r--r--cyclone/hammer/funnel.c179
-rw-r--r--cyclone/hammer/gate.c147
-rw-r--r--cyclone/hammer/grab.c279
-rw-r--r--cyclone/hammer/hammer.c93
-rw-r--r--cyclone/hammer/iter.c112
-rw-r--r--cyclone/hammer/match.c216
-rw-r--r--cyclone/hammer/maximum.c88
-rw-r--r--cyclone/hammer/mean.c79
-rw-r--r--cyclone/hammer/midiflush.c102
-rw-r--r--cyclone/hammer/midiformat.c112
-rw-r--r--cyclone/hammer/midiparse.c132
-rw-r--r--cyclone/hammer/minimum.c88
-rw-r--r--cyclone/hammer/mousefilter.c70
-rw-r--r--cyclone/hammer/next.c58
-rw-r--r--cyclone/hammer/offer.c94
-rw-r--r--cyclone/hammer/onebang.c46
-rw-r--r--cyclone/hammer/past.c154
-rw-r--r--cyclone/hammer/pd-lib-notes.txt61
-rw-r--r--cyclone/hammer/poltocar.c44
-rw-r--r--cyclone/hammer/prepend.c258
-rw-r--r--cyclone/hammer/prob.c312
-rw-r--r--cyclone/hammer/pv.c457
-rw-r--r--cyclone/hammer/seq.c825
-rw-r--r--cyclone/hammer/sinh.c48
-rw-r--r--cyclone/hammer/speedlim.c173
-rw-r--r--cyclone/hammer/spell.c149
-rw-r--r--cyclone/hammer/split.c64
-rw-r--r--cyclone/hammer/spray.c93
-rw-r--r--cyclone/hammer/sprintf.c634
-rw-r--r--cyclone/hammer/substitute.c340
-rw-r--r--cyclone/hammer/sustain.c85
-rw-r--r--cyclone/hammer/switch.c152
-rw-r--r--cyclone/hammer/tanh.c48
-rw-r--r--cyclone/hammer/testmess.c245
-rw-r--r--cyclone/hammer/thresh.c134
-rw-r--r--cyclone/hammer/tosymbol.c184
-rw-r--r--cyclone/hammer/universal.c167
-rw-r--r--cyclone/hammer/urn.c148
-rw-r--r--cyclone/hammer/xbendin.c93
-rw-r--r--cyclone/hammer/xbendin2.c99
-rw-r--r--cyclone/hammer/xbendout.c54
-rw-r--r--cyclone/hammer/xbendout2.c60
-rw-r--r--cyclone/hammer/xnotein.c100
-rw-r--r--cyclone/hammer/xnoteout.c62
-rw-r--r--cyclone/hammer/zl.c982
-rw-r--r--cyclone/shadow/Makefile7
-rw-r--r--cyclone/shadow/Makefile.objects9
-rw-r--r--cyclone/shadow/Makefile.sources6
-rw-r--r--cyclone/shadow/cyclone.c159
-rw-r--r--cyclone/shadow/dummies.c664
-rw-r--r--cyclone/shadow/nettles.c549
-rw-r--r--cyclone/shadow/shadow.h13
-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
164 files changed, 24624 insertions, 0 deletions
diff --git a/cyclone/Makefile b/cyclone/Makefile
new file mode 100644
index 0000000..fc022be
--- /dev/null
+++ b/cyclone/Makefile
@@ -0,0 +1,2 @@
+ROOT_DIR = ..
+include $(ROOT_DIR)/Makefile.common
diff --git a/cyclone/Makefile.dirs b/cyclone/Makefile.dirs
new file mode 100644
index 0000000..0dde72f
--- /dev/null
+++ b/cyclone/Makefile.dirs
@@ -0,0 +1,2 @@
+MIXED_DIRS = shadow hammer sickle
+RELEASE_DIRS = shadow hammer sickle
diff --git a/cyclone/Makefile.objects b/cyclone/Makefile.objects
new file mode 100644
index 0000000..9b421fe
--- /dev/null
+++ b/cyclone/Makefile.objects
@@ -0,0 +1,24 @@
+HLOUD_OBJECTS = common/loud.o
+HFRAGILE_OBJECTS = common/loud.o unstable/fragile.o
+HGROW_OBJECTS = common/grow.o common/loud.o
+HFILE_OBJECTS = hammer/file.o common/loud.o
+HRAND_OBJECTS = common/rand.o common/loud.o
+HRANDFILE_OBJECTS = common/rand.o hammer/file.o common/loud.o
+HRANDGROW_OBJECTS = common/rand.o common/grow.o common/loud.o
+HTREE_OBJECTS = hammer/tree.o common/loud.o
+HTREEFILEVEFL_OBJECTS = hammer/tree.o hammer/file.o \
+ common/vefl.o common/loud.o unstable/fragile.o
+HGUI_OBJECTS = hammer/gui.o common/loud.o
+HSEQ_OBJECTS = common/sq.o common/bifi.o common/mifi.o \
+ hammer/file.o common/grow.o common/loud.o
+SSIC_OBJECTS = sickle/sic.o common/loud.o
+SFORKY_OBJECTS = sickle/sic.o common/loud.o unstable/forky.o
+SFRAGILE_OBJECTS = sickle/sic.o common/loud.o unstable/fragile.o
+SGROW_OBJECTS = common/grow.o sickle/sic.o common/loud.o
+SGROWFORKY_OBJECTS = common/grow.o sickle/sic.o common/loud.o unstable/forky.o
+SVEFL_OBJECTS = common/vefl.o sickle/sic.o common/loud.o unstable/fragile.o
+SARSIC_OBJECTS = sickle/sic.o sickle/arsic.o common/vefl.o \
+ common/loud.o unstable/fragile.o
+SFILE_OBJECTS = hammer/file.o sickle/sic.o common/loud.o
+RELEASE_LIBS = cyclone hammer sickle
+RELEASE_APPS = cyclist
diff --git a/cyclone/Makefile.sources b/cyclone/Makefile.sources
new file mode 100644
index 0000000..4d6cc29
--- /dev/null
+++ b/cyclone/Makefile.sources
@@ -0,0 +1,191 @@
+TYPES = HPLAIN HLOUD HFRAGILE HGROW HFILE HRAND HRANDFILE HRANDGROW \
+ HTREE HTREEFILEVEFL HGUI HSEQ \
+ SPLAINNOTILDE SPLAIN SSIC SFORKY SFRAGILE SGROW SGROWFORKY \
+ SVEFL SARSIC SFILE
+
+HPLAIN_SOURCES = \
+hammer/testmess.c \
+hammer/accum.c \
+hammer/acos.c \
+hammer/asin.c \
+hammer/Bucket.c \
+hammer/cartopol.c \
+hammer/cosh.c \
+hammer/counter.c \
+hammer/flush.c \
+hammer/forward.c \
+hammer/fromsymbol.c \
+hammer/mean.c \
+hammer/midiflush.c \
+hammer/midiformat.c \
+hammer/midiparse.c \
+hammer/next.c \
+hammer/onebang.c \
+hammer/Peak.c \
+hammer/poltocar.c \
+hammer/sinh.c \
+hammer/split.c \
+hammer/sustain.c \
+hammer/tanh.c \
+hammer/Trough.c \
+hammer/Uzi.c \
+hammer/xbendin.c \
+hammer/xbendin2.c \
+hammer/xbendout.c \
+hammer/xbendout2.c \
+hammer/xnotein.c \
+hammer/xnoteout.c
+
+HLOUD_SOURCES = \
+hammer/anal.c \
+hammer/bangbang.c \
+hammer/Borax.c \
+hammer/comment.c \
+hammer/cycle.c \
+hammer/decide.c \
+hammer/Decode.c \
+hammer/gate.c \
+hammer/Histo.c \
+hammer/maximum.c \
+hammer/minimum.c \
+hammer/spell.c \
+hammer/spray.c \
+hammer/sprintf.c \
+hammer/switch.c \
+hammer/TogEdge.c
+
+HFRAGILE_SOURCES = \
+hammer/grab.c \
+hammer/universal.c
+
+HGROW_SOURCES = \
+hammer/Append.c \
+hammer/bondo.c \
+hammer/buddy.c \
+hammer/Clip.c \
+hammer/funnel.c \
+hammer/iter.c \
+hammer/match.c \
+hammer/past.c \
+hammer/prepend.c \
+hammer/pv.c \
+hammer/speedlim.c \
+hammer/substitute.c \
+hammer/thresh.c \
+hammer/tosymbol.c \
+hammer/zl.c
+
+HFILE_SOURCES = \
+hammer/capture.c \
+hammer/coll.c
+
+HRAND_SOURCES = \
+hammer/drunk.c
+
+HRANDFILE_SOURCES = \
+hammer/prob.c
+
+HRANDGROW_SOURCES = \
+hammer/urn.c
+
+HTREE_SOURCES = \
+hammer/offer.c
+
+HTREEFILEVEFL_SOURCES = \
+hammer/funbuff.c
+
+HGUI_SOURCES = \
+hammer/active.c \
+hammer/mousefilter.c \
+hammer/MouseState.c
+
+HSEQ_SOURCES = \
+hammer/seq.c
+
+SPLAINNOTILDE_SOURCES = \
+sickle/linedrive.c
+
+SSIC_TILDE = $(TILDE)
+SSIC_SOURCES = \
+sickle/abs.c \
+sickle/acos.c \
+sickle/acosh.c \
+sickle/allpass.c \
+sickle/asin.c \
+sickle/asinh.c \
+sickle/atan.c \
+sickle/atan2.c \
+sickle/atanh.c \
+sickle/average.c \
+sickle/avg.c \
+sickle/bitnot.c \
+sickle/bitshift.c \
+sickle/change.c \
+sickle/Clip.c \
+sickle/comb.c \
+sickle/cosh.c \
+sickle/cosx.c \
+sickle/count.c \
+sickle/delay.c \
+sickle/delta.c \
+sickle/deltaclip.c \
+sickle/edge.c \
+sickle/kink.c \
+sickle/log.c \
+sickle/minmax.c \
+sickle/peakamp.c \
+sickle/phasewrap.c \
+sickle/pow.c \
+sickle/rampsmooth.c \
+sickle/rand.c \
+sickle/sah.c \
+sickle/sinh.c \
+sickle/sinx.c \
+sickle/slide.c \
+sickle/Snapshot.c \
+sickle/spike.c \
+sickle/tanh.c \
+sickle/tanx.c \
+sickle/train.c \
+sickle/trapezoid.c \
+sickle/triangle.c \
+sickle/vectral.c
+
+SFORKY_TILDE = $(TILDE)
+SFORKY_SOURCES = \
+sickle/bitand.c \
+sickle/bitor.c \
+sickle/bitxor.c
+
+SFRAGILE_TILDE = $(TILDE)
+SFRAGILE_SOURCES = \
+sickle/cartopol.c \
+sickle/poltocar.c
+
+SGROW_TILDE = $(TILDE)
+SGROW_SOURCES = \
+sickle/click.c \
+sickle/frameaccum.c \
+sickle/framedelta.c \
+sickle/Line.c
+
+SGROWFORKY_TILDE = $(TILDE)
+SGROWFORKY_SOURCES = \
+sickle/Scope.c
+
+SVEFL_TILDE = $(TILDE)
+SVEFL_SOURCES = \
+sickle/cycle.c
+
+SARSIC_TILDE = $(TILDE)
+SARSIC_SOURCES = \
+sickle/index.c \
+sickle/lookup.c \
+sickle/peek.c \
+sickle/play.c \
+sickle/record.c \
+sickle/wave.c
+
+SFILE_TILDE = $(TILDE)
+SFILE_SOURCES = \
+sickle/capture.c
diff --git a/cyclone/build_counter b/cyclone/build_counter
new file mode 100644
index 0000000..1e05d4b
--- /dev/null
+++ b/cyclone/build_counter
@@ -0,0 +1,3 @@
+#define CYCLONE_VERSION "0.1"
+#define CYCLONE_RELEASE "alpha"
+#define CYCLONE_BUILD 42
diff --git a/cyclone/cyclone-all.exclude b/cyclone/cyclone-all.exclude
new file mode 100644
index 0000000..8b8d91f
--- /dev/null
+++ b/cyclone/cyclone-all.exclude
@@ -0,0 +1,9 @@
+*~
+*.o
+*.gz
+*.html
+*.out
+*/*/old
+*/*/old/*
+*/*/ref
+*/*/ref/*
diff --git a/cyclone/cyclone-shared.include b/cyclone/cyclone-shared.include
new file mode 100644
index 0000000..49cc815
--- /dev/null
+++ b/cyclone/cyclone-shared.include
@@ -0,0 +1,35 @@
+shared/shared.c
+shared/shared.h
+shared/unstable/forky.c
+shared/unstable/forky.h
+shared/unstable/fragile.c
+shared/unstable/fragile.h
+shared/unstable/pd_imp.h
+shared/common/grow.c
+shared/common/grow.h
+shared/common/loud.c
+shared/common/loud.h
+shared/common/binport.c
+shared/common/binport.h
+shared/common/port.c
+shared/common/port.h
+shared/common/rand.c
+shared/common/rand.h
+shared/common/vefl.c
+shared/common/vefl.h
+shared/common/sq.c
+shared/common/sq.h
+shared/common/bifi.c
+shared/common/bifi.h
+shared/common/mifi.c
+shared/common/mifi.h
+shared/hammer/file.c
+shared/hammer/file.h
+shared/hammer/gui.c
+shared/hammer/gui.h
+shared/hammer/tree.c
+shared/hammer/tree.h
+shared/sickle/sic.c
+shared/sickle/sic.h
+shared/sickle/arsic.c
+shared/sickle/arsic.h
diff --git a/cyclone/cyclone-test.exclude b/cyclone/cyclone-test.exclude
new file mode 100644
index 0000000..ec84f87
--- /dev/null
+++ b/cyclone/cyclone-test.exclude
@@ -0,0 +1,4 @@
+*~
+import-result.pd
+temporary
+temporary/*
diff --git a/cyclone/cyclone-vicious.exclude b/cyclone/cyclone-vicious.exclude
new file mode 100644
index 0000000..5e5a82e
--- /dev/null
+++ b/cyclone/cyclone-vicious.exclude
@@ -0,0 +1,3 @@
+*~
+old
+old/*
diff --git a/cyclone/hammer/Append.c b/cyclone/hammer/Append.c
new file mode 100644
index 0000000..19978c7
--- /dev/null
+++ b/cyclone/hammer/Append.c
@@ -0,0 +1,207 @@
+/* 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/loud.h"
+#include "common/grow.h"
+
+#define APPEND_INISIZE 32 /* LATER rethink */
+#define APPEND_MAXSIZE 256
+
+typedef struct _append
+{
+ t_object x_ob;
+ int x_size; /* as allocated */
+ int x_natoms; /* as used */
+ t_atom *x_message;
+ t_atom *x_messbuf;
+ t_atom x_messini[APPEND_INISIZE];
+ int x_entered;
+ int x_auxsize;
+ t_atom *x_auxbuf;
+} t_append;
+
+static t_class *append_class;
+
+/* Usually a preallocation method is used, except in special cases of:
+ 1) reentrant output request, or 2) an output request which would cause
+ resizing to more than MAXSIZE (no such limit for a 'set' message).
+ In both special cases, a temporary output buffer is allocated.
+ A separately preallocated output buffer is not used, thus avoiding
+ memcpying of the stored message (a small performance gain when the
+ preallocation method is chosen). Instead, self-invoked 'set'
+ messages are postponed, using an auxiliary buffer.
+*/
+
+/* Any Append's output goes through outlet_anything() -> typedmess() */
+
+static void append_setnatoms(t_append *x, int natoms)
+{
+ x->x_message = x->x_messbuf + x->x_size - natoms;
+ x->x_natoms = natoms;
+}
+
+static void append_anything(t_append *x, t_symbol *s, int ac, t_atom *av)
+{
+ int reentered = x->x_entered;
+ int prealloc = !reentered;
+ int ntotal = x->x_natoms + ac;
+ t_atom *buf;
+ x->x_entered = 1;
+ if (prealloc && ntotal > x->x_size)
+ {
+ if (ntotal > APPEND_MAXSIZE)
+ prealloc = 0;
+ else
+ {
+ int nrequested = ntotal;
+ x->x_messbuf = grow_withtail(&nrequested, &x->x_natoms,
+ (char **)&x->x_message,
+ &x->x_size, x->x_messbuf,
+ APPEND_INISIZE, x->x_messini,
+ sizeof(*x->x_message));
+ prealloc = (nrequested == ntotal);
+ }
+ }
+ if (prealloc)
+ {
+ buf = x->x_message - ac;
+ if (ac)
+ memcpy(buf, av, ac * sizeof(*buf));
+ outlet_anything(((t_object *)x)->ob_outlet, s, ntotal, buf);
+ }
+ else
+ {
+ /* LATER consider using the stack if ntotal <= MAXSTACK */
+ if (buf = getbytes(ntotal * sizeof(*buf)))
+ {
+ if (ac)
+ memcpy(buf, av, ac * sizeof(*buf));
+ if (x->x_natoms)
+ memcpy(buf + ac, x->x_message, x->x_natoms * sizeof(*buf));
+ outlet_anything(((t_object *)x)->ob_outlet, s, ntotal, buf);
+ freebytes(buf, ntotal * sizeof(*buf));
+ }
+ }
+ if (!reentered)
+ {
+ x->x_entered = 0;
+ if (x->x_auxbuf)
+ {
+ if (x->x_auxsize <= x->x_size)
+ {
+ append_setnatoms(x, x->x_auxsize / 2);
+ memcpy(x->x_message, x->x_auxbuf + x->x_natoms,
+ x->x_natoms * sizeof(*x->x_message));
+ freebytes(x->x_auxbuf, x->x_auxsize * sizeof(*x->x_auxbuf));
+ }
+ else
+ {
+ if (x->x_messbuf != x->x_messini)
+ freebytes(x->x_messbuf, x->x_size * sizeof(*x->x_messbuf));
+ x->x_size = x->x_auxsize;
+ x->x_messbuf = x->x_auxbuf;
+ append_setnatoms(x, x->x_auxsize / 2);
+ }
+ x->x_auxbuf = 0;
+ }
+ }
+}
+
+static void append_bang(t_append *x)
+{
+ /* CHECKED: a nop */
+}
+
+static void append_float(t_append *x, t_float f)
+{
+ t_atom at;
+ SETFLOAT(&at, f);
+ append_anything(x, &s_list, 1, &at); /* CHECKED: converted to list */
+}
+
+/* CHECKED: incompatible -- LATER consider converting to anything */
+static void append_symbol(t_append *x, t_symbol *s)
+{
+ t_atom at;
+ SETSYMBOL(&at, s);
+ append_anything(x, &s_symbol, 1, &at);
+}
+
+/* LATER gpointer */
+
+static void append_set(t_append *x, t_symbol *s, int ac, t_atom *av)
+{
+ int newsize = ac * 2;
+ if (newsize > 0)
+ {
+ if (x->x_entered)
+ {
+ if (x->x_auxbuf)
+ {
+ loud_warning((t_pd *)x, "\'set\' message overridden");
+ freebytes(x->x_auxbuf, x->x_auxsize * sizeof(*x->x_auxbuf));
+ x->x_auxsize = 0;
+ }
+ if (x->x_auxbuf = getbytes(newsize * sizeof(*x->x_auxbuf)))
+ {
+ memcpy(x->x_auxbuf + ac, av, ac * sizeof(*x->x_auxbuf));
+ x->x_auxsize = newsize;
+ }
+ }
+ else
+ {
+ t_atom *ap;
+ if (newsize > x->x_size)
+ {
+ int sz = newsize;
+ x->x_messbuf = grow_nodata(&sz, &x->x_size, x->x_messbuf,
+ APPEND_INISIZE, x->x_messini,
+ sizeof(*x->x_messbuf));
+ if (sz != newsize)
+ ac = sz / 2; /* LATER rethink */
+ }
+ append_setnatoms(x, ac);
+ ap = x->x_message;
+ while (ac--) *ap++ = *av++;
+ }
+ }
+}
+
+static void append_free(t_append *x)
+{
+ if (x->x_messbuf != x->x_messini)
+ freebytes(x->x_messbuf, x->x_size * sizeof(*x->x_messbuf));
+}
+
+static void *append_new(t_symbol *s, int ac, t_atom *av)
+{
+ t_append *x = (t_append *)pd_new(append_class);
+ x->x_size = APPEND_INISIZE;
+ x->x_natoms = 0;
+ x->x_messbuf = x->x_messini;
+ x->x_auxbuf = 0;
+ x->x_entered = 0;
+ outlet_new((t_object *)x, &s_anything);
+ append_setnatoms(x, 0);
+ append_set(x, 0, ac, av);
+ return (x);
+}
+
+void Append_setup(void)
+{
+ append_class = class_new(gensym("Append"),
+ (t_newmethod)append_new,
+ (t_method)append_free,
+ sizeof(t_append), 0,
+ A_GIMME, 0);
+ class_addbang(append_class, append_bang);
+ class_addfloat(append_class, append_float);
+ class_addsymbol(append_class, append_symbol);
+ class_addlist(append_class, append_anything); /* LATER rethink */
+ class_addanything(append_class, append_anything);
+ class_addmethod(append_class, (t_method)append_set,
+ gensym("set"), A_GIMME, 0);
+}
diff --git a/cyclone/hammer/Borax.c b/cyclone/hammer/Borax.c
new file mode 100644
index 0000000..26e0ef8
--- /dev/null
+++ b/cyclone/hammer/Borax.c
@@ -0,0 +1,177 @@
+/* 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. */
+
+/* The first version of this code was written by Olaf Matthes.
+ It was entirely reimplemented in the hope of adapting it to the
+ cyclone's guidelines. */
+
+#include <string.h>
+#include "m_pd.h"
+#include "common/loud.h"
+
+#define BORAX_MAXVOICES 128 /* CHECKME */
+
+typedef struct _Borax_voice
+{
+ int v_index; /* free iff zero */
+ double v_onset;
+ int v_nonsets;
+} t_Borax_voice;
+
+typedef struct _Borax
+{
+ t_object x_ob;
+ int x_vel; /* CHECKME t_float controlled with floatinlet
+ (CHECKME the same in flush) */
+ double x_onset;
+ int x_nonsets;
+ int x_ndurs;
+ int x_ndtimes;
+ int x_minindex;
+ int x_indices[BORAX_MAXVOICES]; /* 0 (free) or 1 (used) */
+ int x_nvoices;
+ t_Borax_voice x_voices[BORAX_MAXVOICES];
+ t_outlet *x_voiceout;
+ t_outlet *x_nvoicesout;
+ t_outlet *x_pitchout;
+ t_outlet *x_velout;
+ t_outlet *x_ndursout;
+ t_outlet *x_durout;
+ t_outlet *x_ndtimesout;
+ t_outlet *x_dtimeout;
+} t_Borax;
+
+static t_class *Borax_class;
+
+static void Borax_delta(t_Borax *x)
+{
+ /* CHECKME first note */
+ float dtime = clock_gettimesince(x->x_onset); /* CHECKME */
+ outlet_float(x->x_dtimeout, dtime);
+ outlet_float(x->x_ndtimesout, ++x->x_ndtimes); /* CHECKME */
+}
+
+static void Borax_durout(t_Borax *x, int pitch)
+{
+ float dur = clock_gettimesince(x->x_voices[pitch].v_onset); /* CHECKME */
+ outlet_float(x->x_durout, dur);
+ outlet_float(x->x_ndursout, ++x->x_ndurs); /* CHECKME */
+}
+
+static void Borax_float(t_Borax *x, t_float f)
+{
+ int pitch;
+ if (loud_checkint((t_pd *)x, f, &pitch, &s_float)) /* CHECKME */
+ {
+ int index;
+ if (pitch < 0 || pitch >= BORAX_MAXVOICES)
+ {
+ /* CHECKME pitch range, complaints */
+ return;
+ }
+ index = x->x_voices[pitch].v_index;
+ if (x->x_vel)
+ {
+ if (index)
+ return; /* CHECKME */
+ x->x_indices[index = x->x_minindex] = 1;
+ while (x->x_indices[++x->x_minindex]);
+ index++; /* CHECKME one-based? */
+ Borax_delta(x);
+ x->x_onset = clock_getlogicaltime(); /* CHECKME (in delta?) */
+ x->x_voices[pitch].v_index = index;
+ x->x_voices[pitch].v_onset = x->x_onset;
+ x->x_voices[pitch].v_nonsets = ++x->x_nonsets;
+ x->x_nvoices++;
+ }
+ else
+ {
+ if (!index)
+ return; /* CHECKME */
+ index--;
+ x->x_indices[index] = 0;
+ if (index < x->x_minindex) x->x_minindex = index;
+ index++;
+ Borax_durout(x, pitch);
+ x->x_voices[pitch].v_index = 0;
+ x->x_nvoices--;
+ }
+ outlet_float(x->x_velout, x->x_vel);
+ outlet_float(x->x_pitchout, pitch);
+ outlet_float(x->x_nvoicesout, x->x_nvoices);
+ outlet_float(x->x_voiceout, index);
+ outlet_float(((t_object *)x)->ob_outlet, x->x_voices[pitch].v_nonsets);
+ }
+}
+
+static void Borax_ft1(t_Borax *x, t_floatarg f)
+{
+ x->x_vel = (int)f; /* CHECKME */
+}
+
+static void Borax_reset(t_Borax *x)
+{
+ x->x_vel = 0;
+ x->x_onset = clock_getlogicaltime();
+ x->x_nonsets = x->x_ndurs = x->x_ndtimes = 0;
+ x->x_minindex = 0;
+ memset(x->x_indices, 0, sizeof(x->x_indices));
+ x->x_nvoices = 0;
+ memset(x->x_voices, 0, sizeof(x->x_voices));
+}
+
+static void Borax_bang2(t_Borax *x)
+{
+ int pitch;
+ for (pitch = 0; pitch < BORAX_MAXVOICES; pitch++)
+ {
+ if (x->x_voices[pitch].v_index)
+ {
+ /* CHECKME counters, etc. */
+ Borax_durout(x, pitch);
+ outlet_float(x->x_velout, 0);
+ outlet_float(x->x_pitchout, pitch);
+ outlet_float(x->x_nvoicesout, --x->x_nvoices);
+ outlet_float(x->x_voiceout, x->x_voices[pitch].v_index);
+ outlet_float(((t_object *)x)->ob_outlet,
+ x->x_voices[pitch].v_nonsets);
+ }
+ }
+ Borax_reset(x);
+}
+
+/* CHECKME flush in a destructor */
+
+static void *Borax_new(void)
+{
+ t_Borax *x = (t_Borax *)pd_new(Borax_class);
+ inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft1"));
+ inlet_new((t_object *)x, (t_pd *)x, &s_bang, gensym("bang2"));
+ outlet_new((t_object *)x, &s_float);
+ x->x_voiceout = outlet_new((t_object *)x, &s_float);
+ x->x_nvoicesout = outlet_new((t_object *)x, &s_float);
+ x->x_pitchout = outlet_new((t_object *)x, &s_float);
+ x->x_velout = outlet_new((t_object *)x, &s_float);
+ x->x_ndursout = outlet_new((t_object *)x, &s_float);
+ x->x_durout = outlet_new((t_object *)x, &s_float);
+ x->x_ndtimesout = outlet_new((t_object *)x, &s_float);
+ x->x_dtimeout = outlet_new((t_object *)x, &s_float);
+ Borax_reset(x);
+ return (x);
+}
+
+void Borax_setup(void)
+{
+ Borax_class = class_new(gensym("Borax"),
+ (t_newmethod)Borax_new, 0,
+ sizeof(t_Borax), 0, 0);
+ class_addfloat(Borax_class, Borax_float);
+ /* CHECKME list unfolding */
+ class_addmethod(Borax_class, (t_method)Borax_ft1,
+ gensym("ft1"), A_FLOAT, 0);
+ class_addmethod(Borax_class, (t_method)Borax_bang2,
+ gensym("bang2"), 0);
+ class_addmethod(Borax_class, (t_method)Borax_delta,
+ gensym("delta"), 0);
+}
diff --git a/cyclone/hammer/Bucket.c b/cyclone/hammer/Bucket.c
new file mode 100644
index 0000000..036f836
--- /dev/null
+++ b/cyclone/hammer/Bucket.c
@@ -0,0 +1,137 @@
+/* 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. */
+
+/* This is a modified version of Joseph A. Sarlo's code.
+ The most important changes are listed in "pd-lib-notes.txt" file. */
+
+#include "m_pd.h"
+
+typedef struct _Bucket
+{
+ t_object x_ob;
+ int x_numbucks;
+ t_float *x_bucks; /* CHECKED: no limit */
+ t_outlet **x_outs;
+ short int x_frozen; /* 0 for thawed, 1 for frozen */
+ short int x_dir; /* 0 for L2R, 1 for R2L */
+} t_Bucket;
+
+static t_class *Bucket_class;
+
+static void Bucket_bang(t_Bucket *x)
+{
+ int i = x->x_numbucks;
+ /* CHECKED: outlets output in right-to-left order */
+ while (i--) outlet_float(x->x_outs[i], x->x_bucks[i]);
+}
+
+static void Bucket_float(t_Bucket *x, t_float val)
+{
+ int i;
+
+ if (!x->x_frozen)
+ Bucket_bang(x);
+ if (!x->x_dir)
+ {
+ for (i = x->x_numbucks - 1; i > 0; i--)
+ x->x_bucks[i] = x->x_bucks[i - 1];
+ x->x_bucks[0] = val;
+ }
+ else
+ {
+ for (i = 0; i < x->x_numbucks - 1; i++)
+ x->x_bucks[i] = x->x_bucks[i + 1];
+ x->x_bucks[x->x_numbucks - 1] = val;
+ }
+}
+
+static void Bucket_freeze(t_Bucket *x)
+{
+ x->x_frozen = 1;
+}
+
+static void Bucket_thaw(t_Bucket *x)
+{
+ x->x_frozen = 0;
+}
+
+static void Bucket_roll(t_Bucket *x)
+{
+ if (x->x_dir)
+ Bucket_float(x, x->x_bucks[0]);
+ else
+ Bucket_float(x, x->x_bucks[x->x_numbucks - 1]);
+}
+
+static void Bucket_rtol(t_Bucket *x)
+{
+ x->x_dir = 1;
+}
+
+static void Bucket_ltor(t_Bucket *x)
+{
+ x->x_dir = 0;
+}
+
+static void Bucket_set(t_Bucket *x, t_floatarg f)
+{
+ int i = x->x_numbucks;
+ while (i--) x->x_bucks[i] = f;
+ if (!x->x_frozen) /* CHECKED */
+ Bucket_bang(x);
+}
+
+static void Bucket_free(t_Bucket *x)
+{
+ if (x->x_bucks)
+ freebytes(x->x_bucks, x->x_numbucks * sizeof(*x->x_bucks));
+ if (x->x_outs)
+ freebytes(x->x_outs, x->x_numbucks * sizeof(*x->x_outs));
+}
+
+static void *Bucket_new(t_floatarg val)
+{
+ t_Bucket *x;
+ int i, nbucks = (int)val;
+ t_float *bucks;
+ t_outlet **outs;
+ if (nbucks < 1)
+ nbucks = 1;
+ if (!(bucks = (t_float *)getbytes(nbucks * sizeof(*bucks))))
+ return (0);
+ if (!(outs = (t_outlet **)getbytes(nbucks * sizeof(*outs))))
+ {
+ freebytes(bucks, nbucks * sizeof(*bucks));
+ return (0);
+ }
+ x = (t_Bucket *)pd_new(Bucket_class);
+ x->x_numbucks = nbucks;
+ x->x_bucks = bucks;
+ x->x_outs = outs;
+ x->x_frozen = 0;
+ x->x_dir = 0;
+ while (nbucks--) *outs++ = outlet_new((t_object *)x, &s_float);
+ return (x);
+}
+
+void Bucket_setup(void)
+{
+ Bucket_class = class_new(gensym("Bucket"),
+ (t_newmethod)Bucket_new,
+ (t_method)Bucket_free,
+ sizeof(t_Bucket), 0, A_DEFFLOAT, 0);
+ class_addbang(Bucket_class, Bucket_bang);
+ class_addfloat(Bucket_class, Bucket_float);
+ class_addmethod(Bucket_class, (t_method)Bucket_freeze, gensym("freeze"), 0);
+ class_addmethod(Bucket_class, (t_method)Bucket_thaw, gensym("thaw"), 0);
+ class_addmethod(Bucket_class, (t_method)Bucket_ltor, gensym("L2R"), 0);
+ class_addmethod(Bucket_class, (t_method)Bucket_rtol, gensym("R2L"), 0);
+ /* CHECKED (refman error) roll has no argument */
+ class_addmethod(Bucket_class, (t_method)Bucket_roll, gensym("roll"), 0);
+ /* 3.5 additions */
+ class_addmethod(Bucket_class, (t_method)Bucket_set,
+ gensym("set"), A_FLOAT, 0);
+ class_addmethod(Bucket_class, (t_method)Bucket_ltor, gensym("l2r"), 0);
+ class_addmethod(Bucket_class, (t_method)Bucket_rtol, gensym("r2l"), 0);
+}
diff --git a/cyclone/hammer/Clip.c b/cyclone/hammer/Clip.c
new file mode 100644
index 0000000..a06d3a8
--- /dev/null
+++ b/cyclone/hammer/Clip.c
@@ -0,0 +1,149 @@
+/* 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"
+
+#define CLIP_INISIZE 32 /* LATER rethink */
+#define CLIP_MAXSIZE 256
+
+typedef struct _clip
+{
+ t_object x_ob;
+ float x_f1;
+ float x_f2;
+ int x_size; /* as allocated */
+ t_atom *x_message;
+ t_atom x_messini[CLIP_INISIZE];
+ int x_entered;
+} t_clip;
+
+static t_class *clip_class;
+
+/* CHECKED case of f1 > f2: x <= f2 => f1, x > f2 => f2
+ (Pd implementation of clip has it the other way around) */
+static void clip_float(t_clip *x, t_float f)
+{
+ outlet_float(((t_object *)x)->ob_outlet,
+ (f > x->x_f2 ? x->x_f2 : (f < x->x_f1 ? x->x_f1 : f)));
+}
+
+static void clip_list(t_clip *x, t_symbol *s, int ac, t_atom *av)
+{
+ if (ac)
+ {
+ int docopy = 0;
+ int i;
+ t_atom *ap;
+ t_float f1 = x->x_f1;
+ t_float f2 = x->x_f2;
+ for (i = 0, ap = av; i < ac; i++, ap++)
+ {
+ t_float f;
+ if (ap->a_type == A_FLOAT)
+ f = ap->a_w.w_float;
+ else
+ {
+ docopy = 1;
+ /* CHECKED: symbols inside lists are converted to zeros */
+ f = 0;
+ }
+ if (f < f1 || f > f2) docopy = 1;
+ }
+ if (docopy)
+ {
+ t_atom *buf;
+ t_atom *bp;
+ int reentered = x->x_entered;
+ int prealloc = !reentered;
+ x->x_entered = 1;
+ if (prealloc && ac > x->x_size)
+ {
+ if (ac > CLIP_MAXSIZE)
+ prealloc = 0;
+ else
+ x->x_message = grow_nodata(&ac, &x->x_size, x->x_message,
+ CLIP_INISIZE, x->x_messini,
+ sizeof(*x->x_message));
+ }
+ if (prealloc) buf = x->x_message;
+ else
+ /* LATER consider using the stack if ntotal <= MAXSTACK */
+ buf = getbytes(ac * sizeof(*buf));
+ if (buf)
+ {
+ for (i = 0, ap = av, bp = buf; i < ac; i++, ap++, bp++)
+ {
+ t_float f = (ap->a_type == A_FLOAT ? ap->a_w.w_float : 0);
+ if (f < f1)
+ f = f1;
+ else if (f > f2)
+ f = f2;
+ SETFLOAT(bp, f);
+ }
+ outlet_list(((t_object *)x)->ob_outlet, &s_list, ac, buf);
+ if (buf != x->x_message)
+ freebytes(buf, ac * sizeof(*buf));
+ }
+ if (!reentered)
+ {
+ x->x_entered = 0;
+ }
+ }
+ else outlet_list(((t_object *)x)->ob_outlet, &s_list, ac, av);
+ }
+}
+
+static void clip_set(t_clip *x, t_symbol *s, int ac, t_atom *av)
+{
+ x->x_f1 = 0;
+ x->x_f2 = 0;
+ if (ac) /* CHECKED: 'set' without arguments sets both values to 0 */
+ {
+ if (av->a_type == A_FLOAT) /* CHECKED: symbol is converted to 0 */
+ x->x_f1 = av->a_w.w_float;
+ av++;
+ if (--ac)
+ {
+ if (av->a_type == A_FLOAT)
+ x->x_f2 = av->a_w.w_float;
+ }
+ else x->x_f2 = x->x_f1; /* CHECKED */
+ }
+}
+
+static void clip_free(t_clip *x)
+{
+ if (x->x_message != x->x_messini)
+ freebytes(x->x_message, x->x_size * sizeof(*x->x_message));
+}
+
+static void *clip_new(t_symbol *s, int ac, t_atom *av)
+{
+ t_clip *x = (t_clip *)pd_new(clip_class);
+ x->x_f1 = 0;
+ x->x_f2 = 0;
+ x->x_size = CLIP_INISIZE;
+ x->x_message = x->x_messini;
+ x->x_entered = 0;
+ floatinlet_new((t_object *)x, &x->x_f1);
+ floatinlet_new((t_object *)x, &x->x_f2);
+ outlet_new(&x->x_ob, &s_anything);
+ clip_set(x, 0, ac, av);
+ return (x);
+}
+
+void Clip_setup(void)
+{
+ clip_class = class_new(gensym("Clip"),
+ (t_newmethod)clip_new,
+ (t_method)clip_free,
+ sizeof(t_clip), 0,
+ A_GIMME, 0);
+ class_addfloat(clip_class, clip_float);
+ class_addlist(clip_class, clip_list);
+ class_addmethod(clip_class, (t_method)clip_set,
+ gensym("set"), A_GIMME, 0);
+}
diff --git a/cyclone/hammer/Decode.c b/cyclone/hammer/Decode.c
new file mode 100644
index 0000000..8317d7e
--- /dev/null
+++ b/cyclone/hammer/Decode.c
@@ -0,0 +1,110 @@
+/* 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. */
+
+/* This is an entirely rewritten version of Joseph A. Sarlo's code.
+ The most important changes are listed in "pd-lib-notes.txt" file. */
+
+#include "m_pd.h"
+#include "common/loud.h"
+
+#define DECODE_MAXOUTS 8 /* CHECKED (does it make any sense?) */
+#define DECODE_DEFOUTS 1
+
+typedef struct _Decode
+{
+ t_object x_ob;
+ int x_numouts;
+ int x_onout;
+ int x_allon; /* submaster switch */
+ int x_alloff; /* master switch */
+ t_outlet **x_outs;
+ t_outlet *x_outbuf[DECODE_MAXOUTS];
+} t_Decode;
+
+static t_class *Decode_class;
+
+/* CHECKED: all outlets deliver after any action */
+/* CHECKED: outlets output in right-to-left order */
+
+static void Decode_deliver(t_Decode *x)
+{
+ int i = x->x_numouts;
+ if (x->x_alloff)
+ while (i--) outlet_float(x->x_outs[i], 0);
+ else if (x->x_allon)
+ while (i--) outlet_float(x->x_outs[i], 1);
+ else
+ while (i--) outlet_float(x->x_outs[i], (i == x->x_onout ? 1 : 0));
+}
+
+static void Decode_float(t_Decode *x, t_floatarg f)
+{
+ int val = (int)f;
+ /* CHECKED: out-of-range input is clipped, not ignored */
+ if (val < 0)
+ val = 0;
+ else if (val >= x->x_numouts)
+ val = x->x_numouts - 1;
+ /* CHECKED: while in all-off mode, input is stored, not ignored */
+ x->x_onout = val;
+ Decode_deliver(x);
+}
+
+static void Decode_allon(t_Decode *x, t_floatarg f)
+{
+ x->x_allon = (f != 0);
+ Decode_deliver(x);
+}
+
+static void Decode_alloff(t_Decode *x, t_floatarg f)
+{
+ x->x_alloff = (f != 0);
+ Decode_deliver(x);
+}
+
+static void Decode_free(t_Decode *x)
+{
+ if (x->x_outs != x->x_outbuf)
+ freebytes(x->x_outs, x->x_numouts * sizeof(*x->x_outs));
+}
+
+static void *Decode_new(t_floatarg val)
+{
+ t_Decode *x;
+ int i, nouts = (int)val;
+ t_outlet **outs;
+ if (nouts < 1)
+ nouts = DECODE_DEFOUTS;
+ if (nouts > DECODE_MAXOUTS)
+ {
+ loud_incompatible_max(Decode_class, DECODE_MAXOUTS, "outlets");
+ if (!(outs = (t_outlet **)getbytes(nouts * sizeof(*outs))))
+ return (0);
+ }
+ else outs = 0;
+ x = (t_Decode *)pd_new(Decode_class);
+ x->x_numouts = nouts;
+ x->x_outs = (outs ? outs : x->x_outbuf);
+ x->x_onout = 0;
+ x->x_allon = 0;
+ x->x_alloff = 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"));
+ for (i = 0; i < nouts; i++)
+ x->x_outs[i] = outlet_new((t_object *)x, &s_float);
+ return (x);
+}
+
+void Decode_setup(void)
+{
+ Decode_class = class_new(gensym("Decode"),
+ (t_newmethod)Decode_new,
+ (t_method)Decode_free,
+ sizeof(t_Decode), 0, A_DEFFLOAT, 0);
+ class_addfloat(Decode_class, Decode_float);
+ class_addmethod(Decode_class, (t_method)Decode_allon,
+ gensym("ft1"), A_FLOAT, 0);
+ class_addmethod(Decode_class, (t_method)Decode_alloff,
+ gensym("ft2"), A_FLOAT, 0);
+}
diff --git a/cyclone/hammer/Histo.c b/cyclone/hammer/Histo.c
new file mode 100644
index 0000000..efb0deb
--- /dev/null
+++ b/cyclone/hammer/Histo.c
@@ -0,0 +1,103 @@
+/* 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. */
+
+/* This is an entirely rewritten version of Joseph A. Sarlo's code.
+ The most important changes are listed in "pd-lib-notes.txt" file. */
+
+#include "m_pd.h"
+#include "common/loud.h"
+
+#define HISTO_DEFSIZE 128
+
+typedef struct _Histo
+{
+ t_object x_ob;
+ int x_size;
+ unsigned *x_hist; /* LATER consider using 64 bits */
+ int x_lastinput;
+ t_outlet *x_countout;
+} t_Histo;
+
+static t_class *Histo_class;
+
+static void Histo_clear(t_Histo *x)
+{
+ int i = x->x_size;
+ while (i--) x->x_hist[i] = 0;
+ /* CHECKED: last input is kept */
+}
+
+static void Histo_doit(t_Histo *x, int val, int doincr)
+{
+ if (val >= 0 && val < x->x_size)
+ {
+ if (doincr)
+ {
+ /* CHECKED: only in-range numbers are stored */
+ x->x_lastinput = val;
+ x->x_hist[val]++;
+ }
+ outlet_float(x->x_countout, x->x_hist[val]);
+ /* CHECKED: out-of-range numbers are never passed thru */
+ outlet_float(((t_object *)x)->ob_outlet, val);
+ }
+}
+
+static void Histo_bang(t_Histo *x)
+{
+ Histo_doit(x, x->x_lastinput, 0);
+}
+
+static void Histo_float(t_Histo *x, t_floatarg f)
+{
+ int i;
+ if (loud_checkint((t_pd *)x, f, &i, &s_float)) /* CHECKED */
+ Histo_doit(x, i, 1);
+}
+
+static void Histo_ft1(t_Histo *x, t_floatarg f)
+{
+ /* CHECKED: floats are accepted in second inlet (truncated) */
+ Histo_doit(x, (int)f, 0);
+}
+
+static void Histo_free(t_Histo *x)
+{
+ if (x->x_hist)
+ freebytes(x->x_hist, x->x_size * sizeof(*x->x_hist));
+}
+
+static void *Histo_new(t_floatarg f)
+{
+ t_Histo *x;
+ int size = (int)f;
+ unsigned *hist;
+ if (size < 1) /* CHECKED: 1 is allowed */
+ size = HISTO_DEFSIZE;
+ if (!(hist = (unsigned *)getbytes(size * sizeof(*hist))))
+ return (0);
+ x = (t_Histo *)pd_new(Histo_class);
+ x->x_size = size;
+ x->x_hist = hist;
+ x->x_lastinput = 0;
+ inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft1"));
+ outlet_new((t_object *)x, &s_float);
+ x->x_countout = outlet_new((t_object *)x, &s_float);
+ Histo_clear(x);
+ return (x);
+}
+
+void Histo_setup(void)
+{
+ Histo_class = class_new(gensym("Histo"),
+ (t_newmethod)Histo_new,
+ (t_method)Histo_free,
+ sizeof(t_Histo), 0, A_DEFFLOAT, 0);
+ class_addbang(Histo_class, Histo_bang);
+ class_addfloat(Histo_class, Histo_float);
+ class_addmethod(Histo_class, (t_method)Histo_ft1,
+ gensym("ft1"), A_FLOAT, 0);
+ class_addmethod(Histo_class, (t_method)Histo_clear,
+ gensym("clear"), 0);
+}
diff --git a/cyclone/hammer/Makefile b/cyclone/hammer/Makefile
new file mode 100644
index 0000000..54383c3
--- /dev/null
+++ b/cyclone/hammer/Makefile
@@ -0,0 +1,3 @@
+ROOT_DIR = ../..
+redefault: allhammers.c default
+include $(ROOT_DIR)/Makefile.common
diff --git a/cyclone/hammer/Makefile.objects b/cyclone/hammer/Makefile.objects
new file mode 100644
index 0000000..0ac0a87
--- /dev/null
+++ b/cyclone/hammer/Makefile.objects
@@ -0,0 +1,14 @@
+SHARED_OBJECTS = \
+unstable/fragile.o \
+common/loud.o \
+common/grow.o \
+common/rand.o \
+common/vefl.o \
+common/sq.o \
+common/bifi.o \
+common/mifi.o \
+common/binport.o \
+common/port.o \
+hammer/file.o \
+hammer/gui.o \
+hammer/tree.o
diff --git a/cyclone/hammer/Makefile.sources b/cyclone/hammer/Makefile.sources
new file mode 100644
index 0000000..5df97f5
--- /dev/null
+++ b/cyclone/hammer/Makefile.sources
@@ -0,0 +1,80 @@
+CX_SOURCES = \
+hammer.c
+
+OTHER_SOURCES = \
+allhammers.c \
+testmess.c \
+accum.c \
+acos.c \
+active.c \
+anal.c \
+Append.c \
+asin.c \
+bangbang.c \
+bondo.c \
+Borax.c \
+Bucket.c \
+buddy.c \
+capture.c \
+cartopol.c \
+Clip.c \
+coll.c \
+comment.c \
+cosh.c \
+counter.c \
+cycle.c \
+decide.c \
+Decode.c \
+drunk.c \
+flush.c \
+forward.c \
+fromsymbol.c \
+funbuff.c \
+funnel.c \
+gate.c \
+grab.c \
+Histo.c \
+iter.c \
+match.c \
+maximum.c \
+mean.c \
+midiflush.c \
+midiformat.c \
+midiparse.c \
+minimum.c \
+mousefilter.c \
+MouseState.c \
+next.c \
+offer.c \
+onebang.c \
+past.c \
+Peak.c \
+poltocar.c \
+prepend.c \
+prob.c \
+pv.c \
+seq.c \
+sinh.c \
+speedlim.c \
+spell.c \
+split.c \
+spray.c \
+sprintf.c \
+substitute.c \
+sustain.c \
+switch.c \
+tanh.c \
+thresh.c \
+TogEdge.c \
+tosymbol.c \
+Trough.c \
+universal.c \
+urn.c \
+Uzi.c \
+xbendin.c \
+xbendin2.c \
+xbendout.c \
+xbendout2.c \
+xnotein.c \
+xnoteout.c \
+zl.c
diff --git a/cyclone/hammer/MouseState.c b/cyclone/hammer/MouseState.c
new file mode 100644
index 0000000..3b831bf
--- /dev/null
+++ b/cyclone/hammer/MouseState.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 "m_pd.h"
+#include "hammer/gui.h"
+
+typedef struct _MouseState
+{
+ t_object x_ob;
+ int x_ispolling;
+ int x_wasbanged;
+ int x_waszeroed;
+ int x_hlast;
+ int x_vlast;
+ int x_hzero;
+ int x_vzero;
+ t_outlet *x_hposout;
+ t_outlet *x_vposout;
+ t_outlet *x_hdiffout;
+ t_outlet *x_vdiffout;
+} t_MouseState;
+
+static t_class *MouseState_class;
+
+static void MouseState_anything(t_MouseState *x,
+ t_symbol *s, int ac, t_atom *av)
+{
+ /* dummy method, filtering out those messages from gui,
+ which are not handled explicitly */
+}
+
+static void MouseState_doup(t_MouseState *x, t_floatarg f)
+{
+ outlet_float(((t_object *)x)->ob_outlet, ((int)f ? 0 : 1));
+}
+
+static void MouseState_dobang(t_MouseState *x, t_floatarg f1, t_floatarg f2)
+{
+ if (x->x_wasbanged)
+ {
+ int h = (int)f1, v = (int)f2;
+ outlet_float(x->x_vdiffout, v - x->x_vlast);
+ outlet_float(x->x_hdiffout, h - x->x_hlast);
+ outlet_float(x->x_vposout, v - x->x_vzero);
+ outlet_float(x->x_hposout, h - x->x_hzero);
+ x->x_hlast = h;
+ x->x_vlast = v;
+ x->x_wasbanged = 0;
+ }
+}
+
+static void MouseState_dozero(t_MouseState *x, t_floatarg f1, t_floatarg f2)
+{
+ if (x->x_waszeroed)
+ {
+ int h = (int)f1, v = (int)f2;
+ x->x_hzero = h;
+ x->x_vzero = v;
+ x->x_waszeroed = 0;
+ }
+}
+
+static void MouseState_dopoll(t_MouseState *x, t_floatarg f1, t_floatarg f2)
+{
+ if (x->x_ispolling)
+ {
+ x->x_wasbanged = 1;
+ MouseState_dobang(x, f1, f2);
+ }
+}
+
+static void MouseState_bang(t_MouseState *x)
+{
+ hammergui_mousexy(gensym("_bang"));
+ x->x_wasbanged = 1;
+}
+
+static void MouseState_poll(t_MouseState *x)
+{
+ if (!x->x_ispolling)
+ {
+ x->x_ispolling = 1;
+ hammergui_startpolling((t_pd *)x);
+ }
+}
+
+static void MouseState_nopoll(t_MouseState *x)
+{
+ if (x->x_ispolling)
+ {
+ x->x_ispolling = 0;
+ hammergui_stoppolling((t_pd *)x);
+ }
+}
+
+static void MouseState_zero(t_MouseState *x)
+{
+ hammergui_mousexy(gensym("_zero"));
+ x->x_waszeroed = 1;
+}
+
+static void MouseState_reset(t_MouseState *x)
+{
+ x->x_hzero = x->x_vzero = 0;
+}
+
+static void MouseState_free(t_MouseState *x)
+{
+ MouseState_nopoll(x);
+ hammergui_unbindmouse((t_pd *)x);
+}
+
+static void *MouseState_new(void)
+{
+ t_MouseState *x = (t_MouseState *)pd_new(MouseState_class);
+ x->x_ispolling = x->x_wasbanged = x->x_waszeroed = 0;
+ outlet_new((t_object *)x, &s_float);
+ x->x_hposout = outlet_new((t_object *)x, &s_float);
+ x->x_vposout = outlet_new((t_object *)x, &s_float);
+ x->x_hdiffout = outlet_new((t_object *)x, &s_float);
+ x->x_vdiffout = outlet_new((t_object *)x, &s_float);
+ hammergui_bindmouse((t_pd *)x);
+ hammergui_willpoll();
+ MouseState_reset(x);
+ return (x);
+}
+
+void MouseState_setup(void)
+{
+ MouseState_class = class_new(gensym("MouseState"),
+ (t_newmethod)MouseState_new,
+ (t_method)MouseState_free,
+ sizeof(t_MouseState), 0, 0);
+ class_addanything(MouseState_class, MouseState_anything);
+ class_addmethod(MouseState_class, (t_method)MouseState_doup,
+ gensym("_up"), A_FLOAT, 0);
+ class_addmethod(MouseState_class, (t_method)MouseState_dobang,
+ gensym("_bang"), A_FLOAT, A_FLOAT, 0);
+ class_addmethod(MouseState_class, (t_method)MouseState_dozero,
+ gensym("_zero"), A_FLOAT, A_FLOAT, 0);
+ class_addmethod(MouseState_class, (t_method)MouseState_dopoll,
+ gensym("_poll"), A_FLOAT, A_FLOAT, 0);
+ class_addbang(MouseState_class, MouseState_bang);
+ class_addmethod(MouseState_class, (t_method)MouseState_poll,
+ gensym("poll"), 0);
+ class_addmethod(MouseState_class, (t_method)MouseState_nopoll,
+ gensym("nopoll"), 0);
+ class_addmethod(MouseState_class, (t_method)MouseState_zero,
+ gensym("zero"), 0);
+ class_addmethod(MouseState_class, (t_method)MouseState_reset,
+ gensym("reset"), 0);
+}
diff --git a/cyclone/hammer/Peak.c b/cyclone/hammer/Peak.c
new file mode 100644
index 0000000..6f7e30c
--- /dev/null
+++ b/cyclone/hammer/Peak.c
@@ -0,0 +1,63 @@
+/* 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"
+
+#define PEAK_INITIAL 0
+
+typedef struct _Peak
+{
+ t_object x_ob;
+ t_float x_value;
+ t_outlet *x_out2;
+ t_outlet *x_out3;
+} t_Peak;
+
+static t_class *Peak_class;
+
+static void Peak_bang(t_Peak *x)
+{
+ outlet_float(((t_object *)x)->ob_outlet, x->x_value);
+}
+
+static void Peak_ft1(t_Peak *x, t_floatarg f)
+{
+ /* CHECKME loud_checkint */
+ outlet_float(x->x_out3, 0); /* CHECKME */
+ outlet_float(x->x_out2, 1);
+ outlet_float(((t_object *)x)->ob_outlet, x->x_value = f);
+}
+
+static void Peak_float(t_Peak *x, t_float f)
+{
+ /* CHECKME loud_checkint */
+ if (f > x->x_value) Peak_ft1(x, f);
+ else
+ {
+ outlet_float(x->x_out3, 1);
+ outlet_float(x->x_out2, 0);
+ }
+}
+
+static void *Peak_new(t_floatarg f)
+{
+ t_Peak *x = (t_Peak *)pd_new(Peak_class);
+ x->x_value = PEAK_INITIAL;
+ inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft1"));
+ outlet_new((t_object *)x, &s_float);
+ x->x_out2 = outlet_new((t_object *)x, &s_float);
+ x->x_out3 = outlet_new((t_object *)x, &s_float);
+ return (x);
+}
+
+void Peak_setup(void)
+{
+ Peak_class = class_new(gensym("Peak"),
+ (t_newmethod)Peak_new, 0,
+ sizeof(t_Peak), 0, 0);
+ class_addbang(Peak_class, Peak_bang);
+ class_addfloat(Peak_class, Peak_float);
+ class_addmethod(Peak_class, (t_method)Peak_ft1,
+ gensym("ft1"), A_FLOAT, 0);
+}
diff --git a/cyclone/hammer/TogEdge.c b/cyclone/hammer/TogEdge.c
new file mode 100644
index 0000000..79c26ec
--- /dev/null
+++ b/cyclone/hammer/TogEdge.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 "m_pd.h"
+#include "common/loud.h"
+
+typedef struct _TogEdge
+{
+ t_object x_ob;
+ int x_wason;
+ t_outlet *x_out1;
+} t_TogEdge;
+
+static t_class *TogEdge_class;
+
+static void TogEdge_bang(t_TogEdge *x)
+{
+ if (x->x_wason)
+ {
+ x->x_wason = 0;
+ outlet_bang(x->x_out1);
+ }
+ else
+ {
+ x->x_wason = 1;
+ outlet_bang(((t_object *)x)->ob_outlet);
+ }
+}
+
+static void TogEdge_float(t_TogEdge *x, t_float f)
+{
+ int i;
+ if (loud_checkint((t_pd *)x, f, &i, &s_float)) /* CHECKED */
+ {
+ if (x->x_wason)
+ {
+ if (!i)
+ {
+ x->x_wason = 0;
+ outlet_bang(x->x_out1);
+ }
+ }
+ else
+ {
+ if (i)
+ {
+ x->x_wason = 1;
+ outlet_bang(((t_object *)x)->ob_outlet);
+ }
+ }
+ }
+}
+
+static void *TogEdge_new(void)
+{
+ t_TogEdge *x = (t_TogEdge *)pd_new(TogEdge_class);
+ x->x_wason = 0; /* CHECKED */
+ outlet_new((t_object *)x, &s_bang);
+ x->x_out1 = outlet_new((t_object *)x, &s_bang);
+ return (x);
+}
+
+void TogEdge_setup(void)
+{
+ TogEdge_class = class_new(gensym("TogEdge"),
+ (t_newmethod)TogEdge_new, 0,
+ sizeof(t_TogEdge), 0, 0);
+ class_addbang(TogEdge_class, TogEdge_bang);
+ class_addfloat(TogEdge_class, TogEdge_float);
+}
diff --git a/cyclone/hammer/Trough.c b/cyclone/hammer/Trough.c
new file mode 100644
index 0000000..27b19ba
--- /dev/null
+++ b/cyclone/hammer/Trough.c
@@ -0,0 +1,63 @@
+/* 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"
+
+#define TROUGH_INITIAL 128 /* CHECKME */
+
+typedef struct _Trough
+{
+ t_object x_ob;
+ t_float x_value;
+ t_outlet *x_out2;
+ t_outlet *x_out3;
+} t_Trough;
+
+static t_class *Trough_class;
+
+static void Trough_bang(t_Trough *x)
+{
+ outlet_float(((t_object *)x)->ob_outlet, x->x_value);
+}
+
+static void Trough_ft1(t_Trough *x, t_floatarg f)
+{
+ /* CHECKME loud_checkint */
+ outlet_float(x->x_out3, 0); /* CHECKME */
+ outlet_float(x->x_out2, 1);
+ outlet_float(((t_object *)x)->ob_outlet, x->x_value = f);
+}
+
+static void Trough_float(t_Trough *x, t_float f)
+{
+ /* CHECKME loud_checkint */
+ if (f < x->x_value) Trough_ft1(x, f);
+ else
+ {
+ outlet_float(x->x_out3, 1);
+ outlet_float(x->x_out2, 0);
+ }
+}
+
+static void *Trough_new(t_floatarg f)
+{
+ t_Trough *x = (t_Trough *)pd_new(Trough_class);
+ x->x_value = TROUGH_INITIAL;
+ inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft1"));
+ outlet_new((t_object *)x, &s_float);
+ x->x_out2 = outlet_new((t_object *)x, &s_float);
+ x->x_out3 = outlet_new((t_object *)x, &s_float);
+ return (x);
+}
+
+void Trough_setup(void)
+{
+ Trough_class = class_new(gensym("Trough"),
+ (t_newmethod)Trough_new, 0,
+ sizeof(t_Trough), 0, 0);
+ class_addbang(Trough_class, Trough_bang);
+ class_addfloat(Trough_class, Trough_float);
+ class_addmethod(Trough_class, (t_method)Trough_ft1,
+ gensym("ft1"), A_FLOAT, 0);
+}
diff --git a/cyclone/hammer/Uzi.c b/cyclone/hammer/Uzi.c
new file mode 100644
index 0000000..c773c6b
--- /dev/null
+++ b/cyclone/hammer/Uzi.c
@@ -0,0 +1,108 @@
+/* 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 negative 'nbangs' value set during run-time */
+
+#include "m_pd.h"
+
+typedef struct _Uzi
+{
+ t_object x_obj;
+ t_float x_nbangs;
+ int x_count;
+ int x_running;
+ t_outlet *x_out2;
+ t_outlet *x_out3;
+} t_Uzi;
+
+static t_class *Uzi_class;
+
+#define UZI_RUNNING 1
+#define UZI_PAUSED 2
+
+static void Uzi_dobang(t_Uzi *x)
+{
+ /* CHECKME reentrancy */
+ if (!x->x_running)
+ {
+ int count, nbangs = (int)x->x_nbangs;
+ x->x_running = UZI_RUNNING;
+ for (count = x->x_count + 1; count <= nbangs; count++)
+ {
+ outlet_float(x->x_out3, count);
+ outlet_bang(((t_object *)x)->ob_outlet);
+ if (x->x_running == UZI_PAUSED)
+ {
+ /* CHECKED: carry bang not sent, even if this is last bang */
+ x->x_count = count;
+ return;
+ }
+ }
+ /* CHECKED: carry bang sent also when there are no left-outlet bangs */
+ /* CHECKED: sent after left outlet, not before */
+ outlet_bang(x->x_out2);
+ x->x_count = 0;
+ x->x_running = 0;
+ }
+}
+
+static void Uzi_bang(t_Uzi *x)
+{
+ /* CHECKED: always restarts (when paused too) */
+ x->x_count = 0;
+ x->x_running = 0;
+ Uzi_dobang(x);
+}
+
+static void Uzi_float(t_Uzi *x, t_float f)
+{
+ /* CHECKED: always sets a new value and restarts (when paused too) */
+ x->x_nbangs = f;
+ Uzi_bang(x);
+}
+
+/* CHECKED: 'pause, resume' (but not just 'resume')
+ sends a carry bang when not running (a bug?) */
+static void Uzi_pause(t_Uzi *x)
+{
+ if (!x->x_running)
+ x->x_count = (int)x->x_nbangs; /* bug emulation? */
+ x->x_running = UZI_PAUSED;
+}
+
+static void Uzi_resume(t_Uzi *x)
+{
+ if (x->x_running == UZI_PAUSED)
+ {
+ x->x_running = 0;
+ Uzi_dobang(x);
+ }
+}
+
+static void *Uzi_new(t_floatarg f)
+{
+ t_Uzi *x = (t_Uzi *)pd_new(Uzi_class);
+ x->x_nbangs = (f > 1. ? f : 1.);
+ x->x_count = 0;
+ x->x_running = 0;
+ /* CHECKED: set when paused, but then 'resume' is blocked (a bug?) */
+ floatinlet_new((t_object *)x, &x->x_nbangs);
+ outlet_new((t_object *)x, &s_bang);
+ x->x_out2 = outlet_new((t_object *)x, &s_bang);
+ x->x_out3 = outlet_new((t_object *)x, &s_float);
+ return (x);
+}
+
+void Uzi_setup(void)
+{
+ Uzi_class = class_new(gensym("Uzi"),
+ (t_newmethod)Uzi_new, 0,
+ sizeof(t_Uzi), 0, A_DEFFLOAT, 0);
+ class_addbang(Uzi_class, Uzi_bang);
+ class_addfloat(Uzi_class, Uzi_float);
+ class_addmethod(Uzi_class, (t_method)Uzi_pause, gensym("pause"), 0);
+ class_addmethod(Uzi_class, (t_method)Uzi_pause, gensym("break"), 0);
+ class_addmethod(Uzi_class, (t_method)Uzi_resume, gensym("resume"), 0);
+ class_addmethod(Uzi_class, (t_method)Uzi_resume, gensym("continue"), 0);
+}
diff --git a/cyclone/hammer/accum.c b/cyclone/hammer/accum.c
new file mode 100644
index 0000000..d266fb3
--- /dev/null
+++ b/cyclone/hammer/accum.c
@@ -0,0 +1,68 @@
+/* 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. */
+
+/* This is a slightly edited version of Joseph A. Sarlo's code.
+ The most important changes are listed in "pd-lib-notes.txt" file. */
+
+#include "m_pd.h"
+
+typedef struct _accum
+{
+ t_object x_ob;
+ t_float x_total;
+} t_accum;
+
+static t_class *accum_class;
+
+static void accum_set(t_accum *x, t_floatarg val)
+{
+ x->x_total = val;
+}
+
+static void accum_bang(t_accum *x)
+{
+ outlet_float(((t_object *)x)->ob_outlet, x->x_total);
+}
+
+static void accum_float(t_accum *x, t_floatarg val)
+{
+ /* LATER reconsider int/float dilemma */
+ accum_set(x, val);
+ accum_bang(x);
+}
+
+static void accum_add(t_accum *x, t_floatarg val)
+{
+ /* LATER reconsider int/float dilemma */
+ x->x_total += val;
+}
+
+static void accum_mult(t_accum *x, t_floatarg val)
+{
+ x->x_total *= val;
+}
+
+static void *accum_new(t_floatarg val)
+{
+ t_accum *x = (t_accum *)pd_new(accum_class);
+ x->x_total = val;
+ 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);
+ return (x);
+}
+
+void accum_setup(void)
+{
+ accum_class = class_new(gensym("accum"), (t_newmethod)accum_new, 0,
+ sizeof(t_accum), 0, A_DEFFLOAT, 0);
+ class_addbang(accum_class, accum_bang);
+ class_addfloat(accum_class, accum_float);
+ class_addmethod(accum_class, (t_method)accum_add,
+ gensym("ft1"), A_FLOAT, 0);
+ class_addmethod(accum_class, (t_method)accum_mult,
+ gensym("ft2"), A_FLOAT, 0);
+ class_addmethod(accum_class, (t_method)accum_set,
+ gensym("set"), A_FLOAT, 0);
+}
diff --git a/cyclone/hammer/acos.c b/cyclone/hammer/acos.c
new file mode 100644
index 0000000..3f3abea
--- /dev/null
+++ b/cyclone/hammer/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"
+
+#if defined(NT) || defined(MACOSX)
+/* cf pd/src/x_arithmetic.c */
+#define acosf acos
+#endif
+
+typedef struct _acos
+{
+ t_object x_ob;
+ float x_value;
+} t_acos;
+
+static t_class *acos_class;
+
+static void acos_bang(t_acos *x)
+{
+ outlet_float(((t_object *)x)->ob_outlet, x->x_value);
+}
+
+static void acos_float(t_acos *x, t_float f)
+{
+ if (f < -1.0) f = -1.0; else if (f > 1.0) f = 1.0; /* CHECKME */
+ outlet_float(((t_object *)x)->ob_outlet, x->x_value = acosf(f));
+}
+
+static void *acos_new(t_floatarg f)
+{
+ t_acos *x = (t_acos *)pd_new(acos_class);
+ if (f < -1.0) f = -1.0; else if (f > 1.0) f = 1.0; /* CHECKME */
+ x->x_value = acosf(f);
+ outlet_new((t_object *)x, &s_float);
+ return (x);
+}
+
+void acos_setup(void)
+{
+ acos_class = class_new(gensym("acos"),
+ (t_newmethod)acos_new, 0,
+ sizeof(t_acos), 0, A_DEFFLOAT, 0);
+ class_addbang(acos_class, acos_bang);
+ class_addfloat(acos_class, acos_float);
+}
diff --git a/cyclone/hammer/active.c b/cyclone/hammer/active.c
new file mode 100644
index 0000000..9d10f80
--- /dev/null
+++ b/cyclone/hammer/active.c
@@ -0,0 +1,55 @@
+/* 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 "hammer/gui.h"
+
+typedef struct _active
+{
+ t_object x_ob;
+ t_symbol *x_cvname;
+ int x_on;
+} t_active;
+
+static t_class *active_class;
+
+static void active_dofocus(t_active *x, t_symbol *s, t_floatarg f)
+{
+ if ((int)f)
+ {
+ int on = (s == x->x_cvname);
+ if (on != x->x_on)
+ outlet_float(((t_object *)x)->ob_outlet, x->x_on = on);
+ }
+ else if (x->x_on && s == x->x_cvname)
+ outlet_float(((t_object *)x)->ob_outlet, x->x_on = 0);
+}
+
+static void active_free(t_active *x)
+{
+ hammergui_unbindfocus((t_pd *)x);
+}
+
+static void *active_new(void)
+{
+ t_active *x = (t_active *)pd_new(active_class);
+ char buf[32];
+ sprintf(buf, ".x%x.c", (int)canvas_getcurrent());
+ x->x_cvname = gensym(buf);
+ x->x_on = 0;
+ outlet_new((t_object *)x, &s_float);
+ hammergui_bindfocus((t_pd *)x);
+ return (x);
+}
+
+void active_setup(void)
+{
+ active_class = class_new(gensym("active"),
+ (t_newmethod)active_new,
+ (t_method)active_free,
+ sizeof(t_active), CLASS_NOINLET, 0);
+ class_addmethod(active_class, (t_method)active_dofocus,
+ gensym("_focus"), A_SYMBOL, A_FLOAT, 0);
+}
diff --git a/cyclone/hammer/allhammers.c b/cyclone/hammer/allhammers.c
new file mode 100644
index 0000000..e6d8235
--- /dev/null
+++ b/cyclone/hammer/allhammers.c
@@ -0,0 +1,160 @@
+// 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 accum_setup(void);
+void acos_setup(void);
+void active_setup(void);
+void anal_setup(void);
+void Append_setup(void);
+void asin_setup(void);
+void bangbang_setup(void);
+void bondo_setup(void);
+void Borax_setup(void);
+void Bucket_setup(void);
+void buddy_setup(void);
+void capture_setup(void);
+void cartopol_setup(void);
+void Clip_setup(void);
+void coll_setup(void);
+void comment_setup(void);
+void cosh_setup(void);
+void counter_setup(void);
+void cycle_setup(void);
+void decide_setup(void);
+void Decode_setup(void);
+void drunk_setup(void);
+void flush_setup(void);
+void forward_setup(void);
+void fromsymbol_setup(void);
+void funbuff_setup(void);
+void funnel_setup(void);
+void gate_setup(void);
+void grab_setup(void);
+void Histo_setup(void);
+void iter_setup(void);
+void match_setup(void);
+void maximum_setup(void);
+void mean_setup(void);
+void midiflush_setup(void);
+void midiformat_setup(void);
+void midiparse_setup(void);
+void minimum_setup(void);
+void mousefilter_setup(void);
+void MouseState_setup(void);
+void next_setup(void);
+void offer_setup(void);
+void onebang_setup(void);
+void past_setup(void);
+void Peak_setup(void);
+void poltocar_setup(void);
+void prepend_setup(void);
+void prob_setup(void);
+void pv_setup(void);
+void seq_setup(void);
+void sinh_setup(void);
+void speedlim_setup(void);
+void spell_setup(void);
+void split_setup(void);
+void spray_setup(void);
+void sprintf_setup(void);
+void substitute_setup(void);
+void sustain_setup(void);
+void switch_setup(void);
+void tanh_setup(void);
+void testmess_setup(void);
+void thresh_setup(void);
+void TogEdge_setup(void);
+void tosymbol_setup(void);
+void Trough_setup(void);
+void universal_setup(void);
+void urn_setup(void);
+void Uzi_setup(void);
+void xbendin2_setup(void);
+void xbendin_setup(void);
+void xbendout2_setup(void);
+void xbendout_setup(void);
+void xnotein_setup(void);
+void xnoteout_setup(void);
+void zl_setup(void);
+
+void allhammers_setup(void)
+{
+ accum_setup();
+ acos_setup();
+ active_setup();
+ anal_setup();
+ Append_setup();
+ asin_setup();
+ bangbang_setup();
+ bondo_setup();
+ Borax_setup();
+ Bucket_setup();
+ buddy_setup();
+ capture_setup();
+ cartopol_setup();
+ Clip_setup();
+ coll_setup();
+ comment_setup();
+ cosh_setup();
+ counter_setup();
+ cycle_setup();
+ decide_setup();
+ Decode_setup();
+ drunk_setup();
+ flush_setup();
+ forward_setup();
+ fromsymbol_setup();
+ funbuff_setup();
+ funnel_setup();
+ gate_setup();
+ grab_setup();
+ Histo_setup();
+ iter_setup();
+ match_setup();
+ maximum_setup();
+ mean_setup();
+ midiflush_setup();
+ midiformat_setup();
+ midiparse_setup();
+ minimum_setup();
+ mousefilter_setup();
+ MouseState_setup();
+ next_setup();
+ offer_setup();
+ onebang_setup();
+ past_setup();
+ Peak_setup();
+ poltocar_setup();
+ prepend_setup();
+ prob_setup();
+ pv_setup();
+ seq_setup();
+ sinh_setup();
+ speedlim_setup();
+ spell_setup();
+ split_setup();
+ spray_setup();
+ sprintf_setup();
+ substitute_setup();
+ sustain_setup();
+ switch_setup();
+ tanh_setup();
+ testmess_setup();
+ thresh_setup();
+ TogEdge_setup();
+ tosymbol_setup();
+ Trough_setup();
+ universal_setup();
+ urn_setup();
+ Uzi_setup();
+ xbendin2_setup();
+ xbendin_setup();
+ xbendout2_setup();
+ xbendout_setup();
+ xnotein_setup();
+ xnoteout_setup();
+ zl_setup();
+}
diff --git a/cyclone/hammer/anal.c b/cyclone/hammer/anal.c
new file mode 100644
index 0000000..477eb20
--- /dev/null
+++ b/cyclone/hammer/anal.c
@@ -0,0 +1,108 @@
+/* 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/loud.h"
+
+#define ANAL_DEFSIZE 128
+#define ANAL_MAXSIZE 1024
+
+typedef struct _anal
+{
+ t_object x_ob;
+ int x_value; /* negative, if initialized or reset */
+ int x_size;
+ int x_bytesize;
+ int *x_table;
+ /* CHECKED: the 'weight' count is a signed short (2 bytes),
+ wrapping into negative domain without any warning.
+ LATER consider complaining at == SHRT_MAX. */
+} t_anal;
+
+static t_class *anal_class;
+
+static void anal_reset(t_anal *x)
+{
+ x->x_value = -1;
+}
+
+static void anal_clear(t_anal *x)
+{
+ memset(x->x_table, 0, x->x_bytesize);
+}
+
+static void anal_float(t_anal *x, t_float f)
+{
+ int value;
+ if (loud_checkint((t_pd *)x, f, &value, &s_float)) /* CHECKED */
+ {
+ /* CHECKED: any input negative or >= size is ignored with an error
+ -- there is no output, and a previous state is kept. */
+ if (value >= 0 && value < x->x_size)
+ {
+ if (x->x_value >= 0)
+ {
+ t_atom at[3];
+ int ndx = x->x_value * x->x_size + value;
+ x->x_table[ndx]++;
+ SETFLOAT(at, x->x_value);
+ SETFLOAT(&at[1], value);
+ SETFLOAT(&at[2], x->x_table[ndx]);
+ outlet_list(((t_object *)x)->ob_outlet, &s_list, 3, at);
+ }
+ x->x_value = value;
+ }
+ else loud_error((t_pd *)x, "%d outside of table bounds", value);
+ }
+}
+
+static void anal_free(t_anal *x)
+{
+ if (x->x_table)
+ freebytes(x->x_table, x->x_bytesize);
+}
+
+static void *anal_new(t_floatarg f)
+{
+ t_anal *x;
+ int size = (int)f;
+ int bytesize;
+ int *table;
+ if (size < 1)
+ /* CHECKED: 1 is allowed (such an object rejects any nonzero input) */
+ size = ANAL_DEFSIZE;
+ else if (size > ANAL_MAXSIZE)
+ {
+ /* CHECKED: */
+ loud_warning(&anal_class, "size too large, using %d", ANAL_MAXSIZE);
+ size = ANAL_MAXSIZE; /* LATER switch into a 'sparse' mode */
+ }
+ /* CHECKED: actually the bytesize is size * size * sizeof(short),
+ and it shows up in */
+ bytesize = size * size * sizeof(*table);
+ if (!(table = (int *)getbytes(bytesize)))
+ return (0);
+ x = (t_anal *)pd_new(anal_class);
+ x->x_size = size;
+ x->x_bytesize = bytesize;
+ x->x_table = table;
+ outlet_new((t_object *)x, &s_list);
+ anal_reset(x);
+ anal_clear(x);
+ return (x);
+}
+
+void anal_setup(void)
+{
+ anal_class = class_new(gensym("anal"),
+ (t_newmethod)anal_new,
+ (t_method)anal_free,
+ sizeof(t_anal), 0, A_DEFFLOAT, 0);
+ class_addfloat(anal_class, anal_float);
+ class_addmethod(anal_class, (t_method)anal_reset,
+ gensym("reset"), 0);
+ class_addmethod(anal_class, (t_method)anal_clear,
+ gensym("clear"), 0);
+}
diff --git a/cyclone/hammer/asin.c b/cyclone/hammer/asin.c
new file mode 100644
index 0000000..0aa8db7
--- /dev/null
+++ b/cyclone/hammer/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"
+
+#if defined(NT) || defined(MACOSX)
+/* cf pd/src/x_arithmetic.c */
+#define asinf asin
+#endif
+
+typedef struct _asin
+{
+ t_object x_ob;
+ float x_value;
+} t_asin;
+
+static t_class *asin_class;
+
+static void asin_bang(t_asin *x)
+{
+ outlet_float(((t_object *)x)->ob_outlet, x->x_value);
+}
+
+static void asin_float(t_asin *x, t_float f)
+{
+ if (f < -1.0) f = -1.0; else if (f > 1.0) f = 1.0; /* CHECKME */
+ outlet_float(((t_object *)x)->ob_outlet, x->x_value = asinf(f));
+}
+
+static void *asin_new(t_floatarg f)
+{
+ t_asin *x = (t_asin *)pd_new(asin_class);
+ if (f < -1.0) f = -1.0; else if (f > 1.0) f = 1.0; /* CHECKME */
+ x->x_value = asinf(f);
+ outlet_new((t_object *)x, &s_float);
+ return (x);
+}
+
+void asin_setup(void)
+{
+ asin_class = class_new(gensym("asin"),
+ (t_newmethod)asin_new, 0,
+ sizeof(t_asin), 0, A_DEFFLOAT, 0);
+ class_addbang(asin_class, asin_bang);
+ class_addfloat(asin_class, asin_float);
+}
diff --git a/cyclone/hammer/bangbang.c b/cyclone/hammer/bangbang.c
new file mode 100644
index 0000000..bebd26e
--- /dev/null
+++ b/cyclone/hammer/bangbang.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. */
+
+/* This is a modified version of Joseph A. Sarlo's code.
+ The most important changes are listed in "pd-lib-notes.txt" file. */
+
+#include "m_pd.h"
+#include "common/loud.h"
+
+#define BANGBANG_MINOUTS 1
+#define BANGBANG_MAXOUTS 40 /* CHECKED (just clipped without warning) */
+#define BANGBANG_DEFOUTS 2
+
+typedef struct _bangbang
+{
+ t_object x_ob;
+ int x_nouts;
+ t_outlet **x_outs;
+ t_outlet *x_outbuf[BANGBANG_DEFOUTS];
+} t_bangbang;
+
+static t_class *bangbang_class;
+
+static void bangbang_bang(t_bangbang *x)
+{
+ int i = x->x_nouts;
+ while (i--) outlet_bang(x->x_outs[i]);
+}
+
+static void bangbang_anything(t_bangbang *x, t_symbol *s, int ac, t_atom *av)
+{
+ bangbang_bang(x);
+}
+
+static void bangbang_free(t_bangbang *x)
+{
+ if (x->x_outs != x->x_outbuf)
+ freebytes(x->x_outs, x->x_nouts * sizeof(*x->x_outs));
+}
+
+static void *bangbang_new(t_floatarg val)
+{
+ t_bangbang *x;
+ int i, nouts = (int)val;
+ t_outlet **outs;
+ if (nouts < BANGBANG_MINOUTS)
+ nouts = BANGBANG_DEFOUTS;
+ if (nouts > BANGBANG_MAXOUTS)
+ loud_incompatible_max(bangbang_class, BANGBANG_MAXOUTS, "outlets");
+ if (nouts > BANGBANG_DEFOUTS)
+ {
+ if (!(outs = (t_outlet **)getbytes(nouts * sizeof(*outs))))
+ return (0);
+ }
+ else outs = 0;
+ x = (t_bangbang *)pd_new(bangbang_class);
+ x->x_nouts = nouts;
+ x->x_outs = (outs ? outs : x->x_outbuf);
+ for (i = 0; i < nouts; i++)
+ x->x_outs[i] = outlet_new((t_object *)x, &s_bang);
+ return (x);
+}
+
+void bangbang_setup(void)
+{
+ bangbang_class = class_new(gensym("bangbang"),
+ (t_newmethod)bangbang_new,
+ (t_method)bangbang_free,
+ sizeof(t_bangbang), 0, A_DEFFLOAT, 0);
+ class_addbang(bangbang_class, bangbang_bang);
+ class_addanything(bangbang_class, bangbang_anything);
+}
diff --git a/cyclone/hammer/bondo.c b/cyclone/hammer/bondo.c
new file mode 100644
index 0000000..2fcdce3
--- /dev/null
+++ b/cyclone/hammer/bondo.c
@@ -0,0 +1,394 @@
+/* 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 revisit buffer handling (maxsize, reentrancy) */
+/* LATER rethink handling of symbols */
+
+/* CHECKED: if 'n' argument is given, then store whole messages, instead of
+ distributing atoms across successive slots. This is a new, buddy-like
+ behaviour. */
+/* CHECKED: without 'n' argument, 'symbol test' is parsed as two symbol atoms,
+ but 'float 1' (or 'list 1') as a single float. */
+
+#include <string.h>
+#include "m_pd.h"
+#include "common/grow.h"
+
+#define BONDO_MINSLOTS 2
+#define BONDO_INISIZE 4 /* LATER rethink (useful only in multiatom mode) */
+
+typedef struct _bondo
+{
+ t_object x_ob;
+ t_float x_delay;
+ int x_multiatom;
+ int x_nslots;
+ int x_nproxies; /* as requested (and allocated) */
+ t_pd **x_proxies;
+ t_outlet **x_outs;
+ t_clock *x_clock;
+} t_bondo;
+
+typedef struct _bondo_proxy
+{
+ t_object p_ob;
+ t_bondo *p_master;
+ int p_id;
+ t_symbol *p_selector;
+ t_float p_float;
+ t_symbol *p_symbol;
+ t_gpointer *p_pointer;
+ int p_size; /* as allocated */
+ int p_natoms; /* as used */
+ t_atom *p_message;
+ t_atom p_messini[BONDO_INISIZE];
+} t_bondo_proxy;
+
+static t_class *bondo_class;
+static t_class *bondo_proxy_class;
+
+static void bondo_doit(t_bondo *x)
+{
+ t_bondo_proxy **p = (t_bondo_proxy **)x->x_proxies;
+ int i = x->x_nslots;
+ p = (t_bondo_proxy **)x->x_proxies;
+ i = x->x_nslots;
+ while (i--)
+ {
+ t_symbol *s = p[i]->p_selector;
+ /* LATER consider complaining about extra arguments (CHECKED) */
+ if (s == &s_bang)
+ outlet_bang(x->x_outs[i]);
+ else if (s == &s_float)
+ outlet_float(x->x_outs[i], p[i]->p_float);
+ else if (s == &s_symbol && p[i]->p_symbol)
+ {
+ /* LATER rethink */
+ if (x->x_multiatom)
+ outlet_symbol(x->x_outs[i], p[i]->p_symbol);
+ else
+ outlet_anything(x->x_outs[i], p[i]->p_symbol, 0, 0);
+ }
+ else if (s == &s_pointer)
+ {
+ /* LATER */
+ }
+ else if (s == &s_list)
+ outlet_list(x->x_outs[i], s, p[i]->p_natoms, p[i]->p_message);
+ else if (s) /* CHECKED: a slot may be inactive (in multiatom mode) */
+ outlet_anything(x->x_outs[i], s, p[i]->p_natoms, p[i]->p_message);
+ }
+}
+
+static void bondo_arm(t_bondo *x)
+{
+ if (x->x_delay <= 0) bondo_doit(x);
+ else clock_delay(x->x_clock, x->x_delay);
+}
+
+static void bondo_proxy_bang(t_bondo_proxy *x)
+{
+ bondo_arm(x->p_master); /* CHECKED: bang in any inlet works in this way */
+}
+
+static void bondo_proxy_dofloat(t_bondo_proxy *x, t_float f, int doit)
+{
+ x->p_selector = &s_float;
+ x->p_float = f;
+ x->p_natoms = 0; /* defensive */
+ if (doit) bondo_arm(x->p_master);
+}
+
+static void bondo_proxy_float(t_bondo_proxy *x, t_float f)
+{
+ bondo_proxy_dofloat(x, f, 1);
+}
+
+static void bondo_proxy_dosymbol(t_bondo_proxy *x, t_symbol *s, int doit)
+{
+ x->p_selector = &s_symbol;
+ x->p_symbol = s;
+ x->p_natoms = 0; /* defensive */
+ if (doit) bondo_arm(x->p_master);
+}
+
+static void bondo_proxy_symbol(t_bondo_proxy *x, t_symbol *s)
+{
+ bondo_proxy_dosymbol(x, s, 1);
+}
+
+static void bondo_proxy_dopointer(t_bondo_proxy *x, t_gpointer *gp, int doit)
+{
+ x->p_selector = &s_pointer;
+ x->p_pointer = gp;
+ x->p_natoms = 0; /* defensive */
+ if (doit) bondo_arm(x->p_master);
+}
+
+static void bondo_proxy_pointer(t_bondo_proxy *x, t_gpointer *gp)
+{
+ bondo_proxy_dopointer(x, gp, 1);
+}
+
+/* CHECKED: the slots fire in right-to-left order,
+ but they trigger only once (refman error) */
+static void bondo_distribute(t_bondo *x, int startid,
+ t_symbol *s, int ac, t_atom *av, int doit)
+{
+ t_atom *ap = av;
+ t_bondo_proxy **pp;
+ int id = startid + ac;
+ if (s) id++;
+ if (id > x->x_nslots)
+ id = x->x_nslots;
+ ap += id - startid;
+ pp = (t_bondo_proxy **)(x->x_proxies + id);
+ if (s) ap--;
+ while (ap-- > av)
+ {
+ pp--;
+ if (ap->a_type == A_FLOAT)
+ bondo_proxy_dofloat(*pp, ap->a_w.w_float, 0);
+ else if (ap->a_type == A_SYMBOL)
+ bondo_proxy_dosymbol(*pp, ap->a_w.w_symbol, 0);
+ else if (ap->a_type == A_POINTER)
+ bondo_proxy_dopointer(*pp, ap->a_w.w_gpointer, 0);
+ }
+ if (s)
+ bondo_proxy_dosymbol((t_bondo_proxy *)x->x_proxies[startid], s, 0);
+ if (doit) bondo_arm(x);
+}
+
+static void bondo_proxy_domultiatom(t_bondo_proxy *x,
+ int ac, t_atom *av, int doit)
+{
+ if (ac > x->p_size)
+ {
+ /* LATER consider using BONDO_MAXSIZE (and warning if exceeded) */
+ x->p_message = grow_nodata(&ac, &x->p_size, x->p_message,
+ BONDO_INISIZE, x->p_messini,
+ sizeof(*x->p_message));
+ }
+ x->p_natoms = ac;
+ memcpy(x->p_message, av, ac * sizeof(*x->p_message));
+ if (doit) bondo_arm(x->p_master);
+}
+
+static void bondo_proxy_dolist(t_bondo_proxy *x, int ac, t_atom *av, int doit)
+{
+ if (x->p_master->x_multiatom)
+ {
+ x->p_selector = &s_list;
+ bondo_proxy_domultiatom(x, ac, av, doit);
+ }
+ else bondo_distribute(x->p_master, x->p_id, 0, ac, av, doit);
+}
+
+static void bondo_proxy_list(t_bondo_proxy *x,
+ t_symbol *s, int ac, t_atom *av)
+{
+ bondo_proxy_dolist(x, ac, av, 1);
+}
+
+static void bondo_proxy_doanything(t_bondo_proxy *x,
+ t_symbol *s, int ac, t_atom *av, int doit)
+{
+ if (x->p_master->x_multiatom)
+ {
+ /* LATER rethink and CHECKME */
+ if (s == &s_symbol)
+ {
+ if (ac && av->a_type == A_SYMBOL)
+ bondo_proxy_dosymbol(x, av->a_w.w_symbol, doit);
+ else
+ bondo_proxy_dosymbol(x, &s_symbol, doit);
+ }
+ else
+ {
+ x->p_selector = s;
+ bondo_proxy_domultiatom(x, ac, av, doit);
+ }
+ }
+ else bondo_distribute(x->p_master, x->p_id, s, ac, av, doit);
+}
+
+static void bondo_proxy_anything(t_bondo_proxy *x,
+ t_symbol *s, int ac, t_atom *av)
+{
+ bondo_proxy_doanything(x, s, ac, av, 1);
+}
+
+static void bondo_proxy_set(t_bondo_proxy *x,
+ t_symbol *s, int ac, t_atom *av)
+{
+ if (ac)
+ {
+ if (av->a_type == A_FLOAT)
+ {
+ if (ac > 1)
+ bondo_proxy_dolist(x, ac, av, 0);
+ else
+ bondo_proxy_dofloat(x, av->a_w.w_float, 0);
+ }
+ else if (av->a_type == A_SYMBOL)
+ /* CHECKED: no tests for 'set float ...' and 'set list...' --
+ the parsing is made in an output routine */
+ bondo_proxy_doanything(x, av->a_w.w_symbol, ac-1, av+1, 0);
+ else if (av->a_type == A_POINTER)
+ bondo_proxy_dopointer(x, av->a_w.w_gpointer, 0);
+ }
+ /* CHECKED: 'set' without arguments makes a slot inactive,
+ if multiatom, but is ignored, if !multiatom */
+ else if (x->p_master->x_multiatom) x->p_selector = 0;
+}
+
+static void bondo_bang(t_bondo *x)
+{
+ bondo_proxy_bang((t_bondo_proxy *)x->x_proxies[0]);
+}
+
+static void bondo_float(t_bondo *x, t_float f)
+{
+ bondo_proxy_dofloat((t_bondo_proxy *)x->x_proxies[0], f, 1);
+}
+
+static void bondo_symbol(t_bondo *x, t_symbol *s)
+{
+ bondo_proxy_dosymbol((t_bondo_proxy *)x->x_proxies[0], s, 1);
+}
+
+static void bondo_pointer(t_bondo *x, t_gpointer *gp)
+{
+ bondo_proxy_dopointer((t_bondo_proxy *)x->x_proxies[0], gp, 1);
+}
+
+static void bondo_list(t_bondo *x, t_symbol *s, int ac, t_atom *av)
+{
+ bondo_proxy_dolist((t_bondo_proxy *)x->x_proxies[0], ac, av, 1);
+}
+
+static void bondo_anything(t_bondo *x, t_symbol *s, int ac, t_atom *av)
+{
+ bondo_proxy_doanything((t_bondo_proxy *)x->x_proxies[0], s, ac, av, 1);
+}
+
+static void bondo_set(t_bondo *x, t_symbol *s, int ac, t_atom *av)
+{
+ bondo_proxy_set((t_bondo_proxy *)x->x_proxies[0], s, ac, av);
+}
+
+static void bondo_free(t_bondo *x)
+{
+ if (x->x_clock) clock_free(x->x_clock);
+ if (x->x_proxies)
+ {
+ int i = x->x_nslots;
+ while (i--)
+ {
+ t_bondo_proxy *y = (t_bondo_proxy *)x->x_proxies[i];
+ if (y->p_message != y->p_messini)
+ freebytes(y->p_message, y->p_size * sizeof(*y->p_message));
+ pd_free((t_pd *)y);
+ }
+ freebytes(x->x_proxies, x->x_nproxies * sizeof(*x->x_proxies));
+ }
+ if (x->x_outs)
+ freebytes(x->x_outs, x->x_nslots * sizeof(*x->x_outs));
+}
+
+static void *bondo_new(t_symbol *s, int ac, t_atom *av)
+{
+ t_bondo *x;
+ int i, nslots, nproxies = BONDO_MINSLOTS;
+ int multiatom = 0;
+ t_float delay = 0;
+ t_pd **proxies;
+ t_outlet **outs;
+ i = 0;
+ while (ac--)
+ {
+ /* CHECKED: no warnings */
+ if (av->a_type == A_FLOAT)
+ {
+ if (i == 0)
+ nproxies = (int)av->a_w.w_float;
+ else if (i == 1)
+ delay = av->a_w.w_float;
+ i++;
+ }
+ else if (av->a_type == A_SYMBOL)
+ {
+ if (av->a_w.w_symbol == gensym("n")) multiatom = 1;
+ /* CHECKED: 'n' has to be the last argument given;
+ the arguments after any symbol are silently ignored --
+ LATER decide if we should comply and break here */
+ }
+ av++;
+ }
+ if (nproxies < BONDO_MINSLOTS)
+ nproxies = BONDO_MINSLOTS;
+ if (!(proxies = (t_pd **)getbytes(nproxies * sizeof(*proxies))))
+ return (0);
+ for (nslots = 0; nslots < nproxies; nslots++)
+ if (!(proxies[nslots] = pd_new(bondo_proxy_class))) break;
+ if (nslots < BONDO_MINSLOTS
+ || !(outs = (t_outlet **)getbytes(nslots * sizeof(*outs))))
+ {
+ i = nslots;
+ while (i--) pd_free(proxies[i]);
+ freebytes(proxies, nproxies * sizeof(*proxies));
+ return (0);
+ }
+ x = (t_bondo *)pd_new(bondo_class);
+ x->x_delay = delay;
+ x->x_multiatom = multiatom;
+ x->x_nslots = nslots;
+ x->x_nproxies = nproxies;
+ x->x_proxies = proxies;
+ x->x_outs = outs;
+ for (i = 0; i < nslots; i++)
+ {
+ t_bondo_proxy *y = (t_bondo_proxy *)proxies[i];
+ y->p_master = x;
+ y->p_id = i;
+ y->p_selector = &s_float; /* CHECKED: it is so in multiatom mode too */
+ y->p_float = 0;
+ y->p_symbol = 0;
+ y->p_pointer = 0;
+ y->p_size = BONDO_INISIZE;
+ y->p_natoms = 0;
+ y->p_message = y->p_messini;
+ if (i) inlet_new((t_object *)x, (t_pd *)y, 0, 0);
+ x->x_outs[i] = outlet_new((t_object *)x, &s_anything);
+ }
+ x->x_clock = clock_new(x, (t_method)bondo_doit);
+ return (x);
+}
+
+void bondo_setup(void)
+{
+ bondo_class = class_new(gensym("bondo"),
+ (t_newmethod)bondo_new,
+ (t_method)bondo_free,
+ sizeof(t_bondo), 0, A_GIMME, 0);
+ class_addbang(bondo_class, bondo_bang);
+ class_addfloat(bondo_class, bondo_float);
+ class_addsymbol(bondo_class, bondo_symbol);
+ class_addpointer(bondo_class, bondo_pointer);
+ class_addlist(bondo_class, bondo_list);
+ class_addanything(bondo_class, bondo_anything);
+ class_addmethod(bondo_class, (t_method)bondo_set,
+ gensym("set"), A_GIMME, 0);
+ bondo_proxy_class = class_new(gensym("_bondo_proxy"), 0, 0,
+ sizeof(t_bondo_proxy),
+ CLASS_PD | CLASS_NOINLET, 0);
+ class_addbang(bondo_proxy_class, bondo_proxy_bang);
+ class_addfloat(bondo_proxy_class, bondo_proxy_float);
+ class_addsymbol(bondo_proxy_class, bondo_proxy_symbol);
+ class_addpointer(bondo_proxy_class, bondo_proxy_pointer);
+ class_addlist(bondo_proxy_class, bondo_proxy_list);
+ class_addanything(bondo_proxy_class, bondo_proxy_anything);
+ class_addmethod(bondo_proxy_class, (t_method)bondo_proxy_set,
+ gensym("set"), A_GIMME, 0);
+}
diff --git a/cyclone/hammer/buddy.c b/cyclone/hammer/buddy.c
new file mode 100644
index 0000000..f272739
--- /dev/null
+++ b/cyclone/hammer/buddy.c
@@ -0,0 +1,253 @@
+/* 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 compare with buddy.c from max sdk */
+/* LATER revisit buffer handling (maxsize, reentrancy) */
+
+#include <string.h>
+#include "m_pd.h"
+#include "common/grow.h"
+
+#define BUDDY_MINSLOTS 2
+#define BUDDY_INISIZE 4 /* LATER rethink */
+
+typedef struct _buddy
+{
+ t_object x_ob;
+ int x_nslots;
+ int x_nproxies; /* as requested (and allocated) */
+ t_pd **x_proxies;
+ t_outlet **x_outs;
+} t_buddy;
+
+typedef struct _buddy_proxy
+{
+ t_object p_ob;
+ t_buddy *p_master;
+ t_symbol *p_selector;
+ t_float p_float;
+ t_symbol *p_symbol;
+ t_gpointer *p_pointer;
+ int p_size; /* as allocated */
+ int p_natoms; /* as used */
+ t_atom *p_message;
+ t_atom p_messini[BUDDY_INISIZE];
+} t_buddy_proxy;
+
+static t_class *buddy_class;
+static t_class *buddy_proxy_class;
+
+static void buddy_clear(t_buddy *x)
+{
+ t_buddy_proxy **p = (t_buddy_proxy **)x->x_proxies;
+ int i = x->x_nslots;
+ while (i--)
+ {
+ (*p)->p_selector = 0;
+ (*p++)->p_natoms = 0; /* defensive */
+ }
+}
+
+static void buddy_check(t_buddy *x)
+{
+ t_buddy_proxy **p = (t_buddy_proxy **)x->x_proxies;
+ int i = x->x_nslots;
+ while (i--)
+ if (!(*p++)->p_selector)
+ return;
+ p = (t_buddy_proxy **)x->x_proxies;
+ i = x->x_nslots;
+ while (i--)
+ {
+ t_symbol *s = p[i]->p_selector;
+ if (s == &s_bang)
+ outlet_bang(x->x_outs[i]);
+ else if (s == &s_float)
+ outlet_float(x->x_outs[i], p[i]->p_float);
+ else if (s == &s_symbol && p[i]->p_symbol)
+ outlet_symbol(x->x_outs[i], p[i]->p_symbol);
+ else if (s == &s_pointer)
+ {
+ /* LATER */
+ }
+ else if (s == &s_list)
+ outlet_list(x->x_outs[i], s, p[i]->p_natoms, p[i]->p_message);
+ else if (s)
+ outlet_anything(x->x_outs[i], s, p[i]->p_natoms, p[i]->p_message);
+ }
+ buddy_clear(x);
+}
+
+static void buddy_proxy_bang(t_buddy_proxy *x)
+{
+ x->p_selector = &s_bang;
+ x->p_natoms = 0; /* defensive */
+ buddy_check(x->p_master);
+}
+
+static void buddy_proxy_float(t_buddy_proxy *x, t_float f)
+{
+ x->p_selector = &s_float;
+ x->p_float = f;
+ x->p_natoms = 0; /* defensive */
+ buddy_check(x->p_master);
+}
+
+static void buddy_proxy_symbol(t_buddy_proxy *x, t_symbol *s)
+{
+ x->p_selector = &s_symbol;
+ x->p_symbol = s;
+ x->p_natoms = 0; /* defensive */
+ buddy_check(x->p_master);
+}
+
+static void buddy_proxy_pointer(t_buddy_proxy *x, t_gpointer *gp)
+{
+ x->p_selector = &s_pointer;
+ x->p_pointer = gp;
+ x->p_natoms = 0; /* defensive */
+ buddy_check(x->p_master);
+}
+
+static void buddy_proxy_domessage(t_buddy_proxy *x, int ac, t_atom *av)
+{
+ if (ac > x->p_size)
+ {
+ /* LATER consider using BUDDY_MAXSIZE (and warning if exceeded) */
+ x->p_message = grow_nodata(&ac, &x->p_size, x->p_message,
+ BUDDY_INISIZE, x->p_messini,
+ sizeof(*x->p_message));
+ }
+ x->p_natoms = ac;
+ memcpy(x->p_message, av, ac * sizeof(*x->p_message));
+ buddy_check(x->p_master);
+}
+
+static void buddy_proxy_list(t_buddy_proxy *x,
+ t_symbol *s, int ac, t_atom *av)
+{
+ x->p_selector = &s_list; /* LATER rethink */
+ buddy_proxy_domessage(x, ac, av);
+}
+
+static void buddy_proxy_anything(t_buddy_proxy *x,
+ t_symbol *s, int ac, t_atom *av)
+{
+ x->p_selector = s; /* LATER rethink */
+ buddy_proxy_domessage(x, ac, av);
+}
+
+static void buddy_bang(t_buddy *x)
+{
+ buddy_proxy_bang((t_buddy_proxy *)x->x_proxies[0]);
+}
+
+static void buddy_float(t_buddy *x, t_float f)
+{
+ buddy_proxy_float((t_buddy_proxy *)x->x_proxies[0], f);
+}
+
+static void buddy_symbol(t_buddy *x, t_symbol *s)
+{
+ buddy_proxy_symbol((t_buddy_proxy *)x->x_proxies[0], s);
+}
+
+static void buddy_pointer(t_buddy *x, t_gpointer *gp)
+{
+ buddy_proxy_pointer((t_buddy_proxy *)x->x_proxies[0], gp);
+}
+
+static void buddy_list(t_buddy *x, t_symbol *s, int ac, t_atom *av)
+{
+ buddy_proxy_list((t_buddy_proxy *)x->x_proxies[0], s, ac, av);
+}
+
+static void buddy_anything(t_buddy *x, t_symbol *s, int ac, t_atom *av)
+{
+ buddy_proxy_anything((t_buddy_proxy *)x->x_proxies[0], s, ac, av);
+}
+
+static void buddy_free(t_buddy *x)
+{
+ if (x->x_proxies)
+ {
+ int i = x->x_nslots;
+ while (i--)
+ {
+ t_buddy_proxy *y = (t_buddy_proxy *)x->x_proxies[i];
+ if (y->p_message != y->p_messini)
+ freebytes(y->p_message, y->p_size * sizeof(*y->p_message));
+ pd_free((t_pd *)y);
+ }
+ freebytes(x->x_proxies, x->x_nproxies * sizeof(*x->x_proxies));
+ }
+ if (x->x_outs)
+ freebytes(x->x_outs, x->x_nslots * sizeof(*x->x_outs));
+}
+
+static void *buddy_new(t_floatarg f)
+{
+ t_buddy *x;
+ int i, nslots, nproxies = (int)f;
+ t_pd **proxies;
+ t_outlet **outs;
+ if (nproxies < BUDDY_MINSLOTS)
+ nproxies = BUDDY_MINSLOTS;
+ if (!(proxies = (t_pd **)getbytes(nproxies * sizeof(*proxies))))
+ return (0);
+ for (nslots = 0; nslots < nproxies; nslots++)
+ if (!(proxies[nslots] = pd_new(buddy_proxy_class))) break;
+ if (nslots < BUDDY_MINSLOTS
+ || !(outs = (t_outlet **)getbytes(nslots * sizeof(*outs))))
+ {
+ int i = nslots;
+ while (i--) pd_free(proxies[i]);
+ freebytes(proxies, nproxies * sizeof(*proxies));
+ return (0);
+ }
+ x = (t_buddy *)pd_new(buddy_class);
+ x->x_nslots = nslots;
+ x->x_nproxies = nproxies;
+ x->x_proxies = proxies;
+ x->x_outs = outs;
+ for (i = 0; i < nslots; i++)
+ {
+ t_buddy_proxy *y = (t_buddy_proxy *)proxies[i];
+ y->p_master = x;
+ y->p_selector = 0;
+ y->p_float = 0;
+ y->p_symbol = 0;
+ y->p_pointer = 0;
+ y->p_size = BUDDY_INISIZE;
+ y->p_natoms = 0;
+ y->p_message = y->p_messini;
+ if (i) inlet_new((t_object *)x, (t_pd *)y, 0, 0);
+ x->x_outs[i] = outlet_new((t_object *)x, &s_anything);
+ }
+ return (x);
+}
+
+void buddy_setup(void)
+{
+ buddy_class = class_new(gensym("buddy"),
+ (t_newmethod)buddy_new,
+ (t_method)buddy_free,
+ sizeof(t_buddy), 0, A_DEFFLOAT, 0);
+ class_addbang(buddy_class, buddy_bang);
+ class_addfloat(buddy_class, buddy_float);
+ class_addsymbol(buddy_class, buddy_symbol);
+ class_addpointer(buddy_class, buddy_pointer);
+ class_addlist(buddy_class, buddy_list);
+ class_addanything(buddy_class, buddy_anything);
+ class_addmethod(buddy_class, (t_method)buddy_clear, gensym("clear"), 0);
+ buddy_proxy_class = class_new(gensym("_buddy_proxy"), 0, 0,
+ sizeof(t_buddy_proxy),
+ CLASS_PD | CLASS_NOINLET, 0);
+ class_addbang(buddy_proxy_class, buddy_proxy_bang);
+ class_addfloat(buddy_proxy_class, buddy_proxy_float);
+ class_addsymbol(buddy_proxy_class, buddy_proxy_symbol);
+ class_addpointer(buddy_proxy_class, buddy_proxy_pointer);
+ class_addlist(buddy_proxy_class, buddy_proxy_list);
+ class_addanything(buddy_proxy_class, buddy_proxy_anything);
+}
diff --git a/cyclone/hammer/capture.c b/cyclone/hammer/capture.c
new file mode 100644
index 0000000..b36c421
--- /dev/null
+++ b/cyclone/hammer/capture.c
@@ -0,0 +1,291 @@
+/* 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 "common/loud.h"
+#include "hammer/file.h"
+
+#define CAPTURE_DEFSIZE 512
+
+typedef struct _capture
+{
+ t_object x_ob;
+ t_canvas *x_canvas;
+ char x_intmode; /* if nonzero ('x' or 'm') floats are ignored */
+ 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_float(t_capture *x, t_float f)
+{
+ if (x->x_intmode && f != (int)f) /* CHECKME float */
+ return;
+ x->x_buffer[x->x_head++] = f;
+ if (x->x_head >= x->x_bufsize)
+ x->x_head = 0;
+ if (x->x_count < x->x_bufsize)
+ x->x_count++;
+}
+
+static void capture_list(t_capture *x, t_symbol *s, int ac, t_atom *av)
+{
+ while (ac--)
+ {
+ if (av->a_type == A_FLOAT) /* CHECKME */
+ capture_float(x, av->a_w.w_float);
+ av++;
+ }
+}
+
+static void capture_clear(t_capture *x)
+{
+ x->x_count = 0;
+ x->x_head = 0;
+}
+
+static void capture_count(t_capture *x)
+{
+ post("capture: %d items received", /* CHECKED */
+ x->x_count); /* CHECKED incompatible (4.07 seems buggy here) */
+}
+
+static void capture_dump(t_capture *x)
+{
+ int count = x->x_count;
+ if (count < x->x_bufsize)
+ {
+ float *bp = x->x_buffer;
+ while (count--)
+ outlet_float(((t_object *)x)->ob_outlet, *bp++);
+ }
+ else
+ {
+ float *bp = x->x_buffer + x->x_head;
+ count = x->x_bufsize - x->x_head;
+ while (count--)
+ outlet_float(((t_object *)x)->ob_outlet, *bp++);
+ bp = x->x_buffer;
+ count = x->x_head;
+ while (count--)
+ outlet_float(((t_object *)x)->ob_outlet, *bp++);
+ }
+}
+
+static int capture_formatint(int i, char *buf, int col,
+ int maxcol, char *fmt)
+{
+ char *bp = buf;
+ int cnt = 0;
+ if (col > 0)
+ *bp++ = ' ', cnt++;
+ cnt += sprintf(bp, fmt, i);
+ if (col + cnt > maxcol)
+ buf[0] = '\n', col = cnt;
+ else
+ col += cnt;
+ return (col);
+}
+
+static int capture_formatfloat(float f, char *buf, int col,
+ int maxcol, char *fmt)
+{
+ char *bp = buf;
+ int cnt = 0;
+ if (col > 0)
+ *bp++ = ' ', cnt++;
+ cnt += sprintf(bp, fmt, f);
+ if (col + cnt > maxcol)
+ buf[0] = '\n', col = cnt;
+ else
+ col += cnt;
+ return (col);
+}
+
+static int capture_formatnumber(t_capture *x, float f, char *buf,
+ int col, int maxcol)
+{
+ char intmode = x->x_intmode;
+ if (intmode == 'm')
+ intmode = (f < 128 && f > -128 ? 'd' : 'x'); /* CHECKME */
+ if (intmode == 'x')
+ col = capture_formatint((int)f, buf, col, maxcol, "%x");
+ else if (intmode)
+ col = capture_formatint((int)f, buf, col, maxcol, "%d");
+ else
+ col = capture_formatfloat(f, buf, col, maxcol, "%g");
+ return (col);
+}
+
+static int capture_writefloat(t_capture *x, float f, char *buf, int col,
+ FILE *fp)
+{
+ /* CHECKED no linebreaks (FIXME) */
+ col = capture_formatnumber(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(x->x_canvas, fn->s_name, buf, MAXPDSTRING);
+ if (fp = fopen(buf, "w")) /* LATER ask if overwriting, CHECKED */
+ {
+ int col = 0;
+ if (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)
+{
+ /* CHECKED 80 columns */
+ col = capture_formatnumber(x, f, buf, col, 80);
+ hammereditor_append(x->x_filehandle, buf);
+ return (col);
+}
+
+static void capture_open(t_capture *x)
+{
+ int count = x->x_count;
+ char buf[MAXPDSTRING];
+ hammereditor_open(x->x_filehandle, "t_capture"); /* CHECKED */
+ if (count < x->x_bufsize)
+ {
+ float *bp = x->x_buffer;
+ int col = 0;
+ while (count--)
+ col = capture_appendfloat(x, *bp++, buf, col);
+ }
+ else
+ {
+ float *bp = x->x_buffer + x->x_head;
+ int col = 0;
+ count = x->x_bufsize - x->x_head;
+ while (count--)
+ col = capture_appendfloat(x, *bp++, buf, col);
+ bp = x->x_buffer;
+ count = x->x_head;
+ while (count--)
+ col = capture_appendfloat(x, *bp++, buf, col);
+ }
+}
+
+/* CHECKED without asking and storing the changes */
+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 void capture_free(t_capture *x)
+{
+ hammerfile_free(x->x_filehandle);
+ if (x->x_buffer)
+ freebytes(x->x_buffer, x->x_bufsize * sizeof(*x->x_buffer));
+}
+
+static void *capture_new(t_symbol *s, t_floatarg f)
+{
+ t_capture *x = 0;
+ float *buffer;
+ int bufsize = (int)f; /* CHECKME */
+ if (bufsize <= 0) /* CHECKME */
+ bufsize = CAPTURE_DEFSIZE;
+ if (buffer = getbytes(bufsize * sizeof(*buffer)))
+ {
+ x = (t_capture *)pd_new(capture_class);
+ x->x_canvas = canvas_getcurrent();
+ if (s && s != &s_)
+ {
+ if (s == gensym("x"))
+ x->x_intmode = 'x';
+ else if (s == gensym("m"))
+ x->x_intmode = 'm';
+ else
+ x->x_intmode = 'd'; /* ignore floats */
+ }
+ x->x_buffer = buffer;
+ x->x_bufsize = bufsize;
+ outlet_new((t_object *)x, &s_float);
+ x->x_filehandle = hammerfile_new((t_pd *)x, 0, 0, capture_writehook, 0);
+ capture_clear(x);
+ }
+ return (x);
+}
+
+void capture_setup(void)
+{
+ capture_class = class_new(gensym("capture"),
+ (t_newmethod)capture_new,
+ (t_method)capture_free,
+ sizeof(t_capture), 0, A_DEFFLOAT, A_DEFSYM, 0);
+ class_addfloat(capture_class, capture_float);
+ class_addlist(capture_class, capture_list);
+ class_addmethod(capture_class, (t_method)capture_clear,
+ gensym("clear"), 0);
+ class_addmethod(capture_class, (t_method)capture_count,
+ gensym("count"), 0);
+ class_addmethod(capture_class, (t_method)capture_dump,
+ gensym("dump"), 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/hammer/cartopol.c b/cyclone/hammer/cartopol.c
new file mode 100644
index 0000000..4200686
--- /dev/null
+++ b/cyclone/hammer/cartopol.c
@@ -0,0 +1,44 @@
+/* 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"
+
+#if defined(NT) || defined(MACOSX)
+/* cf pd/src/x_arithmetic.c */
+#define atan2f atan2
+#define hypotf hypot
+#endif
+
+typedef struct _cartopol
+{
+ t_object x_ob;
+ t_float x_imag;
+ t_outlet *x_out2;
+} t_cartopol;
+
+static t_class *cartopol_class;
+
+static void cartopol_float(t_cartopol *x, t_float f)
+{
+ outlet_float(x->x_out2, atan2f(x->x_imag, f));
+ outlet_float(((t_object *)x)->ob_outlet, hypotf(f, x->x_imag));
+}
+
+static void *cartopol_new(void)
+{
+ t_cartopol *x = (t_cartopol *)pd_new(cartopol_class);
+ floatinlet_new((t_object *)x, &x->x_imag);
+ outlet_new((t_object *)x, &s_float);
+ x->x_out2 = outlet_new((t_object *)x, &s_float);
+ return (x);
+}
+
+void cartopol_setup(void)
+{
+ cartopol_class = class_new(gensym("cartopol"),
+ (t_newmethod)cartopol_new, 0,
+ sizeof(t_cartopol), 0, 0);
+ class_addfloat(cartopol_class, cartopol_float);
+}
diff --git a/cyclone/hammer/coll.c b/cyclone/hammer/coll.c
new file mode 100644
index 0000000..c4a3388
--- /dev/null
+++ b/cyclone/hammer/coll.c
@@ -0,0 +1,1597 @@
+/* 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 <string.h>
+#include "m_pd.h"
+#include "g_canvas.h"
+#include "common/loud.h"
+#include "hammer/file.h"
+
+/* FIXME sort crashes after (corrupt?) transfers from the editor */
+/* LATER make sure that ``reentrancy protection hack'' is really working... */
+/* CHECKME default fname for 'write' -- c_filename, x_name, nothing? */
+
+#define COLL_DEBUG
+
+typedef struct _collelem
+{
+ int e_hasnumkey;
+ int e_numkey;
+ t_symbol *e_symkey;
+ struct _collelem *e_prev;
+ struct _collelem *e_next;
+ int e_size;
+ t_atom *e_data;
+} t_collelem;
+
+typedef struct _collcommon
+{
+ t_pd c_pd;
+ struct _coll *c_refs; /* used in read-banging and dirty flag handling */
+ int c_embedflag; /* common field (CHECKED in 'TEXT') */
+ int c_loading;
+ int c_relinked;
+ int c_selfmodified;
+ int c_entered; /* a counter, LATER rethink */
+ t_symbol *c_filename;
+ t_canvas *c_lastcanvas;
+ t_hammerfile *c_filehandle;
+ t_collelem *c_first;
+ t_collelem *c_last;
+ t_collelem *c_ahead;
+ t_collelem *c_back;
+} t_collcommon;
+
+typedef struct _coll
+{
+ t_object x_ob;
+ t_canvas *x_canvas;
+ t_symbol *x_name;
+ t_collcommon *x_common;
+ t_hammerfile *x_filehandle;
+ t_outlet *x_keyout;
+ t_outlet *x_filebangout;
+ t_outlet *x_dumpbangout;
+ struct _coll *x_next;
+} t_coll;
+
+static t_class *coll_class;
+static t_class *collcommon_class;
+
+static t_collelem *collelem_new(int ac, t_atom *av, int *np, t_symbol *s)
+{
+ t_collelem *ep = (t_collelem *)getbytes(sizeof(*ep));
+ if (ep->e_hasnumkey = (np != 0))
+ ep->e_numkey = *np;
+ ep->e_symkey = s;
+ ep->e_prev = ep->e_next = 0;
+ if (ep->e_size = ac)
+ {
+ t_atom *ap = getbytes(ac * sizeof(*ap));
+ ep->e_data = ap;
+ if (av) while (ac--)
+ *ap++ = *av++;
+ else while (ac--)
+ {
+ SETFLOAT(ap, 0);
+ ap++;
+ }
+ }
+ else ep->e_data = 0;
+ return (ep);
+}
+
+static void collelem_free(t_collelem *ep)
+{
+ if (ep->e_data)
+ freebytes(ep->e_data, ep->e_size * sizeof(*ep->e_data));
+ freebytes(ep, sizeof(*ep));
+}
+
+/* CHECKME again... apparently c74 is not able to fix this for good */
+/* result: 1 for ep1 < ep2, otherwise 0 (symbols are less then floats) */
+static int collelem_less(t_collelem *ep1, t_collelem *ep2, int ndx)
+{
+ if (ndx < 0)
+ {
+ if (ep1->e_symkey)
+ return (ep2->e_symkey ?
+ strcmp(ep1->e_symkey->s_name,
+ ep2->e_symkey->s_name) < 0
+ : 1); /* CHECKED incompatible with 4.07, but consistent */
+ else if (ep2->e_symkey)
+ return (0); /* CHECKED incompatible with 4.07, but consistent */
+ else
+ return (ep1->e_numkey < ep2->e_numkey); /* CHECKED in 4.07 */
+ }
+ else
+ {
+ t_atom *ap1 = (ndx < ep1->e_size ?
+ ep1->e_data + ndx : ep1->e_data + ep1->e_size - 1);
+ t_atom *ap2 = (ndx < ep2->e_size ?
+ ep2->e_data + ndx : ep2->e_data + ep2->e_size - 1);
+ if (ap1->a_type == A_FLOAT)
+ {
+ if (ap2->a_type == A_FLOAT)
+ return (ap1->a_w.w_float < ap2->a_w.w_float);
+ else if (ap2->a_type == A_SYMBOL)
+ return (0);
+ else
+ return (1);
+ }
+ else if (ap1->a_type == A_SYMBOL)
+ {
+ if (ap2->a_type == A_FLOAT)
+ return (1);
+ else if (ap2->a_type == A_SYMBOL)
+ return (strcmp(ap1->a_w.w_symbol->s_name,
+ ap2->a_w.w_symbol->s_name) < 0);
+ else
+ return (1);
+ }
+ else
+ return (0);
+ }
+}
+
+static void collelem_post(t_collelem *ep)
+{
+ if (ep->e_hasnumkey && ep->e_symkey)
+ startpost("%d %s:", ep->e_numkey, ep->e_symkey->s_name);
+ else if (ep->e_hasnumkey)
+ startpost("%d:", ep->e_numkey);
+ else if (ep->e_symkey)
+ startpost("%s:", ep->e_symkey->s_name);
+ else bug("collcommon_post");
+ postatom(ep->e_size, ep->e_data);
+ endpost();
+}
+
+static void collcommon_post(t_collcommon *cc)
+{
+ t_collelem *ep;
+ for (ep = cc->c_first; ep; ep = ep->e_next) collelem_post(ep);
+}
+
+static t_collelem *collcommon_numkey(t_collcommon *cc, int numkey)
+{
+ t_collelem *ep;
+ for (ep = cc->c_first; ep; ep = ep->e_next)
+ if (ep->e_hasnumkey && ep->e_numkey == numkey)
+ return (ep);
+ return (0);
+}
+
+static t_collelem *collcommon_symkey(t_collcommon *cc, t_symbol *symkey)
+{
+ t_collelem *ep;
+ for (ep = cc->c_first; ep; ep = ep->e_next)
+ if (ep->e_symkey == symkey)
+ return (ep);
+ return (0);
+}
+
+static void collcommon_takeout(t_collcommon *cc, t_collelem *ep)
+{
+ if (ep->e_prev)
+ ep->e_prev->e_next = ep->e_next;
+ else
+ cc->c_first = ep->e_next;
+ if (ep->e_next)
+ ep->e_next->e_prev = ep->e_prev;
+ else
+ cc->c_last = ep->e_prev;
+ if (cc->c_ahead == ep)
+ cc->c_ahead = ep->e_next;
+ if (cc->c_back == ep)
+ cc->c_back = ep->e_prev;
+}
+
+static void collcommon_modified(t_collcommon *cc, int relinked)
+{
+ if (cc->c_loading)
+ return;
+ if (relinked)
+ {
+ cc->c_relinked = 1;
+ }
+ if (cc->c_embedflag)
+ {
+ t_coll *x;
+ for (x = cc->c_refs; x; x = x->x_next)
+ if (x->x_canvas && glist_isvisible(x->x_canvas))
+ canvas_dirty(x->x_canvas, 1);
+ }
+}
+
+/* atomic collcommon modifiers: clearall, remove, replace,
+ putbefore, putafter, swaplinks, swapkeys, changesymkey, renumber, sort */
+
+static void collcommon_clearall(t_collcommon *cc)
+{
+ if (cc->c_first)
+ {
+ t_collelem *ep1 = cc->c_first, *ep2;
+ do
+ {
+ ep2 = ep1->e_next;
+ collelem_free(ep1);
+ }
+ while (ep1 = ep2);
+ cc->c_first = cc->c_last = 0;
+ cc->c_ahead = cc->c_back = 0;
+ collcommon_modified(cc, 1);
+ }
+}
+
+static void collcommon_remove(t_collcommon *cc, t_collelem *ep)
+{
+ collcommon_takeout(cc, ep);
+ collelem_free(ep);
+ collcommon_modified(cc, 1);
+}
+
+static void collcommon_replace(t_collcommon *cc, t_collelem *ep,
+ int ac, t_atom *av, int *np, t_symbol *s)
+{
+ if (ep->e_hasnumkey = (np != 0))
+ ep->e_numkey = *np;
+ ep->e_symkey = s;
+ if (ac)
+ {
+ int i = ac;
+ t_atom *ap;
+ if (ep->e_data)
+ {
+ if (ep->e_size != ac)
+ ap = resizebytes(ep->e_data,
+ ep->e_size * sizeof(*ap), ac * sizeof(*ap));
+ else ap = ep->e_data;
+ }
+ else
+ ap = getbytes(ac * sizeof(*ap));
+ ep->e_data = ap;
+ if (av) while (i --)
+ *ap++ = *av++;
+ else while (i --)
+ {
+ SETFLOAT(ap, 0);
+ ap++;
+ }
+ }
+ else
+ {
+ if (ep->e_data)
+ freebytes(ep->e_data, ep->e_size * sizeof(*ep->e_data));
+ ep->e_data = 0;
+ }
+ ep->e_size = ac;
+ collcommon_modified(cc, 0);
+}
+
+static void collcommon_putbefore(t_collcommon *cc,
+ t_collelem *ep, t_collelem *next)
+{
+ if (next)
+ {
+ ep->e_next = next;
+ if (ep->e_prev = next->e_prev)
+ ep->e_prev->e_next = ep;
+ else
+ cc->c_first = ep;
+ next->e_prev = ep;
+ }
+ else if (cc->c_first || cc->c_last)
+ bug("collcommon_putbefore");
+ else
+ cc->c_first = cc->c_last = ep;
+ collcommon_modified(cc, 1);
+}
+
+static void collcommon_putafter(t_collcommon *cc,
+ t_collelem *ep, t_collelem *prev)
+{
+ if (prev)
+ {
+ ep->e_prev = prev;
+ if (ep->e_next = prev->e_next)
+ ep->e_next->e_prev = ep;
+ else
+ cc->c_last = ep;
+ prev->e_next = ep;
+ }
+ else if (cc->c_first || cc->c_last)
+ bug("collcommon_putafter");
+ else
+ cc->c_first = cc->c_last = ep;
+ collcommon_modified(cc, 1);
+}
+
+/* LATER consider making it faster, if there is a real need.
+ Now called only in the sort routine, once per sort. */
+static void collcommon_swaplinks(t_collcommon *cc,
+ t_collelem *ep1, t_collelem *ep2)
+{
+ if (ep1 != ep2)
+ {
+ t_collelem *prev1 = ep1->e_prev, *prev2 = ep2->e_prev;
+ if (prev1 == ep2)
+ {
+ collcommon_takeout(cc, ep2);
+ collcommon_putafter(cc, ep2, ep1);
+ }
+ else if (prev2 == ep1)
+ {
+ collcommon_takeout(cc, ep1);
+ collcommon_putafter(cc, ep1, ep2);
+ }
+ else if (prev1)
+ {
+ if (prev2)
+ {
+ collcommon_takeout(cc, ep1);
+ collcommon_takeout(cc, ep2);
+ collcommon_putafter(cc, ep1, prev2);
+ collcommon_putafter(cc, ep2, prev1);
+ }
+ else
+ {
+ t_collelem *next2 = ep2->e_next;
+ collcommon_takeout(cc, ep1);
+ collcommon_takeout(cc, ep2);
+ collcommon_putbefore(cc, ep1, next2);
+ collcommon_putafter(cc, ep2, prev1);
+ }
+ }
+ else if (prev2)
+ {
+ t_collelem *next1 = ep1->e_next;
+ collcommon_takeout(cc, ep1);
+ collcommon_takeout(cc, ep2);
+ collcommon_putafter(cc, ep1, prev2);
+ collcommon_putbefore(cc, ep2, next1);
+ }
+ else bug("collcommon_swaplinks");
+ }
+}
+
+static void collcommon_swapkeys(t_collcommon *cc,
+ t_collelem *ep1, t_collelem *ep2)
+{
+ int hasnumkey = ep2->e_hasnumkey, numkey = ep2->e_numkey;
+ t_symbol *symkey = ep2->e_symkey;
+ ep2->e_hasnumkey = ep1->e_hasnumkey;
+ ep2->e_numkey = ep1->e_numkey;
+ ep2->e_symkey = ep1->e_symkey;
+ ep1->e_hasnumkey = hasnumkey;
+ ep1->e_numkey = numkey;
+ ep1->e_symkey = symkey;
+ collcommon_modified(cc, 0);
+}
+
+static void collcommon_changesymkey(t_collcommon *cc,
+ t_collelem *ep, t_symbol *s)
+{
+ ep->e_symkey = s;
+ collcommon_modified(cc, 0);
+}
+
+static void collcommon_renumber(t_collcommon *cc, int startkey)
+{
+ t_collelem *ep;
+ for (ep = cc->c_first; ep; ep = ep->e_next)
+ if (ep->e_hasnumkey)
+ ep->e_numkey = startkey++;
+ collcommon_modified(cc, 0);
+}
+
+/* LATER choose a better algo, after coll's storage structures stabilize.
+ Note, that even the simple insertion sort below (n-square) might prove
+ better for dlls, than theoretically efficient algo (nlogn) which requires
+ random access emulation. Avoiding recursion is not a bad idea, too. */
+static void collcommon_sort(t_collcommon *cc, int asc, int ndx)
+{
+ t_collelem *min = cc->c_first;
+ t_collelem *ep;
+ if (min && (ep = min->e_next))
+ {
+ cc->c_loading = 1;
+ /* search for a sentinel element */
+ do
+ if (collelem_less(ep, min, ndx) == asc) min = ep;
+ while (ep = ep->e_next);
+ /* prepend it */
+ collcommon_swaplinks(cc, cc->c_first, min);
+ /* sort */
+ ep = min->e_next->e_next;
+ while (ep)
+ {
+ t_collelem *next = ep->e_next;
+ for (min = ep->e_prev;
+ collelem_less(ep, min, ndx) == asc;
+ min = min->e_prev);
+ if (ep != min->e_next)
+ {
+ collcommon_takeout(cc, ep);
+ collcommon_putafter(cc, ep, min);
+ }
+ ep = next;
+ }
+ cc->c_loading = 0;
+ collcommon_modified(cc, 1);
+ }
+}
+
+static void collcommon_adddata(t_collcommon *cc, t_collelem *ep,
+ int ac, t_atom *av)
+{
+ if (ac)
+ {
+ t_atom *ap;
+ int newsize = ep->e_size + ac;
+ if (ep->e_data)
+ ap = resizebytes(ep->e_data,
+ ep->e_size * sizeof(*ap), newsize * sizeof(*ap));
+ else
+ {
+ ep->e_size = 0; /* redundant, hopefully */
+ ap = getbytes(newsize * sizeof(*ap));
+ }
+ ep->e_data = ap;
+ ap += ep->e_size;
+ if (av) while (ac--)
+ *ap++ = *av++;
+ else while (ac--)
+ {
+ SETFLOAT(ap, 0);
+ ap++;
+ }
+ ep->e_size = newsize;
+ collcommon_modified(cc, 0);
+ }
+}
+
+static t_collelem *collcommon_tonumkey(t_collcommon *cc, int numkey,
+ int ac, t_atom *av, int replace)
+{
+ t_collelem *old = collcommon_numkey(cc, numkey), *new;
+ if (old && replace)
+ collcommon_replace(cc, new = old, ac, av, &numkey, 0);
+ else
+ {
+ new = collelem_new(ac, av, &numkey, 0);
+ if (old)
+ {
+ collcommon_putbefore(cc, new, old);
+ do
+ if (old->e_hasnumkey) old->e_numkey++; /* LATER rethink */
+ while (old = old->e_next);
+ }
+ else
+ {
+ int closestkey = 0; /* LATER rethink */
+ t_collelem *closest = 0, *ep;
+ for (ep = cc->c_first; ep; ep = ep->e_next)
+ {
+ if (ep->e_hasnumkey)
+ {
+ if (numkey >= closestkey && numkey <= ep->e_numkey)
+ {
+ collcommon_putbefore(cc, new, ep);
+ break;
+ }
+ closestkey = ep->e_numkey;
+ }
+ closest = ep;
+ }
+ if (!ep)
+ {
+ if (numkey <= closestkey)
+ collcommon_putbefore(cc, new, closest);
+ else
+ collcommon_putafter(cc, new, closest);
+ }
+ }
+ }
+ return (new);
+}
+
+static t_collelem *collcommon_tosymkey(t_collcommon *cc, t_symbol *symkey,
+ int ac, t_atom *av, int replace)
+{
+ t_collelem *old = collcommon_symkey(cc, symkey), *new;
+ if (old && replace)
+ collcommon_replace(cc, new = old, ac, av, 0, symkey);
+ else
+ collcommon_putafter(cc, new = collelem_new(ac, av, 0, symkey),
+ cc->c_last);
+ return (new);
+}
+
+static int collcommon_fromlist(t_collcommon *cc, int ac, t_atom *av)
+{
+ int hasnumkey = 0, numkey;
+ t_symbol *symkey = 0;
+ int size = 0;
+ t_atom *data = 0;
+ int nlines = 0;
+ cc->c_loading = 1;
+ collcommon_clearall(cc);
+ while (ac--)
+ {
+ if (data)
+ {
+ if (av->a_type == A_SEMI)
+ {
+ t_collelem *ep = collelem_new(size, data,
+ hasnumkey ? &numkey : 0, symkey);
+ collcommon_putafter(cc, ep, cc->c_last);
+ hasnumkey = 0;
+ symkey = 0;
+ data = 0;
+ nlines++;
+ }
+ if (av->a_type == A_COMMA)
+ {
+ /* CHECKED rejecting a comma */
+ collcommon_clearall(cc); /* LATER rethink */
+ cc->c_loading = 0;
+ return (-nlines);
+ }
+ else size++;
+ }
+ else if (av->a_type == A_COMMA)
+ {
+ size = 0;
+ data = av + 1;
+ }
+ else if (av->a_type == A_SYMBOL)
+ symkey = av->a_w.w_symbol;
+ else if (av->a_type == A_FLOAT &&
+ loud_checkint(0, av->a_w.w_float, &numkey, 0))
+ hasnumkey = 1;
+ else
+ {
+ loud_error(0, "coll: bad atom");
+ collcommon_clearall(cc); /* LATER rethink */
+ cc->c_loading = 0;
+ return (-nlines);
+ }
+ av++;
+ }
+ if (data)
+ {
+ loud_error(0, "coll: incomplete");
+ collcommon_clearall(cc); /* LATER rethink */
+ cc->c_loading = 0;
+ return (-nlines);
+ }
+ cc->c_loading = 0;
+ return (nlines);
+}
+
+static int collcommon_frombinbuf(t_collcommon *cc, t_binbuf *bb)
+{
+ return (collcommon_fromlist(cc, binbuf_getnatom(bb), binbuf_getvec(bb)));
+}
+
+static void collcommon_doread(t_collcommon *cc, t_symbol *fn, t_canvas *cv)
+{
+ t_binbuf *bb;
+ int ac;
+ t_atom *av;
+ char buf[MAXPDSTRING];
+ if (!fn && !(fn = cc->c_filename)) /* !fn: 'readagain' */
+ return;
+ if (cv || (cv = cc->c_lastcanvas)) /* !cv: 'read' w/o arg, 'readagain' */
+ canvas_makefilename(cv, fn->s_name, buf, MAXPDSTRING);
+ else
+ {
+ strncpy(buf, fn->s_name, MAXPDSTRING);
+ buf[MAXPDSTRING-1] = 0;
+ }
+ if (!cc->c_refs)
+ {
+ /* loading during object creation --
+ avoid binbuf_read()'s complaints, LATER rethink */
+ FILE *fp;
+ char fname[MAXPDSTRING];
+ sys_bashfilename(buf, fname);
+ if (!(fp = fopen(fname, "r")))
+ {
+ loud_warning(&coll_class, "no coll file '%s'", fname);
+ return;
+ }
+ fclose(fp);
+ }
+ bb = binbuf_new();
+ if (binbuf_read(bb, buf, "", 0))
+ loud_error(0, "coll: error reading text file '%s'", fn->s_name);
+ else
+ {
+ int nlines = collcommon_frombinbuf(cc, bb);
+ if (nlines > 0)
+ {
+ t_coll *x;
+ /* LATER consider making this more robust */
+ for (x = cc->c_refs; x; x = x->x_next)
+ outlet_bang(x->x_filebangout);
+ cc->c_lastcanvas = cv;
+ cc->c_filename = fn;
+ post("coll: finished reading %d lines from text file '%s'",
+ nlines, fn->s_name);
+ }
+ else if (nlines < 0)
+ loud_error(0, "coll: error in line %d of text file '%s'",
+ 1 - nlines, fn->s_name);
+ else
+ loud_error(0, "coll: error reading text file '%s'", fn->s_name);
+ if (cc->c_refs)
+ collcommon_modified(cc, 1);
+ }
+ binbuf_free(bb);
+}
+
+static void collcommon_readhook(t_pd *z, t_symbol *fn, int ac, t_atom *av)
+{
+ collcommon_doread((t_collcommon *)z, fn, 0);
+}
+
+static void collcommon_tobinbuf(t_collcommon *cc, t_binbuf *bb)
+{
+ t_collelem *ep;
+ t_atom at[3];
+ for (ep = cc->c_first; ep; ep = ep->e_next)
+ {
+ t_atom *ap = at;
+ int cnt = 1;
+ if (ep->e_hasnumkey)
+ {
+ SETFLOAT(ap, ep->e_numkey);
+ ap++; cnt++;
+ }
+ if (ep->e_symkey)
+ {
+ SETSYMBOL(ap, ep->e_symkey);
+ ap++; cnt++;
+ }
+ SETCOMMA(ap);
+ binbuf_add(bb, cnt, at);
+ binbuf_add(bb, ep->e_size, ep->e_data);
+ binbuf_addsemi(bb);
+ }
+}
+
+static void collcommon_dowrite(t_collcommon *cc, t_symbol *fn, t_canvas *cv)
+{
+ t_binbuf *bb;
+ int ac;
+ t_atom *av;
+ char buf[MAXPDSTRING];
+ if (!fn && !(fn = cc->c_filename)) /* !fn: 'writeagain' */
+ return;
+ if (cv || (cv = cc->c_lastcanvas)) /* !cv: 'write' w/o arg, 'writeagain' */
+ canvas_makefilename(cv, fn->s_name, buf, MAXPDSTRING);
+ else
+ {
+ strncpy(buf, fn->s_name, MAXPDSTRING);
+ buf[MAXPDSTRING-1] = 0;
+ }
+ bb = binbuf_new();
+ collcommon_tobinbuf(cc, bb);
+ if (binbuf_write(bb, buf, "", 0))
+ loud_error(0, "coll: error writing text file '%s'", fn->s_name);
+ else
+ {
+ cc->c_lastcanvas = cv;
+ cc->c_filename = fn;
+ }
+ binbuf_free(bb);
+}
+
+static void collcommon_writehook(t_pd *z, t_symbol *fn, int ac, t_atom *av)
+{
+ collcommon_dowrite((t_collcommon *)z, fn, 0);
+}
+
+static void coll_embedhook(t_pd *z, t_binbuf *bb, t_symbol *bindsym)
+{
+ t_coll *x = (t_coll *)z;
+ t_collcommon *cc = x->x_common;
+ if (cc->c_embedflag)
+ {
+ t_collelem *ep;
+ t_atom at[6];
+ binbuf_addv(bb, "ssii;", bindsym, gensym("flags"), 1, 0);
+ SETSYMBOL(at, bindsym);
+ for (ep = cc->c_first; ep; ep = ep->e_next)
+ {
+ t_atom *ap = at + 1;
+ int cnt;
+ if (ep->e_hasnumkey && ep->e_symkey)
+ {
+ SETSYMBOL(ap, gensym("nstore"));
+ ap++;
+ SETSYMBOL(ap, ep->e_symkey);
+ ap++;
+ SETFLOAT(ap, ep->e_numkey);
+ cnt = 4;
+ }
+ else if (ep->e_symkey)
+ {
+ SETSYMBOL(ap, gensym("store"));
+ ap++;
+ SETSYMBOL(ap, ep->e_symkey);
+ cnt = 3;
+ }
+ else
+ {
+ SETFLOAT(ap, ep->e_numkey);
+ cnt = 2;
+ }
+ binbuf_add(bb, cnt, at);
+ binbuf_add(bb, ep->e_size, ep->e_data);
+ binbuf_addsemi(bb);
+ }
+ }
+}
+
+static void collcommon_editorhook(t_pd *z, t_symbol *s, int ac, t_atom *av)
+{
+ int nlines = collcommon_fromlist((t_collcommon *)z, ac, av);
+ if (nlines < 0)
+ loud_error(0, "coll: editing error in line %d", 1 - nlines);
+}
+
+static t_collcommon *coll_checkcommon(t_coll *x)
+{
+ if (x->x_name &&
+ x->x_common != (t_collcommon *)pd_findbyclass(x->x_name,
+ collcommon_class))
+ {
+ bug("coll_checkcommon");
+ return (0);
+ }
+ return (x->x_common);
+}
+
+static void coll_unbind(t_coll *x)
+{
+ /* LATER consider calling coll_checkcommon(x) */
+ t_collcommon *cc = x->x_common;
+ t_coll *prev, *next;
+ if ((prev = cc->c_refs) == x)
+ {
+ if (!(cc->c_refs = x->x_next))
+ {
+ hammerfile_free(cc->c_filehandle);
+ cc->c_loading = 1; /* disable dirty-flag handling, LATER rethink */
+ collcommon_clearall(cc);
+ if (x->x_name) pd_unbind(&cc->c_pd, x->x_name);
+ pd_free(&cc->c_pd);
+ }
+ }
+ else if (prev)
+ {
+ while (next = prev->x_next)
+ {
+ if (next == x)
+ {
+ prev->x_next = next->x_next;
+ break;
+ }
+ prev = next;
+ }
+ }
+ x->x_common = 0;
+ x->x_name = 0;
+ x->x_next = 0;
+}
+
+static void coll_bind(t_coll *x, t_symbol *name)
+{
+ t_collcommon *cc = 0;
+ if (name == &s_)
+ name = 0;
+ else if (name)
+ cc = (t_collcommon *)pd_findbyclass(name, collcommon_class);
+ if (!cc)
+ {
+ cc = (t_collcommon *)pd_new(collcommon_class);
+ cc->c_refs = 0;
+ cc->c_embedflag = 0;
+ cc->c_loading = 0;
+ if (name)
+ {
+ pd_bind(&cc->c_pd, name);
+ /* LATER rethink canvas unpredictability */
+ collcommon_doread(cc, name, x->x_canvas);
+ }
+ else
+ {
+ cc->c_filename = 0;
+ cc->c_lastcanvas = 0;
+ }
+ cc->c_filehandle = hammerfile_new((t_pd *)cc, 0, collcommon_readhook,
+ collcommon_writehook,
+ collcommon_editorhook);
+ }
+ x->x_common = cc;
+ x->x_name = name;
+ x->x_next = cc->c_refs;
+ cc->c_refs = x;
+}
+
+static int coll_rebind(t_coll *x, t_symbol *name)
+{
+ t_collcommon *cc;
+ if (name && name != &s_ &&
+ (cc = (t_collcommon *)pd_findbyclass(name, collcommon_class)))
+ {
+ coll_unbind(x);
+ x->x_common = cc;
+ x->x_name = name;
+ x->x_next = cc->c_refs;
+ cc->c_refs = x;
+ return (1);
+ }
+ else return (0);
+}
+
+static void coll_dooutput(t_coll *x, int ac, t_atom *av)
+{
+ if (ac > 1)
+ {
+ if (av->a_type == A_FLOAT)
+ outlet_list(((t_object *)x)->ob_outlet, &s_list, ac, av);
+ else if (av->a_type == A_SYMBOL)
+ outlet_anything(((t_object *)x)->ob_outlet,
+ av->a_w.w_symbol, ac-1, av+1);
+ }
+ else if (ac)
+ {
+ if (av->a_type == A_FLOAT)
+ outlet_float(((t_object *)x)->ob_outlet, av->a_w.w_float);
+ else if (av->a_type == A_SYMBOL)
+ outlet_symbol(((t_object *)x)->ob_outlet, av->a_w.w_symbol);
+ }
+}
+
+static void coll_keyoutput(t_coll *x, t_collelem *ep)
+{
+ t_collcommon *cc = x->x_common;
+ if (!cc->c_entered++) cc->c_selfmodified = 0;
+ cc->c_relinked = 0;
+ if (ep->e_hasnumkey)
+ outlet_float(x->x_keyout, ep->e_numkey);
+ else if (ep->e_symkey)
+ outlet_symbol(x->x_keyout, ep->e_symkey);
+ else
+ outlet_float(x->x_keyout, 0);
+ if (cc->c_relinked) cc->c_selfmodified = 1;
+ cc->c_entered--;
+}
+
+static t_collelem *coll_findkey(t_coll *x, t_atom *key, t_symbol *mess)
+{
+ t_collcommon *cc = x->x_common;
+ t_collelem *ep = 0;
+ if (key->a_type == A_FLOAT)
+ {
+ int numkey;
+ if (loud_checkint((t_pd *)x, key->a_w.w_float, &numkey, mess))
+ ep = collcommon_numkey(cc, numkey);
+ else
+ mess = 0;
+ }
+ else if (key->a_type == A_SYMBOL)
+ ep = collcommon_symkey(cc, key->a_w.w_symbol);
+ else if (mess)
+ {
+ loud_messarg((t_pd *)x, mess);
+ mess = 0;
+ }
+ if (!ep && mess)
+ loud_error((t_pd *)x, "no such key");
+ return (ep);
+}
+
+static t_collelem *coll_tokey(t_coll *x, t_atom *key, int ac, t_atom *av,
+ int replace, t_symbol *mess)
+{
+ t_collcommon *cc = x->x_common;
+ t_collelem *ep = 0;
+ if (key->a_type == A_FLOAT)
+ {
+ int numkey;
+ if (loud_checkint((t_pd *)x, key->a_w.w_float, &numkey, mess))
+ ep = collcommon_tonumkey(cc, numkey, ac, av, replace);
+ }
+ else if (key->a_type == A_SYMBOL)
+ ep = collcommon_tosymkey(cc, key->a_w.w_symbol, ac, av, replace);
+ else if (mess)
+ loud_messarg((t_pd *)x, mess);
+ return (ep);
+}
+
+static t_collelem *coll_firsttyped(t_coll *x, int ndx, t_atomtype type)
+{
+ t_collcommon *cc = x->x_common;
+ t_collelem *ep;
+ for (ep = cc->c_first; ep; ep = ep->e_next)
+ if (ep->e_size > ndx && ep->e_data[ndx].a_type == type)
+ return (ep);
+ return (0);
+}
+
+/* the methods */
+
+static void coll_float(t_coll *x, t_float f)
+{
+ t_collcommon *cc = x->x_common;
+ t_collelem *ep;
+ int numkey;
+ if (loud_checkint((t_pd *)x, f, &numkey, &s_float) &&
+ (ep = collcommon_numkey(cc, numkey)))
+ {
+ coll_keyoutput(x, ep);
+ if (!cc->c_selfmodified || (ep = collcommon_numkey(cc, numkey)))
+ coll_dooutput(x, ep->e_size, ep->e_data);
+ }
+}
+
+static void coll_symbol(t_coll *x, t_symbol *s)
+{
+ t_collcommon *cc = x->x_common;
+ t_collelem *ep;
+ if (ep = collcommon_symkey(cc, s))
+ {
+ coll_keyoutput(x, ep);
+ if (!cc->c_selfmodified || (ep = collcommon_symkey(cc, s)))
+ coll_dooutput(x, ep->e_size, ep->e_data);
+ }
+}
+
+static void coll_list(t_coll *x, t_symbol *s, int ac, t_atom *av)
+{
+ if (ac >= 2 && av->a_type == A_FLOAT)
+ coll_tokey(x, av, ac-1, av+1, 1, &s_list);
+ else
+ loud_messarg((t_pd *)x, &s_list);
+}
+
+static void coll_anything(t_coll *x, t_symbol *s, int ac, t_atom *av)
+{
+ coll_symbol(x, s);
+}
+
+static void coll_store(t_coll *x, t_symbol *s, int ac, t_atom *av)
+{
+ if (ac >= 2)
+ coll_tokey(x, av, ac-1, av+1, 1, s);
+ else
+ loud_messarg((t_pd *)x, s);
+}
+
+static void coll_nstore(t_coll *x, t_symbol *s, int ac, t_atom *av)
+{
+ if (ac >= 3)
+ {
+ t_collcommon *cc = x->x_common;
+ t_collelem *ep;
+ int numkey;
+ if (av->a_type == A_FLOAT && av[1].a_type == A_SYMBOL)
+ {
+ if (loud_checkint((t_pd *)x, av->a_w.w_float, &numkey, s))
+ {
+ if (ep = collcommon_symkey(cc, av[1].a_w.w_symbol))
+ collcommon_remove(cc, ep);
+ ep = collcommon_tonumkey(cc, numkey, ac-2, av+2, 1);
+ ep->e_symkey = av[1].a_w.w_symbol;
+ }
+ }
+ else if (av->a_type == A_SYMBOL && av[1].a_type == A_FLOAT)
+ {
+ if (loud_checkint((t_pd *)x, av[1].a_w.w_float, &numkey, s))
+ {
+ if (ep = collcommon_numkey(cc, numkey))
+ collcommon_remove(cc, ep);
+ ep = collcommon_tosymkey(cc, av->a_w.w_symbol, ac-2, av+2, 1);
+ ep->e_hasnumkey = 1;
+ ep->e_numkey = numkey;
+ }
+ }
+ else loud_messarg((t_pd *)x, s);
+ }
+ else loud_messarg((t_pd *)x, s);
+}
+
+static void coll_insert(t_coll *x, t_symbol *s, int ac, t_atom *av)
+{
+ if (ac >= 2 && av->a_type == A_FLOAT)
+ coll_tokey(x, av, ac-1, av+1, 0, s);
+ else
+ loud_messarg((t_pd *)x, s);
+}
+
+static void coll_remove(t_coll *x, t_symbol *s, int ac, t_atom *av)
+{
+ if (ac)
+ {
+ t_collelem *ep;
+ if (ep = coll_findkey(x, av, s))
+ collcommon_remove(x->x_common, ep);
+ }
+ else loud_messarg((t_pd *)x, s);
+}
+
+static void coll_delete(t_coll *x, t_symbol *s, int ac, t_atom *av)
+{
+ if (ac)
+ {
+ t_collelem *ep;
+ if (ep = coll_findkey(x, av, s))
+ {
+ if (av->a_type == A_FLOAT)
+ {
+ int numkey = ep->e_numkey;
+ t_collelem *next;
+ for (next = ep->e_next; next; next = next->e_next)
+ if (next->e_hasnumkey && next->e_numkey > numkey)
+ next->e_numkey--;
+ }
+ collcommon_remove(x->x_common, ep);
+ }
+ }
+ else loud_messarg((t_pd *)x, s);
+}
+
+static void coll_assoc(t_coll *x, t_symbol *s, t_floatarg f)
+{
+ int numkey;
+ if (loud_checkint((t_pd *)x, f, &numkey, gensym("assoc")))
+ {
+ t_collcommon *cc = x->x_common;
+ t_collelem *ep1, *ep2;
+ if ((ep1 = collcommon_numkey(cc, numkey)) &&
+ ep1->e_symkey != s) /* LATER rethink */
+ {
+ if (ep2 = collcommon_symkey(cc, s))
+ collcommon_remove(cc, ep2);
+ collcommon_changesymkey(cc, ep1, s);
+ }
+ }
+}
+
+static void coll_deassoc(t_coll *x, t_symbol *s, t_floatarg f)
+{
+ int numkey;
+ if (loud_checkint((t_pd *)x, f, &numkey, gensym("deassoc")))
+ {
+ t_collcommon *cc = x->x_common;
+ t_collelem *ep;
+ if (ep = collcommon_numkey(cc, numkey))
+ collcommon_changesymkey(cc, ep, 0);
+ }
+}
+
+static void coll_subsym(t_coll *x, t_symbol *s1, t_symbol *s2)
+{
+ t_collelem *ep;
+ if (s1 != s2 && (ep = collcommon_symkey(x->x_common, s2)))
+ collcommon_changesymkey(x->x_common, ep, s1);
+}
+
+static void coll_renumber(t_coll *x, t_floatarg f)
+{
+ int startkey;
+ if (loud_checkint((t_pd *)x, f, &startkey, gensym("renumber")))
+ collcommon_renumber(x->x_common, startkey);
+}
+
+static void coll_merge(t_coll *x, t_symbol *s, int ac, t_atom *av)
+{
+ if (ac >= 2)
+ {
+ t_collcommon *cc = x->x_common;
+ t_collelem *ep;
+ if (av->a_type == A_FLOAT)
+ {
+ int numkey;
+ if (loud_checkint((t_pd *)x, av->a_w.w_float, &numkey, s))
+ {
+ if (ep = collcommon_numkey(cc, numkey))
+ collcommon_adddata(cc, ep, ac-1, av+1);
+ else /* LATER consider defining collcommon_toclosest() */
+ collcommon_tonumkey(cc, numkey, ac-1, av+1, 1);
+ }
+ }
+ else if (av->a_type == A_SYMBOL)
+ {
+ if (ep = collcommon_symkey(cc, av->a_w.w_symbol))
+ collcommon_adddata(cc, ep, ac-1, av+1);
+ else
+ {
+ ep = collelem_new(ac-1, av+1, 0, av->a_w.w_symbol);
+ collcommon_putafter(cc, ep, cc->c_last);
+ }
+ }
+ else loud_messarg((t_pd *)x, s);
+ }
+ else loud_messarg((t_pd *)x, s);
+}
+
+static void coll_sub(t_coll *x, t_symbol *s, int ac, t_atom *av)
+{
+ if (ac)
+ {
+ t_collelem *ep;
+ if (ep = coll_findkey(x, av, s))
+ {
+ t_collcommon *cc = x->x_common;
+ t_atom *key = av++;
+ ac--;
+ while (ac >= 2)
+ {
+ if (av->a_type == A_FLOAT)
+ {
+ int ndx;
+ if (loud_checkint((t_pd *)x, av->a_w.w_float, &ndx, 0)
+ && ndx >= 1 && ndx <= ep->e_size)
+ ep->e_data[ndx-1] = av[1];
+ }
+ ac -= 2;
+ av += 2;
+ }
+ if (s == gensym("sub"))
+ {
+ coll_keyoutput(x, ep);
+ if (!cc->c_selfmodified || (ep = coll_findkey(x, key, 0)))
+ coll_dooutput(x, ep->e_size, ep->e_data);
+ }
+ }
+ }
+ else loud_messarg((t_pd *)x, s);
+}
+
+static void coll_sort(t_coll *x, t_floatarg f1, t_floatarg f2)
+{
+ int dir, ndx;
+ if (loud_checkint((t_pd *)x, f1, &dir, gensym("sort")) &&
+ loud_checkint((t_pd *)x, f2, &ndx, gensym("sort")))
+ collcommon_sort(x->x_common, (dir < 0 ? 1 : 0),
+ (ndx < 0 ? -1 : (ndx ? ndx - 1 : 0)));
+}
+
+static void coll_clear(t_coll *x)
+{
+ collcommon_clearall(x->x_common);
+}
+
+/* According to the refman, the data should be swapped, rather than the keys
+ -- easy here, but apparently c74 people have chosen to avoid some effort
+ needed in case of their implementation... */
+static void coll_swap(t_coll *x, t_symbol *s, int ac, t_atom *av)
+{
+ if (ac == 2)
+ {
+ t_collelem *ep1, *ep2;
+ if ((ep1 = coll_findkey(x, av, s)) &&
+ (ep2 = coll_findkey(x, av + 1, s)))
+ collcommon_swapkeys(x->x_common, ep1, ep2);
+ }
+ else loud_messarg((t_pd *)x, s);
+}
+
+static void coll_next(t_coll *x)
+{
+ t_collcommon *cc = x->x_common;
+ if (!cc->c_ahead && !(cc->c_ahead = cc->c_first))
+ return;
+ coll_keyoutput(x, cc->c_ahead);
+ if (cc->c_selfmodified && !cc->c_ahead)
+ return;
+ coll_dooutput(x, cc->c_ahead->e_size, cc->c_ahead->e_data);
+ /* LATER think why c74 updates the heads prior to sendout
+ (it seems so clumsy...) */
+ if (!cc->c_ahead && !(cc->c_ahead = cc->c_first))
+ {
+ cc->c_back = 0;
+ return;
+ }
+ if (cc->c_ahead->e_next)
+ {
+ cc->c_ahead = cc->c_ahead->e_next;
+ if (!(cc->c_back = cc->c_ahead->e_prev)) /* LATER rethink */
+ cc->c_back = cc->c_last;
+ }
+ else
+ {
+ /* CHECKED wraping */
+ cc->c_back = cc->c_ahead;
+ cc->c_ahead = 0;
+ }
+}
+
+static void coll_prev(t_coll *x)
+{
+ t_collcommon *cc = x->x_common;
+ if (!cc->c_back && !(cc->c_back = cc->c_last))
+ return;
+ coll_keyoutput(x, cc->c_back);
+ if (cc->c_selfmodified && !cc->c_back)
+ return;
+ coll_dooutput(x, cc->c_back->e_size, cc->c_back->e_data);
+ /* LATER think why c74 updates the heads prior to sendout
+ (it seems so clumsy...) */
+ if (!cc->c_back && !(cc->c_back = cc->c_last))
+ {
+ cc->c_ahead = 0;
+ return;
+ }
+ if (cc->c_back->e_prev)
+ {
+ cc->c_back = cc->c_back->e_prev;
+ if (!(cc->c_ahead = cc->c_back->e_next)) /* LATER rethink */
+ cc->c_ahead = cc->c_first;
+ }
+ else
+ {
+ /* CHECKED wraping */
+ cc->c_ahead = cc->c_back;
+ cc->c_back = 0;
+ }
+}
+
+static void coll_end(t_coll *x)
+{
+ t_collcommon *cc = x->x_common;
+ cc->c_back = cc->c_ahead = cc->c_last;
+}
+
+static void coll_goto(t_coll *x, t_symbol *s, int ac, t_atom *av)
+{
+ if (ac)
+ {
+ t_collelem *ep = coll_findkey(x, av, s);
+ if (ep)
+ x->x_common->c_back = x->x_common->c_ahead = ep;
+ }
+ else loud_messarg((t_pd *)x, s);
+}
+
+static void coll_nth(t_coll *x, t_symbol *s, int ac, t_atom *av)
+{
+ if (ac >= 2 && av[1].a_type == A_FLOAT)
+ {
+ int ndx;
+ t_collelem *ep;
+ if (loud_checkint((t_pd *)x, av[1].a_w.w_float, &ndx, s) &&
+ (ep = coll_findkey(x, av, s)) &&
+ ep->e_size >= ndx)
+ {
+ t_atom *ap = ep->e_data + --ndx;
+ if (ap->a_type == A_FLOAT)
+ outlet_float(((t_object *)x)->ob_outlet, ap->a_w.w_float);
+ else if (ap->a_type == A_SYMBOL)
+ outlet_symbol(((t_object *)x)->ob_outlet, ap->a_w.w_symbol);
+ }
+ }
+ else loud_messarg((t_pd *)x, s);
+}
+
+static void coll_length(t_coll *x)
+{
+ t_collcommon *cc = x->x_common;
+ t_collelem *ep = cc->c_first;
+ int result = 0;
+ while (ep) result++, ep = ep->e_next;
+ outlet_float(((t_object *)x)->ob_outlet, result);
+}
+
+static void coll_min(t_coll *x, t_floatarg f)
+{
+ int ndx;
+ if (loud_checkint((t_pd *)x, f, &ndx, gensym("min")))
+ {
+ t_collelem *found;
+ if (ndx <= 0)
+ ndx = 0; /* LATER consider complaining, CHECKME */
+ else ndx--;
+ if (found = coll_firsttyped(x, ndx, A_FLOAT))
+ {
+ t_float result = found->e_data[ndx].a_w.w_float;
+ t_collelem *ep;
+ for (ep = found->e_next; ep; ep = ep->e_next)
+ {
+ if (ep->e_size > ndx &&
+ ep->e_data[ndx].a_type == A_FLOAT &&
+ ep->e_data[ndx].a_w.w_float < result)
+ {
+ found = ep;
+ result = ep->e_data[ndx].a_w.w_float;
+ }
+ }
+ coll_keyoutput(x, found);
+ outlet_float(((t_object *)x)->ob_outlet, result);
+ }
+ }
+}
+
+static void coll_max(t_coll *x, t_floatarg f)
+{
+ int ndx;
+ if (loud_checkint((t_pd *)x, f, &ndx, gensym("max")))
+ {
+ t_collelem *found;
+ if (ndx <= 0)
+ ndx = 0; /* LATER consider complaining, CHECKME */
+ else ndx--;
+ if (found = coll_firsttyped(x, ndx, A_FLOAT))
+ {
+ t_float result = found->e_data[ndx].a_w.w_float;
+ t_collelem *ep;
+ for (ep = found->e_next; ep; ep = ep->e_next)
+ {
+ if (ep->e_size > ndx &&
+ ep->e_data[ndx].a_type == A_FLOAT &&
+ ep->e_data[ndx].a_w.w_float > result)
+ {
+ found = ep;
+ result = ep->e_data[ndx].a_w.w_float;
+ }
+ }
+ coll_keyoutput(x, found);
+ outlet_float(((t_object *)x)->ob_outlet, result);
+ }
+ }
+}
+
+static void coll_refer(t_coll *x, t_symbol *s)
+{
+ if (!coll_rebind(x, s))
+ {
+ /* LATER consider complaining */
+ }
+}
+
+static void coll_flags(t_coll *x, t_float f1, t_float f2)
+{
+ int i1;
+ if (loud_checkint((t_pd *)x, f1, &i1, gensym("flags")))
+ {
+ t_collcommon *cc = x->x_common;
+ cc->c_embedflag = (i1 != 0);
+ }
+}
+
+static void coll_read(t_coll *x, t_symbol *s)
+{
+ t_collcommon *cc = x->x_common;
+ if (s && s != &s_)
+ collcommon_doread(cc, s, x->x_canvas);
+ else
+ hammerpanel_open(cc->c_filehandle);
+}
+
+static void coll_write(t_coll *x, t_symbol *s)
+{
+ t_collcommon *cc = x->x_common;
+ if (s && s != &s_)
+ collcommon_dowrite(cc, s, x->x_canvas);
+ else
+ hammerpanel_save(cc->c_filehandle, 0, 0); /* CHECKME default name */
+}
+
+static void coll_readagain(t_coll *x)
+{
+ t_collcommon *cc = x->x_common;
+ if (cc->c_filename)
+ collcommon_doread(cc, 0, 0);
+ else
+ hammerpanel_open(cc->c_filehandle);
+}
+
+static void coll_writeagain(t_coll *x)
+{
+ t_collcommon *cc = x->x_common;
+ if (cc->c_filename)
+ collcommon_dowrite(cc, 0, 0);
+ else
+ hammerpanel_save(cc->c_filehandle, 0, 0); /* CHECKME default name */
+}
+
+static void coll_filetype(t_coll *x, t_symbol *s)
+{
+ /* dummy */
+}
+
+static void coll_dump(t_coll *x)
+{
+ t_collcommon *cc = x->x_common;
+ t_collelem *ep;
+ for (ep = cc->c_first; ep; ep = ep->e_next)
+ {
+ coll_keyoutput(x, ep);
+ if (cc->c_selfmodified)
+ break;
+ coll_dooutput(x, ep->e_size, ep->e_data);
+ }
+ outlet_bang(x->x_dumpbangout);
+}
+
+static void coll_open(t_coll *x)
+{
+ t_collcommon *cc = x->x_common;
+ t_binbuf *bb = binbuf_new();
+ int i, natoms, newline;
+ t_atom *ap;
+ char buf[MAXPDSTRING];
+ /* LATER prepend "coll: " */
+ hammereditor_open(cc->c_filehandle,
+ x->x_name ? x->x_name->s_name : "Untitled");
+ collcommon_tobinbuf(cc, bb);
+ natoms = binbuf_getnatom(bb);
+ ap = binbuf_getvec(bb);
+ newline = 1;
+ while (natoms--)
+ {
+ char *ptr = buf;
+ if (ap->a_type != A_SEMI && ap->a_type != A_COMMA && !newline)
+ *ptr++ = ' ';
+ atom_string(ap, ptr, MAXPDSTRING);
+ if (ap->a_type == A_SEMI)
+ {
+ strcat(buf, "\n");
+ newline = 1;
+ }
+ else newline = 0;
+ hammereditor_append(cc->c_filehandle, buf);
+ ap++;
+ }
+ binbuf_free(bb);
+}
+
+/* asking and storing the changes -- CHECKME close window, and 'wclose' */
+static void coll_wclose(t_coll *x)
+{
+ hammereditor_close(x->x_common->c_filehandle, 1);
+}
+
+static void coll_click(t_coll *x, t_floatarg xpos, t_floatarg ypos,
+ t_floatarg shift, t_floatarg ctrl, t_floatarg alt)
+{
+ coll_open(x);
+}
+
+#ifdef COLL_DEBUG
+static void coll_debug(t_coll *x, t_floatarg f)
+{
+ t_collcommon *cc = coll_checkcommon(x);
+ if (cc)
+ {
+ t_coll *x1 = cc->c_refs;
+ t_collelem *ep, *last;
+ int i = 0;
+ while (x1) i++, x1 = x1->x_next;
+ post("refcount %d", i);
+ for (ep = cc->c_first, last = 0; ep; ep = ep->e_next) last = ep;
+ if (last != cc->c_last) bug("coll_debug: last element");
+ collcommon_post(cc);
+ }
+}
+#endif
+
+static void coll_free(t_coll *x)
+{
+ hammerfile_free(x->x_filehandle);
+ coll_unbind(x);
+}
+
+static void *coll_new(t_symbol *s)
+{
+ t_coll *x = (t_coll *)pd_new(coll_class);
+ x->x_canvas = canvas_getcurrent();
+ outlet_new((t_object *)x, &s_);
+ x->x_keyout = outlet_new((t_object *)x, &s_);
+ x->x_filebangout = outlet_new((t_object *)x, &s_bang);
+ x->x_dumpbangout = outlet_new((t_object *)x, &s_bang);
+ x->x_filehandle = hammerfile_new((t_pd *)x, coll_embedhook, 0, 0, 0);
+ coll_bind(x, s);
+ return (x);
+}
+
+void coll_setup(void)
+{
+ coll_class = class_new(gensym("coll"),
+ (t_newmethod)coll_new,
+ (t_method)coll_free,
+ sizeof(t_coll), 0, A_DEFSYM, 0);
+ class_addbang(coll_class, coll_next);
+ class_addfloat(coll_class, coll_float);
+ class_addsymbol(coll_class, coll_symbol);
+ class_addlist(coll_class, coll_list);
+ class_addanything(coll_class, coll_anything);
+ class_addmethod(coll_class, (t_method)coll_store,
+ gensym("store"), A_GIMME, 0);
+ class_addmethod(coll_class, (t_method)coll_nstore,
+ gensym("nstore"), A_GIMME, 0);
+ class_addmethod(coll_class, (t_method)coll_insert,
+ gensym("insert"), A_GIMME, 0);
+ class_addmethod(coll_class, (t_method)coll_remove,
+ gensym("remove"), A_GIMME, 0);
+ class_addmethod(coll_class, (t_method)coll_delete,
+ gensym("delete"), A_GIMME, 0);
+ class_addmethod(coll_class, (t_method)coll_assoc,
+ gensym("assoc"), A_SYMBOL, A_FLOAT, 0);
+ class_addmethod(coll_class, (t_method)coll_deassoc,
+ gensym("deassoc"), A_SYMBOL, A_FLOAT, 0);
+ class_addmethod(coll_class, (t_method)coll_subsym,
+ gensym("subsym"), A_SYMBOL, A_SYMBOL, 0);
+ class_addmethod(coll_class, (t_method)coll_renumber,
+ gensym("renumber"), A_DEFFLOAT, 0);
+ class_addmethod(coll_class, (t_method)coll_merge,
+ gensym("merge"), A_GIMME, 0);
+ class_addmethod(coll_class, (t_method)coll_sub,
+ gensym("sub"), A_GIMME, 0);
+ class_addmethod(coll_class, (t_method)coll_sub,
+ gensym("nsub"), A_GIMME, 0);
+ class_addmethod(coll_class, (t_method)coll_clear,
+ gensym("clear"), 0);
+ class_addmethod(coll_class, (t_method)coll_sort,
+ gensym("sort"), A_FLOAT, A_DEFFLOAT, 0);
+ class_addmethod(coll_class, (t_method)coll_swap,
+ gensym("swap"), A_GIMME, 0);
+ class_addmethod(coll_class, (t_method)coll_next,
+ gensym("next"), 0);
+ class_addmethod(coll_class, (t_method)coll_prev,
+ gensym("prev"), 0);
+ class_addmethod(coll_class, (t_method)coll_end,
+ gensym("end"), 0);
+ class_addmethod(coll_class, (t_method)coll_goto,
+ gensym("goto"), A_GIMME, 0);
+ class_addmethod(coll_class, (t_method)coll_nth,
+ gensym("nth"), A_GIMME, 0);
+ class_addmethod(coll_class, (t_method)coll_length,
+ gensym("length"), 0);
+ class_addmethod(coll_class, (t_method)coll_min,
+ gensym("min"), A_DEFFLOAT, 0);
+ class_addmethod(coll_class, (t_method)coll_max,
+ gensym("max"), A_DEFFLOAT, 0);
+ class_addmethod(coll_class, (t_method)coll_refer,
+ gensym("refer"), A_SYMBOL, 0);
+ class_addmethod(coll_class, (t_method)coll_flags,
+ gensym("flags"), A_FLOAT, A_FLOAT, 0);
+ class_addmethod(coll_class, (t_method)coll_read,
+ gensym("read"), A_DEFSYM, 0);
+ class_addmethod(coll_class, (t_method)coll_write,
+ gensym("write"), A_DEFSYM, 0);
+ class_addmethod(coll_class, (t_method)coll_readagain,
+ gensym("readagain"), 0);
+ class_addmethod(coll_class, (t_method)coll_writeagain,
+ gensym("writeagain"), 0);
+ class_addmethod(coll_class, (t_method)coll_filetype,
+ gensym("filetype"), A_SYMBOL, 0);
+ class_addmethod(coll_class, (t_method)coll_dump,
+ gensym("dump"), 0);
+ class_addmethod(coll_class, (t_method)coll_open,
+ gensym("open"), 0);
+ class_addmethod(coll_class, (t_method)coll_wclose,
+ gensym("wclose"), 0);
+ class_addmethod(coll_class, (t_method)coll_click,
+ gensym("click"),
+ A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0);
+#ifdef COLL_DEBUG
+ class_addmethod(coll_class, (t_method)coll_debug,
+ gensym("debug"), A_DEFFLOAT, 0);
+#endif
+ hammerfile_setup(coll_class, 1);
+ collcommon_class = class_new(gensym("coll"), 0, 0,
+ sizeof(t_collcommon), CLASS_PD, 0);
+ /* this call is a nop (collcommon does not embed, and the hammerfile
+ class itself has been already set up above), but it is better to
+ have it around, just in case... */
+ hammerfile_setup(collcommon_class, 0);
+}
diff --git a/cyclone/hammer/comment.c b/cyclone/hammer/comment.c
new file mode 100644
index 0000000..e5cd5ab
--- /dev/null
+++ b/cyclone/hammer/comment.c
@@ -0,0 +1,835 @@
+/* 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 creation lag (X-specific) */
+/* LATER think about pushing text to the text editor (ctrl-t)
+ -- not easy, because we are not 'textedfor' */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include "m_pd.h"
+#include "g_canvas.h"
+#include "common/loud.h"
+
+/* our proxy of the text_class (not in the API), LATER do not cheat */
+static t_class *makeshift_class;
+
+//#define COMMENT_DEBUG
+
+#define COMMENT_LMARGIN 1
+#define COMMENT_RMARGIN 1
+#define COMMENT_TMARGIN 2
+#define COMMENT_BMARGIN 2
+#define COMMENT_MINWIDTH 8
+#define COMMENT_HANDLEWIDTH 8
+#define COMMENT_OUTBUFSIZE 1000
+
+typedef struct _comment
+{
+ t_object x_ob;
+ t_glist *x_glist;
+ t_canvas *x_canvas; /* also an 'isvised' flag */
+ t_symbol *x_bindsym;
+ char x_tag[32];
+ char x_texttag[32];
+ char x_outlinetag[32];
+ t_clock *x_transclock;
+ t_binbuf *x_binbuf;
+ char *x_textbuf;
+ int x_textbufsize;
+ int x_pixwidth;
+ int x_bbset;
+ int x_bbpending;
+ int x_x1;
+ int x_y1;
+ int x_x2;
+ int x_y2;
+ int x_newx2;
+ int x_dragon;
+ int x_fontsize; /* requested size */
+ t_symbol *x_fontfamily; /* requested family */
+ int x_fontprops; /* LATER pack weight and slant */
+ t_symbol *x_encoding; /* requested encoding */
+ unsigned char x_red;
+ unsigned char x_green;
+ unsigned char x_blue;
+ char x_color[8];
+ int x_selstart;
+ int x_selend;
+ int x_active;
+ int x_ready;
+} t_comment;
+
+static t_class *comment_class;
+static t_class *commentsink_class;
+
+static t_pd *commentsink = 0;
+
+static void comment_draw(t_comment *x)
+{
+ char buf[COMMENT_OUTBUFSIZE], *outbuf, *outp;
+ int cvid = (int)x->x_canvas;
+ int reqsize = x->x_textbufsize + 350; /* FIXME estimation */
+ if (reqsize > COMMENT_OUTBUFSIZE)
+ {
+#ifdef COMMENT_DEBUG
+ post("allocating %d outbuf bytes", reqsize);
+#endif
+ if (!(outbuf = getbytes(reqsize)))
+ return;
+ }
+ else outbuf = buf;
+ outp = outbuf;
+ if (x->x_encoding)
+ sprintf(outp, "set tt [comment_entext %s {%.*s}]\n",
+ x->x_encoding->s_name, x->x_textbufsize, x->x_textbuf);
+ else
+ sprintf(outp, "set tt {%.*s}\n", x->x_textbufsize, x->x_textbuf);
+ outp += strlen(outp);
+ sprintf(outp, ".x%x.c create text %f %f -text $tt \
+ -tags {%s %s} -font {%s %d} -fill %s", cvid,
+ (float)(text_xpix((t_text *)x, x->x_glist) + COMMENT_LMARGIN),
+ (float)(text_ypix((t_text *)x, x->x_glist) + COMMENT_TMARGIN),
+ x->x_texttag, x->x_tag, x->x_fontfamily->s_name, x->x_fontsize,
+ (glist_isselected(x->x_glist, &x->x_glist->gl_gobj) ?
+ "blue" : x->x_color));
+ outp += strlen(outp);
+ if (x->x_pixwidth)
+ sprintf(outp, " -width %d -anchor nw\n", x->x_pixwidth);
+ else
+ strcpy(outp, " -anchor nw\n");
+ outp += strlen(outp);
+ sprintf(outp, "comment_bbox %s .x%x.c %s\n",
+ x->x_bindsym->s_name, cvid, x->x_texttag);
+ outp += strlen(outp);
+ sprintf(outp, ".x%x.c bind %s <Button> {comment_click %s %%W %%x %%y %s}\n",
+ cvid, x->x_texttag, x->x_bindsym->s_name, x->x_texttag);
+ x->x_bbpending = 1;
+ sys_gui(outbuf);
+ if (outbuf != buf) freebytes(outbuf, reqsize);
+}
+
+static void comment_update(t_comment *x)
+{
+ char buf[COMMENT_OUTBUFSIZE], *outbuf, *outp;
+ int cvid = (int)x->x_canvas;
+ int reqsize = x->x_textbufsize + 250; /* FIXME estimation */
+ if (reqsize > COMMENT_OUTBUFSIZE)
+ {
+#ifdef COMMENT_DEBUG
+ post("allocating %d outbuf bytes", reqsize);
+#endif
+ if (!(outbuf = getbytes(reqsize)))
+ return;
+ }
+ else outbuf = buf;
+ outp = outbuf;
+ if (x->x_encoding)
+ sprintf(outp, "set tt [comment_entext %s {%.*s}]\n",
+ x->x_encoding->s_name, x->x_textbufsize, x->x_textbuf);
+ else
+ sprintf(outp, "set tt {%.*s}\n", x->x_textbufsize, x->x_textbuf);
+ outp += strlen(outp);
+ if (x->x_pixwidth)
+ sprintf(outp, ".x%x.c itemconfig %s -text $tt -width %d\n",
+ cvid, x->x_texttag, x->x_pixwidth);
+ else
+ sprintf(outp, ".x%x.c itemconfig %s -text $tt\n", cvid, x->x_texttag);
+ outp += strlen(outp);
+ if (x->x_active)
+ {
+ if (x->x_selend > x->x_selstart)
+ {
+ sprintf(outp, ".x%x.c select from %s %d\n",
+ cvid, x->x_texttag, x->x_selstart);
+ outp += strlen(outp);
+ sprintf(outp, ".x%x.c select to %s %d\n",
+ cvid, x->x_texttag, x->x_selend);
+ outp += strlen(outp);
+ sprintf(outp, ".x%x.c focus {}\n", cvid);
+ }
+ else
+ {
+ sprintf(outp, ".x%x.c select clear\n", cvid);
+ outp += strlen(outp);
+ sprintf(outp, ".x%x.c icursor %s %d\n",
+ cvid, x->x_texttag, x->x_selstart);
+ outp += strlen(outp);
+ sprintf(outp, ".x%x.c focus %s\n", cvid, x->x_texttag);
+ }
+ outp += strlen(outp);
+ }
+ sprintf(outp, "comment_bbox %s .x%x.c %s\n",
+ x->x_bindsym->s_name, cvid, x->x_texttag);
+ x->x_bbpending = 1;
+ sys_gui(outbuf);
+ if (outbuf != buf) freebytes(outbuf, reqsize);
+}
+
+static void comment_validate(t_comment *x, t_glist *glist)
+{
+ if (!x->x_ready)
+ {
+ t_text *t = (t_text *)x;
+ binbuf_free(t->te_binbuf);
+ t->te_binbuf = x->x_binbuf;
+ if (x->x_textbuf) freebytes(x->x_textbuf, x->x_textbufsize);
+ binbuf_gettext(x->x_binbuf, &x->x_textbuf, &x->x_textbufsize);
+ x->x_ready = 1;
+#ifdef COMMENT_DEBUG
+ post("validation done");
+#endif
+ }
+ if (glist)
+ {
+ if (glist != x->x_glist)
+ {
+ bug("comment_getcanvas");
+ x->x_glist = glist;
+ }
+ x->x_canvas = glist_getcanvas(glist);
+ }
+}
+
+static void comment_grabbedkey(void *z, t_floatarg f)
+{
+ /* LATER think about replacing #key binding/comment_float() with grabbing */
+}
+
+static void comment_dograb(t_comment *x)
+{
+ /* LATER investigate the grabbing feature.
+ Here we use it just to prevent backspace from erasing entire text.
+ This has to be done also when we are already active, because
+ after being clicked at we have lost our previous grab. */
+ glist_grab(x->x_glist, (t_gobj *)x, 0, comment_grabbedkey, 0, 0);
+}
+
+static void comment__bboxhook(t_comment *x, t_symbol *bindsym,
+ t_floatarg x1, t_floatarg y1,
+ t_floatarg x2, t_floatarg y2)
+{
+#ifdef COMMENT_DEBUG
+ post("bbox %g %g %g %g", x1, y1, x2, y2);
+#endif
+ x->x_x1 = x1;
+ x->x_y1 = y1;
+ x->x_x2 = x2;
+ x->x_y2 = y2;
+ x->x_bbset = 1;
+ x->x_bbpending = 0;
+}
+
+static void comment__clickhook(t_comment *x, t_symbol *s, int ac, t_atom *av)
+{
+ int xx, yy, ndx;
+ if (ac == 8 && av->a_type == A_SYMBOL
+ && av[1].a_type == A_FLOAT && av[2].a_type == A_FLOAT
+ && av[3].a_type == A_FLOAT
+ && av[4].a_type == A_FLOAT && av[5].a_type == A_FLOAT
+ && av[6].a_type == A_FLOAT && av[7].a_type == A_FLOAT)
+ {
+ xx = (int)av[1].a_w.w_float;
+ yy = (int)av[2].a_w.w_float;
+ ndx = (int)av[3].a_w.w_float;
+ comment__bboxhook(x, av->a_w.w_symbol,
+ av[4].a_w.w_float, av[5].a_w.w_float,
+ av[6].a_w.w_float, av[7].a_w.w_float);
+ }
+ else
+ {
+ bug("comment__clickhook");
+ return;
+ }
+ if (x->x_glist->gl_edit)
+ {
+ if (x->x_active)
+ {
+ if (ndx >= 0 && ndx < x->x_textbufsize)
+ {
+ /* set selection, LATER shift-click and drag */
+ x->x_selstart = x->x_selend = ndx;
+ comment_dograb(x);
+ comment_update(x);
+ }
+ }
+ else if (xx > x->x_x2 - COMMENT_HANDLEWIDTH)
+ {
+ /* start resizing */
+ char buf[COMMENT_OUTBUFSIZE], *outp = buf;
+ int cvid = (int)x->x_canvas;
+ sprintf(outp, ".x%x.c bind %s <ButtonRelease> \
+ {pd [concat %s _release %s \\;]}\n", cvid, x->x_texttag,
+ x->x_bindsym->s_name, x->x_bindsym->s_name);
+ outp += strlen(outp);
+ sprintf(outp, ".x%x.c bind %s <Motion> \
+ {pd [concat %s _motion %s %%x %%y \\;]}\n", cvid, x->x_texttag,
+ x->x_bindsym->s_name, x->x_bindsym->s_name);
+ outp += strlen(outp);
+ sprintf(outp, ".x%x.c create rectangle %d %d %d %d -outline blue \
+ -tags {%s %s}\n",
+ cvid, x->x_x1, x->x_y1, x->x_x2, x->x_y2,
+ x->x_outlinetag, x->x_tag);
+ sys_gui(buf);
+ x->x_newx2 = x->x_x2;
+ x->x_dragon = 1;
+ }
+ }
+}
+
+static void comment__releasehook(t_comment *x, t_symbol *bindsym)
+{
+ int cvid = (int)x->x_canvas;
+ sys_vgui(".x%x.c bind %s <ButtonRelease> {}\n", cvid, x->x_texttag);
+ sys_vgui(".x%x.c bind %s <Motion> {}\n", cvid, x->x_texttag);
+ sys_vgui(".x%x.c delete %s\n", cvid, x->x_outlinetag);
+ x->x_dragon = 0;
+ if (x->x_newx2 != x->x_x2)
+ {
+ x->x_pixwidth = x->x_newx2 - x->x_x1;
+ x->x_x2 = x->x_newx2;
+ comment_update(x);
+ }
+}
+
+static void comment__motionhook(t_comment *x, t_symbol *bindsym,
+ t_floatarg xx, t_floatarg yy)
+{
+ int cvid = (int)x->x_canvas;
+ if (xx > x->x_x1 + COMMENT_MINWIDTH)
+ sys_vgui(".x%x.c coords %s %d %d %d %d\n",
+ cvid, x->x_outlinetag,
+ x->x_x1, x->x_y1, x->x_newx2 = xx, x->x_y2);
+}
+
+static void commentsink__bboxhook(t_pd *x, t_symbol *bindsym,
+ t_floatarg x1, t_floatarg y1,
+ t_floatarg x2, t_floatarg y2)
+{
+ if (bindsym->s_thing == x) /* is the comment gone? */
+ {
+ pd_unbind(x, bindsym); /* if so, no need for this binding anymore */
+#ifdef COMMENT_DEBUG
+ post("sink: %s unbound", bindsym->s_name);
+#endif
+ }
+}
+
+static void commentsink_anything(t_pd *x, t_symbol *s, int ac, t_atom *av)
+{
+ /* nop */
+}
+
+static void comment_getrect(t_gobj *z, t_glist *glist,
+ int *xp1, int *yp1, int *xp2, int *yp2)
+{
+ t_comment *x = (t_comment *)z;
+ if (!glist->gl_havewindow)
+ {
+ /* LATER revisit gop behaviour. Currently text_shouldvis() returns
+ true if we are on parent. Here we return a null rectangle,
+ so that any true ui object is accessible, even if it happens
+ to be covered by a comment. */
+ *xp1 = *yp1 = *xp2 = *yp2 = 0;
+ return;
+ }
+ if (x->x_bbset)
+ {
+ /* LATER think about margins */
+ *xp1 = x->x_x1;
+ *yp1 = x->x_y1;
+ *xp2 = x->x_x2;
+ *yp2 = x->x_y2;
+ }
+ else
+ {
+ int width, height;
+ float x1, y1, x2, y2;
+ comment_validate(x, glist);
+ if ((width = x->x_pixwidth) < 1)
+ /* FIXME estimation */
+ width = x->x_fontsize * x->x_textbufsize;
+ width += COMMENT_LMARGIN + COMMENT_RMARGIN;
+ /* FIXME estimation */
+ height = x->x_fontsize + COMMENT_TMARGIN + COMMENT_BMARGIN;
+ x1 = text_xpix((t_text *)x, glist);
+ y1 = text_ypix((t_text *)x, glist) + 1; /* LATER revisit */
+ x2 = x1 + width;
+ y2 = y1 + height - 2; /* LATER revisit */
+#ifdef COMMENT_DEBUG
+ post("estimated rectangle: %g %g %g %g", x1, y1, x2, y2);
+#endif
+ *xp1 = x1;
+ *yp1 = y1;
+ *xp2 = x2;
+ *yp2 = y2;
+ }
+}
+
+static void comment_displace(t_gobj *z, t_glist *glist, int dx, int dy)
+{
+ t_comment *x = (t_comment *)z;
+ if (!x->x_active && !x->x_dragon) /* LATER rethink */
+ {
+ t_text *t = (t_text *)z;
+ comment_validate(x, glist);
+ t->te_xpix += dx;
+ t->te_ypix += dy;
+ if (x->x_bbset)
+ {
+ x->x_x1 += dx;
+ x->x_y1 += dy;
+ x->x_x2 += dx;
+ x->x_y2 += dy;
+ }
+ if (glist_isvisible(glist))
+ sys_vgui(".x%x.c move %s %d %d\n", x->x_canvas, x->x_tag, dx, dy);
+ }
+}
+
+static void comment_activate(t_gobj *z, t_glist *glist, int state)
+{
+ t_comment *x = (t_comment *)z;
+ comment_validate(x, glist);
+ if (state)
+ {
+ comment_dograb(x);
+ if (x->x_active)
+ return;
+ sys_vgui(".x%x.c focus %s\n", x->x_canvas, x->x_texttag);
+ x->x_selstart = 0;
+ x->x_selend = x->x_textbufsize;
+ x->x_active = 1;
+ pd_bind((t_pd *)x, gensym("#key"));
+ pd_bind((t_pd *)x, gensym("#keyname"));
+ }
+ else
+ {
+ if (!x->x_active)
+ return;
+ pd_unbind((t_pd *)x, gensym("#key"));
+ pd_unbind((t_pd *)x, gensym("#keyname"));
+ sys_vgui("selection clear .x%x.c\n", x->x_canvas);
+ sys_vgui(".x%x.c focus {}\n", x->x_canvas);
+ x->x_active = 0;
+ }
+ comment_update(x);
+}
+
+static void comment_select(t_gobj *z, t_glist *glist, int state)
+{
+ t_comment *x = (t_comment *)z;
+ comment_validate(x, glist);
+ if (!state && x->x_active) comment_activate(z, glist, 0);
+ sys_vgui(".x%x.c itemconfigure %s -fill %s\n", x->x_canvas,
+ x->x_texttag, (state ? "blue" : x->x_color));
+ /* A regular rtext should now set 'canvas_editing' variable to its canvas,
+ but we do not do that, because we get the keys through a global binding
+ to "#key" (and because 'canvas_editing' is not exported). */
+}
+
+static void comment_vis(t_gobj *z, t_glist *glist, int vis)
+{
+ t_comment *x = (t_comment *)z;
+ t_text *t = (t_text *)z;
+ comment_validate(x, glist);
+ if (vis)
+ {
+ /* We do not need no rtext -- we are never 'textedfor' (thus
+ avoiding rtext calls). Creating an rtext has no other purpose
+ than complying to a Pd's assumption about every visible object
+ having an rtext (thus preventing canvas_doclick() from sending
+ garbage warnings). LATER revisit. */
+#ifndef PD_MINOR_VERSION
+ rtext_new(glist, t, glist->gl_editor->e_rtext, 0);
+#endif
+ if (glist->gl_havewindow)
+ comment_draw(x);
+ }
+ else
+ {
+#ifndef PD_MINOR_VERSION
+ t_rtext *rt = glist_findrtext(glist, t);
+ if (rt) rtext_free(rt);
+#endif
+ /* FIXME should we test for having a window? */
+#ifdef COMMENT_DEBUG
+ post("deleting...");
+#endif
+ sys_vgui(".x%x.c delete %s\n", x->x_canvas, x->x_tag);
+ }
+}
+
+static void comment_save(t_gobj *z, t_binbuf *b)
+{
+ t_comment *x = (t_comment *)z;
+ t_text *t = (t_text *)x;
+ comment_validate(x, 0);
+ binbuf_addv(b, "ssiisiissiiii", gensym("#X"), gensym("obj"),
+ (int)t->te_xpix, (int)t->te_ypix,
+ gensym("comment"),
+ x->x_pixwidth, x->x_fontsize, x->x_fontfamily,
+ (x->x_encoding ? x->x_encoding : gensym("?")),
+ x->x_fontprops,
+ (int)x->x_red, (int)x->x_green, (int)x->x_blue);
+ binbuf_addbinbuf(b, t->te_binbuf);
+ binbuf_addv(b, ";");
+}
+
+static t_widgetbehavior comment_widgetbehavior =
+{
+ comment_getrect,
+ comment_displace,
+ comment_select,
+ comment_activate,
+ 0,
+ comment_vis,
+ 0,
+ comment_save,
+ 0,
+};
+
+/* this fires if a transform request was sent to a symbol we are bound to */
+static void comment_transtick(t_comment *x)
+{
+ glist_delete(x->x_glist, (t_gobj *)x);
+}
+
+/* what follows is basically the original code of rtext_key() */
+
+static void comment_float(t_comment *x, t_float f)
+{
+ if (x->x_active)
+ {
+ int keynum = (int)f;
+ if (keynum)
+ {
+ int i, newsize, ndel;
+ char *s1, *s2;
+ int n = keynum;
+ if (n == '\r') n = '\n';
+ if (n == '\b')
+ {
+ if ((!x->x_selstart) && (x->x_selend == x->x_textbufsize))
+ {
+ /* LATER delete the box... this causes reentrancy
+ problems now. */
+ /* glist_delete(x->x_glist, &x->x_text->te_g); */
+ return;
+ }
+ else if (x->x_selstart && (x->x_selstart == x->x_selend))
+ x->x_selstart--;
+ }
+ ndel = x->x_selend - x->x_selstart;
+ for (i = x->x_selend; i < x->x_textbufsize; i++)
+ x->x_textbuf[i- ndel] = x->x_textbuf[i];
+ newsize = x->x_textbufsize - ndel;
+ x->x_textbuf = resizebytes(x->x_textbuf, x->x_textbufsize, newsize);
+ x->x_textbufsize = newsize;
+
+ if (n == '\n' || !iscntrl(n))
+ {
+#ifdef COMMENT_DEBUG
+ post("%d accepted", n);
+#endif
+ newsize = x->x_textbufsize+1;
+ x->x_textbuf = resizebytes(x->x_textbuf,
+ x->x_textbufsize, newsize);
+ for (i = x->x_textbufsize; i > x->x_selstart; i--)
+ x->x_textbuf[i] = x->x_textbuf[i-1];
+ x->x_textbuf[x->x_selstart] = n;
+ x->x_textbufsize = newsize;
+ x->x_selstart = x->x_selstart + 1;
+ }
+#ifdef COMMENT_DEBUG
+ else post("%d rejected", n);
+#endif
+ x->x_selend = x->x_selstart;
+ x->x_glist->gl_editor->e_textdirty = 1;
+ binbuf_text(x->x_binbuf, x->x_textbuf, x->x_textbufsize);
+ comment_update(x);
+ }
+ }
+ else bug("comment_float");
+}
+
+static void comment_list(t_comment *x, t_symbol *s, int ac, t_atom *av)
+{
+ if (!x->x_active)
+ bug("comment_list");
+ else if (ac > 1 && av->a_type == A_FLOAT && (int)av->a_w.w_float
+ && av[1].a_type == A_SYMBOL)
+ {
+ t_symbol *keysym = av[1].a_w.w_symbol;
+ if (!strcmp(keysym->s_name, "Right"))
+ {
+ if (x->x_selend == x->x_selstart &&
+ x->x_selstart < x->x_textbufsize)
+ x->x_selend = x->x_selstart = x->x_selstart + 1;
+ else
+ x->x_selstart = x->x_selend;
+ }
+ else if (!strcmp(keysym->s_name, "Left"))
+ {
+ if (x->x_selend == x->x_selstart && x->x_selstart > 0)
+ x->x_selend = x->x_selstart = x->x_selstart - 1;
+ else
+ x->x_selend = x->x_selstart;
+ }
+ /* this should be improved... life's too short */
+ else if (!strcmp(keysym->s_name, "Up"))
+ {
+ if (x->x_selstart)
+ x->x_selstart--;
+ while (x->x_selstart > 0 && x->x_textbuf[x->x_selstart] != '\n')
+ x->x_selstart--;
+ x->x_selend = x->x_selstart;
+ }
+ else if (!strcmp(keysym->s_name, "Down"))
+ {
+ while (x->x_selend < x->x_textbufsize &&
+ x->x_textbuf[x->x_selend] != '\n')
+ x->x_selend++;
+ if (x->x_selend < x->x_textbufsize)
+ x->x_selend++;
+ x->x_selstart = x->x_selend;
+ }
+ else if (!strcmp(keysym->s_name, "F4"))
+ {
+ t_text *newt, *oldt = (t_text *)x;
+ t_binbuf *bb = binbuf_new();
+ int ac = binbuf_getnatom(x->x_binbuf);
+ binbuf_addv(bb, "siissiiii", gensym("comment"), x->x_pixwidth,
+ x->x_fontsize, x->x_fontfamily,
+ (x->x_encoding ? x->x_encoding : gensym("?")),
+ x->x_fontprops,
+ (int)x->x_red, (int)x->x_green, (int)x->x_blue);
+ binbuf_add(bb, ac, binbuf_getvec(x->x_binbuf));
+ canvas_setcurrent(x->x_glist);
+ newt = (t_text *)pd_new(makeshift_class);
+ newt->te_width = 0;
+ newt->te_type = T_OBJECT;
+ newt->te_binbuf = bb;
+ newt->te_xpix = oldt->te_xpix;
+ newt->te_ypix = oldt->te_ypix;
+ glist_add(x->x_glist, &newt->te_g);
+ glist_noselect(x->x_glist);
+ glist_select(x->x_glist, &newt->te_g);
+ gobj_activate(&newt->te_g, x->x_glist, 1);
+ x->x_glist->gl_editor->e_textdirty = 1; /* force evaluation */
+ canvas_unsetcurrent(x->x_glist);
+ canvas_dirty(x->x_glist, 1);
+ clock_delay(x->x_transclock, 0); /* LATER rethink */
+ return;
+ }
+ else if (!strcmp(keysym->s_name, "F5"))
+ {
+ t_text *t = (t_text *)x;
+ t_binbuf *bb = binbuf_new();
+ int ac = binbuf_getnatom(x->x_binbuf);
+ binbuf_addv(bb, "ii", (int)t->te_xpix + 5, (int)t->te_ypix + 5);
+ binbuf_add(bb, ac, binbuf_getvec(x->x_binbuf));
+ canvas_setcurrent(x->x_glist);
+ typedmess((t_pd *)x->x_glist, gensym("text"),
+ ac + 2, binbuf_getvec(bb));
+ canvas_unsetcurrent(x->x_glist);
+ canvas_dirty(x->x_glist, 1);
+ binbuf_free(bb);
+ return;
+ }
+ else return;
+ comment_update(x);
+ }
+}
+
+static void comment_free(t_comment *x)
+{
+ if (x->x_active)
+ {
+ bug("comment_free");
+ pd_unbind((t_pd *)x, gensym("#key"));
+ pd_unbind((t_pd *)x, gensym("#keyname"));
+ }
+ if (x->x_transclock) clock_free(x->x_transclock);
+ if (x->x_bindsym)
+ {
+ pd_unbind((t_pd *)x, x->x_bindsym);
+ if (!x->x_bbpending)
+ pd_unbind(commentsink, x->x_bindsym);
+ }
+ if (x->x_binbuf && !x->x_ready) binbuf_free(x->x_binbuf);
+ if (x->x_textbuf) freebytes(x->x_textbuf, x->x_textbufsize);
+}
+
+/* the arguments in the full form of a creation message are:
+
+ width fontsize fontfamily encoding fontprops red green blue text...
+
+ For comments typed into an object box, the text part begins with
+ the first atom satisfying one of the following conditions (skipped
+ arguments get default values):
+
+ . having a different type than the corresponding argument of the
+ full form
+
+ . being preceded with a dot atom ('.') put in place of a symbol
+ argument (fontfamily or encoding)
+
+ . being the 10th atom in a box
+
+ The question mark atom ('?') may be used to supply a default fontfamily
+ or an empty encoding value.
+*/
+
+static void *comment_new(t_symbol *s, int ac, t_atom *av)
+{
+ t_comment *x = (t_comment *)pd_new(comment_class);
+ t_text *t = (t_text *)x;
+ t_atom at;
+ char buf[32];
+ t->te_type = T_TEXT;
+ x->x_glist = canvas_getcurrent();
+ x->x_canvas = 0;
+ sprintf(x->x_tag, "all%x", (int)x);
+ sprintf(x->x_texttag, "t%x", (int)x);
+ sprintf(x->x_outlinetag, "h%x", (int)x);
+ x->x_pixwidth = 0;
+ x->x_fontsize = 0;
+ x->x_fontfamily = 0;
+ x->x_encoding = 0;
+ x->x_fontprops = 0;
+ x->x_red = 0;
+ x->x_green = 0;
+ x->x_blue = 0;
+
+ if (ac && av->a_type == A_FLOAT)
+ {
+ x->x_pixwidth = (int)av->a_w.w_float;
+ ac--; av++;
+ if (ac && av->a_type == A_FLOAT)
+ {
+ x->x_fontsize = (int)av->a_w.w_float;
+ ac--; av++;
+ if (ac && av->a_type == A_SYMBOL)
+ {
+ if (av->a_w.w_symbol == gensym("."))
+ {
+ ac--; av++;
+ goto textpart;
+ }
+ else if (av->a_w.w_symbol != gensym("?"))
+ x->x_fontfamily = av->a_w.w_symbol;
+ ac--; av++;
+ if (ac && av->a_type == A_SYMBOL)
+ {
+ if (av->a_w.w_symbol == gensym("."))
+ {
+ ac--; av++;
+ goto textpart;
+ }
+ else if (av->a_w.w_symbol != gensym("?"))
+ x->x_encoding = av->a_w.w_symbol;
+ ac--; av++;
+ if (ac && av->a_type == A_FLOAT)
+ {
+ x->x_fontprops = (int)av->a_w.w_float;
+ ac--; av++;
+ if (ac && av->a_type == A_FLOAT)
+ {
+ x->x_red = (unsigned char)av->a_w.w_float;
+ ac--; av++;
+ if (ac && av->a_type == A_FLOAT)
+ {
+ x->x_green = (unsigned char)av->a_w.w_float;
+ ac--; av++;
+ if (ac && av->a_type == A_FLOAT)
+ {
+ x->x_blue = (unsigned char)av->a_w.w_float;
+ ac--; av++;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+textpart:
+ if (x->x_fontsize < 1)
+ x->x_fontsize = glist_getfont(x->x_glist);
+ if (!x->x_fontfamily)
+ x->x_fontfamily = gensym("helvetica");
+ sprintf(x->x_color, "#%2.2x%2.2x%2.2x", x->x_red, x->x_green, x->x_blue);
+
+ x->x_binbuf = binbuf_new();
+ if (ac) binbuf_restore(x->x_binbuf, ac, av);
+ else
+ {
+ SETSYMBOL(&at, gensym("comment"));
+ binbuf_restore(x->x_binbuf, 1, &at);
+ }
+ x->x_textbuf = 0;
+ x->x_textbufsize = 0;
+ x->x_transclock = clock_new(x, (t_method)comment_transtick);
+ x->x_bbset = 0;
+ x->x_bbpending = 0;
+ sprintf(buf, "miXed%x", (int)x);
+ x->x_bindsym = gensym(buf);
+ pd_bind((t_pd *)x, x->x_bindsym);
+ if (!commentsink)
+ commentsink = pd_new(commentsink_class);
+ pd_bind(commentsink, x->x_bindsym);
+ x->x_ready = 0;
+ x->x_dragon = 0;
+ return (x);
+}
+
+void comment_setup(void)
+{
+ comment_class = class_new(gensym("comment"),
+ (t_newmethod)comment_new,
+ (t_method)comment_free,
+ sizeof(t_comment),
+ CLASS_NOINLET | CLASS_PATCHABLE,
+ A_GIMME, 0);
+ class_addfloat(comment_class, comment_float);
+ class_addlist(comment_class, comment_list);
+ class_addmethod(comment_class, (t_method)comment__bboxhook,
+ gensym("_bbox"),
+ A_SYMBOL, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0);
+ class_addmethod(comment_class, (t_method)comment__clickhook,
+ gensym("_click"), A_GIMME, 0);
+ class_addmethod(comment_class, (t_method)comment__releasehook,
+ gensym("_release"), A_SYMBOL, 0);
+ class_addmethod(comment_class, (t_method)comment__motionhook,
+ gensym("_motion"), A_SYMBOL, A_FLOAT, A_FLOAT, 0);
+ class_setwidget(comment_class, &comment_widgetbehavior);
+
+ makeshift_class = class_new(gensym("text"), 0, 0,
+ sizeof(t_text),
+ CLASS_NOINLET | CLASS_PATCHABLE, 0);
+
+ commentsink_class = class_new(gensym("_commentsink"), 0, 0,
+ sizeof(t_pd), CLASS_PD, 0);
+ class_addanything(commentsink_class, commentsink_anything);
+ class_addmethod(commentsink_class, (t_method)commentsink__bboxhook,
+ gensym("_bbox"),
+ A_SYMBOL, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0);
+
+ sys_gui("proc comment_bbox {target cvname tag} {\n\
+ pd $target _bbox $target [$cvname bbox $tag]\\;}\n");
+
+ /* LATER think about window vs canvas coords */
+ sys_gui("proc comment_click {target cvname x y tag} {\n\
+ pd $target _click $target [$cvname canvasx $x] [$cvname canvasy $y]\
+ [$cvname index $tag @$x,$y] [$cvname bbox $tag]\\;}\n");
+
+ sys_gui("proc comment_entext {enc tt} {\n\
+ set rr [catch {encoding convertfrom $enc $tt} tt1]\n\
+ if {$rr == 0} {concat $tt1} else {\n\
+ puts stderr [concat tcl/tk error: $tt1]\n\
+ concat $tt}}\n");
+}
diff --git a/cyclone/hammer/cosh.c b/cyclone/hammer/cosh.c
new file mode 100644
index 0000000..77d1567
--- /dev/null
+++ b/cyclone/hammer/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"
+
+#if defined(NT) || defined(MACOSX)
+/* cf pd/src/x_arithmetic.c */
+#define coshf cosh
+#endif
+
+typedef struct _cosh
+{
+ t_object x_ob;
+ float x_value;
+} t_cosh;
+
+static t_class *cosh_class;
+
+static void cosh_bang(t_cosh *x)
+{
+ outlet_float(((t_object *)x)->ob_outlet, x->x_value);
+}
+
+static void cosh_float(t_cosh *x, t_float f)
+{
+ /* CHECKME large values */
+ outlet_float(((t_object *)x)->ob_outlet, x->x_value = coshf(f));
+}
+
+static void *cosh_new(t_floatarg f)
+{
+ t_cosh *x = (t_cosh *)pd_new(cosh_class);
+ /* CHECKME large values */
+ x->x_value = coshf(f);
+ outlet_new((t_object *)x, &s_float);
+ return (x);
+}
+
+void cosh_setup(void)
+{
+ cosh_class = class_new(gensym("cosh"),
+ (t_newmethod)cosh_new, 0,
+ sizeof(t_cosh), 0, A_DEFFLOAT, 0);
+ class_addbang(cosh_class, cosh_bang);
+ class_addfloat(cosh_class, cosh_float);
+}
diff --git a/cyclone/hammer/counter.c b/cyclone/hammer/counter.c
new file mode 100644
index 0000000..3117e6c
--- /dev/null
+++ b/cyclone/hammer/counter.c
@@ -0,0 +1,399 @@
+/* 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. */
+
+/* This is an entirely rewritten version of Joseph A. Sarlo's code.
+ The most important changes are listed in "pd-lib-notes.txt" file. */
+
+/* Beware -- the max reference manual page for the counter object
+ reflects mostly opcode max features. Apparently counter works
+ differently in cycling max (e.g. inlets 3 and 4). But I am sick
+ of checking -- I will not bother, until there is some feedback. */
+
+#include "m_pd.h"
+
+#define COUNTER_UP 0
+#define COUNTER_DOWN 1
+#define COUNTER_UPDOWN 2
+#define COUNTER_DEFMAX 0x7fffffff /* CHECKED (man says otherwise) */
+
+typedef struct _counter
+{
+ t_object x_ob;
+ int x_count;
+ int x_maxcount;
+ int x_dir;
+ int x_inc;
+ int x_min;
+ int x_max;
+ int x_carrybang;
+ int x_minhitflag;
+ int x_maxhitflag;
+ t_pd *x_proxies[4];
+ t_outlet *x_out2;
+ t_outlet *x_out3;
+ t_outlet *x_out4;
+} t_counter;
+
+typedef struct _counter_proxy
+{
+ t_object p_ob;
+ t_counter *p_master;
+ void (*p_bangmethod)(t_counter *x);
+ void (*p_floatmethod)(t_counter *x, t_float f);
+} t_counter_proxy;
+
+static t_class *counter_class;
+static t_class *counter_proxy_class;
+
+static void counter_up(t_counter *x)
+{
+ x->x_dir = COUNTER_UP;
+ x->x_inc = 1;
+}
+
+static void counter_down(t_counter *x)
+{
+ /* CHECKED: no explicit minimum needed */
+ x->x_dir = COUNTER_DOWN;
+ x->x_inc = -1;
+}
+
+static void counter_updown(t_counter *x)
+{
+ /* CHECKED: neither explicit maximum, nor minimum needed */
+ x->x_dir = COUNTER_UPDOWN;
+ /* CHECKED: x->x_inc unchanged (continuation) */
+}
+
+static void counter_dir(t_counter *x, t_floatarg f)
+{
+ switch ((int)f)
+ {
+ case COUNTER_UP:
+ counter_up(x);
+ break;
+ case COUNTER_DOWN:
+ counter_down(x);
+ break;
+ case COUNTER_UPDOWN:
+ counter_updown(x);
+ break;
+ default:
+ counter_up(x); /* CHECKED: invalid == default */
+ /* CHECKED: no warning */
+ }
+}
+
+static void counter_dobang(t_counter *x, int notjam)
+{
+ int offmin = 0, offmax = 0, onmin = 0, onmax = 0;
+ /* CHECKED: carry-off is not sent if min >= max */
+ /* LATER rethink (this is a hack) */
+ if (x->x_min < x->x_max)
+ offmin = x->x_minhitflag, offmax = x->x_maxhitflag;
+ x->x_minhitflag = x->x_maxhitflag = 0;
+
+ if (x->x_count < x->x_min)
+ {
+ if (x->x_inc == 1)
+ {
+ /* min has changed, which should imply x->x_count == x->x_min */
+ bug("counter_dobang (count < min)");
+ }
+ else if (x->x_dir == COUNTER_UPDOWN)
+ {
+ x->x_inc = 1;
+ if ((x->x_count = x->x_min + 1) > x->x_max) x->x_count = x->x_min;
+ }
+ else if ((x->x_count = x->x_max) < x->x_min) x->x_count = x->x_min;
+ }
+ else if (x->x_count > x->x_max)
+ {
+ if (x->x_inc == -1)
+ {
+ /* CHECKED: ignored */
+ }
+ else if (x->x_dir == COUNTER_UPDOWN)
+ {
+ x->x_inc = -1;
+ if ((x->x_count = x->x_max - 1) < x->x_min) x->x_count = x->x_min;
+ }
+ else x->x_count = x->x_min;
+ }
+
+ if (x->x_count == x->x_min && x->x_inc == -1)
+ {
+ /* CHECKED: 'jam' inhibits middle outlets (unless carry-off)
+ carry-on is never sent if max < min, but sent if max == min */
+ if (notjam
+ && x->x_min <= x->x_max) /* LATER rethink (this is a hack) */
+ onmin = 1;
+ }
+ else if (x->x_count == x->x_max && x->x_inc == 1)
+ {
+ /* CHECKED: this counter is never reset (and goes up to INT_MAX)
+ -- neither after dir change, nor after max change */
+ x->x_maxcount++; /* CHECKED: 'jam' does the increment */
+ outlet_float(x->x_out4, x->x_maxcount);
+ /* CHECKED: 'jam' inhibits middle outlets (unless carry-off)
+ carry-on is never sent if max < min, but sent if max == min */
+ if (notjam
+ && x->x_min <= x->x_max) /* LATER rethink (this is a hack) */
+ onmax = 1;
+ }
+
+ /* CHECKED: outlets deliver in right-to-left order */
+ if (onmax)
+ {
+ if (x->x_carrybang) outlet_bang(x->x_out3);
+ else
+ {
+ outlet_float(x->x_out3, 1);
+ x->x_maxhitflag = 1;
+ }
+ }
+ else if (offmax) outlet_float(x->x_out3, 0);
+ else if (onmin)
+ {
+ if (x->x_carrybang) outlet_bang(x->x_out2);
+ else
+ {
+ outlet_float(x->x_out2, 1);
+ x->x_minhitflag = 1;
+ }
+ }
+ else if (offmin) outlet_float(x->x_out2, 0);
+
+ outlet_float(((t_object *)x)->ob_outlet, x->x_count);
+}
+
+static void counter_bang(t_counter *x)
+{
+ x->x_count += x->x_inc;
+ counter_dobang(x, 1);
+}
+
+static void counter_float(t_counter *x, t_float dummy)
+{
+ counter_bang(x);
+}
+
+/* CHECKED: out-of-range values are ignored */
+/* CHECKED: 'down, set 3, up, bang' gives 5 */
+static void counter_set(t_counter *x, t_floatarg f)
+{
+ int i = (int)f;
+ if (i >= x->x_min && i <= x->x_max)
+ x->x_count = i - x->x_inc;
+}
+
+/* CHECKED: out-of-range values are ignored */
+static void counter_jam(t_counter *x, t_floatarg f)
+{
+ int i = (int)f;
+ if (i >= x->x_min && i <= x->x_max)
+ {
+ x->x_count = i;
+ counter_dobang(x, 0);
+ }
+}
+
+/* CHECKED: sends max carry on/off in any mode */
+static void counter_inc(t_counter *x)
+{
+ int tempdir = x->x_dir;
+ int tempinc = x->x_inc;
+ counter_up(x);
+ counter_bang(x);
+ x->x_dir = tempdir;
+ x->x_inc = tempinc;
+}
+
+/* CHECKED: sends min carry on/off in any mode */
+static void counter_dec(t_counter *x)
+{
+ int tempdir = x->x_dir;
+ int tempinc = x->x_inc;
+ counter_down(x);
+ counter_bang(x);
+ x->x_dir = tempdir;
+ x->x_inc = tempinc;
+}
+
+/* CHECKED: min can be set over max */
+static void counter_min(t_counter *x, t_floatarg f)
+{
+ /* CHECKED: min change always sets count to min and bangs */
+ /* do not use counter_jam() here -- avoid range checking */
+ x->x_count = x->x_min = (int)f;
+ counter_dobang(x, 0);
+}
+
+/* CHECKED: max can be set below min */
+static void counter_max(t_counter *x, t_floatarg f)
+{
+ x->x_max = (int)f;
+}
+
+static void counter_carrybang(t_counter *x)
+{
+ x->x_carrybang = 1;
+}
+
+static void counter_carryint(t_counter *x)
+{
+ x->x_carrybang = 0;
+}
+
+/* CHECKED: up/down switch */
+static void counter_bang1(t_counter *x)
+{
+ if (x->x_dir == COUNTER_UP)
+ counter_down(x);
+ else if (x->x_dir == COUNTER_DOWN)
+ counter_up(x);
+ else
+ x->x_inc = -x->x_inc; /* CHECKED */
+}
+
+/* CHECKED */
+static void counter_bang2(t_counter *x)
+{
+ counter_set(x, x->x_min);
+}
+
+/* CHECKED: out-of-range values are accepted (LATER rethink) */
+/* CHECKED: no resetting of min, nor of max (contrary to the man) */
+/* CHECKED: 'down, float2 3, up, bang' gives 3 (LATER rethink) */
+static void counter_float2(t_counter *x, t_floatarg f)
+{
+ counter_set(x, f); /* FIXME */
+}
+
+/* CHECKED */
+static void counter_bang3(t_counter *x)
+{
+ counter_jam(x, x->x_min);
+}
+
+/* CHECKED: out-of-range values are accepted (LATER rethink) */
+/* CHECKED: no resetting of min, nor of max (contrary to the man) */
+static void counter_float3(t_counter *x, t_floatarg f)
+{
+ counter_jam(x, f); /* FIXME */
+}
+
+/* CHECKED */
+static void counter_bang4(t_counter *x)
+{
+ counter_set(x, x->x_max);
+}
+
+static void counter_proxy_bang(t_counter_proxy *x)
+{
+ x->p_bangmethod(x->p_master);
+}
+
+static void counter_proxy_float(t_counter_proxy *x, t_float f)
+{
+ x->p_floatmethod(x->p_master, f);
+}
+
+static void counter_free(t_counter *x)
+{
+ int i;
+ for (i = 0; i < 4; i++)
+ if (x->x_proxies[i]) pd_free(x->x_proxies[i]);
+}
+
+static void *counter_new(t_floatarg f1, t_floatarg f2, t_floatarg f3)
+{
+ t_counter *x = (t_counter *)pd_new(counter_class);
+ t_counter_proxy **pp = (t_counter_proxy **)x->x_proxies;
+ int i1 = (int)f1;
+ int i2 = (int)f2;
+ int i3 = (int)f3;
+ int i;
+ static int warned = 0;
+ if (!warned)
+ {
+ post("warning: counter is not fully compatible, \
+please report differences");
+ warned = 1;
+ }
+ x->x_dir = COUNTER_UP;
+ x->x_inc = 1; /* previous value required by counter_dir() */
+ x->x_min = 0;
+ x->x_max = COUNTER_DEFMAX;
+ if (i3) x->x_dir = i1, x->x_min = i2, x->x_max = i3;
+ else if (i2) x->x_min = i1, x->x_max = i2;
+ else if (i1) x->x_max = i1;
+ x->x_carrybang = 0; /* CHECKED */
+ x->x_minhitflag = x->x_maxhitflag = 0;
+ x->x_maxcount = 0;
+ counter_dir(x, x->x_dir);
+ /* CHECKED: [counter 1 <min> <max>] starts from <max> */
+ x->x_count = (x->x_dir == COUNTER_DOWN ? x->x_max : x->x_min);
+ for (i = 0; i < 4; i++)
+ {
+ x->x_proxies[i] = pd_new(counter_proxy_class);
+ ((t_counter_proxy *)x->x_proxies[i])->p_master = x;
+ inlet_new((t_object *)x, x->x_proxies[i], 0, 0);
+ }
+ (*pp)->p_bangmethod = counter_bang1;
+ (*pp++)->p_floatmethod = counter_dir; /* CHECKED: same as dir */
+ (*pp)->p_bangmethod = counter_bang2;
+ (*pp++)->p_floatmethod = counter_float2;
+ (*pp)->p_bangmethod = counter_bang3;
+ (*pp++)->p_floatmethod = counter_float3;
+ (*pp)->p_bangmethod = counter_bang4;
+ (*pp++)->p_floatmethod = counter_max; /* CHECKED: same as max */
+ outlet_new((t_object *)x, &s_float);
+ x->x_out2 = outlet_new((t_object *)x, &s_anything); /* float/bang */
+ x->x_out3 = outlet_new((t_object *)x, &s_anything); /* float/bang */
+ x->x_out4 = outlet_new((t_object *)x, &s_float);
+ return (x);
+}
+
+void counter_setup(void)
+{
+ counter_class = class_new(gensym("counter"),
+ (t_newmethod)counter_new,
+ (t_method)counter_free,
+ sizeof(t_counter), 0,
+ A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0);
+ class_addbang(counter_class, counter_bang);
+ class_addfloat(counter_class, counter_float);
+ class_addmethod(counter_class, (t_method)counter_bang,
+ gensym("next"), 0);
+ class_addmethod(counter_class, (t_method)counter_set,
+ gensym("set"), A_FLOAT, 0);
+ class_addmethod(counter_class, (t_method)counter_set,
+ gensym("goto"), A_FLOAT, 0);
+ class_addmethod(counter_class, (t_method)counter_jam,
+ gensym("jam"), A_FLOAT, 0);
+ class_addmethod(counter_class, (t_method)counter_up,
+ gensym("up"), 0);
+ class_addmethod(counter_class, (t_method)counter_down,
+ gensym("down"), 0);
+ class_addmethod(counter_class, (t_method)counter_updown,
+ gensym("updown"), 0);
+ class_addmethod(counter_class, (t_method)counter_inc,
+ gensym("inc"), 0);
+ class_addmethod(counter_class, (t_method)counter_dec,
+ gensym("dec"), 0);
+ class_addmethod(counter_class, (t_method)counter_min,
+ gensym("min"), A_FLOAT, 0);
+ class_addmethod(counter_class, (t_method)counter_max,
+ gensym("max"), A_FLOAT, 0);
+ class_addmethod(counter_class, (t_method)counter_carrybang,
+ gensym("carrybang"), 0);
+ class_addmethod(counter_class, (t_method)counter_carryint,
+ gensym("carryint"), 0);
+ counter_proxy_class = class_new(gensym("_counter_proxy"), 0, 0,
+ sizeof(t_counter_proxy),
+ CLASS_PD | CLASS_NOINLET, 0);
+ class_addbang(counter_proxy_class, counter_proxy_bang);
+ class_addfloat(counter_proxy_class, counter_proxy_float);
+}
diff --git a/cyclone/hammer/cycle.c b/cyclone/hammer/cycle.c
new file mode 100644
index 0000000..faffc01
--- /dev/null
+++ b/cyclone/hammer/cycle.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. */
+
+/* This is a modified version of Joseph A. Sarlo's code.
+ The most important changes are listed in "pd-lib-notes.txt" file. */
+
+#include "m_pd.h"
+#include "common/loud.h"
+
+//#define CYCLE_USEEVENTNO
+
+#define CYCLE_MINOUTS 1
+#define CYCLE_MAXOUTS 100 /* CHECKED */
+#define CYCLE_DEFOUTS 1
+
+typedef struct _cycle
+{
+ t_object x_ob;
+ int x_eventmode;
+#ifdef CYCLE_USEEVENTNO
+ int x_lastevent;
+#else
+ double x_lastevent;
+#endif
+ int x_index;
+ int x_nouts;
+ t_outlet **x_outs;
+} t_cycle;
+
+static t_class *cycle_class;
+
+static int cycle_isnextevent(t_cycle *x)
+{
+#ifdef CYCLE_USEEVENTNO
+ int nextevent = sys_geteventno();
+#else
+ double nextevent = clock_getlogicaltime();
+#endif
+ if (x->x_lastevent == nextevent)
+ return (0);
+ else
+ {
+ x->x_lastevent = nextevent;
+ return (1);
+ }
+}
+
+static void cycle_bang(t_cycle *x)
+{
+ /* CHECKED: bangs ignored (but message 'bang' is an error -- why?) */
+}
+
+static void cycle_float(t_cycle *x, t_float f)
+{
+ if ((x->x_eventmode && cycle_isnextevent(x)) || x->x_index >= x->x_nouts)
+ x->x_index = 0;
+ outlet_float(x->x_outs[x->x_index++], f);
+}
+
+static void cycle_symbol(t_cycle *x, t_symbol *s)
+{
+ if ((x->x_eventmode && cycle_isnextevent(x)) || x->x_index >= x->x_nouts)
+ x->x_index = 0;
+ outlet_symbol(x->x_outs[x->x_index++], s);
+}
+
+/* LATER gpointer */
+
+static void cycle_list(t_cycle *x, t_symbol *s, int ac, t_atom *av)
+{
+ if ((x->x_eventmode && cycle_isnextevent(x)) || x->x_index >= x->x_nouts)
+ x->x_index = 0;
+ while (ac--)
+ {
+ if (av->a_type == A_FLOAT)
+ outlet_float(x->x_outs[x->x_index], av->a_w.w_float);
+ else if (av->a_type == A_SYMBOL)
+ outlet_symbol(x->x_outs[x->x_index], av->a_w.w_symbol);
+ av++;
+ if (++(x->x_index) >= x->x_nouts) x->x_index = 0;
+ }
+}
+
+static void cycle_anything(t_cycle *x, t_symbol *s, int ac, t_atom *av)
+{
+ if (s && s != &s_) cycle_symbol(x, s); /* CHECKED */
+ cycle_list(x, 0, ac, av);
+}
+
+static void cycle_set(t_cycle *x, t_floatarg f)
+{
+ int i = (int)f;
+ if (i >= 0 && i < x->x_nouts) x->x_index = i;
+}
+
+static void cycle_thresh(t_cycle *x, t_floatarg f)
+{
+ if (x->x_eventmode = (f != 0))
+#ifdef CYCLE_USEEVENTNO
+ x->x_lastevent = sys_geteventno();
+#else
+ x->x_lastevent = clock_getlogicaltime();
+#endif
+}
+
+static void cycle_free(t_cycle *x)
+{
+ if (x->x_outs)
+ freebytes(x->x_outs, x->x_nouts * sizeof(*x->x_outs));
+}
+
+static void *cycle_new(t_floatarg f1, t_floatarg f2)
+{
+ t_cycle *x;
+ int i, nouts = (int)f1;
+ t_outlet **outs;
+ if (nouts < CYCLE_MINOUTS)
+ nouts = CYCLE_DEFOUTS;
+ if (nouts > CYCLE_MAXOUTS)
+ {
+ loud_incompatible_max(cycle_class, CYCLE_MAXOUTS, "outlets");
+ /* CHECKED: max clips with an error:
+ ``perhaps you were trying to make an oscillator?'' */
+ }
+ if (!(outs = (t_outlet **)getbytes(nouts * sizeof(*outs))))
+ return (0);
+ x = (t_cycle *)pd_new(cycle_class);
+ x->x_nouts = nouts;
+ x->x_outs = outs;
+ x->x_index = 0;
+ for (i = 0; i < nouts; i++)
+ x->x_outs[i] = outlet_new((t_object *)x, &s_anything);
+ cycle_thresh(x, f2);
+ return (x);
+}
+
+void cycle_setup(void)
+{
+ cycle_class = class_new(gensym("cycle"),
+ (t_newmethod)cycle_new,
+ (t_method)cycle_free,
+ sizeof(t_cycle), 0, A_DEFFLOAT, A_DEFFLOAT, 0);
+ class_addbang(cycle_class, cycle_bang);
+ class_addfloat(cycle_class, cycle_float);
+ class_addsymbol(cycle_class, cycle_symbol);
+ class_addlist(cycle_class, cycle_list);
+ class_addanything(cycle_class, cycle_anything);
+ class_addmethod(cycle_class, (t_method)cycle_set,
+ gensym("set"), A_FLOAT, 0); /* CHECKED: arg required */
+ class_addmethod(cycle_class, (t_method)cycle_thresh,
+ gensym("thresh"), A_FLOAT, 0);
+}
diff --git a/cyclone/hammer/decide.c b/cyclone/hammer/decide.c
new file mode 100644
index 0000000..a612fbf
--- /dev/null
+++ b/cyclone/hammer/decide.c
@@ -0,0 +1,75 @@
+/* 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/loud.h"
+
+typedef struct _decide
+{
+ t_object x_ob;
+ unsigned int x_seed;
+} t_decide;
+
+static t_class *decide_class;
+
+/* the random bit algo is taken from NR (method II in 7.4) -- CHECKED */
+#define RBIT1 1
+#define RBIT2 2
+#define RBIT5 16
+#define RBIT18 131072
+#define RBIT_MASK (RBIT1 + RBIT2 + RBIT5)
+
+static void decide_bang(t_decide *x)
+{
+ if (x->x_seed & RBIT18)
+ {
+ x->x_seed = ((x->x_seed ^ RBIT_MASK) << 1) | RBIT1;
+ outlet_float(((t_object *)x)->ob_outlet, 1);
+ }
+ else
+ {
+ x->x_seed <<= 1;
+ outlet_float(((t_object *)x)->ob_outlet, 0);
+ }
+}
+
+static void decide_float(t_decide *x, t_float f)
+{
+ /* CHECKED: float loudly rejected, int (any value) same as bang */
+ int i;
+ if (loud_checkint((t_pd *)x, f, &i, &s_float))
+ decide_bang(x);
+}
+
+static void decide_ft1(t_decide *x, t_floatarg f)
+{
+ int i = (int)f; /* CHECKED */
+ if (i) /* CHECKED: negative numbers are accepted */
+ x->x_seed = i;
+ else
+ x->x_seed = 123456789; /* FIXME */
+}
+
+static void *decide_new(t_floatarg f)
+{
+ t_decide *x = (t_decide *)pd_new(decide_class);
+ x->x_seed = 123456789; /* FIXME */
+ inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft1"));
+ outlet_new((t_object *)x, &s_float);
+ return (x);
+}
+
+void decide_setup(void)
+{
+ decide_class = class_new(gensym("decide"),
+ (t_newmethod)decide_new, 0,
+ sizeof(t_decide), 0,
+ A_DEFFLOAT, 0);
+ class_addbang(decide_class, decide_bang);
+ class_addfloat(decide_class, decide_float);
+ class_addmethod(decide_class, (t_method)decide_ft1,
+ gensym("ft1"), A_FLOAT, 0);
+ /* CHECKED list is auto-unfolded */
+ /* CHECKED doesn't understand "seed" */
+}
diff --git a/cyclone/hammer/drunk.c b/cyclone/hammer/drunk.c
new file mode 100644
index 0000000..e08800d
--- /dev/null
+++ b/cyclone/hammer/drunk.c
@@ -0,0 +1,140 @@
+/* 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. */
+
+/* The first version of this code was written by Nicola Bernardini.
+ It was entirely reimplemented in the hope of adapting it to the
+ cyclone's guidelines. */
+
+#include "m_pd.h"
+#include "common/rand.h"
+
+#define DRUNK_DEFMAXVALUE 128
+#define DRUNK_DEFMAXSTEP 2
+
+typedef struct _drunk
+{
+ t_object x_ob;
+ int x_value;
+ int x_maxvalue;
+ int x_maxstep;
+ int x_minstep;
+ unsigned int x_seed;
+ unsigned int x_bitseed;
+} t_drunk;
+
+static t_class *drunk_class;
+
+static void drunk_set(t_drunk *x, t_floatarg f)
+{
+ int i = (int)f; /* CHECKED float silently truncated */
+ if (i > x->x_maxvalue)
+ x->x_value = x->x_maxvalue; /* CHECKED */
+ else if (i < 0)
+ x->x_value = 0; /* CHECKED */
+ else x->x_value = i;
+}
+
+/* CHECKED: this is a superposition of two rngs -- the random bit generator,
+ and the random integer generator, which is the same (CHECKED) as the one
+ used in the 'random' class (quite lame: period 35730773, nonuniform for
+ large ranges, so I would rather not RE it...) */
+#define RBIT1 1
+#define RBIT2 2
+#define RBIT5 16
+#define RBIT18 131072
+#define RBIT_MASK (RBIT1 + RBIT2 + RBIT5)
+
+static void drunk_bang(t_drunk *x)
+{
+ int rnd = rand_int(&x->x_seed, x->x_maxstep) + x->x_minstep;
+ int val;
+ if (x->x_bitseed & RBIT18)
+ {
+ x->x_bitseed = ((x->x_bitseed ^ RBIT_MASK) << 1) | RBIT1;
+ if ((val = x->x_value + rnd) > x->x_maxvalue)
+ val = x->x_value - rnd; /* CHECKED */
+ if (val < 0)
+ val = 0; /* CHECKED (needed for maxstep > maxvalue) */
+ }
+ else
+ {
+ x->x_bitseed <<= 1;
+ if ((val = x->x_value - rnd) < 0)
+ val = x->x_value + rnd; /* CHECKED */
+ if (val > x->x_maxvalue)
+ val = x->x_maxvalue; /* CHECKED (needed for maxstep > maxvalue) */
+ }
+ outlet_float(((t_object *)x)->ob_outlet, x->x_value = val);
+}
+
+static void drunk_float(t_drunk *x, t_float f)
+{
+ drunk_set(x, f);
+ outlet_float(((t_object *)x)->ob_outlet, x->x_value);
+}
+
+static void drunk_ft1(t_drunk *x, t_floatarg f)
+{
+ int i = (int)f; /* CHECKED float silently truncated */
+ x->x_maxvalue = (i < 0 ? 1 : i); /* CHECKED zero allowed */
+ /* CHECKED maxstep not updated */
+}
+
+static void drunk_ft2(t_drunk *x, t_floatarg f)
+{
+ int i = (int)f; /* CHECKED float silently truncated */
+ if (i < 0)
+ {
+ x->x_minstep = 1;
+ i = -i;
+ }
+ else x->x_minstep = 0;
+ /* CHECKED maxstep not clipped to the maxvalue */
+ x->x_maxstep = (x->x_minstep ? i - 1 : i); /* CHECKED zero allowed */
+}
+
+/* apparently, bitseed cannot be controlled, but LATER recheck */
+static void drunk_seed(t_drunk *x, t_floatarg f)
+{
+ int i = (int)f; /* CHECKED */
+ if (i < 0)
+ i = 1; /* CHECKED */
+ rand_seed(&x->x_seed, (unsigned int)i);
+}
+
+static void *drunk_new(t_floatarg f1, t_floatarg f2)
+{
+ t_drunk *x = (t_drunk *)pd_new(drunk_class);
+ x->x_maxvalue = ((int)f1 > 0 ? (int)f1 : 128); /* CHECKED */
+ x->x_maxstep = 2;
+ x->x_minstep = 0;
+ if ((int)f2) /* CHECKED */
+ drunk_ft2(x, f2);
+ x->x_value = x->x_maxvalue / 2; /* CHECKED */
+ rand_seed(&x->x_seed, 0); /* CHECKED third arg silently ignored */
+ x->x_bitseed = 123456789; /* FIXME */
+ 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);
+ return (x);
+}
+
+void drunk_setup(void)
+{
+ drunk_class = class_new(gensym("drunk"),
+ (t_newmethod)drunk_new, 0,
+ sizeof(t_drunk), 0,
+ A_DEFFLOAT, A_DEFFLOAT, 0);
+ class_addbang(drunk_class, drunk_bang);
+ class_addfloat(drunk_class, drunk_float);
+ class_addmethod(drunk_class, (t_method)drunk_ft1,
+ gensym("ft1"), A_FLOAT, 0);
+ class_addmethod(drunk_class, (t_method)drunk_ft2,
+ gensym("ft2"), A_FLOAT, 0);
+ /* CHECKED list is auto-unfolded */
+ class_addmethod(drunk_class, (t_method)drunk_seed,
+ gensym("seed"), A_FLOAT, 0); /* CHECKED arg obligatory */
+ class_addmethod(drunk_class, (t_method)drunk_set,
+ gensym("set"), A_FLOAT, 0); /* CHECKED arg obligatory */
+}
diff --git a/cyclone/hammer/flush.c b/cyclone/hammer/flush.c
new file mode 100644
index 0000000..751fc24
--- /dev/null
+++ b/cyclone/hammer/flush.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 <string.h>
+#include "m_pd.h"
+
+#define FLUSH_NPITCHES 128
+
+typedef struct _flush
+{
+ t_object x_ob;
+ t_float x_velocity;
+ unsigned char x_pitches[FLUSH_NPITCHES]; /* CHECKED */
+ t_outlet *x_voutlet;
+} t_flush;
+
+static t_class *flush_class;
+
+static void flush_float(t_flush *x, t_float f)
+{
+ int pitch = (int)f;
+ if (pitch >= 0 && pitch < FLUSH_NPITCHES)
+ {
+ outlet_float(x->x_voutlet, x->x_velocity);
+ outlet_float(((t_object *)x)->ob_outlet, pitch);
+ if (x->x_velocity != 0)
+ {
+ x->x_pitches[pitch]++; /* CHECKED (lame) */
+ }
+ else if (x->x_pitches[pitch])
+ {
+ x->x_pitches[pitch]--; /* CHECKED (lame) */
+ }
+ }
+}
+
+static void flush_bang(t_flush *x)
+{
+ int i;
+ unsigned char *pp;
+ for (i = 0, pp = x->x_pitches; i < FLUSH_NPITCHES; i++, pp++)
+ {
+ while (*pp)
+ {
+ outlet_float(x->x_voutlet, 0);
+ outlet_float(((t_object *)x)->ob_outlet, i);
+ (*pp)--;
+ }
+ }
+}
+
+static void flush_clear(t_flush *x)
+{
+ memset(x->x_pitches, 0, sizeof(x->x_pitches));
+}
+
+static void *flush_new(void)
+{
+ t_flush *x = (t_flush *)pd_new(flush_class);
+ x->x_velocity = 0;
+ flush_clear(x);
+ floatinlet_new((t_object *)x, &x->x_velocity);
+ outlet_new((t_object *)x, &s_float);
+ x->x_voutlet = outlet_new((t_object *)x, &s_float);
+ return (x);
+}
+
+void flush_setup(void)
+{
+ flush_class = class_new(gensym("flush"),
+ (t_newmethod)flush_new,
+ 0, /* CHECKED: no flushout */
+ sizeof(t_flush), 0, 0);
+ class_addfloat(flush_class, flush_float);
+ class_addbang(flush_class, flush_bang);
+ class_addmethod(flush_class, (t_method)flush_clear,
+ gensym("clear"), 0);
+}
diff --git a/cyclone/hammer/forward.c b/cyclone/hammer/forward.c
new file mode 100644
index 0000000..995e765
--- /dev/null
+++ b/cyclone/hammer/forward.c
@@ -0,0 +1,71 @@
+/* Copyright (c) 1997-2002 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. */
+
+#include "m_pd.h"
+
+typedef struct _forward
+{
+ t_object x_ob;
+ t_symbol *x_sym;
+} t_forward;
+
+static t_class *forward_class;
+
+static void forward_bang(t_forward *x)
+{
+ if (x->x_sym->s_thing) pd_bang(x->x_sym->s_thing);
+}
+
+static void forward_float(t_forward *x, t_float f)
+{
+ if (x->x_sym->s_thing) pd_float(x->x_sym->s_thing, f);
+}
+
+static void forward_symbol(t_forward *x, t_symbol *s)
+{
+ if (x->x_sym->s_thing) pd_symbol(x->x_sym->s_thing, s);
+}
+
+static void forward_pointer(t_forward *x, t_gpointer *gp)
+{
+ if (x->x_sym->s_thing) pd_pointer(x->x_sym->s_thing, gp);
+}
+
+static void forward_list(t_forward *x, t_symbol *s, int ac, t_atom *av)
+{
+ if (x->x_sym->s_thing) pd_list(x->x_sym->s_thing, s, ac, av);
+}
+
+static void forward_anything(t_forward *x, t_symbol *s, int ac, t_atom *av)
+{
+ if (x->x_sym->s_thing) typedmess(x->x_sym->s_thing, s, ac, av);
+}
+
+static void forward_send(t_forward *x, t_symbol *s)
+{
+ /* CHECKED: 'send' without arguments erases destination */
+ if (s) x->x_sym = s;
+}
+
+static void *forward_new(t_symbol *s)
+{
+ t_forward *x = (t_forward *)pd_new(forward_class);
+ x->x_sym = s;
+ return (x);
+}
+
+void forward_setup(void)
+{
+ forward_class = class_new(gensym("forward"),
+ (t_newmethod)forward_new, 0,
+ sizeof(t_forward), 0, A_DEFSYM, 0);
+ class_addbang(forward_class, forward_bang);
+ class_addfloat(forward_class, forward_float);
+ class_addsymbol(forward_class, forward_symbol);
+ class_addpointer(forward_class, forward_pointer);
+ class_addlist(forward_class, forward_list);
+ class_addanything(forward_class, forward_anything);
+ class_addmethod(forward_class, (t_method)forward_send,
+ gensym("send"), A_DEFSYM, 0);
+}
diff --git a/cyclone/hammer/fromsymbol.c b/cyclone/hammer/fromsymbol.c
new file mode 100644
index 0000000..3d508e9
--- /dev/null
+++ b/cyclone/hammer/fromsymbol.c
@@ -0,0 +1,88 @@
+/* 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"
+
+typedef struct _fromsymbol
+{
+ t_object x_ob;
+} t_fromsymbol;
+
+static t_class *fromsymbol_class;
+
+static void fromsymbol_bang(t_fromsymbol *x)
+{
+ outlet_bang(((t_object *)x)->ob_outlet); /* CHECKED */
+}
+
+static void fromsymbol_float(t_fromsymbol *x, t_float f)
+{
+ /* CHECKED: fromsymbol: doesn't understand "int", "float" */
+}
+
+static void fromsymbol_symbol(t_fromsymbol *x, t_symbol *s)
+{
+ static char zero = 0;
+ char *sname = &zero;
+ if (s)
+ {
+ sname = s->s_name;
+ while (*sname == ' ' || *sname == '\t'
+ || *sname == '\n' || *sname == '\r') sname++;
+ }
+ if (*sname)
+ {
+ t_binbuf *bb = binbuf_new();
+ int ac;
+ t_atom *av;
+ binbuf_text(bb, sname, strlen(sname));
+ ac = binbuf_getnatom(bb);
+ av = binbuf_getvec(bb);
+ if (ac)
+ {
+ if (av->a_type == A_SYMBOL)
+ outlet_anything(((t_object *)x)->ob_outlet,
+ av->a_w.w_symbol, ac - 1, av + 1);
+ else if (av->a_type == A_FLOAT)
+ {
+ if (ac > 1)
+ outlet_list(((t_object *)x)->ob_outlet, &s_list, ac, av);
+ else
+ outlet_float(((t_object *)x)->ob_outlet, av->a_w.w_float);
+ }
+ }
+ binbuf_free(bb);
+ }
+}
+
+static void fromsymbol_list(t_fromsymbol *x, t_symbol *s, int ac, t_atom *av)
+{
+ /* CHECKED: fromsymbol: doesn't understand "int", "float",
+ 'list <symbol>' ignored without complaining. */
+}
+
+static void fromsymbol_anything(t_fromsymbol *x, t_symbol *s, int ac, t_atom *av)
+{
+ fromsymbol_symbol(x, s); /* CHECKED */
+}
+
+static void *fromsymbol_new(void)
+{
+ t_fromsymbol *x = (t_fromsymbol *)pd_new(fromsymbol_class);
+ outlet_new((t_object *)x, &s_anything);
+ return (x);
+}
+
+void fromsymbol_setup(void)
+{
+ fromsymbol_class = class_new(gensym("fromsymbol"),
+ (t_newmethod)fromsymbol_new, 0,
+ sizeof(t_fromsymbol), 0, 0);
+ class_addbang(fromsymbol_class, fromsymbol_bang);
+ class_addfloat(fromsymbol_class, fromsymbol_float);
+ class_addsymbol(fromsymbol_class, fromsymbol_symbol);
+ class_addlist(fromsymbol_class, fromsymbol_list);
+ class_addanything(fromsymbol_class, fromsymbol_anything);
+}
diff --git a/cyclone/hammer/funbuff.c b/cyclone/hammer/funbuff.c
new file mode 100644
index 0000000..8d9d698
--- /dev/null
+++ b/cyclone/hammer/funbuff.c
@@ -0,0 +1,521 @@
+/* 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 "unstable/fragile.h"
+#include "common/loud.h"
+#include "common/vefl.h"
+#include "hammer/tree.h"
+#include "hammer/file.h"
+
+typedef struct _funbuff
+{
+ t_object x_ob;
+ t_canvas *x_canvas;
+ t_symbol *x_defname;
+ t_float x_value;
+ int x_valueset;
+ /* CHECKED filling with a large set, then sending 'goto', 'read', 'next'...
+ outputs the previous, replaced contents (same with deletion)
+ -- apparently a node pointer is stored, corrupt in these cases */
+ t_hammernode *x_pointer;
+ int x_pointerset; /* set-with-goto flag */
+ int x_lastdelta;
+ int x_embedflag;
+ t_hammerfile *x_filehandle;
+ t_hammertree x_tree;
+ t_outlet *x_deltaout;
+ t_outlet *x_bangout;
+} t_funbuff;
+
+static t_class *funbuff_class;
+
+static void funbuff_dooutput(t_funbuff *x, float value, float delta)
+{
+ /* CHECKED lastdelta sent for 'next', 'float', 'min', 'max',
+ 'interp', 'find' */
+ outlet_float(x->x_deltaout, delta);
+ outlet_float(((t_object *)x)->ob_outlet, value);
+}
+
+static void funbuff_bang(t_funbuff *x)
+{
+ t_hammernode *np;
+ int count = 0;
+ int xmin = 0, xmax = 0;
+ t_float ymin = 0, ymax = 0;
+ if (np = x->x_tree.t_first)
+ {
+ /* LATER consider using extra fields, updated on the fly */
+ count = 1;
+ xmin = np->n_index;
+ xmax = x->x_tree.t_last->n_index;
+ ymin = ymax = np->n_value;
+ while (np = np->n_next)
+ {
+ if (np->n_value < ymin) ymin = np->n_value;
+ else if (np->n_value > ymax) ymax = np->n_value;
+ count++;
+ }
+ }
+ /* format CHECKED */
+ post("funbuff info: %d elements long", count); /* CHECKED 0 and 1 */
+ if (count)
+ {
+ post(" -> minX= %d maxX= %d", xmin, xmax);
+ post(" -> minY= %g maxY= %g", ymin, ymax);
+ post(" -> domain= %d range= %g", xmax - xmin, ymax - ymin);
+ }
+}
+
+static void funbuff_float(t_funbuff *x, t_float f)
+{
+ int ndx = (int)f; /* CHECKED float is silently truncated */
+ t_hammernode *np;
+ if (x->x_valueset)
+ {
+ if (np = hammertree_insert(&x->x_tree, ndx))
+ np->n_value = x->x_value;
+ x->x_valueset = 0;
+ }
+ else if (np = hammertree_closest(&x->x_tree, ndx, 0))
+ funbuff_dooutput(x, np->n_value, x->x_lastdelta);
+ /* CHECKED pointer is updated --
+ 'next' outputs np also in a !valueset case (it is sent twice) */
+ x->x_pointer = np;
+ x->x_pointerset = 0;
+}
+
+static void funbuff_ft1(t_funbuff *x, t_floatarg f)
+{
+ /* this is incompatible -- CHECKED float is silently truncated */
+ x->x_value = f;
+ x->x_valueset = 1;
+}
+
+static void funbuff_clear(t_funbuff *x)
+{
+ hammertree_clear(&x->x_tree, 0);
+ /* CHECKED valueset is not cleared */
+ x->x_pointer = 0;
+}
+
+/* LATER dirty flag handling */
+static void funbuff_embed(t_funbuff *x, t_floatarg f)
+{
+ x->x_embedflag = (f != 0);
+}
+
+static void funbuff_goto(t_funbuff *x, t_floatarg f)
+{
+ /* CHECKED truncation */
+ x->x_pointer = hammertree_closest(&x->x_tree, (int)f, 1);
+ x->x_pointerset = 1; /* CHECKED delta output by 'next' will be zero */
+}
+
+/* LATER consider using an extra field, updated on the fly */
+static void funbuff_min(t_funbuff *x)
+{
+ t_hammernode *np;
+ if (np = x->x_tree.t_first) /* CHECKED nop if empty */
+ {
+ t_float result = np->n_value;
+ while (np = np->n_next)
+ if (np->n_value < result) result = np->n_value;
+ funbuff_dooutput(x, result, x->x_lastdelta);
+ /* CHECKED pointer not updated */
+ }
+}
+
+/* LATER consider using an extra field, updated on the fly */
+static void funbuff_max(t_funbuff *x)
+{
+ t_hammernode *np;
+ if (np = x->x_tree.t_first) /* CHECKED nop if empty */
+ {
+ t_float result = np->n_value;
+ while (np = np->n_next)
+ if (np->n_value > result) result = np->n_value;
+ funbuff_dooutput(x, result, x->x_lastdelta);
+ /* CHECKED pointer not updated */
+ }
+}
+
+static void funbuff_next(t_funbuff *x)
+{
+ t_hammernode *np;
+ if (!x->x_tree.t_root)
+ return;
+ if (!(np = x->x_pointer))
+ {
+ outlet_bang(x->x_bangout);
+ /* CHECKED banging until reset */
+ return;
+ }
+ if (x->x_pointerset)
+ x->x_lastdelta = 0;
+ else if (np->n_prev)
+ x->x_lastdelta = np->n_index - np->n_prev->n_index;
+ else
+ x->x_lastdelta = 0; /* CHECKED corrupt delta sent here... */
+ funbuff_dooutput(x, np->n_value, x->x_lastdelta);
+ x->x_pointer = np->n_next;
+ x->x_pointerset = 0;
+}
+
+static void funbuff_set(t_funbuff *x, t_symbol *s, int ac, t_atom *av)
+{
+ /* CHECKED symbols somehow bashed to zeros,
+ decreasing x coords corrupt the funbuff -- not emulated here... */
+ int i = ac;
+ t_atom *ap = av;
+ while (i--) if (ap++->a_type != A_FLOAT)
+ {
+ loud_error((t_pd *)x, "bad input (not a number) -- no data to set");
+ return;
+ }
+ if (!ac || (ac % 2))
+ {
+ /* CHECKED odd/null ac loudly rejected, current contents preserved */
+ loud_error((t_pd *)x, "bad input (%s) -- no data to set",
+ (ac ? "odd arg count" : "no input"));
+ return;
+ }
+ funbuff_clear(x); /* CHECKED the contents is replaced */
+ while (ac--)
+ {
+ t_hammernode *np;
+ if (np = hammertree_insert(&x->x_tree, (int)av++->a_w.w_float))
+ np->n_value = av++->a_w.w_float;
+ else return;
+ ac--;
+ }
+}
+
+static void funbuff_doread(t_funbuff *x, t_symbol *fn)
+{
+ t_binbuf *bb = binbuf_new();
+ int ac;
+ t_atom *av;
+ char buf[MAXPDSTRING];
+ canvas_makefilename(x->x_canvas, fn->s_name, buf, MAXPDSTRING);
+ binbuf_read(bb, buf, "", 0);
+ if ((ac = binbuf_getnatom(bb)) &&
+ (av = binbuf_getvec(bb)) &&
+ av->a_type == A_SYMBOL &&
+ av->a_w.w_symbol == gensym("funbuff"))
+ {
+ post("funbuff_read: %s read successful", fn->s_name); /* CHECKED */
+ funbuff_set(x, 0, ac-1, av+1);
+ }
+ else /* CHECKED no complaints... */
+ loud_error((t_pd *)x, "invalid file %s", fn->s_name);
+ binbuf_free(bb);
+}
+
+static void funbuff_readhook(t_pd *z, t_symbol *fn, int ac, t_atom *av)
+{
+ funbuff_doread((t_funbuff *)z, fn);
+}
+
+static void funbuff_dowrite(t_funbuff *x, t_symbol *fn)
+{
+ t_binbuf *bb = binbuf_new();
+ char buf[MAXPDSTRING];
+ t_hammernode *np;
+ binbuf_addv(bb, "s", gensym("funbuff"));
+ for (np = x->x_tree.t_first; np; np = np->n_next)
+ binbuf_addv(bb, "if", np->n_index, np->n_value);
+ canvas_makefilename(x->x_canvas, fn->s_name, buf, MAXPDSTRING);
+ binbuf_write(bb, buf, "", 0);
+ binbuf_free(bb);
+}
+
+static void funbuff_writehook(t_pd *z, t_symbol *fn, int ac, t_atom *av)
+{
+ funbuff_dowrite((t_funbuff *)z, fn);
+}
+
+static void funbuff_embedhook(t_pd *z, t_binbuf *bb, t_symbol *bindsym)
+{
+ t_funbuff *x = (t_funbuff *)z;
+ if (x->x_embedflag)
+ {
+ t_hammernode *np;
+ binbuf_addv(bb, "ssi;", bindsym, gensym("embed"), 1);
+ if (np = x->x_tree.t_first)
+ {
+ binbuf_addv(bb, "ss", bindsym, gensym("set"));
+ for (; np; np = np->n_next)
+ binbuf_addv(bb, "if", np->n_index, np->n_value);
+ binbuf_addsemi(bb);
+ }
+ }
+}
+
+/* CHECKED symbol arg ok */
+static void funbuff_read(t_funbuff *x, t_symbol *s)
+{
+ if (s && s != &s_)
+ funbuff_doread(x, s);
+ else
+ hammerpanel_open(x->x_filehandle);
+}
+
+/* CHECKED symbol arg not allowed --
+ a bug? but CHECKME other classes (cf seq's filetype dilemma) */
+static void funbuff_write(t_funbuff *x, t_symbol *s)
+{
+ if (s && s != &s_)
+ funbuff_dowrite(x, s);
+ else /* CHECKME default name */
+ hammerpanel_save(x->x_filehandle,
+ canvas_getdir(x->x_canvas), x->x_defname);
+}
+
+static void funbuff_delete(t_funbuff *x, t_symbol *s, int ac, t_atom *av)
+{
+ if (ac && av->a_type == A_FLOAT &&
+ (ac == 1 || (ac == 2 && av[1].a_type == A_FLOAT)))
+ {
+ /* CHECKED float is silently truncated */
+ int ndx = (int)av->a_w.w_float;
+ t_hammernode *np;
+ if ((np = hammertree_search(&x->x_tree, ndx)) &&
+ (ac == 1 || np->n_value == av[1].a_w.w_float))
+ {
+ if (np == x->x_pointer)
+ x->x_pointer = 0; /* CHECKED corrupt pointer left here... */
+ hammertree_delete(&x->x_tree, np);
+ }
+ /* CHECKED mismatch silently ignored */
+ }
+ else loud_messarg((t_pd *)x, s); /* CHECKED */
+}
+
+static void funbuff_find(t_funbuff *x, t_floatarg f)
+{
+ t_hammernode *np;
+ if (np = x->x_tree.t_first)
+ {
+ do
+ {
+ /* CHECKED lastdelta preserved */
+ if (np->n_value == f)
+ funbuff_dooutput(x, np->n_index, x->x_lastdelta);
+ }
+ while (np = np->n_next);
+ /* CHECKED no bangout, no complaint if nothing found */
+ }
+ else loud_error((t_pd *)x, "nothing to find"); /* CHECKED */
+}
+
+static void funbuff_dump(t_funbuff *x)
+{
+ t_hammernode *np;
+ if (np = x->x_tree.t_first)
+ {
+ do
+ {
+ x->x_lastdelta = np->n_value; /* CHECKED */
+ /* float value preserved (this is incompatible) */
+ funbuff_dooutput(x, np->n_index, np->n_value);
+ }
+ while (np = np->n_next);
+ /* CHECKED no bangout */
+ }
+ else loud_error((t_pd *)x, "nothing to dump"); /* CHECKED */
+}
+
+/* CHECKME if pointer is updated */
+static void funbuff_dointerp(t_funbuff *x, t_floatarg f, int vsz, t_float *vec)
+{
+ t_hammernode *np1;
+ int trunc = (int)f;
+ if (trunc > f) trunc--; /* CHECKME negative floats */
+ if (np1 = hammertree_closest(&x->x_tree, trunc, 0))
+ {
+ float value = np1->n_value;
+ t_hammernode *np2 = np1->n_next;
+ if (np2)
+ {
+ float delta = (float)(np2->n_index - np1->n_index);
+ /* this is incompatible -- CHECKED float argument is silently
+ truncated (which does not make much sense here), CHECKME again */
+ float frac = f - np1->n_index;
+ if (frac < 0 || frac >= delta)
+ {
+ bug("funbuff_dointerp");
+ return;
+ }
+ frac /= delta;
+ if (vec)
+ {
+ /* CHECKME */
+ float vpos = (vsz - 1) * frac;
+ int vndx = (int)vpos;
+ float vfrac = vpos - vndx;
+ if (vndx < 0 || vndx >= vsz - 1)
+ {
+ bug("funbuff_dointerp redundant test...");
+ return;
+ }
+ vec += vndx;
+ frac = *vec + (vec[1] - *vec) * vfrac;
+ }
+ value += (np2->n_value - np1->n_value) * frac;
+ }
+ funbuff_dooutput(x, value, x->x_lastdelta); /* CHECKME !np2 */
+ }
+ else if (np1 = hammertree_closest(&x->x_tree, trunc, 1))
+ funbuff_dooutput(x, np1->n_value, x->x_lastdelta); /* CHECKME */
+}
+
+static void funbuff_interp(t_funbuff *x, t_floatarg f)
+{
+ funbuff_dointerp(x, f, 0, 0);
+}
+
+static void funbuff_interptab(t_funbuff *x, t_symbol *s, t_floatarg f)
+{
+ int vsz;
+ t_float *vec;
+ if (vec = vefl_get(s, &vsz, 0, (t_pd *)x))
+ {
+ if (vsz > 2)
+ funbuff_dointerp(x, f, vsz, vec);
+ else
+ funbuff_dointerp(x, f, 0, 0);
+ }
+}
+
+static void funbuff_reduce(t_funbuff *x, t_floatarg f)
+{
+ loud_notimplemented((t_pd *)x, "reduce");
+}
+
+static void funbuff_select(t_funbuff *x, t_floatarg f1, t_floatarg f2)
+{
+ loud_notimplemented((t_pd *)x, "select");
+}
+
+/* CHECKED (sub)buffer's copy is stored, as expected --
+ 'delete' does not modify the clipboard */
+/* CHECKED cut entire contents if no selection */
+static void funbuff_cut(t_funbuff *x)
+{
+ loud_notimplemented((t_pd *)x, "cut");
+}
+
+/* CHECKED copy entire contents if no selection */
+static void funbuff_copy(t_funbuff *x)
+{
+ loud_notimplemented((t_pd *)x, "copy");
+}
+
+static void funbuff_paste(t_funbuff *x)
+{
+ loud_notimplemented((t_pd *)x, "paste");
+}
+
+static void funbuff_undo(t_funbuff *x)
+{
+ /* CHECKED apparently not working in 4.07 */
+ loud_notimplemented((t_pd *)x, "undo");
+}
+
+#ifdef HAMMERTREE_DEBUG
+static void funbuff_debug(t_funbuff *x, t_floatarg f)
+{
+ hammertree_debug(&x->x_tree, (int)f);
+}
+#endif
+
+static void funbuff_free(t_funbuff *x)
+{
+ hammerfile_free(x->x_filehandle);
+ hammertree_clear(&x->x_tree, 0);
+}
+
+static void *funbuff_new(t_symbol *s)
+{
+ t_funbuff *x = (t_funbuff *)pd_new(funbuff_class);
+ x->x_canvas = canvas_getcurrent();
+ x->x_valueset = 0;
+ x->x_pointer = 0;
+ x->x_pointerset = 0;
+ x->x_lastdelta = 0;
+ x->x_embedflag = 0;
+ hammertree_init(&x->x_tree, 0);
+ inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft1"));
+ outlet_new((t_object *)x, &s_float);
+ x->x_deltaout = outlet_new((t_object *)x, &s_float);
+ x->x_bangout = outlet_new((t_object *)x, &s_bang);
+ if (s && s != &s_)
+ {
+ x->x_defname = s; /* CHECKME if 'read' changes this */
+ funbuff_doread(x, s);
+ }
+ else x->x_defname = &s_;
+ x->x_filehandle = hammerfile_new((t_pd *)x, funbuff_embedhook,
+ funbuff_readhook, funbuff_writehook, 0);
+ return (x);
+}
+
+void funbuff_setup(void)
+{
+ funbuff_class = class_new(gensym("funbuff"),
+ (t_newmethod)funbuff_new,
+ (t_method)funbuff_free,
+ sizeof(t_funbuff), 0, A_DEFSYM, 0);
+ class_addbang(funbuff_class, funbuff_bang);
+ class_addfloat(funbuff_class, funbuff_float);
+ class_addmethod(funbuff_class, (t_method)funbuff_ft1,
+ gensym("ft1"), A_FLOAT, 0);
+ class_addmethod(funbuff_class, (t_method)funbuff_clear,
+ gensym("clear"), 0);
+ class_addmethod(funbuff_class, (t_method)funbuff_goto,
+ gensym("goto"), A_FLOAT, 0);
+ class_addmethod(funbuff_class, (t_method)funbuff_min,
+ gensym("min"), 0);
+ class_addmethod(funbuff_class, (t_method)funbuff_max,
+ gensym("max"), 0);
+ class_addmethod(funbuff_class, (t_method)funbuff_next,
+ gensym("next"), 0);
+ class_addmethod(funbuff_class, (t_method)funbuff_embed,
+ gensym("embed"), A_FLOAT, 0);
+ class_addmethod(funbuff_class, (t_method)funbuff_read,
+ gensym("read"), A_DEFSYM, 0);
+ class_addmethod(funbuff_class, (t_method)funbuff_write,
+ gensym("write"), A_DEFSYM, 0);
+ class_addmethod(funbuff_class, (t_method)funbuff_set,
+ gensym("set"), A_GIMME, 0);
+ class_addmethod(funbuff_class, (t_method)funbuff_delete,
+ gensym("delete"), A_GIMME, 0);
+ class_addmethod(funbuff_class, (t_method)funbuff_find,
+ gensym("find"), A_FLOAT, 0);
+ class_addmethod(funbuff_class, (t_method)funbuff_dump,
+ gensym("dump"), 0);
+ class_addmethod(funbuff_class, (t_method)funbuff_interp,
+ gensym("interp"), A_FLOAT, 0);
+ class_addmethod(funbuff_class, (t_method)funbuff_interptab,
+ gensym("interptab"), A_FLOAT, A_SYMBOL, 0);
+ class_addmethod(funbuff_class, (t_method)funbuff_reduce,
+ gensym("reduce"), A_FLOAT, 0);
+ class_addmethod(funbuff_class, (t_method)funbuff_select,
+ gensym("select"), A_FLOAT, A_FLOAT, 0);
+ class_addmethod(funbuff_class, (t_method)funbuff_cut,
+ gensym("cut"), 0);
+ class_addmethod(funbuff_class, (t_method)funbuff_copy,
+ gensym("copy"), 0);
+ class_addmethod(funbuff_class, (t_method)funbuff_paste,
+ gensym("paste"), 0);
+ class_addmethod(funbuff_class, (t_method)funbuff_undo,
+ gensym("undo"), 0);
+#ifdef HAMMERTREE_DEBUG
+ class_addmethod(funbuff_class, (t_method)funbuff_debug,
+ gensym("debug"), A_DEFFLOAT, 0);
+#endif
+ hammerfile_setup(funbuff_class, 1);
+}
diff --git a/cyclone/hammer/funnel.c b/cyclone/hammer/funnel.c
new file mode 100644
index 0000000..d289d8d
--- /dev/null
+++ b/cyclone/hammer/funnel.c
@@ -0,0 +1,179 @@
+/* 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"
+
+#define FUNNEL_MINSLOTS 2
+#define FUNNEL_INISIZE 32 /* LATER rethink */
+#define FUNNEL_MAXSIZE 256
+
+typedef struct _funnel
+{
+ t_object x_ob;
+ int x_nslots;
+ int x_nproxies; /* as requested (and allocated) */
+ t_pd **x_proxies;
+} t_funnel;
+
+typedef struct _funnel_proxy
+{
+ t_object p_ob;
+ t_outlet *p_out; /* master outlet (the same value for each slot) */
+ int p_id; /* adjusted according to an offset argument */
+ t_float p_value;
+ int p_size; /* as allocated */
+ t_atom *p_message;
+ t_atom p_messini[FUNNEL_INISIZE];
+ int p_entered;
+} t_funnel_proxy;
+
+static t_class *funnel_class;
+static t_class *funnel_proxy_class;
+
+static void funnel_proxy_bang(t_funnel_proxy *x)
+{
+ t_atom at[2];
+ SETFLOAT(&at[0], x->p_id);
+ SETFLOAT(&at[1], x->p_value);
+ outlet_list(x->p_out, &s_list, 2, at);
+}
+
+static void funnel_proxy_float(t_funnel_proxy *x, t_float f)
+{
+ x->p_value = f;
+ funnel_proxy_bang(x);
+}
+
+static void funnel_proxy_list(t_funnel_proxy *x,
+ t_symbol *s, int ac, t_atom *av)
+{
+ int reentered = x->p_entered;
+ int prealloc = !reentered;
+ int ntotal = ac + 1;
+ x->p_entered = 1;
+ if (prealloc && ntotal > x->p_size)
+ {
+ if (ntotal > FUNNEL_MAXSIZE)
+ prealloc = 0;
+ else
+ {
+ x->p_message = grow_nodata(&ntotal, &x->p_size, x->p_message,
+ FUNNEL_INISIZE, x->p_messini,
+ sizeof(*x->p_message));
+ ac = ntotal - 1;
+ }
+ }
+ /* LATER consider a compatibility warning if av->a_type != A_FLOAT */
+ x->p_value = ((ac && av->a_type == A_FLOAT) ? av->a_w.w_float : 0);
+ if (prealloc)
+ {
+ SETFLOAT(x->p_message, x->p_id);
+ if (ac)
+ memcpy(x->p_message + 1, av, ac * sizeof(*x->p_message));
+ outlet_list(x->p_out, &s_list, ntotal, x->p_message);
+ }
+ else
+ {
+ /* LATER consider using the stack if ntotal <= MAXSTACK */
+ t_atom *buf = getbytes(ntotal * sizeof(*buf));
+ if (buf)
+ {
+ SETFLOAT(buf, x->p_id);
+ if (ac)
+ memcpy(buf + 1, av, ac * sizeof(*buf));
+ outlet_list(x->p_out, &s_list, ntotal, buf);
+ freebytes(buf, ntotal * sizeof(*buf));
+ }
+ }
+ if (!reentered) x->p_entered = 0;
+}
+
+static void funnel_bang(t_funnel *x)
+{
+ funnel_proxy_bang((t_funnel_proxy *)x->x_proxies[0]);
+}
+
+static void funnel_float(t_funnel *x, t_float f)
+{
+ funnel_proxy_float((t_funnel_proxy *)x->x_proxies[0], f);
+}
+
+static void funnel_list(t_funnel *x, t_symbol *s, int ac, t_atom *av)
+{
+ funnel_proxy_list((t_funnel_proxy *)x->x_proxies[0], s, ac, av);
+}
+
+static void funnel_free(t_funnel *x)
+{
+ if (x->x_proxies)
+ {
+ int i = x->x_nslots;
+ while (i--)
+ {
+ t_funnel_proxy *y = (t_funnel_proxy *)x->x_proxies[i];
+ if (y->p_message != y->p_messini)
+ freebytes(y->p_message, y->p_size * sizeof(*y->p_message));
+ pd_free((t_pd *)y);
+ }
+ freebytes(x->x_proxies, x->x_nproxies * sizeof(*x->x_proxies));
+ }
+}
+
+static void *funnel_new(t_floatarg f1, t_floatarg f2)
+{
+ t_funnel *x;
+ int i, nslots, nproxies = (int)f1;
+ int offset = (int)f2;
+ t_outlet *out;
+ t_pd **proxies;
+ if (nproxies < 1) /* CHECKED: one-slot funnel may be created */
+ nproxies = FUNNEL_MINSLOTS;
+ if (!(proxies = (t_pd **)getbytes(nproxies * sizeof(*proxies))))
+ return (0);
+ for (nslots = 0; nslots < nproxies; nslots++)
+ if (!(proxies[nslots] = pd_new(funnel_proxy_class))) break;
+ if (!nslots)
+ {
+ freebytes(proxies, nproxies * sizeof(*proxies));
+ return (0);
+ }
+ x = (t_funnel *)pd_new(funnel_class);
+ x->x_nslots = nslots;
+ x->x_nproxies = nproxies;
+ x->x_proxies = proxies;
+ out = outlet_new((t_object *)x, &s_list);
+ for (i = 0; i < nslots; i++)
+ {
+ t_funnel_proxy *y = (t_funnel_proxy *)proxies[i];
+ y->p_out = out;
+ y->p_id = offset++;
+ y->p_value = 0;
+ y->p_size = FUNNEL_INISIZE;
+ y->p_message = y->p_messini;
+ y->p_entered = 0;
+ if (i) inlet_new((t_object *)x, (t_pd *)y, 0, 0);
+ }
+ return (x);
+}
+
+void funnel_setup(void)
+{
+ funnel_class = class_new(gensym("funnel"),
+ (t_newmethod)funnel_new,
+ (t_method)funnel_free,
+ sizeof(t_funnel), 0, A_DEFFLOAT, A_DEFFLOAT, 0);
+ class_addbang(funnel_class, funnel_bang);
+ class_addfloat(funnel_class, funnel_float);
+ class_addlist(funnel_class, funnel_list);
+ /* CHECKED: funnel doesn't understand symbol, anything */
+ funnel_proxy_class = class_new(gensym("_funnel_proxy"), 0, 0,
+ sizeof(t_funnel_proxy),
+ CLASS_PD | CLASS_NOINLET, 0);
+ class_addbang(funnel_proxy_class, funnel_proxy_bang);
+ class_addfloat(funnel_proxy_class, funnel_proxy_float);
+ class_addlist(funnel_proxy_class, funnel_proxy_list);
+ /* CHECKED: funnel doesn't understand symbol, anything */
+}
diff --git a/cyclone/hammer/gate.c b/cyclone/hammer/gate.c
new file mode 100644
index 0000000..2dbae57
--- /dev/null
+++ b/cyclone/hammer/gate.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. */
+
+#include "m_pd.h"
+#include "common/loud.h"
+
+#define GATE_MINOUTS 1
+#define GATE_MAXOUTS 100
+#define GATE_DEFOUTS 1
+
+typedef struct _gate
+{
+ t_object x_ob;
+ int x_open;
+ t_pd *x_proxy;
+ int x_nouts; /* requested + 1 (as allocated) */
+ t_outlet **x_outs;
+} t_gate;
+
+typedef struct _gate_proxy
+{
+ t_object p_ob;
+ t_gate *p_master;
+} t_gate_proxy;
+
+static t_class *gate_class;
+static t_class *gate_proxy_class;
+
+static void gate_proxy_bang(t_gate_proxy *x)
+{
+ t_gate *master = x->p_master;
+ if (master->x_open)
+ outlet_bang(master->x_outs[master->x_open]);
+}
+
+static void gate_proxy_float(t_gate_proxy *x, t_float f)
+{
+ t_gate *master = x->p_master;
+ if (master->x_open)
+ outlet_float(master->x_outs[master->x_open], f);
+}
+
+static void gate_proxy_symbol(t_gate_proxy *x, t_symbol *s)
+{
+ t_gate *master = x->p_master;
+ if (master->x_open)
+ outlet_symbol(master->x_outs[master->x_open], s);
+}
+
+static void gate_proxy_pointer(t_gate_proxy *x, t_gpointer *gp)
+{
+ t_gate *master = x->p_master;
+ if (master->x_open)
+ outlet_pointer(master->x_outs[master->x_open], gp);
+}
+
+static void gate_proxy_list(t_gate_proxy *x,
+ t_symbol *s, int ac, t_atom *av)
+{
+ t_gate *master = x->p_master;
+ if (master->x_open)
+ outlet_list(master->x_outs[master->x_open], s, ac, av);
+}
+
+static void gate_proxy_anything(t_gate_proxy *x,
+ t_symbol *s, int ac, t_atom *av)
+{
+ t_gate *master = x->p_master;
+ if (master->x_open)
+ outlet_anything(master->x_outs[master->x_open], s, ac, av);
+}
+
+static void gate_float(t_gate *x, t_float f)
+{
+ int i = (int)f;
+ if (i < 0) i = 1;
+ if (i >= x->x_nouts) i = x->x_nouts - 1;
+ x->x_open = i;
+}
+
+static void gate_bang(t_gate *x)
+{
+ outlet_float(x->x_outs[1], x->x_open);
+}
+
+static void gate_free(t_gate *x)
+{
+ if (x->x_proxy) pd_free(x->x_proxy);
+ if (x->x_outs)
+ freebytes(x->x_outs, x->x_nouts * sizeof(*x->x_outs));
+}
+
+static void *gate_new(t_floatarg f1, t_floatarg f2)
+{
+ t_gate *x;
+ int i, nouts = (int)f1;
+ t_outlet **outs;
+ t_pd *proxy;
+ if (nouts < GATE_MINOUTS)
+ nouts = GATE_DEFOUTS;
+ if (nouts > GATE_MAXOUTS)
+ loud_incompatible_max(gate_class, GATE_MAXOUTS, "outlets");
+ nouts++; /* for convenience (the cost is one pointer) */
+ if (!(outs = (t_outlet **)getbytes(nouts * sizeof(*outs))))
+ return (0);
+ if (!(proxy = pd_new(gate_proxy_class)))
+ {
+ freebytes(outs, nouts * sizeof(*outs));
+ return (0);
+ }
+ x = (t_gate *)pd_new(gate_class);
+ x->x_nouts = nouts;
+ x->x_outs = outs;
+ x->x_proxy = proxy;
+ ((t_gate_proxy *)proxy)->p_master = x;
+ /* from max sdk manual: ``The dst parameter can be changed (or set to 0)
+ dynamically with the inlet_to function... The gate object uses this
+ technique to assign its inlet to one of several outlets, or no outlet
+ at all.'' We have to use a proxy, because Pd's outlet is not a t_pd
+ (besides, Pd does not handle inlets with null destination). */
+ inlet_new((t_object *)x, proxy, 0, 0);
+ for (i = 1; i < nouts; i++)
+ x->x_outs[i] = outlet_new((t_object *)x, &s_anything);
+ gate_float(x, (f2 > 0 ? f2 : 0)); /* CHECKED */
+ return (x);
+}
+
+void gate_setup(void)
+{
+ gate_class = class_new(gensym("gate"),
+ (t_newmethod)gate_new,
+ (t_method)gate_free,
+ sizeof(t_gate), 0,
+ A_DEFFLOAT, A_DEFFLOAT, 0);
+ class_addfloat(gate_class, gate_float);
+ class_addbang(gate_class, gate_bang);
+ gate_proxy_class = class_new(gensym("_gate_proxy"), 0, 0,
+ sizeof(t_gate_proxy),
+ CLASS_PD | CLASS_NOINLET, 0);
+ class_addfloat(gate_proxy_class, gate_proxy_float);
+ class_addbang(gate_proxy_class, gate_proxy_bang);
+ class_addsymbol(gate_proxy_class, gate_proxy_symbol);
+ class_addpointer(gate_proxy_class, gate_proxy_pointer);
+ class_addlist(gate_proxy_class, gate_proxy_list);
+ class_addanything(gate_proxy_class, gate_proxy_anything);
+}
diff --git a/cyclone/hammer/grab.c b/cyclone/hammer/grab.c
new file mode 100644
index 0000000..a54a3eb
--- /dev/null
+++ b/cyclone/hammer/grab.c
@@ -0,0 +1,279 @@
+/* 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 "unstable/pd_imp.h"
+#include "unstable/fragile.h"
+#include "common/loud.h"
+
+/* LATER handle canvas grabbing (bypass) */
+/* LATER check self-grabbing */
+/* LATER fragilize */
+
+/* It would be nice to have write access to o_connections field... */
+
+struct _outlet
+{
+ t_object *o_owner;
+ struct _outlet *o_next;
+ t_outconnect *o_connections;
+ t_symbol *o_sym;
+};
+
+/* ...and to have bindlist traversal routines in Pd API. */
+
+static t_class *bindlist_class = 0;
+
+typedef struct _bindelem
+{
+ t_pd *e_who;
+ struct _bindelem *e_next;
+} t_bindelem;
+
+typedef struct _bindlist
+{
+ t_pd b_pd;
+ t_bindelem *b_list;
+} t_bindlist;
+
+typedef struct _grab
+{
+ t_object x_ob;
+ t_symbol *x_target;
+ int x_noutlets; /* not counting right one */
+ t_outconnect **x_grabcons; /* grabbed connections */
+ t_outlet *x_rightout; /* right outlet */
+ /* traversal helpers: */
+ t_object *x_grabbed; /* currently grabbed object */
+ t_outconnect *x_tograbbed; /* a connection to grabbed object */
+ int x_ngrabout; /* number of grabbed object's outlets */
+ t_bindelem *x_bindelem;
+} t_grab;
+
+static t_class *grab_class;
+
+static void grab_start(t_grab *x)
+{
+ x->x_tograbbed = 0;
+ x->x_bindelem = 0;
+ if (x->x_target)
+ {
+ t_pd *proxy = x->x_target->s_thing;
+ t_object *ob;
+ if (proxy && bindlist_class)
+ {
+ if (*proxy == bindlist_class)
+ {
+ x->x_bindelem = ((t_bindlist *)proxy)->b_list;
+ while (x->x_bindelem)
+ {
+ if (ob = pd_checkobject(x->x_bindelem->e_who))
+ {
+ x->x_tograbbed =
+ fragile_outlet_connections(ob->ob_outlet);
+ return;
+ }
+ x->x_bindelem = x->x_bindelem->e_next;
+ }
+ }
+ else if (ob = pd_checkobject(proxy))
+ x->x_tograbbed = fragile_outlet_connections(ob->ob_outlet);
+ }
+ }
+ else x->x_tograbbed = fragile_outlet_connections(x->x_rightout);
+}
+
+static t_pd *grab_next(t_grab *x)
+{
+nextremote:
+ if (x->x_tograbbed)
+ {
+ t_inlet *ip;
+ int inno;
+ x->x_tograbbed = obj_nexttraverseoutlet(x->x_tograbbed,
+ &x->x_grabbed, &ip, &inno);
+ if (x->x_grabbed)
+ {
+ if (inno)
+ {
+ if (x->x_target)
+ loud_error((t_pd *)x,
+ "right outlet must feed leftmost inlet");
+ else
+ loud_error((t_pd *)x,
+ "remote proxy must feed leftmost inlet");
+ }
+ else
+ {
+ t_outlet *op;
+ t_outlet *goutp;
+ int goutno = x->x_noutlets;
+ x->x_ngrabout = obj_noutlets(x->x_grabbed);
+ if (goutno > x->x_ngrabout) goutno = x->x_ngrabout;
+ while (goutno--)
+ {
+ x->x_grabcons[goutno] =
+ obj_starttraverseoutlet(x->x_grabbed, &goutp, goutno);
+ goutp->o_connections =
+ obj_starttraverseoutlet((t_object *)x, &op, goutno);
+ }
+ return ((t_pd *)x->x_grabbed);
+ }
+ }
+ }
+ if (x->x_bindelem) while (x->x_bindelem = x->x_bindelem->e_next)
+ {
+ t_object *ob;
+ if (ob = pd_checkobject(x->x_bindelem->e_who))
+ {
+ x->x_tograbbed = fragile_outlet_connections(ob->ob_outlet);
+ goto nextremote;
+ }
+ }
+ return (0);
+}
+
+static void grab_restore(t_grab *x)
+{
+ t_outlet *goutp;
+ int goutno = x->x_noutlets;
+ if (goutno > x->x_ngrabout) goutno = x->x_ngrabout;
+ while (goutno--)
+ {
+ obj_starttraverseoutlet(x->x_grabbed, &goutp, goutno);
+ goutp->o_connections = x->x_grabcons[goutno];
+ }
+}
+
+static void grab_bang(t_grab *x)
+{
+ t_pd *grabbed;
+ grab_start(x);
+ while (grabbed = grab_next(x))
+ {
+ pd_bang(grabbed);
+ grab_restore(x);
+ }
+}
+
+static void grab_float(t_grab *x, t_float f)
+{
+ t_pd *grabbed;
+ grab_start(x);
+ while (grabbed = grab_next(x))
+ {
+ pd_float(grabbed, f);
+ grab_restore(x);
+ }
+}
+
+static void grab_symbol(t_grab *x, t_symbol *s)
+{
+ t_pd *grabbed;
+ grab_start(x);
+ while (grabbed = grab_next(x))
+ {
+ pd_symbol(grabbed, s);
+ grab_restore(x);
+ }
+}
+
+static void grab_pointer(t_grab *x, t_gpointer *gp)
+{
+ t_pd *grabbed;
+ grab_start(x);
+ while (grabbed = grab_next(x))
+ {
+ pd_pointer(grabbed, gp);
+ grab_restore(x);
+ }
+}
+
+static void grab_list(t_grab *x, t_symbol *s, int ac, t_atom *av)
+{
+ t_pd *grabbed;
+ grab_start(x);
+ while (grabbed = grab_next(x))
+ {
+ pd_list(grabbed, s, ac, av);
+ grab_restore(x);
+ }
+}
+
+static void grab_anything(t_grab *x, t_symbol *s, int ac, t_atom *av)
+{
+ t_pd *grabbed;
+ grab_start(x);
+ while (grabbed = grab_next(x))
+ {
+ typedmess(grabbed, s, ac, av);
+ grab_restore(x);
+ }
+}
+
+static void grab_set(t_grab *x, t_symbol *s)
+{
+ if (x->x_target && s && s != &s_) x->x_target = s;
+}
+
+/* LATER use A_GIMME */
+static void *grab_new(t_symbol *s, t_floatarg f)
+{
+ t_grab *x;
+ t_outconnect **grabcons;
+ int i, noutlets = (int)f;
+ if (noutlets < 1) noutlets = 1;
+ if (!(grabcons = getbytes(noutlets * sizeof(*grabcons))))
+ return (0);
+ x = (t_grab *)pd_new(grab_class);
+ x->x_noutlets = noutlets;
+ x->x_grabcons = grabcons;
+ while (noutlets--) outlet_new((t_object *)x, &s_anything);
+ if (s && s != &s_)
+ {
+ x->x_target = s;
+ x->x_rightout = 0;
+ }
+ else
+ {
+ x->x_target = 0;
+ x->x_rightout = outlet_new((t_object *)x, &s_anything);
+ }
+ return (x);
+}
+
+static void grab_free(t_grab *x)
+{
+ if (x->x_grabcons)
+ freebytes(x->x_grabcons, x->x_noutlets * sizeof(*x->x_grabcons));
+}
+
+void grab_setup(void)
+{
+ t_symbol *s = gensym("grab");
+ grab_class = class_new(s, (t_newmethod)grab_new,
+ (t_method)grab_free,
+ sizeof(t_grab), 0,
+ A_DEFFLOAT, A_DEFSYMBOL, 0);
+ class_addfloat(grab_class, grab_float);
+ class_addbang(grab_class, grab_bang);
+ class_addsymbol(grab_class, grab_symbol);
+ class_addpointer(grab_class, grab_pointer);
+ class_addlist(grab_class, grab_list);
+ class_addanything(grab_class, grab_anything);
+ class_addmethod(grab_class, (t_method)grab_set,
+ gensym("set"), A_SYMBOL, 0);
+ if (!bindlist_class)
+ {
+ t_class *c = grab_class;
+ pd_bind(&grab_class, s);
+ pd_bind(&c, s);
+ if (!s->s_thing
+ || !(bindlist_class = *s->s_thing)
+ || bindlist_class->c_name != gensym("bindlist"))
+ error("grab: failure to initialize remote grabbing feature");
+ pd_unbind(&c, s);
+ pd_unbind(&grab_class, s);
+ }
+}
diff --git a/cyclone/hammer/hammer.c b/cyclone/hammer/hammer.c
new file mode 100644
index 0000000..a4d7efe
--- /dev/null
+++ b/cyclone/hammer/hammer.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 allhammers_setup(void);
+
+typedef struct _hammer
+{
+ t_object x_ob;
+ t_symbol *x_dir;
+ t_hammerfile *x_filehandle;
+} t_hammer;
+
+static t_class *hammer_class;
+static int hammer_firstndx;
+static int hammer_lastndx;
+
+static void hammer_readhook(t_pd *z, t_symbol *fn, int ac, t_atom *av)
+{
+ import_max(fn->s_name, "");
+}
+
+static void hammer_import(t_hammer *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 hammer_click(t_hammer *x, t_floatarg xpos, t_floatarg ypos,
+ t_floatarg shift, t_floatarg ctrl, t_floatarg alt)
+{
+ hammer_import(x, 0, 0);
+}
+
+static void hammer_bang(t_hammer *x)
+{
+ fragile_class_printnames("hammer classes are: ",
+ hammer_firstndx, hammer_lastndx);
+}
+
+static void hammer_free(t_hammer *x)
+{
+ hammerfile_free(x->x_filehandle);
+}
+
+static void *hammer_new(t_symbol *s)
+{
+ t_hammer *x = (t_hammer *)pd_new(hammer_class);
+ x->x_filehandle = hammerfile_new((t_pd *)x, 0, hammer_readhook, 0, 0);
+ x->x_dir = (s && s != &s_ ? s : canvas_getdir(x->x_filehandle->f_canvas));
+ return (x);
+}
+
+void hammer_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 'hammer' object");
+ loud_errand(0, "without having hammer library preloaded");
+ return;
+ }
+ if (!zgetfn(&pd_objectmaker, gensym("cyclone")))
+ post("this is hammer %s, %s %s build",
+ CYCLONE_VERSION, loud_ordinal(CYCLONE_BUILD), CYCLONE_RELEASE);
+ hammer_class = class_new(gensym("hammer"),
+ (t_newmethod)hammer_new,
+ (t_method)hammer_free,
+ sizeof(t_hammer), 0, A_DEFSYM, 0);
+ class_addbang(hammer_class, hammer_bang);
+ class_addmethod(hammer_class, (t_method)hammer_import,
+ gensym("import"), A_DEFSYM, A_DEFSYM, 0);
+ class_addmethod(hammer_class, (t_method)hammer_click,
+ gensym("click"),
+ A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0);
+ hammerfile_setup(hammer_class, 0);
+ hammer_firstndx = fragile_class_count();
+ allhammers_setup();
+ hammer_lastndx = fragile_class_count() - 1;
+}
diff --git a/cyclone/hammer/iter.c b/cyclone/hammer/iter.c
new file mode 100644
index 0000000..0aa5ef8
--- /dev/null
+++ b/cyclone/hammer/iter.c
@@ -0,0 +1,112 @@
+/* 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. */
+
+/* This is a modified version of Joseph A. Sarlo's code.
+ The most important changes are listed in "pd-lib-notes.txt" file. */
+
+/* LATER compare with iter.c from max sdk */
+/* LATER clean up buffer handling */
+
+#include <string.h>
+#include "m_pd.h"
+#include "common/grow.h"
+
+#define ITER_INISIZE 8 /* LATER rethink */
+
+typedef struct _iter
+{
+ t_object x_ob;
+ int x_size; /* as allocated */
+ int x_natoms; /* as used */
+ t_symbol *x_selector;
+ t_atom *x_message;
+ t_atom x_messini[ITER_INISIZE];
+} t_iter;
+
+static t_class *iter_class;
+
+/* CHECKED: both floats and symbols */
+static void iter_dobang(t_iter *x, t_symbol *s, int ac, t_atom *av)
+{
+ if (s && s != &s_)
+ outlet_symbol(((t_object *)x)->ob_outlet, s);
+ while (ac--)
+ {
+ if (av->a_type == A_FLOAT)
+ outlet_float(((t_object *)x)->ob_outlet, av->a_w.w_float);
+ else if (av->a_type == A_SYMBOL)
+ outlet_symbol(((t_object *)x)->ob_outlet, av->a_w.w_symbol);
+ av++;
+ }
+}
+
+static void iter_bang(t_iter *x)
+{
+ iter_dobang(x, x->x_selector, x->x_natoms, x->x_message);
+}
+
+static void iter_float(t_iter *x, t_float f)
+{
+ outlet_float(((t_object *)x)->ob_outlet, f);
+ x->x_selector = 0;
+ x->x_natoms = 1;
+ SETFLOAT(x->x_message, f);
+}
+
+/* CHECKME */
+static void iter_symbol(t_iter *x, t_symbol *s)
+{
+ outlet_symbol(((t_object *)x)->ob_outlet, s);
+ x->x_selector = 0;
+ x->x_natoms = 1;
+ SETSYMBOL(x->x_message, s);
+}
+
+/* LATER gpointer */
+
+static void iter_anything(t_iter *x, t_symbol *s, int ac, t_atom *av)
+{
+ iter_dobang(x, s, ac, av);
+ x->x_selector = s;
+ if (ac > x->x_size)
+ x->x_message = grow_nodata(&ac, &x->x_size, x->x_message,
+ ITER_INISIZE, x->x_messini,
+ sizeof(*x->x_message));
+ x->x_natoms = ac;
+ memcpy(x->x_message, av, ac * sizeof(*x->x_message));
+}
+
+static void iter_list(t_iter *x, t_symbol *s, int ac, t_atom *av)
+{
+ iter_anything(x, 0, ac, av);
+}
+
+static void iter_free(t_iter *x)
+{
+ if (x->x_message != x->x_messini)
+ freebytes(x->x_message, x->x_natoms * sizeof(*x->x_message));
+}
+
+static void *iter_new(void)
+{
+ t_iter *x = (t_iter *)pd_new(iter_class);
+ x->x_size = ITER_INISIZE;
+ x->x_natoms = 0;
+ x->x_message = x->x_messini;
+ outlet_new((t_object *)x, &s_anything);
+ return (x);
+}
+
+void iter_setup(void)
+{
+ iter_class = class_new(gensym("iter"),
+ (t_newmethod)iter_new,
+ (t_method)iter_free,
+ sizeof(t_iter), 0, 0);
+ class_addbang(iter_class, iter_bang);
+ class_addfloat(iter_class, iter_float);
+ class_addsymbol(iter_class, iter_symbol);
+ class_addlist(iter_class, iter_list);
+ class_addanything(iter_class, iter_anything);
+}
diff --git a/cyclone/hammer/match.c b/cyclone/hammer/match.c
new file mode 100644
index 0000000..d5b03c7
--- /dev/null
+++ b/cyclone/hammer/match.c
@@ -0,0 +1,216 @@
+/* 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 compare with match.c from max sdk */
+
+#include <string.h>
+#include "m_pd.h"
+#include "common/grow.h"
+
+#define MATCH_INISIZE 8 /* LATER rethink */
+
+typedef struct _match
+{
+ t_object x_ob;
+ int x_size; /* as allocated */
+ int x_patlen; /* as used */
+ t_atom *x_pattern;
+ t_atom x_patini[MATCH_INISIZE];
+ int x_quelen;
+ t_atom *x_queue;
+ t_atom x_queini[MATCH_INISIZE];
+ t_atom *x_queend;
+ t_atom *x_queptr; /* writing head, post-incremented (oldest-pointing) */
+} t_match;
+
+static t_class *match_class;
+
+static void match_clear(t_match *x)
+{
+ x->x_quelen = 0;
+ x->x_queptr = x->x_queue;
+}
+
+/* x->x_patlen > 0 is assumed */
+/* LATER use a lock to disable reentrant calls. I do not see any
+ purpose of reentering match, but lets CHECKME first... */
+static void match_checkin(t_match *x)
+{
+ int i, patlen = x->x_patlen;
+ t_atom *queptr, *pp, *qp;
+ if (x->x_queptr >= x->x_queend)
+ x->x_queptr = x->x_queue;
+ else x->x_queptr++;
+ if (x->x_quelen < patlen && ++(x->x_quelen) < patlen)
+ return;
+
+ qp = queptr = x->x_queptr;
+ for (i = 0, pp = x->x_pattern; i < patlen; i++, pp++)
+ {
+ if (pp->a_type == A_FLOAT)
+ {
+ if (qp->a_type != A_FLOAT || qp->a_w.w_float != pp->a_w.w_float)
+ break;
+ }
+ else if (pp->a_type == A_SYMBOL)
+ {
+ if (qp->a_type != A_SYMBOL || qp->a_w.w_symbol != pp->a_w.w_symbol)
+ break;
+ }
+ else if (pp->a_type == A_NULL)
+ {
+ if (qp->a_type == A_FLOAT || qp->a_type == A_SYMBOL)
+ {
+ /* instantiating a pattern */
+ *pp = *qp;
+ qp->a_type = A_NULL;
+ }
+ else break; /* LATER rethink */
+ }
+ else break; /* LATER rethink */
+ if (qp >= x->x_queend)
+ qp = x->x_queue;
+ else qp++;
+ }
+ if (i == patlen)
+ {
+ pp = x->x_pattern;
+ if (pp->a_type == A_FLOAT)
+ {
+ if (patlen == 1)
+ outlet_float(((t_object *)x)->ob_outlet, pp->a_w.w_float);
+ else
+ outlet_list(((t_object *)x)->ob_outlet, &s_list, patlen, pp);
+ }
+ else /* assuming A_SYMBOL (see above) */
+ {
+ if (pp->a_w.w_symbol == &s_symbol /* bypassing typedmess() */
+ && patlen == 2 && pp[1].a_type == A_SYMBOL)
+ outlet_symbol(((t_object *)x)->ob_outlet, pp[1].a_w.w_symbol);
+ else
+ outlet_anything(((t_object *)x)->ob_outlet, pp->a_w.w_symbol,
+ patlen - 1, pp + 1);
+ }
+ /* CHECKED: no implicit clear (resolving overlapping patterns) */
+ }
+ /* restoring a pattern */
+ for (i = 0, pp = x->x_pattern; i < patlen; i++, pp++)
+ {
+ if (queptr->a_type == A_NULL)
+ {
+ queptr->a_type = pp->a_type;
+ pp->a_type = A_NULL;
+ }
+ if (queptr >= x->x_queend)
+ queptr = x->x_queue;
+ else queptr++;
+ }
+}
+
+static void match_float(t_match *x, t_float f)
+{
+ if (x->x_patlen)
+ {
+ SETFLOAT(x->x_queptr, f);
+ match_checkin(x);
+ }
+}
+
+static void match_symbol(t_match *x, t_symbol *s)
+{
+ if (s && s != &s_ && x->x_patlen)
+ {
+ SETSYMBOL(x->x_queptr, s);
+ match_checkin(x);
+ }
+}
+
+/* LATER gpointer */
+
+static void match_list(t_match *x, t_symbol *s, int ac, t_atom *av)
+{
+ while (ac--)
+ {
+ if (av->a_type == A_FLOAT) match_float(x, av->a_w.w_float);
+ else if (av->a_type == A_SYMBOL) match_symbol(x, av->a_w.w_symbol);
+ av++;
+ }
+}
+
+static void match_anything(t_match *x, t_symbol *s, int ac, t_atom *av)
+{
+ match_symbol(x, s);
+ match_list(x, 0, ac, av);
+}
+
+static void match_set(t_match *x, t_symbol *s, int ac, t_atom *av)
+{
+ if (ac) /* CHECKED */
+ {
+ t_atom *pp;
+ t_symbol *ps_nn;
+ int newlen = ac * 2;
+ if (newlen > x->x_size)
+ {
+ x->x_pattern = grow_nodata(&newlen, &x->x_size, x->x_pattern,
+ MATCH_INISIZE * 2, x->x_patini,
+ sizeof(*x->x_pattern));
+ if (newlen == MATCH_INISIZE * 2)
+ {
+ x->x_queue = x->x_queini;
+ ac = MATCH_INISIZE;
+ }
+ else x->x_queue = x->x_pattern + x->x_size / 2;
+ }
+ x->x_patlen = ac;
+ x->x_queend = x->x_queue + ac - 1;
+ match_clear(x); /* CHECKED */
+ memcpy(x->x_pattern, av, ac * sizeof(*x->x_pattern));
+ pp = x->x_pattern;
+ ps_nn = gensym("nn");
+ while (ac--)
+ {
+ if (pp->a_type == A_SYMBOL && pp->a_w.w_symbol == ps_nn)
+ pp->a_type = A_NULL;
+ pp++;
+ }
+ }
+}
+
+static void match_free(t_match *x)
+{
+ if (x->x_pattern != x->x_patini)
+ freebytes(x->x_pattern, 2 * x->x_size * sizeof(*x->x_pattern));
+}
+
+static void *match_new(t_symbol *s, int ac, t_atom *av)
+{
+ t_match *x = (t_match *)pd_new(match_class);
+ x->x_size = MATCH_INISIZE * 2;
+ x->x_patlen = 0;
+ x->x_pattern = x->x_patini;
+ x->x_queue = x->x_queini;
+ /* x->x_queend is not used unless x->x_patlen > 0,
+ LATER consider chosing a more defensive way... */
+ outlet_new((t_object *)x, &s_anything);
+ match_clear(x);
+ match_set(x, 0, ac, av);
+ return (x);
+}
+
+void match_setup(void)
+{
+ match_class = class_new(gensym("match"),
+ (t_newmethod)match_new,
+ (t_method)match_free,
+ sizeof(t_match), 0, A_GIMME, 0);
+ class_addfloat(match_class, match_float);
+ class_addsymbol(match_class, match_symbol);
+ class_addlist(match_class, match_list);
+ class_addanything(match_class, match_anything);
+ class_addmethod(match_class, (t_method)match_set,
+ gensym("set"), A_GIMME, 0);
+ class_addmethod(match_class, (t_method)match_clear,
+ gensym("clear"), 0);
+}
diff --git a/cyclone/hammer/maximum.c b/cyclone/hammer/maximum.c
new file mode 100644
index 0000000..038d8f1
--- /dev/null
+++ b/cyclone/hammer/maximum.c
@@ -0,0 +1,88 @@
+/* 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/loud.h"
+
+typedef struct _maximum
+{
+ t_object x_ob;
+ t_float x_last;
+ t_float x_test;
+} t_maximum;
+
+static t_class *maximum_class;
+
+static void maximum_bang(t_maximum *x)
+{
+ outlet_float(((t_object *)x)->ob_outlet, x->x_last);
+}
+
+static void maximum_float(t_maximum *x, t_float f)
+{
+ outlet_float(((t_object *)x)->ob_outlet,
+ x->x_last = (f > x->x_test ? f : x->x_test));
+}
+
+static void maximum_list(t_maximum *x, t_symbol *s, int ac, t_atom *av)
+{
+ if (ac > 256) loud_incompatible_max(*(t_pd *)x, 256, "items");
+ while (ac && av->a_type != A_FLOAT) ac--, av++; /* CHECKME (a warning?) */
+ if (ac)
+ {
+ t_float fpick = av->a_w.w_float;
+ ac--; av++;
+ while (ac && av->a_type != A_FLOAT) ac--, av++; /* CHECKME */
+ if (ac)
+ {
+ t_float fnext, f = av->a_w.w_float;
+ if (f > fpick)
+ {
+ fnext = fpick;
+ fpick = f;
+ }
+ else fnext = f;
+ ac--; av++;
+ while (ac--)
+ {
+ if (av->a_type == A_FLOAT)
+ {
+ f = av->a_w.w_float;
+ if (f > fpick)
+ {
+ fnext = fpick;
+ fpick = f;
+ }
+ else if (f > fnext) fnext = f;
+ }
+ /* CHECKME else */
+ av++;
+ }
+ x->x_test = fnext;
+ outlet_float(((t_object *)x)->ob_outlet, x->x_last = fpick);
+ }
+ else maximum_float(x, fpick); /* CHECKME */
+ }
+ /* CHECKME else */
+}
+
+static void *maximum_new(t_floatarg f)
+{
+ t_maximum *x = (t_maximum *)pd_new(maximum_class);
+ x->x_last = 0; /* CHECKME */
+ x->x_test = f;
+ floatinlet_new((t_object *)x, &x->x_test);
+ outlet_new((t_object *)x, &s_float);
+ return (x);
+}
+
+void maximum_setup(void)
+{
+ maximum_class = class_new(gensym("maximum"),
+ (t_newmethod)maximum_new, 0,
+ sizeof(t_maximum), 0, A_DEFFLOAT, 0);
+ class_addbang(maximum_class, maximum_bang);
+ class_addfloat(maximum_class, maximum_float);
+ class_addlist(maximum_class, maximum_list);
+}
diff --git a/cyclone/hammer/mean.c b/cyclone/hammer/mean.c
new file mode 100644
index 0000000..13d69ff
--- /dev/null
+++ b/cyclone/hammer/mean.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 "m_pd.h"
+
+typedef struct _mean
+{
+ t_object x_ob;
+ double x_accum;
+ unsigned x_count;
+ t_float x_mean;
+ t_outlet *x_countout;
+} t_mean;
+
+static t_class *mean_class;
+
+static void mean_clear(t_mean *x)
+{
+ x->x_accum = 0;
+ x->x_count = 0;
+ x->x_mean = 0;
+}
+
+static void mean_bang(t_mean *x)
+{
+ /* CHECKED: count is always sent (first) */
+ outlet_float(x->x_countout, x->x_count);
+ outlet_float(((t_object *)x)->ob_outlet, x->x_mean);
+}
+
+static void mean_float(t_mean *x, t_float f)
+{
+ x->x_accum += f;
+ if (++x->x_count)
+ x->x_mean = (t_float)(x->x_accum / (double)x->x_count);
+ else mean_clear(x);
+ mean_bang(x);
+}
+
+static void mean_list(t_mean *x, t_symbol *s, int ac, t_atom *av)
+{
+ mean_clear(x);
+ while (ac--)
+ {
+ if (av->a_type == A_FLOAT)
+ {
+ x->x_accum += av->a_w.w_float;
+ x->x_count++;
+ }
+ av++;
+ }
+ if (x->x_count)
+ x->x_mean = (t_float)(x->x_accum / (double)x->x_count);
+ else mean_clear(x);
+ mean_bang(x);
+ /* CHECKED: no clear after list -- subsequent floats are added */
+}
+
+static void *mean_new(void)
+{
+ t_mean *x = (t_mean *)pd_new(mean_class);
+ mean_clear(x);
+ outlet_new((t_object *)x, &s_float);
+ x->x_countout = outlet_new((t_object *)x, &s_float);
+ return (x);
+}
+
+void mean_setup(void)
+{
+ mean_class = class_new(gensym("mean"),
+ (t_newmethod)mean_new, 0,
+ sizeof(t_mean), 0, 0);
+ class_addbang(mean_class, mean_bang);
+ class_addfloat(mean_class, mean_float);
+ class_addlist(mean_class, mean_list);
+ class_addmethod(mean_class, (t_method)mean_clear,
+ gensym("clear"), 0);
+}
diff --git a/cyclone/hammer/midiflush.c b/cyclone/hammer/midiflush.c
new file mode 100644
index 0000000..592d9e0
--- /dev/null
+++ b/cyclone/hammer/midiflush.c
@@ -0,0 +1,102 @@
+/* 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"
+
+#define MIDIFLUSH_NCHANNELS 16
+#define MIDIFLUSH_NPITCHES 128
+#define MIDIFLUSH_VOIDPITCH 0xFF
+
+typedef struct _midiflush
+{
+ t_object x_ob;
+ unsigned char x_status;
+ unsigned char x_channel;
+ unsigned char x_pitch;
+ unsigned char x_notes[MIDIFLUSH_NCHANNELS][MIDIFLUSH_NPITCHES];
+} t_midiflush;
+
+static t_class *midiflush_class;
+
+static void midiflush_float(t_midiflush *x, t_float f)
+{
+ int ival = (int)f;
+ if (ival >= 0 && ival < 256)
+ {
+ unsigned char bval = ival;
+ outlet_float(((t_object *)x)->ob_outlet, bval);
+ if (bval & 0x80)
+ {
+ x->x_status = bval & 0xF0;
+ if (x->x_status == 0x80 || x->x_status == 0x90)
+ x->x_channel = bval & 0x0F;
+ else
+ x->x_status = 0;
+ }
+ else if (x->x_status)
+ {
+ if (x->x_pitch == MIDIFLUSH_VOIDPITCH)
+ {
+ x->x_pitch = bval;
+ return;
+ }
+ else if (x->x_status == 0x90 && bval)
+ {
+ x->x_notes[x->x_channel][x->x_pitch]++;
+ }
+ else
+ {
+ x->x_notes[x->x_channel][x->x_pitch]--;
+ }
+ }
+ }
+ x->x_pitch = MIDIFLUSH_VOIDPITCH;
+}
+
+static void midiflush_bang(t_midiflush *x)
+{
+ int chn, pch;
+ for (chn = 0; chn < MIDIFLUSH_NCHANNELS; chn++)
+ {
+ for (pch = 0; pch < MIDIFLUSH_NPITCHES; pch++)
+ {
+ int status = 0x090 | chn;
+ while (x->x_notes[chn][pch])
+ {
+ outlet_float(((t_object *)x)->ob_outlet, status);
+ outlet_float(((t_object *)x)->ob_outlet, pch);
+ outlet_float(((t_object *)x)->ob_outlet, 0);
+ x->x_notes[chn][pch]--;
+ }
+ }
+ }
+}
+
+static void midiflush_clear(t_midiflush *x)
+{
+ memset(x->x_notes, 0, sizeof(x->x_notes));
+}
+
+static void *midiflush_new(void)
+{
+ t_midiflush *x = (t_midiflush *)pd_new(midiflush_class);
+ x->x_status = 0; /* `not a note' */
+ x->x_pitch = MIDIFLUSH_VOIDPITCH;
+ midiflush_clear(x);
+ outlet_new((t_object *)x, &s_float);
+ return (x);
+}
+
+void midiflush_setup(void)
+{
+ midiflush_class = class_new(gensym("midiflush"),
+ (t_newmethod)midiflush_new,
+ 0, /* CHECKED: no flushout */
+ sizeof(t_midiflush), 0, 0);
+ class_addfloat(midiflush_class, midiflush_float);
+ class_addbang(midiflush_class, midiflush_bang);
+ class_addmethod(midiflush_class, (t_method)midiflush_clear,
+ gensym("clear"), 0);
+}
diff --git a/cyclone/hammer/midiformat.c b/cyclone/hammer/midiformat.c
new file mode 100644
index 0000000..fa0612b
--- /dev/null
+++ b/cyclone/hammer/midiformat.c
@@ -0,0 +1,112 @@
+/* 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"
+
+typedef struct _midiformat
+{
+ t_object x_ob;
+ t_float x_channel;
+} t_midiformat;
+
+static t_class *midiformat_class;
+
+static int midiformat_channel(t_midiformat *x)
+{
+ int ch = (int)x->x_channel;
+ return (ch > 0 ? (ch - 1) & 0x0F : 0);
+}
+
+static void midiformat_note(t_midiformat *x, t_symbol *s, int ac, t_atom *av)
+{
+ if (ac >= 2 && av[0].a_type == A_FLOAT && av[1].a_type == A_FLOAT)
+ {
+ int pitch = (int)av[0].a_w.w_float; /* CHECKED: anything goes */
+ int velocity = (int)av[1].a_w.w_float;
+ outlet_float(((t_object *)x)->ob_outlet, 0x90 | midiformat_channel(x));
+ outlet_float(((t_object *)x)->ob_outlet, pitch);
+ outlet_float(((t_object *)x)->ob_outlet, velocity);
+ }
+}
+
+static void midiformat_polytouch(t_midiformat *x,
+ t_symbol *s, int ac, t_atom *av)
+{
+ if (ac >= 2 && av[0].a_type == A_FLOAT && av[1].a_type == A_FLOAT)
+ {
+ int touch = (int)av[0].a_w.w_float;
+ int key = (int)av[1].a_w.w_float;
+ outlet_float(((t_object *)x)->ob_outlet, 0xA0 | midiformat_channel(x));
+ outlet_float(((t_object *)x)->ob_outlet, key);
+ outlet_float(((t_object *)x)->ob_outlet, touch);
+ }
+}
+
+static void midiformat_controller(t_midiformat *x,
+ t_symbol *s, int ac, t_atom *av)
+{
+ if (ac >= 2 && av[0].a_type == A_FLOAT && av[1].a_type == A_FLOAT)
+ {
+ int val = (int)av[0].a_w.w_float;
+ int ctl = (int)av[1].a_w.w_float;
+ outlet_float(((t_object *)x)->ob_outlet, 0xB0 | midiformat_channel(x));
+ outlet_float(((t_object *)x)->ob_outlet, ctl);
+ outlet_float(((t_object *)x)->ob_outlet, val);
+ }
+}
+
+static void midiformat_program(t_midiformat *x, t_floatarg f)
+{
+ int pgm = (int)f;
+ outlet_float(((t_object *)x)->ob_outlet, 0xC0 | midiformat_channel(x));
+ outlet_float(((t_object *)x)->ob_outlet, pgm);
+}
+
+static void midiformat_touch(t_midiformat *x, t_floatarg f)
+{
+ int touch = (int)f;
+ outlet_float(((t_object *)x)->ob_outlet, 0xD0 | midiformat_channel(x));
+ outlet_float(((t_object *)x)->ob_outlet, touch);
+}
+
+static void midiformat_bend(t_midiformat *x, t_floatarg f)
+{
+ int val = (int)f;
+ outlet_float(((t_object *)x)->ob_outlet, 0xE0 | midiformat_channel(x));
+ outlet_float(((t_object *)x)->ob_outlet, 0);
+ outlet_float(((t_object *)x)->ob_outlet, val);
+}
+
+static void *midiformat_new(t_floatarg f)
+{
+ t_midiformat *x = (t_midiformat *)pd_new(midiformat_class);
+ x->x_channel = f;
+ inlet_new((t_object *)x, (t_pd *)x, &s_list, gensym("lst1"));
+ inlet_new((t_object *)x, (t_pd *)x, &s_list, gensym("lst2"));
+ inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft3"));
+ inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft4"));
+ inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft5"));
+ floatinlet_new((t_object *)x, &x->x_channel);
+ outlet_new((t_object *)x, &s_float);
+ return (x);
+}
+
+void midiformat_setup(void)
+{
+ midiformat_class = class_new(gensym("midiformat"),
+ (t_newmethod)midiformat_new, 0,
+ sizeof(t_midiformat), 0,
+ A_DEFFLOAT, 0);
+ class_addlist(midiformat_class, midiformat_note);
+ class_addmethod(midiformat_class, (t_method)midiformat_polytouch,
+ gensym("lst1"), A_GIMME, 0);
+ class_addmethod(midiformat_class, (t_method)midiformat_controller,
+ gensym("lst2"), A_GIMME, 0);
+ class_addmethod(midiformat_class, (t_method)midiformat_program,
+ gensym("ft3"), A_FLOAT, 0);
+ class_addmethod(midiformat_class, (t_method)midiformat_touch,
+ gensym("ft4"), A_FLOAT, 0);
+ class_addmethod(midiformat_class, (t_method)midiformat_bend,
+ gensym("ft5"), A_FLOAT, 0);
+}
diff --git a/cyclone/hammer/midiparse.c b/cyclone/hammer/midiparse.c
new file mode 100644
index 0000000..9a79a39
--- /dev/null
+++ b/cyclone/hammer/midiparse.c
@@ -0,0 +1,132 @@
+/* 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"
+
+typedef struct _midiparse
+{
+ t_object x_ob;
+ unsigned char x_ready;
+ unsigned char x_status;
+ unsigned char x_channel;
+ unsigned char x_data1;
+ t_outlet *x_polyout;
+ t_outlet *x_ctlout;
+ t_outlet *x_pgmout;
+ t_outlet *x_touchout;
+ t_outlet *x_bendout;
+ t_outlet *x_chanout;
+} t_midiparse;
+
+static t_class *midiparse_class;
+
+static void midiparse_clear(t_midiparse *x)
+{
+ x->x_status = 0;
+ x->x_ready = 0;
+}
+
+static void midiparse_float(t_midiparse *x, t_float f)
+{
+ int ival = (int)f; /* CHECKED */
+ if (ival < 0)
+ {
+ /* CHECKME */
+ return;
+ }
+ if (ival < 256) /* CHECKED clear if input over 255 */
+ {
+ unsigned char bval = ival;
+ if (bval & 0x80)
+ {
+ unsigned char status = bval & 0xF0;
+ if (status == 0xF0)
+ {
+ /* CHECKED no such test in max -- this is incompatible,
+ but real-time messages are out-of-band, and they
+ should be ignored here. LATER rethink the 0xFE case. */
+ if (bval < 0xF8)
+ midiparse_clear(x);
+ }
+ else
+ {
+ x->x_status = status;
+ x->x_channel = bval & 0x0F;
+ x->x_ready = (status == 0xC0 || status == 0xD0);
+ }
+ }
+ else if (x->x_ready)
+ {
+ t_atom at[2];
+ x->x_ready = 0;
+ outlet_float(x->x_chanout, x->x_channel + 1);
+ switch (x->x_status)
+ {
+ case 0x80:
+ SETFLOAT(&at[0], x->x_data1);
+ SETFLOAT(&at[1], 0);
+ outlet_list(((t_object *)x)->ob_outlet, 0, 2, at);
+ break;
+ case 0x90:
+ SETFLOAT(&at[0], x->x_data1);
+ SETFLOAT(&at[1], bval);
+ outlet_list(((t_object *)x)->ob_outlet, 0, 2, at);
+ break;
+ case 0xA0:
+ SETFLOAT(&at[0], bval);
+ SETFLOAT(&at[1], x->x_data1);
+ outlet_list(x->x_polyout, 0, 2, at);
+ break;
+ case 0xB0:
+ SETFLOAT(&at[0], bval);
+ SETFLOAT(&at[1], x->x_data1);
+ outlet_list(x->x_ctlout, 0, 2, at);
+ break;
+ case 0xC0:
+ outlet_float(x->x_pgmout, bval);
+ x->x_ready = 1;
+ break;
+ case 0xD0:
+ outlet_float(x->x_touchout, bval);
+ x->x_ready = 1;
+ break;
+ case 0xE0:
+ /* CHECKED: ignores data1 */
+ outlet_float(x->x_bendout, bval);
+ break;
+ default:;
+ }
+ }
+ else if (x->x_status)
+ {
+ x->x_data1 = bval; /* CHECKED key #0 accepted */
+ x->x_ready = 1;
+ }
+ }
+ else midiparse_clear(x);
+}
+
+static void *midiparse_new(void)
+{
+ t_midiparse *x = (t_midiparse *)pd_new(midiparse_class);
+ outlet_new((t_object *)x, &s_list);
+ x->x_polyout = outlet_new((t_object *)x, &s_list);
+ x->x_ctlout = outlet_new((t_object *)x, &s_list);
+ x->x_pgmout = outlet_new((t_object *)x, &s_float);
+ x->x_touchout = outlet_new((t_object *)x, &s_float);
+ x->x_bendout = outlet_new((t_object *)x, &s_float);
+ x->x_chanout = outlet_new((t_object *)x, &s_float);
+ midiparse_clear(x);
+ return (x);
+}
+
+void midiparse_setup(void)
+{
+ midiparse_class = class_new(gensym("midiparse"),
+ (t_newmethod)midiparse_new, 0,
+ sizeof(t_midiparse), 0, 0);
+ class_addbang(midiparse_class, midiparse_clear);
+ class_addfloat(midiparse_class, midiparse_float);
+ /* CHECKED autocasting lists to floats */
+}
diff --git a/cyclone/hammer/minimum.c b/cyclone/hammer/minimum.c
new file mode 100644
index 0000000..466b6f8
--- /dev/null
+++ b/cyclone/hammer/minimum.c
@@ -0,0 +1,88 @@
+/* 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/loud.h"
+
+typedef struct _minimum
+{
+ t_object x_ob;
+ t_float x_last;
+ t_float x_test;
+} t_minimum;
+
+static t_class *minimum_class;
+
+static void minimum_bang(t_minimum *x)
+{
+ outlet_float(((t_object *)x)->ob_outlet, x->x_last);
+}
+
+static void minimum_float(t_minimum *x, t_float f)
+{
+ outlet_float(((t_object *)x)->ob_outlet,
+ x->x_last = (f < x->x_test ? f : x->x_test));
+}
+
+static void minimum_list(t_minimum *x, t_symbol *s, int ac, t_atom *av)
+{
+ if (ac > 256) loud_incompatible_max(*(t_pd *)x, 256, "items");
+ while (ac && av->a_type != A_FLOAT) ac--, av++; /* CHECKME (a warning?) */
+ if (ac)
+ {
+ t_float fpick = av->a_w.w_float;
+ ac--; av++;
+ while (ac && av->a_type != A_FLOAT) ac--, av++; /* CHECKME */
+ if (ac)
+ {
+ t_float fnext, f = av->a_w.w_float;
+ if (f < fpick)
+ {
+ fnext = fpick;
+ fpick = f;
+ }
+ else fnext = f;
+ ac--; av++;
+ while (ac--)
+ {
+ if (av->a_type == A_FLOAT)
+ {
+ f = av->a_w.w_float;
+ if (f < fpick)
+ {
+ fnext = fpick;
+ fpick = f;
+ }
+ else if (f < fnext) fnext = f;
+ }
+ /* CHECKME else */
+ av++;
+ }
+ x->x_test = fnext;
+ outlet_float(((t_object *)x)->ob_outlet, x->x_last = fpick);
+ }
+ else minimum_float(x, fpick); /* CHECKME */
+ }
+ /* CHECKME else */
+}
+
+static void *minimum_new(t_floatarg f)
+{
+ t_minimum *x = (t_minimum *)pd_new(minimum_class);
+ x->x_last = 0; /* CHECKME */
+ x->x_test = f;
+ floatinlet_new((t_object *)x, &x->x_test);
+ outlet_new((t_object *)x, &s_float);
+ return (x);
+}
+
+void minimum_setup(void)
+{
+ minimum_class = class_new(gensym("minimum"),
+ (t_newmethod)minimum_new, 0,
+ sizeof(t_minimum), 0, A_DEFFLOAT, 0);
+ class_addbang(minimum_class, minimum_bang);
+ class_addfloat(minimum_class, minimum_float);
+ class_addlist(minimum_class, minimum_list);
+}
diff --git a/cyclone/hammer/mousefilter.c b/cyclone/hammer/mousefilter.c
new file mode 100644
index 0000000..e2e3cc5
--- /dev/null
+++ b/cyclone/hammer/mousefilter.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 "hammer/gui.h"
+
+typedef struct _mousefilter
+{
+ t_object x_ob;
+ int x_isup;
+ int x_ispending;
+ t_float x_value;
+} t_mousefilter;
+
+static t_class *mousefilter_class;
+
+static void mousefilter_float(t_mousefilter *x, t_float f)
+{
+ if (x->x_isup)
+ outlet_float(((t_object *)x)->ob_outlet, f);
+ else
+ {
+ x->x_ispending = 1;
+ x->x_value = f;
+ }
+}
+
+static void mousefilter_anything(t_mousefilter *x,
+ t_symbol *s, int ac, t_atom *av)
+{
+ /* dummy method, filtering out those messages from gui,
+ which are not handled explicitly */
+}
+
+static void mousefilter_doup(t_mousefilter *x, t_floatarg f)
+{
+ if ((x->x_isup = (int)f) && x->x_ispending)
+ {
+ x->x_ispending = 0;
+ outlet_float(((t_object *)x)->ob_outlet, x->x_value);
+ }
+}
+
+static void mousefilter_free(t_mousefilter *x)
+{
+ hammergui_unbindmouse((t_pd *)x);
+}
+
+static void *mousefilter_new(void)
+{
+ t_mousefilter *x = (t_mousefilter *)pd_new(mousefilter_class);
+ x->x_isup = 0; /* LATER rethink */
+ x->x_ispending = 0;
+ outlet_new((t_object *)x, &s_float);
+ hammergui_bindmouse((t_pd *)x);
+ return (x);
+}
+
+void mousefilter_setup(void)
+{
+ mousefilter_class = class_new(gensym("mousefilter"),
+ (t_newmethod)mousefilter_new,
+ (t_method)mousefilter_free,
+ sizeof(t_mousefilter), 0, 0);
+ class_addfloat(mousefilter_class, mousefilter_float);
+ class_addanything(mousefilter_class, mousefilter_anything);
+ class_addmethod(mousefilter_class, (t_method)mousefilter_doup,
+ gensym("_up"), A_FLOAT, 0);
+}
diff --git a/cyclone/hammer/next.c b/cyclone/hammer/next.c
new file mode 100644
index 0000000..3fe7d6e
--- /dev/null
+++ b/cyclone/hammer/next.c
@@ -0,0 +1,58 @@
+/* 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"
+
+//#define NEXT_USEEVENTNO
+
+typedef struct _next
+{
+ t_object x_ob;
+#ifdef NEXT_USEEVENTNO
+ int x_lastevent;
+#else
+ double x_lastevent;
+#endif
+ t_outlet *x_out2;
+} t_next;
+
+static t_class *next_class;
+
+/* CHECKME first call, CHECKME if the outlets are not swapped */
+static void next_anything(t_next *x, t_symbol *s, int ac, t_atom *av)
+{
+#ifdef NEXT_USEEVENTNO
+ int nextevent = sys_geteventno();
+#else
+ double nextevent = clock_getlogicaltime();
+#endif
+ if (x->x_lastevent == nextevent)
+ outlet_bang(x->x_out2);
+ else
+ {
+ x->x_lastevent = nextevent;
+ outlet_bang(((t_object *)x)->ob_outlet);
+ }
+}
+
+static void *next_new(void)
+{
+ t_next *x = (t_next *)pd_new(next_class);
+ outlet_new((t_object *)x, &s_bang);
+ x->x_out2 = outlet_new((t_object *)x, &s_bang);
+#ifdef NEXT_USEEVENTNO
+ x->x_lastevent = sys_geteventno();
+#else
+ x->x_lastevent = clock_getlogicaltime();
+#endif
+ return (x);
+}
+
+void next_setup(void)
+{
+ next_class = class_new(gensym("next"),
+ (t_newmethod)next_new, 0,
+ sizeof(t_next), 0, 0);
+ class_addanything(next_class, next_anything);
+}
diff --git a/cyclone/hammer/offer.c b/cyclone/hammer/offer.c
new file mode 100644
index 0000000..3823c85
--- /dev/null
+++ b/cyclone/hammer/offer.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. */
+
+#include "m_pd.h"
+#include "common/loud.h"
+#include "hammer/tree.h"
+
+/* As a class `derived' from the common hammertree code (also in funbuff),
+ offer uses the auxiliary list, generally not needed here.
+ As a side-effect, it gets a bonus of a small speedup of deletion,
+ and a penalty of a small slowdown of insertion. */
+
+typedef struct _offer
+{
+ t_object x_ob;
+ t_float x_value;
+ int x_valueset;
+ t_hammertree x_tree;
+} t_offer;
+
+static t_class *offer_class;
+
+static void offer_float(t_offer *x, t_float f)
+{
+ int ndx;
+ if (loud_checkint((t_pd *)x, f, &ndx, &s_float)) /* CHECKED */
+ {
+ t_hammernode *np;
+ if (x->x_valueset)
+ {
+ if (np = hammertree_insert(&x->x_tree, ndx))
+ np->n_value = x->x_value;
+ x->x_valueset = 0;
+ }
+ else if (np = hammertree_search(&x->x_tree, ndx))
+ {
+ outlet_float(((t_object *)x)->ob_outlet, np->n_value);
+ hammertree_delete(&x->x_tree, np);
+ }
+ }
+}
+
+static void offer_ft1(t_offer *x, t_floatarg f)
+{
+ /* this is incompatible -- CHECKED float is silently truncated */
+ x->x_value = f;
+ x->x_valueset = 1;
+}
+
+static void offer_clear(t_offer *x)
+{
+ hammertree_clear(&x->x_tree, 0);
+ /* CHECKED valueset is not cleared */
+}
+
+#ifdef HAMMERTREE_DEBUG
+static void offer_debug(t_offer *x, t_floatarg f)
+{
+ hammertree_debug(&x->x_tree, (int)f);
+}
+#endif
+
+static void offer_free(t_offer *x)
+{
+ hammertree_clear(&x->x_tree, 0);
+}
+
+static void *offer_new(void)
+{
+ t_offer *x = (t_offer *)pd_new(offer_class);
+ x->x_valueset = 0;
+ hammertree_init(&x->x_tree, 0);
+ inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft1"));
+ outlet_new((t_object *)x, &s_float);
+ return (x);
+}
+
+void offer_setup(void)
+{
+ offer_class = class_new(gensym("offer"),
+ (t_newmethod)offer_new,
+ (t_method)offer_free,
+ sizeof(t_offer), 0, 0);
+ class_addfloat(offer_class, offer_float);
+ class_addmethod(offer_class, (t_method)offer_ft1,
+ gensym("ft1"), A_FLOAT, 0);
+ class_addmethod(offer_class, (t_method)offer_clear,
+ gensym("clear"), 0);
+#ifdef HAMMERTREE_DEBUG
+ class_addmethod(offer_class, (t_method)offer_debug,
+ gensym("debug"), A_DEFFLOAT, 0);
+#endif
+}
diff --git a/cyclone/hammer/onebang.c b/cyclone/hammer/onebang.c
new file mode 100644
index 0000000..a4132dc
--- /dev/null
+++ b/cyclone/hammer/onebang.c
@@ -0,0 +1,46 @@
+/* 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"
+
+typedef struct _onebang
+{
+ t_object x_ob;
+ int x_isopen;
+} t_onebang;
+
+static t_class *onebang_class;
+
+static void onebang_bang(t_onebang *x)
+{
+ if (x->x_isopen)
+ {
+ outlet_bang(((t_object *)x)->ob_outlet);
+ x->x_isopen = 0;
+ }
+}
+
+static void onebang_bang1(t_onebang *x)
+{
+ x->x_isopen = 1;
+}
+
+static void *onebang_new(t_floatarg f)
+{
+ t_onebang *x = (t_onebang *)pd_new(onebang_class);
+ x->x_isopen = ((int)f != 0); /* CHECKED */
+ inlet_new((t_object *)x, (t_pd *)x, &s_bang, gensym("bang1"));
+ outlet_new((t_object *)x, &s_bang);
+ return (x);
+}
+
+void onebang_setup(void)
+{
+ onebang_class = class_new(gensym("onebang"),
+ (t_newmethod)onebang_new, 0,
+ sizeof(t_onebang), 0, A_DEFFLOAT, 0);
+ class_addbang(onebang_class, onebang_bang);
+ class_addmethod(onebang_class, (t_method)onebang_bang1,
+ gensym("bang1"), 0);
+}
diff --git a/cyclone/hammer/past.c b/cyclone/hammer/past.c
new file mode 100644
index 0000000..eb29c8e
--- /dev/null
+++ b/cyclone/hammer/past.c
@@ -0,0 +1,154 @@
+/* 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:
+ bang for a float at > (refman error: >=)
+ bang for a list if all >= (refman page says the same)
+ bang for a list if any is >, even if the rest (but not previous) is <
+ well...
+*/
+
+#include "m_pd.h"
+#include "common/loud.h"
+#include "common/grow.h"
+
+#define PAST_MAXSIZE 8 /* CHECKED */
+
+typedef struct past
+{
+ t_object x_ob;
+ int x_low;
+ int x_size; /* as allocated */
+ int x_nthresh; /* as used */
+ t_atom *x_thresh;
+ t_atom x_thrini[PAST_MAXSIZE];
+} t_past;
+
+static t_class *past_class;
+
+static int past_compare(t_past *x, t_float f, t_atom *ap)
+{
+ if (ap->a_type == A_FLOAT)
+ {
+ if (f > ap->a_w.w_float)
+ return (1);
+ else if (f == ap->a_w.w_float)
+ return (0);
+ else
+ return (-1);
+ }
+ else /* CHECKED */
+ {
+ if (f > 0.)
+ return (1);
+ else if (f == 0.)
+ return (0);
+ else
+ return (-1);
+ }
+}
+
+static void past_float(t_past *x, t_float f)
+{
+ if (x->x_nthresh == 1)
+ {
+ if (past_compare(x, f, x->x_thresh) > 0) /* CHECKED: equal is low */
+ {
+ if (x->x_low)
+ {
+ x->x_low = 0;
+ outlet_bang(((t_object *)x)->ob_outlet);
+ }
+ }
+ else x->x_low = 1;
+ }
+ else if (past_compare(x, f, x->x_thresh) < 0) x->x_low = 1;
+}
+
+/* CHECKME: x_low handling */
+static void past_list(t_past *x, t_symbol *s, int ac, t_atom *av)
+{
+ if (ac && ac <= x->x_nthresh)
+ {
+ int result;
+ t_atom *vp = x->x_thresh;
+ if (av->a_type == A_FLOAT
+ && (result = past_compare(x, av->a_w.w_float, vp)) >= 0)
+ {
+ if (!result)
+ {
+ for (ac--, av++, vp++; ac; ac--, av++, vp++)
+ {
+ if (av->a_type != A_FLOAT
+ || (result =
+ past_compare(x, av->a_w.w_float, vp++)) < 0)
+ {
+ x->x_low = 1;
+ return;
+ }
+ if (result) break;
+ }
+ }
+ if (x->x_low)
+ {
+ x->x_low = 0;
+ outlet_bang(((t_object *)x)->ob_outlet);
+ }
+ }
+ else x->x_low = 1;
+ }
+}
+
+static void past_clear(t_past *x)
+{
+ x->x_low = 1;
+}
+
+static void past_set(t_past *x, t_symbol *s, int ac, t_atom *av)
+{
+ if (ac)
+ {
+ t_atom *vp = x->x_thresh;
+ if (ac > x->x_size)
+ {
+ loud_incompatible_max(past_class, PAST_MAXSIZE, "guard points");
+ x->x_thresh = grow_nodata(&ac, &x->x_size, x->x_thresh,
+ PAST_MAXSIZE, x->x_thrini,
+ sizeof(*x->x_thresh));
+ }
+ x->x_nthresh = ac;
+ while (ac--) *vp++ = *av++;
+ /* CHECKED: x_low is not set here */
+ }
+}
+
+static void past_free(t_past *x)
+{
+ if (x->x_thresh != x->x_thrini)
+ freebytes(x->x_thresh, x->x_size * sizeof(*x->x_thresh));
+}
+
+static void *past_new(t_symbol *s, int ac, t_atom *av)
+{
+ t_past *x = (t_past *)pd_new(past_class);
+ x->x_low = 1;
+ x->x_nthresh = 0;
+ x->x_size = PAST_MAXSIZE;
+ x->x_thresh = x->x_thrini;
+ outlet_new((t_object *)x, &s_bang);
+ past_set(x, 0, ac, av);
+ return (x);
+}
+
+void past_setup(void)
+{
+ past_class = class_new(gensym("past"),
+ (t_newmethod)past_new,
+ (t_method)past_free,
+ sizeof(t_past), 0, A_GIMME, 0);
+ class_addfloat(past_class, past_float);
+ class_addlist(past_class, past_list);
+ class_addmethod(past_class, (t_method)past_clear, gensym("clear"), 0);
+ class_addmethod(past_class, (t_method)past_set, gensym("set"), A_GIMME, 0);
+}
diff --git a/cyclone/hammer/pd-lib-notes.txt b/cyclone/hammer/pd-lib-notes.txt
new file mode 100644
index 0000000..8b45005
--- /dev/null
+++ b/cyclone/hammer/pd-lib-notes.txt
@@ -0,0 +1,61 @@
+modifications to Joseph A. Sarlo's code (formerly part of `pd-lib')
+-------------------------------------------------------------------
+
+LATER: more testing, max-checking, resolving reentrancy, gc, etc.
+
+accum: only cosmetics
+
+bangbang:
+- if argument > 2 the array is dynamically allocated
+- if argument > 40 (max in max), a warning is printed
+- accepts any message
+
+Bucket:
+- arrays are dynamically allocated, no upper limit (max has no limit too)
+- outlets output in right-to-left order
+- added: 'set' method, 'l2r' and 'r2l' aliases
+
+buddy: coded from scratch
+- using array of proxy objects (accepting any message)
+- no upper limit for number of slots
+
+capture: coded from scratch
+- text editor, savepanel
+- any size
+- circular buffering
+
+counter (rewritten entirely):
+- using proxies to handle bangs and floats in other inlets than first
+- new `engine', counter_dobang(), coded from scratch
+- various adjustments of things that turned out to work differently in max,
+ too many to list here (and probably more are required -- please let me know!)
+
+cycle:
+- the array of outlets is dynamically allocated
+- fixing cycle_list()'s bugs
+- accepting (and sending) both floats and symbols, accepting anything
+- 'thresh' and 'set' methods
+- event-sensitive mode emulation (a temporary hack)
+
+Decode (rewritten entirely):
+- if argument > 8 the array is dynamically allocated (with a warning)
+- all outlets deliver after any action
+- outlets output in right-to-left order
+- while in all-off mode, input is stored, not ignored
+- out-of-range input is clipped, not ignored
+
+Histo (rewritten entirely):
+- creation argument added (size)
+- the array is dynamically allocated, no upper limit (max has no limit too)
+- check if input is in range, to prevent crashes :)
+- 'bang' method
+
+iter:
+- different method of memory allocation
+- dripping both floats and symbols (max4 feature)
+- 'anything' method
+
+match: coded from scratch
+- matching stream of both floats and symbols (max4 feature)
+- scanning all kinds of messages, not only separate floats
+- recognizing overlapping patterns
diff --git a/cyclone/hammer/poltocar.c b/cyclone/hammer/poltocar.c
new file mode 100644
index 0000000..486eead
--- /dev/null
+++ b/cyclone/hammer/poltocar.c
@@ -0,0 +1,44 @@
+/* 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"
+
+#if defined(NT) || defined(MACOSX)
+/* cf pd/src/x_arithmetic.c */
+#define sinf sin
+#define cosf cos
+#endif
+
+typedef struct _poltocar
+{
+ t_object x_ob;
+ t_float x_phase;
+ t_outlet *x_out2;
+} t_poltocar;
+
+static t_class *poltocar_class;
+
+static void poltocar_float(t_poltocar *x, t_float f)
+{
+ outlet_float(x->x_out2, f * sinf(x->x_phase));
+ outlet_float(((t_object *)x)->ob_outlet, f * cosf(x->x_phase));
+}
+
+static void *poltocar_new(void)
+{
+ t_poltocar *x = (t_poltocar *)pd_new(poltocar_class);
+ floatinlet_new((t_object *)x, &x->x_phase);
+ outlet_new((t_object *)x, &s_float);
+ x->x_out2 = outlet_new((t_object *)x, &s_float);
+ return (x);
+}
+
+void poltocar_setup(void)
+{
+ poltocar_class = class_new(gensym("poltocar"),
+ (t_newmethod)poltocar_new, 0,
+ sizeof(t_poltocar), 0, 0);
+ class_addfloat(poltocar_class, poltocar_float);
+}
diff --git a/cyclone/hammer/prepend.c b/cyclone/hammer/prepend.c
new file mode 100644
index 0000000..567bb73
--- /dev/null
+++ b/cyclone/hammer/prepend.c
@@ -0,0 +1,258 @@
+/* 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/loud.h"
+#include "common/grow.h"
+
+#define PREPEND_INISIZE 32 /* LATER rethink */
+#define PREPEND_MAXSIZE 256
+
+typedef struct _prepend
+{
+ t_object x_ob;
+ t_symbol *x_selector;
+ int x_size; /* as allocated */
+ int x_natoms; /* as used */
+ t_atom *x_message;
+ t_atom x_messini[PREPEND_INISIZE];
+ int x_entered;
+ int x_auxsize;
+ t_atom *x_auxbuf;
+} t_prepend;
+
+static t_class *prepend_class;
+
+/* Usually a preallocation method is used, except in special cases of:
+ 1) reentrant output request, or 2) an output request which would cause
+ resizing to more than MAXSIZE (no such limit for a 'set' message).
+ In both special cases, a temporary output buffer is allocated.
+ A separately preallocated output buffer is not used, thus avoiding
+ memcpying of the stored message (a small performance gain when the
+ preallocation method is chosen). Instead, self-invoked 'set'
+ messages are postponed, using an auxiliary buffer.
+*/
+
+static void prepend_dooutput(t_prepend *x, t_symbol *s, int ac, t_atom *av)
+{
+ if (s == &s_float)
+ {
+ if (ac > 1)
+ outlet_list(((t_object *)x)->ob_outlet, &s_list, ac, av);
+ else
+ outlet_float(((t_object *)x)->ob_outlet, av->a_w.w_float);
+ }
+ else if (s == &s_list)
+ outlet_list(((t_object *)x)->ob_outlet, &s_list, ac, av);
+ else if (s)
+ /* CHECKED: 'bang' is prepended -- we cannot do so...
+ ('symbol' cannot be compatible too) */
+ {
+ outlet_anything(((t_object *)x)->ob_outlet, s, ac, av);
+ }
+}
+
+static void prepend_anything(t_prepend *x, t_symbol *s, int ac, t_atom *av)
+{
+ int reentered = x->x_entered;
+ int prealloc = !reentered;
+ int ntotal = x->x_natoms + ac;
+ t_atom *buf;
+ x->x_entered = 1;
+ if (s == &s_) s = 0;
+ if (s)
+ ntotal++;
+ if (prealloc && ntotal > x->x_size)
+ {
+ if (ntotal > PREPEND_MAXSIZE)
+ prealloc = 0;
+ else
+ {
+ int nrequested = ntotal;
+ x->x_message = grow_withdata(&nrequested, &x->x_natoms,
+ &x->x_size, x->x_message,
+ PREPEND_INISIZE, x->x_messini,
+ sizeof(*x->x_message));
+ prealloc = (nrequested == ntotal);
+ }
+ }
+ if (prealloc)
+ {
+ buf = x->x_message + x->x_natoms;
+ if (s)
+ {
+ SETSYMBOL(buf, s);
+ buf++;
+ }
+ if (ac)
+ memcpy(buf, av, ac * sizeof(*buf));
+ prepend_dooutput(x, x->x_selector, ntotal, x->x_message);
+ }
+ else
+ {
+ /* LATER consider using the stack if ntotal <= MAXSTACK */
+ if (buf = getbytes(ntotal * sizeof(*buf)))
+ {
+ t_atom *bp = buf + x->x_natoms;
+ if (x->x_natoms)
+ memcpy(buf, x->x_message, x->x_natoms * sizeof(*buf));
+ if (s)
+ {
+ SETSYMBOL(bp, s);
+ bp++;
+ }
+ if (ac)
+ memcpy(bp, av, ac * sizeof(*bp));
+ prepend_dooutput(x, x->x_selector, ntotal, buf);
+ freebytes(buf, ntotal * sizeof(*buf));
+ }
+ }
+ if (!reentered)
+ {
+ x->x_entered = 0;
+ if (x->x_auxbuf)
+ {
+ if (x->x_auxsize <= x->x_size)
+ {
+ x->x_natoms = x->x_auxsize / 2;
+ memcpy(x->x_message, x->x_auxbuf,
+ x->x_natoms * sizeof(*x->x_message));
+ freebytes(x->x_auxbuf, x->x_auxsize * sizeof(*x->x_auxbuf));
+ }
+ else
+ {
+ if (x->x_message != x->x_messini)
+ freebytes(x->x_message, x->x_size * sizeof(*x->x_message));
+ x->x_size = x->x_auxsize;
+ x->x_message = x->x_auxbuf;
+ x->x_natoms = x->x_auxsize / 2;
+ }
+ x->x_auxbuf = 0;
+ }
+ }
+}
+
+static void prepend_bang(t_prepend *x)
+{
+ t_atom at;
+ SETSYMBOL(&at, &s_bang); /* CHECKED */
+ prepend_anything(x, 0, 1, &at);
+}
+
+static void prepend_float(t_prepend *x, t_float f)
+{
+ t_atom at;
+ SETFLOAT(&at, f);
+ prepend_anything(x, 0, 1, &at);
+}
+
+static void prepend_symbol(t_prepend *x, t_symbol *s)
+{
+ t_atom at;
+ SETSYMBOL(&at, s);
+ prepend_anything(x, 0, 1, &at);
+}
+
+/* LATER gpointer */
+
+static void prepend_list(t_prepend *x, t_symbol *s, int ac, t_atom *av)
+{
+ prepend_anything(x, 0, ac, av);
+}
+
+static void prepend_set(t_prepend *x, t_symbol *s, int ac, t_atom *av)
+{
+ if (ac)
+ {
+ int newsize;
+ if (av->a_type == A_FLOAT)
+ {
+ if (ac > 1) x->x_selector = &s_list;
+ else x->x_selector = &s_float;
+ }
+ else if (av->a_type == A_SYMBOL)
+ {
+ x->x_selector = av->a_w.w_symbol;
+ ac--;
+ av++;
+ }
+ else
+ return; /* LATER rethink */
+ newsize = ac * 2;
+ if (x->x_entered)
+ {
+ if (x->x_auxbuf)
+ {
+ loud_warning((t_pd *)x, "'set' message overridden");
+ freebytes(x->x_auxbuf, x->x_auxsize * sizeof(*x->x_auxbuf));
+ x->x_auxsize = 0;
+ }
+ if (x->x_auxbuf = getbytes(newsize * sizeof(*x->x_auxbuf)))
+ {
+ memcpy(x->x_auxbuf, av, ac * sizeof(*x->x_auxbuf));
+ x->x_auxsize = newsize;
+ }
+ }
+ else
+ {
+ t_atom *ap;
+ if (newsize > x->x_size)
+ {
+ int sz = newsize;
+ x->x_message = grow_nodata(&sz, &x->x_size, x->x_message,
+ PREPEND_INISIZE, x->x_messini,
+ sizeof(*x->x_message));
+ if (sz != newsize)
+ ac = sz / 2; /* LATER rethink */
+ }
+ x->x_natoms = ac;
+ ap = x->x_message;
+ while (ac--) *ap++ = *av++;
+ }
+ }
+}
+
+static void prepend_free(t_prepend *x)
+{
+ if (x->x_message != x->x_messini)
+ freebytes(x->x_message, x->x_size * sizeof(*x->x_message));
+}
+
+static void *prepend_new(t_symbol *s, int ac, t_atom *av)
+{
+ t_prepend *x = (t_prepend *)pd_new(prepend_class);
+ x->x_selector = 0;
+ x->x_size = PREPEND_INISIZE;
+ x->x_natoms = 0;
+ x->x_message = x->x_messini;
+ x->x_auxbuf = 0;
+ x->x_entered = 0;
+ if (!ac)
+ {
+ loud_incompatible(prepend_class,
+ "creating an object without an argument");
+ /* CHECKED: this is not compatible -- in max an object without an outlet
+ is created, and there is no warning if loading from a file. */
+ }
+ outlet_new((t_object *)x, &s_anything);
+ prepend_set(x, 0, ac, av);
+ return (x);
+}
+
+void prepend_setup(void)
+{
+ prepend_class = class_new(gensym("prepend"),
+ (t_newmethod)prepend_new,
+ (t_method)prepend_free,
+ sizeof(t_prepend), 0,
+ A_GIMME, 0);
+ class_addbang(prepend_class, prepend_bang);
+ class_addfloat(prepend_class, prepend_float);
+ class_addsymbol(prepend_class, prepend_symbol);
+ class_addlist(prepend_class, prepend_list);
+ class_addanything(prepend_class, prepend_anything);
+ class_addmethod(prepend_class, (t_method)prepend_set,
+ gensym("set"), A_GIMME, 0);
+}
diff --git a/cyclone/hammer/prob.c b/cyclone/hammer/prob.c
new file mode 100644
index 0000000..5227870
--- /dev/null
+++ b/cyclone/hammer/prob.c
@@ -0,0 +1,312 @@
+/* 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 "common/loud.h"
+#include "common/rand.h"
+#include "hammer/file.h"
+
+/* CHECKED: no preallocation. Apparently, it looks like if the new
+ state-entries were added to the list's head, and the new transition-entries
+ were added to the sublist's head. No sorting of any kind. */
+
+#define PROB_DEBUG 0
+
+typedef struct _probtrans
+{
+ int tr_value; /* state (if a header trans), or suffix value (otherwise) */
+ int tr_count; /* (a total in case of a header trans) */
+ struct _probtrans *tr_suffix; /* header trans of a suffix state */
+ struct _probtrans *tr_nexttrans; /* next trans of this state */
+ struct _probtrans *tr_nextstate; /* header trans of a next state */
+} t_probtrans;
+
+typedef struct _prob
+{
+ t_object x_ob;
+ t_probtrans *x_translist;
+ t_probtrans *x_state;
+ t_probtrans *x_default;
+ int x_embedmode;
+ int x_silent;
+ unsigned int x_seed;
+ t_outlet *x_bangout;
+ t_hammerfile *x_filehandle;
+} t_prob;
+
+static t_class *prob_class;
+
+static t_probtrans *prob_findstate(t_prob *x, int value, int complain)
+{
+ t_probtrans *state;
+ for (state = x->x_translist; state; state = state->tr_nextstate)
+ if (state->tr_value == value)
+ break;
+ if (!state && complain && !x->x_silent)
+ loud_error((t_pd *)x, "no state %d", value); /* CHECKED */
+ return (state);
+}
+
+static void prob_reset(t_prob *x, t_floatarg f)
+{
+ int value = (int)f; /* CHECKED: float converted to int */
+ t_probtrans *state = prob_findstate(x, value, 1);
+ if (state) /* CHECKED */
+ {
+ x->x_default = state;
+ /* CHECKED (sort of): */
+ if (!x->x_state->tr_nexttrans)
+ x->x_state = state;
+ }
+}
+
+/*
+CHECKED: embedmode off:
+#N prob;
+#P newobj ... prob;
+
+CHECKED: embedmode on, after clear:
+#N prob;
+#T embed 1;
+#P newobj ... prob;
+
+CHECKED: embedmode on, filled:
+#N prob;
+#T <preffix> <suffix> <count>
+...
+#T embed 1;
+#T reset <default>; (if set)
+#P newobj ... prob;
+*/
+static void prob_embed(t_prob *x, t_floatarg f)
+{
+ x->x_embedmode = ((int)f != 0);
+ if (x->x_embedmode)
+ loud_incompatible(prob_class, "embedding not supported (yet)...");
+}
+
+static void prob_clear(t_prob *x)
+{
+ t_probtrans *state, *nextstate;
+ for (state = x->x_translist; state; state = nextstate)
+ {
+ t_probtrans *trans, *nexttrans;
+ for (trans = state->tr_nexttrans; trans; trans = nexttrans)
+ {
+ nexttrans = trans->tr_nexttrans;
+ freebytes(trans, sizeof(*trans));
+ }
+ nextstate = state->tr_nextstate;
+ freebytes(state, sizeof(*state));
+ }
+ x->x_translist = 0;
+ x->x_state = 0;
+ x->x_default = 0; /* CHECKED: default number is not kept */
+ /* CHECKED embedmode is kept */
+}
+
+/* CHECKED */
+static void prob_dump(t_prob *x)
+{
+ t_probtrans *state;
+ post("transition probabilities:");
+ for (state = x->x_translist; state; state = state->tr_nextstate)
+ {
+ t_probtrans *trans;
+ for (trans = state->tr_nexttrans; trans; trans = trans->tr_nexttrans)
+ post(" from %3d to %3d: %d",
+ state->tr_value, trans->tr_value, trans->tr_count);
+ /* CHECKED: dead-ends are reported */
+ post("total weights for state %d: %d",
+ state->tr_value, state->tr_count);
+ }
+}
+
+static void prob_bang(t_prob *x)
+{
+ if (x->x_state) /* CHECKED: no output after clear */
+ {
+ int rnd = rand_int(&x->x_seed, x->x_state->tr_count);
+ t_probtrans *trans = x->x_state->tr_nexttrans;
+ if (trans)
+ {
+ for (trans = x->x_state->tr_nexttrans; trans;
+ trans = trans->tr_nexttrans)
+ if ((rnd -= trans->tr_count) < 0)
+ break;
+ if (trans)
+ {
+ t_probtrans *nextstate = trans->tr_suffix;
+ if (nextstate)
+ {
+ outlet_float(((t_object *)x)->ob_outlet,
+ nextstate->tr_value);
+ x->x_state = nextstate;
+ }
+ else bug("prob_bang: void suffix");
+ }
+ else bug("prob_bang: search overflow");
+ }
+ else
+ {
+ outlet_bang(x->x_bangout);
+ if (x->x_default) /* CHECKED: stays at dead-end if no default */
+ x->x_state = x->x_default;
+ }
+ }
+}
+
+static void prob_float(t_prob *x, t_float f)
+{
+ int value;
+ if (loud_checkint((t_pd *)x, f, &value, &s_float)) /* CHECKED */
+ {
+ t_probtrans *state = prob_findstate(x, value, 1);
+ if (state) /* CHECKED */
+ x->x_state = state;
+ }
+}
+
+static void prob_list(t_prob *x, t_symbol *s, int ac, t_atom *av)
+{
+ int prefval, suffval, count;
+ if (ac == 3 && av->a_type == A_FLOAT
+ && av[1].a_type == A_FLOAT && av[2].a_type == A_FLOAT
+ && (prefval = (int)av->a_w.w_float) == av->a_w.w_float
+ && (suffval = (int)av[1].a_w.w_float) == av[1].a_w.w_float
+ && (count = (int)av[2].a_w.w_float) == av[2].a_w.w_float)
+ {
+ t_probtrans *prefix = prob_findstate(x, prefval, 0);
+ t_probtrans *suffix = prob_findstate(x, suffval, 0);
+ t_probtrans *trans;
+ if (prefix && suffix)
+ {
+ for (trans = prefix->tr_nexttrans; trans;
+ trans = trans->tr_nexttrans)
+ if (trans->tr_suffix == suffix)
+ break;
+ if (trans)
+ {
+ /* the transition already exists... */
+ prefix->tr_count += (count - trans->tr_count);
+ trans->tr_count = count;
+ return;
+ }
+ }
+ if (!prefix)
+ {
+ if (!(prefix = getbytes(sizeof(*prefix))))
+ return;
+ prefix->tr_value = prefval;
+ prefix->tr_count = 0;
+ prefix->tr_suffix = 0;
+ prefix->tr_nexttrans = 0;
+ prefix->tr_nextstate = x->x_translist;
+ x->x_translist = prefix;
+ if (suffval == prefval)
+ suffix = prefix;
+ }
+ if (!suffix)
+ {
+ if (!(suffix = getbytes(sizeof(*suffix))))
+ return;
+ suffix->tr_value = suffval;
+ suffix->tr_count = 0;
+ suffix->tr_suffix = 0;
+ suffix->tr_nexttrans = 0;
+ suffix->tr_nextstate = x->x_translist;
+ x->x_translist = suffix;
+ }
+ if (trans = getbytes(sizeof(*trans)))
+ {
+ trans->tr_value = suffval;
+ trans->tr_count = count;
+ trans->tr_suffix = suffix;
+ trans->tr_nexttrans = prefix->tr_nexttrans;
+ trans->tr_nextstate = prefix->tr_nextstate;
+ prefix->tr_count += count;
+ prefix->tr_nexttrans = trans;
+ }
+ if (!x->x_state) /* CHECKED */
+ x->x_state = prefix; /* CHECKED */
+ }
+ else loud_error((t_pd *)x, "bad list message format"); /* CHECKED */
+}
+
+static void prob_silent(t_prob *x)
+{
+ if (!x->x_silent)
+ {
+ loud_incompatible(prob_class, "no 'silent' message in max");
+ x->x_silent = 1;
+ }
+}
+
+static void prob_click(t_prob *x, t_floatarg xpos, t_floatarg ypos,
+ t_floatarg shift, t_floatarg ctrl, t_floatarg alt)
+{
+ t_probtrans *state;
+ char buf[64];
+ hammereditor_open(x->x_filehandle, "prob");
+ for (state = x->x_translist; state; state = state->tr_nextstate)
+ {
+ t_probtrans *trans;
+ for (trans = state->tr_nexttrans; trans; trans = trans->tr_nexttrans)
+ {
+ sprintf(buf, "%d %d %d\n",
+ state->tr_value, trans->tr_value, trans->tr_count);
+ hammereditor_append(x->x_filehandle, buf);
+ }
+ }
+}
+
+static void prob_free(t_prob *x)
+{
+ prob_clear(x);
+ hammerfile_free(x->x_filehandle);
+}
+
+static void *prob_new(void)
+{
+ t_prob *x = (t_prob *)pd_new(prob_class);
+ x->x_translist = 0;
+ x->x_state = 0;
+ x->x_default = 0;
+ x->x_embedmode = 0; /* CHECKED */
+ x->x_silent = 0;
+ rand_seed(&x->x_seed, 0);
+ outlet_new((t_object *)x, &s_float);
+ x->x_bangout = outlet_new((t_object *)x, &s_bang);
+ x->x_filehandle = hammerfile_new((t_pd *)x, 0, 0, 0, 0);
+ return (x);
+}
+
+void prob_setup(void)
+{
+ prob_class = class_new(gensym("prob"),
+ (t_newmethod)prob_new,
+ (t_method)prob_free,
+ sizeof(t_prob), 0, 0);
+ class_addbang(prob_class, prob_bang);
+ class_addfloat(prob_class, prob_float);
+ class_addlist(prob_class, prob_list);
+ class_addmethod(prob_class, (t_method)prob_embed,
+ gensym("embed"), A_FLOAT, 0);
+ class_addmethod(prob_class, (t_method)prob_reset,
+ gensym("reset"), A_FLOAT, 0);
+ class_addmethod(prob_class, (t_method)prob_clear,
+ gensym("clear"), 0);
+ class_addmethod(prob_class, (t_method)prob_dump,
+ gensym("dump"), 0);
+ /* CHECKED: doesn't understand "seed" */
+
+ /* below are the incompatible extensions... */
+ class_addmethod(prob_class, (t_method)prob_silent,
+ gensym("silent"), 0);
+ class_addmethod(prob_class, (t_method)prob_click,
+ gensym("click"),
+ A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0);
+ hammerfile_setup(prob_class, 0); /* LATER embedding (, 1) */
+}
diff --git a/cyclone/hammer/pv.c b/cyclone/hammer/pv.c
new file mode 100644
index 0000000..235da2c
--- /dev/null
+++ b/cyclone/hammer/pv.c
@@ -0,0 +1,457 @@
+/* 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 (it cannot be emulated): creating [s/r <pv-symbol>] prints
+ "error:send/receive:<pv-symbol>:already exists"
+*/
+
+#include <string.h>
+#include "m_pd.h"
+#include "g_canvas.h"
+#include "common/loud.h"
+#include "common/grow.h"
+
+#define PV_INISIZE 32 /* LATER rethink */
+#define PV_MAXSIZE 256
+
+typedef struct _pvfamily
+{
+ t_symbol *f_selector;
+ t_float f_float;
+ t_symbol *f_symbol;
+ t_gpointer *f_pointer;
+ int f_size; /* as allocated */
+ int f_natoms; /* as used */
+ t_atom *f_message;
+ t_atom f_messini[PV_INISIZE];
+ t_glist *f_glist; /* root glist of a family */
+ t_symbol *f_name;
+ struct _pvfamily *f_next;
+} t_pvfamily;
+
+typedef struct _pvlist
+{
+ t_pd l_pd;
+ int l_refcount;
+ t_symbol *l_name;
+ t_pvfamily *l_pvlist;
+} t_pvlist;
+
+typedef struct _pv
+{
+ t_object x_ob;
+ t_glist *x_glist;
+ t_symbol *x_name;
+ t_pvfamily *x_family;
+} t_pv;
+
+static t_class *pv_class;
+static t_class *pvlist_class;
+
+static void pvlist_decrement(t_pvlist *pl)
+{
+ if (!--pl->l_refcount)
+ {
+ pd_unbind(&pl->l_pd, pl->l_name);
+ pd_free(&pl->l_pd);
+ }
+}
+
+static t_pvlist *pv_getlist(t_symbol *s, int create)
+{
+ t_pvlist *pl = (t_pvlist *)pd_findbyclass(s, pvlist_class);
+ if (pl)
+ {
+ if (create) pl->l_refcount++;
+ }
+ else
+ {
+ if (create)
+ {
+ pl = (t_pvlist *)pd_new(pvlist_class);
+ pl->l_refcount = 1;
+ pl->l_name = s;
+ pl->l_pvlist = 0;
+ pd_bind(&pl->l_pd, s);
+ }
+ else bug("pv_getlist");
+ }
+ return (pl);
+}
+
+static t_pvfamily *pv_newfamily(t_pvlist *pvlist)
+{
+ t_pvfamily *pf = (t_pvfamily *)getbytes(sizeof(*pf));
+ pf->f_name = pvlist->l_name;
+ pf->f_next = pvlist->l_pvlist;
+ pvlist->l_pvlist = pf;
+ pf->f_selector = 0;
+ pf->f_float = 0;
+ pf->f_symbol = 0;
+ pf->f_pointer = 0;
+ pf->f_size = PV_INISIZE;
+ pf->f_natoms = 0;
+ pf->f_message = pf->f_messini;
+ return (pf);
+}
+
+static void pvfamily_free(t_pvfamily *pf)
+{
+ if (pf->f_message != pf->f_messini)
+ freebytes(pf->f_message, pf->f_size * sizeof(*pf->f_message));
+ freebytes(pf, sizeof(*pf));
+}
+
+static void pv_update(t_glist *glist, t_pvfamily *pf)
+{
+ t_gobj *g;
+ for (g = glist->gl_list; g; g = g->g_next)
+ if (pd_class(&g->g_pd) == canvas_class) /* LATER rethink */
+ pv_update((t_glist *)g, pf);
+ else if (pd_class(&g->g_pd) == pv_class
+ && ((t_pv *)g)->x_name == pf->f_name)
+ ((t_pv *)g)->x_family = pf;
+}
+
+static t_pvfamily *pvfamily_reusable;
+
+static void pv_breakup(t_pvlist *pvlist, t_glist *glist)
+{
+ t_gobj *g;
+ for (g = glist->gl_list; g; g = g->g_next)
+ {
+ if (pd_class(&g->g_pd) == pv_class
+ && ((t_pv *)g)->x_name == pvlist->l_name)
+ {
+ t_pvfamily *pf;
+ if (!(pf = pvfamily_reusable))
+ pf = pv_newfamily(pvlist);
+ else pvfamily_reusable = 0;
+ pf->f_glist = glist;
+ pv_update(glist, pf);
+ /* LATER keep current value */
+ return;
+ }
+ }
+ for (g = glist->gl_list; g; g = g->g_next)
+ if (pd_class(&g->g_pd) == canvas_class) /* LATER rethink */
+ pv_breakup(pvlist, (t_glist *)g);
+}
+
+/* join all families of a 'pvlist' rooted in any subglist of a 'glist' */
+static t_pvfamily *pv_joinup(t_pvlist *pvlist, t_glist *glist)
+{
+ t_pvfamily *result = 0;
+ t_pvfamily *pf, *pfprev, *pfnext;
+ for (pfprev = 0, pf = pvlist->l_pvlist; pf; pfprev = pf, pf = pfnext)
+ {
+ t_glist *gl;
+ pfnext = pf->f_next;
+ for (gl = pf->f_glist; gl; gl = gl->gl_owner)
+ {
+ if (gl == glist)
+ {
+ if (result)
+ {
+ pvfamily_free(pf);
+ if (pfprev)
+ pfprev->f_next = pfnext;
+ else
+ pvlist->l_pvlist = pfnext;
+ pf = pfprev;
+ }
+ else result = pf;
+ break;
+ }
+ }
+ }
+ return (result);
+}
+
+/* Called normally with either 'create' or 'destroy' set to 1,
+ but it might be called with both set to 0 for testing. */
+static t_pvfamily *pv_getfamily(t_glist *glist, t_symbol *s,
+ int create, int destroy)
+{
+ t_pvlist *pl = pv_getlist(s, create);
+ if (pl)
+ {
+ if (destroy)
+ {
+ t_pvfamily *pf, *mypf;
+ t_glist *gl;
+ for (mypf = pl->l_pvlist; mypf; mypf = mypf->f_next)
+ if (mypf->f_glist == glist)
+ break;
+ /* mypf is not null iff we are invoked via a [pv] in root */
+ /* now check if there is a family rooted in a super-branch */
+ for (gl = glist->gl_owner; gl; gl = gl->gl_owner)
+ {
+ for (pf = pl->l_pvlist; pf; pf = pf->f_next)
+ {
+ if (pf->f_glist == gl)
+ {
+ if (mypf)
+ bug("pv_getfamily 1: %s in %s",
+ mypf->f_name->s_name,
+ mypf->f_glist->gl_name->s_name);
+ else
+ return (0);
+ }
+ }
+ }
+ if (mypf)
+ {
+ pvfamily_reusable = mypf;
+ pv_breakup(pl, glist);
+ if (pvfamily_reusable == mypf)
+ {
+ pvfamily_reusable = 0;
+ if (pl->l_pvlist == mypf)
+ pl->l_pvlist = mypf->f_next;
+ else
+ {
+ for (pf = pl->l_pvlist; pf; pf = pf->f_next)
+ {
+ if (pf->f_next == mypf)
+ {
+ pf->f_next = mypf->f_next;
+ break;
+ }
+ }
+ if (!pf) bug("pv_getfamily 2");
+ }
+ pvfamily_free(mypf);
+ }
+ }
+ else bug("pv_getfamily 3");
+ pvlist_decrement(pl);
+ }
+ else
+ {
+ t_pvfamily *pf;
+ t_glist *gl;
+ for (gl = glist; gl; gl = gl->gl_owner)
+ for (pf = pl->l_pvlist; pf; pf = pf->f_next)
+ if (pf->f_glist == gl)
+ return (pf);
+ if (create)
+ {
+ if (!(pf = pv_joinup(pl, glist)))
+ pf = pv_newfamily(pl);
+ pf->f_glist = glist;
+ pv_update(glist, pf);
+ return (pf);
+ }
+ else bug("pv_getfamily 4");
+ }
+ }
+ else bug("pv_getfamily 5");
+ return (0);
+}
+
+static t_pvfamily *pv_checkfamily(t_pv *x)
+{
+ if (!x->x_family)
+ {
+ bug("pv_checkfamily");
+ x->x_family = pv_getfamily(x->x_glist, x->x_name, 0, 0);
+ }
+ return (x->x_family);
+}
+
+static void pv_bang(t_pv *x)
+{
+ t_pvfamily *pf = pv_checkfamily(x);
+ if (pf)
+ {
+ t_symbol *s = pf->f_selector;
+ if (s == &s_bang)
+ outlet_bang(((t_object *)x)->ob_outlet);
+ else if (s == &s_float)
+ outlet_float(((t_object *)x)->ob_outlet, pf->f_float);
+ else if (s == &s_symbol && pf->f_symbol)
+ outlet_symbol(((t_object *)x)->ob_outlet, pf->f_symbol);
+ else if (s == &s_pointer)
+ {
+ /* LATER */
+ }
+ else if (s == &s_list)
+ outlet_list(((t_object *)x)->ob_outlet,
+ s, pf->f_natoms, pf->f_message);
+ else if (s)
+ outlet_anything(((t_object *)x)->ob_outlet,
+ s, pf->f_natoms, pf->f_message);
+ }
+}
+
+static void pv_float(t_pv *x, t_float f)
+{
+ t_pvfamily *pf = pv_checkfamily(x);
+ if (pf)
+ {
+ pf->f_selector = &s_float;
+ pf->f_float = f;
+ pf->f_natoms = 0; /* defensive */
+ }
+}
+
+static void pv_symbol(t_pv *x, t_symbol *s)
+{
+ t_pvfamily *pf = pv_checkfamily(x);
+ if (pf)
+ {
+ pf->f_selector = &s_symbol;
+ pf->f_symbol = s;
+ pf->f_natoms = 0; /* defensive */
+ }
+}
+
+static void pv_pointer(t_pv *x, t_gpointer *gp)
+{
+ t_pvfamily *pf = pv_checkfamily(x);
+ if (pf)
+ {
+ pf->f_selector = &s_pointer;
+ pf->f_pointer = gp;
+ pf->f_natoms = 0; /* defensive */
+ }
+}
+
+static void pvfamily_domessage(t_pvfamily *pf, int ac, t_atom *av)
+{
+ if (ac > pf->f_size)
+ {
+ /* LATER consider using PV_MAXSIZE (and warning if exceeded) */
+ pf->f_message = grow_nodata(&ac, &pf->f_size, pf->f_message,
+ PV_INISIZE, pf->f_messini,
+ sizeof(*pf->f_message));
+ }
+ pf->f_natoms = ac;
+ memcpy(pf->f_message, av, ac * sizeof(*pf->f_message));
+}
+
+static void pv_list(t_pv *x, t_symbol *s, int ac, t_atom *av)
+{
+ t_pvfamily *pf = pv_checkfamily(x);
+ if (pf)
+ {
+ pf->f_selector = &s_list; /* LATER rethink */
+ pvfamily_domessage(pf, ac, av);
+ }
+}
+
+static void pv_anything(t_pv *x, t_symbol *s, int ac, t_atom *av)
+{
+ t_pvfamily *pf = pv_checkfamily(x);
+ if (pf)
+ {
+ pf->f_selector = s; /* LATER rethink */
+ pvfamily_domessage(pf, ac, av);
+ }
+}
+
+static void pv_objstatus(t_pv *x, t_glist *glist)
+{
+ t_gobj *g;
+ for (g = glist->gl_list; g; g = g->g_next)
+ {
+ if (g == (t_gobj *)x)
+ post("%x (this object) owning patcher [%s]",
+ (int)g, glist->gl_name->s_name);
+ else if (pd_class(&g->g_pd) == pv_class
+ && ((t_pv *)g)->x_name == x->x_name)
+ post("%x owning patcher [%s]", (int)g, glist->gl_name->s_name);
+ }
+}
+
+static void pv_status(t_pv *x)
+{
+ t_pvlist *pl = pv_getlist(x->x_name, 0);
+ post("pv status: Tied to %s", x->x_name->s_name);
+ if (pl)
+ {
+ t_pvfamily *pf;
+ int fcount;
+ for (pf = pl->l_pvlist, fcount = 1; pf; pf = pf->f_next, fcount++)
+ {
+ t_glist *glist = pf->f_glist;
+ t_gobj *g;
+ post("Family %d:", fcount);
+ pv_objstatus(x, glist);
+ for (g = glist->gl_list; g; g = g->g_next)
+ if (pd_class(&g->g_pd) == canvas_class) /* LATER rethink */
+ pv_objstatus(x, (t_glist *)g);
+ }
+ }
+}
+
+static void pv_free(t_pv *x)
+{
+ pv_getfamily(x->x_glist, x->x_name, 0, 1);
+}
+
+static void *pv_new(t_symbol *s, int ac, t_atom *av)
+{
+ t_pv *x = 0;
+ if (ac && av->a_type == A_SYMBOL)
+ s = av->a_w.w_symbol;
+ else s = 0;
+ if (s && s != &s_)
+ {
+ t_glist *gl = canvas_getcurrent();
+ t_pvfamily *pf = pv_getfamily(gl, s, 1, 0);
+ x = (t_pv *)pd_new(pv_class);
+ x->x_glist = gl;
+ x->x_name = s;
+ x->x_family = pf;
+ outlet_new((t_object *)x, &s_float);
+ if (--ac)
+ {
+ av++;
+ if (av->a_type == A_SYMBOL)
+ {
+ if (av->a_w.w_symbol == &s_symbol)
+ {
+ if (ac > 1 && av[1].a_type == A_SYMBOL)
+ pv_symbol(x, av[1].a_w.w_symbol);
+ }
+ /* LATER rethink 'pv <name> bang' (now it is accepted) */
+ else pv_anything(x, av->a_w.w_symbol, ac - 1, av + 1);
+ }
+ else if (av->a_type == A_FLOAT)
+ {
+ if (ac > 1)
+ pv_list(x, &s_list, ac, av);
+ else pv_float(x, av->a_w.w_float);
+ }
+ }
+
+ }
+ else
+ /* CHECKED: "error: missing or bad arguments",
+ a box is created without inlets and outlets */
+ loud_classarg(pv_class);
+ return (x);
+}
+
+void pv_setup(void)
+{
+ pv_class = class_new(gensym("pv"),
+ (t_newmethod)pv_new,
+ (t_method)pv_free,
+ sizeof(t_pv), 0, A_GIMME, 0);
+ class_addbang(pv_class, pv_bang);
+ class_addfloat(pv_class, pv_float);
+ class_addsymbol(pv_class, pv_symbol);
+ class_addpointer(pv_class, pv_pointer);
+ class_addlist(pv_class, pv_list);
+ class_addanything(pv_class, pv_anything);
+ class_addmethod(pv_class, (t_method)pv_status,
+ gensym("status"), 0);
+ /* CHECKED: sending bang (or int, list, status, etc.) with '; <pv-symbol>'
+ "error::doesn't understand bang" (class name is an empty string) */
+ pvlist_class = class_new(&s_, 0, 0,
+ sizeof(t_pvlist), CLASS_PD, 0);
+}
diff --git a/cyclone/hammer/seq.c b/cyclone/hammer/seq.c
new file mode 100644
index 0000000..503b205
--- /dev/null
+++ b/cyclone/hammer/seq.c
@@ -0,0 +1,825 @@
+/* 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 no sharing of data among seq objects having the same creation arg */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "m_pd.h"
+#include "shared.h"
+#include "common/loud.h"
+#include "common/grow.h"
+#include "common/sq.h"
+#include "common/bifi.h"
+#include "common/mifi.h"
+#include "hammer/file.h"
+
+#define SEQ_DEBUG
+
+#define SEQ_INISIZE 256 /* LATER rethink */
+#define SEQ_EOM 255 /* end of message marker, LATER rethink */
+
+typedef struct _seqevent
+{
+ int e_delta;
+ unsigned char e_bytes[4];
+} t_seqevent;
+
+typedef struct _seq
+{
+ t_object x_ob;
+ t_canvas *x_canvas;
+ t_symbol *x_defname;
+ t_hammerfile *x_filehandle;
+ int x_isplaying;
+ int x_isrecording;
+ int x_playhead;
+ float x_tempo;
+ double x_prevtime;
+ unsigned char x_status;
+ int x_evesize;
+ int x_expectedsize;
+ int x_size; /* as allocated */
+ int x_nevents; /* as used */
+ t_seqevent *x_sequence;
+ t_seqevent x_seqini[SEQ_INISIZE];
+ t_clock *x_clock;
+ t_outlet *x_bangout;
+} t_seq;
+
+static t_class *seq_class;
+
+static void seq_doclear(t_seq *x, int dofree)
+{
+ if (dofree && x->x_sequence != x->x_seqini)
+ {
+ freebytes(x->x_sequence, x->x_size * sizeof(*x->x_sequence));
+ x->x_sequence = x->x_seqini;
+ x->x_size = SEQ_INISIZE;
+ }
+ x->x_nevents = 0;
+}
+
+static void seq_complete(t_seq *x)
+{
+ if (x->x_evesize < x->x_expectedsize)
+ {
+ /* CHECKED no warning if no data after status byte requiring data */
+ if (x->x_evesize > 1)
+ post("seq: truncated midi message"); /* CHECKED */
+ /* CHECKED nothing stored */
+ }
+ else
+ {
+ t_seqevent *ep = &x->x_sequence[x->x_nevents];
+ double elapsed = clock_gettimesince(x->x_prevtime);
+ ep->e_delta = (int)elapsed;
+ x->x_prevtime = clock_getlogicaltime();
+ if (x->x_evesize < 4)
+ ep->e_bytes[x->x_evesize] = SEQ_EOM;
+ x->x_nevents++;
+ if (x->x_nevents >= x->x_size)
+ {
+ int nexisting = x->x_size;
+ /* store-ahead scheme, LATER consider using x_currevent */
+ int nrequested = x->x_nevents + 1;
+#ifdef SEQ_DEBUG
+ post("growing...");
+#endif
+ x->x_sequence =
+ grow_withdata(&nrequested, &nexisting,
+ &x->x_size, x->x_sequence,
+ SEQ_INISIZE, x->x_seqini, sizeof(*x->x_sequence));
+ if (nrequested <= x->x_nevents)
+ x->x_nevents = 0;
+ }
+ }
+ x->x_evesize = 0;
+}
+
+static void seq_checkstatus(t_seq *x, unsigned char c)
+{
+ if (x->x_status && x->x_evesize > 1) /* LATER rethink */
+ seq_complete(x);
+ if (c < 192)
+ x->x_expectedsize = 3;
+ else if (c < 224)
+ x->x_expectedsize = 2;
+ else if (c < 240)
+ x->x_expectedsize = 3;
+ else if (c < 248)
+ {
+ /* FIXME */
+ x->x_expectedsize = -1;
+ }
+ else
+ {
+ x->x_sequence[x->x_nevents].e_bytes[0] = c;
+ x->x_evesize = x->x_expectedsize = 1;
+ seq_complete(x);
+ return;
+ }
+ x->x_status = x->x_sequence[x->x_nevents].e_bytes[0] = c;
+ x->x_evesize = 1;
+}
+
+static void seq_addbyte(t_seq *x, unsigned char c, int docomplete)
+{
+ x->x_sequence[x->x_nevents].e_bytes[x->x_evesize++] = c;
+ if (x->x_evesize == x->x_expectedsize)
+ {
+ seq_complete(x);
+ if (x->x_status)
+ {
+ x->x_sequence[x->x_nevents].e_bytes[0] = x->x_status;
+ x->x_evesize = 1;
+ }
+ }
+ else if (x->x_evesize == 4)
+ {
+ if (x->x_status != 240)
+ bug("seq_addbyte");
+ /* CHECKED sysex is broken into 4-byte packets marked with
+ the actual delta time of last byte received in a packet */
+ seq_complete(x);
+ }
+ else if (docomplete) seq_complete(x);
+}
+
+static void seq_endofsysex(t_seq *x)
+{
+ seq_addbyte(x, 247, 1);
+ x->x_status = 0;
+}
+
+static void seq_stopplayback(t_seq *x)
+{
+ /* FIXME */
+ /* CHECKED "seq: incomplete sysex" at playback stop, 247 added implicitly */
+ /* CHECKME resetting controllers, etc. */
+ /* CHECKED bang not sent if playback stopped early */
+ clock_unset(x->x_clock);
+ x->x_playhead = 0;
+ x->x_isplaying = 0;
+}
+
+static void seq_stoprecording(t_seq *x)
+{
+ if (x->x_status == 240)
+ {
+ post("seq: incomplete sysex"); /* CHECKED */
+ seq_endofsysex(x); /* CHECKED 247 added implicitly */
+ }
+ else if (x->x_status)
+ seq_complete(x);
+ /* CHECKED running status used in recording, but not across recordings */
+ x->x_status = 0;
+ x->x_isrecording = 0;
+}
+
+static void seq_tick(t_seq *x)
+{
+ if (x->x_isplaying)
+ {
+ t_seqevent *ep = &x->x_sequence[x->x_playhead++];
+ unsigned char *bp = ep->e_bytes;
+nextevent:
+ outlet_float(((t_object *)x)->ob_outlet, *bp++);
+ if (*bp != SEQ_EOM)
+ {
+ outlet_float(((t_object *)x)->ob_outlet, *bp++);
+ if (*bp != SEQ_EOM)
+ {
+ outlet_float(((t_object *)x)->ob_outlet, *bp++);
+ if (*bp != SEQ_EOM)
+ outlet_float(((t_object *)x)->ob_outlet, *bp++);
+ }
+ }
+ if (!x->x_isplaying) /* reentrancy protection */
+ return;
+ if (x->x_playhead < x->x_nevents)
+ {
+ ep++;
+ if (ep->e_delta <= 0)
+ /* continue output in the same scheduler event, LATER rethink */
+ {
+ x->x_playhead++;
+ bp = ep->e_bytes;
+ goto nextevent;
+ }
+ else clock_delay(x->x_clock, ep->e_delta);
+ }
+ else
+ {
+ seq_stopplayback(x);
+ /* CHECKED bang sent immediately _after_ last byte */
+ outlet_bang(x->x_bangout); /* LATER think about reentrancy */
+ }
+ }
+}
+
+/* CHECKED running status not used in playback */
+static void seq_dostart(t_seq *x, float tempo)
+{
+ if (x->x_isplaying)
+ {
+ /* CHECKED tempo change */
+ x->x_tempo = tempo;
+ /* FIXME update the clock */
+ }
+ else
+ {
+ if (x->x_isrecording) /* CHECKED 'start' stops recording */
+ seq_stoprecording(x);
+ /* CHECKED bang not sent if a sequence is empty */
+ if (x->x_nevents)
+ {
+ x->x_tempo = tempo;
+ x->x_playhead = 0;
+ x->x_isplaying = 1;
+ /* playback data never sent within the scheduler event of
+ a start message (even for the first delta <= 0), LATER rethink */
+ clock_delay(x->x_clock, x->x_sequence->e_delta);
+ }
+ }
+}
+
+static void seq_bang(t_seq *x)
+{
+ seq_dostart(x, 1.0);
+}
+
+static void seq_float(t_seq *x, t_float f)
+{
+ if (x->x_isrecording)
+ {
+ /* CHECKED noninteger and out of range silently truncated */
+ unsigned char c = (unsigned char)f;
+ if (c < 128)
+ {
+ if (x->x_status) seq_addbyte(x, c, 0);
+ }
+ else if (c != 254) /* CHECKED active sensing ignored */
+ {
+ if (x->x_status == 240)
+ {
+ if (c == 247) seq_endofsysex(x);
+ else
+ {
+ /* CHECKED rt bytes alike */
+ post("seq: unterminated sysex"); /* CHECKED */
+ seq_endofsysex(x); /* CHECKED 247 added implicitly */
+ seq_checkstatus(x, c);
+ }
+ }
+ else if (c != 247) seq_checkstatus(x, c);
+ }
+ }
+}
+
+static void seq_symbol(t_seq *x, t_symbol *s)
+{
+ loud_nomethod((t_pd *)x, &s_symbol); /* CHECKED */
+}
+
+static void seq_list(t_seq *x, t_symbol *s, int ac, t_atom *av)
+{
+ if (ac && av->a_type == A_FLOAT) seq_float(x, av->a_w.w_float);
+ /* CHECKED anything else/more silently ignored */
+}
+
+static void seq_record(t_seq *x)
+{
+ /* CHECKED 'record' resets recording */
+ if (x->x_isplaying) /* CHECKED 'record' stops playback */
+ seq_stopplayback(x);
+ seq_doclear(x, 0);
+ x->x_isrecording = 1;
+ x->x_prevtime = clock_getlogicaltime();
+ x->x_status = 0;
+ x->x_evesize = 0;
+ x->x_expectedsize = -1; /* LATER rethink */
+}
+
+static void seq_append(t_seq *x)
+{
+ if (x->x_isrecording)
+ return; /* CHECKME 'append' does not reset recording */
+ if (x->x_isplaying) /* CHECKME 'append' stops playback */
+ seq_stopplayback(x);
+ x->x_isrecording = 1;
+ x->x_prevtime = clock_getlogicaltime();
+ x->x_status = 0;
+ x->x_evesize = 0;
+ x->x_expectedsize = -1; /* LATER rethink */
+}
+
+static void seq_stop(t_seq *x)
+{
+ if (x->x_isplaying)
+ seq_stopplayback(x);
+ else if (x->x_isrecording)
+ seq_stoprecording(x);
+}
+
+static int seq_dogrowing(t_seq *x, int nevents)
+{
+ if (nevents > x->x_size)
+ {
+ int nrequested = nevents;
+#ifdef SEQ_DEBUG
+ post("growing...");
+#endif
+ x->x_sequence =
+ grow_nodata(&nrequested, &x->x_size, x->x_sequence,
+ SEQ_INISIZE, x->x_seqini, sizeof(*x->x_sequence));
+ if (nrequested < nevents)
+ {
+ x->x_nevents = 0;
+ return (0);
+ }
+ }
+ x->x_nevents = nevents;
+ return (1);
+}
+
+static int seq_seekhook(t_squiter *it, int offset)
+{
+ t_seq *x = (t_seq *)it->i_owner;
+ post("seek in %d", x->x_nevents);
+ it->i_nelems = x->x_nevents;
+ it->i_sequence = x->x_sequence;
+ if (offset < 0)
+ offset += it->i_nelems;
+ if (offset >= 0 && offset < it->i_nelems)
+ {
+ it->i_element = (t_seqevent *)it->i_sequence + offset;
+ it->i_index = offset;
+ return (1);
+ }
+ else return (0);
+}
+
+static void seq_incrhook(t_squiter *it)
+{
+ ((t_seqevent *)it->i_element)++;
+ it->i_index++;
+}
+
+/* LATER put seq_mfwrite_doit() functionality here */
+static void seq_getevehook(t_squiter *it, t_mifi_event *mev, int *ret)
+{
+ *ret = 1;
+}
+
+static void seq_setevehook(t_squiter *it, t_mifi_event *mev, int *ret)
+{
+ t_seqevent *sev = it->i_element;
+ sev->e_delta = mev->e_delay;
+ sev->e_bytes[0] = mev->e_status | mev->e_channel;
+ sev->e_bytes[1] = mev->e_data[0];
+ if (MIFI_ONE_DATABYTE(mev->e_status))
+ sev->e_bytes[2] = SEQ_EOM;
+ else
+ {
+ sev->e_bytes[2] = mev->e_data[1];
+ sev->e_bytes[3] = SEQ_EOM;
+ }
+ *ret = 1;
+}
+
+static t_float seq_gettimhook(t_squiter *it, int *ret)
+{
+ t_seqevent *sev = it->i_element;
+ *ret = 1;
+ return (sev->e_delta);
+}
+
+static void seq_settimhook(t_squiter *it, t_float f, int *ret)
+{
+ t_seqevent *sev = it->i_element;
+ sev->e_delta = f;
+ *ret = 1;
+}
+
+static t_symbol *seq_gettarhook(t_squiter *it, int *ret)
+{
+ *ret = 1;
+ return (0);
+}
+
+static void seq_settarhook(t_squiter *it, t_symbol *s, int *ret)
+{
+ *ret = 1;
+}
+
+static int seq_make_iterator(t_seq *x, t_mifi_stream *stp)
+{
+ t_squiter *it = squiter_new(stp);
+ if (it)
+ {
+ it->i_owner = x;
+ it->i_nelems = x->x_nevents;
+ it->i_sequence = it->i_element = x->x_sequence;
+ it->i_index = 0;
+ it->i_hooks[SQUITER_SEEKHOOK] = (t_squiterhook)seq_seekhook;
+ it->i_hooks[SQUITER_INCRHOOK] = (t_squiterhook)seq_incrhook;
+ it->i_hooks[SQUITER_GETEVEHOOK] = (t_squiterhook)seq_getevehook;
+ it->i_hooks[SQUITER_SETEVEHOOK] = (t_squiterhook)seq_setevehook;
+ it->i_hooks[SQUITER_GETTIMHOOK] = (t_squiterhook)seq_gettimhook;
+ it->i_hooks[SQUITER_SETTIMHOOK] = (t_squiterhook)seq_settimhook;
+ it->i_hooks[SQUITER_GETTARHOOK] = (t_squiterhook)seq_gettarhook;
+ it->i_hooks[SQUITER_SETTARHOOK] = (t_squiterhook)seq_settarhook;
+ return (1);
+ }
+ else return (0);
+}
+
+static t_mifi_stream *seq_makestream(t_seq *x)
+{
+ t_mifi_stream *stp = 0;
+ if (stp = mifi_stream_new())
+ {
+ if (seq_make_iterator(x, stp))
+ return (stp);
+ else
+ mifi_stream_free(stp);
+ }
+ return (0);
+}
+
+static int seq_comparehook(const void *e1, const void *e2)
+{
+ return (((t_seqevent *)e1)->e_delta > ((t_seqevent *)e2)->e_delta ? 1 : -1);
+}
+
+/* FIXME */
+static int seq_mfread(t_seq *x, char *path)
+{
+ int result = 0;
+ t_mifi_stream *stp = 0;
+ if (!(stp = seq_makestream(x)) ||
+ !mifi_read_start(stp, path, "", 0))
+ goto readfailed;
+#ifdef SEQ_DEBUG
+ if (stp->s_nframes)
+ post("midifile (format %d): %d tracks, %d ticks (%d smpte frames)",
+ stp->s_format, stp->s_hdtracks, stp->s_nticks, stp->s_nframes);
+ else
+ post("midifile (format %d): %d tracks, %d ticks per beat",
+ stp->s_format, stp->s_hdtracks, stp->s_nticks);
+#endif
+ if (mifi_read_analyse(stp) != MIFI_READ_EOF ||
+ !seq_dogrowing(x, stp->s_nevents) ||
+ !mifi_read_restart(stp) ||
+ mifi_read_doit(stp) != MIFI_READ_EOF)
+ goto readfailed;
+ squmpi_sort(stp);
+ qsort(x->x_sequence, stp->s_nevents, sizeof(*x->x_sequence),
+ seq_comparehook);
+ sq_fold_time(stp);
+#ifdef SEQ_DEBUG
+ post("finished reading %d events from midifile", stp->s_nevents);
+#endif
+ result = 1;
+readfailed:
+ if (stp)
+ {
+ mifi_read_end(stp);
+ mifi_stream_free(stp);
+ }
+ return (result);
+}
+
+/* FIXME */
+static int seq_mfwrite_doit(t_seq *x, t_mifi_stream *stp)
+{
+ t_mifi_event *mev = stp->s_auxeve;
+ t_seqevent *sev = x->x_sequence;
+ int nevents = x->x_nevents;
+ while (nevents--)
+ {
+ unsigned char *bp = sev->e_bytes;
+ int i;
+ mev->e_delay = (uint32)(sev->e_delta * stp->s_timecoef);
+ mev->e_status = *bp & 0xf0;
+ mev->e_channel = *bp & 0x0f;
+ /* FIXME sysex continuation */
+ for (i = 0, bp++; i < 3 && *bp != SEQ_EOM; i++, bp++)
+ mev->e_data[i] = *bp;
+ if (!mifi_write_event(stp, mev))
+ return (0);
+ sev++;
+ }
+ return (1);
+}
+
+/* FIXME */
+static int seq_mfwrite(t_seq *x, char *path)
+{
+ int result = 0;
+ t_mifi_stream *stp = 0;
+ if (!(stp = seq_makestream(x)))
+ goto writefailed;
+ stp->s_ntracks = 1;
+ stp->s_hdtracks = 1;
+ stp->s_format = 0;
+ if (!mifi_write_start(stp, path, ""))
+ goto writefailed;
+ mifi_event_settext(stp->s_auxeve, MIFI_META_TRACKNAME, "seq-track");
+ if (!mifi_write_start_track(stp) ||
+ !mifi_write_event(stp, stp->s_auxeve) ||
+ !seq_mfwrite_doit(x, stp) ||
+ !mifi_write_adjust_track(stp, 0))
+ goto writefailed;
+ result = 1;
+writefailed:
+ if (stp)
+ {
+ mifi_write_end(stp);
+ mifi_stream_free(stp);
+ }
+ return (result);
+}
+
+/* FIXME */
+/* CHECKED absolute timestamps, semi-terminated, verified */
+static int seq_frombinbuf(t_seq *x, t_binbuf *bb)
+{
+ int nevents = 0;
+ int ac = binbuf_getnatom(bb);
+ t_atom *av = binbuf_getvec(bb);
+ while (ac--)
+ if (av++->a_type == A_SEMI) /* FIXME parsing */
+ nevents++;
+ if (nevents)
+ {
+ t_seqevent *ep;
+ float prevtime = 0;
+ int i = -1;
+ if (!seq_dogrowing(x, nevents))
+ return (0);
+ nevents = 0;
+ ac = binbuf_getnatom(bb);
+ av = binbuf_getvec(bb);
+ ep = x->x_sequence;
+ while (ac--)
+ {
+ if (av->a_type == A_FLOAT)
+ {
+ if (i < 0)
+ {
+ ep->e_delta = av->a_w.w_float - prevtime;
+ prevtime = av->a_w.w_float;
+ i = 0;
+ }
+ else if (i < 4)
+ ep->e_bytes[i++] = av->a_w.w_float;
+ /* CHECKME else */
+ }
+ else if (av->a_type == A_SEMI && i > 0)
+ {
+ if (i < 4)
+ ep->e_bytes[i] = SEQ_EOM;
+ nevents++;
+ ep++;
+ i = -1;
+ }
+ /* CHECKME else */
+ av++;
+ }
+ x->x_nevents = nevents;
+ }
+ return (nevents);
+}
+
+static void seq_tobinbuf(t_seq *x, t_binbuf *bb)
+{
+ int nevents = x->x_nevents;
+ t_seqevent *ep = x->x_sequence;
+ t_atom at[5];
+ float timestamp = 0;
+ while (nevents--)
+ {
+ unsigned char *bp = ep->e_bytes;
+ int i;
+ t_atom *ap = at;
+ timestamp += ep->e_delta;
+ SETFLOAT(ap, timestamp); /* CHECKED same for sysex continuation */
+ ap++;
+ SETFLOAT(ap, *bp);
+ for (i = 0, ap++, bp++; i < 3 && *bp != SEQ_EOM; i++, ap++, bp++)
+ SETFLOAT(ap, *bp);
+ binbuf_add(bb, i + 2, at);
+ binbuf_addsemi(bb);
+ ep++;
+ }
+}
+
+static void seq_textread(t_seq *x, char *path)
+{
+ t_binbuf *bb;
+ bb = binbuf_new();
+ if (binbuf_read(bb, path, "", 0))
+ {
+ /* CHECKED no complaint, open dialog presented */
+ hammerpanel_open(x->x_filehandle); /* LATER rethink */
+ }
+ else
+ {
+ int nlines = seq_frombinbuf(x, bb);
+ if (nlines < 0)
+ /* CHECKED "bad MIDI file (truncated)" alert, even if a text file */
+ loud_error((t_pd *)x, "bad text file (truncated)");
+ else if (nlines == 0)
+ {
+ /* CHECKED no complaint, sequence erased, LATER rethink */
+ }
+ }
+ binbuf_free(bb);
+}
+
+static void seq_textwrite(t_seq *x, char *path)
+{
+ t_binbuf *bb;
+ bb = binbuf_new();
+ seq_tobinbuf(x, bb);
+ /* CHECKED empty sequence stored as an empty file */
+ if (binbuf_write(bb, path, "", 0))
+ {
+ /* CHECKME complaint and FIXME */
+ loud_error((t_pd *)x, "error writing text file");
+ }
+ binbuf_free(bb);
+}
+
+static void seq_doread(t_seq *x, t_symbol *fn, int creation)
+{
+ char buf[MAXPDSTRING];
+ if (x->x_canvas)
+ canvas_makefilename(x->x_canvas, fn->s_name, buf, MAXPDSTRING);
+ else
+ {
+ strncpy(buf, fn->s_name, MAXPDSTRING);
+ buf[MAXPDSTRING-1] = 0;
+ }
+ if (creation)
+ {
+ /* loading during object creation -- CHECKED no warning if a file
+ specified with an arg does not exist, LATER rethink */
+ FILE *fp;
+ char path[MAXPDSTRING];
+ sys_bashfilename(buf, path);
+ if (!(fp = fopen(path, "r")))
+ return;
+ fclose(fp);
+ }
+ /* CHECKED all cases: arg or not, message and creation */
+ post("seq: reading %s", fn->s_name);
+ if (!seq_mfread(x, buf))
+ seq_textread(x, buf);
+}
+
+static void seq_dowrite(t_seq *x, t_symbol *fn)
+{
+ char buf[MAXPDSTRING], *dotp;
+ if (x->x_canvas)
+ canvas_makefilename(x->x_canvas, fn->s_name, buf, MAXPDSTRING);
+ else
+ {
+ strncpy(buf, fn->s_name, MAXPDSTRING);
+ buf[MAXPDSTRING-1] = 0;
+ }
+ post("seq: writing %s", fn->s_name); /* CHECKED arg or not */
+ /* save as text for any extension other then ".mid" */
+ if ((dotp = strrchr(fn->s_name, '.')) && strcmp(dotp + 1, "mid"))
+ seq_textwrite(x, buf);
+ else /* save as mf for ".mid" or no extension at all, LATER rethink */
+ seq_mfwrite(x, buf);
+}
+
+static void seq_readhook(t_pd *z, t_symbol *fn, int ac, t_atom *av)
+{
+ seq_doread((t_seq *)z, fn, 0);
+}
+
+static void seq_writehook(t_pd *z, t_symbol *fn, int ac, t_atom *av)
+{
+ seq_dowrite((t_seq *)z, fn);
+}
+
+static void seq_read(t_seq *x, t_symbol *s)
+{
+ if (s && s != &s_)
+ seq_doread(x, s, 0);
+ else /* CHECKED no default */
+ hammerpanel_open(x->x_filehandle);
+}
+
+static void seq_write(t_seq *x, t_symbol *s)
+{
+ if (s && s != &s_)
+ seq_dowrite(x, s);
+ else /* CHECKED creation arg is a default */
+ hammerpanel_save(x->x_filehandle,
+ canvas_getdir(x->x_canvas), x->x_defname);
+}
+
+static void seq_print(t_seq *x)
+{
+ int nevents = x->x_nevents;
+ startpost("midiseq:"); /* CHECKED */
+ if (nevents)
+ {
+ t_seqevent *ep = x->x_sequence;
+ int truncated;
+ if (nevents > 16)
+ nevents = 16, truncated = 1;
+ else
+ truncated = 0;
+ while (nevents--)
+ {
+ unsigned char *bp = ep->e_bytes;
+ int i;
+ if (*bp < 128 || *bp == 247)
+ /* CHECKED (sysex continuation) */
+ startpost("\n(%d)->", ep->e_delta);
+ else
+ startpost("\n(%d)", ep->e_delta);
+ /* CHECKED space-separated, no semi */
+ postfloat((float)*bp);
+ for (i = 0, bp++; i < 3 && *bp != SEQ_EOM; i++, bp++)
+ postfloat((float)*bp);
+ ep++;
+ }
+ endpost();
+ if (truncated) post("..."); /* CHECKED */
+ }
+ else post(" no sequence"); /* CHECKED */
+}
+
+static void seq_free(t_seq *x)
+{
+ if (x->x_clock) clock_free(x->x_clock);
+ hammerfile_free(x->x_filehandle);
+ if (x->x_sequence != x->x_seqini)
+ freebytes(x->x_sequence, x->x_size * sizeof(*x->x_sequence));
+}
+
+static void *seq_new(t_symbol *s)
+{
+ t_seq *x = (t_seq *)pd_new(seq_class);
+ static int warned = 0;
+ if (!warned)
+ {
+ loud_warning((t_pd *)x, "seq is not ready yet");
+ warned = 1;
+ }
+ x->x_canvas = canvas_getcurrent();
+ x->x_filehandle = hammerfile_new((t_pd *)x, 0,
+ seq_readhook, seq_writehook, 0);
+ x->x_prevtime = 0;
+ x->x_size = SEQ_INISIZE;
+ x->x_nevents = 0;
+ x->x_sequence = x->x_seqini;
+ outlet_new((t_object *)x, &s_anything);
+ x->x_bangout = outlet_new((t_object *)x, &s_bang);
+ if (s && s != &s_)
+ {
+ x->x_defname = s; /* CHECKME if 'read' changes this */
+ seq_doread(x, s, 1);
+ }
+ else x->x_defname = &s_;
+ x->x_clock = clock_new(x, (t_method)seq_tick);
+ return (x);
+}
+
+void seq_setup(void)
+{
+ seq_class = class_new(gensym("seq"),
+ (t_newmethod)seq_new,
+ (t_method)seq_free,
+ sizeof(t_seq), 0,
+ A_DEFSYM, 0);
+ class_addbang(seq_class, seq_bang);
+ class_addfloat(seq_class, seq_float);
+ /* CHECKED symbol rejected */
+ class_addsymbol(seq_class, seq_symbol);
+ /* CHECKED 1st atom of a list accepted if a float, ignored if a symbol */
+ class_addlist(seq_class, seq_list);
+ class_addmethod(seq_class, (t_method)seq_record,
+ gensym("record"), 0);
+ class_addmethod(seq_class, (t_method)seq_append,
+ gensym("append"), 0);
+ class_addmethod(seq_class, (t_method)seq_stop,
+ gensym("stop"), 0);
+ class_addmethod(seq_class, (t_method)seq_read,
+ gensym("read"), A_DEFSYM, 0);
+ class_addmethod(seq_class, (t_method)seq_write,
+ gensym("write"), A_DEFSYM, 0);
+ class_addmethod(seq_class, (t_method)seq_print,
+ gensym("print"), 0);
+ hammerfile_setup(seq_class, 0);
+}
diff --git a/cyclone/hammer/sinh.c b/cyclone/hammer/sinh.c
new file mode 100644
index 0000000..93fb6fa
--- /dev/null
+++ b/cyclone/hammer/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"
+
+#if defined(NT) || defined(MACOSX)
+/* cf pd/src/x_arithmetic.c */
+#define sinhf sinh
+#endif
+
+typedef struct _sinh
+{
+ t_object x_ob;
+ float x_value;
+} t_sinh;
+
+static t_class *sinh_class;
+
+static void sinh_bang(t_sinh *x)
+{
+ outlet_float(((t_object *)x)->ob_outlet, x->x_value);
+}
+
+static void sinh_float(t_sinh *x, t_float f)
+{
+ /* CHECKME large values */
+ outlet_float(((t_object *)x)->ob_outlet, x->x_value = sinhf(f));
+}
+
+static void *sinh_new(t_floatarg f)
+{
+ t_sinh *x = (t_sinh *)pd_new(sinh_class);
+ /* CHECKME large values */
+ x->x_value = sinhf(f);
+ outlet_new((t_object *)x, &s_float);
+ return (x);
+}
+
+void sinh_setup(void)
+{
+ sinh_class = class_new(gensym("sinh"),
+ (t_newmethod)sinh_new, 0,
+ sizeof(t_sinh), 0, A_DEFFLOAT, 0);
+ class_addbang(sinh_class, sinh_bang);
+ class_addfloat(sinh_class, sinh_float);
+}
diff --git a/cyclone/hammer/speedlim.c b/cyclone/hammer/speedlim.c
new file mode 100644
index 0000000..3cad0f7
--- /dev/null
+++ b/cyclone/hammer/speedlim.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. */
+
+/* LATER 'clock' method */
+
+#include <string.h>
+#include "m_pd.h"
+#include "common/grow.h"
+
+#define SPEEDLIM_INISIZE 32 /* LATER rethink */
+#define SPEEDLIM_MAXSIZE 256 /* not used */
+
+typedef struct _speedlim
+{
+ t_object x_ob;
+ int x_open;
+ t_float x_delta;
+ t_symbol *x_selector;
+ t_float x_float;
+ t_symbol *x_symbol;
+ t_gpointer *x_pointer;
+ int x_size; /* as allocated */
+ int x_natoms; /* as used */
+ t_atom *x_message;
+ t_atom x_messini[SPEEDLIM_INISIZE];
+ int x_entered;
+ t_clock *x_clock;
+} t_speedlim;
+
+static t_class *speedlim_class;
+
+static void speedlim_dooutput(t_speedlim *x, t_symbol *s, int ac, t_atom *av)
+{
+ x->x_open = 0; /* so there will be no reentrant calls of dooutput */
+ x->x_entered = 1; /* this prevents a message from being overridden */
+ clock_unset(x->x_clock);
+ if (s == &s_bang)
+ outlet_bang(((t_object *)x)->ob_outlet);
+ else if (s == &s_float)
+ outlet_float(((t_object *)x)->ob_outlet, x->x_float);
+ else if (s == &s_symbol && x->x_symbol)
+ {
+ /* if x_symbol is null, then symbol &s_ is passed
+ by outlet_anything() -> typedmess() */
+ outlet_symbol(((t_object *)x)->ob_outlet, x->x_symbol);
+ x->x_symbol = 0;
+ }
+ else if (s == &s_pointer && x->x_pointer)
+ {
+ /* LATER */
+ x->x_pointer = 0;
+ }
+ else if (s == &s_list)
+ outlet_list(((t_object *)x)->ob_outlet, &s_list, ac, av);
+ else if (s)
+ outlet_anything(((t_object *)x)->ob_outlet, s, ac, av);
+ x->x_selector = 0;
+ x->x_natoms = 0;
+ if (x->x_delta > 0)
+ clock_delay(x->x_clock, x->x_delta);
+ else
+ x->x_open = 1;
+ x->x_entered = 0;
+}
+
+static void speedlim_tick(t_speedlim *x)
+{
+ if (x->x_selector)
+ speedlim_dooutput(x, x->x_selector, x->x_natoms, x->x_message);
+ else
+ x->x_open = 1;
+}
+
+static void speedlim_anything(t_speedlim *x, t_symbol *s, int ac, t_atom *av)
+{
+ if (x->x_open)
+ speedlim_dooutput(x, s, ac, av);
+ else if (s && s != &s_ && !x->x_entered)
+ {
+ if (ac > x->x_size)
+ /* MAXSIZE not used, not even a warning...
+ LATER consider clipping */
+ x->x_message = grow_nodata(&ac, &x->x_size, x->x_message,
+ SPEEDLIM_INISIZE, x->x_messini,
+ sizeof(*x->x_message));
+ x->x_selector = s;
+ x->x_natoms = ac;
+ if (ac)
+ memcpy(x->x_message, av, ac * sizeof(*x->x_message));
+ }
+}
+
+static void speedlim_bang(t_speedlim *x)
+{
+ x->x_selector = &s_bang;
+ speedlim_anything(x, x->x_selector, 0, 0);
+}
+
+static void speedlim_float(t_speedlim *x, t_float f)
+{
+ x->x_selector = &s_float;
+ x->x_float = f;
+ speedlim_anything(x, x->x_selector, 0, 0);
+}
+
+static void speedlim_symbol(t_speedlim *x, t_symbol *s)
+{
+ x->x_selector = &s_symbol;
+ x->x_symbol = s;
+ speedlim_anything(x, x->x_selector, 0, 0);
+}
+
+/* LATER gpointer */
+
+static void speedlim_list(t_speedlim *x, t_symbol *s, int ac, t_atom *av)
+{
+ x->x_selector = &s_list;
+ speedlim_anything(x, x->x_selector, ac, av);
+}
+
+static void speedlim_ft1(t_speedlim *x, t_floatarg f)
+{
+ if (f < 0)
+ f = 0; /* redundant (and CHECKED) */
+ x->x_delta = f;
+ /* CHECKED: no rearming --
+ if clock is set, then new delta value is not used until next tick */
+}
+
+static void speedlim_free(t_speedlim *x)
+{
+ if (x->x_message != x->x_messini)
+ freebytes(x->x_message, x->x_size * sizeof(*x->x_message));
+ if (x->x_clock)
+ clock_free(x->x_clock);
+}
+
+static void *speedlim_new(t_floatarg f)
+{
+ t_speedlim *x = (t_speedlim *)pd_new(speedlim_class);
+ x->x_open = 1; /* CHECKED */
+ x->x_delta = 0;
+ x->x_selector = 0;
+ x->x_float = 0;
+ x->x_symbol = 0;
+ x->x_pointer = 0;
+ x->x_size = SPEEDLIM_INISIZE;
+ x->x_natoms = 0;
+ x->x_message = x->x_messini;
+ x->x_entered = 0;
+ inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft1"));
+ outlet_new((t_object *)x, &s_anything);
+ x->x_clock = clock_new(x, (t_method)speedlim_tick);
+ speedlim_ft1(x, f);
+ return (x);
+}
+
+void speedlim_setup(void)
+{
+ speedlim_class = class_new(gensym("speedlim"),
+ (t_newmethod)speedlim_new,
+ (t_method)speedlim_free,
+ sizeof(t_speedlim), 0,
+ A_DEFFLOAT, 0);
+ class_addbang(speedlim_class, speedlim_bang);
+ class_addfloat(speedlim_class, speedlim_float);
+ class_addsymbol(speedlim_class, speedlim_symbol);
+ class_addlist(speedlim_class, speedlim_list);
+ class_addanything(speedlim_class, speedlim_anything);
+ class_addmethod(speedlim_class, (t_method)speedlim_ft1,
+ gensym("ft1"), A_FLOAT, 0);
+}
diff --git a/cyclone/hammer/spell.c b/cyclone/hammer/spell.c
new file mode 100644
index 0000000..f9a32d6
--- /dev/null
+++ b/cyclone/hammer/spell.c
@@ -0,0 +1,149 @@
+/* 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 "common/loud.h"
+
+typedef struct _spell
+{
+ t_object x_ob;
+ int x_minsize;
+ int x_padchar; /* actually, any nonnegative integer (CHECKED) */
+} t_spell;
+
+static t_class *spell_class;
+
+static void spell_fill(t_spell *x, int cnt)
+{
+ for (; cnt < x->x_minsize; cnt++)
+ outlet_float(((t_object *)x)->ob_outlet, x->x_padchar);
+}
+
+/* CHECKED: chars are spelled as signed */
+static int spell_out(t_spell *x, char *ptr, int flush)
+{
+ int cnt = 0;
+ while (*ptr)
+ outlet_float(((t_object *)x)->ob_outlet, *ptr++), cnt++;
+ if (flush)
+ {
+ spell_fill(x, cnt);
+ return (0);
+ }
+ return (cnt);
+}
+
+static void spell_bang(t_spell *x)
+{
+ /* need to somehow override a default bang-to-empty-list conversion... */
+ loud_nomethod((t_pd *)x, &s_bang); /* CHECKED */
+}
+
+static void spell_float(t_spell *x, t_float f)
+{
+ int i;
+ if (loud_checkint((t_pd *)x, f, &i, &s_float)) /* CHECKED */
+ {
+ char buf[16];
+ sprintf(buf, "%d", i); /* CHECKED (negative numbers) */
+ spell_out(x, buf, 1);
+ }
+}
+
+/* CHECKED: 'symbol' selector is not spelled! */
+static void spell_symbol(t_spell *x, t_symbol *s)
+{
+ spell_out(x, s->s_name, 1);
+}
+
+static void spell_list(t_spell *x, t_symbol *s, int ac, t_atom *av)
+{
+ int cnt = 0;
+ int addsep = 0;
+ while (ac--)
+ {
+ if (addsep)
+ {
+ outlet_float(((t_object *)x)->ob_outlet, x->x_padchar);
+ cnt++;
+ }
+ else addsep = 1;
+ if (av->a_type == A_FLOAT)
+ {
+ int i;
+ /* CHECKME */
+ if (loud_checkint((t_pd *)x, av->a_w.w_float, &i, &s_list))
+ {
+ char buf[16];
+ sprintf(buf, "%d", i); /* CHECKED (negative numbers) */
+ cnt += spell_out(x, buf, 0);
+ }
+ /* CHECKED: floats as empty strings (separator is added) */
+ }
+ /* CHECKED: symbols as empty strings (separator is added) */
+ av++;
+ }
+ if (cnt) /* CHECKED: empty list is silently ignored */
+ spell_fill(x, cnt);
+}
+
+static void spell_anything(t_spell *x, t_symbol *s, int ac, t_atom *av)
+{
+ int cnt = 0;
+ int addsep = 0;
+ if (s)
+ {
+ cnt += spell_out(x, s->s_name, 0);
+ addsep = 1;
+ }
+ while (ac--)
+ {
+ if (addsep)
+ {
+ outlet_float(((t_object *)x)->ob_outlet, x->x_padchar);
+ cnt++;
+ }
+ else addsep = 1;
+ if (av->a_type == A_FLOAT)
+ {
+ int i;
+ /* CHECKME */
+ if (loud_checkint((t_pd *)x, av->a_w.w_float, &i, &s_list))
+ {
+ char buf[16];
+ sprintf(buf, "%d", i); /* CHECKED (negative numbers) */
+ cnt += spell_out(x, buf, 0);
+ }
+ /* CHECKED: floats as empty strings (separator is added) */
+ }
+ else if (av->a_type == A_SYMBOL && av->a_w.w_symbol)
+ cnt += spell_out(x, av->a_w.w_symbol->s_name, 0);
+ av++;
+ }
+ if (cnt) /* CHECKED: empty list is silently ignored */
+ spell_fill(x, cnt);
+}
+
+static void *spell_new(t_floatarg f1, t_floatarg f2)
+{
+ t_spell *x = (t_spell *)pd_new(spell_class);
+ int i2 = (int)f2; /* CHECKED */
+ x->x_minsize = (f1 > 0 ? (int)f1 : 0);
+ x->x_padchar = (i2 < 0 ? 0 : (i2 > 0 ? i2 : ' ')); /* CHECKED */
+ outlet_new((t_object *)x, &s_float);
+ return (x);
+}
+
+void spell_setup(void)
+{
+ spell_class = class_new(gensym("spell"),
+ (t_newmethod)spell_new, 0,
+ sizeof(t_spell), 0, A_DEFFLOAT, A_DEFFLOAT, 0);
+ class_addbang(spell_class, spell_bang);
+ class_addfloat(spell_class, spell_float);
+ class_addsymbol(spell_class, spell_symbol);
+ class_addlist(spell_class, spell_list);
+ class_addanything(spell_class, spell_anything);
+}
diff --git a/cyclone/hammer/split.c b/cyclone/hammer/split.c
new file mode 100644
index 0000000..2865f66
--- /dev/null
+++ b/cyclone/hammer/split.c
@@ -0,0 +1,64 @@
+/* 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"
+
+/* CHECKED:
+ 'list <symbol>' silently ignored (LATER remove a warning)
+ '<number> <symbol>' as '<number>' (LATER remove a warning)
+ LATER more compatibility checks are needed...
+ LATER sort out float/int dilemmas
+*/
+
+typedef struct _split
+{
+ t_object x_ob;
+ int x_floatmode;
+ t_float x_min;
+ t_float x_max;
+ t_outlet *x_out2;
+} t_split;
+
+static t_class *split_class;
+
+static void split_float(t_split *x, t_float f)
+{
+ if (x->x_floatmode)
+ {
+ if (f >= x->x_min && f <= x->x_max)
+ outlet_float(((t_object *)x)->ob_outlet, f);
+ else outlet_float(x->x_out2, f);
+ }
+ else
+ {
+ /* CHECKED: no pre-truncation */
+ if (f >= x->x_min && f <= x->x_max)
+ outlet_float(((t_object *)x)->ob_outlet, (int)f);
+ else outlet_float(x->x_out2, (int)f);
+ }
+}
+
+static void *split_new(t_floatarg f1, t_floatarg f2)
+{
+ t_split *x = (t_split *)pd_new(split_class);
+ x->x_floatmode = (f1 != (int)f1);
+ /* CHECKED: defaults are [0..0] and [0..f1] (for positive f1) or [f1..0] */
+ if (f1 < f2) /* CHECKED */
+ x->x_min = f1, x->x_max = f2;
+ else
+ x->x_min = f2, x->x_max = f1;
+ floatinlet_new((t_object *)x, &x->x_min);
+ floatinlet_new((t_object *)x, &x->x_max);
+ outlet_new((t_object *)x, &s_float);
+ x->x_out2 = outlet_new((t_object *)x, &s_float);
+ return (x);
+}
+
+void split_setup(void)
+{
+ split_class = class_new(gensym("split"),
+ (t_newmethod)split_new, 0,
+ sizeof(t_split), 0, A_DEFFLOAT, A_DEFFLOAT, 0);
+ class_addfloat(split_class, split_float);
+}
diff --git a/cyclone/hammer/spray.c b/cyclone/hammer/spray.c
new file mode 100644
index 0000000..8aa0556
--- /dev/null
+++ b/cyclone/hammer/spray.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 "m_pd.h"
+#include "common/loud.h"
+
+#define SPRAY_MINOUTS 1
+/* CHECKED: no upper limit */
+#define SPRAY_DEFOUTS 2
+
+typedef struct _spray
+{
+ t_object x_ob;
+ int x_offset;
+ int x_nouts;
+ t_outlet **x_outs;
+} t_spray;
+
+static t_class *spray_class;
+
+static void spray_float(t_spray *x, t_float f)
+{
+ /* CHECKED: floats ignored (LATER rethink), ints loudly rejected */
+ if (f == (int)f) loud_error((t_pd *)x, "requires list");
+}
+
+/* LATER decide, whether float in first atom is to be truncated,
+ or causing a list to be ignored as in max (CHECKED) */
+static void spray_list(t_spray *x, t_symbol *s, int ac, t_atom *av)
+{
+ int ndx;
+ if (ac >= 2 && av->a_type == A_FLOAT
+ /* CHECKED: lists with negative effective ndx are ignored */
+ && (ndx = (int)av->a_w.w_float - x->x_offset) >= 0
+ && ndx < x->x_nouts)
+ {
+ /* CHECKED: ignored atoms (symbols and floats) are counted */
+ /* CHECKED: we must spray in right-to-left order */
+ t_atom *argp;
+ t_outlet **outp;
+ int last = ac - 1 + ndx; /* ndx of last outlet filled (first is 1) */
+ if (last > x->x_nouts)
+ {
+ argp = av + 1 + x->x_nouts - ndx;
+ outp = x->x_outs + x->x_nouts;
+ }
+ else
+ {
+ argp = av + ac;
+ outp = x->x_outs + last;
+ }
+ /* argp/outp now point to one after the first atom/outlet to deliver */
+ for (argp--, outp--; argp > av; argp--, outp--)
+ if (argp->a_type == A_FLOAT)
+ outlet_float(*outp, argp->a_w.w_float);
+ }
+}
+
+static void spray_free(t_spray *x)
+{
+ if (x->x_outs)
+ freebytes(x->x_outs, x->x_nouts * sizeof(*x->x_outs));
+}
+
+static void *spray_new(t_floatarg f1, t_floatarg f2)
+{
+ t_spray *x;
+ int i, nouts = (int)f1;
+ t_outlet **outs;
+ if (nouts < SPRAY_MINOUTS)
+ nouts = SPRAY_DEFOUTS;
+ if (!(outs = (t_outlet **)getbytes(nouts * sizeof(*outs))))
+ return (0);
+ x = (t_spray *)pd_new(spray_class);
+ x->x_nouts = nouts;
+ x->x_outs = outs;
+ x->x_offset = (int)f2;
+ for (i = 0; i < nouts; i++)
+ x->x_outs[i] = outlet_new((t_object *)x, &s_float);
+ return (x);
+}
+
+void spray_setup(void)
+{
+ spray_class = class_new(gensym("spray"),
+ (t_newmethod)spray_new,
+ (t_method)spray_free,
+ sizeof(t_spray), 0, A_DEFFLOAT, A_DEFFLOAT, 0);
+ /* CHECKED: bang, symbol, anything -- ``doesn't understand'' */
+ class_addfloat(spray_class, spray_float);
+ class_addlist(spray_class, spray_list);
+}
diff --git a/cyclone/hammer/sprintf.c b/cyclone/hammer/sprintf.c
new file mode 100644
index 0000000..aebfed3
--- /dev/null
+++ b/cyclone/hammer/sprintf.c
@@ -0,0 +1,634 @@
+/* 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 empty string as a default for %s */
+
+#include <stdio.h>
+#include <string.h>
+#include "m_pd.h"
+#include "common/loud.h"
+
+#define SPRINTF_DEBUG 0
+
+/* Pattern types. These are the parsing routine's return values.
+ If returned value is >= SPRINTF_MINSLOTTYPE, then another slot
+ is created (i.e. an inlet, and a proxy handling it). */
+#define SPRINTF_UNSUPPORTED 0
+#define SPRINTF_LITERAL 1
+#define SPRINTF_MINSLOTTYPE 2
+#define SPRINTF_INT 2
+#define SPRINTF_FLOAT 3
+#define SPRINTF_CHAR 4
+#define SPRINTF_STRING 5
+
+/* Numbers: assuming max 62 digits preceding a decimal point in any
+ fixed-point representation of a t_float (39 in my system)
+ -- need to be sure, that using max precision would never produce
+ a representation longer than max width. If this is so, then no number
+ representation would exceed max width (presumably...).
+ Strings: for the time being, any string longer than max width would
+ be truncated (somehow compatible with Str256, but LATER warn-and-allow). */
+/* LATER rethink it all */
+#define SPRINTF_MAXPRECISION 192
+#define SPRINTF_MAXWIDTH 256
+
+typedef struct _sprintf
+{
+ t_object x_ob;
+ int x_nslots;
+ int x_nproxies; /* as requested (and allocated) */
+ t_pd **x_proxies;
+ int x_fsize; /* as allocated (i.e. including a terminating 0) */
+ char *x_fstring;
+} t_sprintf;
+
+typedef struct _sprintf_proxy
+{
+ t_object p_ob;
+ t_sprintf *p_master;
+ int p_id;
+ int p_type; /* a value #defined above */
+ char *p_pattern;
+ char *p_pattend;
+ t_atom p_atom; /* current input */
+ int p_size; /* also an input validation flag */
+} t_sprintf_proxy;
+
+static t_class *sprintf_class;
+static t_class *sprintf_proxy_class;
+
+/* CHECKED: 'symout' argument has no special meaning in max4.07,
+ LATER investigate */
+
+/* LATER use snprintf, if it is available on other systems (should be...) */
+static void sprintf_proxy_checkit(t_sprintf_proxy *x, char *buf, int checkin)
+{
+ int result = 0;
+ char *pattend = x->p_pattend;
+ if (pattend)
+ {
+ char tmp = *pattend;
+ *pattend = 0;
+ if (x->p_atom.a_type == A_FLOAT)
+ {
+ t_float f = x->p_atom.a_w.w_float;
+ if (x->p_type == SPRINTF_INT)
+ /* CHECKME large/negative values */
+ result = sprintf(buf, x->p_pattern, (int)f);
+ else if (x->p_type == SPRINTF_FLOAT)
+ result = sprintf(buf, x->p_pattern, f);
+ else if (x->p_type == SPRINTF_CHAR)
+ /* CHECKED: if 0 is input into a %c-slot, the whole output
+ string is null-terminated */
+ /* CHECKED: float into a %c-slot is truncated,
+ but CHECKME large/negative values */
+ result = sprintf(buf, x->p_pattern, (unsigned char)f);
+ else if (x->p_type == SPRINTF_STRING)
+ {
+ /* CHECKED: any number input into a %s-slot is ok */
+ char tmp[64]; /* LATER rethink */
+ sprintf(tmp, "%g", f);
+ result = sprintf(buf, x->p_pattern, tmp);
+ }
+ else /* LATER consider calling it a bug(), rather than error? */
+ loud_error((t_pd *)x->p_master,
+ "can't convert float to type of argument %d",
+ x->p_id + 1);
+ }
+ else if (x->p_atom.a_type == A_SYMBOL)
+ {
+ t_symbol *s = x->p_atom.a_w.w_symbol;
+ if (x->p_type == SPRINTF_STRING)
+ {
+ if (strlen(s->s_name) > SPRINTF_MAXWIDTH)
+ {
+ strncpy(buf, s->s_name, SPRINTF_MAXWIDTH);
+ buf[SPRINTF_MAXWIDTH] = 0;
+ result = SPRINTF_MAXWIDTH;
+ }
+ else result = sprintf(buf, x->p_pattern, s->s_name);
+ }
+ else /* CHECKED */
+ loud_error((t_pd *)x->p_master,
+ "can't convert symbol to type of argument %d",
+ x->p_id + 1);
+ }
+ *pattend = tmp;
+ }
+ else bug("sprintf_proxy_checkit");
+ if (result > 0)
+ {
+#if SPRINTF_DEBUG
+ if (checkin) post("[%d in \"%s\"]", result, buf);
+#endif
+ x->p_size = result;
+ }
+ else
+ {
+#if SPRINTF_DEBUG
+ if (checkin) post("checkit failed");
+#endif
+ x->p_size = 0;
+ }
+}
+
+static void sprintf_dooutput(t_sprintf *x)
+{
+ int i, outsize;
+ char *outstring;
+ outsize = x->x_fsize; /* this is strlen() + 1 */
+ /* LATER consider subtracting format pattern sizes */
+ for (i = 0; i < x->x_nslots; i++)
+ {
+ t_sprintf_proxy *y = (t_sprintf_proxy *)x->x_proxies[i];
+ if (y->p_size)
+ outsize += y->p_size;
+ else
+ {
+ /* slot i has received an invalid input -- CHECKME if this
+ condition blocks all subsequent output requests? */
+ return;
+ }
+ }
+ if (outsize > 0 && (outstring = getbytes(outsize)))
+ {
+ char *inp = x->x_fstring;
+ char *outp = outstring;
+ for (i = 0; i < x->x_nslots; i++)
+ {
+ t_sprintf_proxy *y = (t_sprintf_proxy *)x->x_proxies[i];
+ int len = y->p_pattern - inp;
+ if (len > 0)
+ {
+ strncpy(outp, inp, len);
+ outp += len;
+ }
+ sprintf_proxy_checkit(y, outp, 0);
+ outp += y->p_size; /* p_size is never negative */
+ inp = y->p_pattend;
+ }
+ strcpy(outp, inp);
+
+ outp = outstring;
+ while (*outp == ' ' || *outp == '\t'
+ || *outp == '\n' || *outp == '\r') outp++;
+ if (*outp)
+ {
+ t_binbuf *bb = binbuf_new();
+ int ac;
+ t_atom *av;
+ binbuf_text(bb, outp, strlen(outp));
+ ac = binbuf_getnatom(bb);
+ av = binbuf_getvec(bb);
+ if (ac)
+ {
+ if (av->a_type == A_SYMBOL)
+ outlet_anything(((t_object *)x)->ob_outlet,
+ av->a_w.w_symbol, ac - 1, av + 1);
+ else if (av->a_type == A_FLOAT)
+ {
+ if (ac > 1)
+ outlet_list(((t_object *)x)->ob_outlet,
+ &s_list, ac, av);
+ else
+ outlet_float(((t_object *)x)->ob_outlet,
+ av->a_w.w_float);
+ }
+ }
+ binbuf_free(bb);
+ }
+ freebytes(outstring, outsize);
+ }
+}
+
+static void sprintf_proxy_bang(t_sprintf_proxy *x)
+{
+ sprintf_dooutput(x->p_master); /* CHECKED (in any inlet) */
+}
+
+static void sprintf_proxy_float(t_sprintf_proxy *x, t_float f)
+{
+ char buf[SPRINTF_MAXWIDTH + 1]; /* LATER rethink */
+ SETFLOAT(&x->p_atom, f);
+ sprintf_proxy_checkit(x, buf, 1);
+ if (x->p_id == 0 && x->p_size)
+ sprintf_dooutput(x->p_master); /* CHECKED: only first inlet */
+}
+
+static void sprintf_proxy_symbol(t_sprintf_proxy *x, t_symbol *s)
+{
+ char buf[SPRINTF_MAXWIDTH + 1]; /* LATER rethink */
+ if (s && *s->s_name)
+ SETSYMBOL(&x->p_atom, s);
+ else
+ SETFLOAT(&x->p_atom, 0);
+ sprintf_proxy_checkit(x, buf, 1);
+ if (x->p_id == 0 && x->p_size)
+ sprintf_dooutput(x->p_master); /* CHECKED: only first inlet */
+}
+
+static void sprintf_dolist(t_sprintf *x,
+ t_symbol *s, int ac, t_atom *av, int startid)
+{
+ int cnt = x->x_nslots - startid;
+ if (ac > cnt)
+ ac = cnt;
+ if (ac-- > 0)
+ {
+ int id;
+ for (id = startid + ac, av += ac; id >= startid; id--, av--)
+ {
+ if (av->a_type == A_FLOAT)
+ sprintf_proxy_float((t_sprintf_proxy *)x->x_proxies[id],
+ av->a_w.w_float);
+ else if (av->a_type == A_SYMBOL)
+ sprintf_proxy_symbol((t_sprintf_proxy *)x->x_proxies[id],
+ av->a_w.w_symbol);
+ }
+ }
+}
+
+static void sprintf_doanything(t_sprintf *x,
+ t_symbol *s, int ac, t_atom *av, int startid)
+{
+ if (s && s != &s_)
+ {
+ sprintf_dolist(x, 0, ac, av, startid + 1);
+ sprintf_proxy_symbol((t_sprintf_proxy *)x->x_proxies[startid], s);
+ }
+ else sprintf_dolist(x, 0, ac, av, startid);
+}
+
+static void sprintf_proxy_list(t_sprintf_proxy *x,
+ t_symbol *s, int ac, t_atom *av)
+{
+ sprintf_dolist(x->p_master, s, ac, av, x->p_id);
+}
+
+static void sprintf_proxy_anything(t_sprintf_proxy *x,
+ t_symbol *s, int ac, t_atom *av)
+{
+ sprintf_doanything(x->p_master, s, ac, av, x->p_id);
+}
+
+static void sprintf_bang(t_sprintf *x)
+{
+ if (x->x_nslots)
+ sprintf_proxy_bang((t_sprintf_proxy *)x->x_proxies[0]);
+}
+
+static void sprintf_float(t_sprintf *x, t_float f)
+{
+ if (x->x_nslots)
+ sprintf_proxy_float((t_sprintf_proxy *)x->x_proxies[0], f);
+}
+
+static void sprintf_symbol(t_sprintf *x, t_symbol *s)
+{
+ if (x->x_nslots)
+ sprintf_proxy_symbol((t_sprintf_proxy *)x->x_proxies[0], s);
+}
+
+static void sprintf_list(t_sprintf *x, t_symbol *s, int ac, t_atom *av)
+{
+ if (x->x_nslots)
+ sprintf_dolist(x, s, ac, av, 0);
+}
+
+static void sprintf_anything(t_sprintf *x, t_symbol *s, int ac, t_atom *av)
+{
+ if (x->x_nslots)
+ sprintf_doanything(x, s, ac, av, 0);
+}
+
+/* adjusted binbuf_gettext(), LATER do it right */
+static char *hammer_gettext(int ac, t_atom *av, int *sizep)
+{
+ char *buf = getbytes(1);
+ int size = 1;
+ char atomtext[MAXPDSTRING];
+ while (ac--)
+ {
+ char *newbuf;
+ int newsize;
+ if (buf[size-1] == 0 || av->a_type == A_SEMI || av->a_type == A_COMMA)
+ size--;
+ atom_string(av, atomtext, MAXPDSTRING);
+ newsize = size + strlen(atomtext) + 1;
+ if (!(newbuf = resizebytes(buf, size, newsize)))
+ {
+ *sizep = 1;
+ return (getbytes(1));
+ }
+ buf = newbuf;
+ strcpy(buf + size, atomtext);
+ size = newsize;
+ buf[size-1] = ' ';
+ av++;
+ }
+ buf[size-1] = 0;
+ *sizep = size;
+ return (buf);
+}
+
+/* Called twice: 1st pass (with x == 0) is used for counting valid patterns;
+ 2nd pass (after object allocation) -- for initializing the proxies.
+ If there is a "%%" pattern, then the buffer is shrinked in the second pass
+ (LATER rethink). */
+static int sprintf_parsepattern(t_sprintf *x, char **patternp)
+{
+ int type = SPRINTF_UNSUPPORTED;
+ char errstring[MAXPDSTRING];
+ char *ptr;
+ char modifier = 0;
+ int width = 0;
+ int precision = 0;
+ int *numfield = &width;
+ int dotseen = 0;
+ *errstring = 0;
+ for (ptr = *patternp; *ptr; ptr++)
+ {
+ if (*ptr >= '0' && *ptr <= '9')
+ {
+ if (!numfield)
+ {
+ if (x) sprintf(errstring, "extra number field");
+ break;
+ }
+ *numfield = 10 * *numfield + *ptr - '0';
+ if (dotseen)
+ {
+ if (precision > SPRINTF_MAXPRECISION)
+ {
+ if (x) sprintf(errstring, "precision field too large");
+ break;
+ }
+ }
+ else
+ {
+ if (width > SPRINTF_MAXWIDTH)
+ {
+ if (x) sprintf(errstring, "width field too large");
+ break;
+ }
+ }
+ continue;
+ }
+ if (*numfield)
+ numfield = 0;
+
+ if (strchr("diouxX", *ptr))
+ {
+ type = SPRINTF_INT;
+ break;
+ }
+ else if (strchr("aAeEfgG", *ptr))
+ {
+ if (modifier)
+ {
+ if (x) sprintf(errstring,
+ "\'%c\' modifier not supported", modifier);
+ break;
+ }
+ type = SPRINTF_FLOAT;
+ break;
+ }
+ else if (strchr("c", *ptr))
+ {
+ if (modifier)
+ {
+ if (x) sprintf(errstring,
+ "\'%c\' modifier not supported", modifier);
+ break;
+ }
+ type = SPRINTF_CHAR;
+ break;
+ }
+ else if (strchr("s", *ptr))
+ {
+ if (modifier)
+ {
+ if (x) sprintf(errstring,
+ "\'%c\' modifier not supported", modifier);
+ break;
+ }
+ type = SPRINTF_STRING;
+ break;
+ }
+ else if (*ptr == '%')
+ {
+ type = SPRINTF_LITERAL;
+ if (x)
+ { /* buffer-shrinking hack, LATER rethink */
+ char *p1 = ptr, *p2 = ptr + 1;
+ do
+ *p1++ = *p2;
+ while (*p2++);
+ ptr--;
+ }
+ break;
+ }
+ else if (strchr("CSnm", *ptr))
+ {
+ if (x) sprintf(errstring, "\'%c\' type not supported", *ptr);
+ break;
+ }
+ else if (strchr("l", *ptr))
+ {
+ if (modifier)
+ {
+ if (x) sprintf(errstring, "only single modifier is supported");
+ break;
+ }
+ modifier = *ptr;
+ }
+ else if (strchr("hjLqtzZ", *ptr))
+ {
+ if (x) sprintf(errstring, "\'%c\' modifier not supported", *ptr);
+ break;
+ }
+ else if (*ptr == '.')
+ {
+ if (dotseen)
+ {
+ if (x) sprintf(errstring, "multiple dots");
+ break;
+ }
+ numfield = &precision;
+ dotseen = 1;
+ }
+ else if (*ptr == '$')
+ {
+ if (x) sprintf(errstring, "parameter number field not supported");
+ break;
+ }
+ else if (*ptr == '*')
+ {
+ if (x) sprintf(errstring, "%s parameter not supported",
+ (dotseen ? "precision" : "width"));
+ break;
+ }
+ else if (!strchr("-+ #\'", *ptr))
+ {
+ if (x) sprintf(errstring,
+ "\'%c\' format character not supported", *ptr);
+ break;
+ }
+ }
+ if (*ptr)
+ ptr++; /* LATER rethink */
+ else
+ if (x) sprintf(errstring, "type not specified");
+ if (x && type == SPRINTF_UNSUPPORTED)
+ {
+ if (*errstring)
+ loud_error((t_pd *)x, "slot skipped (%s %s)",
+ errstring, "in a format pattern");
+ else
+ loud_error((t_pd *)x, "slot skipped");
+ }
+ *patternp = ptr;
+ return (type);
+}
+
+static void sprintf_free(t_sprintf *x)
+{
+ if (x->x_proxies)
+ {
+ int i = x->x_nslots;
+ while (i--)
+ {
+ t_sprintf_proxy *y = (t_sprintf_proxy *)x->x_proxies[i];
+ pd_free((t_pd *)y);
+ }
+ freebytes(x->x_proxies, x->x_nproxies * sizeof(*x->x_proxies));
+ }
+ if (x->x_fstring)
+ freebytes(x->x_fstring, x->x_fsize);
+}
+
+static void *sprintf_new(t_symbol *s, int ac, t_atom *av)
+{
+ t_sprintf *x;
+ int fsize;
+ char *fstring;
+ char *p1, *p2;
+ int i, nslots, nproxies = 0;
+ t_pd **proxies;
+ fstring = hammer_gettext(ac, av, &fsize);
+ p1 = fstring;
+ while (p2 = strchr(p1, '%'))
+ {
+ int type;
+ p1 = p2 + 1;
+ type = sprintf_parsepattern(0, &p1);
+ if (type >= SPRINTF_MINSLOTTYPE)
+ nproxies++;
+ }
+ if (!nproxies)
+ {
+ /* CHECKED: an object without arguments, if created in the editor,
+ has no inlets/outlets, but it would have one inlet (no outlets)
+ upon loading. Error message is printed in either case. */
+ x = (t_sprintf *)pd_new(sprintf_class);
+ x->x_nslots = 0;
+ x->x_nproxies = 0;
+ x->x_proxies = 0;
+ x->x_fsize = fsize;
+ x->x_fstring = fstring;
+ p1 = fstring;
+ while (p2 = strchr(p1, '%'))
+ {
+ p1 = p2 + 1;
+ sprintf_parsepattern(x, &p1);
+ }
+ loud_error((t_pd *)x,
+ "an object created without valid format patterns...");
+ return (x);
+ }
+#if SPRINTF_DEBUG
+ post("%d slots:", nproxies);
+#endif
+ /* CHECKED: max creates as many inlets, as there are %-signs, no matter
+ if they are valid, or not -- if not, it prints ``can't convert'' errors
+ for any input... */
+ if (!(proxies = (t_pd **)getbytes(nproxies * sizeof(*proxies))))
+ {
+ freebytes(fstring, fsize);
+ return (0);
+ }
+ for (nslots = 0; nslots < nproxies; nslots++)
+ if (!(proxies[nslots] = pd_new(sprintf_proxy_class))) break;
+ if (!nslots)
+ {
+ freebytes(fstring, fsize);
+ freebytes(proxies, nproxies * sizeof(*proxies));
+ return (0);
+ }
+ x = (t_sprintf *)pd_new(sprintf_class);
+ x->x_nslots = nslots;
+ x->x_nproxies = nproxies;
+ x->x_proxies = proxies;
+ x->x_fsize = fsize;
+ x->x_fstring = fstring;
+ p1 = fstring;
+ i = 0;
+ while (p2 = strchr(p1, '%'))
+ {
+ int type;
+ p1 = p2 + 1;
+ type = sprintf_parsepattern(x, &p1);
+ if (type >= SPRINTF_MINSLOTTYPE)
+ {
+#if SPRINTF_DEBUG
+ char tmp = *++p1;
+ *p1 = 0;
+ poststring(p2);
+ endpost();
+ *p1 = tmp;
+#endif
+ if (i < nslots)
+ {
+ char buf[SPRINTF_MAXWIDTH + 1]; /* LATER rethink */
+ t_sprintf_proxy *y = (t_sprintf_proxy *)proxies[i];
+ y->p_master = x;
+ y->p_id = i;
+ y->p_type = type;
+ y->p_pattern = p2;
+ y->p_pattend = p1;
+ SETFLOAT(&y->p_atom, 0);
+ y->p_size = 0;
+ if (i) inlet_new((t_object *)x, (t_pd *)y, 0, 0);
+ sprintf_proxy_checkit(y, buf, 1);
+ i++;
+ }
+ }
+ }
+#if SPRINTF_DEBUG
+ post("printf(\"%s\", ...)", fstring);
+#endif
+ outlet_new((t_object *)x, &s_anything);
+ return (x);
+}
+
+void sprintf_setup(void)
+{
+ sprintf_class = class_new(gensym("sprintf"),
+ (t_newmethod)sprintf_new,
+ (t_method)sprintf_free,
+ sizeof(t_sprintf), 0, A_GIMME, 0);
+ class_addbang(sprintf_class, sprintf_bang);
+ class_addfloat(sprintf_class, sprintf_float);
+ class_addsymbol(sprintf_class, sprintf_symbol);
+ class_addlist(sprintf_class, sprintf_list);
+ class_addanything(sprintf_class, sprintf_anything);
+ sprintf_proxy_class = class_new(gensym("_sprintf_proxy"), 0, 0,
+ sizeof(t_sprintf_proxy),
+ CLASS_PD | CLASS_NOINLET, 0);
+ class_addbang(sprintf_proxy_class, sprintf_proxy_bang);
+ class_addfloat(sprintf_proxy_class, sprintf_proxy_float);
+ class_addsymbol(sprintf_proxy_class, sprintf_proxy_symbol);
+ class_addlist(sprintf_proxy_class, sprintf_proxy_list);
+ class_addanything(sprintf_proxy_class, sprintf_proxy_anything);
+}
diff --git a/cyclone/hammer/substitute.c b/cyclone/hammer/substitute.c
new file mode 100644
index 0000000..48a9b9d
--- /dev/null
+++ b/cyclone/hammer/substitute.c
@@ -0,0 +1,340 @@
+/* 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"
+
+#define SUBSTITUTE_INISIZE 32 /* LATER rethink */
+#define SUBSTITUTE_MAXSIZE 256
+
+typedef struct _substitute
+{
+ t_object x_ob;
+ t_pd *x_proxy;
+ t_atom x_match;
+ t_atom x_repl;
+ int x_size; /* as allocated */
+ t_atom *x_message;
+ t_atom x_messini[SUBSTITUTE_INISIZE];
+ int x_entered;
+ t_atom x_auxmatch;
+ t_atom x_auxrepl;
+ t_outlet *x_passout;
+} t_substitute;
+
+typedef struct _substitute_proxy
+{
+ t_object p_ob;
+ t_atom *p_match; /* pointing to parent's (aux)match */
+ t_atom *p_repl;
+} t_substitute_proxy;
+
+static t_class *substitute_class;
+static t_class *substitute_proxy_class;
+
+/* LATER rethink */
+static void substitute_dooutput(t_substitute *x,
+ t_symbol *s, int ac, t_atom *av, int pass)
+{
+ t_outlet *out = (pass ? x->x_passout : ((t_object *)x)->ob_outlet);
+ if (s == &s_float)
+ {
+ if (ac > 1)
+ outlet_list(out, &s_list, ac, av);
+ else
+ outlet_float(out, av->a_w.w_float);
+ }
+ else if (s == &s_bang && !ac) /* CHECKED */
+ outlet_bang(out);
+ else if (s == &s_symbol && ac == 1 && av->a_type == A_SYMBOL)
+ outlet_symbol(out, av->a_w.w_symbol);
+ else if (s)
+ outlet_anything(out, s, ac, av);
+ else if (ac)
+ outlet_list(out, &s_list, ac, av);
+}
+
+static int substitute_check(t_substitute *x, t_symbol *s, int ac, t_atom *av)
+{
+ if (x->x_repl.a_type == A_NULL)
+ return (-2);
+ /* see substitute_proxy_validate() for possible types and values */
+ if (x->x_match.a_type == A_FLOAT)
+ {
+ t_float f = x->x_match.a_w.w_float;
+ int i;
+ for (i = 0; i < ac; i++, av++)
+ if (av->a_type == A_FLOAT && av->a_w.w_float == f)
+ return (i);
+ }
+ else if (x->x_match.a_type == A_SYMBOL)
+ {
+ /* match symbol is validated -- never null */
+ t_symbol *match = x->x_match.a_w.w_symbol;
+ int i;
+ if (s == match)
+ return (-1);
+ for (i = 0; i < ac; i++, av++)
+ if (av->a_type == A_SYMBOL && av->a_w.w_symbol == match)
+ return (i);
+ }
+ return (-2);
+}
+
+static void substitute_doit(t_substitute *x,
+ t_symbol *s, int ac, t_atom *av, int startndx)
+{
+ int cnt = ac - startndx;
+ if (cnt > 0)
+ {
+ t_atom *ap = av + startndx;
+ if (x->x_match.a_type == A_FLOAT)
+ {
+ t_float f = x->x_match.a_w.w_float;
+ while (cnt--)
+ {
+ if (ap->a_type == A_FLOAT && ap->a_w.w_float == f)
+ *ap = x->x_repl;
+ ap++;
+ }
+ }
+ else if (x->x_match.a_type == A_SYMBOL)
+ {
+ t_symbol *match = x->x_match.a_w.w_symbol;
+ while (cnt--)
+ {
+ if (ap->a_type == A_SYMBOL && ap->a_w.w_symbol == match)
+ *ap = x->x_repl;
+ ap++;
+ }
+ }
+ }
+ substitute_dooutput(x, s, ac, av, 0);
+}
+
+static void substitute_anything(t_substitute *x,
+ t_symbol *s, int ac, t_atom *av)
+{
+ int matchndx = substitute_check(x, s, ac, av);
+ if (matchndx < -1)
+ substitute_dooutput(x, s, ac, av, 1);
+ else
+ {
+ int reentered = x->x_entered;
+ int prealloc = !reentered;
+ int ntotal = ac;
+ t_atom *buf;
+ t_substitute_proxy *proxy = (t_substitute_proxy *)x->x_proxy;
+ x->x_entered = 1;
+ proxy->p_match = &x->x_auxmatch;
+ proxy->p_repl = &x->x_auxrepl;
+ if (s == &s_) s = 0;
+ if (matchndx == -1)
+ {
+ if (x->x_repl.a_type == A_FLOAT)
+ {
+ ntotal++;
+ if (ac) s = &s_list;
+ else s = &s_float;
+ }
+ else if (x->x_repl.a_type == A_SYMBOL)
+ {
+ s = x->x_repl.a_w.w_symbol;
+ matchndx = 0;
+ }
+ }
+ else if (matchndx == 0
+ && (!s || s == &s_list || s == &s_float)
+ && av->a_type == A_FLOAT
+ && x->x_repl.a_type == A_SYMBOL)
+ {
+ s = x->x_repl.a_w.w_symbol;
+ ac--;
+ av++;
+ ntotal = ac;
+ }
+ if (prealloc && ac > x->x_size)
+ {
+ if (ntotal > SUBSTITUTE_MAXSIZE)
+ prealloc = 0;
+ else
+ x->x_message = grow_nodata(&ntotal, &x->x_size, x->x_message,
+ SUBSTITUTE_INISIZE, x->x_messini,
+ sizeof(*x->x_message));
+ }
+ if (prealloc) buf = x->x_message;
+ else
+ /* LATER consider using the stack if ntotal <= MAXSTACK */
+ buf = getbytes(ntotal * sizeof(*buf));
+ if (buf)
+ {
+ int ncopy = ntotal;
+ t_atom *bp = buf;
+ if (matchndx == -1)
+ {
+ SETFLOAT(bp++, x->x_repl.a_w.w_float);
+ ncopy--;
+ }
+ if (ncopy)
+ memcpy(bp, av, ncopy * sizeof(*buf));
+ substitute_doit(x, s, ntotal, buf, matchndx);
+ if (buf != x->x_message)
+ freebytes(buf, ntotal * sizeof(*buf));
+ }
+ if (!reentered)
+ {
+ x->x_entered = 0;
+ if (x->x_auxmatch.a_type != A_NULL)
+ {
+ x->x_match = x->x_auxmatch;
+ x->x_auxmatch.a_type = A_NULL;
+ }
+ if (x->x_auxrepl.a_type != A_NULL)
+ {
+ x->x_repl = x->x_auxrepl;
+ x->x_auxrepl.a_type = A_NULL;
+ }
+ proxy->p_match = &x->x_match;
+ proxy->p_repl = &x->x_repl;
+ }
+ }
+}
+
+static void substitute_bang(t_substitute *x)
+{
+ substitute_anything(x, &s_bang, 0, 0);
+}
+
+static void substitute_float(t_substitute *x, t_float f)
+{
+ t_atom at;
+ SETFLOAT(&at, f);
+ substitute_anything(x, 0, 1, &at);
+}
+
+/* CHECKED (but LATER rethink) */
+static void substitute_symbol(t_substitute *x, t_symbol *s)
+{
+ t_atom at;
+ SETSYMBOL(&at, s);
+ substitute_anything(x, &s_symbol, 1, &at);
+}
+
+/* LATER gpointer */
+
+static void substitute_list(t_substitute *x, t_symbol *s, int ac, t_atom *av)
+{
+ substitute_anything(x, 0, ac, av);
+}
+
+static int substitute_atomvalidate(t_atom *ap)
+{
+ return (ap->a_type == A_FLOAT
+ || (ap->a_type == A_SYMBOL
+ && ap->a_w.w_symbol && ap->a_w.w_symbol != &s_));
+}
+
+/* CHECKED: 'set' is ignored, single '<atom>' does not modify a replacement */
+static void substitute_proxy_anything(t_substitute_proxy *x,
+ t_symbol *s, int ac, t_atom *av)
+{
+ if (s == &s_) s = 0;
+ if (s)
+ {
+ SETSYMBOL(x->p_match, s);
+ if (ac && substitute_atomvalidate(av))
+ *x->p_repl = *av;
+ }
+ else if (ac && substitute_atomvalidate(av))
+ {
+ *x->p_match = *av++;
+ if (ac > 1 && substitute_atomvalidate(av))
+ *x->p_repl = *av;
+ }
+}
+
+static void substitute_proxy_bang(t_substitute_proxy *x)
+{
+ SETSYMBOL(x->p_match, &s_bang);
+}
+
+static void substitute_proxy_float(t_substitute_proxy *x, t_float f)
+{
+ SETFLOAT(x->p_match, f);
+}
+
+/* CHECKED (but LATER rethink) */
+static void substitute_proxy_symbol(t_substitute_proxy *x, t_symbol *s)
+{
+ SETSYMBOL(x->p_match, &s_symbol);
+ SETSYMBOL(x->p_repl, s);
+}
+
+/* LATER gpointer */
+
+static void substitute_proxy_list(t_substitute_proxy *x,
+ t_symbol *s, int ac, t_atom *av)
+{
+ substitute_proxy_anything(x, 0, ac, av);
+}
+
+static void substitute_free(t_substitute *x)
+{
+ if (x->x_proxy) pd_free(x->x_proxy);
+ if (x->x_message != x->x_messini)
+ freebytes(x->x_message, x->x_size * sizeof(*x->x_message));
+}
+
+static void *substitute_new(t_symbol *s, int ac, t_atom *av)
+{
+ t_substitute *x = 0;
+ t_substitute_proxy *proxy =
+ (t_substitute_proxy *)pd_new(substitute_proxy_class);
+ if (proxy)
+ {
+ x = (t_substitute *)pd_new(substitute_class);
+ proxy->p_match = &x->x_match;
+ proxy->p_repl = &x->x_repl;
+ x->x_proxy = (t_pd *)proxy;
+ x->x_size = SUBSTITUTE_INISIZE;
+ x->x_message = x->x_messini;
+ x->x_entered = 0;
+ /* CHECKED: everything is to be passed unchanged, until both are set */
+ /* CHECKED: max crashes if a match has been set, but not a replacement,
+ and there is a match */
+ x->x_match.a_type = x->x_repl.a_type = A_NULL;
+ x->x_auxmatch.a_type = x->x_auxrepl.a_type = A_NULL;
+ inlet_new((t_object *)x, (t_pd *)proxy, 0, 0);
+ outlet_new((t_object *)x, &s_anything);
+ /* CHECKED (refman error: 'a bang is sent') */
+ x->x_passout = outlet_new((t_object *)x, &s_anything);
+ substitute_proxy_anything(proxy, 0, ac, av);
+ }
+ return (x);
+}
+
+void substitute_setup(void)
+{
+ substitute_class = class_new(gensym("substitute"),
+ (t_newmethod)substitute_new,
+ (t_method)substitute_free,
+ sizeof(t_substitute), 0,
+ A_GIMME, 0);
+ class_addbang(substitute_class, substitute_bang);
+ class_addfloat(substitute_class, substitute_float);
+ class_addsymbol(substitute_class, substitute_symbol);
+ class_addlist(substitute_class, substitute_list);
+ class_addanything(substitute_class, substitute_anything);
+ substitute_proxy_class = class_new(gensym("_substitute_proxy"), 0, 0,
+ sizeof(t_substitute_proxy),
+ CLASS_PD | CLASS_NOINLET, 0);
+ class_addbang(substitute_proxy_class, substitute_proxy_bang);
+ class_addfloat(substitute_proxy_class, substitute_proxy_float);
+ class_addsymbol(substitute_proxy_class, substitute_proxy_symbol);
+ class_addlist(substitute_proxy_class, substitute_proxy_list);
+ class_addanything(substitute_proxy_class, substitute_proxy_anything);
+ class_addmethod(substitute_proxy_class, (t_method)substitute_proxy_list,
+ gensym("set"), A_GIMME, 0);
+}
diff --git a/cyclone/hammer/sustain.c b/cyclone/hammer/sustain.c
new file mode 100644
index 0000000..975e6aa
--- /dev/null
+++ b/cyclone/hammer/sustain.c
@@ -0,0 +1,85 @@
+/* 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"
+
+#define SUSTAIN_NPITCHES 128
+
+typedef struct _sustain
+{
+ t_object x_ob;
+ t_float x_velocity;
+ int x_switch;
+ unsigned char x_pitches[SUSTAIN_NPITCHES];
+ t_outlet *x_voutlet;
+} t_sustain;
+
+static t_class *sustain_class;
+
+static void sustain_float(t_sustain *x, t_float f)
+{
+ int pitch = (int)f;
+ if (pitch >= 0 && pitch < SUSTAIN_NPITCHES)
+ {
+ if (x->x_velocity || !x->x_switch)
+ {
+ outlet_float(x->x_voutlet, x->x_velocity);
+ outlet_float(((t_object *)x)->ob_outlet, pitch);
+ }
+ else x->x_pitches[pitch]++;
+ }
+}
+
+static void sustain_bang(t_sustain *x)
+{
+ int i;
+ unsigned char *pp;
+ for (i = 0, pp = x->x_pitches; i < SUSTAIN_NPITCHES; i++, pp++)
+ {
+ while (*pp)
+ {
+ outlet_float(x->x_voutlet, 0);
+ outlet_float(((t_object *)x)->ob_outlet, i);
+ (*pp)--;
+ }
+ }
+}
+
+static void sustain_clear(t_sustain *x)
+{
+ memset(x->x_pitches, 0, sizeof(x->x_pitches));
+}
+
+static void sustain_ft2(t_sustain *x, t_floatarg f)
+{
+ int newstate = ((int)f != 0);
+ if (x->x_switch && !newstate) sustain_bang(x);
+ x->x_switch = newstate;
+}
+
+static void *sustain_new(void)
+{
+ t_sustain *x = (t_sustain *)pd_new(sustain_class);
+ x->x_velocity = 0;
+ x->x_switch = 0;
+ sustain_clear(x);
+ floatinlet_new((t_object *)x, &x->x_velocity);
+ inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft2"));
+ outlet_new((t_object *)x, &s_float);
+ x->x_voutlet = outlet_new((t_object *)x, &s_float);
+ return (x);
+}
+
+void sustain_setup(void)
+{
+ sustain_class = class_new(gensym("sustain"),
+ (t_newmethod)sustain_new,
+ 0, /* CHECKED: no flushout */
+ sizeof(t_sustain), 0, 0);
+ class_addfloat(sustain_class, sustain_float);
+ class_addbang(sustain_class, sustain_bang);
+ class_addmethod(sustain_class, (t_method)sustain_ft2,
+ gensym("ft2"), A_FLOAT, 0);
+}
diff --git a/cyclone/hammer/switch.c b/cyclone/hammer/switch.c
new file mode 100644
index 0000000..69317a1
--- /dev/null
+++ b/cyclone/hammer/switch.c
@@ -0,0 +1,152 @@
+/* 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/loud.h"
+
+#define SWITCH_MININLETS 2 /* LATER consider using 1 (with a warning) */
+#define SWITCH_MAXINLETS 100
+#define SWITCH_DEFINLETS 2
+
+typedef struct _switch
+{
+ t_object x_ob;
+ int x_open;
+ int x_ninlets; /* not counting left one */
+ int x_nproxies; /* as requested (and allocated) */
+ t_pd **x_proxies;
+} t_switch;
+
+typedef struct _switch_proxy
+{
+ t_object p_ob;
+ t_switch *p_master;
+ int p_id;
+} t_switch_proxy;
+
+static t_class *switch_class;
+static t_class *switch_proxy_class;
+
+static void switch_proxy_bang(t_switch_proxy *x)
+{
+ t_switch *master = x->p_master;
+ if (master->x_open == x->p_id)
+ outlet_bang(((t_object *)master)->ob_outlet);
+}
+
+static void switch_proxy_float(t_switch_proxy *x, t_float f)
+{
+ t_switch *master = x->p_master;
+ if (master->x_open == x->p_id)
+ outlet_float(((t_object *)master)->ob_outlet, f);
+}
+
+static void switch_proxy_symbol(t_switch_proxy *x, t_symbol *s)
+{
+ t_switch *master = x->p_master;
+ if (master->x_open == x->p_id)
+ outlet_symbol(((t_object *)master)->ob_outlet, s);
+}
+
+static void switch_proxy_pointer(t_switch_proxy *x, t_gpointer *gp)
+{
+ t_switch *master = x->p_master;
+ if (master->x_open == x->p_id)
+ outlet_pointer(((t_object *)master)->ob_outlet, gp);
+}
+
+static void switch_proxy_list(t_switch_proxy *x,
+ t_symbol *s, int ac, t_atom *av)
+{
+ t_switch *master = x->p_master;
+ if (master->x_open == x->p_id)
+ outlet_list(((t_object *)master)->ob_outlet, s, ac, av);
+}
+
+static void switch_proxy_anything(t_switch_proxy *x,
+ t_symbol *s, int ac, t_atom *av)
+{
+ t_switch *master = x->p_master;
+ if (master->x_open == x->p_id)
+ outlet_anything(((t_object *)master)->ob_outlet, s, ac, av);
+}
+
+static void switch_float(t_switch *x, t_float f)
+{
+ int i = (int)f;
+ if (i < 0) i = -i;
+ if (i > x->x_ninlets) i = x->x_ninlets;
+ x->x_open = i;
+}
+
+static void switch_bang(t_switch *x)
+{
+ outlet_float(((t_object *)x)->ob_outlet, x->x_open);
+}
+
+static void switch_free(t_switch *x)
+{
+ if (x->x_proxies)
+ {
+ int i = x->x_ninlets;
+ while (i--) pd_free(x->x_proxies[i]);
+ freebytes(x->x_proxies, x->x_nproxies * sizeof(*x->x_proxies));
+ }
+}
+
+static void *switch_new(t_floatarg f1, t_floatarg f2)
+{
+ t_switch *x;
+ int i, ninlets, nproxies = (int)f1;
+ t_pd **proxies;
+ if (nproxies < SWITCH_MININLETS)
+ nproxies = SWITCH_DEFINLETS;
+ if (nproxies > SWITCH_MAXINLETS)
+ loud_incompatible_max(switch_class, SWITCH_MAXINLETS, "inlets");
+ if (!(proxies = (t_pd **)getbytes(nproxies * sizeof(*proxies))))
+ return (0);
+ for (ninlets = 0; ninlets < nproxies; ninlets++)
+ if (!(proxies[ninlets] = pd_new(switch_proxy_class))) break;
+ if (ninlets < SWITCH_MININLETS)
+ {
+ int i = ninlets;
+ while (i--) pd_free(proxies[i]);
+ freebytes(proxies, nproxies * sizeof(*proxies));
+ return (0);
+ }
+ x = (t_switch *)pd_new(switch_class);
+ x->x_ninlets = ninlets;
+ x->x_nproxies = nproxies;
+ x->x_proxies = proxies;
+ for (i = 0; i < ninlets; i++)
+ {
+ t_switch_proxy *y = (t_switch_proxy *)proxies[i];
+ y->p_master = x;
+ y->p_id = i + 1;
+ inlet_new((t_object *)x, (t_pd *)y, 0, 0);
+ }
+ outlet_new((t_object *)x, &s_anything);
+ switch_float(x, (f2 > 0 ? f2 : 0)); /* CHECKED */
+ return (x);
+}
+
+void switch_setup(void)
+{
+ switch_class = class_new(gensym("switch"),
+ (t_newmethod)switch_new,
+ (t_method)switch_free,
+ sizeof(t_switch), 0,
+ A_DEFFLOAT, A_DEFFLOAT, 0);
+ class_addfloat(switch_class, switch_float);
+ class_addbang(switch_class, switch_bang);
+ switch_proxy_class = class_new(gensym("_switch_proxy"), 0, 0,
+ sizeof(t_switch_proxy),
+ CLASS_PD | CLASS_NOINLET, 0);
+ class_addfloat(switch_proxy_class, switch_proxy_float);
+ class_addbang(switch_proxy_class, switch_proxy_bang);
+ class_addsymbol(switch_proxy_class, switch_proxy_symbol);
+ class_addpointer(switch_proxy_class, switch_proxy_pointer);
+ class_addlist(switch_proxy_class, switch_proxy_list);
+ class_addanything(switch_proxy_class, switch_proxy_anything);
+}
diff --git a/cyclone/hammer/tanh.c b/cyclone/hammer/tanh.c
new file mode 100644
index 0000000..e124d4c
--- /dev/null
+++ b/cyclone/hammer/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"
+
+#if defined(NT) || defined(MACOSX)
+/* cf pd/src/x_arithmetic.c */
+#define tanhf tanh
+#endif
+
+typedef struct _tanh
+{
+ t_object x_ob;
+ float x_value;
+} t_tanh;
+
+static t_class *tanh_class;
+
+static void tanh_bang(t_tanh *x)
+{
+ outlet_float(((t_object *)x)->ob_outlet, x->x_value);
+}
+
+static void tanh_float(t_tanh *x, t_float f)
+{
+ /* CHECKME large values */
+ outlet_float(((t_object *)x)->ob_outlet, x->x_value = tanhf(f));
+}
+
+static void *tanh_new(t_floatarg f)
+{
+ t_tanh *x = (t_tanh *)pd_new(tanh_class);
+ /* CHECKME large values */
+ x->x_value = tanhf(f);
+ outlet_new((t_object *)x, &s_float);
+ return (x);
+}
+
+void tanh_setup(void)
+{
+ tanh_class = class_new(gensym("tanh"),
+ (t_newmethod)tanh_new, 0,
+ sizeof(t_tanh), 0, A_DEFFLOAT, 0);
+ class_addbang(tanh_class, tanh_bang);
+ class_addfloat(tanh_class, tanh_float);
+}
diff --git a/cyclone/hammer/testmess.c b/cyclone/hammer/testmess.c
new file mode 100644
index 0000000..a6e8fe4
--- /dev/null
+++ b/cyclone/hammer/testmess.c
@@ -0,0 +1,245 @@
+/* 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"
+
+#define TESTMESS_INISIZE 4 /* LATER rethink */
+#define TESTMESS_STACKSIZE 256
+
+typedef struct _testmess
+{
+ t_object x_ob;
+ t_symbol *x_method;
+ void (*x_messfun)(struct _testmess *, t_symbol *s, int, t_atom *);
+ int x_appendmode;
+ int x_size; /* as allocated */
+ int x_natoms; /* as used */
+ int x_tailwise; /* data is moved to the end of a buffer */
+ t_atom *x_message;
+ t_atom *x_messbuf;
+ t_atom x_messini[TESTMESS_INISIZE];
+} t_testmess;
+
+static t_class *testmess_class;
+
+static void testmess_setnatoms(t_testmess *x, int natoms)
+{
+ if (x->x_tailwise)
+ x->x_message = x->x_messbuf + x->x_size - natoms;
+ else
+ x->x_message = x->x_messbuf;
+ x->x_natoms = natoms;
+}
+
+static int testmess_makeroom(t_testmess *x, int natoms, int preserve)
+{
+ if (x->x_size < natoms)
+ {
+ int newsize = x->x_size * 2;
+ while (newsize < natoms) newsize *= 2;
+ post("makeroom %s %d %d %d", x->x_method->s_name,
+ preserve, natoms, newsize);
+ if (x->x_messbuf == x->x_messini)
+ {
+ if (!(x->x_messbuf =
+ (t_atom *)getbytes(newsize * sizeof(*x->x_messbuf))))
+ {
+ x->x_messbuf = x->x_messini;
+ testmess_setnatoms(x, preserve ? x->x_natoms : 0);
+ return (0);
+ }
+ x->x_size = newsize;
+ testmess_setnatoms(x, preserve ? x->x_natoms : 0);
+ if (x->x_natoms)
+ {
+ if (x->x_tailwise)
+ memcpy(x->x_message,
+ x->x_messini + TESTMESS_INISIZE - x->x_natoms,
+ x->x_natoms * sizeof(*x->x_message));
+ else
+ memcpy(x->x_message,
+ x->x_messini, x->x_natoms * sizeof(*x->x_message));
+ }
+ }
+ else
+ {
+ int oldsize = x->x_size;
+ if (!(x->x_messbuf =
+ (t_atom *)resizebytes(x->x_messbuf,
+ x->x_size * sizeof(*x->x_messbuf),
+ newsize * sizeof(*x->x_messbuf))))
+ {
+ x->x_messbuf = x->x_messini;
+ x->x_size = TESTMESS_INISIZE;
+ testmess_setnatoms(x, 0);
+ return (0);
+ }
+ x->x_size = newsize;
+ testmess_setnatoms(x, preserve ? x->x_natoms : 0);
+ if (x->x_natoms && x->x_tailwise)
+ memmove(x->x_message, x->x_messbuf + oldsize - x->x_natoms,
+ x->x_natoms * sizeof(*x->x_message));
+ }
+ }
+ return (1);
+}
+
+static void testmess_stackmess(t_testmess *x, t_symbol *s, int ac, t_atom *av)
+{
+ t_atom buf[TESTMESS_STACKSIZE];
+ int natoms = x->x_natoms;
+ if (x->x_appendmode)
+ {
+ int left = TESTMESS_STACKSIZE - ac;
+ if (left < 0) ac = TESTMESS_STACKSIZE, natoms = 0;
+ else if (natoms > left) natoms = left;
+ if (ac)
+ memcpy(buf, av, ac * sizeof(*buf));
+ if (natoms)
+ memcpy(buf + ac, x->x_message, natoms * sizeof(*buf));
+ }
+ else
+ {
+ int left = TESTMESS_STACKSIZE - natoms;
+ if (left < 0) natoms = TESTMESS_STACKSIZE, ac = 0;
+ else if (ac > left) ac = left;
+ if (natoms)
+ memcpy(buf, x->x_message, natoms * sizeof(*buf));
+ if (ac)
+ memcpy(buf + natoms, av, ac * sizeof(*buf));
+ }
+ outlet_anything(((t_object *)x)->ob_outlet, s, natoms + ac, buf);
+}
+
+static void testmess_heapmess(t_testmess *x, t_symbol *s, int ac, t_atom *av)
+{
+ int ntotal = x->x_natoms + ac;
+ t_atom *buf = getbytes(ntotal * sizeof(*buf));
+ if (buf)
+ {
+ if (x->x_appendmode)
+ {
+ if (ac)
+ memcpy(buf, av, ac * sizeof(*buf));
+ if (x->x_natoms)
+ memcpy(buf + ac, x->x_message, x->x_natoms * sizeof(*buf));
+ }
+ else
+ {
+ if (x->x_natoms)
+ memcpy(buf, x->x_message, x->x_natoms * sizeof(*buf));
+ if (ac)
+ memcpy(buf + x->x_natoms, av, ac * sizeof(*buf));
+ }
+ outlet_anything(((t_object *)x)->ob_outlet, s, ntotal, buf);
+ freebytes(buf, ntotal * sizeof(*buf));
+ }
+}
+
+static void testmess_premess(t_testmess *x, t_symbol *s, int ac, t_atom *av)
+{
+ int ntotal = x->x_natoms + ac;
+ if (testmess_makeroom(x, ntotal, 1))
+ {
+ t_atom *buf;
+ if (x->x_appendmode)
+ {
+ buf = x->x_messbuf + x->x_size - ntotal;
+ if (ac)
+ memcpy(buf, av, ac * sizeof(*buf));
+ }
+ else
+ {
+ buf = x->x_messbuf;
+ if (ac)
+ memcpy(buf + x->x_natoms, av, ac * sizeof(*buf));
+ }
+ outlet_anything(((t_object *)x)->ob_outlet, s, ntotal, buf);
+ }
+}
+
+static void testmess_bang(t_testmess *x)
+{
+ if (x->x_natoms)
+ x->x_messfun(x, &s_list, 0, 0);
+}
+
+static void testmess_float(t_testmess *x, t_float f)
+{
+ t_atom at;
+ SETFLOAT(&at, f);
+ x->x_messfun(x, (x->x_natoms ? &s_list : &s_float), 1, &at);
+}
+
+static void testmess_symbol(t_testmess *x, t_symbol *s)
+{
+ x->x_messfun(x, s, 0, 0);
+}
+
+static void testmess_anything(t_testmess *x, t_symbol *s, int ac, t_atom *av)
+{
+ x->x_messfun(x, s, ac, av);
+}
+
+static void testmess_set(t_testmess *x, t_floatarg f1, t_floatarg f2)
+{
+ int natoms = (int)f1;
+ if (natoms > 0 && testmess_makeroom(x, natoms * 2, 0))
+ {
+ t_atom *ap;
+ int i = (int)f2;;
+ testmess_setnatoms(x, natoms);
+ ap = x->x_message;
+ while (natoms--)
+ {
+ SETFLOAT(ap, i);
+ i++; ap++;
+ }
+ }
+}
+
+static void testmess_free(t_testmess *x)
+{
+ if (x->x_messbuf != x->x_messini)
+ freebytes(x->x_messbuf, x->x_size * sizeof(*x->x_messbuf));
+}
+
+static void *testmess_new(t_symbol *s, t_floatarg f)
+{
+ t_testmess *x = (t_testmess *)pd_new(testmess_class);
+ x->x_appendmode = 1;
+ x->x_tailwise = 0;
+ if (s == gensym("stack"))
+ x->x_method = s, x->x_messfun = testmess_stackmess;
+ else if (s == gensym("heap"))
+ x->x_method = s, x->x_messfun = testmess_heapmess;
+ else
+ {
+ x->x_method = gensym("prealloc");
+ x->x_messfun = testmess_premess;
+ x->x_tailwise = x->x_appendmode;
+ }
+ x->x_size = TESTMESS_INISIZE;
+ x->x_messbuf = x->x_messini;
+ outlet_new((t_object *)x, &s_anything);
+ testmess_setnatoms(x, 0);
+ testmess_set(x, f, 0);
+ return (x);
+}
+
+void testmess_setup(void)
+{
+ testmess_class = class_new(gensym("testmess"),
+ (t_newmethod)testmess_new,
+ (t_method)testmess_free,
+ sizeof(t_testmess), 0,
+ A_DEFFLOAT, A_DEFSYM, 0);
+ class_addbang(testmess_class, testmess_bang);
+ class_addfloat(testmess_class, testmess_float);
+ class_addsymbol(testmess_class, testmess_symbol);
+ class_addanything(testmess_class, testmess_anything);
+ class_addmethod(testmess_class, (t_method)testmess_set,
+ gensym("set"), A_FLOAT, A_DEFFLOAT, 0);
+}
diff --git a/cyclone/hammer/thresh.c b/cyclone/hammer/thresh.c
new file mode 100644
index 0000000..6890dcc
--- /dev/null
+++ b/cyclone/hammer/thresh.c
@@ -0,0 +1,134 @@
+/* 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"
+
+#define THRESH_INISIZE 32 /* LATER rethink */
+#define THRESH_MAXSIZE 256
+#define THRESH_DEFTHRESH 10
+
+typedef struct _thresh
+{
+ t_object x_ob;
+ t_float x_thresh;
+ int x_size; /* as allocated */
+ int x_natoms; /* as used */
+ t_atom *x_message;
+ t_atom x_messini[THRESH_INISIZE];
+ t_clock *x_clock;
+} t_thresh;
+
+static t_class *thresh_class;
+
+static void thresh_tick(t_thresh *x)
+{
+ int ac = x->x_natoms;
+ if (ac)
+ {
+ t_atom *av = x->x_message;
+ if (av->a_type == A_FLOAT) /* redundant, but we might need it LATER */
+ {
+ if (ac > 1)
+ outlet_list(((t_object *)x)->ob_outlet, &s_list, ac, av);
+ else
+ outlet_float(((t_object *)x)->ob_outlet, av->a_w.w_float);
+ }
+ x->x_natoms = 0;
+ }
+}
+
+static void thresh_anything(t_thresh *x, t_symbol *s, int ac, t_atom *av)
+{
+ int ntotal = x->x_natoms + ac;
+ t_atom *buf;
+ clock_unset(x->x_clock);
+ if (s == &s_) s = 0;
+ if (s)
+ ntotal++;
+ if (ntotal > x->x_size)
+ {
+ /* LATER if (ntotal > THRESH_MAXSIZE)... (cf prepend) */
+ int nrequested = ntotal;
+ x->x_message = grow_withdata(&nrequested, &x->x_natoms,
+ &x->x_size, x->x_message,
+ THRESH_INISIZE, x->x_messini,
+ sizeof(*x->x_message));
+ if (nrequested != ntotal)
+ {
+ x->x_natoms = 0;
+ if (ac >= x->x_size)
+ ac = (s ? x->x_size - 1 : x->x_size);
+ }
+ }
+ buf = x->x_message + x->x_natoms;
+ if (s)
+ {
+ SETSYMBOL(buf, s);
+ buf++;
+ x->x_natoms++;
+ }
+ if (ac)
+ {
+ memcpy(buf, av, ac * sizeof(*buf));
+ x->x_natoms += ac;
+ }
+ clock_delay(x->x_clock, x->x_thresh);
+}
+
+static void thresh_float(t_thresh *x, t_float f)
+{
+ t_atom at;
+ SETFLOAT(&at, f);
+ thresh_anything(x, 0, 1, &at);
+}
+
+static void thresh_list(t_thresh *x, t_symbol *s, int ac, t_atom *av)
+{
+ thresh_anything(x, 0, ac, av);
+}
+
+static void thresh_ft1(t_thresh *x, t_floatarg f)
+{
+ if (f < 0)
+ f = 0; /* CHECKED */
+ x->x_thresh = f;
+ /* CHECKED: no rearming */
+}
+
+static void thresh_free(t_thresh *x)
+{
+ if (x->x_message != x->x_messini)
+ freebytes(x->x_message, x->x_size * sizeof(*x->x_message));
+ if (x->x_clock)
+ clock_free(x->x_clock);
+}
+
+static void *thresh_new(t_floatarg f)
+{
+ t_thresh *x = (t_thresh *)pd_new(thresh_class);
+ x->x_thresh = (f > 0 ? f : THRESH_DEFTHRESH);
+ x->x_size = THRESH_INISIZE;
+ x->x_natoms = 0;
+ x->x_message = x->x_messini;
+ inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft1"));
+ outlet_new((t_object *)x, &s_list); /* LATER rethink: list or float */
+ x->x_clock = clock_new(x, (t_method)thresh_tick);
+ return (x);
+}
+
+void thresh_setup(void)
+{
+ thresh_class = class_new(gensym("thresh"),
+ (t_newmethod)thresh_new,
+ (t_method)thresh_free,
+ sizeof(t_thresh), 0,
+ A_DEFFLOAT, 0);
+ class_addfloat(thresh_class, thresh_float);
+ class_addlist(thresh_class, thresh_list);
+ class_addmethod(thresh_class, (t_method)thresh_ft1,
+ gensym("ft1"), A_FLOAT, 0);
+ /* CHECKED: thresh: doesn't understand bang, symbol, anything */
+}
diff --git a/cyclone/hammer/tosymbol.c b/cyclone/hammer/tosymbol.c
new file mode 100644
index 0000000..8b45ad0
--- /dev/null
+++ b/cyclone/hammer/tosymbol.c
@@ -0,0 +1,184 @@
+/* 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 <string.h>
+#include "m_pd.h"
+#include "common/grow.h"
+
+#define TOSYMBOL_INISTRING 128 /* LATER rethink */
+#define TOSYMBOL_MAXSTRING 2048 /* the refman says so, later CHECKME */
+static char tosymbol_defseparator[] = " ";
+
+typedef struct _tosymbol
+{
+ t_object x_ob;
+ t_symbol *x_separator;
+ int x_bufsize;
+ char *x_buffer;
+ char x_bufini[TOSYMBOL_INISTRING];
+ int x_entered;
+} t_tosymbol;
+
+static t_class *tosymbol_class;
+static char tosymbol_buffer[TOSYMBOL_MAXSTRING];
+static int tosymbol_bufferlocked = 0;
+/* The idea is to prevent two different tosymbol objects from using the static
+ buffer at the same time. In the current scenario this buffer is never used
+ for output, so this lock is unnecessary... but it does no harm either... */
+
+static void tosymbol_flushbuffer(t_tosymbol *x)
+{
+ if (*x->x_buffer)
+ {
+ x->x_entered = 1;
+ outlet_symbol(((t_object *)x)->ob_outlet, gensym(x->x_buffer));
+ x->x_entered = 0;
+ }
+}
+
+static void tosymbol_bang(t_tosymbol *x)
+{
+ outlet_bang(((t_object *)x)->ob_outlet); /* CHECKED */
+}
+
+static void tosymbol_float(t_tosymbol *x, t_float f)
+{
+ if (!x->x_entered)
+ {
+ sprintf(x->x_buffer, "%g", f);
+ tosymbol_flushbuffer(x);
+ }
+}
+
+static void tosymbol_symbol(t_tosymbol *x, t_symbol *s)
+{
+ outlet_symbol(((t_object *)x)->ob_outlet, s);
+}
+
+static void tosymbol_pointer(t_tosymbol *x, t_gpointer *gp)
+{
+ /* nop: otherwise gpointer would be converted to 'list <gp>' */
+}
+
+static int tosymbol_parse(t_symbol *s, int ac, t_atom *av, t_symbol *separator,
+ int bufsize, char *buffer)
+{
+ int nleft = bufsize - 1;
+ int len;
+ char *bp = buffer;
+ bp[0] = bp[nleft] = 0;
+ if (s)
+ strncpy(bp, s->s_name, nleft);
+ len = strlen(bp);
+ nleft -= len;
+ bp += len;
+ if (ac && nleft > 0)
+ {
+ char *sepstring = (separator ?
+ separator->s_name : tosymbol_defseparator);
+ while (ac--)
+ {
+ if (*sepstring && bp > buffer)
+ {
+ strncpy(bp, sepstring, nleft);
+ len = strlen(bp);
+ nleft -= len;
+ if (nleft <= 0) break;
+ bp += len;
+ }
+ /* LATER rethink: type-checking */
+ atom_string(av, bp, nleft);
+ len = strlen(bp);
+ nleft -= len;
+ bp += len;
+ if (nleft <= 0) break;
+ av++;
+ }
+ }
+ if (nleft < 0)
+ {
+ bug("tosymbol_parse");
+ return (bufsize);
+ }
+ return (bufsize - nleft);
+}
+
+static void tosymbol_anything(t_tosymbol *x, t_symbol *s, int ac, t_atom *av)
+{
+ if (!x->x_entered)
+ {
+ if (tosymbol_bufferlocked)
+ {
+ bug("tosymbol_anything");
+ tosymbol_parse(s, ac, av, x->x_separator,
+ x->x_bufsize, x->x_buffer);
+ }
+ else
+ {
+ int ntotal;
+ tosymbol_bufferlocked = 1;
+ ntotal = tosymbol_parse(s, ac, av, x->x_separator,
+ TOSYMBOL_MAXSTRING, tosymbol_buffer);
+ if (ntotal > x->x_bufsize)
+ {
+ int newtotal = ntotal;
+ x->x_buffer = grow_nodata(&newtotal, &x->x_bufsize, x->x_buffer,
+ TOSYMBOL_INISTRING, x->x_bufini,
+ sizeof(*x->x_buffer));
+ if (newtotal < ntotal)
+ {
+ ntotal = newtotal - 1;
+ x->x_buffer[ntotal] = 0;
+ }
+ }
+ memcpy(x->x_buffer, tosymbol_buffer, ntotal);
+ tosymbol_bufferlocked = 0;
+ }
+ tosymbol_flushbuffer(x);
+ }
+}
+
+static void tosymbol_list(t_tosymbol *x, t_symbol *s, int ac, t_atom *av)
+{
+ tosymbol_anything(x, 0, ac, av);
+}
+
+static void tosymbol_separator(t_tosymbol *x, t_symbol *s)
+{
+ x->x_separator = (s ? s : &s_); /* default: empty string */
+}
+
+static void tosymbol_free(t_tosymbol *x)
+{
+ if (x->x_buffer != x->x_bufini)
+ freebytes(x->x_buffer, x->x_bufsize);
+}
+
+static void *tosymbol_new(void)
+{
+ t_tosymbol *x = (t_tosymbol *)pd_new(tosymbol_class);
+ x->x_separator = 0; /* default: a space */
+ x->x_bufsize = TOSYMBOL_INISTRING;
+ x->x_buffer = x->x_bufini;
+ x->x_entered = 0;
+ outlet_new((t_object *)x, &s_symbol);
+ return (x);
+}
+
+void tosymbol_setup(void)
+{
+ tosymbol_class = class_new(gensym("tosymbol"),
+ (t_newmethod)tosymbol_new,
+ (t_method)tosymbol_free,
+ sizeof(t_tosymbol), 0, 0);
+ class_addbang(tosymbol_class, tosymbol_bang);
+ class_addfloat(tosymbol_class, tosymbol_float);
+ class_addsymbol(tosymbol_class, tosymbol_symbol);
+ class_addpointer(tosymbol_class, tosymbol_pointer);
+ class_addlist(tosymbol_class, tosymbol_list);
+ class_addanything(tosymbol_class, tosymbol_anything);
+ class_addmethod(tosymbol_class, (t_method)tosymbol_separator,
+ gensym("separator"), A_DEFSYM, 0);
+}
diff --git a/cyclone/hammer/universal.c b/cyclone/hammer/universal.c
new file mode 100644
index 0000000..b1731d8
--- /dev/null
+++ b/cyclone/hammer/universal.c
@@ -0,0 +1,167 @@
+/* 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 "g_canvas.h"
+#include "unstable/pd_imp.h"
+#include "common/loud.h"
+
+/* LATER fragilize */
+
+typedef struct _universal
+{
+ t_object x_ob;
+ t_glist *x_glist;
+ t_int x_descend;
+} t_universal;
+
+static t_class *universal_class;
+
+static void universal_dobang(t_glist *glist, int descend, t_symbol *cname)
+{
+ t_gobj *g;
+ for (g = glist->gl_list; g; g = g->g_next)
+ if (pd_class(&g->g_pd)->c_name == cname) /* LATER rethink */
+ pd_bang(&g->g_pd);
+ if (descend)
+ for (g = glist->gl_list; g; g = g->g_next)
+ if (pd_class(&g->g_pd) == canvas_class) /* LATER rethink */
+ universal_dobang((t_glist *)g, descend, cname);
+}
+
+static void universal_dofloat(t_glist *glist, int descend, t_symbol *cname,
+ t_float f)
+{
+ t_gobj *g;
+ for (g = glist->gl_list; g; g = g->g_next)
+ if (pd_class(&g->g_pd)->c_name == cname) /* LATER rethink */
+ pd_float(&g->g_pd, f);
+ if (descend)
+ for (g = glist->gl_list; g; g = g->g_next)
+ if (pd_class(&g->g_pd) == canvas_class) /* LATER rethink */
+ universal_dofloat((t_glist *)g, descend, cname, f);
+}
+
+static void universal_dosymbol(t_glist *glist, int descend, t_symbol *cname,
+ t_symbol *s)
+{
+ t_gobj *g;
+ for (g = glist->gl_list; g; g = g->g_next)
+ if (pd_class(&g->g_pd)->c_name == cname) /* LATER rethink */
+ pd_symbol(&g->g_pd, s);
+ if (descend)
+ for (g = glist->gl_list; g; g = g->g_next)
+ if (pd_class(&g->g_pd) == canvas_class) /* LATER rethink */
+ universal_dosymbol((t_glist *)g, descend, cname, s);
+}
+
+static void universal_dopointer(t_glist *glist, int descend, t_symbol *cname,
+ t_gpointer *gp)
+{
+ t_gobj *g;
+ for (g = glist->gl_list; g; g = g->g_next)
+ if (pd_class(&g->g_pd)->c_name == cname) /* LATER rethink */
+ pd_pointer(&g->g_pd, gp);
+ if (descend)
+ for (g = glist->gl_list; g; g = g->g_next)
+ if (pd_class(&g->g_pd) == canvas_class) /* LATER rethink */
+ universal_dopointer((t_glist *)g, descend, cname, gp);
+}
+
+static void universal_dolist(t_glist *glist, int descend, t_symbol *cname,
+ int ac, t_atom *av)
+{
+ t_gobj *g;
+ for (g = glist->gl_list; g; g = g->g_next)
+ if (pd_class(&g->g_pd)->c_name == cname) /* LATER rethink */
+ pd_list(&g->g_pd, &s_list, ac, av);
+ if (descend)
+ for (g = glist->gl_list; g; g = g->g_next)
+ if (pd_class(&g->g_pd) == canvas_class) /* LATER rethink */
+ universal_dolist((t_glist *)g, descend, cname, ac, av);
+}
+
+static void universal_doanything(t_glist *glist, int descend, t_symbol *cname,
+ t_symbol *s, int ac, t_atom *av)
+{
+ t_gobj *g;
+ for (g = glist->gl_list; g; g = g->g_next)
+ if (pd_class(&g->g_pd)->c_name == cname) /* LATER rethink */
+ typedmess(&g->g_pd, s, ac, av);
+ if (descend)
+ for (g = glist->gl_list; g; g = g->g_next)
+ if (pd_class(&g->g_pd) == canvas_class) /* LATER rethink */
+ universal_doanything((t_glist *)g, descend, cname, s, ac, av);
+}
+
+/* LATER rethink type-checking -- it is borrowed from typedmess().
+ Anyway, do it once, before traversal, bypassing the generic mechanism
+ performed for every object. */
+static void universal_anything(t_universal *x, t_symbol *s, int ac, t_atom *av)
+{
+ /* CHECKED selector without arguments ignored with no complaints */
+ if (x->x_glist && s && ac)
+ {
+ if (av->a_type == A_FLOAT)
+ {
+ if (ac > 1)
+ universal_dolist(x->x_glist, x->x_descend, s, ac, av);
+ else
+ universal_dofloat(x->x_glist, x->x_descend, s, av->a_w.w_float);
+ }
+ else if (av->a_type == A_SYMBOL)
+ {
+ if (av->a_w.w_symbol == &s_bang)
+ universal_dobang(x->x_glist, x->x_descend, s);
+ else if (av->a_w.w_symbol == &s_float)
+ {
+ if (ac == 1)
+ universal_dofloat(x->x_glist, x->x_descend, s, 0.);
+ else if (av[1].a_type == A_FLOAT)
+ universal_dofloat(x->x_glist, x->x_descend, s,
+ av[1].a_w.w_float);
+ else
+ loud_error((t_pd *)x, "Bad argument for message 'float'");
+ }
+ else if (av->a_w.w_symbol == &s_symbol)
+ universal_dosymbol(x->x_glist, x->x_descend, s,
+ (ac > 1 && av[1].a_type == A_SYMBOL ?
+ av[1].a_w.w_symbol : &s_));
+ else if (av->a_w.w_symbol == &s_list)
+ universal_dolist(x->x_glist, x->x_descend, s, ac - 1, av + 1);
+ else
+ universal_doanything(x->x_glist, x->x_descend, s,
+ av->a_w.w_symbol, ac - 1, av + 1);
+ }
+ if (av->a_type == A_POINTER)
+ universal_dopointer(x->x_glist, x->x_descend, s,
+ av->a_w.w_gpointer);
+ }
+}
+
+static void universal_send(t_universal *x, t_symbol *s, int ac, t_atom *av)
+{
+ if (ac && av->a_type == A_SYMBOL)
+ universal_anything(x, av->a_w.w_symbol, ac - 1, av + 1);
+ /* CHECKED: else ignored without complaints */
+}
+
+static void *universal_new(t_floatarg f)
+{
+ t_universal *x = (t_universal *)pd_new(universal_class);
+ x->x_glist = canvas_getcurrent();
+ x->x_descend = ((int)f != 0); /* CHECKED */
+ return (x);
+}
+
+void universal_setup(void)
+{
+ universal_class = class_new(gensym("universal"),
+ (t_newmethod)universal_new, 0,
+ sizeof(t_universal), 0, A_DEFFLOAT, 0);
+ class_addanything(universal_class, universal_anything);
+ /* CHECKED: 'send', not 'sendmessage' */
+ class_addmethod(universal_class, (t_method)universal_send,
+ gensym("send"), A_GIMME, 0);
+}
diff --git a/cyclone/hammer/urn.c b/cyclone/hammer/urn.c
new file mode 100644
index 0000000..59b140e
--- /dev/null
+++ b/cyclone/hammer/urn.c
@@ -0,0 +1,148 @@
+/* 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 think again about avoiding memory allocation overhead in run-time.
+ One would need to use a creation argument greater than any future right
+ inlet value. But this is incompatible (max uses a `static', max-size
+ array), and should be put somewhere in the docs... */
+
+#include "m_pd.h"
+#include "common/loud.h"
+#include "common/rand.h"
+#include "common/grow.h"
+
+#define URN_INISIZE 128 /* LATER rethink */
+#define URN_MAXSIZE 4096 /* CHECKED */
+#define URN_MAXIMUMSIZE 65536 /* LATER use USHRT_MAX */
+
+typedef struct _urn
+{
+ t_object x_ob;
+ int x_count;
+ int x_size; /* as allocated (in bytes) */
+ int x_range; /* as used */
+ unsigned short *x_urn;
+ unsigned short x_urnini[URN_INISIZE];
+ unsigned int x_seed;
+ t_outlet *x_bangout;
+} t_urn;
+
+static t_class *urn_class;
+
+static int urn_resize(t_urn *x, t_float f, int init)
+{
+ int maxmax = URN_MAXSIZE;
+ int range = (int)f; /* CHECKED silent truncation */
+ if (init)
+ {
+ maxmax--; /* CHECKED: max 4095 here (a bug, sort of) */
+ /* CHECKED in the constructor this is silent
+ (also > maxmax clipped without complaining) */
+ if (range < 1)
+ range = 1;
+ }
+ else if (range < 1)
+ {
+ /* CHECKED (the same for > maxmax) */
+ loud_error((t_pd *)x, "illegal size %d", f);
+ return (0);
+ }
+ if (range > URN_MAXIMUMSIZE)
+ {
+ loud_warning((t_pd *)x,
+ "requested size (%d) clipped -- effective size is %d",
+ range, URN_MAXIMUMSIZE);
+ range = URN_MAXIMUMSIZE;
+ }
+ if (range > maxmax)
+ loud_incompatible_max(urn_class, maxmax, "elements");
+ x->x_range = range;
+ if (range > x->x_size)
+ x->x_urn = grow_nodata(&x->x_range, &x->x_size, x->x_urn,
+ URN_INISIZE, x->x_urnini,
+ sizeof(*x->x_urn));
+ return (1);
+}
+
+static void urn_bang(t_urn *x)
+{
+ if (x->x_count)
+ {
+ int ndx = rand_int(&x->x_seed, x->x_count);
+ unsigned short pick = x->x_urn[ndx];
+ x->x_urn[ndx] = x->x_urn[--x->x_count];
+ outlet_float(((t_object *)x)->ob_outlet, pick);
+ }
+ /* CHECKED: start banging when the first bang is input
+ into an empty urn (and not when the last value is output).
+ CHECKED: keep banging until cleared. */
+ else outlet_bang(x->x_bangout);
+}
+
+static void urn_clear(t_urn *x)
+{
+ int i;
+ x->x_count = x->x_range;
+ for (i = 0; i < x->x_count; i++) x->x_urn[i] = i;
+}
+
+static void urn_float(t_urn *x, t_float f)
+{
+ /* CHECKED: float loudly rejected, int (any value) same as bang */
+ int i;
+ if (loud_checkint((t_pd *)x, f, &i, &s_float))
+ urn_bang(x);
+}
+
+static void urn_ft1(t_urn *x, t_floatarg f)
+{
+ if (urn_resize(x, f, 0)) /* CHECKED cleared only if a legal resize */
+ urn_clear(x);
+}
+
+static void urn_seed(t_urn *x, t_floatarg f)
+{
+ int i = (int)f; /* CHECKED */
+ if (i < 0)
+ i = 1; /* CHECKED */
+ rand_seed(&x->x_seed, (unsigned int)i);
+}
+
+static void urn_free(t_urn *x)
+{
+ if (x->x_urn != x->x_urnini)
+ freebytes(x->x_urn, x->x_size * sizeof(*x->x_urn));
+}
+
+static void *urn_new(t_floatarg f1, t_floatarg f2)
+{
+ t_urn *x = (t_urn *)pd_new(urn_class);
+ x->x_size = URN_INISIZE;
+ x->x_urn = x->x_urnini;
+ urn_resize(x, f1, 1);
+ urn_seed(x, f2); /* CHECKME */
+ inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft1"));
+ outlet_new((t_object *)x, &s_float);
+ x->x_bangout = outlet_new((t_object *)x, &s_bang);
+ urn_clear(x);
+ return (x);
+}
+
+void urn_setup(void)
+{
+ urn_class = class_new(gensym("urn"),
+ (t_newmethod)urn_new,
+ (t_method)urn_free,
+ sizeof(t_urn), 0,
+ A_DEFFLOAT, A_DEFFLOAT, 0);
+ class_addbang(urn_class, urn_bang);
+ class_addfloat(urn_class, urn_float);
+ class_addmethod(urn_class, (t_method)urn_ft1,
+ gensym("ft1"), A_FLOAT, 0);
+ /* CHECKED list is auto-unfolded */
+ class_addmethod(urn_class, (t_method)urn_seed,
+ gensym("seed"), A_FLOAT, 0); /* CHECKED arg obligatory */
+ class_addmethod(urn_class, (t_method)urn_clear,
+ gensym("clear"), 0);
+}
diff --git a/cyclone/hammer/xbendin.c b/cyclone/hammer/xbendin.c
new file mode 100644
index 0000000..54082b3
--- /dev/null
+++ b/cyclone/hammer/xbendin.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 "m_pd.h"
+
+typedef struct _xbendin
+{
+ t_object x_ob;
+ int x_omni;
+ unsigned char x_ready;
+ unsigned char x_status;
+ unsigned char x_channel;
+ unsigned char x_lsb;
+ t_outlet *x_chanout;
+} t_xbendin;
+
+static t_class *xbendin_class;
+
+static void xbendin_clear(t_xbendin *x)
+{
+ x->x_status = 0;
+ x->x_ready = 0;
+}
+
+static void xbendin_float(t_xbendin *x, t_float f)
+{
+ int ival = (int)f; /* CHECKME */
+ if (ival < 0)
+ {
+ /* CHECKME */
+ return;
+ }
+ if (ival < 256) /* CHECKME */
+ {
+ unsigned char bval = ival;
+ if (bval & 0x80)
+ {
+ unsigned char status = bval & 0xF0;
+ if (status == 0xF0)
+ {
+ /* CHECKME */
+ if (bval < 0xF8)
+ xbendin_clear(x);
+ }
+ else if (status == 0xE0)
+ {
+ unsigned char channel = bval & 0x0F;
+ if (x->x_omni)
+ x->x_channel = channel;
+ x->x_status = (x->x_channel == channel);
+ x->x_ready = 0;
+ }
+ else xbendin_clear(x);
+ }
+ else if (x->x_ready)
+ {
+ if (x->x_omni)
+ outlet_float(x->x_chanout, x->x_channel + 1);
+ outlet_float(((t_object *)x)->ob_outlet, (bval << 7) + x->x_lsb);
+ x->x_ready = 0;
+ }
+ else if (x->x_status)
+ {
+ x->x_lsb = bval;
+ x->x_ready = 1;
+ }
+ }
+ else xbendin_clear(x);
+}
+
+static void *xbendin_new(t_floatarg f)
+{
+ int channel = (int)f; /* CHECKME */
+ t_xbendin *x = (t_xbendin *)pd_new(xbendin_class);
+ outlet_new((t_object *)x, &s_float);
+ if (x->x_omni = (channel == 0)) /* CHECKME */
+ x->x_chanout = outlet_new((t_object *)x, &s_float);
+ else
+ x->x_channel = (unsigned char)--channel; /* CHECKME */
+ xbendin_clear(x);
+ return (x);
+}
+
+void xbendin_setup(void)
+{
+ xbendin_class = class_new(gensym("xbendin"),
+ (t_newmethod)xbendin_new, 0,
+ sizeof(t_xbendin), 0,
+ A_DEFFLOAT, 0);
+ class_addfloat(xbendin_class, xbendin_float);
+ /* CHECKME autocasting lists to floats */
+}
diff --git a/cyclone/hammer/xbendin2.c b/cyclone/hammer/xbendin2.c
new file mode 100644
index 0000000..1336800
--- /dev/null
+++ b/cyclone/hammer/xbendin2.c
@@ -0,0 +1,99 @@
+/* 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"
+
+/* LATER find a better way to synchronize with xbendin,
+ while avoiding the c74's bug... */
+
+typedef struct _xbendin2
+{
+ t_object x_ob;
+ int x_omni;
+ unsigned char x_ready;
+ unsigned char x_status;
+ unsigned char x_channel;
+ unsigned char x_lsb;
+ t_outlet *x_lsbout;
+ t_outlet *x_chanout;
+} t_xbendin2;
+
+static t_class *xbendin2_class;
+
+static void xbendin2_clear(t_xbendin2 *x)
+{
+ x->x_status = 0;
+ x->x_ready = 0;
+}
+
+static void xbendin2_float(t_xbendin2 *x, t_float f)
+{
+ int ival = (int)f; /* CHECKME */
+ if (ival < 0)
+ {
+ /* CHECKME */
+ return;
+ }
+ if (ival < 256) /* CHECKME */
+ {
+ unsigned char bval = ival;
+ if (bval & 0x80)
+ {
+ unsigned char status = bval & 0xF0;
+ if (status == 0xF0)
+ {
+ /* CHECKME */
+ if (bval < 0xF8)
+ xbendin2_clear(x);
+ }
+ else if (status == 0xE0)
+ {
+ unsigned char channel = bval & 0x0F;
+ if (x->x_omni)
+ x->x_channel = channel;
+ x->x_status = (x->x_channel == channel);
+ x->x_ready = 0;
+ }
+ else xbendin2_clear(x);
+ }
+ else if (x->x_ready)
+ {
+ if (x->x_omni)
+ outlet_float(x->x_chanout, x->x_channel + 1);
+ outlet_float(x->x_lsbout, x->x_lsb);
+ outlet_float(((t_object *)x)->ob_outlet, bval);
+ x->x_ready = 0;
+ }
+ else if (x->x_status)
+ {
+ x->x_lsb = bval;
+ x->x_ready = 1;
+ }
+ }
+ else xbendin2_clear(x);
+}
+
+static void *xbendin2_new(t_floatarg f)
+{
+ int channel = (int)f; /* CHECKME */
+ t_xbendin2 *x = (t_xbendin2 *)pd_new(xbendin2_class);
+ outlet_new((t_object *)x, &s_float);
+ x->x_lsbout = outlet_new((t_object *)x, &s_float);
+ if (x->x_omni = (channel == 0)) /* CHECKME */
+ x->x_chanout = outlet_new((t_object *)x, &s_float);
+ else
+ x->x_channel = (unsigned char)--channel; /* CHECKME */
+ xbendin2_clear(x);
+ return (x);
+}
+
+void xbendin2_setup(void)
+{
+ xbendin2_class = class_new(gensym("xbendin2"),
+ (t_newmethod)xbendin2_new, 0,
+ sizeof(t_xbendin2), 0,
+ A_DEFFLOAT, 0);
+ class_addfloat(xbendin2_class, xbendin2_float);
+ /* CHECKME autocasting lists to floats */
+}
diff --git a/cyclone/hammer/xbendout.c b/cyclone/hammer/xbendout.c
new file mode 100644
index 0000000..faa401e
--- /dev/null
+++ b/cyclone/hammer/xbendout.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 "m_pd.h"
+
+typedef struct _xbendout
+{
+ t_object x_ob;
+ t_float x_channel;
+ int x_value;
+} t_xbendout;
+
+static t_class *xbendout_class;
+
+static void xbendout_dooutput(t_xbendout *x)
+{
+ int value = x->x_value;
+ int channel = (int)x->x_channel; /* CHECKME */
+ if (value >= 0 && /* CHECKME */
+ value <= 16383 && /* CHECKME */
+ channel > 0) /* CHECKME */
+ {
+ outlet_float(((t_object *)x)->ob_outlet, 224 + ((channel-1) & 0x0F));
+ outlet_float(((t_object *)x)->ob_outlet, value & 0x7F);
+ outlet_float(((t_object *)x)->ob_outlet, value >> 7);
+ }
+}
+
+static void xbendout_float(t_xbendout *x, t_float f)
+{
+ x->x_value = (int)f; /* CHECKME */
+ xbendout_dooutput(x);
+}
+
+static void *xbendout_new(t_floatarg f)
+{
+ t_xbendout *x = (t_xbendout *)pd_new(xbendout_class);
+ floatinlet_new((t_object *)x, &x->x_channel);
+ outlet_new((t_object *)x, &s_float);
+ x->x_channel = ((int)f > 0 ? f : 1); /* CHECKME */
+ x->x_value = 8192; /* CHECKME if not -1 */
+ return (x);
+}
+
+void xbendout_setup(void)
+{
+ xbendout_class = class_new(gensym("xbendout"),
+ (t_newmethod)xbendout_new, 0,
+ sizeof(t_xbendout), 0,
+ A_DEFFLOAT, 0);
+ class_addbang(xbendout_class, xbendout_dooutput);
+ class_addfloat(xbendout_class, xbendout_float);
+}
diff --git a/cyclone/hammer/xbendout2.c b/cyclone/hammer/xbendout2.c
new file mode 100644
index 0000000..a2f8817
--- /dev/null
+++ b/cyclone/hammer/xbendout2.c
@@ -0,0 +1,60 @@
+/* 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"
+
+typedef struct _xbendout2
+{
+ t_object x_ob;
+ t_float x_channel;
+ t_float x_lsb;
+ int x_msb;
+} t_xbendout2;
+
+static t_class *xbendout2_class;
+
+static void xbendout2_dooutput(t_xbendout2 *x)
+{
+ int msb = x->x_msb;
+ int lsb = (int)x->x_lsb; /* CHECKME */
+ int channel = (int)x->x_channel; /* CHECKME */
+ if (msb >= 0 && /* CHECKME */
+ msb <= 127 && /* CHECKME */
+ lsb >= 0 && /* CHECKME */
+ lsb <= 127 && /* CHECKME */
+ channel > 0) /* CHECKME */
+ {
+ outlet_float(((t_object *)x)->ob_outlet, 224 + ((channel-1) & 0x0F));
+ outlet_float(((t_object *)x)->ob_outlet, lsb);
+ outlet_float(((t_object *)x)->ob_outlet, msb);
+ }
+}
+
+static void xbendout2_float(t_xbendout2 *x, t_float f)
+{
+ x->x_msb = (int)f; /* CHECKME */
+ xbendout2_dooutput(x);
+}
+
+static void *xbendout2_new(t_floatarg f)
+{
+ t_xbendout2 *x = (t_xbendout2 *)pd_new(xbendout2_class);
+ floatinlet_new((t_object *)x, &x->x_lsb);
+ floatinlet_new((t_object *)x, &x->x_channel);
+ outlet_new((t_object *)x, &s_float);
+ x->x_channel = ((int)f > 0 ? f : 1); /* CHECKME */
+ x->x_lsb = 0;
+ x->x_msb = 64; /* CHECKME if not -1 */
+ return (x);
+}
+
+void xbendout2_setup(void)
+{
+ xbendout2_class = class_new(gensym("xbendout2"),
+ (t_newmethod)xbendout2_new, 0,
+ sizeof(t_xbendout2), 0,
+ A_DEFFLOAT, 0);
+ class_addbang(xbendout2_class, xbendout2_dooutput);
+ class_addfloat(xbendout2_class, xbendout2_float);
+}
diff --git a/cyclone/hammer/xnotein.c b/cyclone/hammer/xnotein.c
new file mode 100644
index 0000000..73b271b
--- /dev/null
+++ b/cyclone/hammer/xnotein.c
@@ -0,0 +1,100 @@
+/* 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"
+
+typedef struct _xnotein
+{
+ t_object x_ob;
+ int x_omni;
+ unsigned char x_ready;
+ unsigned char x_status;
+ unsigned char x_channel;
+ unsigned char x_pitch;
+ t_outlet *x_velout;
+ t_outlet *x_flagout;
+ t_outlet *x_chanout;
+} t_xnotein;
+
+static t_class *xnotein_class;
+
+static void xnotein_clear(t_xnotein *x)
+{
+ x->x_status = 0;
+ x->x_ready = 0;
+}
+
+static void xnotein_float(t_xnotein *x, t_float f)
+{
+ int ival = (int)f; /* CHECKME */
+ if (ival < 0)
+ {
+ /* CHECKME */
+ return;
+ }
+ if (ival < 256) /* CHECKME */
+ {
+ unsigned char bval = ival;
+ if (bval & 0x80)
+ {
+ unsigned char status = bval & 0xF0;
+ if (status == 0xF0)
+ {
+ /* CHECKME */
+ if (bval < 0xF8)
+ xnotein_clear(x);
+ }
+ else if (status == 0x80 || status == 0x90)
+ {
+ unsigned char channel = bval & 0x0F;
+ if (x->x_omni)
+ x->x_channel = channel;
+ x->x_status = (x->x_channel == channel ? status : 0);
+ x->x_ready = 0;
+ }
+ else xnotein_clear(x);
+ }
+ else if (x->x_ready)
+ {
+ int flag = (x->x_status == 0x90 && bval);
+ if (x->x_omni)
+ outlet_float(x->x_chanout, x->x_channel + 1);
+ outlet_float(x->x_flagout, flag);
+ outlet_float(x->x_velout, bval);
+ outlet_float(((t_object *)x)->ob_outlet, x->x_pitch);
+ x->x_ready = 0;
+ }
+ else if (x->x_status)
+ {
+ x->x_pitch = bval;
+ x->x_ready = 1;
+ }
+ }
+ else xnotein_clear(x);
+}
+
+static void *xnotein_new(t_floatarg f)
+{
+ int channel = (int)f; /* CHECKME */
+ t_xnotein *x = (t_xnotein *)pd_new(xnotein_class);
+ outlet_new((t_object *)x, &s_float);
+ x->x_velout = outlet_new((t_object *)x, &s_float);
+ x->x_flagout = outlet_new((t_object *)x, &s_float);
+ if (x->x_omni = (channel == 0)) /* CHECKME */
+ x->x_chanout = outlet_new((t_object *)x, &s_float);
+ else
+ x->x_channel = (unsigned char)--channel; /* CHECKME */
+ xnotein_clear(x);
+ return (x);
+}
+
+void xnotein_setup(void)
+{
+ xnotein_class = class_new(gensym("xnotein"),
+ (t_newmethod)xnotein_new, 0,
+ sizeof(t_xnotein), 0,
+ A_DEFFLOAT, 0);
+ class_addfloat(xnotein_class, xnotein_float);
+ /* CHECKME autocasting lists to floats */
+}
diff --git a/cyclone/hammer/xnoteout.c b/cyclone/hammer/xnoteout.c
new file mode 100644
index 0000000..058c7f9
--- /dev/null
+++ b/cyclone/hammer/xnoteout.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"
+
+typedef struct _xnoteout
+{
+ t_object x_ob;
+ t_float x_channel;
+ t_float x_flag;
+ t_float x_velocity;
+ int x_pitch;
+} t_xnoteout;
+
+static t_class *xnoteout_class;
+
+static void xnoteout_dooutput(t_xnoteout *x)
+{
+ int status = ((int)x->x_flag ? 0x90 : 0x80); /* CHECKME */
+ int channel = (int)x->x_channel; /* CHECKME */
+ int pitch = x->x_pitch;
+ int velocity = (int)x->x_velocity & 0x7F; /* CHECKME */
+ if (pitch >= 0 && /* CHECKME */
+ pitch <= 127 && /* CHECKME */
+ channel > 0) /* CHECKME */
+ {
+ outlet_float(((t_object *)x)->ob_outlet, status + ((channel-1) & 0x0F));
+ outlet_float(((t_object *)x)->ob_outlet, pitch);
+ outlet_float(((t_object *)x)->ob_outlet, velocity);
+ }
+}
+
+static void xnoteout_float(t_xnoteout *x, t_float f)
+{
+ x->x_pitch = (int)f; /* CHECKME */
+ xnoteout_dooutput(x);
+}
+
+static void *xnoteout_new(t_floatarg f)
+{
+ t_xnoteout *x = (t_xnoteout *)pd_new(xnoteout_class);
+ floatinlet_new((t_object *)x, &x->x_velocity);
+ floatinlet_new((t_object *)x, &x->x_flag);
+ floatinlet_new((t_object *)x, &x->x_channel);
+ outlet_new((t_object *)x, &s_float);
+ x->x_channel = ((int)f > 0 ? f : 1); /* CHECKME */
+ x->x_flag = 0; /* CHECKME */
+ x->x_velocity = 0; /* CHECKME */
+ x->x_pitch = -1; /* CHECKME */
+ return (x);
+}
+
+void xnoteout_setup(void)
+{
+ xnoteout_class = class_new(gensym("xnoteout"),
+ (t_newmethod)xnoteout_new, 0,
+ sizeof(t_xnoteout), 0,
+ A_DEFFLOAT, 0);
+ class_addbang(xnoteout_class, xnoteout_dooutput);
+ class_addfloat(xnoteout_class, xnoteout_float);
+}
diff --git a/cyclone/hammer/zl.c b/cyclone/hammer/zl.c
new file mode 100644
index 0000000..566c18e
--- /dev/null
+++ b/cyclone/hammer/zl.c
@@ -0,0 +1,982 @@
+/* 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/loud.h"
+#include "common/grow.h"
+
+/* LATER test reentrancy, tune speedwise */
+
+#define ZL_DEBUG
+
+#define ZL_INISIZE 32 /* LATER rethink */
+#define ZL_MAXSIZE 256
+#define ZL_MAXMODES 16
+#define ZL_DEFMODE 0
+
+struct _zl;
+typedef int (*t_zlintargfn)(struct _zl *, int);
+typedef void (*t_zlanyargfn)(struct _zl *, t_symbol *, int, t_atom *);
+typedef int (*t_zlnatomsfn)(struct _zl *);
+typedef void (*t_zldoitfn)(struct _zl *, int, t_atom *);
+
+static int zl_nmodes = 0;
+static t_symbol *zl_modesym[ZL_MAXMODES];
+static int zl_modeflags[ZL_MAXMODES];
+static t_zlintargfn zl_intargfn[ZL_MAXMODES];
+static t_zlanyargfn zl_anyargfn[ZL_MAXMODES];
+static t_zlnatomsfn zl_natomsfn[ZL_MAXMODES];
+static t_zldoitfn zl_doitfn[ZL_MAXMODES];
+
+typedef struct _zldata
+{
+ int d_size; /* as allocated */
+ int d_natoms; /* as used */
+ t_atom *d_buf;
+ t_atom d_bufini[ZL_INISIZE];
+} t_zldata;
+
+typedef struct _zl
+{
+ t_object x_ob;
+ struct _zlproxy *x_proxy;
+ int x_entered;
+ int x_locked; /* locking inbuf1 in modes: iter, reg, slice */
+ t_zldata x_inbuf1;
+ t_zldata x_inbuf2;
+ t_zldata x_outbuf;
+ int x_mode;
+ int x_modearg;
+ t_outlet *x_out2;
+} t_zl;
+
+typedef struct _zlproxy
+{
+ t_object p_ob;
+ t_zl *p_master;
+} t_zlproxy;
+
+static t_class *zl_class;
+static t_class *zlproxy_class;
+
+static void zldata_init(t_zldata *d)
+{
+ d->d_size = ZL_INISIZE;
+ d->d_natoms = 0;
+ d->d_buf = d->d_bufini;
+}
+
+static void zldata_free(t_zldata *d)
+{
+ if (d->d_buf != d->d_bufini)
+ freebytes(d->d_buf, d->d_size * sizeof(*d->d_buf));
+}
+
+static void zldata_setfloat(t_zldata *d, t_float f)
+{
+ SETFLOAT(d->d_buf, f);
+ d->d_natoms = 1;
+}
+
+static void zldata_addfloat(t_zldata *d, t_float f)
+{
+ int natoms = d->d_natoms;
+ int nrequested = natoms + 1;
+ if (nrequested > d->d_size)
+ {
+ d->d_buf = grow_withdata(&nrequested, &natoms, &d->d_size,
+ d->d_buf, ZL_INISIZE, d->d_bufini,
+ sizeof(*d->d_buf));
+ if (natoms >= nrequested)
+ natoms = nrequested - 1;
+ }
+ SETFLOAT(d->d_buf + natoms, f);
+ d->d_natoms = natoms + 1;
+}
+
+static void zldata_setsymbol(t_zldata *d, t_symbol *s)
+{
+ SETSYMBOL(d->d_buf, s);
+ d->d_natoms = 1;
+}
+
+static void zldata_addsymbol(t_zldata *d, t_symbol *s)
+{
+ int natoms = d->d_natoms;
+ int nrequested = natoms + 1;
+ if (nrequested > d->d_size)
+ {
+ d->d_buf = grow_withdata(&nrequested, &natoms, &d->d_size,
+ d->d_buf, ZL_INISIZE, d->d_bufini,
+ sizeof(*d->d_buf));
+ if (natoms >= nrequested)
+ natoms = nrequested - 1;
+ }
+ SETSYMBOL(d->d_buf + natoms, s);
+ d->d_natoms = natoms + 1;
+}
+
+static void zldata_setlist(t_zldata *d, int ac, t_atom *av)
+{
+ int nrequested = ac;
+ if (nrequested > d->d_size)
+ d->d_buf = grow_nodata(&nrequested, &d->d_size, d->d_buf,
+ ZL_INISIZE, d->d_bufini, sizeof(*d->d_buf));
+ if (d->d_natoms = nrequested)
+ memcpy(d->d_buf, av, nrequested * sizeof(*d->d_buf));
+}
+
+static void zldata_addlist(t_zldata *d, int ac, t_atom *av)
+{
+ int natoms = d->d_natoms;
+ int nrequested = natoms + ac;
+ if (nrequested > d->d_size)
+ {
+ d->d_buf = grow_withdata(&nrequested, &natoms, &d->d_size,
+ d->d_buf, ZL_INISIZE, d->d_bufini,
+ sizeof(*d->d_buf));
+ if (natoms + ac > nrequested)
+ {
+ natoms = nrequested - ac;
+ if (natoms < 0)
+ natoms = 0, ac = nrequested;
+ }
+ }
+ if (d->d_natoms = natoms + ac)
+ memcpy(d->d_buf + natoms, av, ac * sizeof(*d->d_buf));
+}
+
+static void zldata_set(t_zldata *d, t_symbol *s, int ac, t_atom *av)
+{
+ if (s && s != &s_)
+ {
+ int nrequested = ac + 1;
+ if (nrequested > d->d_size)
+ d->d_buf = grow_nodata(&nrequested, &d->d_size, d->d_buf,
+ ZL_INISIZE, d->d_bufini, sizeof(*d->d_buf));
+ if (d->d_natoms = nrequested)
+ {
+ SETSYMBOL(d->d_buf, s);
+ if (--nrequested)
+ memcpy(d->d_buf + 1, av, nrequested * sizeof(*d->d_buf));
+ }
+ }
+ else zldata_setlist(d, ac, av);
+}
+
+static void zldata_add(t_zldata *d, t_symbol *s, int ac, t_atom *av)
+{
+ if (s && s != &s_)
+ {
+ int natoms = d->d_natoms;
+ int nrequested = natoms + 1 + ac;
+ if (nrequested > d->d_size)
+ {
+ d->d_buf = grow_withdata(&nrequested, &natoms, &d->d_size,
+ d->d_buf, ZL_INISIZE, d->d_bufini,
+ sizeof(*d->d_buf));
+ if (natoms + 1 + ac > nrequested)
+ {
+ natoms = nrequested - 1 - ac;
+ if (natoms < 0)
+ natoms = 0, ac = nrequested - 1;
+ }
+ }
+ if (d->d_natoms = natoms + 1 + ac)
+ {
+ SETSYMBOL(d->d_buf + natoms, s);
+ if (ac > 0)
+ memcpy(d->d_buf + natoms + 1, av, ac * sizeof(*d->d_buf));
+ }
+ }
+ else zldata_addlist(d, ac, av);
+}
+
+/* LATER rethink */
+static void zl_dooutput(t_outlet *o, int ac, t_atom *av)
+{
+ if (ac > 1)
+ {
+ if (av->a_type == A_FLOAT)
+ outlet_list(o, &s_list, ac, av);
+ else if (av->a_type == A_SYMBOL)
+ outlet_anything(o, av->a_w.w_symbol, ac - 1, av + 1);
+ }
+ else if (ac)
+ {
+ if (av->a_type == A_FLOAT)
+ outlet_float(o, av->a_w.w_float);
+ else if (av->a_type == A_SYMBOL)
+#if 1
+ outlet_anything(o, av->a_w.w_symbol, 0, 0); /* CHECKED */
+#else
+ outlet_symbol(o, av->a_w.w_symbol); /* LATER rethink */
+#endif
+ }
+}
+
+static void zl_output(t_zl *x, int ac, t_atom *av)
+{
+ zl_dooutput(((t_object *)x)->ob_outlet, ac, av);
+}
+
+static void zl_output2(t_zl *x, int ac, t_atom *av)
+{
+ zl_dooutput(x->x_out2, ac, av);
+}
+
+static int zl_equal(t_atom *ap1, t_atom *ap2)
+{
+ return (ap1->a_type == ap2->a_type
+ &&
+ ((ap1->a_type == A_FLOAT
+ && ap1->a_w.w_float == ap2->a_w.w_float)
+ ||
+ (ap1->a_type == A_SYMBOL
+ && ap1->a_w.w_symbol == ap2->a_w.w_symbol)));
+}
+
+/* Mode handlers:
+ If zl_<mode>_count's return value is positve, then the main routine
+ uses an output buffer 'buf' (outbuf, or a separately allocated one).
+ If zl_<mode>_count's return value is zero, then the main routine is
+ passed a null 'buf' (see below); if it is negative, then the main
+ routine is not being called.
+ zl_<mode> (main routine) arguments: if 'buf' is null, 'natoms'
+ is always zero -- in modes other than len (no buffer used), group,
+ iter, reg, slice/ecils (inbuf1 used), there should be no output.
+ If 'buf' is not null, then 'natoms' is guaranteed to be positive.
+*/
+
+static int zl_nop_count(t_zl *x)
+{
+ return (0);
+}
+
+static void zl_nop(t_zl *x, int natoms, t_atom *buf)
+{
+ loud_warning((t_pd *)x, "unknown mode");
+}
+
+static int zl_ecils_intarg(t_zl *x, int i)
+{
+ return (i > 0 ? i : 0); /* CHECKED */
+}
+
+static int zl_ecils_count(t_zl *x)
+{
+ return (x->x_entered ? -1 : 0);
+}
+
+static void zl_ecils(t_zl *x, int natoms, t_atom *buf)
+{
+ int cnt1, cnt2 = x->x_modearg;
+ natoms = x->x_inbuf1.d_natoms;
+ buf = x->x_inbuf1.d_buf;
+ if (cnt2 > natoms)
+ cnt2 = natoms, cnt1 = 0; /* CHECKED */
+ else
+ cnt1 = natoms - cnt2;
+ x->x_locked = 1;
+ if (cnt2)
+ zl_output2(x, cnt2, buf + cnt1);
+ if (cnt1)
+ zl_output(x, cnt1, buf);
+}
+
+static int zl_group_intarg(t_zl *x, int i)
+{
+ return (i > 0 ? i : 0); /* CHECKED */
+}
+
+static int zl_group_count(t_zl *x)
+{
+ return (x->x_entered ? -1 : 0);
+}
+
+static void zl_group(t_zl *x, int natoms, t_atom *buf)
+{
+ int cnt = x->x_modearg;
+ if (cnt > 0)
+ {
+ natoms = x->x_inbuf1.d_natoms;
+ buf = x->x_inbuf1.d_buf;
+ if (natoms >= cnt)
+ {
+ t_atom *from;
+ x->x_locked = 1;
+ for (from = buf; natoms >= cnt; natoms -= cnt, from += cnt)
+ zl_output(x, cnt, from);
+ x->x_inbuf1.d_natoms = natoms;
+ while (natoms--) *buf++ = *from++;
+ }
+ }
+ else x->x_inbuf1.d_natoms = 0; /* CHECKED */
+}
+
+static int zl_iter_intarg(t_zl *x, int i)
+{
+ return (i > 0 ? i : 0); /* CHECKED */
+}
+
+static int zl_iter_count(t_zl *x)
+{
+ return (x->x_entered ?
+ (x->x_modearg < x->x_inbuf1.d_natoms ?
+ x->x_modearg : x->x_inbuf1.d_natoms)
+ : 0);
+}
+
+static void zl_iter(t_zl *x, int natoms, t_atom *buf)
+{
+ int nremaining = x->x_inbuf1.d_natoms;
+ t_atom *ptr = x->x_inbuf1.d_buf;
+ if (!buf)
+ {
+ if (natoms = (x->x_modearg < nremaining ?
+ x->x_modearg : nremaining))
+ x->x_locked = 1;
+ else
+ return;
+ }
+ while (nremaining)
+ {
+ if (natoms > nremaining)
+ natoms = nremaining;
+ if (buf)
+ {
+ memcpy(buf, ptr, natoms * sizeof(*buf));
+ zl_output(x, natoms, buf);
+ }
+ else zl_output(x, natoms, ptr);
+ nremaining -= natoms;
+ ptr += natoms;
+ }
+}
+
+static int zl_join_count(t_zl *x)
+{
+ return (x->x_inbuf1.d_natoms + x->x_inbuf2.d_natoms);
+}
+
+static void zl_join(t_zl *x, int natoms, t_atom *buf)
+{
+ if (buf)
+ {
+ int ac1 = x->x_inbuf1.d_natoms, ac2 = x->x_inbuf2.d_natoms;
+ if (ac1)
+ memcpy(buf, x->x_inbuf1.d_buf, ac1 * sizeof(*buf));
+ if (ac2)
+ memcpy(buf + ac1, x->x_inbuf2.d_buf, ac2 * sizeof(*buf));
+ zl_output(x, natoms, buf);
+ }
+}
+
+static int zl_len_count(t_zl *x)
+{
+ return (0);
+}
+
+static void zl_len(t_zl *x, int natoms, t_atom *buf)
+{
+ outlet_float(((t_object *)x)->ob_outlet, x->x_inbuf1.d_natoms);
+}
+
+static int zl_nth_intarg(t_zl *x, int i)
+{
+ return (i > 0 ? i : 0); /* CHECKED */
+}
+
+static void zl_nth_anyarg(t_zl *x, t_symbol *s, int ac, t_atom *av)
+{
+ if (!s && ac && av->a_type == A_FLOAT)
+ zldata_setlist(&x->x_inbuf2, ac - 1, av + 1);
+}
+
+static int zl_nth_count(t_zl *x)
+{
+ int ac1 = x->x_inbuf1.d_natoms;
+ if (ac1)
+ {
+ if (x->x_modearg > 0)
+ return (ac1 - 1 + x->x_inbuf2.d_natoms);
+ else
+ return (x->x_entered ? ac1 : 0);
+ }
+ else return (-1);
+}
+
+static void zl_nth(t_zl *x, int natoms, t_atom *buf)
+{
+ int ac1 = x->x_inbuf1.d_natoms,
+ ndx = x->x_modearg - 1; /* CHECKED one-based */
+ if (ac1 && ndx < ac1) /* CHECKED */
+ {
+ t_atom *av1 = x->x_inbuf1.d_buf;
+ if (ndx < 0)
+ {
+ if (buf) memcpy(buf, av1, ac1 * sizeof(*buf));
+ else
+ {
+ buf = av1;
+ x->x_locked = 1;
+ }
+ zl_output2(x, ac1, buf);
+ }
+ else
+ {
+ t_atom at = av1[ndx];
+ if (buf)
+ {
+ int ac2 = x->x_inbuf2.d_natoms, ntail = ac1 - ndx + 1;
+ t_atom *ptr = buf;
+ if (ndx)
+ {
+ memcpy(ptr, av1, ndx * sizeof(*buf));
+ ptr += ndx;
+ }
+ if (ac2)
+ {
+ memcpy(ptr, x->x_inbuf2.d_buf, ac2 * sizeof(*buf));
+ ptr += ac2;
+ }
+ if (ntail)
+ memcpy(ptr, av1 + ndx + 1, ntail * sizeof(*buf));
+ zl_output2(x, natoms, buf);
+ }
+ zl_output(x, 1, &at);
+ }
+ }
+}
+
+static void zl_reg_anyarg(t_zl *x, t_symbol *s, int ac, t_atom *av)
+{
+ if (!x->x_locked)
+ zldata_set(&x->x_inbuf1, s, ac, av);
+}
+
+static int zl_reg_count(t_zl *x)
+{
+ return (x->x_entered ? x->x_inbuf1.d_natoms : 0);
+}
+
+static void zl_reg(t_zl *x, int natoms, t_atom *buf)
+{
+ if (buf) memcpy(buf, x->x_inbuf1.d_buf, natoms * sizeof(*buf));
+ else
+ {
+ natoms = x->x_inbuf1.d_natoms;
+ buf = x->x_inbuf1.d_buf;
+ x->x_locked = 1;
+ }
+ if (natoms)
+ zl_output(x, natoms, buf);
+}
+
+static int zl_rev_count(t_zl *x)
+{
+ return (x->x_inbuf1.d_natoms);
+}
+
+static void zl_rev(t_zl *x, int natoms, t_atom *buf)
+{
+ if (buf)
+ {
+ t_atom *from = x->x_inbuf1.d_buf, *to = buf + natoms;
+ while (to-- > buf)
+ *to = *from++;
+ zl_output(x, natoms, buf);
+ }
+}
+
+static int zl_rot_intarg(t_zl *x, int i)
+{
+ return (i); /* CHECKED anything goes (modulo) */
+}
+
+static int zl_rot_count(t_zl *x)
+{
+ return (x->x_inbuf1.d_natoms);
+}
+
+static void zl_rot(t_zl *x, int natoms, t_atom *buf)
+{
+ if (buf)
+ {
+ int cnt1 = x->x_modearg, cnt2;
+ if (cnt1)
+ {
+ if (cnt1 > 0)
+ {
+ cnt1 %= natoms;
+ cnt2 = natoms - cnt1;
+ }
+ else
+ {
+ cnt2 = -cnt1 % natoms;
+ cnt1 = natoms - cnt2;
+ }
+ /* CHECKED right rotation for positive args */
+ memcpy(buf, x->x_inbuf1.d_buf + cnt2, cnt1 * sizeof(*buf));
+ memcpy(buf + cnt1, x->x_inbuf1.d_buf, cnt2 * sizeof(*buf));
+ }
+ else memcpy(buf, x->x_inbuf1.d_buf, natoms * sizeof(*buf));
+ zl_output(x, natoms, buf);
+ }
+}
+
+/* LATER rethink */
+static int zl_sect_count(t_zl *x)
+{
+ int result = 0;
+ int ac1 = x->x_inbuf1.d_natoms, ac2 = x->x_inbuf2.d_natoms, i1;
+ t_atom *av1 = x->x_inbuf1.d_buf, *av2 = x->x_inbuf2.d_buf, *ap1;
+ for (i1 = 0, ap1 = av1; i1 < ac1; i1++, ap1++)
+ {
+ int i2;
+ t_atom *testp;
+ for (i2 = 0, testp = av1; i2 < i1; i2++, testp++)
+ if (zl_equal(ap1, testp))
+ goto skip;
+ for (i2 = 0, testp = av2; i2 < ac2; i2++, testp++)
+ {
+ if (zl_equal(ap1, testp))
+ {
+ result++;
+ break;
+ }
+ }
+ skip:;
+ }
+ return (result);
+}
+
+/* CHECKED in-buffer duplicates are skipped */
+static void zl_sect(t_zl *x, int natoms, t_atom *buf)
+{
+ if (buf)
+ {
+ int ac1 = x->x_inbuf1.d_natoms, ac2 = x->x_inbuf2.d_natoms, i1;
+ t_atom *ap1 = x->x_inbuf1.d_buf, *av2 = x->x_inbuf2.d_buf, *to = buf;
+ for (i1 = 0; i1 < ac1; i1++, ap1++)
+ {
+ int i2;
+ t_atom *testp;
+ for (testp = buf; testp < to; testp++)
+ if (zl_equal(ap1, testp))
+ goto skip;
+ for (i2 = 0, testp = av2; i2 < ac2; i2++, testp++)
+ {
+ if (zl_equal(ap1, testp))
+ {
+ *to++ = *ap1;
+ break;
+ }
+ }
+ skip:;
+ }
+ zl_output(x, natoms, buf);
+ }
+}
+
+static int zl_slice_intarg(t_zl *x, int i)
+{
+ return (i > 0 ? i : 0); /* CHECKED */
+}
+
+static int zl_slice_count(t_zl *x)
+{
+ return (x->x_entered ? -1 : 0);
+}
+
+static void zl_slice(t_zl *x, int natoms, t_atom *buf)
+{
+ int cnt1 = x->x_modearg, cnt2;
+ natoms = x->x_inbuf1.d_natoms;
+ buf = x->x_inbuf1.d_buf;
+ if (cnt1 > natoms)
+ cnt1 = natoms, cnt2 = 0; /* CHECKED */
+ else
+ cnt2 = natoms - cnt1;
+ x->x_locked = 1;
+ if (cnt2)
+ zl_output2(x, cnt2, buf + cnt1);
+ if (cnt1)
+ zl_output(x, cnt1, buf);
+}
+
+static int zl_sub_count(t_zl *x)
+{
+ return (0);
+}
+
+static void zl_sub(t_zl *x, int natoms, t_atom *buf)
+{
+ int natoms2 = x->x_inbuf2.d_natoms;
+ if (natoms2)
+ {
+ int ndx1, natoms1 = x->x_inbuf1.d_natoms;
+ t_atom *av1 = x->x_inbuf1.d_buf, *av2 = x->x_inbuf2.d_buf;
+ for (ndx1 = 0; ndx1 < natoms1; ndx1++, av1++)
+ {
+ int ndx2;
+ t_atom *ap1 = av1, *ap2 = av2;
+ for (ndx2 = 0; ndx2 < natoms2; ndx2++, ap1++, ap2++)
+ if (!zl_equal(ap1, ap2))
+ break;
+ if (ndx2 == natoms2)
+ /* CHECKED output position is zero-based */
+ outlet_float(((t_object *)x)->ob_outlet, ndx1);
+ }
+ }
+}
+
+/* LATER rethink */
+static int zl_union_count(t_zl *x)
+{
+ int result, ac1 = x->x_inbuf1.d_natoms, ac2 = x->x_inbuf2.d_natoms, i2;
+ t_atom *av1 = x->x_inbuf1.d_buf, *ap2 = x->x_inbuf2.d_buf;
+ result = ac1 + ac2;
+ for (i2 = 0; i2 < ac2; i2++, ap2++)
+ {
+ int i1;
+ t_atom *ap1;
+ for (i1 = 0, ap1 = av1; i1 < ac1; i1++, ap1++)
+ {
+ if (zl_equal(ap1, ap2))
+ {
+ result--;
+ break;
+ }
+ }
+ }
+ return (result);
+}
+
+/* CHECKED in-buffer duplicates not skipped */
+static void zl_union(t_zl *x, int natoms, t_atom *buf)
+{
+ if (buf)
+ {
+ int ac1 = x->x_inbuf1.d_natoms, ac2 = x->x_inbuf2.d_natoms, i2;
+ t_atom *av1 = x->x_inbuf1.d_buf, *ap2 = x->x_inbuf2.d_buf;
+ if (ac1)
+ {
+ t_atom *to = buf + ac1;
+ memcpy(buf, av1, ac1 * sizeof(*buf));
+ for (i2 = 0; i2 < ac2; i2++, ap2++)
+ {
+ int i1;
+ t_atom *ap1;
+ for (i1 = 0, ap1 = av1; i1 < ac1; i1++, ap1++)
+ if (zl_equal(ap1, ap2))
+ break;
+ if (i1 == ac1)
+ *to++ = *ap2;
+ }
+ }
+ else memcpy(buf, ap2, ac2 * sizeof(*buf));
+ zl_output(x, natoms, buf);
+ }
+}
+
+static void zl_doit(t_zl *x)
+{
+ int reentered = x->x_entered;
+ int prealloc = !reentered;
+ int natoms = (*zl_natomsfn[x->x_mode])(x);
+ if (natoms < 0)
+ return;
+ x->x_entered = 1;
+ if (natoms)
+ {
+ t_zldata *d = &x->x_outbuf;
+ t_atom *buf;
+ if (prealloc && natoms > d->d_size)
+ {
+ if (natoms > ZL_MAXSIZE)
+ prealloc = 0;
+ else
+ {
+ int nrequested = natoms;
+ d->d_buf = grow_nodata(&nrequested, &d->d_size, d->d_buf,
+ ZL_INISIZE, d->d_bufini,
+ sizeof(*d->d_buf));
+ if (nrequested != natoms)
+ prealloc = 0;
+ }
+ }
+ /* LATER consider using the stack if !prealloc && natoms <= MAXSTACK */
+ if (buf = (prealloc ? d->d_buf : getbytes(natoms * sizeof(*buf))))
+ {
+ (*zl_doitfn[x->x_mode])(x, natoms, buf);
+ if (buf != d->d_buf)
+ freebytes(buf, natoms * sizeof(*buf));
+ }
+ }
+ else (*zl_doitfn[x->x_mode])(x, 0, 0);
+ if (!reentered)
+ x->x_entered = x->x_locked = 0;
+}
+
+static void zl_bang(t_zl *x)
+{
+ /* CHECKED bang is a nop in len mode, LATER consider emulating this */
+ /* CHECKED 'mode len, bang'->[zl]->[print] crashes max 4.0.7... */
+ zl_doit(x);
+}
+
+static void zl_float(t_zl *x, t_float f)
+{
+ if (!x->x_locked)
+ {
+ if (zl_modeflags[x->x_mode])
+ zldata_addfloat(&x->x_inbuf1, f);
+ else
+ zldata_setfloat(&x->x_inbuf1, f);
+ }
+ zl_doit(x);
+}
+
+static void zl_symbol(t_zl *x, t_symbol *s)
+{
+ if (!x->x_locked)
+ {
+ if (zl_modeflags[x->x_mode])
+ zldata_addsymbol(&x->x_inbuf1, s);
+ else
+ zldata_setsymbol(&x->x_inbuf1, s);
+ }
+ zl_doit(x);
+}
+
+/* LATER gpointer */
+
+static void zl_list(t_zl *x, t_symbol *s, int ac, t_atom *av)
+{
+ if (!x->x_locked)
+ {
+ if (zl_modeflags[x->x_mode])
+ zldata_addlist(&x->x_inbuf1, ac, av);
+ else
+ zldata_setlist(&x->x_inbuf1, ac, av);
+ }
+ zl_doit(x);
+}
+
+static void zl_anything(t_zl *x, t_symbol *s, int ac, t_atom *av)
+{
+ if (!x->x_locked)
+ {
+ if (zl_modeflags[x->x_mode])
+ zldata_add(&x->x_inbuf1, s, ac, av);
+ else
+ zldata_set(&x->x_inbuf1, s, ac, av);
+ }
+ zl_doit(x);
+}
+
+static int zl_modeargfn(t_zl *x)
+{
+ return (zl_intargfn[x->x_mode] || zl_anyargfn[x->x_mode]);
+}
+
+static void zl_setmodearg(t_zl *x, t_symbol *s, int ac, t_atom *av)
+{
+ if (zl_intargfn[x->x_mode])
+ {
+ int i = (!s && ac && av->a_type == A_FLOAT ?
+ (int)av->a_w.w_float : /* CHECKED silent truncation */
+ 0); /* CHECKED current x->x_modearg not kept */
+ x->x_modearg = (*zl_intargfn[x->x_mode])(x, i);
+ }
+ if (zl_anyargfn[x->x_mode])
+ (*zl_anyargfn[x->x_mode])(x, s, ac, av);
+}
+
+static void zl_mode(t_zl *x, t_symbol *s, int ac, t_atom *av)
+{
+ if (ac && av->a_type == A_SYMBOL)
+ {
+ t_symbol *modesym = av->a_w.w_symbol;
+ int i;
+ for (i = 0; i < zl_nmodes; i++)
+ if (modesym == zl_modesym[i])
+ break;
+ /* LATER consider making this compatible:
+ CHECKED setting unknown mode makes a zl nop */
+ if (i && i < zl_nmodes)
+ {
+ x->x_mode = i;
+ zl_setmodearg(x, 0, ac - 1, av + 1);
+ }
+ }
+}
+
+static void zlproxy_bang(t_zlproxy *d)
+{
+ /* CHECKED a nop */
+}
+
+static void zlproxy_float(t_zlproxy *p, t_float f)
+{
+ t_zl *x = p->p_master;
+ if (zl_modeargfn(x))
+ {
+ t_atom at;
+ SETFLOAT(&at, f);
+ zl_setmodearg(x, 0, 1, &at);
+ }
+ else /* CHECKED inbuf2 filled only when used */
+ zldata_setfloat(&x->x_inbuf2, f);
+}
+
+static void zlproxy_symbol(t_zlproxy *p, t_symbol *s)
+{
+ t_zl *x = p->p_master;
+ if (zl_modeargfn(x))
+ {
+ t_atom at;
+ SETSYMBOL(&at, s);
+ zl_setmodearg(x, 0, 1, &at);
+ }
+ else /* CHECKED inbuf2 filled only when used */
+ zldata_setsymbol(&x->x_inbuf2, s);
+}
+
+/* LATER gpointer */
+
+static void zlproxy_list(t_zlproxy *p, t_symbol *s, int ac, t_atom *av)
+{
+ if (ac)
+ {
+ t_zl *x = p->p_master;
+ if (zl_modeargfn(x))
+ zl_setmodearg(x, 0, ac, av);
+ else /* CHECKED inbuf2 filled only when used */
+ zldata_setlist(&x->x_inbuf2, ac, av);
+ }
+}
+
+static void zlproxy_anything(t_zlproxy *p, t_symbol *s, int ac, t_atom *av)
+{
+ t_zl *x = p->p_master;
+ if (zl_modeargfn(x))
+ zl_setmodearg(x, s, ac, av);
+ else /* CHECKED inbuf2 filled only when used */
+ zldata_set(&x->x_inbuf2, s, ac, av);
+}
+
+#ifdef ZL_DEBUG
+static void zl_debug(t_zl *x, t_floatarg f)
+{
+ startpost("mode %s", zl_modesym[x->x_mode]->s_name);
+ if (zl_intargfn[x->x_mode])
+ post(" %d", x->x_modearg);
+ else
+ endpost();
+ if ((int)f)
+ {
+ startpost("first:");
+ postatom(x->x_inbuf1.d_natoms, x->x_inbuf1.d_buf);
+ endpost();
+ startpost("second:");
+ postatom(x->x_inbuf2.d_natoms, x->x_inbuf2.d_buf);
+ endpost();
+ }
+}
+#endif
+
+static void zl_free(t_zl *x)
+{
+ zldata_free(&x->x_inbuf1);
+ zldata_free(&x->x_inbuf2);
+ zldata_free(&x->x_outbuf);
+ if (x->x_proxy) pd_free((t_pd *)x->x_proxy);
+}
+
+static void *zl_new(t_symbol *s, int ac, t_atom *av)
+{
+ t_zl *x = (t_zl *)pd_new(zl_class);
+ t_zlproxy *y = (t_zlproxy *)pd_new(zlproxy_class);
+ x->x_proxy = y;
+ y->p_master = x;
+ x->x_entered = 0;
+ x->x_locked = 0;
+ zldata_init(&x->x_inbuf1);
+ zldata_init(&x->x_inbuf2);
+ zldata_init(&x->x_outbuf);
+ x->x_mode = ZL_DEFMODE;
+ zl_mode(x, s, ac, av);
+ inlet_new((t_object *)x, (t_pd *)y, 0, 0);
+ outlet_new((t_object *)x, &s_anything);
+ x->x_out2 = outlet_new((t_object *)x, &s_anything);
+ return (x);
+}
+
+static void zl_setupmode(char *id, int flags,
+ t_zlintargfn ifn, t_zlanyargfn afn,
+ t_zlnatomsfn nfn, t_zldoitfn dfn)
+{
+ if (zl_nmodes < ZL_MAXMODES)
+ {
+ zl_modesym[zl_nmodes] = gensym(id);
+ zl_modeflags[zl_nmodes] = flags;
+ zl_intargfn[zl_nmodes] = ifn;
+ zl_anyargfn[zl_nmodes] = afn;
+ zl_natomsfn[zl_nmodes] = nfn;
+ zl_doitfn[zl_nmodes] = dfn;
+ zl_nmodes++;
+ }
+ else bug("zl_setupmode");
+}
+
+static void zl_setupallmodes(void)
+{
+ zl_setupmode("unknown", 0, 0, 0, zl_nop_count, zl_nop);
+ zl_setupmode("ecils", 0, zl_ecils_intarg, 0, zl_ecils_count, zl_ecils);
+ zl_setupmode("group", 1, zl_group_intarg, 0, zl_group_count, zl_group);
+ zl_setupmode("iter", 0, zl_iter_intarg, 0, zl_iter_count, zl_iter);
+ zl_setupmode("join", 0, 0, 0, zl_join_count, zl_join);
+ zl_setupmode("len", 0, 0, 0, zl_len_count, zl_len);
+ zl_setupmode("nth", 0, zl_nth_intarg, zl_nth_anyarg, zl_nth_count, zl_nth);
+ zl_setupmode("reg", 0, 0, zl_reg_anyarg, zl_reg_count, zl_reg);
+ zl_setupmode("rev", 0, 0, 0, zl_rev_count, zl_rev);
+ zl_setupmode("rot", /* CHECKED (refman error) */
+ 0, zl_rot_intarg, 0, zl_rot_count, zl_rot);
+ zl_setupmode("sect", 0, 0, 0, zl_sect_count, zl_sect);
+ zl_setupmode("slice", 0, zl_slice_intarg, 0, zl_slice_count, zl_slice);
+ zl_setupmode("sub", 0, 0, 0, zl_sub_count, zl_sub);
+ zl_setupmode("union", 0, 0, 0, zl_union_count, zl_union);
+}
+
+void zl_setup(void)
+{
+ zl_class = class_new(gensym("zl"),
+ (t_newmethod)zl_new,
+ (t_method)zl_free,
+ sizeof(t_zl), 0,
+ A_GIMME, 0);
+ class_addbang(zl_class, zl_bang);
+ class_addfloat(zl_class, zl_float);
+ class_addsymbol(zl_class, zl_symbol);
+ class_addlist(zl_class, zl_list);
+ class_addanything(zl_class, zl_anything);
+ class_addmethod(zl_class, (t_method)zl_mode,
+ gensym("mode"), A_GIMME, 0);
+#ifdef ZL_DEBUG
+ class_addmethod(zl_class, (t_method)zl_debug,
+ gensym("debug"), A_DEFFLOAT, 0);
+#endif
+ zlproxy_class = class_new(gensym("_zlproxy"), 0, 0,
+ sizeof(t_zlproxy),
+ CLASS_PD | CLASS_NOINLET, 0);
+ class_addbang(zlproxy_class, zlproxy_bang);
+ class_addfloat(zlproxy_class, zlproxy_float);
+ class_addsymbol(zlproxy_class, zlproxy_symbol);
+ class_addlist(zlproxy_class, zlproxy_list);
+ class_addanything(zlproxy_class, zlproxy_anything);
+ zl_setupallmodes();
+}
diff --git a/cyclone/shadow/Makefile b/cyclone/shadow/Makefile
new file mode 100644
index 0000000..b700e5e
--- /dev/null
+++ b/cyclone/shadow/Makefile
@@ -0,0 +1,7 @@
+ROOT_DIR = ../..
+redefault: default $(ROOT_DIR)/bin/cyclist
+include $(ROOT_DIR)/Makefile.common
+
+$(ROOT_DIR)/bin/cyclist: $(SHARED_DIR)/common/binport.c
+ $(CC) -DBINPORT_STANDALONE -o $@ $<
+
diff --git a/cyclone/shadow/Makefile.objects b/cyclone/shadow/Makefile.objects
new file mode 100644
index 0000000..f77675c
--- /dev/null
+++ b/cyclone/shadow/Makefile.objects
@@ -0,0 +1,9 @@
+SHARED_OBJECTS = \
+common/loud.o \
+common/grow.o \
+common/binport.o \
+common/port.o \
+hammer/file.o \
+sickle/sic.o \
+unstable/fragile.o \
+unstable/loader.o
diff --git a/cyclone/shadow/Makefile.sources b/cyclone/shadow/Makefile.sources
new file mode 100644
index 0000000..8ba4681
--- /dev/null
+++ b/cyclone/shadow/Makefile.sources
@@ -0,0 +1,6 @@
+CX_SOURCES = \
+cyclone.c
+
+OTHER_SOURCES = \
+nettles.c \
+dummies.c
diff --git a/cyclone/shadow/cyclone.c b/cyclone/shadow/cyclone.c
new file mode 100644
index 0000000..047d39d
--- /dev/null
+++ b/cyclone/shadow/cyclone.c
@@ -0,0 +1,159 @@
+/* Copyright (c) 2003 krzYszcz and others.
+ * For information on usage and redistribution, and for a DISCLAIMER OF ALL
+ * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
+
+/* Never use forked calls in shadow code... */
+
+#include <stdio.h>
+#include "m_pd.h"
+#include "common/loud.h"
+#include "common/port.h"
+#include "hammer/file.h"
+#include "unstable/fragile.h"
+#include "unstable/loader.h"
+#include "shadow.h"
+#include "../build_counter"
+
+typedef struct _cyclone
+{
+ t_object x_ob;
+ t_symbol *x_dir;
+ t_hammerfile *x_filehandle;
+} t_cyclone;
+
+static t_class *cyclone_class;
+static int cyclone_hammerndx;
+static int cyclone_sicklendx;
+static int cyclone_nettlesndx;
+static int cyclone_dummiesndx;
+static int cyclone_lastndx;
+
+static void cyclone_readhook(t_pd *z, t_symbol *fn, int ac, t_atom *av)
+{
+ import_max(fn->s_name, "");
+}
+
+static void cyclone_import(t_cyclone *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 cyclone_click(t_cyclone *x, t_floatarg xpos, t_floatarg ypos,
+ t_floatarg shift, t_floatarg ctrl, t_floatarg alt)
+{
+ cyclone_import(x, 0, 0);
+}
+
+static void cyclone_bang(t_cyclone *x)
+{
+ int i;
+ fragile_class_printnames("hammer classes are: ",
+ cyclone_hammerndx, cyclone_sicklendx - 1);
+ fragile_class_printnames("sickle classes are: ",
+ cyclone_sicklendx, cyclone_nettlesndx - 1);
+ fragile_class_printnames("nettles are: ",
+ cyclone_nettlesndx, cyclone_dummiesndx - 1);
+ if (i = dummy_nreplacements())
+ post("send 'reps' message to see the list of %d \
+replacement abstractions", i);
+ else
+ post("no replacement abstractions");
+ post("send 'dummies' message to see the list of %d dummy classes",
+ /* cyclone_lastndx points to the "_dummy" sentinel class */
+ cyclone_lastndx - cyclone_dummiesndx);
+}
+
+static void cyclone_reps(t_cyclone *x)
+{
+ if (dummy_nreplacements())
+ dummy_printreplacements("replacement abstractions are: ");
+ else
+ post("no replacement abstractions");
+}
+
+static void cyclone_dummies(t_cyclone *x)
+{
+ fragile_class_printnames("dummies are: ",
+ cyclone_dummiesndx, cyclone_lastndx);
+}
+
+static void cyclone_free(t_cyclone *x)
+{
+ hammerfile_free(x->x_filehandle);
+}
+
+static void *cyclone_new(t_symbol *s)
+{
+ t_cyclone *x = (t_cyclone *)pd_new(cyclone_class);
+ x->x_filehandle = hammerfile_new((t_pd *)x, 0, cyclone_readhook, 0, 0);
+ x->x_dir = (s && s != &s_ ? s : canvas_getdir(x->x_filehandle->f_canvas));
+ return (x);
+}
+
+void cyclone_setup(void)
+{
+ int hresult, sresult;
+ hresult = sresult = LOADER_OK;
+ 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 'cyclone' object");
+ loud_errand(0, "without having cyclone library preloaded");
+ return;
+ }
+ post("this is cyclone %s, %s %s build",
+ CYCLONE_VERSION, loud_ordinal(CYCLONE_BUILD), CYCLONE_RELEASE);
+ cyclone_class = class_new(gensym("cyclone"),
+ (t_newmethod)cyclone_new,
+ (t_method)cyclone_free,
+ sizeof(t_cyclone), 0, A_DEFSYM, 0);
+ class_addbang(cyclone_class, cyclone_bang);
+ class_addmethod(cyclone_class, (t_method)cyclone_reps,
+ gensym("reps"), 0);
+ class_addmethod(cyclone_class, (t_method)cyclone_dummies,
+ gensym("dummies"), 0);
+ class_addmethod(cyclone_class, (t_method)cyclone_import,
+ gensym("import"), A_DEFSYM, A_DEFSYM, 0);
+ class_addmethod(cyclone_class, (t_method)cyclone_click,
+ gensym("click"),
+ A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0);
+ hammerfile_setup(cyclone_class, 0);
+
+ cyclone_hammerndx = fragile_class_count();
+ if (zgetfn(&pd_objectmaker, gensym("hammer")))
+ loud_warning(0, "hammer is already loaded");
+ else
+ hresult = unstable_load_lib("", "hammer");
+
+ cyclone_sicklendx = fragile_class_count();
+ if (zgetfn(&pd_objectmaker, gensym("sickle")))
+ loud_warning(0, "sickle is already loaded");
+ else
+ sresult = unstable_load_lib("", "sickle");
+
+ cyclone_nettlesndx = fragile_class_count();
+ allnettles_setup();
+
+ cyclone_dummiesndx = fragile_class_count();
+ alldummies_setup();
+ cyclone_lastndx = fragile_class_count() - 1;
+
+ if (hresult == LOADER_NOFILE)
+ loud_error(0, "hammer library is missing");
+ else if (sresult == LOADER_NOFILE)
+ loud_error(0, "sickle library is missing");
+ else if (!zgetfn(&pd_objectmaker, gensym("hammer")) ||
+ !zgetfn(&pd_objectmaker, gensym("sickle")))
+ {
+ loud_error(0, "version mismatch");
+ loud_errand(0,
+ "use a more recent Pd release (or recompile the cyclone).");
+ }
+}
diff --git a/cyclone/shadow/dummies.c b/cyclone/shadow/dummies.c
new file mode 100644
index 0000000..272fd45
--- /dev/null
+++ b/cyclone/shadow/dummies.c
@@ -0,0 +1,664 @@
+/* Copyright (c) 2003 krzYszcz and others.
+ * For information on usage and redistribution, and for a DISCLAIMER OF ALL
+ * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
+
+#include <string.h>
+#ifdef UNIX
+#include <unistd.h>
+#endif
+#ifdef NT
+#include <io.h>
+#endif
+#include "m_pd.h"
+#include "common/loud.h"
+#include "shadow.h"
+
+static int dummy_nclasses = 0;
+static t_class **dummy_classes;
+static int dummy_nreps = 0;
+
+typedef struct _dummy_slot
+{
+ char *s_name;
+ int s_nins;
+ int s_nouts;
+ int s_warned;
+ t_newmethod s_method; /* a specialized constructor */
+} t_dummy_slot;
+
+static t_object *dummy_newobject(t_symbol *s, t_dummy_slot **slotp);
+static void dummy_io(t_object *x, int nins, int nouts);
+
+static void *dummy_2dwave_tilde_new(t_symbol *s, int ac, t_atom *av)
+{
+ t_dummy_slot *sl;
+ t_object *x = dummy_newobject(s, &sl);
+ int nouts = 0;
+ if (ac && av->a_type == A_SYMBOL)
+ {
+ if (ac > 3 && av[3].a_type == A_FLOAT)
+ nouts = (int)av[3].a_w.w_float;
+ }
+ else loud_classarg(*(t_pd *)x);
+ if (nouts < 1)
+ nouts = 1;
+ dummy_io(x, sl->s_nins, nouts);
+ return (x);
+}
+
+static void *dummy_adoutput_tilde_new(t_symbol *s, int ac, t_atom *av)
+{
+ t_dummy_slot *sl;
+ t_object *x = dummy_newobject(s, &sl);
+ int nouts = 0;
+ while (ac--)
+ {
+ if (av++->a_type == A_FLOAT) nouts++;
+ else
+ {
+ loud_classarg(*(t_pd *)x);
+ break;
+ }
+ }
+ if (nouts < 1)
+ nouts = 2;
+ dummy_io(x, sl->s_nins, nouts);
+ return (x);
+}
+
+static void *dummy_fffb_tilde_new(t_symbol *s, int ac, t_atom *av)
+{
+ t_dummy_slot *sl;
+ t_object *x = dummy_newobject(s, &sl);
+ int nouts = 0;
+ if (ac && av->a_type == A_FLOAT)
+ nouts = (int)av->a_w.w_float;
+ if (nouts < 1)
+ {
+ loud_classarg(*(t_pd *)x);
+ nouts = 1;
+ }
+ dummy_io(x, sl->s_nins, nouts);
+ return (x);
+}
+
+static void *dummy_gate_tilde_new(t_symbol *s, int ac, t_atom *av)
+{
+ t_dummy_slot *sl;
+ t_object *x = dummy_newobject(s, &sl);
+ int nouts = 0;
+ if (ac && av->a_type == A_FLOAT)
+ nouts = (int)av->a_w.w_float;
+ if (nouts < 1)
+ nouts = 1;
+ dummy_io(x, sl->s_nins, nouts);
+ return (x);
+}
+
+static void *dummy_groove_tilde_new(t_symbol *s, int ac, t_atom *av)
+{
+ t_dummy_slot *sl;
+ t_object *x = dummy_newobject(s, &sl);
+ int nouts = 0;
+ if (ac && av->a_type == A_SYMBOL)
+ {
+ if (ac > 1 && av[1].a_type == A_FLOAT)
+ nouts = (int)av[1].a_w.w_float;
+ }
+ else loud_classarg(*(t_pd *)x);
+ if (nouts < 1)
+ nouts = 1;
+ dummy_io(x, sl->s_nins, nouts + 1);
+ return (x);
+}
+
+/* FIXME */
+static void *dummy_if_new(t_symbol *s, int ac, t_atom *av)
+{
+ t_object *x = dummy_newobject(s, 0);
+ int nins = 0;
+ int nouts = 1;
+ t_symbol *ps_out2 = gensym("out2");
+ while (ac--)
+ {
+ if (av->a_type == A_SYMBOL)
+ {
+ if (av->a_w.w_symbol == ps_out2)
+ nouts = 2;
+ else
+ {
+ char *name = av->a_w.w_symbol->s_name;
+ if (strlen(name) >= 3 && *name == '$')
+ {
+ char c = name[2];
+ if (c > '1' && c <= '9' && c > '0' + nins)
+ nins = c - '0';
+ }
+ }
+ }
+ av++;
+ }
+ dummy_io(x, nins, nouts);
+ return (x);
+}
+
+static void *dummy_matrix_tilde_new(t_symbol *s, int ac, t_atom *av)
+{
+ t_dummy_slot *sl;
+ t_object *x = dummy_newobject(s, &sl);
+ int nins = 0, nouts = 0;
+ if (ac && av->a_type == A_FLOAT)
+ {
+ nins = (int)av->a_w.w_float;
+ if (ac > 1 && av[1].a_type == A_FLOAT)
+ nouts = (int)av[1].a_w.w_float;
+ }
+ if (nins < 1 || nouts < 1)
+ {
+ loud_classarg(*(t_pd *)x);
+ if (nins < 1) nins = 1;
+ if (nouts < 1) nouts = 1;
+ }
+ dummy_io(x, nins, nouts + 1); /* CHECKME */
+ return (x);
+}
+
+static void *dummy_mtr_new(t_symbol *s, int ac, t_atom *av)
+{
+ t_dummy_slot *sl;
+ t_object *x = dummy_newobject(s, &sl);
+ int nios = 0;
+ if (ac && av->a_type == A_FLOAT)
+ nios = (int)av->a_w.w_float;
+ if (nios < 1)
+ nios = 1;
+ dummy_io(x, nios + 1, nios + 1);
+ return (x);
+}
+
+/* CHECKME */
+static void *dummy_pong_tilde_new(t_symbol *s, int ac, t_atom *av)
+{
+ t_dummy_slot *sl;
+ t_object *x = dummy_newobject(s, &sl);
+ int nins = 0;
+ if (ac)
+ {
+ if (av->a_type == A_FLOAT)
+ {
+ ac--; av++;
+ if (ac)
+ {
+ if (av->a_type == A_FLOAT) nins = 3;
+ }
+ else nins = 2;
+ }
+ }
+ else nins = 2;
+ if (nins < 1)
+ {
+ loud_classarg(*(t_pd *)x);
+ nins = 2;
+ }
+ dummy_io(x, nins, sl->s_nouts);
+ return (x);
+}
+
+static void *dummy_rewire_tilde_new(t_symbol *s, int ac, t_atom *av)
+{
+ t_dummy_slot *sl;
+ t_object *x = dummy_newobject(s, &sl);
+ int nouts = 0;
+ if (ac && av->a_type == A_FLOAT)
+ nouts = (int)av->a_w.w_float;
+ else if (ac > 1 && av[1].a_type == A_FLOAT)
+ nouts = (int)av[1].a_w.w_float;
+ if (nouts < 1)
+ nouts = 1; /* CHECKME */
+ dummy_io(x, sl->s_nins, nouts + 4);
+ return (x);
+}
+
+static void *dummy_selector_tilde_new(t_symbol *s, int ac, t_atom *av)
+{
+ t_dummy_slot *sl;
+ t_object *x = dummy_newobject(s, &sl);
+ int nins = 0;
+ if (ac && av->a_type == A_FLOAT)
+ nins = (int)av->a_w.w_float;
+ if (nins < 1)
+ nins = 1;
+ dummy_io(x, nins + 1, sl->s_nouts);
+ return (x);
+}
+
+static void *dummy_sfplay_tilde_new(t_symbol *s, int ac, t_atom *av)
+{
+ t_dummy_slot *sl;
+ t_object *x = dummy_newobject(s, &sl);
+ int nouts = 0;
+ if (ac)
+ {
+ if (av->a_type == A_FLOAT)
+ nouts = (int)av->a_w.w_float;
+ else if (ac > 1 && av[1].a_type == A_FLOAT)
+ nouts = (int)av[1].a_w.w_float;
+ }
+ if (nouts < 1)
+ nouts = 1;
+ dummy_io(x, sl->s_nins, nouts + 1);
+ return (x);
+}
+
+static void *dummy_sfrecord_tilde_new(t_symbol *s, int ac, t_atom *av)
+{
+ t_dummy_slot *sl;
+ t_object *x = dummy_newobject(s, &sl);
+ int nins = 0;
+ if (ac && av->a_type == A_FLOAT)
+ nins = (int)av->a_w.w_float;
+ if (nins < 1)
+ nins = 1;
+ dummy_io(x, nins, sl->s_nouts);
+ return (x);
+}
+
+static void *dummy_stutter_tilde_new(t_symbol *s, int ac, t_atom *av)
+{
+ t_dummy_slot *sl;
+ t_object *x = dummy_newobject(s, &sl);
+ int nios = 0;
+ if (ac > 4 && av[4].a_type == A_FLOAT)
+ nios = (int)av[4].a_w.w_float;
+ if (nios < 1)
+ nios = 1;
+ dummy_io(x, nios + 2, nios);
+ return (x);
+}
+
+static void *dummy_sxformat_new(t_symbol *s, int ac, t_atom *av)
+{
+ return (dummy_if_new(s, ac, av)); /* FIXME */
+}
+
+static void *dummy_tapout_tilde_new(t_symbol *s, int ac, t_atom *av)
+{
+ t_dummy_slot *sl;
+ t_object *x = dummy_newobject(s, &sl);
+ int warned = 0, nios = 0;
+ while (ac--)
+ if (av++->a_type == A_FLOAT)
+ nios++;
+ else if (!warned++)
+ loud_classarg(*(t_pd *)x);
+ if (nios < 1)
+ nios = 1;
+ dummy_io(x, nios, nios);
+ return (x);
+}
+
+/* CHECKME */
+static void *dummy_tiCmd_new(t_symbol *s, int ac, t_atom *av)
+{
+ t_dummy_slot *sl;
+ t_object *x = dummy_newobject(s, &sl);
+ int nouts = 0;
+ if (ac > 1)
+ {
+ ac--; av++;
+ while (ac--)
+ {
+ char c = 0;
+ if (av->a_type == A_SYMBOL)
+ {
+ c = *av->a_w.w_symbol->s_name;
+ if (c == 'i' || c == 'f' || c == 'l'
+ || c == 'b' || c == 's' || c == 'a')
+ nouts++;
+ else
+ c = 0;
+ }
+ if (c == 0)
+ {
+ loud_classarg(*(t_pd *)x);
+ break;
+ }
+ av++;
+ }
+ }
+ if (nouts < 1)
+ nouts = 0;
+ dummy_io(x, sl->s_nins, nouts + 2);
+ return (x);
+}
+
+/* CHECKME */
+static void *dummy_timeline_new(t_symbol *s, int ac, t_atom *av)
+{
+ t_dummy_slot *sl;
+ t_object *x = dummy_newobject(s, &sl);
+ int nouts = 0;
+ if (ac)
+ {
+ if (av->a_type == A_FLOAT)
+ nouts = (int)av->a_w.w_float;
+ else if (ac > 1 && av[1].a_type == A_FLOAT)
+ nouts = (int)av[1].a_w.w_float;
+ }
+ if (nouts < 1)
+ nouts = 0;
+ dummy_io(x, sl->s_nins, nouts);
+ return (x);
+}
+
+static void *dummy_vexpr_new(t_symbol *s, int ac, t_atom *av)
+{
+ return (dummy_if_new(s, ac, av)); /* FIXME */
+}
+
+static void *dummy_vst_tilde_new(t_symbol *s, int ac, t_atom *av)
+{
+ t_dummy_slot *sl;
+ t_object *x = dummy_newobject(s, &sl);
+ int nins = 0, nouts = 0;
+ if (ac > 1 && av[1].a_type == A_FLOAT)
+ {
+ if (av->a_type == A_FLOAT)
+ {
+ nins = (int)av->a_w.w_float;
+ nouts = (int)av[1].a_w.w_float;
+ }
+ }
+ else if (ac && av->a_type == A_FLOAT)
+ nouts = (int)av->a_w.w_float;
+ if (nins < 1)
+ nins = 2; /* CHECKME */
+ if (nouts < 1)
+ nouts = 2; /* CHECKME */
+ dummy_io(x, nins, nouts + 4); /* CHECKME */
+ return (x);
+}
+
+static t_dummy_slot dummy_slots[] =
+{
+ { "2d.wave~", 4, -1, 0, (t_newmethod)dummy_2dwave_tilde_new },
+ { "absolutepath", 1, 1, 0, 0 },
+ { "acosh", 1, 1, 0, 0 },
+ { "adoutput~", 1, -1, 0, (t_newmethod)dummy_adoutput_tilde_new },
+ { "adstatus", 2, 2, 0, 0 },
+ { "asinh", 1, 1, 0, 0 },
+ { "atanh", 1, 1, 0, 0 },
+ { "begin~", 0, 1, 0, 0 },
+ { "Biquad~", 6, 1, 0, 0 },
+ /* LATER try mapping bpatcher to a gop abstraction/subpatch */
+ { "buffer~", 1, 2, 0, 0 },
+ { "buffir~", 3, 1, 0, 0 },
+ { "cd", 1, 2, 0, 0 }, /* CHECKED (refman error?) */
+ { "cd~", 1, 6, 0, 0 }, /* CHECKED (refman error?) */
+ { "Change", 1, 3, 0, 0 },
+ { "clocker", 2, 1, 0, 0 },
+ { "closebang", 0, 1, 0, 0 },
+ { "colorpicker", 1, 1, 0, 0 },
+ { "curve~", 3, 2, 0, 0 },
+ { "date", 1, 3, 0, 0 },
+ { "defer", 1, 1, 0, 0 }, /* LATER pass anything through */
+ { "degrade~", 3, 1, 0, 0 },
+ { "detonate", 8, 8, 0, 0 },
+ { "dial", 1, 1, 0, 0 },
+ { "dialog", 2, 1, 0, 0 },
+ { "downsamp~", 2, 1, 0, 0 },
+ { "dropfile", 1, 2, 0, 0 },
+ { "dspstate~", 1, 3, 0, 0 },
+ { "dsptime~", 1, 1, 0, 0 },
+ { "env", 1, 1, 0, 0 },
+ { "envi", 1, 1, 0, 0 },
+ { "error", 1, 1, 0, 0 },
+ { "ezadc~", 1, 2, 0, 0 },
+ { "ezdac~", 2, 0, 0, 0 },
+ { "fffb~", 1, -1, 0, (t_newmethod)dummy_fffb_tilde_new },
+ /* LATER Fft~ */
+ /* LATER pfft~-specific classes: fftin~, fftinfo~, fftout~ */
+ { "filedate", 1, 1, 0, 0 },
+ { "filein", 3, 3, 0, 0 },
+ { "filepath", 1, 1, 0, 0 },
+ { "filtergraph~", 8, 6, 0, 0 },
+ { "folder", 1, 1, 0, 0 }, /* CHECKME 2nd outlet */
+ { "follow", 1, 2, 0, 0 },
+ { "fpic", 1, 0, 0, 0 },
+ { "frame", 6, 0, 0, 0 },
+ { "function", 1, 4, 0, 0 },
+ { "gain~", 2, 2, 0, 0 },
+ { "gate~", 2, -1, 0, (t_newmethod)dummy_gate_tilde_new },
+ { "gestalt", 1, 2, 0, 0 },
+ { "Ggate", 2, 2, 0, 0 },
+ /* LATER glove? */
+ { "graphic", 1, 0, 0, 0 },
+ { "groove~", 3, -1, 0, (t_newmethod)dummy_groove_tilde_new },
+ { "Gswitch", 3, 1, 0, 0 },
+ { "hint", 1, 1, 0, 0 },
+ { "if", -1, -1, 0, (t_newmethod)dummy_if_new },
+ /* LATER Ifft~ */
+ { "imovie", 1, 3, 0, 0 },
+ { "IncDec", 1, 1, 0, 0 },
+ { "info~", 1, 8, 0, 0 }, /* CHECKME nouts */
+ { "ioscbank~", 4, 1, 0, 0 },
+ { "Key", 0, 3, 0, 0 },
+ { "Keyup", 0, 3, 0, 0 },
+ { "kslider", 2, 2, 0, 0 },
+ { "lcd", 1, 4, 0, 0 }, /* CHECKME nouts */
+ { "led", 1, 1, 0, 0 },
+ { "Line", 3, 2, 0, 0 },
+ { "lores~", 3, 1, 0, 0 },
+ { "matrixctrl", 1, 1, 0, 0 }, /* CHECKME nins, nouts */
+ { "matrix~", -1, -1, 0, (t_newmethod)dummy_matrix_tilde_new },
+ { "maximum~", 2, 1, 0, 0 },
+ { "menubar", 1, 4, 0, 0 }, /* LATER parse #Xs (additional outs) */
+ { "meter~", 1, 1, 0, 0 }, /* LATER consider mapping to the vu */
+ { "minimum~", 2, 1, 0, 0 },
+ { "movie", 1, 3, 0, 0 },
+ /* CHECKME msd */
+ { "mstosamps~", 1, 2, 0, 0 },
+ { "mtr", -1, -1, 0, (t_newmethod)dummy_mtr_new },
+ { "multiSlider", 1, 1, 0, 0 },
+ { "mute~", 1, 1, 0, 0 },
+ { "normalize~", 2, 1, 0, 0 },
+ { "number~", 2, 2, 0, 0 },
+ { "numkey", 1, 2, 0, 0 },
+ { "omscontrollers", 4, 2, 0, 0 }, /* CHECKME osx */
+ { "omsinfo", 2, 1, 0, 0 }, /* LATER midiinfo? */
+ { "omsnotes", 4, 2, 0, 0 }, /* CHECKME osx */
+ { "omspatches", 3, 2, 0, 0 }, /* CHECKME osx */
+ { "onecopy", 0, 0, 0, 0 }, /* CHECKME */
+ { "onepole~", 2, 1, 0, 0 },
+ { "opendialog", 1, 2, 0, 0 },
+ { "oscbank~", 4, 1, 0, 0 },
+ { "oval", 6, 0, 0, 0 },
+ { "overdrive~", 2, 1, 0, 0 },
+ { "panel", 1, 0, 0, 0 },
+ { "pass~", 1, 1, 0, 0 },
+ { "pcontrol", 1, 1, 0, 0 },
+ /* LATER pfft~ */
+ { "phaseshift~", 3, 1, 0, 0 },
+ { "pics", 3, 0, 0, 0 }, /* CHECKME */
+ { "pics2", 3, 0, 0, 0 }, /* CHECKME */
+ { "pict", 3, 0, 0, 0 },
+ { "pictctrl", 1, 1, 0, 0 },
+ { "pictslider", 2, 2, 0, 0 }, /* CHECKME one-dimensional mode */
+ { "pink~", 1, 1, 0, 0 }, /* CHECKME inlet */
+ { "playbar", 1, 2, 0, 0 }, /* CHECKME */
+ { "plugconfig", 1, 0, 0, 0 },
+ { "plugin~", 2, 2, 0, 0 },
+ { "plugmidiin", 0, 1, 0, 0 },
+ { "plugmidiout", 1, 0, 0, 0 },
+ { "plugmod", 5, 3, 0, 0 },
+ { "plugmorph", 2, 3, 0, 0 },
+ { "plugmultiparam", 1, 2, 0, 0 },
+ { "plugout~", 2, 2, 0, 0 }, /* CHECKME nouts */
+ { "plugphasor~", 0, 1, 0, 0 }, /* CHECKME nouts */
+ { "plugreceive~", 1, 1, 0, 0 },
+ { "plugsend~", 1, 0, 0, 0 },
+ { "plugstore", 1, 1, 0, 0 }, /* CHECKME nouts */
+ { "plugsync~", 0, 9, 0, 0 }, /* CHECKME nouts */
+ { "poke~", 3, 0, 0, 0 },
+ { "Poly", 2, 4, 0, 0 },
+ { "polyin", 1, 3, 0, 0 }, /* LATER parse args for nouts */
+ { "polyout", 3, 0, 0, 0 }, /* CHECKME nins */
+ /* LATER poly~ */
+ { "pong~", -1, 1, 0, (t_newmethod)dummy_pong_tilde_new },
+ { "pp", 2, 2, 0, 0 }, /* CHECKME nins */
+ { "pptempo", 2, 2, 0, 0 },
+ { "pptime", 4, 4, 0, 0 },
+ { "preset", 1, 3, 0, 0 },
+ { "radiogroup", 1, 1, 0, 0 },
+ { "rate~", 2, 1, 0, 0 }, /* CHECKME */
+ /* LATER settable Receive? */
+ { "rect", 6, 0, 0, 0 },
+ { "relativepath", 1, 1, 0, 0 },
+ { "reson~", 4, 1, 0, 0 },
+ { "rewire~", 1, -1, 0, (t_newmethod)dummy_rewire_tilde_new },
+ { "ring", 6, 0, 0, 0 },
+ { "round~", 2, 1, 0, 0 },
+ { "rslider", 2, 2, 0, 0 },
+ { "rtin", 1, 1, 0, 0 },
+ { "sampstoms~", 1, 2, 0, 0 },
+ { "savedialog", 1, 3, 0, 0 },
+ { "screensize", 1, 2, 0, 0 },
+ { "selector~", -1, 1, 0, (t_newmethod)dummy_selector_tilde_new },
+ { "seq~", 1, 2, 0, 0 },
+ { "serial", 1, 2, 0, 0 },
+ { "setclock", 2, 1, 0, 0 },
+ { "sfinfo~", 1, 6, 0, 0 }, /* CHECKME nouts */
+ { "sflist~", 1, 0, 0, 0 },
+ { "sfplay~", 1, -1, 0, (t_newmethod)dummy_sfplay_tilde_new },
+ { "sfrecord~", -1, 0, 0, (t_newmethod)dummy_sfrecord_tilde_new },
+ { "sndmgrin~", 0, 2, 0, 0 }, /* CHECKME */
+ { "strippath", 1, 2, 0, 0 },
+ { "stutter~", -1, -1, 0, (t_newmethod)dummy_stutter_tilde_new },
+ { "suspend", 0, 1, 0, 0 },
+ { "svf~", 3, 4, 0, 0 },
+ { "swatch", 3, 2, 0, 0 },
+ { "sxformat", -1, 1, 0, (t_newmethod)dummy_sxformat_new },
+ { "sysexin", 1, 1, 0, 0 },
+ { "Table", 2, 2, 0, 0 },
+ { "tapin~", 1, 1, 0, 0 },
+ { "tapout~", -1, -1, 0, (t_newmethod)dummy_tapout_tilde_new },
+ { "teeth~", 6, 1, 0, 0 },
+ { "tempo", 4, 1, 0, 0 },
+ { "Text", 1, 1, 0, 0 },
+ { "textedit", 1, 3, 0, 0 },
+ { "thisobject", 1, 3, 0, 0 }, /* CHECKME */
+ { "thispatcher", 1, 2, 0, 0 },
+ { "thisTimeline", 1, 1, 0, 0 },
+ { "thisTrack", 1, 0, 0, 0 },
+ { "thispoly~", 1, 1, 0, 0 },
+ { "thresh~", 3, 1, 0, 0 },
+ { "tiCmd", 0, -1, 0, (t_newmethod)dummy_tiCmd_new },
+ { "timeline", 1, -1, 0, (t_newmethod)dummy_timeline_new },
+ { "tiOut", 1, 0, 0, 0 },
+ { "timein", 3, 4, 0, 0 },
+ { "timeout", 4, 0, 0, 0 },
+ /* LATER touchin's inlet (Touchin?) */
+ { "trunc~", 1, 1, 0, 0 }, /* CHECKME */
+ { "ubutton", 1, 4, 0, 0 },
+ { "umenu", 1, 2, 0, 0 },
+ { "vdp", 3, 4, 0, 0 },
+ { "vexpr", -1, 1, 0, (t_newmethod)dummy_vexpr_new },
+ { "vpicture", 0, 0, 0, 0 },
+ { "vst~", -1, -1, 0, (t_newmethod)dummy_vst_tilde_new },
+ { "waveform~", 5, 6, 0, 0 }, /* CHECKME */
+ { "zerox~", 1, 2, 0, 0 },
+ { "zigzag~", 2, 4, 0, 0 },
+ { "_dummy", 0, 0, 0, 0 }
+};
+
+static void *dummy_new(t_symbol *s, int ac, t_atom *av)
+{
+ t_dummy_slot *sl;
+ t_object *x = dummy_newobject(s, &sl);
+ dummy_io(x, sl->s_nins, sl->s_nouts);
+ return (x);
+}
+
+static void dummy_io(t_object *x, int nins, int nouts)
+{
+ nins = (nins > 0 ? nins - 1 : 0);
+ while (nins--) inlet_new(x, (t_pd *)x, 0, 0);
+ while (nouts--) outlet_new(x, &s_anything);
+}
+
+static t_object *dummy_newobject(t_symbol *s, t_dummy_slot **slotp)
+{
+ t_object *x;
+ t_dummy_slot *sl;
+ int fnd;
+ for (fnd = 0; fnd < dummy_nclasses; fnd++)
+ /* LATER compare symbols, rather than strings */
+ if (dummy_classes[fnd] /* empty slot: abstraction replacement */
+ && !strcmp(class_getname(dummy_classes[fnd]), s->s_name))
+ break;
+ x = (t_object *)pd_new(dummy_classes[fnd]);
+ sl = &dummy_slots[fnd];
+ if (fnd == dummy_nclasses)
+ bug("dummy_newobject"); /* create a "_dummy" in this case */
+ else if (!sl->s_warned)
+ {
+ loud_warning((t_pd *)x, "dummy substitution");
+ sl->s_warned = 1;
+ }
+ if (slotp) *slotp = sl;
+ return (x);
+}
+
+int dummy_nreplacements(void)
+{
+ return (dummy_nreps);
+}
+
+void dummy_printreplacements(char *msg)
+{
+ int i, len = strlen(msg);
+ t_dummy_slot *sl;
+ startpost(msg);
+ for (i = 0, sl = dummy_slots; i < dummy_nclasses; i++, sl++)
+ {
+ if (!dummy_classes[i])
+ {
+ int l = 1 + strlen(sl->s_name);
+ if ((len += l) > 66)
+ {
+ endpost();
+ startpost(" ");
+ len = 3 + l;
+ }
+ poststring(sl->s_name);
+ }
+ }
+ endpost();
+}
+
+void alldummies_setup(void)
+{
+ t_dummy_slot *sl;
+ int i;
+ dummy_nclasses = sizeof(dummy_slots)/sizeof(*dummy_slots);
+ /* never freed: */
+ dummy_classes = getbytes(dummy_nclasses * sizeof(*dummy_classes));
+ for (i = 0, sl = dummy_slots; i < dummy_nclasses; i++, sl++)
+ {
+ int fd;
+ char dirbuf[MAXPDSTRING], *nameptr;
+ if ((fd = open_via_path("", sl->s_name, ".pd",
+ dirbuf, &nameptr, MAXPDSTRING, 0)) >= 0)
+ {
+ close(fd);
+ dummy_nreps++;
+ }
+ else
+ dummy_classes[i] =
+ class_new(gensym(sl->s_name),
+ sl->s_method ? sl->s_method : (t_newmethod)dummy_new,
+ 0, sizeof(t_object),
+ (sl->s_nins ? 0 : CLASS_NOINLET), A_GIMME, 0);
+ }
+ dummy_nclasses--; /* use "_dummy" as a sentinel */
+}
diff --git a/cyclone/shadow/nettles.c b/cyclone/shadow/nettles.c
new file mode 100644
index 0000000..d7ccb87
--- /dev/null
+++ b/cyclone/shadow/nettles.c
@@ -0,0 +1,549 @@
+/* Copyright (c) 2003 krzYszcz and others.
+ * For information on usage and redistribution, and for a DISCLAIMER OF ALL
+ * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
+
+#include <math.h>
+#include "m_pd.h"
+#include "shared.h"
+#include "sickle/sic.h"
+#include "shadow.h"
+
+#if defined(NT) || defined(MACOSX)
+/* cf pd/src/x_arithmetic.c */
+#define fmodf fmod
+#endif
+
+/* Two remaining control binops have their inputs reversed.
+ LATER think about float-to-int conversion -- there is no point in making
+ the two below compatible, while all the others are not compatible... */
+
+/* CHECKED left inlet causes output (refman's error -- a total rubbish) */
+
+typedef struct _rbinop
+{
+ t_object x_ob;
+ t_float x_f1; /* left inlet value */
+ t_float x_f2;
+} t_rbinop;
+
+static t_class *rminus_class;
+
+static void rminus_bang(t_rbinop *x)
+{
+ outlet_float(((t_object *)x)->ob_outlet, x->x_f2 - x->x_f1);
+}
+
+static void rminus_float(t_rbinop *x, t_float f)
+{
+ outlet_float(((t_object *)x)->ob_outlet, x->x_f2 - (x->x_f1 = f));
+}
+
+static void *rminus_new(t_floatarg f)
+{
+ t_rbinop *x = (t_rbinop *)pd_new(rminus_class);
+ floatinlet_new((t_object *)x, &x->x_f2); /* CHECKED */
+ outlet_new((t_object *)x, &s_float);
+ x->x_f1 = 0;
+ x->x_f2 = f; /* CHECKED */
+ return (x);
+}
+
+static t_class *rdiv_class;
+
+static void rdiv_bang(t_rbinop *x)
+{
+ if (x->x_f1 != 0.)
+ outlet_float(((t_object *)x)->ob_outlet, x->x_f2 / x->x_f1);
+ else
+ /* CHECKED int mode: nonnegative/0 == 0, negative/0 == -1,
+ float mode: positive/0 == INT_MAX, nonpositive/0 == INT_MIN
+ LATER rethink -- why is it INT_MAX, not FLT_MAX? */
+ outlet_float(((t_object *)x)->ob_outlet,
+ (x->x_f2 > 0 ? SHARED_INT_MAX : SHARED_INT_MIN));
+}
+
+static void rdiv_float(t_rbinop *x, t_float f)
+{
+ x->x_f1 = f;
+ rdiv_bang(x);
+}
+
+static void *rdiv_new(t_floatarg f)
+{
+ t_rbinop *x = (t_rbinop *)pd_new(rdiv_class);
+ floatinlet_new((t_object *)x, &x->x_f2);
+ outlet_new((t_object *)x, &s_float);
+ x->x_f1 = 0;
+ x->x_f2 = f; /* CHECKED (refman's error) */
+ return (x);
+}
+
+/* The implementation of signal relational operators below has been tuned
+ somewhat, mostly in order to get rid of costly int->float conversions.
+ Loops are not hand-unrolled, because these have proven to be slower
+ in all the tests performed so far. LATER find a good soul willing to
+ make a serious profiling research... */
+
+typedef struct _sigeq
+{
+ t_sic x_sic;
+ int x_algo;
+} t_sigeq;
+
+static t_class *sigeq_class;
+
+static t_int *sigeq_perform0(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]);
+ t_shared_floatint fi;
+#ifdef NETTLES_SAFE
+ int32 truebits;
+ fi.fi_f = 1.;
+ truebits = fi.fi_i;
+#endif
+ while (nblock--)
+ {
+#ifdef NETTLES_SAFE
+ fi.fi_i = ~((*in1++ == *in2++) - 1) & truebits;
+#else
+ fi.fi_i = ~((*in1++ == *in2++) - 1) & SHARED_TRUEBITS;
+#endif
+ *out++ = fi.fi_f;
+ }
+ return (w + 5);
+}
+
+static t_int *sigeq_perform1(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--) *out++ = (*in1++ == *in2++);
+ return (w + 5);
+}
+
+static t_int *sigeq_perform2(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]);
+ for (; nblock; nblock -= 8, in1 += 8, in2 += 8, out += 8)
+ {
+ float f0 = in1[0], f1 = in1[1], f2 = in1[2], f3 = in1[3];
+ float f4 = in1[4], f5 = in1[5], f6 = in1[6], f7 = in1[7];
+ float g0 = in2[0], g1 = in2[1], g2 = in2[2], g3 = in2[3];
+ float g4 = in2[4], g5 = in2[5], g6 = in2[6], g7 = in2[7];
+ out[0] = f0 == g0; out[1] = f1 == g1;
+ out[2] = f2 == g2; out[3] = f3 == g3;
+ out[4] = f4 == g4; out[5] = f5 == g5;
+ out[6] = f6 == g6; out[7] = f7 == g7;
+ }
+ return (w + 5);
+}
+
+static void sigeq_dsp(t_sigeq *x, t_signal **sp)
+{
+ switch (x->x_algo)
+ {
+ case 1:
+ dsp_add(sigeq_perform1, 4, sp[0]->s_n,
+ sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec);
+ break;
+ case 2:
+ dsp_add(sigeq_perform2, 4, sp[0]->s_n,
+ sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec);
+ break;
+ default:
+ dsp_add(sigeq_perform0, 4, sp[0]->s_n,
+ sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec);
+ }
+}
+
+static void sigeq__algo(t_sigeq *x, t_floatarg f)
+{
+ x->x_algo = f;
+}
+
+static void *sigeq_new(t_symbol *s, int ac, t_atom *av)
+{
+ t_sigeq *x = (t_sigeq *)pd_new(sigeq_class);
+ if (s == gensym("_==1~"))
+ x->x_algo = 1;
+ else if (s == gensym("_==2~"))
+ x->x_algo = 2;
+ else
+ x->x_algo = 0;
+ sic_inlet((t_sic *)x, 1, 0, 0, ac, av);
+ outlet_new((t_object *)x, &s_signal);
+ return (x);
+}
+
+typedef t_sic t_signeq;
+static t_class *signeq_class;
+
+static t_int *signeq_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]);
+ t_shared_floatint fi;
+ while (nblock--)
+ {
+ fi.fi_i = ~((*in1++ != *in2++) - 1) & SHARED_TRUEBITS;
+ *out++ = fi.fi_f;
+ }
+ return (w + 5);
+}
+
+static void signeq_dsp(t_signeq *x, t_signal **sp)
+{
+ dsp_add(signeq_perform, 4, sp[0]->s_n,
+ sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec);
+}
+
+static void *signeq_new(t_symbol *s, int ac, t_atom *av)
+{
+ t_signeq *x = (t_signeq *)pd_new(signeq_class);
+ sic_inlet((t_sic *)x, 1, 0, 0, ac, av);
+ outlet_new((t_object *)x, &s_signal);
+ return (x);
+}
+
+typedef t_sic t_siglt;
+static t_class *siglt_class;
+
+static t_int *siglt_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]);
+ t_shared_floatint fi;
+ while (nblock--)
+ {
+ fi.fi_i = ~((*in1++ < *in2++) - 1) & SHARED_TRUEBITS;
+ *out++ = fi.fi_f;
+ }
+ return (w + 5);
+}
+
+static void siglt_dsp(t_siglt *x, t_signal **sp)
+{
+ dsp_add(siglt_perform, 4, sp[0]->s_n,
+ sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec);
+}
+
+static void *siglt_new(t_symbol *s, int ac, t_atom *av)
+{
+ t_siglt *x = (t_siglt *)pd_new(siglt_class);
+ sic_inlet((t_sic *)x, 1, 0, 0, ac, av);
+ outlet_new((t_object *)x, &s_signal);
+ return (x);
+}
+
+typedef t_sic t_siggt;
+static t_class *siggt_class;
+
+static t_int *siggt_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]);
+ t_shared_floatint fi;
+ while (nblock--)
+ {
+ fi.fi_i = ~((*in1++ > *in2++) - 1) & SHARED_TRUEBITS;
+ *out++ = fi.fi_f;
+ }
+ return (w + 5);
+}
+
+static void siggt_dsp(t_siggt *x, t_signal **sp)
+{
+ dsp_add(siggt_perform, 4, sp[0]->s_n,
+ sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec);
+}
+
+static void *siggt_new(t_symbol *s, int ac, t_atom *av)
+{
+ t_siggt *x = (t_siggt *)pd_new(siggt_class);
+ sic_inlet((t_sic *)x, 1, 0, 0, ac, av);
+ outlet_new((t_object *)x, &s_signal);
+ return (x);
+}
+
+typedef t_sic t_sigleq;
+static t_class *sigleq_class;
+
+static t_int *sigleq_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]);
+ t_shared_floatint fi;
+ while (nblock--)
+ {
+ fi.fi_i = ~((*in1++ <= *in2++) - 1) & SHARED_TRUEBITS;
+ *out++ = fi.fi_f;
+ }
+ return (w + 5);
+}
+
+static void sigleq_dsp(t_sigleq *x, t_signal **sp)
+{
+ dsp_add(sigleq_perform, 4, sp[0]->s_n,
+ sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec);
+}
+
+static void *sigleq_new(t_symbol *s, int ac, t_atom *av)
+{
+ t_sigleq *x = (t_sigleq *)pd_new(sigleq_class);
+ sic_inlet((t_sic *)x, 1, 0, 0, ac, av);
+ outlet_new((t_object *)x, &s_signal);
+ return (x);
+}
+
+typedef t_sic t_siggeq;
+static t_class *siggeq_class;
+
+static t_int *siggeq_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]);
+ t_shared_floatint fi;
+ while (nblock--)
+ {
+ fi.fi_i = ~((*in1++ >= *in2++) - 1) & SHARED_TRUEBITS;
+ *out++ = fi.fi_f;
+ }
+ return (w + 5);
+}
+
+static void siggeq_dsp(t_siggeq *x, t_signal **sp)
+{
+ dsp_add(siggeq_perform, 4, sp[0]->s_n,
+ sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec);
+}
+
+static void *siggeq_new(t_symbol *s, int ac, t_atom *av)
+{
+ t_siggeq *x = (t_siggeq *)pd_new(siggeq_class);
+ sic_inlet((t_sic *)x, 1, 0, 0, ac, av);
+ outlet_new((t_object *)x, &s_signal);
+ return (x);
+}
+
+typedef t_sic t_sigrminus;
+static t_class *sigrminus_class;
+
+static t_int *sigrminus_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--) *out++ = *in2++ - *in1++;
+ return (w + 5);
+}
+
+static void sigrminus_dsp(t_sigrminus *x, t_signal **sp)
+{
+ dsp_add(sigrminus_perform, 4, sp[0]->s_n,
+ sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec);
+}
+
+static void *sigrminus_new(t_symbol *s, int ac, t_atom *av)
+{
+ t_sigrminus *x = (t_sigrminus *)pd_new(sigrminus_class);
+ sic_inlet((t_sic *)x, 1, 0, 0, ac, av);
+ outlet_new((t_object *)x, &s_signal);
+ return (x);
+}
+
+typedef t_sic t_sigrover;
+static t_class *sigrover_class;
+
+static t_int *sigrover_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--)
+ {
+ t_float f1 = *in1++;
+ /* CHECKED incompatible: c74 outputs NaNs.
+ The line below is consistent with Pd's /~, LATER rethink. */
+ /* LATER multiply by reciprocal if in1 has no signal feeders */
+ *out++ = (f1 == 0. ? 0. : *in2++ / f1);
+ }
+ return (w + 5);
+}
+
+static void sigrover_dsp(t_sigrover *x, t_signal **sp)
+{
+ dsp_add(sigrover_perform, 4, sp[0]->s_n,
+ sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec);
+}
+
+static void *sigrover_new(t_symbol *s, int ac, t_atom *av)
+{
+ t_sigrover *x = (t_sigrover *)pd_new(sigrover_class);
+ /* CHECKED default 0 (refman's error), LATER rethink */
+ sic_inlet((t_sic *)x, 1, 0, 0, ac, av);
+ outlet_new((t_object *)x, &s_signal);
+ return (x);
+}
+
+typedef t_sic t_sigmod;
+static t_class *sigmod_class;
+
+static t_int *sigmod_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--)
+ {
+ t_float f1 = *in1++;
+ t_float f2 = *in2++;
+ /* LATER think about using ieee-754 normalization tricks */
+ *out++ = (f2 == 0. ? 0. /* CHECKED */
+ : fmod(f1, f2));
+ }
+ return (w + 5);
+}
+
+static void sigmod_dsp(t_sigmod *x, t_signal **sp)
+{
+ dsp_add(sigmod_perform, 4, sp[0]->s_n,
+ sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec);
+}
+
+static void *sigmod_new(t_symbol *s, int ac, t_atom *av)
+{
+ t_sigmod *x = (t_sigmod *)pd_new(sigmod_class);
+ /* CHECKED default 0 (refman's error), LATER rethink */
+ sic_inlet((t_sic *)x, 1, 0, 0, ac, av);
+ outlet_new((t_object *)x, &s_signal);
+ return (x);
+}
+
+typedef struct _sigaccum
+{
+ t_sic x_sic;
+ t_float x_sum;
+} t_sigaccum;
+
+static t_class *sigaccum_class;
+
+static t_int *sigaccum_perform(t_int *w)
+{
+ t_sigaccum *x = (t_sigaccum *)(w[1]);
+ int nblock = (int)(w[2]);
+ t_float *in = (t_float *)(w[3]);
+ t_float *out = (t_float *)(w[4]);
+ t_float sum = x->x_sum;
+ while (nblock--) *out++ = (sum += *in++);
+ x->x_sum = sum;
+ return (w + 5);
+}
+
+static void sigaccum_dsp(t_sigaccum *x, t_signal **sp)
+{
+ dsp_add(sigaccum_perform, 4, x, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec);
+}
+
+static void sigaccum_bang(t_sigaccum *x)
+{
+ x->x_sum = 0;
+}
+
+static void sigaccum_set(t_sigaccum *x, t_floatarg f)
+{
+ x->x_sum = f;
+}
+
+static void *sigaccum_new(t_floatarg f)
+{
+ t_sigaccum *x = (t_sigaccum *)pd_new(sigaccum_class);
+ x->x_sum = f;
+ outlet_new((t_object *)x, &s_signal);
+ return (x);
+}
+
+void allnettles_setup(void)
+{
+ rminus_class = class_new(gensym("!-"),
+ (t_newmethod)rminus_new, 0,
+ sizeof(t_rbinop), 0, A_DEFFLOAT, 0);
+ class_addbang(rminus_class, rminus_bang);
+ class_addfloat(rminus_class, rminus_float);
+ rdiv_class = class_new(gensym("!/"),
+ (t_newmethod)rdiv_new, 0,
+ sizeof(t_rbinop), 0, A_DEFFLOAT, 0);
+ class_addbang(rdiv_class, rdiv_bang);
+ class_addfloat(rdiv_class, rdiv_float);
+
+ sigeq_class = class_new(gensym("==~"),
+ (t_newmethod)sigeq_new, 0,
+ sizeof(t_sigeq), 0, A_GIMME, 0);
+ class_addcreator((t_newmethod)sigeq_new,
+ gensym("_==1~"), A_GIMME, 0);
+ class_addcreator((t_newmethod)sigeq_new,
+ gensym("_==2~"), A_GIMME, 0);
+ sic_setup(sigeq_class, sigeq_dsp, SIC_FLOATTOSIGNAL);
+ class_addmethod(sigeq_class, (t_method)sigeq__algo,
+ gensym("_algo"), A_FLOAT, 0);
+
+ signeq_class = class_new(gensym("!=~"),
+ (t_newmethod)signeq_new, 0,
+ sizeof(t_signeq), 0, A_GIMME, 0);
+ sic_setup(signeq_class, signeq_dsp, SIC_FLOATTOSIGNAL);
+ siglt_class = class_new(gensym("<~"),
+ (t_newmethod)siglt_new, 0,
+ sizeof(t_siglt), 0, A_GIMME, 0);
+ sic_setup(siglt_class, siglt_dsp, SIC_FLOATTOSIGNAL);
+ siggt_class = class_new(gensym(">~"),
+ (t_newmethod)siggt_new, 0,
+ sizeof(t_siggt), 0, A_GIMME, 0);
+ sic_setup(siggt_class, siggt_dsp, SIC_FLOATTOSIGNAL);
+ sigleq_class = class_new(gensym("<=~"),
+ (t_newmethod)sigleq_new, 0,
+ sizeof(t_sigleq), 0, A_GIMME, 0);
+ sic_setup(sigleq_class, sigleq_dsp, SIC_FLOATTOSIGNAL);
+ siggeq_class = class_new(gensym(">=~"),
+ (t_newmethod)siggeq_new, 0,
+ sizeof(t_siggeq), 0, A_GIMME, 0);
+ sic_setup(siggeq_class, siggeq_dsp, SIC_FLOATTOSIGNAL);
+ sigrminus_class = class_new(gensym("!-~"),
+ (t_newmethod)sigrminus_new, 0,
+ sizeof(t_sigrminus), 0, A_GIMME, 0);
+ sic_setup(sigrminus_class, sigrminus_dsp, SIC_FLOATTOSIGNAL);
+ sigrover_class = class_new(gensym("!/~"),
+ (t_newmethod)sigrover_new, 0,
+ sizeof(t_sigrover), 0, A_GIMME, 0);
+ sic_setup(sigrover_class, sigrover_dsp, SIC_FLOATTOSIGNAL);
+ sigmod_class = class_new(gensym("%~"),
+ (t_newmethod)sigmod_new, 0,
+ sizeof(t_sigmod), 0, A_GIMME, 0);
+ sic_setup(sigmod_class, sigmod_dsp, SIC_FLOATTOSIGNAL);
+ sigaccum_class = class_new(gensym("+=~"),
+ (t_newmethod)sigaccum_new, 0,
+ sizeof(t_sigaccum), 0, A_DEFFLOAT, 0);
+ sic_setup(sigaccum_class, sigaccum_dsp, SIC_FLOATTOSIGNAL);
+ class_addbang(sigaccum_class, sigaccum_bang);
+ class_addmethod(sigaccum_class, (t_method)sigaccum_set,
+ gensym("set"), A_FLOAT, 0);
+}
diff --git a/cyclone/shadow/shadow.h b/cyclone/shadow/shadow.h
new file mode 100644
index 0000000..aefc46e
--- /dev/null
+++ b/cyclone/shadow/shadow.h
@@ -0,0 +1,13 @@
+/* Copyright (c) 2003 krzYszcz and others.
+ * For information on usage and redistribution, and for a DISCLAIMER OF ALL
+ * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
+
+#ifndef __SHADOW_H__
+#define __SHADOW_H__
+
+void allnettles_setup(void);
+void alldummies_setup(void);
+int dummy_nreplacements(void);
+void dummy_printreplacements(char *msg);
+
+#endif
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);
+}