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