From faada59567f8cb252f4a909116595ce309ff5828 Mon Sep 17 00:00:00 2001 From: "N.N." Date: Fri, 23 May 2003 12:29:55 +0000 Subject: This commit was generated by cvs2svn to compensate for changes in r647, which included commits to RCS files with non-trunk default branches. svn path=/trunk/externals/miXed/; revision=648 --- cyclone/sickle/Clip.c | 59 +++ cyclone/sickle/Line.c | 299 +++++++++++ cyclone/sickle/Makefile | 3 + cyclone/sickle/Makefile.objects | 11 + cyclone/sickle/Makefile.sources | 67 +++ cyclone/sickle/Scope.c | 1043 +++++++++++++++++++++++++++++++++++++++ cyclone/sickle/Snapshot.c | 161 ++++++ cyclone/sickle/abs.c | 42 ++ cyclone/sickle/acos.c | 48 ++ cyclone/sickle/acosh.c | 48 ++ cyclone/sickle/allpass.c | 153 ++++++ cyclone/sickle/allsickles.c | 134 +++++ cyclone/sickle/asin.c | 48 ++ cyclone/sickle/asinh.c | 48 ++ cyclone/sickle/atan.c | 48 ++ cyclone/sickle/atan2.c | 53 ++ cyclone/sickle/atanh.c | 48 ++ cyclone/sickle/average.c | 194 ++++++++ cyclone/sickle/avg.c | 62 +++ cyclone/sickle/bitand.c | 144 ++++++ cyclone/sickle/bitnot.c | 66 +++ cyclone/sickle/bitor.c | 144 ++++++ cyclone/sickle/bitshift.c | 130 +++++ cyclone/sickle/bitxor.c | 144 ++++++ cyclone/sickle/capture.c | 408 +++++++++++++++ cyclone/sickle/cartopol.c | 79 +++ cyclone/sickle/change.c | 52 ++ cyclone/sickle/click.c | 119 +++++ cyclone/sickle/comb.c | 162 ++++++ cyclone/sickle/cosh.c | 48 ++ cyclone/sickle/cosx.c | 51 ++ cyclone/sickle/count.c | 145 ++++++ cyclone/sickle/cycle.c | 173 +++++++ cyclone/sickle/delay.c | 101 ++++ cyclone/sickle/delta.c | 52 ++ cyclone/sickle/deltaclip.c | 67 +++ cyclone/sickle/edge.c | 106 ++++ cyclone/sickle/frameaccum.c | 71 +++ cyclone/sickle/framedelta.c | 76 +++ cyclone/sickle/index.c | 107 ++++ cyclone/sickle/kink.c | 62 +++ cyclone/sickle/linedrive.c | 73 +++ cyclone/sickle/log.c | 74 +++ cyclone/sickle/lookup.c | 94 ++++ cyclone/sickle/minmax.c | 78 +++ cyclone/sickle/peakamp.c | 107 ++++ cyclone/sickle/peek.c | 147 ++++++ cyclone/sickle/phasewrap.c | 131 +++++ cyclone/sickle/play.c | 122 +++++ cyclone/sickle/poltocar.c | 79 +++ cyclone/sickle/pow.c | 54 ++ cyclone/sickle/rampsmooth.c | 206 ++++++++ cyclone/sickle/rand.c | 95 ++++ cyclone/sickle/record.c | 242 +++++++++ cyclone/sickle/sah.c | 70 +++ cyclone/sickle/sickle.c | 93 ++++ cyclone/sickle/sinh.c | 48 ++ cyclone/sickle/sinx.c | 51 ++ cyclone/sickle/slide.c | 77 +++ cyclone/sickle/spike.c | 109 ++++ cyclone/sickle/tanh.c | 48 ++ cyclone/sickle/tanx.c | 51 ++ cyclone/sickle/train.c | 117 +++++ cyclone/sickle/trapezoid.c | 105 ++++ cyclone/sickle/triangle.c | 95 ++++ cyclone/sickle/vectral.c | 235 +++++++++ cyclone/sickle/wave.c | 161 ++++++ 67 files changed, 7838 insertions(+) create mode 100644 cyclone/sickle/Clip.c create mode 100644 cyclone/sickle/Line.c create mode 100644 cyclone/sickle/Makefile create mode 100644 cyclone/sickle/Makefile.objects create mode 100644 cyclone/sickle/Makefile.sources create mode 100644 cyclone/sickle/Scope.c create mode 100644 cyclone/sickle/Snapshot.c create mode 100644 cyclone/sickle/abs.c create mode 100644 cyclone/sickle/acos.c create mode 100644 cyclone/sickle/acosh.c create mode 100644 cyclone/sickle/allpass.c create mode 100644 cyclone/sickle/allsickles.c create mode 100644 cyclone/sickle/asin.c create mode 100644 cyclone/sickle/asinh.c create mode 100644 cyclone/sickle/atan.c create mode 100644 cyclone/sickle/atan2.c create mode 100644 cyclone/sickle/atanh.c create mode 100644 cyclone/sickle/average.c create mode 100644 cyclone/sickle/avg.c create mode 100644 cyclone/sickle/bitand.c create mode 100644 cyclone/sickle/bitnot.c create mode 100644 cyclone/sickle/bitor.c create mode 100644 cyclone/sickle/bitshift.c create mode 100644 cyclone/sickle/bitxor.c create mode 100644 cyclone/sickle/capture.c create mode 100644 cyclone/sickle/cartopol.c create mode 100644 cyclone/sickle/change.c create mode 100644 cyclone/sickle/click.c create mode 100644 cyclone/sickle/comb.c create mode 100644 cyclone/sickle/cosh.c create mode 100644 cyclone/sickle/cosx.c create mode 100644 cyclone/sickle/count.c create mode 100644 cyclone/sickle/cycle.c create mode 100644 cyclone/sickle/delay.c create mode 100644 cyclone/sickle/delta.c create mode 100644 cyclone/sickle/deltaclip.c create mode 100644 cyclone/sickle/edge.c create mode 100644 cyclone/sickle/frameaccum.c create mode 100644 cyclone/sickle/framedelta.c create mode 100644 cyclone/sickle/index.c create mode 100644 cyclone/sickle/kink.c create mode 100644 cyclone/sickle/linedrive.c create mode 100644 cyclone/sickle/log.c create mode 100644 cyclone/sickle/lookup.c create mode 100644 cyclone/sickle/minmax.c create mode 100644 cyclone/sickle/peakamp.c create mode 100644 cyclone/sickle/peek.c create mode 100644 cyclone/sickle/phasewrap.c create mode 100644 cyclone/sickle/play.c create mode 100644 cyclone/sickle/poltocar.c create mode 100644 cyclone/sickle/pow.c create mode 100644 cyclone/sickle/rampsmooth.c create mode 100644 cyclone/sickle/rand.c create mode 100644 cyclone/sickle/record.c create mode 100644 cyclone/sickle/sah.c create mode 100644 cyclone/sickle/sickle.c create mode 100644 cyclone/sickle/sinh.c create mode 100644 cyclone/sickle/sinx.c create mode 100644 cyclone/sickle/slide.c create mode 100644 cyclone/sickle/spike.c create mode 100644 cyclone/sickle/tanh.c create mode 100644 cyclone/sickle/tanx.c create mode 100644 cyclone/sickle/train.c create mode 100644 cyclone/sickle/trapezoid.c create mode 100644 cyclone/sickle/triangle.c create mode 100644 cyclone/sickle/vectral.c create mode 100644 cyclone/sickle/wave.c (limited to 'cyclone/sickle') 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 +#include +#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