diff --git a/bin/helpbrowser.tcl b/bin/helpbrowser.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/bin/pd.tk b/bin/pd.tk
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/bin/pkgIndex.tcl b/bin/pkgIndex.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/extra/bonk~/bonk~-help.pd b/extra/bonk~/bonk~-help.pd
new file mode 100644
index 0000000000000000000000000000000000000000..e52b7c506f1fde987bab3f725ca88ce3eeabb582
--- /dev/null
+++ b/extra/bonk~/bonk~-help.pd
@@ -0,0 +1,209 @@
+#N canvas 43 123 1054 583 12;
+#X obj 382 492 spigot;
+#X msg 484 293 bang;
+#X obj 483 454 bonk~;
+#X msg 483 357 print;
+#X obj 435 428 adc~;
+#X msg 637 506 \; pd dsp 1;
+#X obj 300 492 spigot;
+#N canvas 366 126 604 404 synth 0;
+#X obj 112 24 r bonk-cooked;
+#X obj 112 49 unpack;
+#X obj 112 99 * 12;
+#X obj 112 124 div 7;
+#X obj 112 74 + 1;
+#X obj 112 174 mtof;
+#X obj 112 224 osc~;
+#X obj 112 249 cos~;
+#X obj 112 149 + 47;
+#X obj 209 247 line~;
+#X obj 209 272 *~;
+#X obj 209 297 lop~ 500;
+#X obj 112 274 *~;
+#X obj 103 361 dac~;
+#X obj 253 165 dbtorms;
+#X obj 253 115 * 0.5;
+#X obj 253 140 + 50;
+#X obj 211 189 f;
+#X msg 173 159 bang;
+#X obj 258 83 inlet;
+#X obj 111 307 hip~ 5;
+#X msg 34 24 0 60;
+#X obj 112 199 sig~;
+#X msg 209 222 \$1 \, 0 200;
+#X connect 0 0 1 0;
+#X connect 1 0 4 0;
+#X connect 2 0 3 0;
+#X connect 3 0 8 0;
+#X connect 4 0 2 0;
+#X connect 5 0 18 0;
+#X connect 5 0 22 0;
+#X connect 6 0 7 0;
+#X connect 7 0 12 0;
+#X connect 8 0 5 0;
+#X connect 9 0 10 0;
+#X connect 9 0 10 1;
+#X connect 10 0 11 0;
+#X connect 11 0 12 1;
+#X connect 12 0 20 0;
+#X connect 14 0 17 1;
+#X connect 15 0 16 0;
+#X connect 16 0 14 0;
+#X connect 17 0 23 0;
+#X connect 18 0 17 0;
+#X connect 19 0 15 0;
+#X connect 20 0 13 1;
+#X connect 20 0 13 0;
+#X connect 21 0 1 0;
+#X connect 22 0 6 0;
+#X connect 23 0 9 0;
+#X restore 869 523 pd synth;
+#X floatatom 869 500 0 0 0 0 - - -;
+#X msg 869 470 0;
+#X msg 900 470 90;
+#X text 625 472 click here;
+#X text 626 485 to start DSP;
+#X text 5 285 In this patch \, after starting DSP \, you can print
+out the raw or cooked output using the two "spigots" or listen to a
+synthesizer output by raising its volume.;
+#X text 770 469 output volume;
+#X text 784 487 (0-100);
+#X msg 483 138 mask 4 0.7;
+#X text 578 120 Describes how energy in each frequency band masks later
+energy in the band. Here the masking is total for 4 analysis periods
+and then drops by 0.7 each period.;
+#X text 528 286 Poll the current spectrum via "raw" outlet \, You can
+set a very high threshold if you don't want attacks mixed in.;
+#X msg 483 331 debug 0;
+#X text 561 331 turn debugging on or off.;
+#X obj 349 493 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0
+1;
+#X obj 431 493 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0
+1;
+#X obj 382 522 print cooked;
+#X obj 300 522 print raw;
+#X text 162 491 enable printout:;
+#X text 560 202 Minimum "velocity" to output (quieter notes are ignored.)
+;
+#X obj 485 481 s bonk-cooked;
+#X text 8 145 Bonk's two outputs are the raw spectrum of the attack
+(provided as a list of 11 numbers giving the signal "loudness" in the
+11 frequency bands used) \, and the "cooked" output which gives only
+an instrument number (counting up from zero) and a "velocity". This
+"velocity" is the sum of the square roots of the amplitudes of the
+bands \, normalized so that 100 is an attack of amplitude of about
+1 The instrument number is significant only if Bonk has a "template
+set" in memory.;
+#X text 580 35 Set low and high thresholds. Signal growth must exceed
+the high one and then fall to the low one to make an attack. The unit
+is the sum of the proportional growth in the 11 filter bands. Proportional
+growth is essentially the logarithmic time derivative.;
+#X msg 483 384 print 1;
+#X text 551 386 print out filterbank settings;
+#X text 9 33 The Bonk object takes an audio signal input and looks
+for "attacks" defined as sharp changes in the spectral envelope of
+the incoming sound. Optionally \, and less reliably \, you can have
+Bonk check the attack against a collection of stored templates to try
+to guess which of two or more instruments was hit. Bonk is described
+theoretically in the 1998 ICMC proceedings \, reprinted on crca.ucsd.edu/~msp
+.;
+#N canvas 723 241 701 719 creation-arguments 0;
+#X text 228 14 creation arguments for bonk~;
+#X text 70 272 -npts 256;
+#X text 44 244 default value:;
+#X text 70 308 -hop 128;
+#X text 70 342 -nfilters 11;
+#X text 68 380 -halftones 6;
+#X text 76 514 -overlap 1;
+#X text 79 567 -firstbin 1;
+#X text 71 454 -minbandwidth 1.5;
+#X text 122 147 All frequency parameters are specified in 'bins'. One
+bin is the sample rate divided by the window size. The minimum possible
+bandwidth is 1.5 bins. Higher bandwidths give numerically more robust
+outputs.;
+#X text 43 229 Arguments and;
+#X text 212 270 window size in points;
+#X text 210 306 analysis period ("hop size") in points;
+#X text 212 340 number of filters to use;
+#X text 212 379 desired bandwidth of filters in halftones \, effective
+in the exponentially spaced region. (At lower center frequencies the
+bandwidth is supported by the "minbandwidth" parameter below).;
+#X text 212 511 overlap factor between filters. If 1 \, the filters
+are spaced to line up at their half-power points. Other values specify
+more or fewer filters proportionally.;
+#X text 121 49 bonk~ uses a filterbank whose center frequencies are
+spaced equally at low frequencies and proportionally at high ones -
+i.e. \, they increase linearly \, then exponentially. They are determined
+by the filters' bandwidths and overlap. The bandwidths are specified
+proportionally to frequency but bounded below by a specified minimum.
+;
+#X text 210 455 minimum bandwidth in bins. If the bandwidth specified
+by "halftones" is smaller than this \, this value is used. This must
+be at least 1.5.;
+#X text 212 567 center frequency \, in bins \, of the lowest filter.
+The others are computed from this.;
+#X restore 147 414 pd creation-arguments;
+#N canvas 660 173 579 589 templates 0;
+#X msg 76 197 learn 0;
+#X msg 76 227 forget;
+#X msg 76 257 write templates.txt;
+#X msg 76 287 read templates.txt;
+#X msg 76 107 debounce 0;
+#X msg 76 137 learn 10;
+#X obj 62 431 outlet;
+#X text 155 133 Forget all templates and start learning new ones. The
+argument gives the number of times you will hit each instrument (10
+recommended.) Turn on the output volume above for audible feedback
+as you train Bonk. "Learn 0" exits learn mode.;
+#X text 155 217 Forget the last template. In Learn mode \, use "forget"
+to erase and record over a template.;
+#X text 220 253 Write templates to a file in text-editable format.
+;
+#X text 221 283 Read templates from a file.;
+#X text 157 104 Minimum time (msec) between attacks in learn mode;
+#X connect 0 0 6 0;
+#X connect 1 0 6 0;
+#X connect 2 0 6 0;
+#X connect 3 0 6 0;
+#X connect 4 0 6 0;
+#X connect 5 0 6 0;
+#X restore 500 421 pd templates;
+#X msg 483 68 thresh 2.5 5;
+#X msg 483 173 attack-frames 1;
+#X text 608 174 number of frames over which to measure growth;
+#X text 605 422 more messages for managing templates;
+#X msg 483 201 minvel 7;
+#X msg 483 228 spew 0;
+#X text 550 230 Turn spew mode on/off;
+#X msg 483 255 useloudness 0;
+#X text 597 254 experimental: use alternative loudness units;
+#X text 212 9 BONK~ - attack detection and spectral envelope measurement
+;
+#X text 734 552 Updated for Pd version 0.42;
+#X text 5 344 By default bonk's analysis is carried out on a 256-point
+window (6 msec at 44.1 kHz) and the analysis period is 128 samples.
+These and other parameters may be overridden using creation arguments
+as shown in the subpatch below:;
+#X text 552 356 Print out settings and templates.;
+#X connect 0 0 23 0;
+#X connect 1 0 2 0;
+#X connect 2 0 6 0;
+#X connect 2 1 0 0;
+#X connect 2 1 27 0;
+#X connect 3 0 2 0;
+#X connect 4 0 2 0;
+#X connect 6 0 24 0;
+#X connect 8 0 7 0;
+#X connect 9 0 8 0;
+#X connect 10 0 8 0;
+#X connect 16 0 2 0;
+#X connect 19 0 2 0;
+#X connect 21 0 6 1;
+#X connect 22 0 0 1;
+#X connect 30 0 2 0;
+#X connect 34 0 2 0;
+#X connect 35 0 2 0;
+#X connect 36 0 2 0;
+#X connect 39 0 2 0;
+#X connect 40 0 2 0;
+#X connect 42 0 2 0;
diff --git a/extra/bonk~/bonk~.c b/extra/bonk~/bonk~.c
new file mode 100644
index 0000000000000000000000000000000000000000..d0f18de967c4cf527cd20541668cc12348becf77
--- /dev/null
+++ b/extra/bonk~/bonk~.c
@@ -0,0 +1,1475 @@
+/*
+ ###########################################################################
+ # bonk~ - a Max/MSP external
+ # by miller puckette and ted apel
+ # http://crca.ucsd.edu/~msp/
+ # Max/MSP port by barry threw
+ # http://www.barrythrew.com
+ # me@barrythrew.com
+ # San Francisco, CA
+ # (c) 2008
+ # for Kesumo - http://www.kesumo.com
+ ###########################################################################
+ // bonk~ detects attacks in an audio signal
+ ###########################################################################
+ This software is copyrighted by Miller Puckette and others.  The following
+ terms (the "Standard Improved BSD License") apply to all files associated with
+ the software unless explicitly disclaimed in individual files:
+ 
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+ 
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above  
+ copyright notice, this list of conditions and the following 
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+ 3. The name of the author may not be used to endorse or promote
+ products derived from this software without specific prior 
+ written permission.
+ 
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR
+ BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,   
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+dolist:
+decay and other times in msec 
+*/
+
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+
+/* These pragmas are only used for MSVC, not MinGW or Cygwin <hans@at.or.at> */
+#ifdef _MSC_VER
+#pragma warning (disable: 4305 4244)
+#endif
+ 
+#ifdef MSP
+#include "ext.h"
+#include "z_dsp.h"
+#include "math.h"
+#include "ext_support.h"
+#include "ext_proto.h"
+#include "ext_obex.h"
+
+typedef double t_floatarg;      /* from m_pd.h */
+#define flog log
+#define fexp exp
+#define fsqrt sqrt
+#define t_resizebytes(a, b, c) t_resizebytes((char *)(a), (b), (c))
+
+void *bonk_class;
+#define getbytes t_getbytes
+#define freebytes t_freebytes
+#endif /* MSP */
+
+#ifdef PD
+#include "m_pd.h"
+static t_class *bonk_class;
+#endif
+
+#ifndef _MSC_VER
+#include <alloca.h>
+#endif
+
+/* ------------------------ bonk~ ----------------------------- */
+
+#define DEFNPOINTS 256
+#define MAXCHANNELS 8
+#define MINPOINTS 64
+#define DEFPERIOD 128
+#define DEFNFILTERS 11
+#define DEFHALFTONES 6
+#define DEFOVERLAP 1
+#define DEFFIRSTBIN 1
+#define DEFMINBANDWIDTH 1.5
+#define DEFHITHRESH 5
+#define DEFLOTHRESH 2.5
+#define DEFMASKTIME 4
+#define DEFMASKDECAY 0.7
+#define DEFDEBOUNCEDECAY 0
+#define DEFMINVEL 7
+#define DEFATTACKBINS 1
+#define MAXATTACKWAIT 4
+
+typedef struct _filterkernel
+{
+    int k_filterpoints;
+    int k_hoppoints;
+    int k_skippoints;
+    int k_nhops;
+    float k_centerfreq;          /* center frequency, bins */
+    float k_bandwidth;           /* bandwidth, bins */
+    float *k_stuff;
+} t_filterkernel;
+
+typedef struct _filterbank
+{
+    int b_nfilters;             /* number of filters in bank */
+    int b_npoints;              /* input vector size */
+    float b_halftones;          /* filter bandwidth in halftones */
+    float b_overlap;            /* overlap; default 1 for 1/2-power pts */
+    float b_firstbin;           /* freq of first filter in bins, default 1 */
+    float b_minbandwidth;       /* minimum bandwidth, default 1.5 */
+    t_filterkernel *b_vec;      /* filter kernels */
+    int b_refcount;             /* number of bonk~ objects using this */
+    struct _filterbank *b_next; /* next in linked list */
+} t_filterbank;
+
+#if 0   /* this is the design for 1.0: */
+static t_filterkernel bonk_filterkernels[] =
+    {{256, 2, .01562}, {256, 4, .01562}, {256, 6, .01562}, {180, 6, .02222},
+    {128, 6, .01803}, {90, 6, .02222}, {64, 6, .02362}, {46, 6, .02773},
+    {32, 6, .03227}, {22, 6, .03932}, {16, 6, .04489}};
+#endif
+
+#if 0
+    /* here's the 1.1 rev: */
+static t_filterkernel bonk_filterkernels[] =
+    {{256, 1, .01562, 0}, {256, 3, .01562, 0}, {256, 5, .01562, 0},
+    {212, 6, .01886, 0}, {150, 6, .01885, 0}, {106, 6, .02179, 0},
+    {76, 6, .0236, 0}, {54, 6, .02634, 0}, {38, 6, .03047, 0},
+    {26, 6, .03667, 0}, {18, 6, .04458, 0}};
+
+#define NFILTERS \
+    ((int)(sizeof(bonk_filterkernels) / sizeof(bonk_filterkernels[0])))
+
+#endif
+
+#if 0
+    /* and 1.2 */
+#define NFILTERS 11
+static t_filterkernel bonk_filterkernels[NFILTERS];
+#endif
+
+   /* and 1.3 */
+#define MAXNFILTERS 50
+#define MASKHIST 8
+
+static t_filterbank *bonk_filterbanklist;
+
+typedef struct _hist
+{
+    float h_power;
+    float h_before;
+    float h_outpower;
+    int h_countup;
+    float h_mask[MASKHIST];
+} t_hist;
+
+typedef struct template
+{
+    float t_amp[MAXNFILTERS];
+} t_template;
+
+typedef struct _insig
+{
+    t_hist g_hist[MAXNFILTERS];    /* history for each filter */
+#ifdef PD
+    t_outlet *g_outlet;         /* outlet for raw data */
+#endif
+#ifdef MSP
+    void *g_outlet;             /* outlet for raw data */
+#endif
+    float *g_inbuf;             /* buffered input samples */
+    t_float *g_invec;           /* new input samples */
+} t_insig;
+
+typedef struct _bonk
+{
+#ifdef PD
+    t_object x_obj;
+    t_outlet *x_cookedout;
+    t_clock *x_clock;
+#endif /* PD */
+#ifdef MSP
+    t_pxobject x_obj;
+    void *obex;
+    void *x_cookedout;
+    void *x_clock;
+#endif /* MSP */
+    /* parameters */
+    int x_npoints;          /* number of points in input buffer */
+    int x_period;           /* number of input samples between analyses */
+    int x_nfilters;         /* number of filters requested */
+    float x_halftones;      /* nominal halftones between filters */
+    float x_overlap;
+    float x_firstbin;
+    float x_minbandwidth;
+    float x_hithresh;       /* threshold for total growth to trigger */
+    float x_lothresh;       /* threshold for total growth to re-arm */
+    float x_minvel;         /* minimum velocity we output */
+    float x_maskdecay;
+    int x_masktime;
+    int x_useloudness;      /* use loudness spectra instead of power */
+    float x_debouncedecay;
+    float x_debouncevel;
+    double x_learndebounce; /* debounce time (in "learn" mode only) */
+    int x_attackbins;       /* number of bins to wait for attack */
+
+    t_filterbank *x_filterbank;
+    t_hist x_hist[MAXNFILTERS];
+    t_template *x_template;
+    t_insig *x_insig;                   
+    int x_ninsig;
+    int x_ntemplate;
+    int x_infill;
+    int x_countdown;
+    int x_willattack;
+    int x_attacked;
+    int x_debug;
+    int x_learn;
+    int x_learncount;           /* countup for "learn" mode */
+    int x_spew;                 /* if true, always generate output! */
+    int x_maskphase;            /* phase, 0 to MASKHIST-1, for mask history */
+    float x_sr;                 /* current sample rate in Hz. */
+    int x_hit;                  /* next "tick" called because of a hit, not a poll */
+} t_bonk;
+
+#ifdef MSP
+static void *bonk_new(t_symbol *s, long ac, t_atom *av);
+static void bonk_tick(t_bonk *x);
+static void bonk_doit(t_bonk *x);
+static t_int *bonk_perform(t_int *w);
+static void bonk_dsp(t_bonk *x, t_signal **sp);
+void bonk_assist(t_bonk *x, void *b, long m, long a, char *s);
+static void bonk_free(t_bonk *x);
+void bonk_setup(void);
+int main();
+
+static void bonk_thresh(t_bonk *x, t_floatarg f1, t_floatarg f2);
+static void bonk_print(t_bonk *x, t_floatarg f);
+static void bonk_bang(t_bonk *x);
+
+static void bonk_write(t_bonk *x, t_symbol *s);
+static void bonk_read(t_bonk *x, t_symbol *s);
+
+void bonk_minvel_set(t_bonk *x, void *attr, long ac, t_atom *av);
+void bonk_lothresh_set(t_bonk *x, void *attr, long ac, t_atom *av);
+void bonk_hithresh_set(t_bonk *x, void *attr, long ac, t_atom *av);
+void bonk_masktime_set(t_bonk *x, void *attr, long ac, t_atom *av);
+void bonk_maskdecay_set(t_bonk *x, void *attr, long ac, t_atom *av);
+void bonk_debouncedecay_set(t_bonk *x, void *attr, long ac, t_atom *av);
+void bonk_debug_set(t_bonk *x, void *attr, long ac, t_atom *av);
+void bonk_spew_set(t_bonk *x, void *attr, long ac, t_atom *av);
+void bonk_useloudness_set(t_bonk *x, void *attr, long ac, t_atom *av);
+void bonk_attackbins_set(t_bonk *x, void *attr, long ac, t_atom *av);
+void bonk_learn_set(t_bonk *x, void *attr, long ac, t_atom *av);
+
+float qrsqrt(float f);
+double clock_getsystime();
+double clock_gettimesince(double prevsystime);
+char *strcpy(char *s1, const char *s2);
+#endif
+
+static void bonk_tick(t_bonk *x);
+
+#define HALFWIDTH 0.75  /* half peak bandwidth at half power point in bins */
+#define SLIDE 0.25    /* relative slide between filter subwindows */
+
+static t_filterbank *bonk_newfilterbank(int npoints, int nfilters,
+    float halftones, float overlap, float firstbin, float minbandwidth)
+{
+    int i, j;
+    float cf, bw, h, relspace;
+    t_filterbank *b = (t_filterbank *)getbytes(sizeof(*b));
+    b->b_npoints = npoints;
+    b->b_nfilters = nfilters;
+    b->b_halftones = halftones;
+    b->b_overlap = overlap;
+    b->b_firstbin = firstbin;
+    b->b_minbandwidth = minbandwidth;
+    b->b_refcount = 0;
+    b->b_next = bonk_filterbanklist;
+    bonk_filterbanklist = b;
+    b->b_vec = (t_filterkernel *)getbytes(nfilters * sizeof(*b->b_vec));
+    
+    h = exp((log(2.)/12.)*halftones);  /* specced interval between filters */
+    relspace = (h - 1)/(h + 1);        /* nominal spacing-per-f for fbank */
+    
+    if (minbandwidth < 2*HALFWIDTH)
+        minbandwidth = 2*HALFWIDTH;
+    if (firstbin < minbandwidth/(2*HALFWIDTH))
+        firstbin = minbandwidth/(2*HALFWIDTH);
+    cf = firstbin;
+    bw = cf * relspace * overlap;
+    if (bw < (0.5*minbandwidth))
+        bw = (0.5*minbandwidth);
+    for (i = 0; i < nfilters; i++)
+    {
+        float *fp, newcf, newbw;
+        float normalizer = 0;
+        int filterpoints, skippoints, hoppoints, nhops;
+        
+        filterpoints = npoints * HALFWIDTH/bw;
+        if (cf > npoints/2)
+        {
+            post("bonk~: only using %d filters (ran past Nyquist)", i+1);
+            break;
+        }
+        if (filterpoints < 4)
+        {
+            post("bonk~: only using %d filters (kernels got too short)", i+1);
+            break;
+        }
+        else if (filterpoints > npoints)
+            filterpoints = npoints;
+        
+        hoppoints = SLIDE * npoints * HALFWIDTH/bw;
+        
+        nhops = 1. + (npoints-filterpoints)/(float)hoppoints;
+        skippoints = 0.5 * (npoints-filterpoints - (nhops-1) * hoppoints);
+        
+        b->b_vec[i].k_stuff =
+            (float *)getbytes(2 * sizeof(float) * filterpoints);
+        b->b_vec[i].k_filterpoints = filterpoints;
+        b->b_vec[i].k_nhops = nhops;
+        b->b_vec[i].k_hoppoints = hoppoints;
+        b->b_vec[i].k_skippoints = skippoints;
+        b->b_vec[i].k_centerfreq = cf;
+        b->b_vec[i].k_bandwidth = bw;
+        
+        for (fp = b->b_vec[i].k_stuff, j = 0; j < filterpoints; j++, fp+= 2)
+        {
+            float phase = j * cf * (2*3.14159/ npoints);
+            float wphase = j * (2*3.14159 / filterpoints);
+            float window = sin(0.5*wphase);
+            fp[0] = window * cos(phase);
+            fp[1] = window * sin(phase);
+            normalizer += window;
+        }
+        normalizer = 1/(normalizer * sqrt(nhops));
+        for (fp = b->b_vec[i].k_stuff, j = 0;
+             j < filterpoints; j++, fp+= 2)
+            fp[0] *= normalizer, fp[1] *= normalizer;
+#if 0
+        post("i %d  cf %.2f  bw %.2f  nhops %d, hop %d, skip %d, npoints %d",
+             i, cf, bw, nhops, hoppoints, skippoints, filterpoints);
+#endif
+        newcf = (cf + bw/overlap)/(1 - relspace);
+        newbw = newcf * overlap * relspace;
+        if (newbw < 0.5*minbandwidth)
+        {
+            newbw = 0.5*minbandwidth;
+            newcf = cf + minbandwidth / overlap;
+        }
+        cf = newcf;
+        bw = newbw;
+    }
+    for (; i < nfilters; i++)
+        b->b_vec[i].k_stuff = 0, b->b_vec[i].k_filterpoints = 0;
+    return (b);
+}
+
+static void bonk_freefilterbank(t_filterbank *b)
+{
+    t_filterbank *b2, *b3;
+    int i;
+    if (bonk_filterbanklist == b)
+        bonk_filterbanklist = b->b_next;
+    else for (b2 = bonk_filterbanklist; b3 = b2->b_next; b2 = b3)
+        if (b3 == b)
+    {
+        b2->b_next = b3->b_next;
+        break;
+    }
+    for (i = 0; i < b->b_nfilters; i++)
+        if (b->b_vec[i].k_stuff)
+            freebytes(b->b_vec[i].k_stuff,
+                b->b_vec[i].k_filterpoints * sizeof(float));
+    freebytes(b, sizeof(*b));
+}
+
+static void bonk_donew(t_bonk *x, int npoints, int period, int nsig, 
+    int nfilters, float halftones, float overlap, float firstbin,
+    float minbandwidth, float samplerate)
+{
+    int i, j;
+    t_hist *h;
+    float *fp;
+    t_insig *g;
+    t_filterbank *fb;
+    for (j = 0, g = x->x_insig; j < nsig; j++, g++)
+    {
+        for (i = 0, h = g->g_hist; i--; h++)
+        {
+            h->h_power = h->h_before = 0, h->h_countup = 0;
+            for (j = 0; j < MASKHIST; j++)
+                h->h_mask[j] = 0;
+        }
+            /* we ought to check for failure to allocate memory here */
+        g->g_inbuf = (float *)getbytes(npoints * sizeof(float));
+        for (i = npoints, fp = g->g_inbuf; i--; fp++) *fp = 0;
+    }
+    if (!period) period = npoints/2;
+    x->x_npoints = npoints;
+    x->x_period = period;
+    x->x_ninsig = nsig;
+    x->x_nfilters = nfilters;
+    x->x_halftones = halftones;
+    x->x_template = (t_template *)getbytes(0);
+    x->x_ntemplate = 0;
+    x->x_infill = 0;
+    x->x_countdown = 0;
+    x->x_willattack = 0;
+    x->x_attacked = 0;
+    x->x_maskphase = 0;
+    x->x_debug = 0;
+    x->x_hithresh = DEFHITHRESH;
+    x->x_lothresh = DEFLOTHRESH;
+    x->x_masktime = DEFMASKTIME;
+    x->x_maskdecay = DEFMASKDECAY;
+    x->x_learn = 0;
+    x->x_learndebounce = clock_getsystime();
+    x->x_learncount = 0;
+    x->x_debouncedecay = DEFDEBOUNCEDECAY;
+    x->x_minvel = DEFMINVEL;
+    x->x_useloudness = 0;
+    x->x_debouncevel = 0;
+    x->x_attackbins = DEFATTACKBINS;
+    x->x_sr = samplerate;
+    x->x_filterbank = 0;
+    x->x_hit = 0;
+    for (fb = bonk_filterbanklist; fb; fb = fb->b_next)
+        if (fb->b_nfilters == x->x_nfilters &&
+            fb->b_halftones == x->x_halftones &&
+            fb->b_firstbin == firstbin &&
+            fb->b_overlap == overlap &&
+            fb->b_npoints == x->x_npoints &&
+            fb->b_minbandwidth == minbandwidth)
+    {
+        fb->b_refcount++;
+        x->x_filterbank = fb;
+        break;
+    }
+    if (!x->x_filterbank)
+        x->x_filterbank = bonk_newfilterbank(npoints, nfilters, 
+            halftones, overlap, firstbin, minbandwidth),
+                x->x_filterbank->b_refcount++;
+}
+
+static void bonk_tick(t_bonk *x)
+{
+    t_atom at[MAXNFILTERS], *ap, at2[3];
+    int i, j, k, n;
+    t_hist *h;
+    float *pp, vel = 0, temperature = 0;
+    float *fp;
+    t_template *tp;
+    int nfit, ninsig = x->x_ninsig, ntemplate = x->x_ntemplate, nfilters = x->x_nfilters;
+    t_insig *gp;
+#ifdef _MSC_VER
+    float powerout[MAXNFILTERS*MAXCHANNELS];
+#else
+    float *powerout = alloca(x->x_nfilters * x->x_ninsig * sizeof(*powerout));
+#endif
+    
+    for (i = ninsig, pp = powerout, gp = x->x_insig; i--; gp++)
+    {
+        for (j = 0, h = gp->g_hist; j < nfilters; j++, h++, pp++)
+        {
+            float power = h->h_outpower;
+            float intensity = *pp = (power > 0 ? 100. * qrsqrt(qrsqrt(power)) : 0);
+            vel += intensity;
+            temperature += intensity * (float)j;
+        }
+    }
+    if (vel > 0) temperature /= vel;
+    else temperature = 0;
+    vel *= 0.5 / ninsig;        /* fudge factor */
+    if (x->x_hit)
+    {
+        /* if hit nonzero it's a clock callback.  if in "learn" mode update the
+         template list; in any event match the hit to known templates. */
+        
+        if (vel < x->x_debouncevel)
+        {
+            if (x->x_debug)
+                post("bounce cancelled: vel %f debounce %f",
+                     vel, x->x_debouncevel);
+            return;
+        }
+        if (vel < x->x_minvel)
+        {
+            if (x->x_debug)
+                post("low velocity cancelled: vel %f, minvel %f",
+                     vel, x->x_minvel);
+            return;
+        }
+        x->x_debouncevel = vel;
+        if (x->x_learn)
+        {
+            double lasttime = x->x_learndebounce;
+            double msec = clock_gettimesince(lasttime);
+            if ((!ntemplate) || (msec > 200))
+            {
+                int countup = x->x_learncount;
+                /* normalize to 100  */
+                float norm;
+                for (i = nfilters * ninsig, norm = 0, pp = powerout; i--; pp++)
+                    norm += *pp * *pp;
+                if (norm < 1.0e-15) norm = 1.0e-15;
+                norm = 100.f * qrsqrt(norm);
+                /* check if this is the first strike for a new template */
+                if (!countup)
+                {
+                    int oldn = ntemplate;
+                    x->x_ntemplate = ntemplate = oldn + ninsig;
+                    x->x_template = (t_template *)t_resizebytes(x->x_template,
+                        oldn * sizeof(x->x_template[0]),
+                            ntemplate * sizeof(x->x_template[0]));
+                    for (i = ninsig, pp = powerout; i--; oldn++)
+                        for (j = nfilters, fp = x->x_template[oldn].t_amp; j--;
+                             pp++, fp++)
+                                *fp = *pp * norm;
+                }
+                else
+                {
+                    int oldn = ntemplate - ninsig;
+                    if (oldn < 0) post("bonk_tick bug");
+                    for (i = ninsig, pp = powerout; i--; oldn++)
+                    {
+                        for (j = nfilters, fp = x->x_template[oldn].t_amp; j--;
+                             pp++, fp++)
+                            *fp = (countup * *fp + *pp * norm)
+                            /(countup + 1.0f);
+                    }
+                }
+                countup++;
+                if (countup == x->x_learn) countup = 0;
+                x->x_learncount = countup;
+            }
+            else return;
+        }
+        x->x_learndebounce = clock_getsystime();
+        if (ntemplate)
+        {
+            float bestfit = -1e30;
+            int templatecount;
+            nfit = -1;
+            for (i = 0, templatecount = 0, tp = x->x_template; 
+                 templatecount < ntemplate; i++)
+            {
+                float dotprod = 0;
+                for (k = 0, pp = powerout;
+                     k < ninsig && templatecount < ntemplate;
+                     k++, tp++, templatecount++)
+                {
+                    for (j = nfilters, fp = tp->t_amp;
+                         j--; fp++, pp++)
+                    {
+                        if (*fp < 0 || *pp < 0) post("bonk_tick bug 2");
+                        dotprod += *fp * *pp;
+                    }
+                }
+                if (dotprod > bestfit)
+                {
+                    bestfit = dotprod;
+                    nfit = i;
+                }
+            }
+            if (nfit < 0) post("bonk_tick bug");
+        }
+        else nfit = 0;
+    }
+    else nfit = -1;     /* hit is zero; this is the "bang" method. */
+    
+    x->x_attacked = 1;
+    if (x->x_debug)
+        post("bonk out: number %d, vel %f, temperature %f",
+            nfit, vel, temperature);
+    
+    SETFLOAT(at2, nfit);
+    SETFLOAT(at2+1, vel);
+    SETFLOAT(at2+2, temperature);
+    outlet_list(x->x_cookedout, 0, 3, at2);
+    
+    for (n = 0, gp = x->x_insig + (ninsig-1),
+        pp = powerout + nfilters * (ninsig-1); n < ninsig;
+            n++, gp--, pp -= nfilters)
+    {
+        float *pp2;
+        for (i = 0, ap = at, pp2 = pp; i < nfilters;
+            i++, ap++, pp2++)
+        {
+            ap->a_type = A_FLOAT;
+            ap->a_w.w_float = *pp2;
+        }
+        outlet_list(gp->g_outlet, 0, nfilters, at);
+    }
+}
+
+static void bonk_doit(t_bonk *x)
+{
+    int i, j, ch, n;
+    t_filterkernel *k;
+    t_hist *h;
+    float growth = 0, *fp1, *fp3, *fp4, hithresh, lothresh;
+    int ninsig = x->x_ninsig, nfilters = x->x_nfilters,
+        maskphase = x->x_maskphase, nextphase, oldmaskphase;
+    t_insig *gp;
+    nextphase = maskphase + 1;
+    if (nextphase >= MASKHIST)
+        nextphase = 0;
+    x->x_maskphase = nextphase;
+    oldmaskphase = nextphase - x->x_attackbins;
+    if (oldmaskphase < 0)
+        oldmaskphase += MASKHIST;
+    if (x->x_useloudness)
+        hithresh = qrsqrt(qrsqrt(x->x_hithresh)),
+        lothresh = qrsqrt(qrsqrt(x->x_lothresh));
+    else hithresh = x->x_hithresh, lothresh = x->x_lothresh;
+    for (ch = 0, gp = x->x_insig; ch < ninsig; ch++, gp++)
+    {
+        for (i = 0, k = x->x_filterbank->b_vec, h = gp->g_hist;
+             i < nfilters; i++, k++, h++)
+        {
+            float power = 0, maskpow = h->h_mask[maskphase];
+            float *inbuf= gp->g_inbuf + k->k_skippoints;
+            int countup = h->h_countup;
+            int filterpoints = k->k_filterpoints;
+            /* if the user asked for more filters that fit under the
+             Nyquist frequency, some filters won't actually be filled in
+             so we skip running them. */
+            if  (!filterpoints)
+            {
+                h->h_countup = 0;
+                h->h_mask[nextphase] = 0;
+                h->h_power = 0;
+                continue;
+            }
+            /* run the filter repeatedly, sliding it forward by hoppoints,
+             for nhop times */
+            for (fp1 = inbuf, n = 0;
+                 n < k->k_nhops; fp1 += k->k_hoppoints, n++)
+            {
+                float rsum = 0, isum = 0;
+                for (fp3 = fp1, fp4 = k->k_stuff, j = filterpoints; j--;)
+                {
+                    float g = *fp3++;
+                    rsum += g * *fp4++;
+                    isum += g * *fp4++;
+                }
+                power += rsum * rsum + isum * isum;
+            }
+            if (!x->x_willattack) 
+                h->h_before = maskpow;
+            
+            if (power > h->h_mask[oldmaskphase])
+            {
+                if (x->x_useloudness)
+                    growth += qrsqrt(qrsqrt(
+                        power/(h->h_mask[oldmaskphase] + 1.0e-15))) - 1.f;
+                else growth += power/(h->h_mask[oldmaskphase] + 1.0e-15) - 1.f;
+            }
+            if (!x->x_willattack && countup >= x->x_masktime)
+                maskpow *= x->x_maskdecay;
+            
+            if (power > maskpow)
+            {
+                maskpow = power;
+                countup = 0;
+            }
+            countup++;
+            h->h_countup = countup;
+            h->h_mask[nextphase] = maskpow;
+            h->h_power = power;
+        }
+    }
+    if (x->x_willattack)
+    {
+        if (x->x_willattack > MAXATTACKWAIT || growth < x->x_lothresh)
+        {
+            /* if haven't yet, and if not in spew mode, report a hit */
+            if (!x->x_spew && !x->x_attacked)
+            {
+                for (ch = 0, gp = x->x_insig; ch < ninsig; ch++, gp++)
+                    for (i = nfilters, h = gp->g_hist; i--; h++)
+                        h->h_outpower = h->h_mask[nextphase];
+                x->x_hit = 1;
+                clock_delay(x->x_clock, 0);
+            }
+        }
+        if (growth < x->x_lothresh)
+            x->x_willattack = 0;
+        else x->x_willattack++;
+    }
+    else if (growth > x->x_hithresh)
+    {
+        if (x->x_debug) post("attack: growth = %f", growth);
+        x->x_willattack = 1;
+        x->x_attacked = 0;
+        for (ch = 0, gp = x->x_insig; ch < ninsig; ch++, gp++)
+            for (i = nfilters, h = gp->g_hist; i--; h++)
+                h->h_mask[nextphase] = h->h_power, h->h_countup = 0;
+    }
+    
+    /* if in "spew" mode just always output */
+    if (x->x_spew)
+    {
+        for (ch = 0, gp = x->x_insig; ch < ninsig; ch++, gp++)
+            for (i = nfilters, h = gp->g_hist; i--; h++)
+                h->h_outpower = h->h_power;
+        x->x_hit = 0;
+        clock_delay(x->x_clock, 0);
+    }
+    x->x_debouncevel *= x->x_debouncedecay;
+}
+
+static t_int *bonk_perform(t_int *w)
+{
+    t_bonk *x = (t_bonk *)(w[1]);
+    int n = (int)(w[2]);
+    int onset = 0;
+    if (x->x_countdown >= n)
+        x->x_countdown -= n;
+    else
+    {
+        int i, j, ninsig = x->x_ninsig;
+        t_insig *gp;
+        if (x->x_countdown > 0)
+        {
+            n -= x->x_countdown;
+            onset += x->x_countdown;
+            x->x_countdown = 0;
+        }
+        while (n > 0)
+        {
+            int infill = x->x_infill;
+            int m = (n < (x->x_npoints - infill) ?
+                     n : (x->x_npoints - infill));
+            for (i = 0, gp = x->x_insig; i < ninsig; i++, gp++)
+            {
+                float *fp = gp->g_inbuf + infill;
+                t_float *in1 = gp->g_invec + onset;
+                for (j = 0; j < m; j++)
+                    *fp++ = *in1++;
+            }
+            infill += m;
+            x->x_infill = infill;   
+            if (infill == x->x_npoints)
+            {
+                bonk_doit(x);
+                
+                /* shift or clear the input buffer and update counters */
+                if (x->x_period > x->x_npoints)
+                    x->x_countdown = x->x_period - x->x_npoints;
+                else x->x_countdown = 0;
+                if (x->x_period < x->x_npoints)
+                {
+                    int overlap = x->x_npoints - x->x_period;
+                    float *fp1, *fp2;
+                    for (n = 0, gp = x->x_insig; n < ninsig; n++, gp++)
+                        for (i = overlap, fp1 = gp->g_inbuf,
+                             fp2 = fp1 + x->x_period; i--;)
+                                *fp1++ = *fp2++;
+                    x->x_infill = overlap;
+                }
+                else x->x_infill = 0;
+            }
+            n -= m;
+            onset += m;
+        }
+    }
+    return (w+3);
+}
+
+static void bonk_dsp(t_bonk *x, t_signal **sp)
+{
+    int i, n = sp[0]->s_n, ninsig = x->x_ninsig;
+    t_insig *gp;
+    
+    x->x_sr = sp[0]->s_sr;
+    
+    for (i = 0, gp = x->x_insig; i < ninsig; i++, gp++)
+        gp->g_invec = (*(sp++))->s_vec;
+    
+    dsp_add(bonk_perform, 2, x, n);
+}
+
+static void bonk_thresh(t_bonk *x, t_floatarg f1, t_floatarg f2)
+{
+    if (f1 > f2)
+        post("bonk: warning: low threshold greater than hi threshold");
+    x->x_lothresh = (f1 <= 0 ? 0.0001 : f1);
+    x->x_hithresh = (f2 <= 0 ? 0.0001 : f2);
+}
+
+#ifdef PD
+static void bonk_mask(t_bonk *x, t_floatarg f1, t_floatarg f2)
+{
+    int ticks = f1;
+    if (ticks < 0) ticks = 0;
+    if (f2 < 0) f2 = 0;
+    else if (f2 > 1) f2 = 1;
+    x->x_masktime = ticks;
+    x->x_maskdecay = f2;
+}
+
+static void bonk_debounce(t_bonk *x, t_floatarg f1)
+{
+    if (f1 < 0) f1 = 0;
+    else if (f1 > 1) f1 = 1;
+    x->x_debouncedecay = f1;
+}
+
+static void bonk_minvel(t_bonk *x, t_floatarg f)
+{
+    if (f < 0) f = 0; 
+    x->x_minvel = f;
+}
+
+static void bonk_debug(t_bonk *x, t_floatarg f)
+{
+    x->x_debug = (f != 0);
+}
+
+static void bonk_spew(t_bonk *x, t_floatarg f)
+{
+    x->x_spew = (f != 0);
+}
+
+static void bonk_useloudness(t_bonk *x, t_floatarg f)
+{
+    x->x_useloudness = (f != 0);
+}
+
+static void bonk_attackbins(t_bonk *x, t_floatarg f)
+{
+    if (f < 1)
+        f = 1;
+    else if (f > MASKHIST)
+        f = MASKHIST;
+    x->x_attackbins = f;
+}
+
+static void bonk_learn(t_bonk *x, t_floatarg f)
+{
+    int n = f;
+    if (n < 0) n = 0;
+    if (n)
+    {
+        x->x_template = (t_template *)t_resizebytes(x->x_template,
+            x->x_ntemplate * sizeof(x->x_template[0]), 0);
+        x->x_ntemplate = 0;
+    }
+    x->x_learn = n;
+    x->x_learncount = 0;
+}
+#endif
+
+static void bonk_print(t_bonk *x, t_floatarg f)
+{
+    int i;
+    post("thresh %f %f", x->x_lothresh, x->x_hithresh);
+    post("mask %d %f", x->x_masktime, x->x_maskdecay);
+    post("attack-frames %d", x->x_attackbins);
+    post("debounce %f", x->x_debouncedecay);
+    post("minvel %f", x->x_minvel);
+    post("spew %d", x->x_spew);
+    post("useloudness %d", x->x_useloudness);
+    
+#if 0       /* LATER rewrite without hard-coded 11 filters */
+    if (x->x_ntemplate)
+    {
+        post("templates:");
+        for (i = 0; i < x->x_ntemplate; i++)
+            post(
+"%2d %5.2f %5.2f %5.2f %5.2f %5.2f %5.2f %5.2f %5.2f %5.2f %5.2f %5.2f",
+                i,
+                x->x_template[i].t_amp[0],
+                x->x_template[i].t_amp[1],
+                x->x_template[i].t_amp[2],
+                x->x_template[i].t_amp[3],
+                x->x_template[i].t_amp[4],
+                x->x_template[i].t_amp[5],
+                x->x_template[i].t_amp[6],
+                x->x_template[i].t_amp[7],
+                x->x_template[i].t_amp[8],
+                x->x_template[i].t_amp[9],
+                x->x_template[i].t_amp[10]);
+    }
+    else post("no templates");
+#endif
+    post("number of templates %d", x->x_ntemplate);
+    if (x->x_learn) post("learn mode");
+    if (f != 0)
+    {
+        int j, ninsig = x->x_ninsig;
+        t_insig *gp;
+        for (j = 0, gp = x->x_insig; j < ninsig; j++, gp++)
+        {
+            t_hist *h;
+            if (ninsig > 1) post("input %d:", j+1);
+            for (i = x->x_nfilters, h = gp->g_hist; i--; h++)
+                post("pow %f mask %f before %f count %d",
+                     h->h_power, h->h_mask[x->x_maskphase],
+                     h->h_before, h->h_countup);
+        }
+        post("filter details (frequencies are in units of %.2f-Hz. bins):",
+             x->x_sr/x->x_npoints);
+        for (j = 0; j < x->x_nfilters; j++)
+            post("%2d  cf %.2f  bw %.2f  nhops %d hop %d skip %d npoints %d",
+                 j, 
+                 x->x_filterbank->b_vec[j].k_centerfreq,
+                 x->x_filterbank->b_vec[j].k_bandwidth,
+                 x->x_filterbank->b_vec[j].k_nhops,
+                 x->x_filterbank->b_vec[j].k_hoppoints,
+                 x->x_filterbank->b_vec[j].k_skippoints,
+                 x->x_filterbank->b_vec[j].k_filterpoints);
+    }
+    if (x->x_debug) post("debug mode");
+}
+
+static void bonk_forget(t_bonk *x)
+{
+    int ntemplate = x->x_ntemplate, newn = ntemplate - x->x_ninsig;
+    if (newn < 0) newn = 0;
+    x->x_template = (t_template *)t_resizebytes(x->x_template,
+        x->x_ntemplate * sizeof(x->x_template[0]),
+            newn * sizeof(x->x_template[0]));
+    x->x_ntemplate = newn;
+    x->x_learncount = 0;
+}
+
+static void bonk_bang(t_bonk *x)
+{
+    int i, ch;
+    t_insig *gp;
+    x->x_hit = 0;
+    for (ch = 0, gp = x->x_insig; ch < x->x_ninsig; ch++, gp++)
+    {
+        t_hist *h;
+        for (i = 0, h = gp->g_hist; i < x->x_nfilters; i++, h++)
+            h->h_outpower = h->h_power;
+    }
+    bonk_tick(x);
+}
+
+static void bonk_read(t_bonk *x, t_symbol *s)
+{
+    FILE *fd = fopen(s->s_name, "r");
+    float vec[MAXNFILTERS];
+    int i, ntemplate = 0, remaining;
+    float *fp, *fp2;
+    if (!fd)
+    {
+        post("%s: open failed", s->s_name);
+        return;
+    }
+    x->x_template = (t_template *)t_resizebytes(x->x_template, 
+        x->x_ntemplate * sizeof(t_template), 0);
+    while (1)
+    {
+        for (i = x->x_nfilters, fp = vec; i--; fp++)
+            if (fscanf(fd, "%f", fp) < 1) goto nomore;
+        x->x_template = (t_template *)t_resizebytes(x->x_template,
+            ntemplate * sizeof(t_template),
+                (ntemplate + 1) * sizeof(t_template));
+        for (i = x->x_nfilters, fp = vec,
+             fp2 = x->x_template[ntemplate].t_amp; i--;)
+            *fp2++ = *fp++;
+        ntemplate++;
+    }
+nomore:
+    if (remaining = (ntemplate % x->x_ninsig))
+    {
+        post("bonk_read: %d templates not a multiple of %d; dropping extras");
+        x->x_template = (t_template *)t_resizebytes(x->x_template,
+            ntemplate * sizeof(t_template),
+                (ntemplate - remaining) * sizeof(t_template));
+        ntemplate = ntemplate - remaining;
+    }
+    post("bonk: read %d templates\n", ntemplate);
+    x->x_ntemplate = ntemplate;
+    fclose(fd);
+}
+
+static void bonk_write(t_bonk *x, t_symbol *s)
+{
+    FILE *fd = fopen(s->s_name, "w");
+    int i, ntemplate = x->x_ntemplate;
+    t_template *tp = x->x_template;
+    float *fp;
+    if (!fd)
+    {
+        post("%s: couldn't create", s->s_name);
+        return;
+    }
+    for (; ntemplate--; tp++)
+    {
+        for (i = x->x_nfilters, fp = tp->t_amp; i--; fp++)
+            fprintf(fd, "%6.2f ", *fp);
+        fprintf(fd, "\n");
+    }
+    post("bonk: wrote %d templates\n", x->x_ntemplate);
+    fclose(fd);
+}
+
+static void bonk_free(t_bonk *x)
+{
+    
+    int i, ninsig = x->x_ninsig;
+    t_insig *gp = x->x_insig;
+#ifdef MSP
+    dsp_free((t_pxobject *)x);
+#endif
+    for (i = 0, gp = x->x_insig; i < ninsig; i++, gp++)
+        freebytes(gp->g_inbuf, x->x_npoints * sizeof(float));
+    clock_free(x->x_clock);
+    if (!--(x->x_filterbank->b_refcount))
+        bonk_freefilterbank(x->x_filterbank);
+    
+}
+
+/* -------------------------- Pd glue ------------------------- */
+#ifdef PD
+
+static void *bonk_new(t_symbol *s, int argc, t_atom *argv)
+{
+    t_bonk *x = (t_bonk *)pd_new(bonk_class);
+    int nsig = 1, period = DEFPERIOD, npts = DEFNPOINTS,
+        nfilters = DEFNFILTERS, j;
+    float halftones = DEFHALFTONES, overlap = DEFOVERLAP,
+        firstbin = DEFFIRSTBIN, minbandwidth = DEFMINBANDWIDTH;
+    t_insig *g;
+
+    if (argc > 0 && argv[0].a_type == A_FLOAT)
+    {
+            /* old style args for compatibility */
+        period = atom_getfloatarg(0, argc, argv);
+        nsig = atom_getfloatarg(1, argc, argv);
+    }
+    else while (argc > 0)
+    {
+        t_symbol *firstarg = atom_getsymbolarg(0, argc, argv);
+        if (!strcmp(firstarg->s_name, "-npts") && argc > 1)
+        {
+            npts = atom_getfloatarg(1, argc, argv);
+            argc -= 2; argv += 2;
+        }
+        else if (!strcmp(firstarg->s_name, "-hop") && argc > 1)
+        {
+            period = atom_getfloatarg(1, argc, argv);
+            argc -= 2; argv += 2;
+        }
+        else if (!strcmp(firstarg->s_name, "-nsigs") && argc > 1)
+        {
+            nsig = atom_getfloatarg(1, argc, argv);
+            argc -= 2; argv += 2;
+        }
+        else if (!strcmp(firstarg->s_name, "-nfilters") && argc > 1)
+        {
+            nfilters = atom_getfloatarg(1, argc, argv);
+            argc -= 2; argv += 2;
+        }
+        else if (!strcmp(firstarg->s_name, "-halftones") && argc > 1)
+        {
+            halftones = atom_getfloatarg(1, argc, argv);
+            argc -= 2; argv += 2;
+        }
+        else if (!strcmp(firstarg->s_name, "-overlap") && argc > 1)
+        {
+            overlap = atom_getfloatarg(1, argc, argv);
+            argc -= 2; argv += 2;
+        }
+        else if (!strcmp(firstarg->s_name, "-firstbin") && argc > 1)
+        {
+            firstbin = atom_getfloatarg(1, argc, argv);
+            argc -= 2; argv += 2;
+        }
+        else if (!strcmp(firstarg->s_name, "-minbandwidth") && argc > 1)
+        {
+            minbandwidth = atom_getfloatarg(1, argc, argv);
+            argc -= 2; argv += 2;
+        }
+        else if (!strcmp(firstarg->s_name, "-spew") && argc > 1)
+        {
+            x->x_spew = (atom_getfloatarg(1, argc, argv) != 0);
+            argc -= 2; argv += 2;
+        }
+        else
+        {
+            pd_error(x,
+"usage is: bonk [-npts #] [-hop #] [-nsigs #] [-nfilters #] [-halftones #]"); 
+            post(
+"... [-overlap #] [-firstbin #] [-spew #]");
+            argc = 0;
+        }
+    }
+
+    x->x_npoints = (npts >= MINPOINTS ? npts : DEFNPOINTS);
+    x->x_period = (period >= 1 ? period : npts/2);
+    x->x_nfilters = (nfilters >= 1 ? nfilters : DEFNFILTERS);
+    if (halftones < 0.01)
+        halftones = DEFHALFTONES;
+    else if (halftones > 12)
+        halftones = 12;
+    if (nsig < 1)
+        nsig = 1;
+    else if (nsig > MAXCHANNELS)
+        nsig = MAXCHANNELS;
+    if (firstbin < 0.5)
+        firstbin = 0.5;
+    if (overlap < 1)
+        overlap = 1;
+
+    x->x_clock = clock_new(x, (t_method)bonk_tick);
+    x->x_insig = (t_insig *)getbytes(nsig * sizeof(*x->x_insig));
+    for (j = 0, g = x->x_insig; j < nsig; j++, g++)
+    {
+        g->g_outlet = outlet_new(&x->x_obj, gensym("list"));
+        if (j)
+            inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal);
+    }
+    x->x_cookedout = outlet_new(&x->x_obj, gensym("list"));
+    bonk_donew(x, npts, period, nsig, nfilters, halftones, overlap,
+        firstbin, minbandwidth, sys_getsr());
+    return (x);
+}
+
+void bonk_tilde_setup(void)
+{
+    bonk_class = class_new(gensym("bonk~"), (t_newmethod)bonk_new,
+        (t_method)bonk_free, sizeof(t_bonk), 0, A_GIMME, 0);
+    class_addmethod(bonk_class, nullfn, gensym("signal"), 0);
+    class_addmethod(bonk_class, (t_method)bonk_dsp, gensym("dsp"), 0);
+    class_addbang(bonk_class, bonk_bang);
+    class_addmethod(bonk_class, (t_method)bonk_learn,
+        gensym("learn"), A_FLOAT, 0);
+    class_addmethod(bonk_class, (t_method)bonk_forget, gensym("forget"), 0);
+    class_addmethod(bonk_class, (t_method)bonk_thresh,
+        gensym("thresh"), A_FLOAT, A_FLOAT, 0);
+    class_addmethod(bonk_class, (t_method)bonk_mask,
+        gensym("mask"), A_FLOAT, A_FLOAT, 0);
+    class_addmethod(bonk_class, (t_method)bonk_debounce,
+        gensym("debounce"), A_FLOAT, 0);
+    class_addmethod(bonk_class, (t_method)bonk_minvel,
+        gensym("minvel"), A_FLOAT, 0);
+    class_addmethod(bonk_class, (t_method)bonk_print,
+        gensym("print"), A_DEFFLOAT, 0);
+    class_addmethod(bonk_class, (t_method)bonk_debug,
+        gensym("debug"), A_DEFFLOAT, 0);
+    class_addmethod(bonk_class, (t_method)bonk_spew,
+        gensym("spew"), A_DEFFLOAT, 0);
+    class_addmethod(bonk_class, (t_method)bonk_useloudness,
+        gensym("useloudness"), A_DEFFLOAT, 0);
+    class_addmethod(bonk_class, (t_method)bonk_attackbins,
+        gensym("attack-bins"), A_DEFFLOAT, 0);
+    class_addmethod(bonk_class, (t_method)bonk_attackbins,
+        gensym("attack-frames"), A_DEFFLOAT, 0);
+    class_addmethod(bonk_class, (t_method)bonk_read,
+        gensym("read"), A_SYMBOL, 0);
+    class_addmethod(bonk_class, (t_method)bonk_write,
+        gensym("write"), A_SYMBOL, 0);
+    post("bonk version 1.3");
+}
+#endif
+
+/* -------------------------- MSP glue ------------------------- */
+#ifdef MSP
+
+int main()
+{       
+        t_class *c;
+        t_object *attr;
+        long attrflags = 0;
+        t_symbol *sym_long = gensym("long"), *sym_float32 = gensym("float32");
+        
+        c = class_new("bonk~", (method)bonk_new, (method)bonk_free, sizeof(t_bonk), (method)0L, A_GIMME, 0);
+        
+        class_obexoffset_set(c, calcoffset(t_bonk, obex));
+        
+        attr = attr_offset_new("npoints", sym_long, attrflags, (method)0L, (method)0L, calcoffset(t_bonk, x_npoints));
+        class_addattr(c, attr);
+        
+        attr = attr_offset_new("hop", sym_long, attrflags, (method)0L, (method)0L, calcoffset(t_bonk, x_period));
+        class_addattr(c, attr);
+        
+        attr = attr_offset_new("nfilters", sym_long, attrflags, (method)0L, (method)0L, calcoffset(t_bonk, x_nfilters));
+        class_addattr(c, attr);
+        
+        attr = attr_offset_new("halftones", sym_float32, attrflags, (method)0L, (method)0L, calcoffset(t_bonk, x_halftones));
+        class_addattr(c, attr);
+        
+        attr = attr_offset_new("overlap", sym_float32, attrflags, (method)0L, (method)0L, calcoffset(t_bonk, x_overlap));
+        class_addattr(c, attr);
+        
+        attr = attr_offset_new("firstbin", sym_float32, attrflags, (method)0L, (method)0L, calcoffset(t_bonk, x_firstbin));
+        class_addattr(c, attr);
+        
+        attr = attr_offset_new("minbandwidth", sym_float32, attrflags, (method)0L, (method)0L, calcoffset(t_bonk, x_minbandwidth));
+        class_addattr(c, attr);
+        
+        attr = attr_offset_new("minvel", sym_float32, attrflags, (method)0L, (method)bonk_minvel_set, calcoffset(t_bonk, x_minvel));
+        class_addattr(c, attr);
+        
+        attr = attr_offset_new("lothresh", sym_float32, attrflags, (method)0L, (method)bonk_lothresh_set, calcoffset(t_bonk, x_lothresh));
+        class_addattr(c, attr);
+        
+        attr = attr_offset_new("hithresh", sym_float32, attrflags, (method)0L, (method)bonk_hithresh_set, calcoffset(t_bonk, x_hithresh));
+        class_addattr(c, attr);
+        
+        attr = attr_offset_new("masktime", sym_long, attrflags, (method)0L, (method)bonk_masktime_set, calcoffset(t_bonk, x_masktime));
+        class_addattr(c, attr);
+        
+        attr = attr_offset_new("maskdecay", sym_float32, attrflags, (method)0L, (method)bonk_maskdecay_set, calcoffset(t_bonk, x_maskdecay));
+        class_addattr(c, attr);
+    
+        attr = attr_offset_new("debouncedecay", sym_float32, attrflags, (method)0L, (method)bonk_debouncedecay_set, calcoffset(t_bonk, x_debouncedecay));
+        class_addattr(c, attr);
+        
+        attr = attr_offset_new("debug", sym_long, attrflags, (method)0L, (method)bonk_debug_set, calcoffset(t_bonk, x_debug));
+        class_addattr(c, attr);
+        
+        attr = attr_offset_new("spew", sym_long, attrflags, (method)0L, (method)bonk_spew_set, calcoffset(t_bonk, x_spew));
+        class_addattr(c, attr);
+        
+        attr = attr_offset_new("useloudness", sym_long, attrflags, (method)0L, (method)bonk_useloudness_set, calcoffset(t_bonk, x_useloudness));
+        class_addattr(c, attr);
+
+        attr = attr_offset_new("attackframes", sym_long, attrflags, (method)0L, (method)bonk_attackbins_set, calcoffset(t_bonk, x_attackbins));
+        class_addattr(c, attr);
+        
+        attr = attr_offset_new("learn", sym_long, attrflags, (method)0L, (method)bonk_learn_set, calcoffset(t_bonk, x_learn));
+        class_addattr(c, attr);
+    
+        class_addmethod(c, (method)bonk_dsp, "dsp", A_CANT, 0);
+        class_addmethod(c, (method)bonk_bang, "bang", A_CANT, 0);
+        class_addmethod(c, (method)bonk_forget, "forget", 0);
+        class_addmethod(c, (method)bonk_thresh, "thresh", A_FLOAT, A_FLOAT, 0);
+        class_addmethod(c, (method)bonk_print, "print", A_DEFFLOAT, 0);
+        class_addmethod(c, (method)bonk_read, "read", A_DEFSYM, 0);
+        class_addmethod(c, (method)bonk_write, "write", A_DEFSYM, 0);
+        class_addmethod(c, (method)bonk_assist, "assist", A_CANT, 0);
+        
+        class_addmethod(c, (method)object_obex_dumpout, "dumpout", A_CANT, 0);
+        class_addmethod(c, (method)object_obex_quickref, "quickref", A_CANT, 0);
+        
+        class_dspinit(c);
+    
+        class_register(CLASS_BOX, c);
+        bonk_class = c;
+        
+        post("bonk~ v1.3");
+        return (0);
+}
+
+static void *bonk_new(t_symbol *s, long ac, t_atom *av)
+{
+    short j;
+    t_bonk *x;
+        
+    if (x = (t_bonk *)object_alloc(bonk_class)) {
+        
+        t_insig *g;
+
+        x->x_npoints = DEFNPOINTS;
+        x->x_period = DEFPERIOD;
+        x->x_nfilters = DEFNFILTERS;
+        x->x_halftones = DEFHALFTONES;
+        x->x_firstbin = DEFFIRSTBIN;
+        x->x_minbandwidth = DEFMINBANDWIDTH;
+        x->x_overlap = DEFOVERLAP;
+        x->x_ninsig = 1;
+
+        x->x_hithresh = DEFHITHRESH;
+        x->x_lothresh = DEFLOTHRESH;
+        x->x_masktime = DEFMASKTIME;
+        x->x_maskdecay = DEFMASKDECAY;
+        x->x_debouncedecay = DEFDEBOUNCEDECAY;
+        x->x_minvel = DEFMINVEL;
+        x->x_attackbins = DEFATTACKBINS;
+        
+        if (!x->x_period) x->x_period = x->x_npoints/2;
+        x->x_template = (t_template *)getbytes(0);
+        x->x_ntemplate = 0;
+        x->x_infill = 0;
+        x->x_countdown = 0;
+        x->x_willattack = 0;
+        x->x_attacked = 0;
+        x->x_maskphase = 0;
+        x->x_debug = 0;
+        x->x_learn = 0;
+        x->x_learndebounce = clock_getsystime();
+        x->x_learncount = 0;
+        x->x_useloudness = 0;
+        x->x_debouncevel = 0;
+        x->x_sr = sys_getsr();
+        
+        if (ac) {
+            switch (av[0].a_type) {
+                case A_LONG:
+                    x->x_ninsig = av[0].a_w.w_long;
+                    break;
+            }
+        }
+
+        if (x->x_ninsig < 1) x->x_ninsig = 1;
+        if (x->x_ninsig > MAXCHANNELS) x->x_ninsig = MAXCHANNELS;
+        
+        attr_args_process(x, ac, av);   
+
+        x->x_insig = (t_insig *)getbytes(x->x_ninsig * sizeof(*x->x_insig));
+
+        dsp_setup((t_pxobject *)x, x->x_ninsig);
+
+        object_obex_store(x, gensym("dumpout"), outlet_new(x, NULL));
+
+        x->x_cookedout = listout((t_object *)x);
+
+        for (j = 0, g = x->x_insig + x->x_ninsig-1; j < x->x_ninsig; j++, g--) {
+                g->g_outlet = listout((t_object *)x);
+        }
+
+        x->x_clock = clock_new(x, (method)bonk_tick);
+
+        bonk_donew(x, x->x_npoints, x->x_period, x->x_ninsig, x->x_nfilters,
+            x->x_halftones, x->x_overlap, x->x_firstbin, x->x_minbandwidth,
+                sys_getsr());
+    }
+    return (x);
+}
+
+/* Attribute setters. */
+void bonk_minvel_set(t_bonk *x, void *attr, long ac, t_atom *av)
+{
+    if (ac && av) {
+        float f = atom_getfloat(av);
+        if (f < 0) f = 0; 
+        x->x_minvel = f;
+    }
+}
+
+void bonk_lothresh_set(t_bonk *x, void *attr, long ac, t_atom *av)
+{
+    if (ac && av) {
+        float f = atom_getfloat(av);
+        if (f > x->x_hithresh)
+            post("bonk: warning: low threshold greater than hi threshold");
+        x->x_lothresh = (f <= 0 ? 0.0001 : f);
+    }
+}
+    
+void bonk_hithresh_set(t_bonk *x, void *attr, long ac, t_atom *av)
+{
+    if (ac && av) {
+        float f = atom_getfloat(av);
+        if (f < x->x_lothresh)
+            post("bonk: warning: low threshold greater than hi threshold");
+        x->x_hithresh = (f <= 0 ? 0.0001 : f);
+    }
+}
+
+void bonk_masktime_set(t_bonk *x, void *attr, long ac, t_atom *av)
+{
+    if (ac && av) {
+        int n = atom_getlong(av);
+        x->x_masktime = (n < 0) ? 0 : n;
+    }
+}
+
+void bonk_maskdecay_set(t_bonk *x, void *attr, long ac, t_atom *av)
+{
+    if (ac && av) {
+        float f = atom_getfloat(av);
+        f = (f < 0) ? 0 : f;
+        f = (f > 1) ? 1 : f;
+        x->x_maskdecay = f;
+    }
+}
+
+void bonk_debouncedecay_set(t_bonk *x, void *attr, long ac, t_atom *av)
+{
+    if (ac && av) {
+        float f = atom_getfloat(av);
+        f = (f < 0) ? 0 : f;
+        f = (f > 1) ? 1 : f;
+        x->x_debouncedecay = f;
+    }
+}
+
+void bonk_debug_set(t_bonk *x, void *attr, long ac, t_atom *av)
+{
+    if (ac && av) {
+        int n = atom_getlong(av);
+        x->x_debug = (n != 0);
+    }
+}
+
+void bonk_spew_set(t_bonk *x, void *attr, long ac, t_atom *av)
+{
+    if (ac && av) {
+        int n = atom_getlong(av);
+        x->x_spew = (n != 0);
+    }
+}
+
+void bonk_useloudness_set(t_bonk *x, void *attr, long ac, t_atom *av)
+{
+    if (ac && av) {
+        int n = atom_getlong(av);
+        x->x_useloudness = (n != 0);
+    }
+}
+
+void bonk_attackbins_set(t_bonk *x, void *attr, long ac, t_atom *av)
+{
+    if (ac && av) {
+        int n = atom_getlong(av);
+        n = (n < 1) ? 1 : n;
+        n = (n > MASKHIST) ? MASKHIST : n;
+        x->x_attackbins = n;
+    }
+}
+
+void bonk_learn_set(t_bonk *x, void *attr, long ac, t_atom *av)
+{
+    if (ac && av) {
+        int n = atom_getlong(av);
+        if (n != 0) {
+            x->x_template = (t_template *)t_resizebytes(x->x_template,
+                x->x_ntemplate * sizeof(x->x_template[0]), 0);
+            x->x_ntemplate = 0;
+        }
+        x->x_learn = (n != 0);
+        x->x_learncount = 0;
+    }
+}
+/* end attr setters */
+
+void bonk_assist(t_bonk *x, void *b, long m, long a, char *s)
+{
+}
+
+    /* get current system time */
+double clock_getsystime()
+{
+    return gettime();
+}
+
+    /* elapsed time in milliseconds since the given system time */
+double clock_gettimesince(double prevsystime)
+{
+    return ((gettime() - prevsystime));
+}
+
+float qrsqrt(float f)
+{
+    return 1/sqrt(f);
+}
+#endif /* MSP */
diff --git a/extra/bonk~/makefile b/extra/bonk~/makefile
new file mode 100644
index 0000000000000000000000000000000000000000..af6399cca16d00a8033b4ba22ea02779fe98b80b
--- /dev/null
+++ b/extra/bonk~/makefile
@@ -0,0 +1,4 @@
+NAME=bonk~
+CSYM=bonk_tilde
+
+include ../makefile
diff --git a/extra/bonk~/templates.txt b/extra/bonk~/templates.txt
new file mode 100644
index 0000000000000000000000000000000000000000..f3528d78acad986c438e2c36cdef7d6f36642ba2
--- /dev/null
+++ b/extra/bonk~/templates.txt
@@ -0,0 +1,4 @@
+ 10.47   9.65  14.95  23.77  28.32  38.84  53.21  41.20  31.25  21.70  16.48 
+  6.52  13.93  27.82  58.05  24.11  35.26  35.98  37.78  22.54  13.56  10.75 
+ 30.45  28.86  29.42  21.94  29.92  35.70  38.49  32.01  28.19  27.38  22.10 
+ 66.77  46.27  28.82  25.95  22.84  20.61  20.33  14.18   6.86   8.92   7.37 
diff --git a/extra/choice/choice.pd_linux b/extra/choice/choice.pd_linux
deleted file mode 100755
index e462551346fee426bd8eab05b2c5d3030d9a0132..0000000000000000000000000000000000000000
Binary files a/extra/choice/choice.pd_linux and /dev/null differ
diff --git a/extra/expr~/LICENSE.txt b/extra/expr~/LICENSE.txt
new file mode 100644
index 0000000000000000000000000000000000000000..a52b16e4064dfee29faf4b9fdbb058237b418fce
--- /dev/null
+++ b/extra/expr~/LICENSE.txt
@@ -0,0 +1,341 @@
+
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/extra/expr~/README.txt b/extra/expr~/README.txt
new file mode 100644
index 0000000000000000000000000000000000000000..bf84f2ae6e8f83170f2940db2e2094283dd64835
--- /dev/null
+++ b/extra/expr~/README.txt
@@ -0,0 +1,97 @@
+
+You can get more information on the expr object at
+http://www.crca.ucsd.edu/~yadegari/expr.html
+
+-----------
+
+New if Version 0.4
+
+-access to variables (made by value object)
+-multiple expression separated by ;
+-added the following shorthands:
+	$y or $y1 = $y1[-1] and $y2 = $y2[-1]
+-new functions:
+	if - conditional evaluation
+	cbrt - cube root
+	erf - error function
+	erfc - complementary error function
+	expm1 - exponential minus 1,
+	log1p - logarithm of 1 plus
+	isinf - is the value infinite,
+	finite - is the value finite
+	isnan -- is the resut a nan (Not a number)
+	copysign - copy sign of a number
+	ldexp  -  multiply floating-point number by integral power of 2
+	imodf -	get signed integral value from floating-point number
+	modf - get signed fractional value from floating-point number
+	drem - floating-point remainder function
+
+   Thanks to Orm Finnendahl for adding the following functions:
+	fmod - floating-point remainder function
+	ceil - ceiling function: smallest integral value not less than argument 
+	floor - largest integral value not greater than argument
+
+------------
+
+New in Version 0.3
+-Full function functionality
+
+------------
+
+The object "expr" is used for expression evaluaion of control data.
+
+Expr~ and fexpr~ are extentions to the expr object to work with vectors.
+The expr~ object is designed to efficiently combine signal and control
+stream processing by vector operations on the basis of the block size of
+the environment.
+
+fexpr~ object provides a flexible mechanism for building FIR and
+IIR filters by evaluating expressions on a sample by sample basis
+and providing access to prior samples of the input and output audio
+streams. When fractional offset is used, fexpr~ uses linear interpolation
+to determine the value of the indexed sample. fexpr~ evaluates the
+expression for every single sample and at every evaluation previous
+samples (limited by the audio vector size) can be accessed. $x is used to
+denote a singnal input whose samples we would like to access. The syntax
+is $x followed by the inlet number and indexed by brackets, for example
+$x1[-1] specifies the previous sample of the first inlet. Therefore,
+if we are to build a simple filter which replaces every sample by
+the average of that sample and its previous one, we would use "fexpr~
+($x1[0]+$x1[-1])/2 ". For ease of when the brackets are omitted, the
+current sample is implied, so we can right the previous filter expression
+as follows:  " fexpr~ ($x1+$x1[-1])/2". To build IIR filters $y is used
+to access the previous samples of the output stream.
+
+The three objects expr, expr~, and fexpr~ are implemented in the same object
+so the files expr~.pd_linux and fexpr~.pd_linux are links to expr.pd_linux
+This release has been compiled and tested on Linux 6.0.
+
+--------
+
+Here are some syntax information: (refer to help-expr.pd for examples)
+ 
+Syntyax:
+The syntax is very close to how expression are written in
+C. Variables are specified as follows where the '#' stands
+for the inlet number:
+$i#: integer input variable
+$f#: float input variable
+$s#: symbol input variable
+
+Used for expr~ only:
+$v#: signal (vector) input (vector by vector evaluation)
+
+Used for fexpr~ only:
+$x#[n]: the sample from inlet # indexed by n, where n has to
+	satisfy 0 => n >= -vector size,
+	($x# is a shorthand for $x#[0], specifying the current sample)
+
+$y#[n]: the output value indexed by n, where n has to
+	satisfy 0 > n >= -vector size,
+	$y[n] is a shorthand for $y1[n]
+
+
+I'll appreciate hearing about bugs, comments, suggestions, ...
+
+Shahrokh Yadegari (sdy@ucsd.edu)
+7/10/02
diff --git a/extra/expr~/fts_to_pd.h b/extra/expr~/fts_to_pd.h
new file mode 100644
index 0000000000000000000000000000000000000000..9ca2fc4222da17a148135192391a5b9a46d9f6a9
--- /dev/null
+++ b/extra/expr~/fts_to_pd.h
@@ -0,0 +1,41 @@
+/* fts_to_pd.h -- alias some fts names to compile in Pd.
+
+copyright 1999 Miller Puckette;
+permission is granted to use this file for any purpose.
+*/
+
+
+#define fts_malloc malloc
+#define fts_calloc calloc
+#define fts_free free
+#define fts_realloc realloc
+#define fts_atom_t t_atom
+#define fts_object_t t_object
+typedef t_symbol *fts_symbol_t;
+
+#ifdef MSP
+#define t_atom          Atom
+#define t_symbol        Symbol
+#define pd_new(x)       newobject(x);
+#define pd_free(x)      freeobject(x);
+#define t_outlet        void
+#define t_binbuf        void
+typedef t_class         *t_pd;
+typedef float           t_floatarg;
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+
+void pd_error(void *object, char *fmt, ...);
+
+#endif /* MSP */
+
+#define post_error pd_error
+#define fts_is_floatg(x) ((x)->a_type == A_FLOAT)
+
+#define fts_new_symbol_copy gensym
+
+#define fts_symbol_name(x) ((x)->s_name)
diff --git a/extra/expr~/makefile b/extra/expr~/makefile
new file mode 100644
index 0000000000000000000000000000000000000000..4c6481407e601a0afed81ac3be4b69d478b7719f
--- /dev/null
+++ b/extra/expr~/makefile
@@ -0,0 +1,191 @@
+
+current: expr.pd_linux expr~.pd_linux fexpr~.pd_linux \
+     ../expr.pd_linux ../expr~.pd_linux ../fexpr~.pd_linux
+
+install: install_linux
+
+clean: clean_linux
+
+PDEXTERN=/usr/local/lib/pd/externs
+
+# ----------------------- NT -----------------------
+
+pd_nt: expr.dll
+
+NTOBJ =  vexp.obj vexp_fun.obj vexp_if.obj
+
+PDNTCFLAGS = /W3 /DNT /DPD /nologo
+VC = "C:\Program Files\Microsoft Visual Studio 9.0\VC"
+VSTK = "C:\Program Files\Microsoft SDKs\Windows\v6.0A"
+
+PDNTINCLUDE = /I. /I..\..\src /I$(VC)\include
+
+PDNTLDIR = $(VC)\lib
+PDNTLIB = /NODEFAULTLIB:libcmt /NODEFAULTLIB:oldnames /NODEFAULTLIB:kernel32 \
+	$(PDNTLDIR)\libcmt.lib $(PDNTLDIR)\oldnames.lib \
+        $(VSTK)\lib\kernel32.lib \
+	 ..\..\bin\pd.lib 
+
+.c.obj:
+	cl $(PDNTCFLAGS) $(PDNTINCLUDE) /c $*.c
+
+expr.dll: $(NTOBJ)
+	link /dll /export:expr_setup /export:expr_tilde_setup \
+	    /export:fexpr_tilde_setup $(NTOBJ) $(PDNTLIB)
+	ren vexp.dll expr.dll
+	copy expr.dll ..\expr.dll
+	copy expr.dll ..\expr~.dll
+	copy expr.dll ..\fexpr~.dll
+	copy help-expr.pd ..\help-expr.pd
+
+# ----------------------- IRIX 5.x -----------------------
+
+pd_irix5: 
+
+.SUFFIXES: .pd_irix5
+
+SGICFLAGS5 = -o32 -DPD -DSGI -O2
+
+
+SGIINCLUDE =  -I/usr/people/msp/pd/pd/src
+
+.c.pd_irix5:
+	$(CC) $(SGICFLAGS5) $(SGIINCLUDE) -o $*.o -c $*.c
+	ld -elf -shared -rdata_shared -o $*.pd_irix5 $*.o
+	rm $*.o
+
+# ----------------------- IRIX 6.x -----------------------
+
+pd_irix6: 
+
+.SUFFIXES: .pd_irix6
+
+SGICFLAGS6 = -DPD -DSGI -n32 \
+	-OPT:roundoff=3 -OPT:IEEE_arithmetic=3 -OPT:cray_ivdep=true \
+	-Ofast=ip32
+
+SGICFLAGS5 = -DPD -O2 -DSGI
+
+SGIINCLUDE =  -I/usr/people/msp/pd/pd/src
+
+.c.pd_irix6:
+	$(CC) $(SGICFLAGS6) $(SGIINCLUDE) -o $*.o -c $*.c
+	ld -elf -shared -rdata_shared -o $*.pd_irix6 $*.o
+	rm $*.o
+
+# ----------------------- LINUX i386 -----------------------
+
+LINUXOBJ =  vexp.pd_linux_o vexp_fun.pd_linux_o vexp_if.pd_linux_o
+.SUFFIXES: .pd_linux_o
+
+LINUXCFLAGS = -DPD -O2 -funroll-loops -fomit-frame-pointer -fPIC \
+    -fno-strict-aliasing -Wall -W -Wshadow -Wstrict-prototypes \
+    -Wno-unused -Wno-parentheses -Wno-switch 
+
+LINUXINCLUDE =  -I../../src
+
+.c.pd_linux_o:
+	$(CC) -g $(LINUXCFLAGS) $(LINUXINCLUDE) -o $*.pd_linux_o -c $*.c
+
+expr.pd_linux: $(LINUXOBJ)
+	$(CC)  -shared -o expr.pd_linux $(LINUXOBJ) -lc -lm
+	strip --strip-unneeded expr.pd_linux
+
+expr~.pd_linux: expr.pd_linux
+	-ln -s expr.pd_linux expr~.pd_linux
+
+fexpr~.pd_linux: expr.pd_linux
+	-ln -s expr.pd_linux fexpr~.pd_linux
+
+../expr.pd_linux: expr.pd_linux
+	-ln -s expr~/expr.pd_linux ../expr.pd_linux
+
+../expr~.pd_linux: expr.pd_linux
+	-ln -s expr~/expr.pd_linux ../expr~.pd_linux
+
+../fexpr~.pd_linux: expr.pd_linux
+	-ln -s expr~/expr.pd_linux ../fexpr~.pd_linux
+
+install_linux:
+	install expr.pd_linux $(PDEXTERN)
+	rm -f $(PDEXTERN)/expr~.pd_linux
+	rm -f $(PDEXTERN)/fexpr~.pd_linux
+	cd $(PDEXTERN); \
+	-ln -s expr.pd_linux expr~.pd_linux
+	-ln -s expr.pd_linux fexpr~.pd_linux
+
+
+linux_clean:
+	rm -f *.pd_linux_o *.o
+
+# ----------------------- MAC OSX -----------------------
+
+MACOSXOBJ3 =  vexp.d_ppc_o vexp_fun.d_ppc_o vexp_if.d_ppc_o
+MACOSXOBJ =  vexp.d_fat_o vexp_fun.d_fat_o vexp_if.d_fat_o
+.SUFFIXES: .d_ppc_o .d_fat_o
+
+MACOSXCFLAGS = -DMACOSX -DPD -O2 -Wall -W -Wshadow -Wstrict-prototypes \
+    -Wno-unused -Wno-parentheses -Wno-switch 
+
+MACOSXINCLUDE =  -I../../src
+
+d_ppc: expr.d_ppc expr~.d_ppc fexpr~.d_ppc
+.c.d_ppc_o:
+	$(CC) -g $(MACOSXCFLAGS) $(MACOSXINCLUDE) -o $*.d_ppc_o -c $*.c
+
+expr.d_ppc: $(MACOSXOBJ3)
+	$(CC) -bundle -undefined suppress  -flat_namespace \
+		-o expr.d_ppc $(MACOSXOBJ3)  -lm
+	rm -f ../expr.d_ppc
+	-ln -s expr~/expr.d_ppc ..
+
+expr~.d_ppc: expr.d_ppc
+	-ln -s expr.d_ppc expr~.d_ppc
+	rm -f ../expr~.d_ppc
+	-ln -s expr~/expr~.d_ppc ..
+
+fexpr~.d_ppc: expr.d_ppc
+	-ln -s expr.d_ppc fexpr~.d_ppc
+	rm -f ../fexpr~.d_ppc
+	-ln -s expr~/fexpr~.d_ppc ..
+
+install_d_fat:
+	install expr.d_fat $(PDEXTERN)
+	rm -f $(PDEXTERN)/expr~.d_fat
+	rm -f $(PDEXTERN)/fexpr~.d_fat
+	cd $(PDEXTERN); \
+	-ln -s expr.d_fat expr~.d_fat; \
+	-ln -s expr.d_fat fexpr~.d_fat
+
+d_fat: expr.d_fat expr~.d_fat fexpr~.d_fat
+.c.d_fat_o:
+	$(CC) -g $(MACOSXCFLAGS) $(MACOSXINCLUDE)  -arch i386 -arch ppc \
+	-o $*.d_fat_o -c $*.c
+
+expr.d_fat: $(MACOSXOBJ)
+	$(CC) -arch i386 -arch ppc -bundle -undefined suppress  -flat_namespace \
+		-o expr.d_fat $(MACOSXOBJ)  -lm
+	rm -f ../expr.d_fat
+	-ln -s expr~/expr.d_fat ..
+
+expr~.d_fat: expr.d_fat
+	-ln -s expr.d_fat expr~.d_fat
+	rm -f ../expr~.d_fat
+	-ln -s expr~/expr~.d_fat ..
+
+fexpr~.d_fat: expr.d_fat
+	-ln -s expr.d_fat fexpr~.d_fat
+	rm -f ../fexpr~.d_fat
+	-ln -s expr~/fexpr~.d_fat ..
+
+install_d_ppc:
+	install expr.d_ppc $(PDEXTERN)
+	rm -f $(PDEXTERN)/expr~.d_ppc
+	rm -f $(PDEXTERN)/fexpr~.d_ppc
+	cd $(PDEXTERN); \
+	-ln -s expr.d_ppc expr~.d_ppc; \
+	-ln -s expr.d_ppc fexpr~.d_ppc
+
+clean_d_ppc:
+	rm -f *.d_ppc_o *.o
+
diff --git a/extra/expr~/vexp.c b/extra/expr~/vexp.c
new file mode 100644
index 0000000000000000000000000000000000000000..732944deba515452b0ebfbc8bd81524cce48e9c9
--- /dev/null
+++ b/extra/expr~/vexp.c
@@ -0,0 +1,2142 @@
+/*
+ * jMax
+ * Copyright (C) 1994, 1995, 1998, 1999 by IRCAM-Centre Georges Pompidou, Paris, France.
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * See file LICENSE for further informations on licensing terms.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * 
+ * Based on Max/ISPW by Miller Puckette.
+ *
+ * Authors: Maurizio De Cecco, Francois Dechelle, Enzo Maggi, Norbert Schnell.
+ *
+ */
+
+/* "expr" was written by Shahrokh Yadegari c. 1989. -msp */
+/* "expr~" and "fexpr~" conversion by Shahrokh Yadegari c. 1999,2000 */
+
+/*
+ * Feb 2002 -   added access to variables
+ *              multiple expression support
+ *              new short hand forms for fexpr~
+ *                      now $y or $y1 = $y1[-1] and $y2 = $y2[-1]
+ *              --sdy
+ *
+ * July 2002
+ *              fixed bugs introduced in last changes in store and ET_EQ
+ *              --sdy
+ *              
+ */
+
+/*
+ * vexp.c -- a variable expression evaluator
+ *
+ * This modules implements an expression evaluator using the
+ * operator-precedence parsing.  It transforms an infix expression
+ * to a prefix stack ready to be evaluated.  The expression sysntax
+ * is close to that of C.  There are a few operators that are not
+ * supported and functions are also recognized.  Strings can be
+ * passed to functions when they are quoted in '"'s. "[]" are implememted
+ * as an easy way of accessing the content of tables, and the syntax
+ * table_name[index].
+ * Variables (inlets) are specified with the following syntax: $x#,
+ * where x is either i(integers), f(floats), and s(strings); and #
+ * is a digit that coresponds to the inlet number.  The string variables
+ * can be used as strings when they are quoted and can also be used as
+ * table names when they are followed by "[]".
+ *
+ * signal vectors have been added to this implementation:
+ * $v# denotes a signal vector
+ * $x#[index]  is the value of a sample at the index of a the signal vector
+ * $x# is the shorthand for $x#[0]
+ * $y[index]   is the value of the sample output at the index of a the
+ *             signal output
+ * "index" for $x#[index] has to have this range (0 <= index < vectorsize)
+ * "index" for $y[index]  has to have this range (0 <  index < vectorsize)
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include "vexp.h" 
+#ifdef MSP
+#undef isdigit
+#define isdigit(x)      (x >= '0' && x <= '9')
+#endif
+
+char *atoif(char *s, long int *value, long int *type);
+
+static struct ex_ex *ex_lex(struct expr *expr, long int *n);
+struct ex_ex *ex_match(struct ex_ex *eptr, long int op);
+struct ex_ex *ex_parse(struct expr *expr, struct ex_ex *iptr,
+                                        struct ex_ex *optr, long int *argc);
+struct ex_ex *ex_eval(struct expr *expr, struct ex_ex *eptr,
+                                                struct ex_ex *optr, int i);
+
+int expr_donew(struct expr *exprr, int ac, t_atom *av);
+struct ex_ex *eval_func(struct expr *expr,struct ex_ex *eptr,
+                                                struct ex_ex *optr, int i);
+struct ex_ex *eval_tab(struct expr *expr, struct ex_ex *eptr,
+                                                struct ex_ex *optr, int i);
+struct ex_ex *eval_var(struct expr *expr, struct ex_ex *eptr,
+                                                struct ex_ex *optr, int i);
+struct ex_ex *eval_store(struct expr *expr, struct ex_ex *eptr,
+                                                struct ex_ex *optr, int i);
+struct ex_ex *eval_sigidx(struct expr *expr, struct ex_ex *eptr,
+                                                struct ex_ex *optr, int i);
+static int cal_sigidx(struct ex_ex *optr,       /* The output value */
+           int i, float rem_i,      /* integer and fractinal part of index */
+           int idx,                  /* index of current fexpr~ processing */
+           int vsize,                                       /* vector size */
+           float *curvec, float *prevec);   /* current and previous table */
+t_ex_func *find_func(char *s);
+void ex_dzdetect(struct expr *expr);
+
+#define MAX_ARGS        10
+extern t_ex_func ex_funcs[];
+
+struct ex_ex nullex;
+
+void set_tokens (char *s);
+int getoken (struct expr *expr, struct ex_ex *eptr);
+void ex_print (struct ex_ex *eptr);
+#ifdef MSP
+void atom_string(t_atom *a, char *buf, unsigned int bufsize);
+
+void atom_string(t_atom *a, char *buf, unsigned int bufsize)
+{
+    char tbuf[30];
+    switch(a->a_type)
+    {
+    case A_SEMI: strcpy(buf, ";"); break;
+    case A_COMMA: strcpy(buf, ","); break;
+#ifdef PD
+    case A_POINTER:
+        strcpy(buf, "(pointer)");
+        break;
+#endif
+    case A_FLOAT:
+        sprintf(tbuf, "%g", a->a_w.w_float);
+        if (strlen(tbuf) < bufsize-1) strcpy(buf, tbuf);
+        else if (a->a_w.w_float < 0) strcpy(buf, "-");
+        else  strcat(buf, "+");
+        break;
+    case A_LONG:
+        sprintf(tbuf, "%d", a->a_w.w_long);
+        if (strlen(tbuf) < bufsize-1) strcpy(buf, tbuf);
+        else if (a->a_w.w_float < 0) strcpy(buf, "-");
+        else  strcat(buf, "+");
+        break;
+    case A_SYMBOL:
+    {   
+        char *sp;       
+        unsigned int len;
+        int quote;
+        for (sp = a->a_w.w_symbol->s_name, len = 0, quote = 0; *sp; sp++, len++)
+            if (*sp == ';' || *sp == ',' || *sp == '\\' ||
+                (*sp == '$' && sp == a->a_w.w_symbol->s_name && sp[1] >= '0'
+                    && sp[1] <= '9'))
+                quote = 1;
+        if (quote)
+        {
+            char *bp = buf, *ep = buf + (bufsize-2);
+            sp = a->a_w.w_symbol->s_name;
+            while (bp < ep && *sp)
+            {
+                if (*sp == ';' || *sp == ',' || *sp == '\\' ||
+                    (*sp == '$' && bp == buf && sp[1] >= '0' && sp[1] <= '9'))
+                        *bp++ = '\\';
+                *bp++ = *sp++;
+            }
+            if (*sp) *bp++ = '*';
+            *bp = 0;
+            /* post("quote %s -> %s", a->a_w.w_symbol->s_name, buf); */
+        }
+        else
+        {
+            if (len < bufsize-1) strcpy(buf, a->a_w.w_symbol->s_name);
+            else
+            {
+                strncpy(buf, a->a_w.w_symbol->s_name, bufsize - 2);
+                strcpy(buf + (bufsize - 2), "*");
+            }
+        }
+    }
+        break;
+#ifdef PD
+    case A_DOLLAR:
+        sprintf(buf, "$%d", a->a_w.w_index);
+        break;
+    case A_DOLLSYM:
+        sprintf(buf, "$%s", a->a_w.w_symbol->s_name);
+                break;
+#else /* MAX */
+ case A_DOLLAR:
+        sprintf(buf, "$%s", a->a_w.w_symbol->s_name);
+        break;
+#endif
+    default:
+        post("atom_string bug");
+    }
+}
+#endif /* MSP */
+/*
+ * expr_donew -- create a new "expr" object.  
+ *           returns 1 on failure, 0 on success.
+ */ 
+int
+expr_donew(struct expr *expr, int ac, t_atom *av)
+{
+        struct ex_ex *list;
+        struct ex_ex *ret;
+        long max_node = 0;              /* maximum number of nodes needed */
+        char *exp_string;
+        int exp_strlen;
+        t_binbuf *b;
+        int i;
+
+        memset(expr->exp_var, 0, MAX_VARS * sizeof (*expr->exp_var));
+#ifdef PD
+        b = binbuf_new();
+        binbuf_add(b, ac, av);
+        binbuf_gettext(b, &exp_string, &exp_strlen);
+
+#else /* MSP */
+ {
+    char *buf = getbytes(0), *newbuf;
+    int length = 0;
+    char string[250];
+    t_atom *ap;
+    int indx;
+
+    for (ap = av, indx = 0; indx < ac; indx++, ap = ++av) {
+        int newlength;
+        if ((ap->a_type == A_SEMI || ap->a_type == A_COMMA) &&
+                length && buf[length-1] == ' ') length--;
+        atom_string(ap, string, 250);
+        newlength = length + strlen(string) + 1;
+        if (!(newbuf = t_resizebytes(buf, length, newlength))) break;
+        buf = newbuf;
+        strcpy(buf + length, string);
+        length = newlength;
+        if (ap->a_type == A_SEMI) buf[length-1] = '\n';
+        else buf[length-1] = ' ';
+    }
+
+    if (length && buf[length-1] == ' ') {
+        if (newbuf = t_resizebytes(buf, length, length-1))
+        {
+            buf = newbuf;
+            length--;
+        }
+    }
+    exp_string = buf;
+    exp_strlen  = length;
+ }
+#endif
+        exp_string = (char *)t_resizebytes(exp_string, exp_strlen,exp_strlen+1);
+        exp_string[exp_strlen] = 0;
+        expr->exp_string = exp_string;
+        expr->exp_str = exp_string;
+        expr->exp_nexpr = 0;
+        ret = (struct ex_ex *) 0;
+        /*
+         * if ret == 0 it means that we have no expression
+         * so we let the pass go through to build a single null stack
+         */
+        while (*expr->exp_str || !ret) {
+                list = ex_lex(expr, &max_node);
+                if (!list) {            /* syntax error */
+                        goto error;
+                }
+                expr->exp_stack[expr->exp_nexpr] =
+                  (struct ex_ex *)fts_malloc(max_node * sizeof (struct ex_ex));
+                expr->exp_nexpr++;
+                ret = ex_match(list, (long)0);
+                if (!ret)               /* syntax error */
+                        goto error;
+                ret = ex_parse(expr,
+                        list, expr->exp_stack[expr->exp_nexpr - 1], (long *)0);
+                if (!ret)
+                        goto error;
+        }
+        *ret = nullex;
+        t_freebytes(exp_string, exp_strlen+1);
+        return (0);
+error:
+        for (i = 0; i < expr->exp_nexpr; i++) {
+                fts_free(expr->exp_stack[i]);
+                expr->exp_stack[i] = 0;
+        }
+        expr->exp_nexpr = 0;
+        if (list)
+                fts_free(list);
+        t_freebytes(exp_string, exp_strlen+1);
+        return (1);
+}
+
+/*
+ * ex_lex -- This routine is a bit more than a lexical parser since it will
+ *           also do some syntax checking.  It reads the string s and will
+ *           return a linked list of struct ex_ex. 
+ *           It will also put the number of the nodes in *n.
+ */
+struct ex_ex *
+ex_lex(struct expr *expr, long int *n)
+{
+        struct ex_ex *list_arr;
+        struct ex_ex *exptr;
+        long non = 0;           /* number of nodes */
+        long maxnode = 0;
+
+        list_arr = (struct ex_ex *)fts_malloc(sizeof (struct ex_ex) * MINODES);
+        if (! list_arr) {
+                post("ex_lex: no mem\n");
+                return ((struct ex_ex *)0);
+        }
+        exptr = list_arr;
+        maxnode = MINODES;
+
+        while (8)
+        {
+                if (non >= maxnode) {
+                        maxnode += MINODES;
+
+                        list_arr = fts_realloc((void *)list_arr,
+                                        sizeof (struct ex_ex) * maxnode);
+                        if (!list_arr) {
+                                post("ex_lex: no mem\n");
+                                return ((struct ex_ex *)0);
+                        }
+                        exptr = &(list_arr)[non];
+                }
+
+                if (getoken(expr, exptr)) {
+                        fts_free(list_arr);
+                        return ((struct ex_ex *)0);
+                }
+                non++;
+
+                if (!exptr->ex_type)
+                        break;
+
+                exptr++;
+        }
+        *n = non;
+
+        return list_arr;
+}
+
+/*
+ * ex_match -- this routine walks through the eptr and matches the
+ *             perentheses and brackets, it also converts the function
+ *             names to a pointer to the describing structure of the 
+ *             specified function
+ */
+/* operator to match */
+struct ex_ex *
+ex_match(struct ex_ex *eptr, long int op)
+{
+        int firstone = 1;
+        struct ex_ex *ret;
+        t_ex_func *fun;
+
+        for (; 8; eptr++, firstone = 0) {
+                switch (eptr->ex_type) {
+                case 0:
+                        if (!op)
+                                return (eptr);
+                        post("expr syntax error: an open %s not matched\n",
+                            op == OP_RP ? "parenthesis" : "bracket");
+                        return (exNULL);
+                case ET_INT:
+                case ET_FLT:
+                case ET_II:
+                case ET_FI:
+                case ET_SI:
+                case ET_VI:
+                case ET_SYM:
+                case ET_VSYM:
+                        continue;
+                case ET_YO:
+                        if (eptr[1].ex_type != ET_OP || eptr[1].ex_op != OP_LB)
+                                eptr->ex_type = ET_YOM1;
+                        continue;
+                case ET_XI:
+                        if (eptr[1].ex_type != ET_OP || eptr[1].ex_op != OP_LB)
+                                eptr->ex_type = ET_XI0;
+                        continue;
+                case ET_TBL:
+                case ET_FUNC:
+                case ET_LP:
+                        /* CHANGE
+                case ET_RP:
+                        */
+                case ET_LB:
+                        /* CHANGE
+                case ET_RB:
+                         */
+                        post("ex_match: unexpected type, %ld\n", eptr->ex_type);
+                        return (exNULL);
+                case ET_OP:
+                        if (op == eptr->ex_op)
+                                return (eptr);
+                        /*
+                         * if we are looking for a right peranthesis
+                         * or a right bracket and find the other kind,
+                         * it has to be a syntax error
+                         */
+                        if ((eptr->ex_op == OP_RP && op == OP_RB) ||
+                            (eptr->ex_op == OP_RB && op == OP_RP)) {
+                                post("expr syntax error: prenthesis or brackets not matched\n");
+                                return (exNULL);
+                        }
+                        /*
+                         * Up to now we have marked the unary minuses as
+                         * subrtacts.  Any minus that is the first one in
+                         * chain or is preceeded by anything except ')' and
+                         * ']' is a unary minus.
+                         */
+                        if (eptr->ex_op == OP_SUB) {
+                                ret = eptr - 1;
+                                if (firstone ||  (ret->ex_type == ET_OP &&
+                                    ret->ex_op != OP_RB && ret->ex_op != OP_RP))
+                                        eptr->ex_op = OP_UMINUS;
+                        } else if (eptr->ex_op == OP_LP) {
+                                ret = ex_match(eptr + 1, OP_RP);
+                                if (!ret)
+                                        return (ret);
+                                eptr->ex_type = ET_LP;
+                                eptr->ex_ptr = (char *) ret;
+                                eptr = ret;
+                        } else if (eptr->ex_op == OP_LB) {
+                                ret = ex_match(eptr + 1, OP_RB);
+                                if (!ret)
+                                        return (ret);
+                                eptr->ex_type = ET_LB;
+                                eptr->ex_ptr = (char *) ret;
+                                eptr = ret;
+                        }
+                        continue;
+                case ET_STR:
+                        if (eptr[1].ex_op == OP_LB) {
+                                char *tmp;
+
+                                eptr->ex_type = ET_TBL;
+                                tmp = eptr->ex_ptr;
+                                if (ex_getsym(tmp, (t_symbol **)&(eptr->ex_ptr))) {
+                                        post("expr: syntax error: problms with ex_getsym\n");
+                                        return (exNULL);
+                                }
+                                fts_free((void *)tmp);
+                        } else if (eptr[1].ex_op == OP_LP) {
+                                fun = find_func(eptr->ex_ptr);
+                                if (!fun) {
+                                        post(
+                                         "expr: error: function %s not found\n",
+                                                                eptr->ex_ptr);
+                                        return (exNULL);
+                                }
+                                eptr->ex_type = ET_FUNC;
+                                eptr->ex_ptr = (char *) fun;
+                        } else {
+                                char *tmp;
+
+                                if (eptr[1].ex_type && eptr[1].ex_type!=ET_OP){
+                                        post("expr: syntax error: bad string '%s'\n", eptr->ex_ptr);
+                                        return (exNULL);
+                                }
+                                /* it is a variable */
+                                eptr->ex_type = ET_VAR;
+                                tmp = eptr->ex_ptr;
+                                if (ex_getsym(tmp,
+                                                (t_symbol **)&(eptr->ex_ptr))) {
+                                        post("expr: variable '%s' not found",tmp);
+                                        return (exNULL);
+                                }
+                        }
+                        continue;
+                default:
+                        post("ex_match: bad type\n");
+                        return (exNULL);
+                }
+        }
+        /* NOTREACHED */
+}
+
+/*
+ * ex_parse -- This function if called when we have already done some
+ *             parsing on the expression, and we have already matched
+ *             our brackets and parenthesis.  The main job of this
+ *             function is to convert the infix expression to the
+ *             prefix form. 
+ *             First we find the operator with the lowest precedence and
+ *             put it on the stack ('optr', it is really just an array), then
+ *             we call ourself (ex_parse()), on its arguments (unary operators
+ *             only have one operator.)  
+ *             When "argc" is set it means that we are parsing the arguments
+ *             of a function and we will increment *argc anytime we find
+ *             a a segment that can qualify as an argument (counting commas).
+ *
+ *             returns 0 on syntax error
+ */
+/* number of argument separated by comma */
+struct ex_ex *
+ex_parse(struct expr *x, struct ex_ex *iptr, struct ex_ex *optr, long int *argc)
+{
+        struct ex_ex *eptr;
+        struct ex_ex *lowpre = 0;       /* pointer to the lowest precedence */
+        struct ex_ex savex;
+        long pre = HI_PRE;
+        long count;
+
+        if (!iptr) {
+                post("ex_parse: input is null, iptr = 0x%lx\n", iptr);
+                return (exNULL);
+        }
+        if (!iptr->ex_type)
+                return (exNULL);
+
+        /*
+         * the following loop finds the lowest precedence operator in the
+         * the input token list, comma is explicitly checked here since
+         * that is a special operator and is only legal in functions
+         */
+        for (eptr = iptr, count = 0; eptr->ex_type; eptr++, count++)
+                switch (eptr->ex_type) {
+                case ET_SYM:
+                case ET_VSYM:
+                        if (!argc) {
+                                post("expr: syntax error: symbols allowed for functions only\n");
+                                ex_print(eptr);
+                                return (exNULL);
+                        }
+                case ET_INT:
+                case ET_FLT:
+                case ET_II:
+                case ET_FI:
+                case ET_XI0:
+                case ET_YOM1:
+                case ET_VI:
+                case ET_VAR:
+                        if (!count && !eptr[1].ex_type) {
+                                *optr++ = *eptr;
+                                return (optr);
+                        }
+                        break;
+                case ET_XI:
+                case ET_YO:
+                case ET_SI:
+                case ET_TBL:
+                        if (eptr[1].ex_type != ET_LB) {
+                                post("expr: syntax error: brackets missing\n");
+                                ex_print(eptr);
+                                return (exNULL);
+                        }
+                        /* if this table is the only token, parse the table */
+                        if (!count &&
+                            !((struct ex_ex *) eptr[1].ex_ptr)[1].ex_type) {
+                                savex = *((struct ex_ex *) eptr[1].ex_ptr);
+                                *((struct ex_ex *) eptr[1].ex_ptr) = nullex;
+                                *optr++ = *eptr;
+                                lowpre = ex_parse(x, &eptr[2], optr, (long *)0);
+                                *((struct ex_ex *) eptr[1].ex_ptr) = savex;
+                                return(lowpre);
+                        }
+                        eptr = (struct ex_ex *) eptr[1].ex_ptr;
+                        break;
+                case ET_OP:
+                        if (eptr->ex_op == OP_COMMA) {
+                                if (!argc || !count || !eptr[1].ex_type) {
+                                        post("expr: syntax error: illegal comma\n");
+                                        ex_print(eptr[1].ex_type ? eptr : iptr);
+                                        return (exNULL);
+                                }
+                        }
+                        if (!eptr[1].ex_type) {
+                                post("expr: syntax error: missing operand\n");
+                                ex_print(iptr);
+                                return (exNULL);
+                        }
+                        if ((eptr->ex_op & PRE_MASK) <= pre) {
+                                pre = eptr->ex_op & PRE_MASK;
+                                lowpre = eptr;
+                        }
+                        break;
+                case ET_FUNC:
+                        if (eptr[1].ex_type != ET_LP) {
+                                post("expr: ex_parse: no parenthesis\n");
+                                return (exNULL);
+                        }
+                        /* if this function is the only token, parse it */
+                        if (!count &&
+                            !((struct ex_ex *) eptr[1].ex_ptr)[1].ex_type) {
+                                long ac;
+
+                                if (eptr[1].ex_ptr == (char *) &eptr[2]) {
+                                        post("expr: syntax error: missing argument\n");
+                                        ex_print(eptr);
+                                        return (exNULL);
+                                }
+                                ac = 0;
+                                savex = *((struct ex_ex *) eptr[1].ex_ptr);
+                                *((struct ex_ex *) eptr[1].ex_ptr) = nullex;
+                                *optr++ = *eptr;
+                                lowpre = ex_parse(x, &eptr[2], optr, &ac);
+                                if (!lowpre)
+                                        return (exNULL);
+                                ac++;
+                                if (ac !=
+                                    ((t_ex_func *)eptr->ex_ptr)->f_argc){
+                                        post("expr: syntax error: function '%s' needs %ld arguments\n",
+                                            ((t_ex_func *)eptr->ex_ptr)->f_name,
+                                            ((t_ex_func *)eptr->ex_ptr)->f_argc);
+                                        return (exNULL);
+                                }
+                                *((struct ex_ex *) eptr[1].ex_ptr) = savex;
+                                return (lowpre);
+                        }
+                        eptr = (struct ex_ex *) eptr[1].ex_ptr;
+                        break;
+                case ET_LP:
+                case ET_LB:
+                        if (!count &&
+                            !((struct ex_ex *) eptr->ex_ptr)[1].ex_type) {
+                                if (eptr->ex_ptr == (char *)(&eptr[1])) {
+                                        post("expr: syntax error: empty '%s'\n",
+                                            eptr->ex_type==ET_LP?"()":"[]");
+                                        ex_print(eptr);
+                                        return (exNULL);
+                                }
+                                savex = *((struct ex_ex *) eptr->ex_ptr);
+                                *((struct ex_ex *) eptr->ex_ptr) = nullex;
+                                lowpre = ex_parse(x, &eptr[1], optr, (long *)0);
+                                *((struct ex_ex *) eptr->ex_ptr) = savex;
+                                return (lowpre);
+                        }
+                        eptr = (struct ex_ex *)eptr->ex_ptr;
+                        break;
+                case ET_STR:
+                default:
+                        ex_print(eptr);
+                        post("expr: ex_parse: type = 0x%lx\n", eptr->ex_type);
+                        return (exNULL);
+                }
+
+        if (pre == HI_PRE) {
+                post("expr: syntax error: missing operation\n");
+                ex_print(iptr);
+                return (exNULL);
+        }
+        if (count < 2) {
+                post("expr: syntax error: mission operand\n");
+                ex_print(iptr);
+                return (exNULL);
+        }
+        if (count == 2) {
+                if (lowpre != iptr) {
+                        post("expr: ex_parse: unary operator should be first\n");
+                        return (exNULL);
+                }
+                if (!unary_op(lowpre->ex_op)) {
+                        post("expr: syntax error: not a uniary operator\n");
+                        ex_print(iptr);
+                        return (exNULL);
+                }
+                *optr++ = *lowpre;
+                eptr = ex_parse(x, &lowpre[1], optr, argc);
+                return (eptr);
+        }
+        if (lowpre == iptr) {
+                post("expr: syntax error: mission operand\n");
+                ex_print(iptr);
+                return (exNULL);
+        }
+        savex = *lowpre;
+        *lowpre = nullex;
+        if (savex.ex_op != OP_COMMA)
+                *optr++ = savex;
+        else
+                (*argc)++;
+        eptr = ex_parse(x, iptr, optr, argc);
+        if (eptr) {
+                eptr = ex_parse(x, &lowpre[1], eptr, argc);
+                *lowpre = savex;
+        }
+        return (eptr);
+}
+
+/*
+ * this is the devide zero check for a a non devide operator
+ */
+#define DZC(ARG1,OPR,ARG2)      (ARG1 OPR ARG2)
+
+#define EVAL(OPR);                                                      \
+eptr = ex_eval(expr, ex_eval(expr, eptr, &left, idx), &right, idx);     \
+switch (left.ex_type) {                                                 \
+case ET_INT:                                                            \
+        switch(right.ex_type) {                                         \
+        case ET_INT:                                                    \
+                if (optr->ex_type == ET_VEC) {                          \
+                        op = optr->ex_vec;                              \
+                        scalar = (float)DZC(left.ex_int, OPR, right.ex_int); \
+                        for (j = 0; j < expr->exp_vsize; j++)           \
+                                *op++ = scalar;                         \
+                } else {                                                \
+                        optr->ex_type = ET_INT;                         \
+                        optr->ex_int = DZC(left.ex_int, OPR, right.ex_int); \
+                }                                                       \
+                break;                                                  \
+        case ET_FLT:                                                    \
+                if (optr->ex_type == ET_VEC) {                          \
+                        op = optr->ex_vec;                              \
+                        scalar = DZC(((float)left.ex_int), OPR, right.ex_flt);\
+                        for (j = 0; j < expr->exp_vsize; j++)           \
+                                *op++ = scalar;                         \
+                } else {                                                \
+                        optr->ex_type = ET_FLT;                         \
+                        optr->ex_flt = DZC(((float)left.ex_int), OPR,   \
+                                                        right.ex_flt);  \
+                }                                                       \
+                break;                                                  \
+        case ET_VEC:                                                    \
+        case ET_VI:                                                     \
+                if (optr->ex_type != ET_VEC) {                          \
+                        if (optr->ex_type == ET_VI) {                   \
+                                post("expr~: Int. error %d", __LINE__); \
+                                abort();                                \
+                        }                                               \
+                        optr->ex_type = ET_VEC;                         \
+                        optr->ex_vec = (t_float *)                      \
+                          fts_malloc(sizeof (t_float)*expr->exp_vsize); \
+                }                                                       \
+                scalar = left.ex_int;                                   \
+                rp = right.ex_vec;                                      \
+                op = optr->ex_vec;                                      \
+                for (i = 0; i < expr->exp_vsize; i++) {                 \
+                        *op++ = DZC (scalar, OPR, *rp);                 \
+                        rp++;                                           \
+                }                                                       \
+                break;                                                  \
+        case ET_SYM:                                                    \
+        default:                                                        \
+                post_error((fts_object_t *) expr,                       \
+                      "expr: ex_eval(%d): bad right type %ld\n",        \
+                                              __LINE__, right.ex_type); \
+                nullret = 1;                                            \
+        }                                                               \
+        break;                                                          \
+case ET_FLT:                                                            \
+        switch(right.ex_type) {                                         \
+        case ET_INT:                                                    \
+                if (optr->ex_type == ET_VEC) {                          \
+                        op = optr->ex_vec;                              \
+                        scalar = DZC((float) left.ex_flt, OPR, right.ex_int); \
+                        for (j = 0; j < expr->exp_vsize; j++)           \
+                                *op++ = scalar;                         \
+                } else {                                                \
+                        optr->ex_type = ET_FLT;                         \
+                        optr->ex_flt = DZC(left.ex_flt, OPR, right.ex_int); \
+                }                                                       \
+                break;                                                  \
+        case ET_FLT:                                                    \
+                if (optr->ex_type == ET_VEC) {                          \
+                        op = optr->ex_vec;                              \
+                        scalar = DZC(left.ex_flt, OPR, right.ex_flt);   \
+                        for (j = 0; j < expr->exp_vsize; j++)           \
+                                *op++ = scalar;                         \
+                } else {                                                \
+                        optr->ex_type = ET_FLT;                         \
+                        optr->ex_flt= DZC(left.ex_flt, OPR, right.ex_flt); \
+                }                                                       \
+                break;                                                  \
+        case ET_VEC:                                                    \
+        case ET_VI:                                                     \
+                if (optr->ex_type != ET_VEC) {                          \
+                        if (optr->ex_type == ET_VI) {                   \
+                                post("expr~: Int. error %d", __LINE__); \
+                                abort();                                \
+                        }                                               \
+                        optr->ex_type = ET_VEC;                         \
+                        optr->ex_vec = (t_float *)                      \
+                          fts_malloc(sizeof (t_float)*expr->exp_vsize); \
+                }                                                       \
+                scalar = left.ex_flt;                                   \
+                rp = right.ex_vec;                                      \
+                op = optr->ex_vec;                                      \
+                for (i = 0; i < expr->exp_vsize; i++) {                 \
+                        *op++ = DZC(scalar, OPR, *rp);                  \
+                        rp++;                                           \
+                }                                                       \
+                break;                                                  \
+        case ET_SYM:                                                    \
+        default:                                                        \
+                post_error((fts_object_t *) expr,                       \
+                      "expr: ex_eval(%d): bad right type %ld\n",        \
+                                              __LINE__, right.ex_type); \
+                nullret = 1;                                            \
+        }                                                               \
+        break;                                                          \
+case ET_VEC:                                                            \
+case ET_VI:                                                             \
+        if (optr->ex_type != ET_VEC) {                                  \
+                if (optr->ex_type == ET_VI) {                           \
+                        post("expr~: Int. error %d", __LINE__);         \
+                        abort();                                        \
+                }                                                       \
+                optr->ex_type = ET_VEC;                                 \
+                optr->ex_vec = (t_float *)                              \
+                  fts_malloc(sizeof (t_float)*expr->exp_vsize);         \
+        }                                                               \
+        op = optr->ex_vec;                                              \
+        lp = left.ex_vec;                                               \
+        switch(right.ex_type) {                                         \
+        case ET_INT:                                                    \
+                scalar = right.ex_int;                                  \
+                for (i = 0; i < expr->exp_vsize; i++) {                 \
+                        *op++ = DZC(*lp, OPR, scalar);                  \
+                        lp++;                                           \
+                }                                                       \
+                break;                                                  \
+        case ET_FLT:                                                    \
+                scalar = right.ex_flt;                                  \
+                for (i = 0; i < expr->exp_vsize; i++) {                 \
+                        *op++ = DZC(*lp, OPR, scalar);                  \
+                        lp++;                                           \
+                }                                                       \
+                break;                                                  \
+        case ET_VEC:                                                    \
+        case ET_VI:                                                     \
+                rp = right.ex_vec;                                      \
+                for (i = 0; i < expr->exp_vsize; i++) {                 \
+                        /*                                              \
+                         * on a RISC processor one could copy           \
+                         * 8 times in each round to get a considerable  \
+                         * improvement                                  \
+                         */                                             \
+                        *op++ = DZC(*lp, OPR, *rp);                     \
+                        rp++; lp++;                                     \
+                }                                                       \
+                break;                                                  \
+        case ET_SYM:                                                    \
+        default:                                                        \
+                post_error((fts_object_t *) expr,                       \
+                      "expr: ex_eval(%d): bad right type %ld\n",        \
+                                              __LINE__, right.ex_type); \
+                nullret = 1;                                            \
+        }                                                               \
+        break;                                                          \
+case ET_SYM:                                                            \
+default:                                                                \
+                post_error((fts_object_t *) expr,                       \
+                      "expr: ex_eval(%d): bad left type %ld\n",         \
+                                              __LINE__, left.ex_type);  \
+}                                                                       \
+break;
+
+/*
+ * evaluate a unary operator, TYPE is applied to float operands
+ */
+#define EVAL_UNARY(OPR, TYPE)                                           \
+        eptr = ex_eval(expr, eptr, &left, idx);                         \
+        switch(left.ex_type) {                                          \
+        case ET_INT:                                                    \
+                if (optr->ex_type == ET_VEC) {                          \
+                        ex_mkvector(optr->ex_vec,(float)(OPR left.ex_int),\
+                                                        expr->exp_vsize);\
+                        break;                                          \
+                }                                                       \
+                optr->ex_type = ET_INT;                                 \
+                optr->ex_int = OPR left.ex_int;                         \
+                break;                                                  \
+        case ET_FLT:                                                    \
+                if (optr->ex_type == ET_VEC) {                          \
+                        ex_mkvector(optr->ex_vec, OPR (TYPE left.ex_flt),\
+                                                        expr->exp_vsize);\
+                        break;                                          \
+                }                                                       \
+                optr->ex_type = ET_FLT;                                 \
+                optr->ex_flt = OPR (TYPE left.ex_flt);                  \
+                break;                                                  \
+        case ET_VI:                                                     \
+        case ET_VEC:                                                    \
+                j = expr->exp_vsize;                                    \
+                if (optr->ex_type != ET_VEC) {                          \
+                        optr->ex_type = ET_VEC;                         \
+                        optr->ex_vec = (t_float *)                      \
+                          fts_malloc(sizeof (t_float)*expr->exp_vsize); \
+                }                                                       \
+                op = optr->ex_vec;                                      \
+                lp = left.ex_vec;                                       \
+                j = expr->exp_vsize;                                    \
+                for (i = 0; i < j; i++)                                 \
+                        *op++ = OPR (TYPE *lp++);                       \
+                break;                                                  \
+        default:                                                        \
+                post_error((fts_object_t *) expr,                       \
+                        "expr: ex_eval(%d): bad left type %ld\n",       \
+                                              __LINE__, left.ex_type);  \
+                nullret++;                                              \
+        }                                                               \
+        break;
+
+void
+ex_mkvector(t_float *fp, t_float x, int size)
+{
+        while (size--)
+                *fp++ = x;
+}
+
+/*
+ * ex_dzdetect -- divide by zero detected
+ */
+void
+ex_dzdetect(struct expr *expr)
+{
+        char *etype;
+
+        if (!expr->exp_error & EE_DZ) {
+                if (IS_EXPR(expr))
+                        etype = "expr";
+                else if (IS_EXPR_TILDE(expr))
+                        etype = "expr~";
+                else if (IS_FEXPR_TILDE(expr))
+                        etype = "fexpr~";
+                else {
+                        post ("expr -- ex_dzdetect internal error");
+                        etype = "";
+                }
+                post ("%s divide by zero detected", etype);
+                expr->exp_error |= EE_DZ;
+        }
+}
+                
+
+/*
+ * ex_eval -- evaluate the array of prefix expression
+ *            ex_eval returns the pointer to the first unevaluated node
+ *            in the array.  This is a recursive routine.
+ */
+
+/* SDY
+all the returns in this function need to be changed so that the code
+ends up at the end to check for newly allocated right and left vectors which
+need to be freed
+
+look into the variable nullret
+*/
+struct ex_ex *
+ex_eval(struct expr *expr, struct ex_ex *eptr, struct ex_ex *optr, int idx)
+/* the expr object data pointer */
+/* the operation stack */
+/* the result pointer */
+/* the sample numnber processed for fexpr~ */
+{
+        int i, j;
+        t_float *lp, *rp, *op; /* left, right, and out pointer to vectors */
+        t_float scalar;
+        int nullret = 0;                /* did we have an error */
+        struct ex_ex left, right;       /* left and right operands */
+
+        left.ex_type = 0;
+        left.ex_int = 0;
+        right.ex_type = 0;
+        right.ex_int = 0;
+
+        if (!eptr)
+                return (exNULL);
+        switch (eptr->ex_type) {
+        case ET_INT:
+                if (optr->ex_type == ET_VEC)
+                        ex_mkvector(optr->ex_vec, (float) eptr->ex_int,
+                                                                expr->exp_vsize);
+                else
+                        *optr = *eptr;
+                return (++eptr);
+
+        case ET_FLT:
+
+                if (optr->ex_type == ET_VEC)
+                        ex_mkvector(optr->ex_vec, eptr->ex_flt, expr->exp_vsize);
+                else
+                        *optr = *eptr;
+                return (++eptr);
+
+        case ET_SYM:
+                if (optr->ex_type == ET_VEC) {
+                        post_error((fts_object_t *) expr,
+                              "expr: ex_eval: cannot turn string to vector\n");
+                        return (exNULL);
+                }
+                *optr = *eptr;
+                return (++eptr);
+        case ET_II:
+                if (eptr->ex_int == -1) {
+                        post_error((fts_object_t *) expr,
+                            "expr: ex_eval: inlet number not set\n");
+                        return (exNULL);
+                }
+                if (optr->ex_type == ET_VEC) {
+                        ex_mkvector(optr->ex_vec,
+                               (t_float)expr->exp_var[eptr->ex_int].ex_int,
+                                                                expr->exp_vsize);
+                } else {
+                        optr->ex_type = ET_INT;
+                        optr->ex_int = expr->exp_var[eptr->ex_int].ex_int;
+                }
+                return (++eptr);
+        case ET_FI:
+                if (eptr->ex_int == -1) {
+                        post_error((fts_object_t *) expr,
+                            "expr: ex_eval: inlet number not set\n");
+                        return (exNULL);
+                }
+                if (optr->ex_type == ET_VEC) {
+                        ex_mkvector(optr->ex_vec,
+                             expr->exp_var[eptr->ex_int].ex_flt, expr->exp_vsize);
+                } else {
+                        optr->ex_type = ET_FLT;
+                        optr->ex_flt = expr->exp_var[eptr->ex_int].ex_flt;
+                }
+                return (++eptr);
+
+        case ET_VSYM:
+                if (optr->ex_type == ET_VEC) {
+                        post_error((fts_object_t *) expr,
+                            "expr: IntErr. vsym in for vec out\n");
+                        return (exNULL);
+                }
+                if (eptr->ex_int == -1) {
+                        post_error((fts_object_t *) expr,
+                                "expr: ex_eval: inlet number not set\n");
+                        return (exNULL);
+                }
+                optr->ex_type = ET_SYM;
+                optr->ex_ptr = expr->exp_var[eptr->ex_int].ex_ptr;
+                return(++eptr);
+
+        case ET_VI:
+                if (optr->ex_type != ET_VEC)
+                        *optr = expr->exp_var[eptr->ex_int];
+                else if (optr->ex_vec != expr->exp_var[eptr->ex_int].ex_vec)
+                        memcpy(optr->ex_vec, expr->exp_var[eptr->ex_int].ex_vec,
+                                        expr->exp_vsize * sizeof (t_float));
+                return(++eptr);
+        case ET_VEC:
+                if (optr->ex_type != ET_VEC) {
+                        optr->ex_type = ET_VEC;
+                        optr->ex_vec = eptr->ex_vec;
+                        eptr->ex_type = ET_INT;
+                        eptr->ex_int = 0;
+                } else if (optr->ex_vec != eptr->ex_vec) {
+                        memcpy(optr->ex_vec, eptr->ex_vec,
+                                        expr->exp_vsize * sizeof (t_float));
+/* do we need to free here? or can we free higher up */
+/* SDY  the next lines do not make sense */
+post("calling fts_free\n");
+abort();
+                        fts_free(optr->ex_vec);
+                        optr->ex_type = ET_INT;
+                        eptr->ex_int = 0;
+                } else { /* this should not happen */   
+                        post("expr int. error, optr->ex_vec = %d",optr->ex_vec);
+                        abort();
+                }
+                return(++eptr);
+        case ET_XI0:
+                /* short hand for $x?[0] */
+
+                /* SDY delete the following check */
+                if (!IS_FEXPR_TILDE(expr) || optr->ex_type==ET_VEC) {
+                        post("%d:exp->exp_flags = %d", __LINE__,expr->exp_flags);
+                        abort();
+                }
+                optr->ex_type = ET_FLT;
+                optr->ex_flt = expr->exp_var[eptr->ex_int].ex_vec[idx];
+                return(++eptr);
+        case ET_YOM1:
+                /*
+                 * short hand for $y?[-1]
+                 * if we are calculating the first sample of the vector
+                 * we need to look at the previous results buffer
+                 */
+                optr->ex_type = ET_FLT;
+                if (idx == 0)
+                        optr->ex_flt =
+                        expr->exp_p_res[eptr->ex_int][expr->exp_vsize - 1];
+                else
+                        optr->ex_flt=expr->exp_tmpres[eptr->ex_int][idx-1];
+                return(++eptr);
+                
+        case ET_YO:
+        case ET_XI:
+                /* SDY delete the following */
+                if (!IS_FEXPR_TILDE(expr) || optr->ex_type==ET_VEC) {
+                        post("%d:expr->exp_flags = %d", __LINE__,expr->exp_flags);
+                        abort();
+                }
+                return (eval_sigidx(expr, eptr, optr, idx));
+                        
+        case ET_TBL:
+        case ET_SI:
+                return (eval_tab(expr, eptr, optr, idx));
+        case ET_FUNC:
+                return (eval_func(expr, eptr, optr, idx));
+        case ET_VAR:
+                return (eval_var(expr, eptr, optr, idx));
+        case ET_OP:
+                break;
+        case ET_STR:
+        case ET_LP:
+        case ET_LB:
+        default:
+                post_error((fts_object_t *) expr,
+                        "expr: ex_eval: unexpected type %d\n", eptr->ex_type);
+                return (exNULL);
+        }
+        if (!eptr[1].ex_type) {
+                post_error((fts_object_t *) expr,
+                                        "expr: ex_eval: not enough nodes 1\n");
+                return (exNULL);
+        }
+        if (!unary_op(eptr->ex_op) && !eptr[2].ex_type) {
+                post_error((fts_object_t *) expr,
+                                        "expr: ex_eval: not enough nodes 2\n");
+                return (exNULL);
+        }
+
+        switch((eptr++)->ex_op) {
+        case OP_STORE:
+                return (eval_store(expr, eptr, optr, idx));
+        case OP_NOT:
+                EVAL_UNARY(!, +);
+        case OP_NEG:
+                EVAL_UNARY(~, (long));
+        case OP_UMINUS:
+                EVAL_UNARY(-, +);
+        case OP_MUL:
+                EVAL(*);
+        case OP_ADD:
+                EVAL(+);
+        case OP_SUB:
+                EVAL(-);
+        case OP_LT:
+                EVAL(<);
+        case OP_LE:
+                EVAL(<=);
+        case OP_GT:
+                EVAL(>);
+        case OP_GE:
+                EVAL(>=);
+        case OP_EQ:
+                EVAL(==);
+        case OP_NE:
+                EVAL(!=);
+/*
+ * following operators convert their argument to integer
+ */
+#undef DZC
+#define DZC(ARG1,OPR,ARG2)      (((int)ARG1) OPR ((int)ARG2))
+        case OP_SL:
+                EVAL(<<);
+        case OP_SR:
+                EVAL(>>);
+        case OP_AND:
+                EVAL(&);
+        case OP_XOR:
+                EVAL(^);
+        case OP_OR:
+                EVAL(|);
+        case OP_LAND:
+                EVAL(&&);
+        case OP_LOR:
+                EVAL(||);
+/*
+ * for modulo we need to convert to integer and check for divide by zero
+ */
+#undef DZC
+#define DZC(ARG1,OPR,ARG2)      (((ARG2)?(((int)ARG1) OPR ((int)ARG2)) \
+                                                        : (ex_dzdetect(expr),0)))
+        case OP_MOD:
+                EVAL(%);
+/*
+ * define the divide by zero check for divide
+ */
+#undef DZC
+#define DZC(ARG1,OPR,ARG2)      (((ARG2)?(ARG1 OPR ARG2):(ex_dzdetect(expr),0)))
+        case OP_DIV:
+                EVAL(/);
+        case OP_LP:
+        case OP_RP:
+        case OP_LB:
+        case OP_RB:
+        case OP_COMMA:
+        case OP_SEMI:
+        default:
+                post_error((fts_object_t *) expr, "expr: ex_print: bad op 0x%x\n", eptr->ex_op);
+                return (exNULL);
+        }
+
+
+        /*
+         * the left and right nodes could have been transformed to vectors
+         * down the chain
+         */
+        if (left.ex_type == ET_VEC)
+                fts_free(left.ex_vec);
+        if (right.ex_type == ET_VEC)
+                fts_free(right.ex_vec);
+        if (nullret)
+                return (exNULL);
+        else
+                return (eptr);
+}
+
+/*
+ * eval_func --  evaluate a function, call ex_eval() on all the arguments
+ *               so that all of them are terminal nodes. The call the
+ *               appropriate function
+ */
+struct ex_ex *
+eval_func(struct expr *expr, struct ex_ex *eptr, struct ex_ex *optr, int idx)
+/* the expr object data pointer */
+/* the operation stack */
+/* the result pointer */
+{
+        int i;
+        struct ex_ex args[MAX_ARGS];
+        t_ex_func *f;
+
+        f = (t_ex_func *)(eptr++)->ex_ptr;
+        if (!f || !f->f_name) {
+                return (exNULL);
+        }
+        if (f->f_argc > MAX_ARGS) {
+                post_error((fts_object_t *) expr, "expr: eval_func: asking too many arguments\n");
+                return (exNULL);
+        }
+
+        for (i = 0; i < f->f_argc; i++) {
+                args[i].ex_type = 0;
+                args[i].ex_int = 0;
+                eptr = ex_eval(expr, eptr, &args[i], idx);
+        }
+        (*f->f_func)(expr, f->f_argc, args, optr);
+        for (i = 0; i < f->f_argc; i++) {
+                if (args[i].ex_type == ET_VEC)
+                        fts_free(args[i].ex_vec);
+        }
+        return (eptr);
+}
+
+
+/*
+ * eval_store --  evaluate the '=' operator, 
+ *                make sure the first operator is a legal left operator
+ *                and call ex_eval on the right operator
+ */
+struct ex_ex *
+eval_store(struct expr *expr, struct ex_ex *eptr, struct ex_ex *optr, int idx)
+/* the expr object data pointer */
+/* the operation stack */
+/* the result pointer */
+{
+        struct ex_ex arg;
+        int isvalue;
+        char *tbl = (char *) 0;
+        char *var = (char *) 0;
+        int badleft = 0;
+
+post("store called\n");
+ex_print(eptr);
+eptr = ex_eval(expr, ++eptr, optr, idx);
+return (eptr);
+
+#ifdef notdef /* SDY */
+        arg.ex_type = ET_INT;
+        arg.ex_int = 0;
+        if (eptr->ex_type == ET_VAR) {
+                var = (char *) eptr->ex_ptr;
+
+                eptr = ex_eval(expr, ++eptr, &arg, idx);
+                (void)max_ex_var_store(expr, (t_symbol *)var, &arg, optr);
+                if (arg.ex_type == ET_VEC)
+                        fts_free(arg.ex_vec);
+        }
+
+
+        if (eptr->ex_type == ET_SI) {
+                eptr++;
+                if (eptr->ex_type =
+        }
+
+        /* the left operator should either be a value or a array member */
+        switch (eptr->ex_type) {
+        case ET_SI:
+                if ((eptr + 1)->ex_type == OP_LB) {
+                }
+                if (!expr->exp_var[eptr->ex_int].ex_ptr) {
+                                if (!(expr->exp_error & EE_NOTABLE)) {
+                                        post("expr: syntax error: no string for inlet %d", eptr->ex_int + 1);
+                                        post("expr: No more table errors will be reported");
+                                        post("expr: till the next reset");
+                                        expr->exp_error |= EE_NOTABLE;
+                                }
+                                badleft++;
+                } else
+                        tbl = (char *) expr->exp_var[eptr->ex_int].ex_ptr;
+                break;
+        case ET_TBL:
+        }
+#endif /* SDY */
+}
+
+/*
+ * eval_tab -- evaluate a table operation
+ */
+struct ex_ex *
+eval_tab(struct expr *expr, struct ex_ex *eptr, struct ex_ex *optr, int idx)
+/* the expr object data pointer */
+/* the operation stack */
+/* the result pointer */
+{
+        struct ex_ex arg;
+        char *tbl = (char *) 0;
+        int notable = 0;
+        
+        if (eptr->ex_type == ET_SI) {
+                if (!expr->exp_var[eptr->ex_int].ex_ptr) {
+/* SDY post_error() does not work in MAX/MSP yet
+                                post_error((fts_object_t *) expr,
+                                     "expr: syntax error: no string for inlet %d\n", eptr->ex_int + 1);
+*/
+                                if (!(expr->exp_error & EE_NOTABLE)) {
+                                        post("expr: syntax error: no string for inlet %d", eptr->ex_int + 1);
+                                        post("expr: No more table errors will be reported");
+                                        post("expr: till the next reset");
+                                        expr->exp_error |= EE_NOTABLE;
+                                }
+                                notable++;
+                } else
+                        tbl = (char *) expr->exp_var[eptr->ex_int].ex_ptr;
+        } else if (eptr->ex_type == ET_TBL)
+                tbl = (char *) eptr->ex_ptr;
+        else {
+                post_error((fts_object_t *) expr, "expr: eval_tbl: bad type %ld\n", eptr->ex_type);
+                notable++;
+
+        }
+        arg.ex_type = 0;
+        arg.ex_int = 0;
+        eptr = ex_eval(expr, ++eptr, &arg, idx);
+
+        optr->ex_type = ET_INT;
+        optr->ex_int = 0;
+        if (!notable)
+                (void)max_ex_tab(expr, (t_symbol *)tbl, &arg, optr);
+        if (arg.ex_type == ET_VEC)
+                fts_free(arg.ex_vec);
+        return (eptr);
+}
+
+/*
+ * eval_var -- evaluate a variable
+ */
+struct ex_ex *
+eval_var(struct expr *expr, struct ex_ex *eptr, struct ex_ex *optr, int idx)
+/* the expr object data pointer */
+/* the operation stack */
+/* the result pointer */
+{
+        struct ex_ex arg;
+        char *var = (char *) 0;
+        int novar = 0;
+        
+        if (eptr->ex_type == ET_SI) {
+                if (!expr->exp_var[eptr->ex_int].ex_ptr) {
+/* SDY post_error() does not work in MAX/MSP yet
+post_error((fts_object_t *) expr,
+"expr: syntax error: no string for inlet %d\n", eptr->ex_int + 1);
+*/
+                                if (!(expr->exp_error & EE_NOVAR)) {
+                                        post("expr: syntax error: no string for inlet %d", eptr->ex_int + 1);
+                                        post("expr: No more table errors will be reported");
+                                        post("expr: till the next reset");
+                                        expr->exp_error |= EE_NOVAR;
+                                }
+                                novar++;
+                } else
+                        var = (char *) expr->exp_var[eptr->ex_int].ex_ptr;
+        } else if (eptr->ex_type == ET_VAR)
+                var = (char *) eptr->ex_ptr;
+        else {
+                post_error((fts_object_t *) expr, "expr: eval_tbl: bad type %ld\n", eptr->ex_type);
+                novar++;
+
+        }
+
+        optr->ex_type = ET_INT;
+        optr->ex_int = 0;
+        if (!novar)
+                (void)max_ex_var(expr, (t_symbol *)var, optr);
+        return (++eptr);
+}
+
+/*
+ * eval_sigidx -- evaluate the value of an indexed signal for fexpr~
+ */
+struct ex_ex *
+eval_sigidx(struct expr *expr, struct ex_ex *eptr, struct ex_ex *optr, int idx)
+/* the expr object data pointer */
+/* the operation stack */
+/* the result pointer */
+/* the index */
+{
+        struct ex_ex arg;
+        struct ex_ex *reteptr;
+        int i = 0, j = 0;
+        float fi = 0,           /* index in float */
+              rem_i = 0;        /* remains of the float */
+        char *tbl;
+
+        arg.ex_type = 0;
+        arg.ex_int = 0;
+        reteptr = ex_eval(expr, eptr + 1, &arg, idx);
+        if (arg.ex_type == ET_FLT) {
+                fi = arg.ex_flt;                /* float index */
+                i = (int) arg.ex_flt;           /* integer index */
+                rem_i =  arg.ex_flt - i;        /* remains of integer */
+        } else if (arg.ex_type == ET_INT) {
+                fi = arg.ex_int;                /* float index */
+                i = arg.ex_int;
+                rem_i = 0;
+        } else {
+                post("eval_sigidx: bad res type (%d)", arg.ex_type);
+        }
+        optr->ex_type = ET_FLT;
+        /*
+         * indexing an input vector
+         */
+        if (eptr->ex_type == ET_XI) {
+                if (fi > 0) {
+                        if (!(expr->exp_error & EE_BI_INPUT)) {
+                                expr->exp_error |= EE_BI_INPUT;
+                          post("expr: input vector index > 0, (vector x%d[%f])",
+                                               eptr->ex_int + 1, i + rem_i);
+                                post("fexpr~: index assumed to be = 0");
+                                post("fexpr~: no error report till next reset");
+                                ex_print(eptr);
+                        }
+                        /* just replace it with zero */
+                        i = 0;
+                        rem_i = 0;
+                }
+                if (cal_sigidx(optr, i, rem_i, idx, expr->exp_vsize,
+                                        expr->exp_var[eptr->ex_int].ex_vec,
+                                                expr->exp_p_var[eptr->ex_int])) {
+                        if (!(expr->exp_error & EE_BI_INPUT)) {
+                                expr->exp_error |= EE_BI_INPUT;
+                                post("expr: input vector index <  -VectorSize, (vector x%d[%f])", eptr->ex_int + 1, fi);
+                                ex_print(eptr);
+                                post("fexpr~: index assumed to be = -%d",
+                                        expr->exp_vsize);
+                                post("fexpr~: no error report till next reset");
+                        }
+                }
+
+        /*
+         * indexing an output vector
+         */
+        } else if (eptr->ex_type == ET_YO) {
+                /* for output vectors index of zero is not legal */
+                if (fi >= 0) {
+                        if (!(expr->exp_error & EE_BI_OUTPUT)) {
+                                expr->exp_error |= EE_BI_OUTPUT;
+                                post("fexpr~: bad output index, (%f)", fi);
+                                ex_print(eptr);
+                                post("fexpr~: no error report till next reset");
+                                post("fexpr~: index assumed to be = -1");
+                        }
+                        i = -1;
+                }
+                if (eptr->ex_int >= expr->exp_nexpr) {
+                        post("fexpr~: $y%d illegal: not that many exprs",
+                                                                eptr->ex_int);
+                        optr->ex_flt = 0;
+                        return (reteptr);
+                }
+                if (cal_sigidx(optr, i, rem_i, idx, expr->exp_vsize,
+                             expr->exp_tmpres[eptr->ex_int],
+                                                expr->exp_p_res[eptr->ex_int])) {
+                        if (!(expr->exp_error & EE_BI_OUTPUT)) {
+                                expr->exp_error |= EE_BI_OUTPUT;
+                                post("fexpr~: bad output index, (%f)", fi);
+                                ex_print(eptr);
+                                post("fexpr~: index assumed to be = -%d",
+                                        expr->exp_vsize);
+                        }
+                }
+        } else {
+                optr->ex_flt = 0;
+                post("fexpr~:eval_sigidx: internal error - unknown vector (%d)",
+                                                                eptr->ex_type);
+        }
+        return (reteptr);
+}
+
+/*
+ * cal_sigidx -- given two tables (one current one previous) calculate an
+ *               evaluation of a float index into the vectors by linear
+ *               interpolation
+ *              return 0 on success, 1 on failure (index out of bound)
+ */
+static int
+cal_sigidx(struct ex_ex *optr,  /* The output value */
+           int i, float rem_i,  /* integer and fractinal part of index */
+           int idx,             /* index of current fexpr~ processing */
+           int vsize,           /* vector size */
+           float *curvec, float *prevec)        /* current and previous table */
+{
+        int n;
+
+        n = i + idx;
+        if (n > 0) {
+                /* from the curvec */
+                if (rem_i)
+                        optr->ex_flt = curvec[n] +
+                                        rem_i * (curvec[n] - curvec[n - 1]);
+                else
+                        optr->ex_flt = curvec[n];
+                return (0);
+        }
+        if (n == 0) {
+                /*
+                 * this is the case that the remaining float
+                 * is between two tables
+                 */
+                if (rem_i)
+                        optr->ex_flt = *curvec +
+                                        rem_i * (*curvec - prevec[vsize - 1]);
+                else
+                        optr->ex_flt = *curvec;
+                return (0);
+        }
+        /* find the index in the saved buffer */
+        n = vsize + n;
+        if (n > 0) {
+                if (rem_i)
+                        optr->ex_flt = prevec[n] +
+                                        rem_i * (prevec[n] - prevec[n - 1]);
+                else
+                        optr->ex_flt = prevec[n];
+                return (0);
+        }
+        /* out of bound */
+        optr->ex_flt = *prevec;
+        return (1);
+}
+
+/*
+ * getoken -- return 1 on syntax error otherwise 0
+ */
+int
+getoken(struct expr *expr, struct ex_ex *eptr)
+{
+        char *p;
+        long i;
+
+
+        if (!expr->exp_str) {
+                post("expr: getoken: expression string not set\n");
+                return (0);
+        }
+retry:
+        if (!*expr->exp_str) {
+                eptr->ex_type = 0;
+                eptr->ex_int = 0;
+                return (0);
+        }
+        if (*expr->exp_str == ';') {
+                expr->exp_str++;
+                eptr->ex_type = 0;
+                eptr->ex_int = 0;
+                return (0);
+        }
+        eptr->ex_type = ET_OP;
+        switch (*expr->exp_str++) {
+        case '\\':
+        case ' ':
+        case '\t':
+                goto retry;
+        case ';':
+                post("expr: syntax error: ';' not implemented\n");
+                return (1);
+        case ',':
+                eptr->ex_op = OP_COMMA;
+                break;
+        case '(':
+                eptr->ex_op = OP_LP;
+                break;
+        case ')':
+                eptr->ex_op = OP_RP;
+                break;
+        case ']':
+                eptr->ex_op = OP_RB;
+                break;
+        case '~':
+                eptr->ex_op = OP_NEG;
+                break;
+                /* we will take care of unary minus later */
+        case '*':
+                eptr->ex_op = OP_MUL;
+                break;
+        case '/':
+                eptr->ex_op = OP_DIV;
+                break;
+        case '%':
+                eptr->ex_op = OP_MOD;
+                break;
+        case '+':
+                eptr->ex_op = OP_ADD;
+                break;
+        case '-':
+                eptr->ex_op = OP_SUB;
+                break;
+        case '^':
+                eptr->ex_op = OP_XOR;
+                break;
+        case '[':
+                eptr->ex_op = OP_LB;
+                break;
+        case '!':
+                if (*expr->exp_str == '=') {
+                        eptr->ex_op = OP_NE;
+                        expr->exp_str++;
+                } else
+                        eptr->ex_op = OP_NOT;
+                break;
+        case '<':
+                switch (*expr->exp_str) {
+                case '<':
+                        eptr->ex_op = OP_SL;
+                        expr->exp_str++;
+                        break;
+                case '=':
+                        eptr->ex_op = OP_LE;
+                        expr->exp_str++;
+                        break;
+                default:
+                        eptr->ex_op = OP_LT;
+                        break;
+                }
+                break;
+        case '>':
+                switch (*expr->exp_str) {
+                case '>':
+                        eptr->ex_op = OP_SR;
+                        expr->exp_str++;
+                        break;
+                case '=':
+                        eptr->ex_op = OP_GE;
+                        expr->exp_str++;
+                        break;
+                default:
+                        eptr->ex_op = OP_GT;
+                        break;
+                }
+                break;
+        case '=':
+                if (*expr->exp_str++ != '=') {
+                        post("expr: syntax error: =\n");
+                        return (1);
+                }
+                eptr->ex_op = OP_EQ;
+                break;
+/* do not allow the store till the function is fixed
+                if (*expr->exp_str != '=')
+                        eptr->ex_op = OP_STORE;
+                else {
+                        expr->exp_str++;
+                        eptr->ex_op = OP_EQ;
+                }
+                break;
+*/
+
+        case '&':
+                if (*expr->exp_str == '&') {
+                        expr->exp_str++;
+                        eptr->ex_op = OP_LAND;
+                } else
+                        eptr->ex_op = OP_AND;
+                break;
+
+        case '|':
+                if ((*expr->exp_str == '|')) {
+                        expr->exp_str++;
+                        eptr->ex_op = OP_LOR;
+                } else
+                        eptr->ex_op = OP_OR;
+                break;
+        case '$':
+                switch (*expr->exp_str++) {
+                case 'I':
+                case 'i':
+                        eptr->ex_type = ET_II;
+                        break;
+                case 'F':
+                case 'f':
+                        eptr->ex_type = ET_FI;
+                        break;
+                case 'S':
+                case 's':
+                        eptr->ex_type = ET_SI;
+                        break;
+                case 'V':
+                case 'v':
+                        if (IS_EXPR_TILDE(expr)) {
+                                eptr->ex_type = ET_VI;
+                                break;
+                        }
+                        post("$v? works only for expr~");
+                        post("expr: syntax error: %s\n", &expr->exp_str[-2]);
+                        return (1);
+                case 'X':
+                case 'x':
+                        if (IS_FEXPR_TILDE(expr)) {
+                                eptr->ex_type = ET_XI;
+                                if (isdigit(*expr->exp_str))
+                                        break;
+                                /* for $x[] is a shorhand for $x1[] */
+                                eptr->ex_int = 0;
+                                goto noinletnum;
+                        }
+                        post("$x? works only for fexpr~");
+                        post("expr: syntax error: %s\n", &expr->exp_str[-2]);
+                        return (1);
+                case 'y':
+                case 'Y':
+                        if (IS_FEXPR_TILDE(expr)) {
+                                eptr->ex_type = ET_YO;
+                                /*$y takes no number */
+                                if (isdigit(*expr->exp_str))
+                                        break;
+                                /* for $y[] is a shorhand for $y1[] */
+                                eptr->ex_int = 0;
+                                goto noinletnum;
+                        }
+                        post("$y works only for fexpr~");
+                default:
+                        post("expr: syntax error: %s\n", &expr->exp_str[-2]);
+                        return (1);
+                }
+                p = atoif(expr->exp_str, &eptr->ex_op, &i);
+                if (!p) {
+                        post("expr: syntax error: %s\n", &expr->exp_str[-2]);
+                        return (1);
+                }
+                if (i != ET_INT) {
+                        post("expr: syntax error: %s\n", expr->exp_str);
+                        return (1);
+                }
+                /*
+                 * make the user inlets one based rather than zero based
+                 * therefore we decrement the number that user has supplied
+                 */
+                if (!eptr->ex_op || (eptr->ex_op)-- > MAX_VARS) {
+                 post("expr: syntax error: inlet or outlet out of range: %s\n",
+                                                             expr->exp_str);
+                        return (1);
+                }
+
+                /*
+                 * until we can change the input type of inlets on
+                 * the fly (at pd_new()
+                 * time) the first input to expr~ is always a vectore
+                 * and $f1 or $i1 is
+                 * illegal for fexr~
+                 */
+                if (eptr->ex_op == 0 &&
+                   (IS_FEXPR_TILDE(expr) ||  IS_EXPR_TILDE(expr)) &&
+                   (eptr->ex_type==ET_II || eptr->ex_type==ET_FI ||
+                                                        eptr->ex_type==ET_SI)) {
+                       post("first inlet of expr~/fexpr~ can only be a vector");
+                       return (1);
+                }
+                /* record the inlet or outlet type and check for consistency */
+                if (eptr->ex_type == ET_YO ) {
+                        /* it is an outlet  for fexpr~*/
+                        /* no need to do anything */
+                        ;
+                } else if (!expr->exp_var[eptr->ex_op].ex_type)
+                        expr->exp_var[eptr->ex_op].ex_type = eptr->ex_type;
+                else if (expr->exp_var[eptr->ex_op].ex_type != eptr->ex_type) {
+                        post("expr: syntax error: inlets can only have one type: %s\n", expr->exp_str);
+                        return (1);
+                }
+                expr->exp_str = p;
+noinletnum:
+                break;
+        case '"':
+                {
+                        struct ex_ex ex;
+
+                        p = expr->exp_str;
+                        if (!*expr->exp_str || *expr->exp_str == '"') {
+                                post("expr: syntax error: empty symbol: %s\n", --expr->exp_str);
+                                return (1);
+                        }
+                        if (getoken(expr, &ex))
+                                return (1);
+                        switch (ex.ex_type) {
+                        case ET_STR:
+                                if (ex_getsym(ex.ex_ptr, (t_symbol **)&(eptr->ex_ptr))) {
+                                        post("expr: syntax error: getoken: problms with ex_getsym\n");
+                                        return (1);
+                                }
+                                eptr->ex_type = ET_SYM;
+                                break;
+                        case ET_SI:
+                                *eptr = ex;
+                                eptr->ex_type = ET_VSYM;
+                                break;
+                        default:
+                                post("expr: syntax error: bad symbol name: %s\n", p);
+                                return (1);
+                        }
+                        if (*expr->exp_str++ != '"') {
+                                post("expr: syntax error: missing '\"'\n");
+                                return (1);
+                        }
+                        break;
+                }
+        case '.':
+        case '0':
+        case '1':
+        case '2':
+        case '3':
+        case '4':
+        case '5':
+        case '6':
+        case '7':
+        case '8':
+        case '9':
+                p = atoif(--expr->exp_str, &eptr->ex_int, &eptr->ex_type);
+                if (!p)
+                        return (1);
+                expr->exp_str = p;
+                break;
+
+        default:
+                /*
+                 * has to be a string, it should either be a 
+                 * function or a table 
+                 */
+                p = --expr->exp_str;
+                for (i = 0; name_ok(*p); i++)
+                        p++;
+                if (!i) {
+                        post("expr: syntax error: %s\n", expr->exp_str);
+                        return (1);
+                }
+                eptr->ex_ptr = (char *)fts_malloc(i + 1);
+                strncpy(eptr->ex_ptr, expr->exp_str, (int) i);
+                (eptr->ex_ptr)[i] = 0;
+                expr->exp_str = p;
+                /*
+                 * we mark this as a string and later we will change this
+                 * to either a function or a table
+                 */
+                eptr->ex_type = ET_STR;
+                break;
+        }
+        return (0);
+}
+
+/*
+ * atoif -- ascii to float or integer (understands hex numbers also)
+ */
+char *
+atoif(char *s, long int *value, long int *type)
+{
+        char *p;
+        long int_val = 0;
+        int flt = 0;
+        float pos = 0;
+        float flt_val = 0;
+        int base = 10;
+
+        p = s;
+        if (*p == '0' && (p[1] == 'x' || p[1] == 'X')) {
+                base = 16;
+                p += 2;
+        }
+        while (8) {
+                switch (*p) {
+                case '.':
+                        if (flt || base != 10) {
+                                post("expr: syntax error: %s\n", s);
+                                return ((char *) 0);
+                        }
+                        flt++;
+                        pos = 10;
+                        flt_val = int_val;
+                        break;
+                case '0':
+                case '1':
+                case '2':
+                case '3':
+                case '4':
+                case '5':
+                case '6':
+                case '7':
+                case '8':
+                case '9':
+                        if (flt) {
+                                flt_val += (*p - '0') / pos;
+                                pos *= 10;
+                        } else {
+                                int_val *= base;
+                                int_val += (*p - '0');
+                        }
+                        break;
+                case 'a':
+                case 'b':
+                case 'c':
+                case 'd':
+                case 'e':
+                case 'f':
+                        if (base != 16 || flt) {
+                                post("expr: syntax error: %s\n", s);
+                                return ((char *) 0);
+                        }
+                        int_val *= base;
+                        int_val += (*p - 'a' + 10);
+                        break;
+                case 'A':
+                case 'B':
+                case 'C':
+                case 'D':
+                case 'E':
+                case 'F':
+                        if (base != 16 || flt) {
+                                post("expr: syntax error: %s\n", s);
+                                return ((char *) 0);
+                        }
+                        int_val *= base;
+                        int_val += (*p - 'A' + 10);
+                        break;
+                default:
+                        if (flt) {
+                                *type = ET_FLT;
+                                *((float *) value) = flt_val;
+                        } else {
+                                *type = ET_INT;
+                                *value = int_val;
+                        }
+                        return (p);
+                }
+                p++;
+        }
+}
+
+/*
+ * find_func -- returns a pointer to the found function structure
+ *              otherwise it returns 0
+ */
+t_ex_func *
+find_func(char *s)
+{
+        t_ex_func *f;
+
+        for (f = ex_funcs; f->f_name; f++)
+                if (!strcmp(f->f_name, s))
+                        return (f);
+        return ((t_ex_func *) 0);
+}
+
+
+/*
+ * ex_print -- print an expression array
+ */
+
+void
+ex_print(struct ex_ex *eptr)
+{
+
+        while (eptr->ex_type) {
+                switch (eptr->ex_type) {
+                case ET_INT:
+                        post("%ld ", eptr->ex_int);
+                        break;
+                case ET_FLT:
+                        post("%f ", eptr->ex_flt);
+                        break;
+                case ET_STR:
+                        post("%s ", eptr->ex_ptr);
+                        break;
+                case ET_TBL:
+                case ET_VAR:
+                        post("%s ", ex_symname((fts_symbol_t )eptr->ex_ptr));
+                        break;
+                case ET_SYM:
+                        post("\"%s\" ", ex_symname((fts_symbol_t )eptr->ex_ptr));
+                        break;
+                case ET_VSYM:
+                        post("\"$s%ld\" ", eptr->ex_int + 1);
+                        break;
+                case ET_FUNC:
+                        post("%s ",
+                            ((t_ex_func *)eptr->ex_ptr)->f_name);
+                        break;
+                case ET_LP:
+                        post("%c", '(');
+                        break;
+                        /* CHANGE
+                 case ET_RP:
+                         post("%c ", ')');
+                         break;
+                         */
+                case ET_LB:
+                        post("%c", '[');
+                        break;
+                        /* CHANGE
+                case ET_RB:
+                         post("%c ", ']');
+                         break;
+                         */
+                case ET_II:
+                        post("$i%ld ", eptr->ex_int + 1);
+                        break;
+                case ET_FI:
+                        post("$f%ld ", eptr->ex_int + 1);
+                        break;
+                case ET_SI:
+                        post("$s%lx ", eptr->ex_ptr);
+                        break;
+                case ET_VI:
+                        post("$v%lx ", eptr->ex_vec);
+                        break;
+                case ET_VEC:
+                        post("vec = %ld ", eptr->ex_vec);
+                        break;
+                case ET_YOM1:
+                case ET_YO:
+                        post("$y%d", eptr->ex_int + 1);
+                        break;
+                case ET_XI:
+                case ET_XI0:
+                        post("$x%d", eptr->ex_int + 1);
+                        break;
+                case ET_OP:
+                        switch (eptr->ex_op) {
+                        case OP_LP:
+                                post("%c", '(');
+                                break;
+                        case OP_RP:
+                                post("%c ", ')');
+                                break;
+                        case OP_LB:
+                                post("%c", '[');
+                                break;
+                        case OP_RB:
+                                post("%c ", ']');
+                                break;
+                        case OP_NOT:
+                                post("%c", '!');
+                                break;
+                        case OP_NEG:
+                                post("%c", '~');
+                                break;
+                        case OP_UMINUS:
+                                post("%c", '-');
+                                break;
+                        case OP_MUL:
+                                post("%c", '*');
+                                break;
+                        case OP_DIV:
+                                post("%c", '/');
+                                break;
+                        case OP_MOD:
+                                post("%c", '%');
+                                break;
+                        case OP_ADD:
+                                post("%c", '+');
+                                break;
+                        case OP_SUB:
+                                post("%c", '-');
+                                break;
+                        case OP_SL:
+                                post("%s", "<<");
+                                break;
+                        case OP_SR:
+                                post("%s", ">>");
+                                break;
+                        case OP_LT:
+                                post("%c", '<');
+                                break;
+                        case OP_LE:
+                                post("%s", "<=");
+                                break;
+                        case OP_GT:
+                                post("%c", '>');
+                                break;
+                        case OP_GE:
+                                post("%s", ">=");
+                                break;
+                        case OP_EQ:
+                                post("%s", "==");
+                                break;
+                        case OP_STORE:
+                                post("%s", "=");
+                                break;
+                        case OP_NE:
+                                post("%s", "!=");
+                                break;
+                        case OP_AND:
+                                post("%c", '&');
+                                break;
+                        case OP_XOR:
+                                post("%c", '^');
+                                break;
+                        case OP_OR:
+                                post("%c", '|');
+                                break;
+                        case OP_LAND:
+                                post("%s", "&&");
+                                break;
+                        case OP_LOR:
+                                post("%s", "||");
+                                break;
+                        case OP_COMMA:
+                                post("%c", ',');
+                                break;
+                        case OP_SEMI:
+                                post("%c", ';');
+                                break;
+                        default:
+                                post("expr: ex_print: bad op 0x%lx\n", eptr->ex_op);
+                        }
+                        break;
+                default:
+                        post("expr: ex_print: bad type 0x%lx\n", eptr->ex_type);
+                }
+                eptr++;
+        }
+        post("\n");
+}
+
+#ifdef _WIN32
+void ABORT( void) {bug("expr");}
+#endif
diff --git a/extra/expr~/vexp.h b/extra/expr~/vexp.h
new file mode 100644
index 0000000000000000000000000000000000000000..d096842f58299bf079067d728009170a375a2827
--- /dev/null
+++ b/extra/expr~/vexp.h
@@ -0,0 +1,248 @@
+/*
+ * jMax
+ * Copyright (C) 1994, 1995, 1998, 1999 by IRCAM-Centre Georges Pompidou, Paris, France.
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * See file LICENSE for further informations on licensing terms.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * 
+ * Based on Max/ISPW by Miller Puckette.
+ *
+ * Authors: Maurizio De Cecco, Francois Dechelle, Enzo Maggi, Norbert Schnell.
+ *
+ */
+
+/* "expr" was written by Shahrokh Yadegari c. 1989. -msp */
+/* "expr~" and "fexpr~" conversion by Shahrokh Yadegari c. 1999,2000 */
+
+#define MSP
+#ifdef PD
+#undef MSP
+#endif
+
+#ifdef PD
+#include "m_pd.h"
+#else /* MSP */
+#include "ext.h"
+#include "z_dsp.h"
+#endif
+
+#include "fts_to_pd.h"
+/* This is put in fts_to_pd.h
+
+#ifdef MSP
+#define t_atom  Atom
+#define t_symbol Symbol
+#define pd_new(x)       newobject(x);
+#define t_outlet void
+#endif
+*/
+
+/*
+ * Currently the maximum number of variables (inlets) that are supported
+ * is 10.
+ */
+
+#define MAX_VARS        9
+#define MINODES         10 /* was 200 */
+
+/* terminal defines */
+
+/*
+ * operations
+ * (x<<16|y) x defines the level of precedence,
+ * the lower the number the lower the precedence
+ * separators are defines as operators just for convenience
+ */
+
+#define OP_SEMI         ((long)(1<<16|1))               /* ; */
+#define OP_COMMA        ((long)(2<<16|2))               /* , */
+#define OP_LOR          ((long)(3<<16|3))               /* || */
+#define OP_LAND         ((long)(4<<16|4))               /* && */
+#define OP_OR           ((long)(5<<16|5))               /* | */
+#define OP_XOR          ((long)(6<<16|6))               /* ^ */
+#define OP_AND          ((long)(7<<16|7))               /* & */
+#define OP_NE           ((long)(8<<16|8))               /* != */
+#define OP_EQ           ((long)(8<<16|9))               /* == */
+#define OP_GE           ((long)(9<<16|10))              /* >= */
+#define OP_GT           ((long)(9<<16|11))              /* > */
+#define OP_LE           ((long)(9<<16|12))              /* <= */
+#define OP_LT           ((long)(9<<16|13))              /* < */
+#define OP_SR           ((long)(10<<16|14))             /* >> */
+#define OP_SL           ((long)(10<<16|15))             /* << */
+#define OP_SUB          ((long)(11<<16|16))             /* - */
+#define OP_ADD          ((long)(11<<16|17))             /* + */
+#define OP_MOD          ((long)(12<<16|18))             /* % */
+#define OP_DIV          ((long)(12<<16|19))             /* / */
+#define OP_MUL          ((long)(12<<16|20))             /* * */
+#define OP_UMINUS       ((long)(13<<16|21))             /* - unary minus */
+#define OP_NEG          ((long)(13<<16|22))             /* ~ one complement */
+#define OP_NOT          ((long)(13<<16|23))             /* ! */
+#define OP_RB           ((long)(14<<16|24))             /* ] */
+#define OP_LB           ((long)(14<<16|25))             /* [ */
+#define OP_RP           ((long)(14<<16|26))             /* ) */
+#define OP_LP           ((long)(14<<16|27))             /* ( */
+#define OP_STORE        ((long)(15<<16|28))             /* = */
+#define HI_PRE          ((long)(100<<16))       /* infinite precedence */
+#define PRE_MASK        ((long)0xffff0000)      /* precedence level mask */
+
+struct ex_ex;
+
+#define name_ok(c)      (((c)=='_') || ((c)>='a' && (c)<='z') || \
+                        ((c)>='A' && (c)<='Z') || ((c) >= '0' && (c) <= '9'))
+#define unary_op(x)     ((x) == OP_NOT || (x) == OP_NEG || (x) == OP_UMINUS)
+
+struct ex_ex {
+        union {
+                long v_int;
+                float v_flt;
+                t_float *v_vec;         /* this is an for allocated vector */
+                long op;
+                char *ptr;
+        } ex_cont;              /* content */
+#define ex_int          ex_cont.v_int
+#define ex_flt          ex_cont.v_flt
+#define ex_vec          ex_cont.v_vec
+#define ex_op           ex_cont.op
+#define ex_ptr          ex_cont.ptr
+        long ex_type;           /* type of the node */
+};
+#define exNULL  ((struct ex_ex *)0)
+
+/* defines for ex_type */
+#define ET_INT          1               /* an int */
+#define ET_FLT          2               /* a float */
+#define ET_OP           3               /* operator */
+#define ET_STR          4               /* string */
+#define ET_TBL          5               /* a table, the content is a pointer */
+#define ET_FUNC         6               /* a function */
+#define ET_SYM          7               /* symbol ("string") */
+#define ET_VSYM         8               /* variable symbol ("$s?") */
+                                /* we treat parenthesis and brackets */
+                                /* special to keep a pointer to their */
+                                /* match in the content */
+#define ET_LP           9               /* left parenthesis */
+#define ET_LB           10              /* left bracket */
+#define ET_II           11              /* and integer inlet */
+#define ET_FI           12              /* float inlet */
+#define ET_SI           13              /* string inlet */
+#define ET_VI           14              /* signal inlet */
+#define ET_VEC          15              /* allocated signal vector */
+                                /* special types for fexpr~ */
+#define ET_YO           16              /* vector output for fexpr~ */
+#define ET_YOM1         17              /* shorthand for $y?[-1] */
+#define ET_XI           18              /* vector input for fexpr~ */
+#define ET_XI0          20              /* shorthand for $x?[0] */
+#define ET_VAR          21              /* variable */
+
+/* defines for ex_flags */
+#define EF_TYPE_MASK    0x07    /* first three bits define the type of expr */
+#define EF_EXPR         0x01    /* expr  - control in and out */
+#define EF_EXPR_TILDE   0x02    /* expr~ signal and control in, signal out */
+#define EF_FEXPR_TILDE  0x04    /* fexpr~ filter expression */
+
+#define EF_STOP         0x08    /* is it stopped used for expr~ and fexpr~ */
+#define EF_VERBOSE      0x10    /* verbose mode */
+
+#define IS_EXPR(x)        ((((x)->exp_flags&EF_TYPE_MASK)|EF_EXPR) == EF_EXPR)
+#define IS_EXPR_TILDE(x)  \
+                 ((((x)->exp_flags&EF_TYPE_MASK)|EF_EXPR_TILDE)==EF_EXPR_TILDE)
+#define IS_FEXPR_TILDE(x) \
+               ((((x)->exp_flags&EF_TYPE_MASK)|EF_FEXPR_TILDE)==EF_FEXPR_TILDE)
+
+#define SET_EXPR(x)     (x)->exp_flags |= EF_EXPR; \
+                        (x)->exp_flags &= ~EF_EXPR_TILDE;  \
+                        (x)->exp_flags &= ~EF_FEXPR_TILDE; 
+
+#define SET_EXPR_TILDE(x)       (x)->exp_flags &= ~EF_EXPR; \
+                                (x)->exp_flags |= EF_EXPR_TILDE;  \
+                                (x)->exp_flags &= ~EF_FEXPR_TILDE; 
+
+#define SET_FEXPR_TILDE(x)      (x)->exp_flags &= ~EF_EXPR; \
+                                (x)->exp_flags &= ~EF_EXPR_TILDE;  \
+                                (x)->exp_flags |= EF_FEXPR_TILDE; 
+
+/*
+ * defines for expr_error
+ */
+#define EE_DZ           0x01    /* divide by zero error */
+#define EE_BI_OUTPUT    0x02    /* Bad output index */
+#define EE_BI_INPUT     0x04    /* Bad input index */
+#define EE_NOTABLE      0x08    /* NO TABLE */
+#define EE_NOVAR        0x10    /* NO VARIABLE */
+
+typedef struct expr {
+#ifdef PD
+        t_object exp_ob;
+#else /* MSP */
+        t_pxobject exp_ob;
+#endif
+        int     exp_flags;              /* are we expr~, fexpr~, or expr */
+        int     exp_error;              /* reported errors */
+        int     exp_nexpr;              /* number of expressions */
+        char    *exp_string;            /* the full expression string */
+        char    *exp_str;               /* current parsing position */
+        t_outlet *exp_outlet[MAX_VARS];
+#ifdef PD
+        struct _exprproxy *exp_proxy;
+#else /* MAX */
+        void *exp_proxy[MAX_VARS];
+        long exp_proxy_id;
+#endif
+        struct ex_ex *exp_stack[MAX_VARS];
+        struct ex_ex exp_var[MAX_VARS];
+        struct ex_ex exp_res[MAX_VARS]; /* the evluation result */
+        t_float *exp_p_var[MAX_VARS];
+        t_float *exp_p_res[MAX_VARS];   /* the previous evaluation result */
+        t_float *exp_tmpres[MAX_VARS];          /* temporty result for fexpr~ */
+        int exp_vsize;                  /* the size of the signal vector */
+        int exp_nivec;                  /* # of vector inlets */
+        float exp_f;            /* control value to be transformed to signal */
+} t_expr;
+
+typedef struct ex_funcs {
+        char *f_name;                                   /* function name */
+        void (*f_func)(t_expr *, long, struct ex_ex *, struct ex_ex *);
+          /* the real function performing the function (void, no return!!!) */
+        long f_argc;                            /* number of arguments */
+} t_ex_func;
+
+/* function prototypes for pd-related functions called withing vexp.h */
+
+extern int max_ex_tab(struct expr *expr, t_symbol *s, struct ex_ex *arg, struct ex_ex *optr);
+extern int max_ex_var(struct expr *expr, t_symbol *s, struct ex_ex *optr);
+extern int ex_getsym(char *p, t_symbol **s);
+extern const char *ex_symname(t_symbol *s);
+void ex_mkvector(t_float *fp, t_float x, int size);
+extern void ex_size(t_expr *expr, long int argc, struct ex_ex *argv,
+                                                        struct ex_ex *optr);
+extern void ex_sum(t_expr *expr, long int argc, struct ex_ex *argv,                                                                     struct ex_ex *optr);
+extern void ex_Sum(t_expr *expr, long int argc, struct ex_ex *argv,                                                                     struct ex_ex *optr);
+extern void ex_avg(t_expr *expr, long int argc, struct ex_ex *argv,                                                                     struct ex_ex *optr);
+extern void ex_Avg(t_expr *expr, long int argc, struct ex_ex *argv,                                                                     struct ex_ex *optr);
+extern void ex_store(t_expr *expr, long int argc, struct ex_ex *argv,                                                                   struct ex_ex *optr);
+
+int value_getonly(t_symbol *s, t_float *f);
+
+
+/* These pragmas are only used for MSVC, not MinGW or Cygwin <hans@at.or.at> */
+#ifdef _MSC_VER
+#pragma warning (disable: 4305 4244)
+#endif
+
+#ifdef _WIN32
+#define abort ABORT
+void ABORT(void);
+#endif
diff --git a/extra/expr~/vexp_fun.c b/extra/expr~/vexp_fun.c
new file mode 100644
index 0000000000000000000000000000000000000000..26b0b7675c4b1296370bc3e3d1ca3a93941bbd33
--- /dev/null
+++ b/extra/expr~/vexp_fun.c
@@ -0,0 +1,1315 @@
+/*
+ * jMax
+ * Copyright (C) 1994, 1995, 1998, 1999 by IRCAM-Centre Georges Pompidou, Paris, France.
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * See file LICENSE for further informations on licensing terms.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * 
+ * Based on Max/ISPW by Miller Puckette.
+ *
+ * Authors: Maurizio De Cecco, Francois Dechelle, Enzo Maggi, Norbert Schnell.
+ *
+ */
+
+/* "expr" was written by Shahrokh Yadegari c. 1989. -msp
+ *
+ * Nov. 2001 --sdy
+ *      conversion for expr~
+ *
+ * Jan, 2002 --sdy
+ *      added fmod()
+ *
+ * May  2002
+ *      added floor and ceil for expr -- Orm Finnendahl
+ *
+ * July 2002 --sdy
+ *      added the following math funtions:
+ *              cbrt - cube root
+ *              erf - error function
+ *              erfc - complementary error function
+ *              expm1 - exponential minus 1,
+ *              log1p - logarithm of 1 plus
+ *              isinf - is the value infinite,
+ *              finite - is the value finite
+ *              isnan -- is the resut a nan (Not a number)
+ *              copysign - copy sign of a number
+ *              ldexp  -  multiply floating-point number by integral power of 2
+ *              imodf - get signed integral value from floating-point number
+ *              modf - get signed fractional value from floating-point number
+ *              drem - floating-point remainder function
+ *
+ *      The following are done but not popular enough in math libss
+ *      to be included yet
+ *              hypoth - Euclidean distance function
+ *              trunc
+ *              round
+ *              nearbyint - 
+ */
+
+
+
+/*
+ * vexp_func.c -- this file include all the functions for vexp.
+ *                the first two arguments to the function are the number
+ *                of argument and an array of arguments (argc, argv)
+ *                the last argument is a pointer to a struct ex_ex for
+ *                the result.  Up do this point, the content of the
+ *                struct ex_ex that these functions receive are either
+ *                ET_INT (long), ET_FLT (float), or ET_SYM (char **, it is
+ *                char ** and not char * since NewHandle of Mac returns
+ *                a char ** for relocatability.)  The common practice in
+ *                these functions is that they figure out the type of their
+ *                result according to the type of the arguments. In general
+ *                the ET_SYM is used an ET_INT when we expect a value.
+ *                It is the users responsibility not to pass strings to the
+ *                function.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#define __STRICT_BSD__
+#include <math.h>
+#undef __STRICT_BSD__
+
+
+#include "vexp.h"
+
+/* forward declarations */
+
+static void ex_min(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex *optr);
+static void ex_max(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex *optr);
+static void ex_toint(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex *optr);
+static void ex_rint(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex *optr);
+static void ex_tofloat(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex *optr);
+static void ex_pow(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex *optr);
+static void ex_exp(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex *optr);
+static void ex_log(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex *optr);
+static void ex_ln(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex *optr);
+static void ex_sin(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex *optr);
+static void ex_cos(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex *optr);
+static void ex_asin(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex *optr);
+static void ex_acos(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex *optr);
+static void ex_tan(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex *optr);
+static void ex_atan(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex *optr);
+static void ex_sinh(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex *optr);
+static void ex_cosh(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex *optr);
+static void ex_asinh(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr);
+static void ex_acosh(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr);
+static void ex_tanh(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex *optr);
+static void ex_atanh(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr);
+static void ex_atan2(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex *optr);
+static void ex_sqrt(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex *optr);
+static void ex_fact(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex *optr);
+static void ex_random(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex *optr);
+static void ex_abs(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex *optr);
+static void ex_fmod(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr);
+static void ex_ceil(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr);
+static void ex_floor(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr);
+static void ex_if(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr);
+static void ex_ldexp(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr);
+static void ex_imodf(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr);
+static void ex_modf(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr);
+#ifndef _WIN32
+static void ex_cbrt(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr);
+static void ex_erf(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr);
+static void ex_erfc(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr);
+static void ex_expm1(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr);
+static void ex_log1p(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr);
+static void ex_isinf(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr);
+static void ex_finite(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr);
+static void ex_isnan(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr);
+static void ex_copysign(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr);
+static void ex_drem(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr);
+#endif
+#ifdef notdef
+/* the following will be added once they are more popular in math libraries */
+static void ex_round(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr);
+static void ex_trunc(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr);
+static void ex_nearbyint(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr);
+static void ex_hypoth(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr);
+#endif
+ 
+
+t_ex_func ex_funcs[] = {
+        {"min",         ex_min,         2},
+        {"max",         ex_max,         2},
+        {"int",         ex_toint,       1},
+        {"rint",        ex_rint,        1},
+        {"float",       ex_tofloat,     1},
+        {"fmod",        ex_fmod,        2},
+        {"floor",       ex_floor,       2},
+        {"ceil",        ex_ceil,        2},
+        {"pow",         ex_pow,         2},
+        {"sqrt",        ex_sqrt,        1},
+        {"exp",         ex_exp,         1},
+        {"log10",       ex_log,         1},
+        {"ln",          ex_ln,          1},
+        {"log",         ex_ln,          1},
+        {"sin",         ex_sin,         1},
+        {"cos",         ex_cos,         1},
+        {"tan",         ex_tan,         1},
+        {"asin",        ex_asin,        1},
+        {"acos",        ex_acos,        1},
+        {"atan",        ex_atan,        1},
+        {"atan2",       ex_atan2,       2},
+        {"sinh",        ex_sinh,        1},
+        {"cosh",        ex_cosh,        1},
+        {"tanh",        ex_tanh,        1},
+        {"fact",        ex_fact,        1},
+        {"random",      ex_random,      2},     /* random number */
+        {"abs",         ex_abs,         1},
+        {"if",          ex_if,          3},
+        {"ldexp ",      ex_ldexp,       1},
+        {"imodf ",      ex_imodf,       1},
+        {"modf",        ex_modf,        1},
+#ifndef _WIN32
+        {"cbrt",        ex_cbrt,        1},
+        {"erf",         ex_erf,         1},
+        {"erfc",        ex_erfc,        1},
+        {"expm1",       ex_expm1,       1},
+        {"log1p",       ex_log1p,       1},
+        {"isinf",       ex_isinf,       1},
+        {"finite",      ex_finite,      1},
+        {"isnan",       ex_isnan,       1},
+        {"copysig",     ex_copysign,    1},
+        {"drem",        ex_drem,        1},
+        {"asinh",       ex_asinh,       1},
+        {"acosh",       ex_acosh,       1},
+        {"atanh",       ex_atanh,       1},     /* hyperbolic atan */
+#endif
+#ifdef PD
+        {"size",        ex_size,        1},
+        {"sum",         ex_sum,         1},
+        {"Sum",         ex_Sum,         3},
+        {"avg",         ex_avg,         1},
+        {"Avg",         ex_Avg,         3},
+        {"store",       ex_store,       3},
+#endif
+#ifdef notdef
+/* the following will be added once they are more popular in math libraries */
+        {"round",       ex_round,       1},
+        {"trunc",       ex_trunc,       1},
+        {"nearbyint",   ex_nearbyint,   1},
+        {"hypoth",      ex_hypoth,      1},
+#endif
+        {0,             0,              0}
+};
+
+/*
+ * FUN_EVAL --  do type checking, evaluate a function,
+ *              if fltret is set return float
+ *              otherwise return value based on regular typechecking,
+ */
+#define FUNC_EVAL(left, right, func, leftfuncast, rightfuncast, optr, fltret) \
+switch (left->ex_type) {                                                \
+case ET_INT:                                                            \
+        switch(right->ex_type) {                                        \
+        case ET_INT:                                                    \
+                if (optr->ex_type == ET_VEC) {                          \
+                        op = optr->ex_vec;                              \
+                        scalar = (float)func(leftfuncast left->ex_int,  \
+                                        rightfuncast right->ex_int);    \
+                        j = e->exp_vsize;                               \
+                        while (j--)                                     \
+                                *op++ = scalar;                         \
+                } else {                                                \
+                        if (fltret) {                                   \
+                                optr->ex_type = ET_FLT;                 \
+                                optr->ex_flt = (float)func(leftfuncast  \
+                                left->ex_int, rightfuncast right->ex_int); \
+                        } else {                                        \
+                                optr->ex_type = ET_INT;                 \
+                                optr->ex_int = (int)func(leftfuncast    \
+                                left->ex_int, rightfuncast right->ex_int); \
+                        }                                               \
+                }                                                       \
+                break;                                                  \
+        case ET_FLT:                                                    \
+                if (optr->ex_type == ET_VEC) {                          \
+                        op = optr->ex_vec;                              \
+                        scalar = (float)func(leftfuncast left->ex_int,  \
+                                        rightfuncast right->ex_flt);    \
+                        j = e->exp_vsize;                               \
+                        while (j--)                                     \
+                                *op++ = scalar;                         \
+                } else {                                                \
+                        optr->ex_type = ET_FLT;                         \
+                        optr->ex_flt = (float)func(leftfuncast left->ex_int,  \
+                                        rightfuncast right->ex_flt);    \
+                }                                                       \
+                break;                                                  \
+        case ET_VEC:                                                    \
+        case ET_VI:                                                     \
+                if (optr->ex_type != ET_VEC) {                          \
+                        if (optr->ex_type == ET_VI) {                   \
+                                post("expr~: Int. error %d", __LINE__); \
+                                abort();                                \
+                        }                                               \
+                        optr->ex_type = ET_VEC;                         \
+                        optr->ex_vec = (t_float *)                      \
+                          fts_malloc(sizeof (t_float)*e->exp_vsize);    \
+                }                                                       \
+                scalar = left->ex_int;                                  \
+                rp = right->ex_vec;                                     \
+                op = optr->ex_vec;                                      \
+                j = e->exp_vsize;                                       \
+                while (j--) {                                           \
+                        *op++ = (float)func(leftfuncast scalar,         \
+                                                rightfuncast *rp);      \
+                        rp++;                                           \
+                }                                                       \
+                break;                                                  \
+        case ET_SYM:                                                    \
+        default:                                                        \
+                post_error((fts_object_t *) e,                          \
+                      "expr: FUNC_EVAL(%d): bad right type %ld\n",      \
+                                              __LINE__, right->ex_type);\
+        }                                                               \
+        break;                                                          \
+case ET_FLT:                                                            \
+        switch(right->ex_type) {                                        \
+        case ET_INT:                                                    \
+                if (optr->ex_type == ET_VEC) {                          \
+                        op = optr->ex_vec;                              \
+                        scalar = (float)func(leftfuncast left->ex_flt,  \
+                                        rightfuncast right->ex_int);    \
+                        j = e->exp_vsize;                               \
+                        while (j--)                                     \
+                                *op++ = scalar;                         \
+                } else {                                                \
+                        optr->ex_type = ET_FLT;                         \
+                        optr->ex_flt = (float)func(leftfuncast left->ex_flt,  \
+                                        rightfuncast right->ex_int);    \
+                }                                                       \
+                break;                                                  \
+        case ET_FLT:                                                    \
+                if (optr->ex_type == ET_VEC) {                          \
+                        op = optr->ex_vec;                              \
+                        scalar = (float)func(leftfuncast left->ex_flt,  \
+                                        rightfuncast right->ex_flt);    \
+                        j = e->exp_vsize;                               \
+                        while (j--)                                     \
+                                *op++ = scalar;                         \
+                } else {                                                \
+                        optr->ex_type = ET_FLT;                         \
+                        optr->ex_flt = (float)func(leftfuncast left->ex_flt,  \
+                                        rightfuncast right->ex_flt);    \
+                }                                                       \
+                break;                                                  \
+        case ET_VEC:                                                    \
+        case ET_VI:                                                     \
+                if (optr->ex_type != ET_VEC) {                          \
+                        if (optr->ex_type == ET_VI) {                   \
+                                post("expr~: Int. error %d", __LINE__); \
+                                abort();                                \
+                        }                                               \
+                        optr->ex_type = ET_VEC;                         \
+                        optr->ex_vec = (t_float *)                      \
+                          fts_malloc(sizeof (t_float) * e->exp_vsize);\
+                }                                                       \
+                scalar = left->ex_flt;                                  \
+                rp = right->ex_vec;                                     \
+                op = optr->ex_vec;                                      \
+                j = e->exp_vsize;                                       \
+                while (j--) {                                           \
+                        *op++ = (float)func(leftfuncast scalar,         \
+                                                rightfuncast *rp);      \
+                        rp++;                                           \
+                }                                                       \
+                break;                                                  \
+        case ET_SYM:                                                    \
+        default:                                                        \
+                post_error((fts_object_t *) e,                  \
+                      "expr: FUNC_EVAL(%d): bad right type %ld\n",      \
+                                              __LINE__, right->ex_type);\
+        }                                                               \
+        break;                                                          \
+case ET_VEC:                                                            \
+case ET_VI:                                                             \
+        if (optr->ex_type != ET_VEC) {                                  \
+                if (optr->ex_type == ET_VI) {                           \
+                        post("expr~: Int. error %d", __LINE__);         \
+                        abort();                                        \
+                }                                                       \
+                optr->ex_type = ET_VEC;                                 \
+                optr->ex_vec = (t_float *)                              \
+                  fts_malloc(sizeof (t_float) * e->exp_vsize);  \
+        }                                                               \
+        op = optr->ex_vec;                                              \
+        lp = left->ex_vec;                                              \
+        switch(right->ex_type) {                                        \
+        case ET_INT:                                                    \
+                scalar = right->ex_int;                                 \
+                j = e->exp_vsize;                                       \
+                while (j--) {                                           \
+                        *op++ = (float)func(leftfuncast *lp,            \
+                                                rightfuncast scalar);   \
+                        lp++;                                           \
+                }                                                       \
+                break;                                                  \
+        case ET_FLT:                                                    \
+                scalar = right->ex_flt;                                 \
+                j = e->exp_vsize;                                       \
+                while (j--) {                                           \
+                        *op++ = (float)func(leftfuncast *lp,            \
+                                                rightfuncast scalar);   \
+                        lp++;                                           \
+                }                                                       \
+                break;                                                  \
+        case ET_VEC:                                                    \
+        case ET_VI:                                                     \
+                rp = right->ex_vec;                                     \
+                j = e->exp_vsize;                                       \
+                while (j--) {                                           \
+                        /*                                              \
+                         * on a RISC processor one could copy           \
+                         * 8 times in each round to get a considerable  \
+                         * improvement                                  \
+                         */                                             \
+                        *op++ = (float)func(leftfuncast *lp,            \
+                                                rightfuncast *rp);      \
+                        rp++; lp++;                                     \
+                }                                                       \
+                break;                                                  \
+        case ET_SYM:                                                    \
+        default:                                                        \
+                post_error((fts_object_t *) e,                  \
+                      "expr: FUNC_EVAL(%d): bad right type %ld\n",      \
+                                              __LINE__, right->ex_type);\
+        }                                                               \
+        break;                                                          \
+case ET_SYM:                                                            \
+default:                                                                \
+                post_error((fts_object_t *) e,                  \
+                      "expr: FUNC_EVAL(%d): bad left type %ld\n",               \
+                                              __LINE__, left->ex_type); \
+}
+
+/*
+ * FUNC_EVAL_UNARY - evaluate a unary function,
+ *              if fltret is set return float
+ *              otherwise return value based on regular typechecking,
+ */
+#define FUNC_EVAL_UNARY(left, func, leftcast, optr, fltret)             \
+switch(left->ex_type) {                                         \
+case ET_INT:                                                    \
+        if (optr->ex_type == ET_VEC) {                          \
+                ex_mkvector(optr->ex_vec,                       \
+                (float)(func (leftcast left->ex_int)), e->exp_vsize);\
+                break;                                          \
+        }                                                       \
+        if (fltret) {                                           \
+                optr->ex_type = ET_FLT;                         \
+                optr->ex_flt = (float) func(leftcast left->ex_int); \
+                break;                                          \
+        }                                                       \
+        optr->ex_type = ET_INT;                                 \
+        optr->ex_int = (int) func(leftcast left->ex_int);       \
+        break;                                                  \
+case ET_FLT:                                                    \
+        if (optr->ex_type == ET_VEC) {                          \
+                ex_mkvector(optr->ex_vec,                       \
+                (float)(func (leftcast left->ex_flt)), e->exp_vsize);\
+                break;                                          \
+        }                                                       \
+        optr->ex_type = ET_FLT;                                 \
+        optr->ex_flt = (float) func(leftcast left->ex_flt);     \
+        break;                                                  \
+case ET_VI:                                                     \
+case ET_VEC:                                                    \
+        if (optr->ex_type != ET_VEC) {                          \
+                optr->ex_type = ET_VEC;                         \
+                optr->ex_vec = (t_float *)                      \
+                  fts_malloc(sizeof (t_float)*e->exp_vsize);    \
+        }                                                       \
+        op = optr->ex_vec;                                      \
+        lp = left->ex_vec;                                      \
+        j = e->exp_vsize;                                       \
+        while (j--)                                             \
+                *op++ = (float)(func (leftcast *lp++));         \
+        break;                                                  \
+default:                                                        \
+        post_error((fts_object_t *) e,                          \
+                "expr: FUNV_EVAL_UNARY(%d): bad left type %ld\n",\
+                                      __LINE__, left->ex_type); \
+}
+
+#undef min
+#undef max
+#define min(x,y)        (x > y ? y : x)
+#define max(x,y)        (x > y ? x : y)
+
+#define FUNC_DEF(ex_func, func, castleft, castright, fltret);                   \
+static void                                                             \
+ex_func(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr)\
+{                                                                       \
+        struct ex_ex *left, *right;                                     \
+        float *op; /* output pointer */                                 \
+        float *lp, *rp;         /* left and right vector pointers */    \
+        float scalar;                                                   \
+        int j;                                                          \
+                                                                        \
+        left = argv++;                                                  \
+        right = argv;                                                   \
+        FUNC_EVAL(left, right, func, castleft, castright, optr, fltret); \
+}
+
+
+#define FUNC_DEF_UNARY(ex_func, func, cast, fltret);                    \
+static void                                                             \
+ex_func(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr)\
+{                                                                       \
+        struct ex_ex *left;                                             \
+        float *op; /* output pointer */                                 \
+        float *lp, *rp;         /* left and right vector pointers */    \
+        float scalar;                                                   \
+        int j;                                                          \
+                                                                        \
+        left = argv++;                                                  \
+                                                                        \
+        FUNC_EVAL_UNARY(left, func, cast, optr, fltret);                \
+}
+
+/*
+ * ex_min -- if any of the arguments are or the output are vectors, a vector
+ *           of floats is generated otherwise the type of the result is the
+ *           type of the smaller value
+ */
+static void
+ex_min(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr)
+{
+        struct ex_ex *left, *right;
+        float *op; /* output pointer */
+        float *lp, *rp;         /* left and right vector pointers */
+        float scalar;
+        int j;
+
+        left = argv++;
+        right = argv;
+
+        FUNC_EVAL(left, right, min, (double), (double), optr, 0);
+}
+
+/*
+ * ex_max -- if any of the arguments are or the output are vectors, a vector
+ *           of floats is generated otherwise the type of the result is the
+ *           type of the larger value
+ */
+static void
+ex_max(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr)
+{
+        struct ex_ex *left, *right;
+        float *op; /* output pointer */
+        float *lp, *rp;         /* left and right vector pointers */
+        float scalar;
+        int j;
+
+        left = argv++;
+        right = argv;
+
+        FUNC_EVAL(left, right, max, (double), (double), optr, 0);
+}
+
+/*
+ * ex_toint -- convert to integer
+ */
+static void
+ex_toint(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr)
+{
+        struct ex_ex *left;
+        float *op; /* output pointer */
+        float *lp, *rp;         /* left and right vector pointers */
+        float scalar;
+        int j;
+
+        left = argv++;
+
+#define toint(x)        ((int)(x))
+                FUNC_EVAL_UNARY(left, toint, (int), optr, 0);
+        }
+
+#ifdef _WIN32
+/* No rint in NT land ??? */
+double rint(double x);
+
+double
+rint(double x)
+{
+        return (floor(x + 0.5));
+}
+#endif
+
+/*
+ * ex_rint -- rint() round to the nearest int according to the common
+ *            rounding mechanism
+ */
+static void
+ex_rint(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr)
+{
+        struct ex_ex *left;
+        float *op; /* output pointer */
+        float *lp, *rp;         /* left and right vector pointers */
+        float scalar;
+        int j;
+
+        left = argv++;
+
+
+        FUNC_EVAL_UNARY(left, rint, (double), optr, 1);
+}
+
+/*
+ * ex_tofloat -- convert to float
+ */
+static void
+ex_tofloat(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr)
+{
+        struct ex_ex *left;
+        float *op; /* output pointer */
+        float *lp, *rp;         /* left and right vector pointers */
+        float scalar;
+        int j;
+
+        left = argv++;
+
+#define tofloat(x)      ((float)(x))
+        FUNC_EVAL_UNARY(left, tofloat, (int), optr, 1);
+}
+
+
+/*
+ * ex_pow -- the power of
+ */
+static void
+ex_pow(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr)
+{
+        struct ex_ex *left, *right;
+        float *op; /* output pointer */
+        float *lp, *rp;         /* left and right vector pointers */
+        float scalar;
+        int j;
+
+        left = argv++;
+        right = argv;
+        FUNC_EVAL(left, right, pow, (double), (double), optr, 1);
+}
+
+/*
+ * ex_sqrt -- square root
+ */
+static void
+ex_sqrt(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr)
+{
+        struct ex_ex *left;
+        float *op; /* output pointer */
+        float *lp, *rp;         /* left and right vector pointers */
+        float scalar;
+        int j;
+
+        left = argv++;
+
+        FUNC_EVAL_UNARY(left, sqrt, (double), optr, 1);
+}
+
+/*
+ * ex_exp -- e to the power of
+ */
+static void
+ex_exp(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr)
+{
+        struct ex_ex *left;
+        float *op; /* output pointer */
+        float *lp, *rp;         /* left and right vector pointers */
+        float scalar;
+        int j;
+
+        left = argv++;
+
+        FUNC_EVAL_UNARY(left, exp, (double), optr, 1);
+}
+
+/*
+ * ex_log -- 10 based logarithm
+ */
+static void
+ex_log(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr)
+{
+        struct ex_ex *left;
+        float *op; /* output pointer */
+        float *lp, *rp;         /* left and right vector pointers */
+        float scalar;
+        int j;
+
+        left = argv++;
+
+        FUNC_EVAL_UNARY(left, log10, (double), optr, 1);
+}
+
+/*
+ * ex_ln -- natural log
+ */
+static void
+ex_ln(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr)
+{
+        struct ex_ex *left;
+        float *op; /* output pointer */
+        float *lp, *rp;         /* left and right vector pointers */
+        float scalar;
+        int j;
+
+        left = argv++;
+
+        FUNC_EVAL_UNARY(left, log, (double), optr, 1);
+}
+
+static void
+ex_sin(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr)
+{
+        struct ex_ex *left;
+        float *op; /* output pointer */
+        float *lp, *rp;         /* left and right vector pointers */
+        float scalar;
+        int j;
+
+        left = argv++;
+
+        FUNC_EVAL_UNARY(left, sin, (double), optr, 1);
+}
+
+static void
+ex_cos(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr)
+{
+        struct ex_ex *left;
+        float *op; /* output pointer */
+        float *lp, *rp;         /* left and right vector pointers */
+        float scalar;
+        int j;
+
+        left = argv++;
+
+        FUNC_EVAL_UNARY(left, cos, (double), optr, 1);
+}
+
+
+static void
+ex_tan(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr)
+{
+        struct ex_ex *left;
+        float *op; /* output pointer */
+        float *lp, *rp;         /* left and right vector pointers */
+        float scalar;
+        int j;
+
+        left = argv++;
+
+        FUNC_EVAL_UNARY(left, tan, (double), optr, 1);
+}
+
+static void
+ex_asin(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr)
+{
+        struct ex_ex *left;
+        float *op; /* output pointer */
+        float *lp, *rp;         /* left and right vector pointers */
+        float scalar;
+        int j;
+
+        left = argv++;
+
+        FUNC_EVAL_UNARY(left, asin, (double), optr, 1);
+}
+
+static void
+ex_acos(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr)
+{
+        struct ex_ex *left;
+        float *op; /* output pointer */
+        float *lp, *rp;         /* left and right vector pointers */
+        float scalar;
+        int j;
+
+        left = argv++;
+
+        FUNC_EVAL_UNARY(left, acos, (double), optr, 1);
+}
+
+
+static void
+ex_atan(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr)
+{
+        struct ex_ex *left;
+        float *op; /* output pointer */
+        float *lp, *rp;         /* left and right vector pointers */
+        float scalar;
+        int j;
+
+        left = argv++;
+
+        FUNC_EVAL_UNARY(left, atan, (double), optr, 1);
+}
+
+/*
+ *ex_atan2 --
+ */
+static void
+ex_atan2(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr)
+{
+        struct ex_ex *left, *right;
+        float *op; /* output pointer */
+        float *lp, *rp;         /* left and right vector pointers */
+        float scalar;
+        int j;
+
+        left = argv++;
+        right = argv;
+        FUNC_EVAL(left, right, atan2, (double), (double), optr, 1);
+}
+
+/*
+ * ex_fmod -- floating point modulo
+ */
+static void
+ex_fmod(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr)
+{
+        struct ex_ex *left, *right;
+        float *op; /* output pointer */
+        float *lp, *rp;         /* left and right vector pointers */
+        float scalar;
+        int j;
+
+        left = argv++;
+        right = argv;
+        FUNC_EVAL(left, right, fmod, (double), (double), optr, 1);
+}
+
+
+/*
+ * ex_floor -- floor
+ */
+static void
+ex_floor(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr)
+{
+        struct ex_ex *left;
+        float *op; /* output pointer */
+        float *lp, *rp;         /* left and right vector pointers */
+        float scalar;
+        int j;
+
+        left = argv++;
+        FUNC_EVAL_UNARY(left, floor, (double), optr, 1);
+}
+
+
+/*
+ * ex_ceil -- ceil
+ */
+static void
+ex_ceil(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr)
+{
+        struct ex_ex *left;
+        float *op; /* output pointer */
+        float *lp, *rp;         /* left and right vector pointers */
+        float scalar;
+        int j;
+
+        left = argv++;
+        FUNC_EVAL_UNARY(left, ceil, (double), optr, 1);
+}
+
+static void
+ex_sinh(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr)
+{
+        struct ex_ex *left;
+        float *op; /* output pointer */
+        float *lp, *rp;         /* left and right vector pointers */
+        float scalar;
+        int j;
+
+        left = argv++;
+
+        FUNC_EVAL_UNARY(left, sinh, (double), optr, 1);
+}
+
+static void
+ex_cosh(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr)
+{
+        struct ex_ex *left;
+        float *op; /* output pointer */
+        float *lp, *rp;         /* left and right vector pointers */
+        float scalar;
+        int j;
+
+        left = argv++;
+
+        FUNC_EVAL_UNARY(left, cosh, (double), optr, 1);
+}
+
+
+static void
+ex_tanh(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr)
+{
+        struct ex_ex *left;
+        float *op; /* output pointer */
+        float *lp, *rp;         /* left and right vector pointers */
+        float scalar;
+        int j;
+
+        left = argv++;
+
+        FUNC_EVAL_UNARY(left, tanh, (double), optr, 1);
+}
+
+
+#ifndef _WIN32
+static void
+ex_asinh(t_expr *e, long argc, struct ex_ex *argv, struct ex_ex *optr)
+{
+        struct ex_ex *left;
+        float *op; /* output pointer */
+        float *lp, *rp;         /* left and right vector pointers */
+        float scalar;
+        int j;
+
+        left = argv++;
+
+        FUNC_EVAL_UNARY(left, asinh, (double), optr, 1);
+}
+
+static void
+ex_acosh(t_expr *e, long argc, struct ex_ex *argv, struct ex_ex *optr)
+{
+        struct ex_ex *left;
+        float *op; /* output pointer */
+        float *lp, *rp;         /* left and right vector pointers */
+        float scalar;
+        int j;
+
+        left = argv++;
+
+        FUNC_EVAL_UNARY(left, acosh, (double), optr, 1);
+}
+
+static void
+ex_atanh(t_expr *e, long argc, struct ex_ex *argv, struct ex_ex *optr)
+{
+        struct ex_ex *left;
+        float *op; /* output pointer */
+        float *lp, *rp;         /* left and right vector pointers */
+        float scalar;
+        int j;
+
+        left = argv++;
+
+        FUNC_EVAL_UNARY(left, atanh, (double), optr, 1);
+}
+#endif
+
+static int
+ex_dofact(int i)
+{
+        int ret = 0;
+
+        if (i)
+                ret = 1;
+        else
+                return (0);
+
+        do {
+                ret *= i;
+        } while (--i);
+
+        return(ret);
+}
+
+static void
+ex_fact(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr)
+{
+        struct ex_ex *left;
+        float *op; /* output pointer */
+        float *lp, *rp;         /* left and right vector pointers */
+        float scalar;
+        int j;
+
+        left = argv++;
+
+        FUNC_EVAL_UNARY(left, ex_dofact,  (int), optr, 0);
+}
+
+static int
+ex_dorandom(int i1, int i2)
+{
+        return(i1 + (((i2 - i1) * (rand() & 0x7fffL)) >> 15));
+}
+/*
+ * ex_random -- return a random number
+ */
+static void
+ex_random(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr)
+{
+        struct ex_ex *left, *right;
+        float *op; /* output pointer */
+        float *lp, *rp;         /* left and right vector pointers */
+        float scalar;
+        int j;
+
+        left = argv++;
+        right = argv;
+        FUNC_EVAL(left, right, ex_dorandom, (int), (int), optr, 0);
+}
+
+
+static void
+ex_abs(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr)
+{
+        struct ex_ex *left;
+        float *op; /* output pointer */
+        float *lp, *rp;         /* left and right vector pointers */
+        float scalar;
+        int j;
+
+        left = argv++;
+
+        FUNC_EVAL_UNARY(left, fabs, (double), optr, 0);
+}
+
+/*
+ *ex_if -- floating point modulo
+ */
+static void
+ex_if(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr)
+{
+        struct ex_ex *left, *right, *cond, *res;
+        float *op; /* output pointer */
+        float *lp, *rp;         /* left and right vector pointers */
+        float *cp;              /* condition pointer */
+        float leftvalue, rightvalue;
+        int j;
+
+        cond = argv++;
+        left = argv++;
+        right = argv;
+
+        switch (cond->ex_type) {
+        case ET_VEC:
+        case ET_VI:
+                if (optr->ex_type != ET_VEC) {
+                        if (optr->ex_type == ET_VI) {
+                                /* SDY remove this test */
+                                post("expr~: Int. error %d", __LINE__);
+                                return;
+                        }
+                                optr->ex_type = ET_VEC;
+                                optr->ex_vec = (t_float *)
+                                  fts_malloc(sizeof (t_float) * e->exp_vsize);
+                }
+                op = optr->ex_vec;
+                j = e->exp_vsize;
+                cp = cond->ex_vec;
+                switch (left->ex_type) {
+                case ET_INT:
+                        leftvalue = left->ex_int;
+                        switch (right->ex_type) {
+                        case ET_INT:
+                                rightvalue = right->ex_int;
+                                while (j--) {
+                                        if (*cp++)
+                                                *op++ = leftvalue;
+                                        else
+                                                *op++ = rightvalue;
+                                }
+                        return;
+                        case ET_FLT:
+                                rightvalue = right->ex_flt;
+                                while (j--) {
+                                        if (*cp++)
+                                                *op++ = leftvalue;
+                                        else
+                                                *op++ = rightvalue;
+                                }
+                                return;
+                        case ET_VEC:
+                        case ET_VI:
+                                rp = right->ex_vec;
+                                while (j--) {
+                                        if (*cp++)
+                                                *op++ = leftvalue;
+                                        else
+                                                *op++ = *rp;
+                                        rp++;
+                                }
+                                return;
+                        case ET_SYM:
+                        default:
+                                post_error((fts_object_t *) e,
+                              "expr: FUNC_EVAL(%d): bad right type %ld\n",
+                                                      __LINE__, right->ex_type);
+                                return;
+                        }
+                case ET_FLT:
+                        leftvalue = left->ex_flt;
+                        switch (right->ex_type) {
+                        case ET_INT:
+                                rightvalue = right->ex_int;
+                                while (j--) {
+                                        if (*cp++)
+                                                *op++ = leftvalue;
+                                        else
+                                                *op++ = rightvalue;
+                                }
+                                return;
+                        case ET_FLT:
+                                rightvalue = right->ex_flt;
+                                while (j--) {
+                                        if (*cp++)
+                                                *op++ = leftvalue;
+                                        else
+                                                *op++ = rightvalue;
+                                }
+                                return;
+                        case ET_VEC:
+                        case ET_VI:
+                                rp = right->ex_vec;
+                                while (j--) {
+                                        if (*cp++)
+                                                *op++ = leftvalue;
+                                        else
+                                                *op++ = *rp;
+                                        rp++;
+                                }
+                                return;
+                        case ET_SYM:
+                        default:
+                                post_error((fts_object_t *) e,
+                              "expr: FUNC_EVAL(%d): bad right type %ld\n",
+                                                      __LINE__, right->ex_type);
+                                return;
+                        }
+                case ET_VEC:
+                case ET_VI:
+                        lp = left->ex_vec;
+                        switch (right->ex_type) {
+                        case ET_INT:
+                                rightvalue = right->ex_int;
+                                while (j--) {
+                                        if (*cp++)
+                                                *op++ = *lp;
+                                        else
+                                                *op++ = rightvalue;
+                                        lp++;
+                                }
+                                return;
+                        case ET_FLT:
+                                rightvalue = right->ex_flt;
+                                while (j--) {
+                                        if (*cp++)
+                                                *op++ = *lp;
+                                        else
+                                                *op++ = rightvalue;
+                                        lp++;
+                                }
+                                return;
+                        case ET_VEC:
+                        case ET_VI:
+                                rp = right->ex_vec;
+                                while (j--) {
+                                        if (*cp++)
+                                                *op++ = *lp;
+                                        else
+                                                *op++ = *rp;
+                                        lp++; rp++;
+                                }
+                                return;
+                        case ET_SYM:
+                        default:
+                                post_error((fts_object_t *) e,
+                              "expr: FUNC_EVAL(%d): bad right type %ld\n",
+                                                      __LINE__, right->ex_type);
+                                return;
+                        }
+                case ET_SYM:
+                default:
+                        post_error((fts_object_t *) e,
+                      "expr: FUNC_EVAL(%d): bad left type %ld\n",
+                                              __LINE__, left->ex_type);
+                        return;
+                }
+        case ET_INT:
+                if (cond->ex_int)
+                        res = left;
+                else
+                        res = right;
+                break;
+        case ET_FLT:
+                if (cond->ex_flt)
+                        res = left;
+                else
+                        res = right;
+                break;
+        case ET_SYM:
+        default:
+                post_error((fts_object_t *) e,
+              "expr: FUNC_EVAL(%d): bad condition type %ld\n",
+                                      __LINE__, cond->ex_type);
+                return;
+        }
+        switch(res->ex_type) {
+        case ET_INT:
+                if (optr->ex_type == ET_VEC) {
+                        ex_mkvector(optr->ex_vec, (float)res->ex_int,
+                                                                e->exp_vsize);
+                        return;
+                }
+                *optr = *res;
+                return;
+        case ET_FLT:
+                if (optr->ex_type == ET_VEC) {
+                        ex_mkvector(optr->ex_vec, (float)res->ex_flt,
+                                                                e->exp_vsize);
+                        return;
+                }
+                *optr = *res;
+                return;
+        case ET_VEC:
+        case ET_VI:
+                if (optr->ex_type != ET_VEC) {
+                        if (optr->ex_type == ET_VI) {
+                                /* SDY remove this test */
+                                post("expr~: Int. error %d", __LINE__);
+                                return;
+                        }
+                                optr->ex_type = ET_VEC;
+                                optr->ex_vec = (t_float *)
+                                  fts_malloc(sizeof (t_float) * e->exp_vsize);
+                }
+                memcpy(optr->ex_vec, res->ex_vec, e->exp_vsize*sizeof(t_float));
+                return;
+        case ET_SYM:
+        default:
+                post_error((fts_object_t *) e,
+              "expr: FUNC_EVAL(%d): bad res type %ld\n",
+                                      __LINE__, res->ex_type);
+                return;
+        }
+        
+}
+
+/*
+ * ex_imodf -   extract signed integral value from floating-point number
+ */
+static double
+imodf(double x)
+{
+        double  xx;
+
+        modf(x, &xx);
+        return (xx);
+}
+FUNC_DEF_UNARY(ex_imodf, imodf, (double), 1);
+
+/*
+ * ex_modf - extract signed  fractional value from floating-point number
+ *
+ *  using fracmodf because fmodf() is alrady defined in a .h file
+ */
+static double
+fracmodf(double x)
+{
+        double  xx;
+
+        return(modf(x, &xx));
+}
+FUNC_DEF_UNARY(ex_modf, fracmodf, (double), 1);
+
+/*
+ * ex_ldexp  -  multiply floating-point number by integral power of 2
+ */
+FUNC_DEF(ex_ldexp, ldexp, (double), (int), 1);
+
+#ifndef _WIN32
+/*
+ * ex_cbrt - cube root
+ */
+FUNC_DEF_UNARY(ex_cbrt, cbrt, (double), 1);
+
+/*
+ * ex_erf - error function
+ */
+FUNC_DEF_UNARY(ex_erf, erf, (double), 1);
+
+/*
+ * ex_erfc - complementary error function
+ */
+FUNC_DEF_UNARY(ex_erfc, erfc, (double), 1);
+
+/*
+ * ex_expm1 - exponential minus 1,
+ */
+FUNC_DEF_UNARY(ex_expm1, expm1, (double), 1);
+
+/*
+ * ex_log1p - logarithm of 1 plus
+ */
+FUNC_DEF_UNARY(ex_log1p, log1p, (double), 1);
+
+/*
+ * ex_isinf - is the value infinite,
+ */
+FUNC_DEF_UNARY(ex_isinf, isinf, (double), 0);
+
+/*
+ * ex_finite - is the value finite
+ */
+FUNC_DEF_UNARY(ex_finite, finite, (double), 0);
+
+/*
+ * ex_isnan -- is the resut a nan (Not a number)
+ */
+FUNC_DEF_UNARY(ex_isnan, isnan, (double), 0);
+
+/*
+ * ex_copysign - copy sign of a number
+ */
+FUNC_DEF(ex_copysign, copysign, (double), (double), 1);
+
+/*
+ * ex_drem - floating-point remainder function
+ */
+FUNC_DEF(ex_drem, drem, (double), (double), 1);
+#endif
+
+#ifdef notdef
+/* the following will be added once they are more popular in math libraries */
+/*
+ * ex_hypoth - Euclidean distance function
+ */
+FUNC_DEF(ex_hypoth, hypoth, (double), (double), 1);
+
+/*
+ * ex_round -  round to nearest integer, away from zero
+ */
+FUNC_DEF_UNARY(ex_round, round, (double), 1);
+
+/*
+ * ex_trunc -  round to interger, towards zero
+ */
+FUNC_DEF_UNARY(ex_trunc, trunc, (double), 1);
+
+/*
+ * ex_nearbyint -  round to nearest integer
+ */
+FUNC_DEF_UNARY(ex_nearbyint, nearbyint, (double), 1);
+#endif
diff --git a/extra/expr~/vexp_if.c b/extra/expr~/vexp_if.c
new file mode 100644
index 0000000000000000000000000000000000000000..648aba73235579fbb999b44ca72229f3a2726764
--- /dev/null
+++ b/extra/expr~/vexp_if.c
@@ -0,0 +1,1225 @@
+/*
+ * jMax
+ * Copyright (C) 1994, 1995, 1998, 1999 by IRCAM-Centre Georges Pompidou, Paris, France.
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * See file LICENSE for further informations on licensing terms.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * 
+ * Based on Max/ISPW by Miller Puckette.
+ *
+ * Authors: Maurizio De Cecco, Francois Dechelle, Enzo Maggi, Norbert Schnell.
+ *
+ */
+
+/* "expr" was written by Shahrokh Yadegari c. 1989. -msp */
+/* "expr~" and "fexpr~" conversion by Shahrokh Yadegari c. 1999,2000 */
+
+/*
+ * Feb 2002 - added access to variables
+ *            multiple expression support
+ *            new short hand forms for fexpr~
+ *              now $y or $y1 = $y1[-1] and $y2 = $y2[-1]
+ * --sdy
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "vexp.h"
+
+static char *exp_version = "0.4";
+
+extern struct ex_ex *ex_eval(struct expr *expr, struct ex_ex *eptr,
+                                                struct ex_ex *optr, int n);
+
+#ifdef PD
+static t_class *expr_class;
+static t_class *expr_tilde_class;
+static t_class *fexpr_tilde_class;
+#else /* MSP */
+void *expr_tilde_class;
+#endif
+
+
+/*------------------------- expr class -------------------------------------*/
+
+extern int expr_donew(struct expr *expr, int ac, t_atom *av);
+
+/*#define EXPR_DEBUG*/
+
+static void expr_bang(t_expr *x);
+t_int *expr_perform(t_int *w);
+
+
+static void
+expr_list(t_expr *x, t_symbol *s, int argc, const fts_atom_t *argv)
+{
+        int i;
+
+        if (argc > MAX_VARS) argc = MAX_VARS;
+
+        for (i = 0; i < argc; i++)
+        {
+                if (argv[i].a_type == A_FLOAT)
+                {
+                        if (x->exp_var[i].ex_type == ET_FI)
+                                x->exp_var[i].ex_flt = argv[i].a_w.w_float;
+                        else if (x->exp_var[i].ex_type == ET_II)
+                                x->exp_var[i].ex_int = argv[i].a_w.w_float;
+                        else if (x->exp_var[i].ex_type)
+                            pd_error(x, "expr: type mismatch");
+                }
+                else if (argv[i].a_type == A_SYMBOL)
+                {
+                        if (x->exp_var[i].ex_type == ET_SI)
+                                x->exp_var[i].ex_ptr = (char *)argv[i].a_w.w_symbol;
+                        else if (x->exp_var[i].ex_type)
+                            pd_error(x, "expr: type mismatch");
+                }
+        }
+        expr_bang(x);
+}
+
+static void
+expr_flt(t_expr *x, t_float f, int in)
+{
+        if (in > MAX_VARS)
+                return;
+
+        if (x->exp_var[in].ex_type == ET_FI)
+                x->exp_var[in].ex_flt = f;
+        else if (x->exp_var[in].ex_type == ET_II)
+                x->exp_var[in].ex_int = f;
+}
+
+static t_class *exprproxy_class;
+
+typedef struct _exprproxy {
+        t_pd p_pd;
+        int p_index;
+        t_expr *p_owner;
+        struct _exprproxy *p_next;
+} t_exprproxy;
+
+t_exprproxy *exprproxy_new(t_expr *owner, int indx);
+void exprproxy_float(t_exprproxy *p, t_floatarg f);
+
+t_exprproxy *
+exprproxy_new(t_expr *owner, int indx)
+{
+        t_exprproxy *x = (t_exprproxy *)pd_new(exprproxy_class);
+        x->p_owner = owner;
+        x->p_index = indx;
+        x->p_next = owner->exp_proxy;
+        owner->exp_proxy = x;
+        return (x);
+}
+
+void
+exprproxy_float(t_exprproxy *p, t_floatarg f)
+{
+        t_expr *x = p->p_owner;
+        int in = p->p_index;
+
+        if (in > MAX_VARS)
+                return;
+
+        if (x->exp_var[in].ex_type == ET_FI)
+                x->exp_var[in].ex_flt = f;
+        else if (x->exp_var[in].ex_type == ET_II)
+                x->exp_var[in].ex_int = f;
+}
+
+/* method definitions */
+static void
+expr_ff(t_expr *x)
+{
+        t_exprproxy *y;
+        int i;
+        
+        y = x->exp_proxy;
+        while (y)
+        {
+                x->exp_proxy = y->p_next;
+#ifdef PD
+                pd_free(&y->p_pd);
+#else /*MSP */
+        /* SDY find out what needs to be called for MSP */
+
+#endif
+                y = x->exp_proxy;
+        }
+        for (i = 0 ; i < x->exp_nexpr; i++);
+                if (x->exp_stack[i])
+                        fts_free(x->exp_stack[i]);
+/*
+ * SDY free all the allocated buffers here for expr~ and fexpr~
+ * check to see if there are others
+ */
+        for (i = 0; i < MAX_VARS; i++) {
+                if (x->exp_p_var[i])
+                        fts_free(x->exp_p_var[i]);
+                if (x->exp_p_res[i])
+                        fts_free(x->exp_p_res[i]);
+                if (x->exp_tmpres[i])
+                        fts_free(x->exp_tmpres[i]);
+        }
+
+
+}
+
+static void
+expr_bang(t_expr *x)
+{
+        int i;
+
+#ifdef EXPR_DEBUG
+        {
+                struct ex_ex *eptr;
+
+                for (i = 0, eptr = x->exp_var;  ; eptr++, i++)
+                {
+                        if (!eptr->ex_type)
+                                break;
+                        switch (eptr->ex_type)
+                        {
+                        case ET_II:
+                                fprintf(stderr,"ET_II: %d \n", eptr->ex_int);
+                                break;
+
+                        case ET_FI:
+                                fprintf(stderr,"ET_FT: %f \n", eptr->ex_flt);
+                                break;
+
+                        default:
+                                fprintf(stderr,"oups\n");
+                        }
+                }
+        }
+#endif
+        /* banging a signal or filter object means nothing */
+        if (!IS_EXPR(x))
+                return;
+
+        for (i = x->exp_nexpr - 1; i > -1 ; i--) {
+                if (!ex_eval(x, x->exp_stack[i], &x->exp_res[i], 0)) {
+                        /*fprintf(stderr,"expr_bang(error evaluation)\n"); */
+                /*  SDY now that we have mutiple ones, on error we should
+                 * continue
+                        return;
+                 */
+                }
+                switch(x->exp_res[i].ex_type) {
+                case ET_INT:
+                        outlet_float(x->exp_outlet[i], 
+                                        (t_float) x->exp_res[i].ex_int);
+                        break;
+
+                case ET_FLT:
+                        outlet_float(x->exp_outlet[i],  x->exp_res[i].ex_flt);
+                        break;
+
+                case ET_SYM:
+                        /* CHANGE this will have to be taken care of */
+
+                default:
+                        post("expr: bang: unrecognized result %ld\n", x->exp_res[i].ex_type);
+                }
+        }
+}
+
+static t_expr *
+#ifdef PD
+expr_new(t_symbol *s, int ac, t_atom *av)
+#else /* MSP */
+Nexpr_new(t_symbol *s, int ac, t_atom *av)
+#endif
+{
+        struct expr *x;
+        int i, ninlet;
+        struct ex_ex *eptr;
+        t_atom fakearg;
+        int dsp_index;  /* keeping track of the dsp inlets */
+
+
+/*
+ * SDY - we may need to call dsp_setup() in this function
+ */
+
+        if (!ac)
+        {
+                ac = 1;
+                av = &fakearg;
+                SETFLOAT(&fakearg, 0);
+        }
+
+#ifdef PD
+        /*
+         * figure out if we are expr, expr~, or fexpr~
+         */
+        if (!strcmp("expr", s->s_name)) {
+                x = (t_expr *)pd_new(expr_class);
+                SET_EXPR(x);
+        } else if (!strcmp("expr~", s->s_name)) {
+                x = (t_expr *)pd_new(expr_tilde_class);
+                SET_EXPR_TILDE(x);
+        } else if (!strcmp("fexpr~", s->s_name)) {
+                x = (t_expr *)pd_new(fexpr_tilde_class);
+                SET_FEXPR_TILDE(x);
+        } else {
+                post("expr_new: bad object name '%s'");
+                /* assume expr */
+                x = (t_expr *)pd_new(expr_class);
+                SET_EXPR(x);
+        }
+#else /* MSP */
+        /* for now assume an expr~ */
+        x = (t_expr *)pd_new(expr_tilde_class);
+        SET_EXPR_TILDE(x);
+#endif          
+        
+        /*
+         * initialize the newly allocated object
+         */
+        x->exp_proxy = 0;
+        x->exp_nivec = 0;
+        x->exp_nexpr = 0;
+        x->exp_error = 0;
+        for (i = 0; i < MAX_VARS; i++) {
+                x->exp_stack[i] = (struct ex_ex *)0;
+                x->exp_outlet[i] = (t_outlet *)0;
+                x->exp_res[i].ex_type = 0;
+                x->exp_res[i].ex_int = 0;
+                x->exp_p_res[i] = (t_float *)0;
+                x->exp_var[i].ex_type = 0;
+                x->exp_var[i].ex_int = 0;
+                x->exp_p_var[i] = (t_float *)0;
+                x->exp_tmpres[i] = (t_float *)0;
+                x->exp_vsize = 0;
+        }
+        x->exp_f = 0; /* save the control value to be transformed to signal */
+                
+
+        if (expr_donew(x, ac, av))
+        {
+                pd_error(x, "expr: syntax error");
+/*
+SDY the following coredumps why?
+                pd_free(&x->exp_ob.ob_pd);
+*/
+                return (0);
+        }
+
+        ninlet = 1;
+        for (i = 0, eptr = x->exp_var; i < MAX_VARS ; i++, eptr++)
+                if (eptr->ex_type) {
+                        ninlet = i + 1;
+                }
+
+        /*
+         * create the new inlets
+         */
+        for (i = 1, eptr = x->exp_var + 1, dsp_index=1; i<ninlet ; i++, eptr++)
+        {
+                t_exprproxy *p;
+                switch (eptr->ex_type)
+                {
+                case 0:
+                        /* nothing is using this inlet */
+                        if (i < ninlet)
+#ifdef PD
+                                floatinlet_new(&x->exp_ob, &eptr->ex_flt);
+#else /* MSP */
+                                inlet_new(&x->exp_ob, "float");
+#endif
+                        break;
+
+                case ET_II:
+                case ET_FI:
+                        p = exprproxy_new(x, i);
+#ifdef PD
+                        inlet_new(&x->exp_ob, &p->p_pd, &s_float, &s_float);
+#else /* MSP */
+                        inlet_new(&x->exp_ob, "float");
+#endif
+                        break;
+
+                case ET_SI:
+#ifdef PD
+                        symbolinlet_new(&x->exp_ob, (t_symbol **)&eptr->ex_ptr);
+#else /* MSP */
+                        inlet_new(&x->exp_ob, "symbol");
+#endif
+                        break;
+
+                case ET_XI:
+                case ET_VI:
+                        if (!IS_EXPR(x)) {
+                                dsp_index++;
+#ifdef PD
+                                inlet_new(&x->exp_ob, &x->exp_ob.ob_pd,
+                                                        &s_signal, &s_signal);
+#else /* MSP */
+                                inlet_new(&x->exp_ob, "signal");
+#endif
+                                break;
+                        } else
+                                post("expr: internal error expr_new");
+                default:
+                        pd_error(x, "expr: bad type (%lx) inlet = %d\n",
+                                            eptr->ex_type, i + 1, 0, 0, 0);
+                        break;
+                }
+        }
+        if (IS_EXPR(x)) {
+                for (i = 0; i < x->exp_nexpr; i++)
+                        x->exp_outlet[i] = outlet_new(&x->exp_ob, 0);
+        } else {
+                for (i = 0; i < x->exp_nexpr; i++)
+                        x->exp_outlet[i] = outlet_new(&x->exp_ob,
+                                                        gensym("signal"));
+                x->exp_nivec = dsp_index;
+        }
+        /*
+         * for now assume a 64 sample size block but this may change once
+         * expr_dsp is called
+         */
+        x->exp_vsize = 64;
+        for (i = 0; i < x->exp_nexpr; i++) {
+                x->exp_p_res[i] = fts_calloc(x->exp_vsize, sizeof (t_float));
+                x->exp_tmpres[i] = fts_calloc(x->exp_vsize, sizeof (t_float));
+        }
+        for (i = 0; i < MAX_VARS; i++)
+                x->exp_p_var[i] = fts_calloc(x->exp_vsize, sizeof (t_float));
+
+        return (x);
+}
+
+t_int *
+expr_perform(t_int *w)
+{
+        int i, j;
+        t_expr *x = (t_expr *)w[1];
+        struct ex_ex res;
+        int n;
+
+        /* sanity check */
+        if (IS_EXPR(x)) {
+                post("expr_perform: bad x->exp_flags = %d", x->exp_flags);
+                abort();
+        }
+
+        if (x->exp_flags & EF_STOP) {
+                for (i = 0; i < x->exp_nexpr; i++)
+                        memset(x->exp_res[i].ex_vec, 0,
+                                        x->exp_vsize * sizeof (float));
+                return (w + 2);
+        }
+
+        if (IS_EXPR_TILDE(x)) {
+                /*
+                 * if we have only one expression, we can right on
+                 * on the output directly, otherwise we have to copy
+                 * the data because, outputs could be the same buffer as
+                 * inputs
+                 */
+                if ( x->exp_nexpr == 1)
+                        ex_eval(x, x->exp_stack[0], &x->exp_res[0], 0);
+                else {
+                        res.ex_type = ET_VEC;
+                        for (i = 0; i < x->exp_nexpr; i++) {
+                                res.ex_vec = x->exp_tmpres[i];
+                                ex_eval(x, x->exp_stack[i], &res, 0);
+                        }
+                        n = x->exp_vsize * sizeof(t_float);
+                        for (i = 0; i < x->exp_nexpr; i++)
+                                memcpy(x->exp_res[i].ex_vec, x->exp_tmpres[i],
+                                                                        n);
+                }
+                return (w + 2);
+        }
+
+        if (!IS_FEXPR_TILDE(x)) {
+                post("expr_perform: bad x->exp_flags = %d - expecting fexpr",
+                                                                x->exp_flags);
+                return (w + 2);
+        }
+        /*
+         * since the output buffer could be the same as one of the inputs
+         * we need to keep the output in  a different buffer
+         */
+        for (i = 0; i < x->exp_vsize; i++) for (j = 0; j < x->exp_nexpr; j++) {
+                res.ex_type = 0;
+                res.ex_int = 0;
+                ex_eval(x, x->exp_stack[j], &res, i);
+                switch (res.ex_type) {
+                case ET_INT:
+                        x->exp_tmpres[j][i] = (t_float) res.ex_int;
+                        break;
+                case ET_FLT:
+                        x->exp_tmpres[j][i] = res.ex_flt;
+                        break;
+                default:
+                        post("expr_perform: bad result type %d", res.ex_type);
+                }
+        }
+        /*
+         * copy inputs and results to the save buffers
+         * inputs need to be copied first as the output buffer can be
+         * same as an input buffer
+         */
+        n = x->exp_vsize * sizeof(t_float);
+        for (i = 0; i < MAX_VARS; i++)
+                if (x->exp_var[i].ex_type == ET_XI)
+                        memcpy(x->exp_p_var[i], x->exp_var[i].ex_vec, n);
+        for (i = 0; i < x->exp_nexpr; i++) {
+                memcpy(x->exp_p_res[i], x->exp_tmpres[i], n);
+                memcpy(x->exp_res[i].ex_vec, x->exp_tmpres[i], n);
+        }
+        return (w + 2);
+}
+
+static void
+expr_dsp(t_expr *x, t_signal **sp)
+{
+        int i, nv;
+        int newsize;
+
+        x->exp_error = 0;               /* reset all errors */
+        newsize = (x->exp_vsize !=  sp[0]->s_n);
+        x->exp_vsize = sp[0]->s_n;      /* record the vector size */
+        for (i = 0; i < x->exp_nexpr; i++) {
+                x->exp_res[i].ex_type = ET_VEC;
+                x->exp_res[i].ex_vec =  sp[x->exp_nivec + i]->s_vec; 
+        }
+        for (i = 0, nv = 0; i < MAX_VARS; i++)
+                /*
+                 * the first inlet is always a signal
+                 *
+                 * SDY  We are warning the user till this limitation
+                 * is taken away from pd
+                 */
+                if (!i || x->exp_var[i].ex_type == ET_VI ||
+                                        x->exp_var[i].ex_type == ET_XI) {
+                        if (nv >= x->exp_nivec) {
+                          post("expr_dsp int. err nv = %d, x->exp_nive = %d",
+                                                          nv,  x->exp_nivec);
+                          abort();
+                        }
+                        x->exp_var[i].ex_vec  = sp[nv]->s_vec;
+                        nv++;
+                }
+        /* we always have one inlet but we may not use it */
+        if (nv != x->exp_nivec && (nv != 0 ||  x->exp_nivec != 1)) {
+                post("expr_dsp internal error 2 nv = %d, x->exp_nive = %d",
+                                                          nv,  x->exp_nivec);
+                abort();
+        }
+
+        dsp_add(expr_perform, 1, (t_int *) x);
+
+        /*
+         * The buffer are now being allocated for expr~ and fexpr~
+         * because if we have more than one expression we need the
+         * temporary buffers, The save buffers are not really needed
+        if (!IS_FEXPR_TILDE(x))
+                return;
+         */
+        /*
+         * if we have already allocated the buffers and we have a 
+         * new size free all the buffers
+         */
+        if (x->exp_p_res[0]) {
+                if (!newsize)
+                        return;
+                /*
+                 * if new size, reallocate all the previous buffers for fexpr~
+                 */
+                for (i = 0; i < x->exp_nexpr; i++) {
+                        fts_free(x->exp_p_res[i]);
+                        fts_free(x->exp_tmpres[i]);
+                }
+                for (i = 0; i < MAX_VARS; i++)
+                        fts_free(x->exp_p_var[i]);
+
+        }
+        for (i = 0; i < x->exp_nexpr; i++) {
+                x->exp_p_res[i] = fts_calloc(x->exp_vsize, sizeof (t_float));
+                x->exp_tmpres[i] = fts_calloc(x->exp_vsize, sizeof (t_float));
+        }
+        for (i = 0; i < MAX_VARS; i++)
+                x->exp_p_var[i] = fts_calloc(x->exp_vsize, sizeof (t_float));
+}
+
+/*
+ * expr_verbose -- toggle the verbose switch
+ */
+static void
+expr_verbose(t_expr *x)
+{
+        if (x->exp_flags & EF_VERBOSE) {
+                x->exp_flags &= ~EF_VERBOSE;
+                post ("verbose off");
+        } else {
+                x->exp_flags |= EF_VERBOSE;
+                post ("verbose on");
+        }
+}
+
+/*
+ * expr_start -- turn on expr processing for now only used for fexpr~
+ */
+static void
+expr_start(t_expr *x)
+{
+        x->exp_flags &= ~EF_STOP;
+}
+
+/*
+ * expr_stop -- turn on expr processing for now only used for fexpr~
+ */
+static void
+expr_stop(t_expr *x)
+{
+        x->exp_flags |= EF_STOP;
+}
+static void
+fexpr_set_usage(void)
+{
+        post("fexpr~: set val ...");
+        post("fexpr~: set {xy}[#] val ...");
+}
+
+/*
+ * fexpr_tilde_set -- set previous values of the buffers
+ *              set val val ... - sets the first elements of output buffers
+ *              set x val ...   - sets the elements of the first input buffer
+ *              set x# val ...  - sets the elements of the #th input buffers
+ *              set y val ...   - sets the elements of the first output buffer
+ *              set y# val ...  - sets the elements of the #th output buffers
+ */
+static void
+fexpr_tilde_set(t_expr *x, t_symbol *s, int argc, t_atom *argv)
+{
+        t_symbol *sx;
+        int vecno;
+        int i, nargs;
+
+        if (!argc)
+                return;
+        sx = atom_getsymbolarg(0, argc, argv);
+        switch(sx->s_name[0]) {
+        case 'x':
+                if (!sx->s_name[1])
+                        vecno = 0;
+                else {
+                        vecno = atoi(sx->s_name + 1);
+                        if (!vecno) {
+                                post("fexpr~.set: bad set x vector number");
+                                fexpr_set_usage();
+                                return;
+                        }
+                        if (vecno >= MAX_VARS) {
+                                post("fexpr~.set: no more than %d inlets",
+                                                                      MAX_VARS);
+                                return;
+                        }
+                        vecno--;
+                }
+                if (x->exp_var[vecno].ex_type != ET_XI) {
+                        post("fexpr~-set: no signal at inlet %d", vecno + 1);
+                        return;
+                }
+                nargs = argc - 1;
+                if (!nargs) {
+                        post("fexpr~-set: no argument to set");
+                        return;
+                }
+                if (nargs > x->exp_vsize) {
+                   post("fexpr~.set: %d set values larger than vector size(%d)",
+                                                        nargs,  x->exp_vsize);
+                   post("fexpr~.set: only the first %d values will be set",
+                                                                x->exp_vsize);
+                   nargs = x->exp_vsize;
+                }
+                for (i = 0; i < nargs; i++) {
+                        x->exp_p_var[vecno][x->exp_vsize - i - 1] =
+                                        atom_getfloatarg(i + 1, argc, argv);
+                }
+                return;
+        case 'y':
+                if (!sx->s_name[1])
+                        vecno = 0;
+                else {
+                        vecno = atoi(sx->s_name + 1);
+                        if (!vecno) {
+                                post("fexpr~.set: bad set y vector number");
+                                fexpr_set_usage();
+                                return;
+                        }
+                        vecno--;
+                }
+                if (vecno >= x->exp_nexpr) {
+                        post("fexpr~.set: only %d outlets", x->exp_nexpr);
+                        return;
+                }
+                nargs = argc - 1;
+                if (!nargs) {
+                        post("fexpr~-set: no argument to set");
+                        return;
+                }
+                if (nargs > x->exp_vsize) {
+                   post("fexpr~-set: %d set values larger than vector size(%d)",
+                                                        nargs,  x->exp_vsize);
+                   post("fexpr~.set: only the first %d values will be set",
+                                                                x->exp_vsize);
+                   nargs = x->exp_vsize;
+                }
+                for (i = 0; i < nargs; i++) {
+                        x->exp_p_res[vecno][x->exp_vsize - i - 1] =
+                                        atom_getfloatarg(i + 1, argc, argv);
+                }
+                return;
+        case 0:
+                if (argc >  x->exp_nexpr) {
+                        post("fexpr~.set: only %d outlets available",
+                                                                x->exp_nexpr);
+                        post("fexpr~.set: the extra set values are ignored");
+                }
+                for (i = 0; i < x->exp_nexpr && i < argc; i++)
+                        x->exp_p_res[i][x->exp_vsize - 1] =
+                                        atom_getfloatarg(i, argc, argv);
+                return;
+        default:
+                fexpr_set_usage();
+                return;
+        }
+        return;
+}
+
+/*
+ * fexpr_tilde_clear - clear the past buffers
+ */
+static void
+fexpr_tilde_clear(t_expr *x, t_symbol *s, int argc, t_atom *argv)
+{
+        t_symbol *sx;
+        int vecno;
+        int i, nargs;
+
+        /*
+         *  if no arguement clear all input and output buffers
+         */
+        if (!argc) {
+                for (i = 0; i < x->exp_nexpr; i++)
+                        memset(x->exp_p_res[i], 0, x->exp_vsize*sizeof(float));
+                for (i = 0; i < MAX_VARS; i++)
+                        if (x->exp_var[i].ex_type == ET_XI)
+                                memset(x->exp_p_var[i], 0,
+                                                x->exp_vsize*sizeof(float));
+                return;
+        }
+        if (argc > 1) {
+                post("fexpr~ usage: 'clear' or 'clear {xy}[#]'");
+                return;
+        }
+
+        sx = atom_getsymbolarg(0, argc, argv);
+        switch(sx->s_name[0]) {
+        case 'x':
+                if (!sx->s_name[1])
+                        vecno = 0;
+                else {
+                        vecno = atoi(sx->s_name + 1);
+                        if (!vecno) {
+                                post("fexpr~.clear: bad clear x vector number");
+                                return;
+                        }
+                        if (vecno >= MAX_VARS) {
+                                post("fexpr~.clear: no more than %d inlets",
+                                                                      MAX_VARS);
+                                return;
+                        }
+                        vecno--;
+                }
+                if (x->exp_var[vecno].ex_type != ET_XI) {
+                        post("fexpr~-clear: no signal at inlet %d", vecno + 1);
+                        return;
+                }
+                memset(x->exp_p_var[vecno], 0, x->exp_vsize*sizeof(float));
+                return;
+        case 'y':
+                if (!sx->s_name[1])
+                        vecno = 0;
+                else {
+                        vecno = atoi(sx->s_name + 1);
+                        if (!vecno) {
+                                post("fexpr~.clear: bad clear y vector number");
+                                return;
+                        }
+                        vecno--;
+                }
+                if (vecno >= x->exp_nexpr) {
+                        post("fexpr~.clear: only %d outlets", x->exp_nexpr);
+                        return;
+                }
+                memset(x->exp_p_res[vecno], 0, x->exp_vsize*sizeof(float));
+                return;
+                return;
+        default:
+                post("fexpr~ usage: 'clear' or 'clear {xy}[#]'");
+                return;
+        }
+        return;
+}
+
+#ifdef PD
+
+void
+expr_setup(void)
+{
+        /*
+         * expr initialization
+         */
+        expr_class = class_new(gensym("expr"), (t_newmethod)expr_new,
+            (t_method)expr_ff, sizeof(t_expr), 0, A_GIMME, 0);
+        class_addlist(expr_class, expr_list);
+        exprproxy_class = class_new(gensym("exprproxy"), 0,
+                                        0, sizeof(t_exprproxy), CLASS_PD, 0);
+        class_addfloat(exprproxy_class, exprproxy_float);
+
+        /*
+         * expr~ initialization
+         */
+        expr_tilde_class = class_new(gensym("expr~"), (t_newmethod)expr_new,
+            (t_method)expr_ff, sizeof(t_expr), 0, A_GIMME, 0);
+        class_addmethod(expr_tilde_class, nullfn, gensym("signal"), 0);
+        CLASS_MAINSIGNALIN(expr_tilde_class, t_expr, exp_f);
+        class_addmethod(expr_tilde_class,(t_method)expr_dsp, gensym("dsp"), 0);
+        class_sethelpsymbol(expr_tilde_class, gensym("expr"));
+        /*
+         * fexpr~ initialization
+         */
+        fexpr_tilde_class = class_new(gensym("fexpr~"), (t_newmethod)expr_new,
+            (t_method)expr_ff, sizeof(t_expr), 0, A_GIMME, 0);
+        class_addmethod(fexpr_tilde_class, nullfn, gensym("signal"), 0);
+        class_addmethod(fexpr_tilde_class,(t_method)expr_start,
+                                                        gensym("start"), 0);
+        class_addmethod(fexpr_tilde_class,(t_method)expr_stop,
+                                                        gensym("stop"), 0);
+
+        class_addmethod(fexpr_tilde_class,(t_method)expr_dsp,gensym("dsp"), 0);
+        class_addmethod(fexpr_tilde_class, (t_method)fexpr_tilde_set,
+                        gensym("set"), A_GIMME, 0);
+        class_addmethod(fexpr_tilde_class, (t_method)fexpr_tilde_clear,
+                        gensym("clear"), A_GIMME, 0);
+        class_addmethod(fexpr_tilde_class,(t_method)expr_verbose,
+                                                        gensym("verbose"), 0);
+        class_sethelpsymbol(fexpr_tilde_class, gensym("expr"));
+
+
+
+        post("expr, expr~, fexpr~ version %s under GNU General Public License ", exp_version);
+
+}
+
+void
+expr_tilde_setup(void)
+{
+        expr_setup();
+}
+
+void
+fexpr_tilde_setup(void)
+{
+        expr_setup();
+}
+#else /* MSP */
+void
+main(void)
+{
+        setup((t_messlist **)&expr_tilde_class, (method)Nexpr_new,
+                (method)expr_ff, (short)sizeof(t_expr), 0L, A_GIMME, 0);
+        addmess((method)expr_dsp, "dsp", A_CANT, 0); // dsp method
+        dsp_initclass();
+}
+#endif
+
+
+/* -- the following functions use Pd internals and so are in the "if" file. */
+
+
+int
+ex_getsym(char *p, fts_symbol_t *s)
+{
+        *s = gensym(p);
+        return (0);
+}
+
+const char *
+ex_symname(fts_symbol_t s)
+{
+        return (fts_symbol_name(s));
+}
+
+/*
+ * max_ex_tab -- evaluate this table access
+ *               eptr is the name of the table and arg is the index we
+ *               have to put the result in optr
+ *               return 1 on error and 0 otherwise
+ *
+ * Arguments:
+ *  the expr object
+ *  table 
+ *  the argument 
+ *  the result pointer 
+ */
+int
+max_ex_tab(struct expr *expr, fts_symbol_t s, struct ex_ex *arg,
+    struct ex_ex *optr)
+{
+#ifdef PD
+        t_garray *garray;
+        int size, indx;
+        t_word *wvec;
+
+        if (!s || !(garray = (t_garray *)pd_findbyclass(s, garray_class)) ||
+            !garray_getfloatwords(garray, &size, &wvec))
+        {
+                optr->ex_type = ET_FLT;
+                optr->ex_flt = 0;
+                pd_error(expr, "no such table '%s'", s->s_name);
+                return (1);
+        }
+        optr->ex_type = ET_FLT;
+
+        switch (arg->ex_type) {
+        case ET_INT:
+                indx = arg->ex_int;
+                break;
+        case ET_FLT:
+                /* strange interpolation code deleted here -msp */
+                indx = arg->ex_flt;
+                break;
+
+        default:        /* do something with strings */
+                pd_error(expr, "expr: bad argument for table '%s'\n", fts_symbol_name(s));
+                indx = 0;
+        }
+        if (indx < 0) indx = 0;
+        else if (indx >= size) indx = size - 1;
+        optr->ex_flt = wvec[indx].w_float;
+#else /* MSP */
+        /*
+         * table lookup not done for MSP yet
+         */
+        post("max_ex_tab: not complete for MSP yet!");
+        optr->ex_type = ET_FLT;
+        optr->ex_flt = 0;
+#endif  
+        return (0);
+}
+
+int
+max_ex_var(struct expr *expr, fts_symbol_t var, struct ex_ex *optr)
+{
+        optr->ex_type = ET_FLT;
+        if (value_getfloat(var, &(optr->ex_flt))) {
+                optr->ex_type = ET_FLT;
+                optr->ex_flt = 0;
+                pd_error(expr, "no such var '%s'", var->s_name);
+                return (1);
+        }
+        return (0);
+}
+
+#ifdef PD /* this goes to the end of this file as the following functions
+           * should be defined in the expr object in MSP
+           */
+#define ISTABLE(sym, garray, size, vec)                               \
+if (!sym || !(garray = (t_garray *)pd_findbyclass(sym, garray_class)) || \
+                !garray_getfloatwords(garray, &size, &vec))  {          \
+        optr->ex_type = ET_FLT;                                         \
+        optr->ex_int = 0;                                               \
+        error("no such table '%s'", sym->s_name);                       \
+        return;                                                         \
+}
+
+/*
+ * ex_size -- find the size of a table
+ */
+void
+ex_size(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr)
+{
+        t_symbol *s;
+        t_garray *garray;
+        int size;
+        t_word *wvec;
+
+        if (argv->ex_type != ET_SYM)
+        {
+                post("expr: size: need a table name\n");
+                optr->ex_type = ET_INT;
+                optr->ex_int = 0;
+                return;
+        }
+
+        s = (fts_symbol_t ) argv->ex_ptr;
+
+        ISTABLE(s, garray, size, wvec);
+
+        optr->ex_type = ET_INT;
+        optr->ex_int = size;
+}
+
+/*
+ * ex_sum -- calculate the sum of all elements of a table
+ */
+
+void
+ex_sum(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr)
+{
+        t_symbol *s;
+        t_garray *garray;
+        int size;
+        t_word *wvec;
+        float sum;
+        int indx;
+
+        if (argv->ex_type != ET_SYM)
+        {
+                post("expr: sum: need a table name\n");
+                optr->ex_type = ET_INT;
+                optr->ex_int = 0;
+                return;
+        }
+
+        s = (fts_symbol_t ) argv->ex_ptr;
+
+        ISTABLE(s, garray, size, wvec);
+
+        for (indx = 0, sum = 0; indx < size; indx++)
+                sum += wvec[indx].w_float;
+
+        optr->ex_type = ET_FLT;
+        optr->ex_flt = sum;
+}
+
+
+/*
+ * ex_Sum -- calculate the sum of table with the given boundries
+ */
+
+void
+ex_Sum(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr)
+{
+        t_symbol *s;
+        t_garray *garray;
+        int size;
+        t_word *wvec;
+        t_float sum;
+        int indx, n1, n2;
+
+        if (argv->ex_type != ET_SYM)
+        {
+                post("expr: sum: need a table name\n");
+                optr->ex_type = ET_INT;
+                optr->ex_int = 0;
+                return;
+        }
+
+        s = (fts_symbol_t ) argv->ex_ptr;
+
+        ISTABLE(s, garray, size, wvec);
+
+        if (argv->ex_type != ET_INT || argv[1].ex_type != ET_INT)
+        {
+                post("expr: Sum: boundries have to be fix values\n");
+                optr->ex_type = ET_INT;
+                optr->ex_int = 0;
+                return;
+        }
+        n1 = argv->ex_int;
+        n2 = argv[1].ex_int;
+
+        for (indx = n1, sum = 0; indx < n2; indx++)
+                if (indx >= 0 && indx < size)
+                        sum += wvec[indx].w_float;
+
+        optr->ex_type = ET_FLT;
+        optr->ex_flt = sum;
+}
+
+/*
+ * ex_avg -- calculate the avarage of a table
+ */
+
+void
+ex_avg(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr)
+{
+/* SDY - look into this function */
+#if 0
+        fts_symbol_t s;
+        fts_integer_vector_t *tw = 0;
+
+        if (argv->ex_type != ET_SYM)
+        {
+                post("expr: avg: need a table name\n");
+                optr->ex_type = ET_INT;
+                optr->ex_int = 0;
+        }
+
+        s = (fts_symbol_t ) argv->ex_ptr;
+
+        tw = table_integer_vector_get_by_name(s);
+
+        if (tw)
+        {
+                optr->ex_type = ET_INT;
+
+                if (! fts_integer_vector_get_size(tw))
+                        optr->ex_int = 0;
+                else
+                        optr->ex_int = fts_integer_vector_get_sum(tw) / fts_integer_vector_get_size(tw);
+        }
+        else
+        {
+                optr->ex_type = ET_INT;
+                optr->ex_int = 0;
+                post("expr: avg: no such table %s\n", fts_symbol_name(s));
+        }
+#endif
+}
+
+
+/*
+ * ex_Avg -- calculate the avarage of table with the given boundries
+ */
+
+void
+ex_Avg(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr)
+{
+/* SDY - look into this function */
+#if 0
+        fts_symbol_t s;
+        fts_integer_vector_t *tw = 0;
+
+        if (argv->ex_type != ET_SYM)
+        {
+                post("expr: Avg: need a table name\n");
+                optr->ex_type = ET_INT;
+                optr->ex_int = 0;
+        }
+
+        s = (fts_symbol_t ) (argv++)->ex_ptr;
+
+        tw = table_integer_vector_get_by_name(s);
+
+        if (! tw)
+        {
+                optr->ex_type = ET_INT;
+                optr->ex_int = 0;
+                post("expr: Avg: no such table %s\n", fts_symbol_name(s));
+                return;
+        }
+
+        if (argv->ex_type != ET_INT || argv[1].ex_type != ET_INT)
+        {
+                post("expr: Avg: boundries have to be fix values\n");
+                optr->ex_type = ET_INT;
+                optr->ex_int = 0;
+                return;
+        }
+
+        optr->ex_type = ET_INT;
+
+        if (argv[1].ex_int - argv->ex_int <= 0)
+                optr->ex_int = 0;
+        else
+                optr->ex_int = (fts_integer_vector_get_sub_sum(tw, argv->ex_int, argv[1].ex_int) /
+                    (argv[1].ex_int - argv->ex_int));
+#endif
+}
+
+/*
+ * ex_store -- store a value in a table
+ *             if the index is greater the size of the table,
+ *             we will make a modulo the size of the table
+ */
+
+void
+ex_store(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr)
+{
+/* SDY - look into this function */
+#if 0
+        fts_symbol_t s;
+        fts_integer_vector_t *tw = 0;
+
+        if (argv->ex_type != ET_SYM)
+        {
+                post("expr: store: need a table name\n");
+        }
+
+        s = (fts_symbol_t ) (argv++)->ex_ptr;
+
+        tw = table_integer_vector_get_by_name(s);
+
+        if (! tw)
+        {
+                optr->ex_type = ET_INT;
+                optr->ex_int = 0;
+                post("expr: store: no such table %s\n", fts_symbol_name(s));
+                return;
+        }
+
+        if (argv->ex_type != ET_INT || argv[1].ex_type != ET_INT)
+        {
+                post("expr: store: arguments have to be integer\n");
+                optr->ex_type = ET_INT;
+                optr->ex_int = 0;
+        }
+
+        fts_integer_vector_set_element(tw, argv->ex_int < 0 ? 0 : argv->ex_int % fts_integer_vector_get_size(tw), argv[1].ex_int);
+        *optr = argv[1];
+#endif
+}
+
+#else /* MSP */
+
+void 
+pd_error(void *object, char *fmt, ...)
+{
+    va_list ap;
+    t_int arg[8];
+    int i;
+    static int saidit = 0;
+    va_start(ap, fmt);
+/* SDY
+    vsprintf(error_string, fmt, ap);
+ */ post(fmt, ap);
+        va_end(ap);
+/* SDY
+    fprintf(stderr, "error: %s\n", error_string);
+    error_object = object;
+*/
+    if (!saidit)
+    {
+        post("... you might be able to track this down from the Find menu.");
+        saidit = 1;
+    }
+}
+#endif
diff --git a/extra/fiddle~/fiddle~-help.pd b/extra/fiddle~/fiddle~-help.pd
new file mode 100644
index 0000000000000000000000000000000000000000..f396725a001bc0572fcf09ee54761a31794c38c0
--- /dev/null
+++ b/extra/fiddle~/fiddle~-help.pd
@@ -0,0 +1,142 @@
+#N canvas 93 26 980 745 10;
+#X obj 262 522 phasor~;
+#X obj 531 616 unpack;
+#X floatatom 531 666 0 0 0 0 - - -;
+#X msg 437 449 print;
+#X obj 262 500 sig~;
+#X floatatom 262 478 0 0 0 0 - - -;
+#X obj 262 456 mtof;
+#X floatatom 262 434 0 0 0 0 - - -;
+#X floatatom 545 643 0 0 0 0 - - -;
+#X obj 531 576 route 1 2 3 4;
+#X obj 614 616 unpack;
+#X floatatom 614 666 0 0 0 0 - - -;
+#X floatatom 628 643 0 0 0 0 - - -;
+#X obj 698 616 unpack;
+#X floatatom 698 666 0 0 0 0 - - -;
+#X floatatom 712 643 0 0 0 0 - - -;
+#X obj 389 616 unpack;
+#X floatatom 389 666 0 0 0 0 - - -;
+#X floatatom 403 643 0 0 0 0 - - -;
+#X obj 334 545 *~;
+#X obj 322 394 loadbang;
+#X obj 353 522 sig~;
+#X floatatom 353 500 0 0 0 0 - - -;
+#X msg 322 478 1;
+#X msg 353 478 0;
+#X floatatom 466 666 0 0 0 0 - - -;
+#X obj 281 666 print attack;
+#X obj 190 666 print pitch;
+#X msg 555 45 \; pd dsp 1;
+#X text 460 39 click here;
+#X text 460 61 to start DSP;
+#X text 226 4 FIDDLE - pitch estimator and sinusoidal peak finder;
+#X text 8 70 The Fiddle object estimates the pitch and amplitude of
+an incoming sound \, both continuously and as a stream of discrete
+"note" events. Fiddle optionally outputs a list of detected sinusoidal
+peaks used to make the pitch determination. Fiddle is described theoretically
+in the 1998 ICMC proceedings \, reprinted on http://man104nfs.ucsd.edu/~mpuckett.
+;
+#X text 8 170 Fiddle's creation arguments specify an analysis window
+size \, the maximum polyphony (i.e. \, the number of simultaneous "pitches"
+to try to find) \, the number of peaks in the spectrum to consider
+\, and the number of peaks \, if any \, to output "raw." The outlets
+give discrete pitch (a number) \, detected attacks in the amplitude
+envelope (a bang) \, one or more voices of continuous pitch and amplitude
+\, overall amplitude \, and optionally a sequence of messages with
+the peaks.;
+#X text 8 296 The analysis hop size is half the window size so in the
+example shown here \, one analysis is done every 512 samples (11.6
+msec at 44K1) \, and the analysis uses the most recent 1024 samples
+(23.2 msec at 44K1). The minimum frequency that Fiddle will report
+is 2-1/2 cycles per analysis windows \, or about 108 Hz. (just below
+MIDI 45.);
+#X text 669 535 number of pitch outlets (1-3 \, default 1);
+#X text 669 557 number of peaks to find (1-100 \, default 20);
+#X text 669 579 number of peaks to output (default 0.);
+#X msg 441 107 amp-range 40 50;
+#X msg 439 227 reattack 100 10;
+#X msg 438 282 npartial 7;
+#X msg 438 170 vibrato 50 0.5;
+#X text 560 91 a low and high amplitude threshold: if signal amplitude
+is below the low threshold \, no pitches or peaks are output. The high
+threshold is a minimum at which "cooked" outputs may appear.;
+#X text 560 152 A period in milliseconds (50) over which the raw pitch
+may not deviate more than an interval in half-tones (0.5) from the
+average pitch to report it as a note to the "cooked" pitch outlet.
+;
+#X text 560 213 A period in milliseconds (100) over which a re-attack
+is reported if the amplitude rises more than (1) dB. The re-attack
+will result in a "bang" in the attack outlet and may give rise to repeated
+notes in the cooked pitch output.;
+#X text 142 432 test input pitch;
+#X text 330 444 test input;
+#X text 330 457 amplitude;
+#X obj 410 545 fiddle~ 1024 1 20 3;
+#X text 538 690 individual sinusoidal components;
+#X text 466 688 amplitude;
+#X text 476 703 (dB);
+#X text 389 688 raw pitch;
+#X text 376 712 and amplitude;
+#X text 364 729 (up to 3 outputs);
+#X text 287 686 bang on;
+#X text 287 708 attack;
+#X text 185 686 cooked pitch;
+#X text 202 703 output;
+#X text 545 545 ------ arguments:;
+#X msg 262 412 57;
+#X msg 440 331 auto 1;
+#X msg 440 353 auto 0;
+#X msg 439 418 bang;
+#X text 561 416 poll current values --- useful if not in auto mode
+\,;
+#X text 560 274 Higher partials are weighed less strongly than lower
+ones in determining the pitch. This specifies the number of the partial
+(7) which will be weighted half as strongly as the fundamental.;
+#X text 560 335 start and stop "auto" mode (on by default.) If off
+\, output only appears on "bang" (poll mode).;
+#X text 561 448 print out all settings;
+#X text 669 513 window size (128-2048 \, default 1024);
+#X msg 440 375 npoints 2048;
+#X text 562 384 number of points in analysis window (power of 2 \,
+128-2048);
+#X msg 439 396 npoints 1024;
+#X connect 0 0 19 0;
+#X connect 1 0 2 0;
+#X connect 1 1 8 0;
+#X connect 3 0 48 0;
+#X connect 4 0 0 0;
+#X connect 5 0 4 0;
+#X connect 6 0 5 0;
+#X connect 7 0 6 0;
+#X connect 9 0 1 0;
+#X connect 9 1 10 0;
+#X connect 9 2 13 0;
+#X connect 10 0 11 0;
+#X connect 10 1 12 0;
+#X connect 13 0 14 0;
+#X connect 13 1 15 0;
+#X connect 16 0 17 0;
+#X connect 16 1 18 0;
+#X connect 19 0 48 0;
+#X connect 20 0 60 0;
+#X connect 20 0 23 0;
+#X connect 21 0 19 1;
+#X connect 22 0 21 0;
+#X connect 23 0 22 0;
+#X connect 24 0 22 0;
+#X connect 38 0 48 0;
+#X connect 39 0 48 0;
+#X connect 40 0 48 0;
+#X connect 41 0 48 0;
+#X connect 48 0 27 0;
+#X connect 48 1 26 0;
+#X connect 48 2 16 0;
+#X connect 48 3 25 0;
+#X connect 48 4 9 0;
+#X connect 60 0 7 0;
+#X connect 61 0 48 0;
+#X connect 62 0 48 0;
+#X connect 63 0 48 0;
+#X connect 69 0 48 0;
+#X connect 71 0 48 0;
diff --git a/extra/fiddle~/fiddle~.c b/extra/fiddle~/fiddle~.c
new file mode 100644
index 0000000000000000000000000000000000000000..4633b3c0510fbd72d652ee9a9c54fc0a3f38afba
--- /dev/null
+++ b/extra/fiddle~/fiddle~.c
@@ -0,0 +1,1851 @@
+/* Copyright (c) 1997-1999 Miller Puckette and Ted Apel.
+* For information on usage and redistribution, and for a DISCLAIMER OF ALL
+* WARRANTIES, see the file, "LICENSE.txt," in this distribution.  */
+
+/*
+ * Fiddle is a pitch tracker hardwired to have hop size ("H") equal to
+ * half its window size ("N").
+ *
+ * This version should compile for Max "0.26," JMAX, Pd, or Max/MSP.
+ *
+ * The "lastanalysis" field holds the shifted FT of the previous H
+ * samples.  The buffer contains in effect points 1/2,  3/2, ..., (N-1)/2
+ * of the DTFT of a real vector of length N, half of whose points are zero,
+ * i.e.,  only the first H points are used.  Put another way, we get the
+ * the odd-numbered points of the FFT of the H points, zero padded to 4*H in
+ * length. The integer points 0, 1, ..., H-1
+ * are found by interpolating these others,  using the fact that the
+ * half-integer points are band-limited (they only have positive frequencies.)
+ * To facilitate the interpolation the "lastanalysis" buffer contains
+ * FILTSIZE extra points (1/2-FILTSIZE, ...,  -1/2) at the beginning and
+ * FILTSIZE again at the end ((N+1)/2, ..., FILTSIZE+(N-1)/2).  The buffer
+ * therefore has N+4*FILTSIZE floating-point numbers in it.
+ *
+ * after doing this I found out that you can just do a real FFT
+ * of the H new points, zero-padded to contain N points, and using a similar
+ * but simpler interpolation scheme you can still get 2N points of the DTFT
+ * of the N points.  Jean Laroche is a big fat hen.
+ *
+ */
+
+
+/* These pragmas are only used for MSVC, not MinGW or Cygwin <hans@at.or.at> */
+#ifdef _MSC_VER
+#pragma warning (disable: 4305 4244)
+#endif
+
+/* this #ifdef does nothing, but its there... */
+#ifdef _WIN32
+#define flog log
+#define fexp exp
+#define fsqrt sqrt
+#else
+#define flog log
+#define fexp exp
+#define fsqrt sqrt
+#endif
+
+char fiddle_version[] = "fiddle version 1.1 TEST4";
+
+#ifdef JMAX
+#include "fts.h"
+#include <stdio.h>
+#include <stdlib.h>
+typedef float t_float;
+typedef float t_floatarg;
+typedef fts_symbol_t t_symbol;
+
+static void *getbytes(size_t nbytes)
+{
+    void *ret;
+    if (nbytes < 1) nbytes = 1;
+    ret = (void *)malloc(nbytes);
+    return (ret);
+}
+
+static void *resizebytes(void *old, size_t oldsize, size_t newsize)
+{
+    void *ret;
+    if (newsize < 1) newsize = 1;
+    ret = (void *)realloc((char *)old, newsize);
+    return (ret);
+}
+
+static void freebytes(void *fatso, size_t nbytes)
+{
+    free(fatso);
+}
+
+#define CLASSNAME "fiddle"
+
+#define OUTLETpower 5
+#define OUTLETmicropitch1 4
+#define OUTLETmicropitch2 3
+#define OUTLETmicropitch3 2
+#define OUTLETattack 1
+#define OUTLETpitch 0
+
+static fts_symbol_t *dsp_symbol = 0;
+#define error post
+
+#endif /* FTS */
+
+#ifdef MAX26
+#define t_floatarg double
+#include "m_extern.h"
+#include "d_graph.h"
+#include "d_ugen.h"
+#endif /* MAX26 */
+
+#ifdef PD
+#include "m_pd.h"
+#endif /* PD */
+
+#ifdef MSP
+#define flog log
+#define fexp exp
+#define fsqrt sqrt
+#endif /* MSP */
+
+#ifdef MSP
+#define t_floatarg double
+#include "ext.h"
+#include "z_dsp.h"
+#include "fft_mayer.proto.h"
+
+#endif /* MSP */
+
+#include <math.h>
+
+
+#define MINBIN 3
+#define DEFAMPLO 40
+#define DEFAMPHI 50
+#define DEFATTACKTIME 100
+#define DEFATTACKTHRESH 10
+#define DEFVIBTIME 50
+#define DEFVIBDEPTH 0.5
+#define GLISS 0.7f
+#define DBFUDGE 30.8f
+#define MINFREQINBINS 5     /* minimum frequency in bins for reliable output */
+
+#define MAXNPITCH 3
+#define MAXHIST 3                   /* find N hottest peaks in histogram */
+
+#define MAXPOINTS 8192
+#define MINPOINTS 128
+#define DEFAULTPOINTS 1024
+
+#define HISTORY 20
+#define MAXPEAK 100             /* maximum number of peaks */
+#define DEFNPEAK 20             /* default number of peaks */
+
+#define MAXNPEAK (MAXLOWPEAK + MAXSTRONGPEAK)
+#define MINBW (0.03f)                   /* consider BW >= 0.03 FFT bins */
+
+#define BINPEROCT 48                    /* bins per octave */
+#define BPERO_OVER_LOG2 69.24936196f    /* BINSPEROCT/log(2) */
+#define FACTORTOBINS (float)(4/0.0145453)       /* 4 / (pow(2.,1/48.) - 1) */
+#define BINGUARD 10                     /* extra bins to throw in front */
+#define PARTIALDEVIANCE 0.023f          /* acceptable partial detuning in % */
+#define LOGTODB 4.34294481903f          /* 20/log(10) */
+
+#define KNOCKTHRESH 10.f     /* don't know how to describe this */
+
+
+static float sigfiddle_partialonset[] =
+{
+0,
+48,
+76.0782000346154967102,
+96,
+111.45254855459339269887,
+124.07820003461549671089,
+134.75303625876499715823,
+144,
+152.15640006923099342109,
+159.45254855459339269887,
+166.05271769459026829915,
+172.07820003461549671088,
+177.62110647077242370064,
+182.75303625876499715892,
+187.53074858920888940907,
+192,
+};
+
+#define NPARTIALONSET ((int)(sizeof(sigfiddle_partialonset)/sizeof(float)))
+
+static int sigfiddle_intpartialonset[] =
+{
+0,
+48,
+76,
+96,
+111,
+124,
+135,
+144,
+152,
+159,
+166,
+172,
+178,
+183,
+188,
+192,
+};
+
+/* these coefficients, which come from the "upsamp" subdirectory,
+are a filter kernel for upsampling by a factor of two, assuming
+the sound to be upsampled has no energy above half the Nyquist, i.e.,
+that it's already 2x oversampled compared to the theoretically possible
+sample rate.  I got these by trial and error. */
+
+#define FILT1 ((float)(.5 * 1.227054))
+#define FILT2 ((float)(.5 * -0.302385))
+#define FILT3 ((float)(.5 * 0.095326))
+#define FILT4 ((float)(.5 * -0.022748))
+#define FILT5 ((float)(.5 * 0.002533))
+#define FILTSIZE 5
+
+typedef struct peakout      /* a peak for output */
+{
+    float po_freq;                  /* frequency in hz */
+    float po_amp;                   /* amplitude */
+} t_peakout;
+
+typedef struct peak         /* a peak for analysis */
+{
+    float p_freq;                   /* frequency in bins */
+    float p_width;                  /* peak width in bins */
+    float p_pow;                    /* peak power */
+    float p_loudness;               /* 4th root of power */
+    float *p_fp;                    /* pointer back to spectrum */
+} t_peak;
+
+typedef struct histopeak
+{
+    float h_pitch;                  /* estimated pitch */
+    float h_value;                  /* value of peak */
+    float h_loud;                   /* combined strength of found partials */
+    int h_index;                    /* index of bin holding peak */
+    int h_used;                     /* true if an x_hist entry points here */
+} t_histopeak;
+
+typedef struct pitchhist            /* struct for keeping history by pitch */
+{
+    float h_pitch;                  /* pitch to output */
+    float h_amps[HISTORY];          /* past amplitudes */
+    float h_pitches[HISTORY];       /* past pitches */
+    float h_noted;                  /* last pitch output */
+    int h_age;                      /* number of frames pitch has been there */
+    t_histopeak *h_wherefrom;       /* new histogram peak to incorporate */
+    void *h_outlet;
+} t_pitchhist;
+
+typedef struct sigfiddle                    /* instance struct */
+{
+#ifdef JMAX
+    fts_object_t x_h;               /* object header */
+    fts_alarm_t x_clock;            /* callback for timeouts */
+#endif
+#ifdef MAX26
+    t_head x_h;                     /* header for tilde objects */
+    t_sig *x_io[IN1+OUT0];          /* number of signal inputs and outputs */
+    void *x_clock;                  /* a "clock" object */
+#endif
+#ifdef PD
+    t_object x_ob;                  /* object header */
+    t_clock *x_clock;               /* callback for timeouts */
+#endif
+#ifdef MSP
+        t_pxobject x_obj;
+        void *x_clock;
+        long x_downsample;              /* downsample feature because of
+                                         MSP's large sig vector sizes */
+#endif
+    float *x_inbuf;                 /* buffer to analyze, npoints/2 elems */
+    float *x_lastanalysis;          /* FT of last buffer (see main comment) */
+    float *x_spiral;                /* 1/4-wave complex exponential */
+    t_peakout *x_peakbuf;           /* spectral peaks for output */
+    int x_npeakout;                 /* number of spectral peaks to output */
+    int x_npeakanal;                /* number of spectral peaks to analyze */
+    int x_phase;                    /* number of points since last output */
+    int x_histphase;                /* phase into amplitude history vector */
+    int x_hop;                      /* period of output, npoints/2 */
+    float x_sr;                     /* sample rate */
+    t_pitchhist x_hist[MAXNPITCH];  /* history of current pitches */
+    int x_nprint;                   /* how many periods to print */
+    int x_npitch;                   /* number of simultaneous pitches */
+    float x_dbs[HISTORY];           /* DB history, indexed by "histphase" */
+    float x_peaked;                 /* peak since last attack */
+    int x_dbage;                    /* number of bins DB has met threshold */
+    int x_auto;                     /* true if generating continuous output */
+/* parameters */
+    float x_amplo;
+    float x_amphi;
+    int x_attacktime;
+    int x_attackbins;
+    float x_attackthresh;
+    int x_vibtime;
+    int x_vibbins;
+    float x_vibdepth;
+    float x_npartial;
+/* outlets & clock */
+    void *x_envout;
+    int x_attackvalue;
+    void *x_attackout;
+    void *x_noteout;
+    void *x_peakout;
+} t_sigfiddle;
+
+#if CHECKER
+float fiddle_checker[1024];
+#endif
+
+#ifdef MSP
+/* Mac compiler requires prototypes for everything */
+
+int sigfiddle_ilog2(int n);
+float fiddle_mtof(float f);
+float fiddle_ftom(float f);
+void sigfiddle_doit(t_sigfiddle *x);
+void sigfiddle_debug(t_sigfiddle *x);
+void sigfiddle_print(t_sigfiddle *x);
+void sigfiddle_assist(t_sigfiddle *x, void *b, long m, long a, char *s);
+void sigfiddle_amprange(t_sigfiddle *x, double amplo,  double amphi);
+void sigfiddle_reattack(t_sigfiddle *x, t_floatarg attacktime, t_floatarg
+attackthresh);
+void sigfiddle_vibrato(t_sigfiddle *x, t_floatarg vibtime, t_floatarg
+vibdepth);
+void sigfiddle_npartial(t_sigfiddle *x, double npartial);
+void sigfiddle_auto(t_sigfiddle *x, t_floatarg f);
+void sigfiddle_setnpoints(t_sigfiddle *x, t_floatarg f);
+int sigfiddle_doinit(t_sigfiddle *x, long npoints, long npitch, long
+npeakanal, long npeakout);
+static t_int *fiddle_perform(t_int *w);
+void sigfiddle_dsp(t_sigfiddle *x, t_signal **sp);
+void sigfiddle_tick(t_sigfiddle *x);
+void sigfiddle_bang(t_sigfiddle *x);
+void sigfiddle_ff(t_sigfiddle *x);
+void *sigfiddle_new(long npoints, long npitch,
+    long npeakanal, long npeakout);
+void msp_fft(float *buf, long np, long inv);
+float msp_ffttemp[MAXPOINTS*2];
+int errno;
+#endif
+
+int sigfiddle_ilog2(int n)
+{
+    int ret = -1;
+    while (n)
+    {
+        n >>= 1;
+        ret++;
+    }
+    return (ret);
+}
+
+float fiddle_mtof(float f)
+{
+        return (8.17579891564 * exp(.0577622650 * f));
+}
+
+float fiddle_ftom(float f)
+{
+        return (17.3123405046 * log(.12231220585 * f));
+}
+#define ftom fiddle_ftom
+#define mtof fiddle_mtof
+
+void sigfiddle_doit(t_sigfiddle *x)
+{
+#ifdef MSP
+        /* prevents interrupt-level stack overflow crash with Netscape. */
+    static float spect1[4*MAXPOINTS];
+    static float spect2[MAXPOINTS + 4*FILTSIZE];
+#else
+    float spect1[4*MAXPOINTS];
+    float spect2[MAXPOINTS + 4*FILTSIZE];
+#endif
+#if CHECKER
+    float checker3[4*MAXPOINTS];
+#endif
+
+    t_peak peaklist[MAXPEAK + 1], *pk1;
+    t_peakout *pk2;
+    t_histopeak histvec[MAXHIST], *hp1;
+    int i, j, k, hop = x->x_hop, n = 2*hop, npeak, npitch,
+        logn = sigfiddle_ilog2(n), newphase, oldphase;
+    float *fp, *fp1, *fp2, *fp3, total_power, total_loudness, total_db;
+    float maxbin = BINPEROCT * (logn-2),  *histogram = spect2 + BINGUARD;
+    t_pitchhist *phist;
+    float hzperbin = x->x_sr / (2.0f * n);
+    int npeakout = x->x_npeakout, npeakanal = x->x_npeakanal;
+    int npeaktot = (npeakout > npeakanal ? npeakout : npeakanal);
+
+    oldphase = x->x_histphase;
+    newphase = x->x_histphase + 1;
+    if (newphase == HISTORY) newphase = 0;
+    x->x_histphase = newphase;
+
+        /*
+         * multiply the H points by a 1/4-wave complex exponential,
+         * and take FFT of the result.
+         */
+    for (i = 0, fp1 = x->x_inbuf, fp2 = x->x_spiral, fp3 = spect1;
+        i < hop; i++, fp1++, fp2 += 2, fp3 += 2)
+            fp3[0] = fp1[0] * fp2[0], fp3[1] = fp1[0] * fp2[1];
+
+#ifdef MAX26
+    fft(spect1, hop, 0);
+#endif
+#ifdef PD
+    pd_fft(spect1, hop, 0);
+#endif
+#ifdef JMAX
+    fts_cfft_inplc((complex *)spect1, hop);
+#endif
+#ifdef MSP
+        msp_fft(spect1,hop,0);
+#endif
+        /*
+         * now redistribute the points to get in effect the odd-numbered
+         * points of the FFT of the H points, zero padded to 4*H in length.
+         */
+    for (i = 0, fp1 = spect1, fp2 = spect2 + (2*FILTSIZE);
+        i < (hop>>1); i++, fp1 += 2, fp2 += 4)
+            fp2[0] = fp1[0], fp2[1] = fp1[1];
+    for (i = 0, fp1 = spect1 + n - 2, fp2 = spect2 + (2*FILTSIZE+2);
+        i < (hop>>1); i++, fp1 -= 2, fp2 += 4)
+            fp2[0] = fp1[0], fp2[1] = -fp1[1];
+    for (i = 0, fp1 = spect2 + (2*FILTSIZE), fp2 = spect2 + (2*FILTSIZE-2);
+        i<FILTSIZE; i++, fp1+=2, fp2-=2)
+            fp2[0] = fp1[0],  fp2[1] = -fp1[1];
+    for (i = 0, fp1 = spect2 + (2*FILTSIZE+n-2), fp2 = spect2 + (2*FILTSIZE+n);
+        i<FILTSIZE; i++, fp1-=2, fp2+=2)
+            fp2[0] = fp1[0],  fp2[1] = -fp1[1];
+#if 0
+    {
+        fp = spect2 + 2*FILTSIZE;
+        post("x1 re %12.4f %12.4f %12.4f %12.4f %12.4f",
+            fp[0], fp[2], fp[4], fp[6], fp[8]);
+        post("x1 im %12.4f %12.4f %12.4f %12.4f %12.4f",
+            fp[1], fp[3], fp[5], fp[7], fp[9]);
+    }
+#endif
+        /* spect2 is now prepared; now combine spect2 and lastanalysis into
+         * spect1.  Odd-numbered points of spect1 are the points of "last"
+         * plus (-i, i, -i, ...) times spect1.  Even-numbered points are
+         * the interpolated points of "last" plus (1, -1, 1, ...) times the
+         * interpolated points of spect1.
+         *
+         * To interpolate, take FILT1 exp(-pi/4) times
+         * the previous point,  FILT2*exp(-3*pi/4) times 3 bins before,
+         * etc,  and FILT1 exp(pi/4), FILT2 exp(3pi/4), etc., to weight
+         * the +1, +3, etc., points.
+         *
+         * In this calculation,  we take (1, i, -1, -i, 1) times the
+         * -9, -7, ..., -1 points, and (i, -1, -i, 1, i) times the 1, 3,..., 9
+         * points of the OLD spectrum, alternately adding and subtracting
+         * the new spectrum to the old; then we multiply the whole thing
+         * by exp(-i pi/4).
+         */
+    for (i = 0, fp1 = spect1, fp2 = x->x_lastanalysis + 2*FILTSIZE,
+        fp3 = spect2 + 2*FILTSIZE;
+            i < (hop>>1); i++)
+    {
+        float re,  im;
+
+        re= FILT1 * ( fp2[ -2] -fp2[ 1]  +fp3[ -2] -fp3[ 1]) +
+            FILT2 * ( fp2[ -3] -fp2[ 2]  +fp3[ -3] -fp3[ 2]) +
+            FILT3 * (-fp2[ -6] +fp2[ 5]  -fp3[ -6] +fp3[ 5]) +
+            FILT4 * (-fp2[ -7] +fp2[ 6]  -fp3[ -7] +fp3[ 6]) +
+            FILT5 * ( fp2[-10] -fp2[ 9]  +fp3[-10] -fp3[ 9]);
+
+        im= FILT1 * ( fp2[ -1] +fp2[ 0]  +fp3[ -1] +fp3[ 0]) +
+            FILT2 * (-fp2[ -4] -fp2[ 3]  -fp3[ -4] -fp3[ 3]) +
+            FILT3 * (-fp2[ -5] -fp2[ 4]  -fp3[ -5] -fp3[ 4]) +
+            FILT4 * ( fp2[ -8] +fp2[ 7]  +fp3[ -8] +fp3[ 7]) +
+            FILT5 * ( fp2[ -9] +fp2[ 8]  +fp3[ -9] +fp3[ 8]);
+
+        fp1[0] = 0.7071f * (re + im);
+        fp1[1] = 0.7071f * (im - re);
+        fp1[4] = fp2[0] + fp3[1];
+        fp1[5] = fp2[1] - fp3[0];
+        
+        fp1 += 8, fp2 += 2, fp3 += 2;
+        re= FILT1 * ( fp2[ -2] -fp2[ 1]  -fp3[ -2] +fp3[ 1]) +
+            FILT2 * ( fp2[ -3] -fp2[ 2]  -fp3[ -3] +fp3[ 2]) +
+            FILT3 * (-fp2[ -6] +fp2[ 5]  +fp3[ -6] -fp3[ 5]) +
+            FILT4 * (-fp2[ -7] +fp2[ 6]  +fp3[ -7] -fp3[ 6]) +
+            FILT5 * ( fp2[-10] -fp2[ 9]  -fp3[-10] +fp3[ 9]);
+
+        im= FILT1 * ( fp2[ -1] +fp2[ 0]  -fp3[ -1] -fp3[ 0]) +
+            FILT2 * (-fp2[ -4] -fp2[ 3]  +fp3[ -4] +fp3[ 3]) +
+            FILT3 * (-fp2[ -5] -fp2[ 4]  +fp3[ -5] +fp3[ 4]) +
+            FILT4 * ( fp2[ -8] +fp2[ 7]  -fp3[ -8] -fp3[ 7]) +
+            FILT5 * ( fp2[ -9] +fp2[ 8]  -fp3[ -9] -fp3[ 8]);
+
+        fp1[0] = 0.7071f * (re + im);
+        fp1[1] = 0.7071f * (im - re);
+        fp1[4] = fp2[0] - fp3[1];
+        fp1[5] = fp2[1] + fp3[0];
+        
+        fp1 += 8, fp2 += 2, fp3 += 2;
+    }
+#if 0
+    if (x->x_nprint)
+    {
+        for (i = 0,  fp = spect1; i < 16; i++,  fp+= 4)
+            post("spect %d %f %f --> %f", i, fp[0], fp[1],
+                sqrt(fp[0] * fp[0] + fp[1] * fp[1]));
+    }
+#endif
+         /* copy new spectrum out */
+    for (i = 0, fp1 = spect2, fp2 = x->x_lastanalysis;
+            i < n + 4*FILTSIZE; i++) *fp2++ = *fp1++;
+
+    for (i = 0; i < MINBIN; i++) spect1[4*i + 2] = spect1[4*i + 3] = 0;
+        /* starting at bin MINBIN, compute hanning windowed power spectrum */
+    for (i = MINBIN, fp1 = spect1+4*MINBIN, total_power = 0;
+        i < n-2; i++,  fp1 += 4)
+    {
+        float re = fp1[0] - 0.5f * (fp1[-8] + fp1[8]);
+        float im = fp1[1] - 0.5f * (fp1[-7] + fp1[9]);
+        fp1[3] = (total_power += (fp1[2] = re * re + im * im));
+    }
+
+    if (total_power > 1e-9f)
+    {
+        total_db = (100.f - DBFUDGE) + LOGTODB * log(total_power/n);
+        total_loudness = fsqrt(fsqrt(total_power));
+        if (total_db < 0) total_db = 0;
+    }
+    else total_db = total_loudness = 0;
+        /*  store new db in history vector */
+    x->x_dbs[newphase] = total_db;
+    if (total_db < x->x_amplo) goto nopow;
+#if 1
+    if (x->x_nprint) post("power %f", total_power);
+#endif
+
+#if CHECKER
+        /* verify that our FFT resampling thing is putting out good results */
+    for (i = 0; i < hop; i++)
+    {
+        checker3[2*i] = fiddle_checker[i];
+        checker3[2*i + 1] = 0;
+        checker3[n + 2*i] = fiddle_checker[i] = x->x_inbuf[i];
+        checker3[n + 2*i + 1] = 0;
+    }
+    for (i = 2*n; i < 4*n; i++) checker3[i] = 0;
+    fft(checker3, 2*n, 0);
+    if (x->x_nprint)
+    {
+        for (i = 0,  fp = checker3; i < 16; i++,  fp += 2)
+            post("spect %d %f %f --> %f", i, fp[0], fp[1],
+                sqrt(fp[0] * fp[0] + fp[1] * fp[1]));
+    }
+
+#endif
+    npeak = 0;
+
+         /* search for peaks */
+    for (i = MINBIN, fp = spect1+4*MINBIN, pk1 = peaklist;
+        i < n-2 && npeak < npeaktot; i++, fp += 4)
+    {
+        float height = fp[2], h1 = fp[-2], h2 = fp[6];
+        float totalfreq, pfreq, f1, f2, m, var, stdev;
+        
+        if (height < h1 || height < h2 ||
+            h1 < 0.00001f*total_power || h2 < 0.00001f*total_power)
+                continue;
+
+            /* use an informal phase vocoder to estimate the frequency.
+            Do this for the two adjacent bins too. */
+        pfreq= ((fp[-8] - fp[8]) * (2.0f * fp[0] - fp[8] - fp[-8]) +
+                (fp[-7] - fp[9]) * (2.0f * fp[1] - fp[9] - fp[-7])) /
+                    (2.0f * height);
+        f1=    ((fp[-12] - fp[4]) * (2.0f * fp[-4] - fp[4] - fp[-12]) +
+                (fp[-11] - fp[5]) * (2.0f * fp[-3] - fp[5] - fp[-11])) /
+                    (2.0f * h1) - 1;
+        f2=    ((fp[-4] - fp[12]) * (2.0f * fp[4] - fp[12] - fp[-4]) +
+                (fp[-3] - fp[13]) * (2.0f * fp[5] - fp[13] - fp[-3])) /
+                    (2.0f * h2) + 1;
+
+            /* get sample mean and variance of the three */
+        m = 0.333333f * (pfreq + f1 + f2);
+        var = 0.5f * ((pfreq-m)*(pfreq-m) + (f1-m)*(f1-m) + (f2-m)*(f2-m));
+
+        totalfreq = i + m;
+        if (var * total_power > KNOCKTHRESH * height || var < 1e-30)
+        {
+#if 0
+            if (x->x_nprint)
+                post("cancel: %.2f hz, index %.1f, power %.5f, stdev=%.2f",
+                    totalfreq * hzperbin, BPERO_OVER_LOG2 * log(totalfreq) - 96,
+                     height, sqrt(var));
+#endif
+            continue;
+        }
+        stdev = fsqrt(var);
+        if (totalfreq < 4)
+        {
+            if (x->x_nprint) post("oops: was %d,  freq %f, m %f, stdev %f h %f",
+                i,  totalfreq, m, stdev, height);
+            totalfreq = 4;
+        }
+        pk1->p_width = stdev;
+
+        pk1->p_pow = height;
+        pk1->p_loudness = fsqrt(fsqrt(height));
+        pk1->p_fp = fp;
+        pk1->p_freq = totalfreq;
+        npeak++;
+#if 1
+        if (x->x_nprint)
+        {
+            post("peak: %.2f hz. index %.1f, power %.5f, stdev=%.2f",
+                pk1->p_freq * hzperbin,
+                BPERO_OVER_LOG2 * log(pk1->p_freq) - 96,
+                 height, stdev);
+        }
+#endif
+        pk1++;
+    }
+
+            /* prepare the raw peaks for output */
+    for (i = 0, pk1 = peaklist, pk2 = x->x_peakbuf; i < npeak;
+        i++, pk1++, pk2++)
+    {
+        float loudness = pk1->p_loudness;
+        if (i >= npeakout) break;
+        pk2->po_freq = hzperbin * pk1->p_freq;
+        pk2->po_amp = (2.f / (float)n) * (loudness * loudness);
+    }
+    for (; i < npeakout; i++, pk2++) pk2->po_amp = pk2->po_freq = 0;
+
+        /* now, working back into spect2, make a sort of "liklihood"
+         * spectrum.  Proceeding in 48ths of an octave,  from 2 to
+         * n/2 (in bins), the likelihood of each pitch range is contributed
+         * to by every peak in peaklist that's an integer multiple of it
+         * in frequency.
+         */
+
+    if (npeak > npeakanal) npeak = npeakanal; /* max # peaks to analyze */
+    for (i = 0, fp1 = histogram; i < maxbin; i++) *fp1++ = 0;
+    for (i = 0, pk1 = peaklist; i < npeak; i++, pk1++)
+    {
+        float pit = BPERO_OVER_LOG2 * flog(pk1->p_freq) - 96.0f;
+        float binbandwidth = FACTORTOBINS * pk1->p_width/pk1->p_freq;
+        float putbandwidth = (binbandwidth < 2 ? 2 : binbandwidth);
+        float weightbandwidth = (binbandwidth < 1.0f ? 1.0f : binbandwidth);
+        /* float weightamp = 1.0f + 3.0f * pk1->p_pow / pow; */
+        float weightamp = 4. * pk1->p_loudness / total_loudness;
+        for (j = 0, fp2 = sigfiddle_partialonset; j < NPARTIALONSET; j++, fp2++)
+        {
+            float bin = pit - *fp2;
+            if (bin < maxbin)
+            {
+                float para, pphase, score = 30.0f * weightamp /
+                    ((j+x->x_npartial) * weightbandwidth);
+                int firstbin = bin + 0.5f - 0.5f * putbandwidth;
+                int lastbin = bin + 0.5f + 0.5f * putbandwidth;
+                int ibw = lastbin - firstbin;
+                if (firstbin < -BINGUARD) break;
+                para = 1.0f / (putbandwidth * putbandwidth);
+                for (k = 0, fp3 = histogram + firstbin,
+                    pphase = firstbin-bin; k <= ibw;
+                        k++, fp3++,  pphase += 1.0f)
+                {
+                    *fp3 += score * (1.0f - para * pphase * pphase);
+                }
+            }
+        }
+    }
+#if 1
+    if (x->x_nprint)
+    {
+        for (i = 0; i < 6*5; i++)
+        {
+            float fhz = hzperbin * exp ((8*i + 96) * (1./BPERO_OVER_LOG2));
+            if (!(i % 6)) post("-- bin %d pitch %f freq %f----", 8*i,
+                ftom(fhz), fhz);;
+            post("%3d %3d %3d %3d %3d %3d %3d %3d",
+                (int)(histogram[8*i]),
+                (int)(histogram[8*i+1]),
+                (int)(histogram[8*i+2]),
+                (int)(histogram[8*i+3]),
+                (int)(histogram[8*i+4]),
+                (int)(histogram[8*i+5]),
+                (int)(histogram[8*i+6]),
+                (int)(histogram[8*i+7]));
+        }
+    }
+
+#endif
+
+        /*
+         * Next we find up to NPITCH strongest peaks in the histogram.
+         * if a peak is related to a stronger one via an interval in
+         * the sigfiddle_partialonset array,  we suppress it.
+         */
+
+    for (npitch = 0; npitch < x->x_npitch; npitch++)
+    {
+        int indx;
+        float best;
+        if (npitch)
+        {
+            for (best = 0, indx = -1, j=1; j < maxbin-1; j++)
+            {
+                if (histogram[j] > best && histogram[j] > histogram[j-1] &&
+                    histogram[j] > histogram[j+1])
+                {
+                    for (k = 0; k < npitch; k++)
+                        if (histvec[k].h_index == j)
+                            goto peaknogood;
+                    for (k = 0; k < NPARTIALONSET; k++)
+                    {
+                        if (j - sigfiddle_intpartialonset[k] < 0) break;
+                        if (histogram[j - sigfiddle_intpartialonset[k]]
+                            > histogram[j]) goto peaknogood;
+                    }
+                    for (k = 0; k < NPARTIALONSET; k++)
+                    {
+                        if (j + sigfiddle_intpartialonset[k] >= maxbin) break;
+                        if (histogram[j + sigfiddle_intpartialonset[k]]
+                            > histogram[j]) goto peaknogood;
+                    }
+                    indx = j;
+                    best = histogram[j];
+                }
+            peaknogood: ;
+            }
+        }
+        else
+        {
+            for (best = 0, indx = -1, j=0; j < maxbin; j++)
+                if (histogram[j] > best)
+                    indx = j,  best = histogram[j];
+        }
+        if (indx < 0) break;
+        histvec[npitch].h_value = best;
+        histvec[npitch].h_index = indx;
+    }
+#if 1
+    if (x->x_nprint)
+    {
+        for (i = 0; i < npitch; i++)
+        {
+            post("index %d freq %f --> value %f", histvec[i].h_index,
+                exp((1./BPERO_OVER_LOG2) * (histvec[i].h_index + 96)),
+                histvec[i].h_value);
+            post("next %f , prev %f",
+                exp((1./BPERO_OVER_LOG2) * (histvec[i].h_index + 97)),
+                exp((1./BPERO_OVER_LOG2) * (histvec[i].h_index + 95)) );
+        }
+    }
+#endif
+
+        /* for each histogram peak, we now search back through the
+         * FFT peaks.  A peak is a pitch if either there are several
+         * harmonics that match it,  or else if (a) the fundamental is
+         * present,  and (b) the sum of the powers of the contributing peaks
+         * is at least 1/100 of the total power.
+         *
+         * A peak is a contributor if its frequency is within 25 cents of
+         * a partial from 1 to 16.
+         *
+         * Finally, we have to be at least 5 bins in frequency, which
+         * corresponds to 2-1/5 periods fitting in the analysis window.
+         */
+
+    for (i = 0; i < npitch; i++)
+    {
+        float cumpow = 0, cumstrength = 0, freqnum = 0, freqden = 0;
+        int npartials = 0,  nbelow8 = 0;
+            /* guessed-at frequency in bins */
+        float putfreq = fexp((1.0f / BPERO_OVER_LOG2) *
+            (histvec[i].h_index + 96.0f));
+        for (j = 0; j < npeak; j++)
+        {
+            float fpnum = peaklist[j].p_freq/putfreq;
+            int pnum = fpnum + 0.5f;
+            float fipnum = pnum;
+            float deviation;
+            if (pnum > 16 || pnum < 1) continue;
+            deviation = 1.0f - fpnum/fipnum;
+            if (deviation > -PARTIALDEVIANCE && deviation < PARTIALDEVIANCE)
+            {
+                /*
+                 * we figure this is a partial since it's within 1/4 of
+                 * a halftone of a multiple of the putative frequency.
+                 */
+
+                float stdev, weight;
+                npartials++;
+                if (pnum < 8) nbelow8++;
+                cumpow += peaklist[j].p_pow;
+                cumstrength += fsqrt(fsqrt(peaklist[j].p_pow));
+                stdev = (peaklist[j].p_width > MINBW ?
+                    peaklist[j].p_width : MINBW);
+                weight = 1.0f / ((stdev*fipnum) * (stdev*fipnum));
+                freqden += weight;
+                freqnum += weight * peaklist[j].p_freq/fipnum;          
+#if 1
+                if (x->x_nprint)
+                {
+                    post("peak %d partial %d f=%f w=%f",
+                        j, pnum, peaklist[j].p_freq/fipnum, weight);
+                }
+#endif
+            }
+#if 1
+            else if (x->x_nprint) post("peak %d partial %d dev %f",
+                        j, pnum, deviation);
+#endif
+        }
+        if ((nbelow8 < 4 || npartials < 7) && cumpow < 0.01f * total_power)
+            histvec[i].h_value = 0;
+        else
+        {
+            float pitchpow = (cumstrength * cumstrength) *
+                (cumstrength * cumstrength);
+            float freqinbins = freqnum/freqden;
+                /* check for minimum output frequency */
+
+            if (freqinbins < MINFREQINBINS)
+                histvec[i].h_value = 0;
+            else
+            {
+                    /* we passed all tests... save the values we got */
+                histvec[i].h_pitch = ftom(hzperbin * freqnum/freqden);
+                histvec[i].h_loud = (100.0f -DBFUDGE) +
+                    (LOGTODB) * log(pitchpow/n);
+            }
+        }
+    }
+#if 1
+    if (x->x_nprint)
+    {
+        for (i = 0; i < npitch; i++)
+        {
+            if (histvec[i].h_value > 0)
+                post("index %d pit %f loud %f", histvec[i].h_index,
+                histvec[i].h_pitch, histvec[i].h_loud);
+            else post("-- cancelled --");
+        }
+    }
+#endif
+
+        /* now try to find continuous pitch tracks that match the new
+         * pitches.  First mark each peak unmatched.
+         */
+    for (i = 0, hp1 = histvec; i < npitch; i++, hp1++)
+        hp1->h_used = 0;
+
+        /* for each old pitch, try to match a new one to it. */
+    for (i = 0, phist = x->x_hist; i < x->x_npitch; i++,  phist++)
+    {
+        float thispitch = phist->h_pitches[oldphase];
+        phist->h_pitch = 0;         /* no output, thanks */
+        phist->h_wherefrom = 0;
+        if (thispitch == 0.0f) continue;
+        for (j = 0, hp1 = histvec; j < npitch; j++, hp1++)
+            if ((hp1->h_value > 0) && hp1->h_pitch > thispitch - GLISS
+                && hp1->h_pitch < thispitch + GLISS)
+        {
+            phist->h_wherefrom = hp1;
+            hp1->h_used = 1;
+        }
+    }
+    for (i = 0, hp1 = histvec; i < npitch; i++, hp1++)
+        if ((hp1->h_value > 0) && !hp1->h_used)
+    {
+        for (j = 0, phist = x->x_hist; j < x->x_npitch; j++,  phist++)
+            if (!phist->h_wherefrom)
+        {
+            phist->h_wherefrom = hp1;
+            phist->h_age = 0;
+            phist->h_noted = 0;
+            hp1->h_used = 1;
+            goto happy;
+        }
+        break;
+    happy: ;
+    }
+        /* copy the pitch info into the history vector */
+    for (i = 0, phist = x->x_hist; i < x->x_npitch; i++,  phist++)
+    {
+        if (phist->h_wherefrom)
+        {
+            phist->h_amps[newphase] = phist->h_wherefrom->h_loud;
+            phist->h_pitches[newphase] =
+                phist->h_wherefrom->h_pitch;
+            (phist->h_age)++;
+        }
+        else
+        {
+            phist->h_age = 0;
+            phist->h_amps[newphase] = phist->h_pitches[newphase] = 0;
+        }
+    }
+#if 1
+    if (x->x_nprint)
+    {
+        post("vibrato %d %f", x->x_vibbins, x->x_vibdepth);
+        for (i = 0, phist = x->x_hist; i < x->x_npitch; i++,  phist++)
+        {
+            post("noted %f, age %d", phist->h_noted,  phist->h_age);
+#ifndef I860
+            post("values %f %f %f %f %f",
+                phist->h_pitches[newphase],
+                phist->h_pitches[(newphase + HISTORY-1)%HISTORY],
+                phist->h_pitches[(newphase + HISTORY-2)%HISTORY],
+                phist->h_pitches[(newphase + HISTORY-3)%HISTORY],
+                phist->h_pitches[(newphase + HISTORY-4)%HISTORY]);
+#endif
+        }
+    }
+#endif
+        /* look for envelope attacks */
+
+    x->x_attackvalue = 0;
+
+    if (x->x_peaked)
+    {
+        if (total_db > x->x_amphi)
+        {
+            int binlook = newphase - x->x_attackbins;
+            if (binlook < 0) binlook += HISTORY;
+            if (total_db > x->x_dbs[binlook] + x->x_attackthresh)
+            {
+                x->x_attackvalue = 1;
+                x->x_peaked = 0;
+            }
+        }
+    }
+    else
+    {
+        int binlook = newphase - x->x_attackbins;
+        if (binlook < 0) binlook += HISTORY;
+        if (x->x_dbs[binlook] > x->x_amphi && x->x_dbs[binlook] > total_db)
+            x->x_peaked = 1;
+    }
+
+        /* for each current frequency track, test for a new note using a
+         * stability criterion.  Later perhaps we should also do as in
+         * pitch~ and check for unstable notes a posteriori when
+         * there's a new attack with no note found since the last onset;
+         * but what's an attack &/or onset when we're polyphonic?
+         */
+
+    for (i = 0, phist = x->x_hist; i < x->x_npitch; i++,  phist++)
+    {
+            /*
+             * if we've found a pitch but we've now strayed from it turn
+             * it off.
+             */
+        if (phist->h_noted)
+        {
+            if (phist->h_pitches[newphase] > phist->h_noted + x->x_vibdepth
+                || phist->h_pitches[newphase] < phist->h_noted - x->x_vibdepth)
+                    phist->h_noted = 0;
+        }
+        else
+        {
+            if (phist->h_wherefrom && phist->h_age >= x->x_vibbins)
+            {
+                float centroid = 0;
+                int not = 0;
+                for (j = 0, k = newphase; j < x->x_vibbins; j++)
+                {
+                    centroid += phist->h_pitches[k];
+                    k--;
+                    if (k < 0) k = HISTORY-1;
+                }
+                centroid /= x->x_vibbins;
+                for (j = 0, k = newphase; j < x->x_vibbins; j++)
+                {
+                        /* calculate deviation from norm */
+                    float dev = centroid - phist->h_pitches[k];
+                    k--;
+                    if (k < 0) k = HISTORY-1;
+                    if (dev > x->x_vibdepth ||
+                        -dev > x->x_vibdepth) not = 1;
+                }
+                if (!not)
+                {
+                    phist->h_pitch = phist->h_noted = centroid;
+                }
+            }
+        }
+    }
+    return;
+
+nopow:
+    for (i = 0; i < x->x_npitch; i++)
+    {
+        x->x_hist[i].h_pitch = x->x_hist[i].h_noted =
+            x->x_hist[i].h_pitches[newphase] =
+            x->x_hist[i].h_amps[newphase] = 0;
+        x->x_hist[i].h_age = 0;
+    }
+    x->x_peaked = 1;
+    x->x_dbage = 0;
+}
+
+void sigfiddle_debug(t_sigfiddle *x)
+{
+    x->x_nprint = 1;
+}
+
+void sigfiddle_print(t_sigfiddle *x)
+{
+    post("npoints %d,",  2 * x->x_hop);
+    post("amp-range %f %f,",  x->x_amplo, x->x_amphi);
+    post("reattack %d %f,",  x->x_attacktime, x->x_attackthresh);
+    post("vibrato %d %f",  x->x_vibtime, x->x_vibdepth);
+    post("npartial %f",  x->x_npartial);
+    post("auto %d",  x->x_auto);
+}
+
+void sigfiddle_amprange(t_sigfiddle *x, t_floatarg amplo, t_floatarg amphi)
+{
+    if (amplo < 0) amplo = 0;
+    if (amphi < amplo) amphi = amplo + 1;
+    x->x_amplo = amplo;
+    x->x_amphi = amphi;
+}
+
+void sigfiddle_reattack(t_sigfiddle *x,
+    t_floatarg attacktime, t_floatarg attackthresh)
+{
+    if (attacktime < 0) attacktime = 0;
+    if (attackthresh <= 0) attackthresh = 1000;
+    x->x_attacktime = attacktime;
+    x->x_attackthresh = attackthresh;
+    x->x_attackbins = (x->x_sr * 0.001 * attacktime) / x->x_hop;
+    if (x->x_attackbins >= HISTORY) x->x_attackbins = HISTORY - 1;
+}
+
+void sigfiddle_vibrato(t_sigfiddle *x, t_floatarg vibtime, t_floatarg vibdepth)
+{
+    if (vibtime < 0) vibtime = 0;
+    if (vibdepth <= 0) vibdepth = 1000;
+    x->x_vibtime = vibtime;
+    x->x_vibdepth = vibdepth;
+    x->x_vibbins = (x->x_sr * 0.001  * vibtime) / x->x_hop;
+    if (x->x_vibbins >= HISTORY) x->x_vibbins = HISTORY - 1;
+    if (x->x_vibbins < 1) x->x_vibbins = 1;
+}
+
+void sigfiddle_npartial(t_sigfiddle *x, t_floatarg npartial)
+{
+    if (npartial < 0.1) npartial = 0.1;
+    x->x_npartial = npartial;
+}
+
+void sigfiddle_auto(t_sigfiddle *x, t_floatarg f)
+{
+    x->x_auto = (f != 0);
+}
+
+static void sigfiddle_freebird(t_sigfiddle *x)
+{
+    if (x->x_inbuf)
+    {
+        freebytes(x->x_inbuf, sizeof(float) * x->x_hop);
+        x->x_inbuf = 0;
+    }
+    if (x->x_lastanalysis)
+    {
+        freebytes(x->x_lastanalysis,
+            sizeof(float) * (2 * x->x_hop + 4 * FILTSIZE));
+        x->x_lastanalysis = 0;
+    }
+    if (x->x_spiral)
+    {
+        freebytes(x->x_spiral, sizeof(float) * 2 * x->x_hop);
+        x->x_spiral = 0;
+    }
+    x->x_hop = 0;
+}
+
+int sigfiddle_setnpoints(t_sigfiddle *x, t_floatarg fnpoints)
+{
+    int i, npoints = fnpoints;
+    sigfiddle_freebird(x);
+    if (npoints < MINPOINTS || npoints > MAXPOINTS)
+    {
+        error("fiddle~: npoints out of range; using %d",
+            npoints = DEFAULTPOINTS);
+    }
+    if (npoints != (1 << sigfiddle_ilog2(npoints)))
+    {
+        error("fiddle~: npoints not a power of 2; using %d", 
+            npoints = (1 << sigfiddle_ilog2(npoints)));
+    }
+    x->x_hop = npoints >> 1;
+    if (!(x->x_inbuf = (float *)getbytes(sizeof(float) * x->x_hop)))
+        goto fail;
+    if (!(x->x_lastanalysis = (float *)getbytes(
+        sizeof(float) * (2 * x->x_hop + 4 * FILTSIZE))))
+            goto fail;
+    if (!(x->x_spiral = (float *)getbytes(sizeof(float) * 2 * x->x_hop)))
+        goto fail;
+    for (i = 0; i < x->x_hop; i++)
+        x->x_inbuf[i] = 0;
+    for (i = 0; i < npoints + 4 * FILTSIZE; i++)
+        x->x_lastanalysis[i] = 0;
+    for (i = 0; i < x->x_hop; i++)
+        x->x_spiral[2*i] =    cos((3.14159*i)/(npoints)),
+        x->x_spiral[2*i+1] = -sin((3.14159*i)/(npoints));
+    x->x_phase = 0;
+    return (1);
+fail:
+    sigfiddle_freebird(x);
+    return (0);
+}
+
+int sigfiddle_doinit(t_sigfiddle *x, long npoints, long npitch,
+    long npeakanal, long npeakout)
+{
+    float *buf1, *buf2,  *buf3;
+    t_peakout *buf4;
+    int i;
+
+    if (!npeakanal && !npeakout) npeakanal = DEFNPEAK, npeakout = 0;
+    if (!npeakanal < 0) npeakanal = 0;
+    else if (npeakanal > MAXPEAK) npeakanal = MAXPEAK;
+    if (!npeakout < 0) npeakout = 0;
+    else if (npeakout > MAXPEAK) npeakout = MAXPEAK;
+    if (npitch <= 0) npitch = 0;
+    else if (npitch > MAXNPITCH) npitch = MAXNPITCH;
+    if (npeakanal && !npitch) npitch = 1;
+    if (!npoints)
+        npoints = DEFAULTPOINTS;
+    if (!sigfiddle_setnpoints(x, npoints))
+    {
+        error("fiddle~: out of memory");
+        return (0);
+    }
+    if (!(buf4 = (t_peakout *)getbytes(sizeof(*buf4) * npeakout)))
+    {
+        sigfiddle_freebird(x);
+        error("fiddle~: out of memory");
+        return (0);
+    }
+    for (i = 0; i < npeakout; i++)
+        buf4[i].po_freq = buf4[i].po_amp = 0;
+    x->x_peakbuf = buf4;
+
+    x->x_npeakout = npeakout;
+    x->x_npeakanal = npeakanal;
+    x->x_phase = 0;
+    x->x_histphase = 0;
+    x->x_sr = 44100;            /* this and the next are filled in later */
+    for (i = 0; i < MAXNPITCH; i++)
+    {
+        int j;
+        x->x_hist[i].h_pitch = x->x_hist[i].h_noted = 0;
+        x->x_hist[i].h_age = 0;
+        x->x_hist[i].h_wherefrom = 0;
+        x->x_hist[i].h_outlet = 0;
+        for (j = 0; j < HISTORY; j++)
+            x->x_hist[i].h_amps[j] = x->x_hist[i].h_pitches[j] = 0;
+    }
+    x->x_nprint = 0;
+    x->x_npitch = npitch;
+    for (i = 0; i < HISTORY; i++) x->x_dbs[i] = 0;
+    x->x_dbage = 0;
+    x->x_peaked = 0;
+    x->x_auto = 1;
+    x->x_amplo = DEFAMPLO;
+    x->x_amphi = DEFAMPHI;
+    x->x_attacktime = DEFATTACKTIME;
+    x->x_attackbins = 1;                /* real value calculated afterward */
+    x->x_attackthresh = DEFATTACKTHRESH;
+    x->x_vibtime = DEFVIBTIME;
+    x->x_vibbins = 1;                   /* real value calculated afterward */
+    x->x_vibdepth = DEFVIBDEPTH;
+    x->x_npartial = 7;
+    x->x_attackvalue = 0;
+    return (1);
+}
+
+    /* formalities for JMAX */
+
+#ifdef JMAX
+
+void sigfiddle_debug13(fts_object_t *o, int winlet, fts_symbol_t s, int ac, const fts_atom_t *at)
+{
+  t_sigfiddle *x = (t_sigfiddle *)o;
+  sigfiddle_debug(x);
+}
+
+void sigfiddle_print13(fts_object_t *o, int winlet, fts_symbol_t s,
+    int ac, const fts_atom_t *at)
+{
+  t_sigfiddle *x = (t_sigfiddle *)o;
+  sigfiddle_print(x);
+}
+
+void sigfiddle_amprange13(fts_object_t *o, int winlet, fts_symbol_t s,
+    int ac, const fts_atom_t *at)
+{
+    t_sigfiddle *x = (t_sigfiddle *)o;
+    float lo =  (float) fts_get_float_arg(ac, at, 0, 0);
+    float hi =  (float) fts_get_float_arg(ac, at, 1, 0);
+    sigfiddle_amprange(x, lo, hi);
+}
+
+void sigfiddle_reattack13(fts_object_t *o, int winlet, fts_symbol_t s,
+    int ac, const fts_atom_t *at)
+{
+    t_sigfiddle *x = (t_sigfiddle *)o;
+    long msec =  fts_get_float_arg(ac, at, 0, 0);
+    float db =  (float) fts_get_float_arg(ac, at, 1, 0);
+    sigfiddle_reattack(x, msec, db);
+}
+
+void sigfiddle_vibrato13(fts_object_t *o, int winlet, fts_symbol_t s,
+    int ac, const fts_atom_t *at)
+{
+    t_sigfiddle *x = (t_sigfiddle *)o;
+    long msec =  fts_get_float_arg(ac, at, 0, 0);
+    float halftones =  (float) fts_get_float_arg(ac, at, 1, 0);
+    sigfiddle_vibrato(x, msec, halftones);
+}
+
+void sigfiddle_npartial13(fts_object_t *o, int winlet, fts_symbol_t s,
+    int ac, const fts_atom_t *at)
+{
+    t_sigfiddle *x = (t_sigfiddle *)o;
+    float npartial =  (float) fts_get_float_arg(ac, at, 0, 0);
+    sigfiddle_npartial(x, npartial);
+}
+
+
+void ftl_sigfiddle(fts_word_t *a)
+{
+    t_sigfiddle *x = (t_sigfiddle *)fts_word_get_long(a);
+    float *in = (float *)fts_word_get_long(a + 1);
+    long n_tick = fts_word_get_long(a + 2);
+
+    int count;
+    float *fp,  *fp2;
+    for (count = 0, fp = x->x_inbuf + x->x_phase;
+            count < n_tick; count++) *fp++ = *in++;
+    if (fp == x->x_inbuf + x->x_hop)
+    {
+        sigfiddle_doit(x);
+        x->x_phase = 0;
+        fts_alarm_set_delay(&x->x_clock, 0L);        /* output bang */
+        fts_alarm_arm(&x->x_clock);
+
+        if (x->x_nprint) x->x_nprint--;
+    }
+    else x->x_phase += n_tick;
+}
+
+void sigfiddle_put(fts_object_t *o, int winlet, fts_symbol_t *s, int ac, const fts_atom_t *at)
+{
+    t_sigfiddle *x = (t_sigfiddle *)o;
+    fts_dsp_descr_t *dsp = (fts_dsp_descr_t *)fts_get_long_arg(ac, at, 0, 0);
+    fts_atom_t a[3];
+
+    x->x_sr = fts_dsp_get_input_srate(dsp, 0);
+    sigfiddle_reattack(x, x->x_attacktime, x->x_attackthresh);
+    sigfiddle_vibrato(x, x->x_vibtime, x->x_vibdepth);
+
+    fts_set_long(a, (long)x);
+    fts_set_symbol(a+1, fts_dsp_get_input_name(dsp, 0));
+    fts_set_long(a+2, fts_dsp_get_input_size(dsp, 0));
+    dsp_add_funcall(dsp_symbol, 3, a);
+}
+
+void sigfiddle_tick(fts_alarm_t *alarm, void *p)
+{
+    fts_object_t *o = (fts_object_t *)p;
+    t_sigfiddle *x = (t_sigfiddle *)p;
+
+    int i;
+    t_pitchhist *ph;
+    fts_outlet_float(o, OUTLETpower, x->x_dbs[x->x_histphase]);
+    for (i = 0,  ph = x->x_hist; i < x->x_npitch; i++,  ph++)
+    {
+        fts_atom_t at[2];
+        fts_set_float(at, ph->h_pitches[x->x_histphase]);
+        fts_set_float(at+1, ph->h_amps[x->x_histphase]);
+        fts_outlet_list(o, OUTLETmicropitch3 - i, 2, at);
+    }
+    if (x->x_attackvalue) fts_outlet_bang(o, OUTLETattack);
+    for (i = 0,  ph = x->x_hist; i < x->x_npitch; i++,  ph++)
+        if (ph->h_pitch) fts_outlet_float(o, OUTLETpitch, ph->h_pitch);
+}
+
+static void sigfiddle_delete(fts_object_t *o, int winlet, fts_symbol_t *s, int ac,
+ const fts_atom_t *at)
+{
+  t_sigfiddle *x = (t_sigfiddle *)o;
+
+  fts_free(x->x_inbuf);
+  fts_free(x->x_lastanalysis);
+  fts_free(x->x_spiral);
+  dsp_list_remove(o);
+}
+
+static void sigfiddle_init(fts_object_t *o, int winlet, fts_symbol_t *s, int ac, const fts_atom_t *at)
+{
+    t_sigfiddle *x = (t_sigfiddle *)o;
+    float *buf1, *buf2,  *buf3;
+    int i, hop;
+    long npoints    = fts_get_long_arg(ac, at, 1, 0);
+    long npitch    = fts_get_long_arg(ac, at, 2, 0);
+    long npeakanal    = fts_get_long_arg(ac, at, 3, 0);
+    long npeakout    = fts_get_long_arg(ac, at, 4, 0);
+
+    if (!sigfiddle_doinit(x, npoints, npitch, npeakanal, npeakout))
+    {
+        post("fiddle~: initialization failed");
+        return;
+    }
+    hop = npoints>>1;
+    if (fts_fft_declaresize(hop) != fts_Success)
+        post("fiddle~: bad FFT size");
+
+    fts_alarm_init(&(x->x_clock), 0, sigfiddle_tick, x);
+    dsp_list_insert(o);
+}
+
+static fts_status_t sigfiddle_instantiate(fts_class_t *cl, int ac,
+    const fts_atom_t *at)
+{
+  int i;
+  fts_type_t a[5];
+
+  fts_class_init(cl, sizeof(t_sigfiddle), 1, 6, 0);  /* 1 inlet + 6 outlets */
+
+  /* the system methods */
+
+  a[0] = fts_Symbol;
+  a[1] = fts_Long | fts_OptArg;
+  a[2] = fts_Long | fts_OptArg;
+  fts_method_define(cl, fts_SystemInlet, fts_s_init, sigfiddle_init, 3, a);
+
+  fts_method_define(cl, fts_SystemInlet, fts_s_delete, sigfiddle_delete, 0, a);
+  a[0] = fts_Object;
+  fts_method_define(cl, fts_SystemInlet, fts_s_put, sigfiddle_put, 1, a);
+
+  /* class' own methods */
+  fts_method_define(cl, 0, fts_new_symbol("print"), sigfiddle_print13, 0, a);
+  fts_method_define(cl, 0, fts_new_symbol("debug"), sigfiddle_debug13, 0, a);
+  fts_method_define(cl, 0, fts_new_symbol("amp-range"), sigfiddle_amprange13,
+        0, a);
+  fts_method_define(cl, 0, fts_new_symbol("reattack"), sigfiddle_reattack13,
+        0, a);
+  fts_method_define(cl, 0, fts_new_symbol("vibrato"), sigfiddle_vibrato13,
+        0, a);
+  fts_method_define(cl, 0, fts_new_symbol("npartial"), sigfiddle_npartial13,
+        0, a);
+
+  /* classes signal inlets */
+  dsp_sig_inlet(cl, 0);                    /* declare signal input #0 */
+
+  /* classes outlets */
+  a[0] = fts_Float;
+  fts_outlet_type_define(cl, OUTLETpitch, fts_s_float, 1, a); /* declare outlet #0 */
+  fts_outlet_type_define(cl, OUTLETattack, fts_s_bang, 0, a); /* declare outlet #1 */
+  a[0] = fts_VarArgs;
+  fts_outlet_type_define(cl, OUTLETmicropitch1, fts_s_list, 1, a); /* declare outlet #2 */
+  fts_outlet_type_define(cl, OUTLETmicropitch2, fts_s_list, 1, a); /* declare outlet #3 */
+  fts_outlet_type_define(cl, OUTLETmicropitch3, fts_s_list, 1, a); /* declare outlet #4 */
+  a[0] = fts_Float;
+  fts_outlet_type_define(cl, OUTLETpower, fts_s_float, 1, a); /* declare outlet #5 */
+
+  dsp_symbol = fts_new_symbol("fiddle");
+  dsp_declare_function(dsp_symbol, ftl_sigfiddle);
+
+  /* DSP properties  */
+
+  fts_class_put_prop(cl, fts_s_dsp_is_sink, fts_true);
+
+  return(fts_Success);
+}
+
+void fiddle_config(void)
+{
+  sys_log(fiddle_version);
+  fts_metaclass_create(fts_new_symbol(CLASSNAME), sigfiddle_instantiate, fts_always_equiv);
+}
+
+fts_module_t fiddle_module =
+  {"fiddle", "sonic meat fiddle", fiddle_config, 0};
+
+#endif  /* JMAX */
+
+#ifdef PD
+
+static t_int *fiddle_perform(t_int *w)
+{
+    t_float *in = (t_float *)(w[1]);
+    t_sigfiddle *x = (t_sigfiddle *)(w[2]);
+    int n = (int)(w[3]);
+    int count;
+    float *fp;
+    if (!x->x_hop)
+        goto nono;
+    for (count = 0, fp = x->x_inbuf + x->x_phase; count < n; count++)
+        *fp++ = *in++;
+    if (fp == x->x_inbuf + x->x_hop)
+    {
+        sigfiddle_doit(x);
+        x->x_phase = 0;
+        if (x->x_auto) clock_delay(x->x_clock, 0L);
+        if (x->x_nprint) x->x_nprint--;
+    }
+    else x->x_phase += n;
+nono:
+    return (w+4);
+}
+
+void sigfiddle_dsp(t_sigfiddle *x, t_signal **sp)
+{
+    x->x_sr = sp[0]->s_sr;
+    sigfiddle_reattack(x, x->x_attacktime, x->x_attackthresh);
+    sigfiddle_vibrato(x, x->x_vibtime, x->x_vibdepth);
+    dsp_add(fiddle_perform, 3, sp[0]->s_vec, x, sp[0]->s_n);
+}
+
+    /* This is the callback function for the clock, but also acts as
+    the "bang" method; you can leave "auto" on to get this called
+    automatically (the default) or turn auto off and bang it yourself. */
+
+void sigfiddle_bang(t_sigfiddle *x)
+{
+    int i;
+    t_pitchhist *ph;
+    if (x->x_npeakout)
+    {
+        int npeakout = x->x_npeakout;
+        t_peakout *po;
+        for (i = 0, po = x->x_peakbuf; i < npeakout; i++, po++)
+        {
+            t_atom at[3];
+            SETFLOAT(at, i+1);
+            SETFLOAT(at+1, po->po_freq);
+            SETFLOAT(at+2, po->po_amp);
+            outlet_list(x->x_peakout, 0, 3, at);
+        }
+    }
+    outlet_float(x->x_envout, x->x_dbs[x->x_histphase]);
+    for (i = 0,  ph = x->x_hist; i < x->x_npitch; i++,  ph++)
+    {
+        t_atom at[2];
+        SETFLOAT(at, ph->h_pitches[x->x_histphase]);
+        SETFLOAT(at+1, ph->h_amps[x->x_histphase]);
+        outlet_list(ph->h_outlet, 0, 2, at);
+    }
+    if (x->x_attackvalue) outlet_bang(x->x_attackout);
+    for (i = 0,  ph = x->x_hist; i < x->x_npitch; i++,  ph++)
+        if (ph->h_pitch) outlet_float(x->x_noteout, ph->h_pitch);
+}
+
+void sigfiddle_ff(t_sigfiddle *x)               /* cleanup on free */
+{
+    if (x->x_inbuf)
+    {
+        freebytes(x->x_inbuf, sizeof(float) * x->x_hop);
+        freebytes(x->x_lastanalysis, sizeof(float) * (2*x->x_hop + 4 * FILTSIZE));
+        freebytes(x->x_spiral, sizeof(float) * 2*x->x_hop);
+        freebytes(x->x_peakbuf, sizeof(*x->x_peakbuf) * x->x_npeakout);
+        clock_free(x->x_clock);
+    }
+}
+
+static t_class *sigfiddle_class;
+
+void *sigfiddle_new(t_floatarg npoints, t_floatarg npitch,
+    t_floatarg fnpeakanal, t_floatarg fnpeakout)
+{
+    t_sigfiddle *x = (t_sigfiddle *)pd_new(sigfiddle_class);
+    int i;
+    int npeakanal = fnpeakanal, npeakout = fnpeakout;
+
+
+    if (!sigfiddle_doinit(x, npoints, npitch,
+        npeakanal, npeakout))
+    {
+        x->x_inbuf = 0;     /* prevent the free routine from cleaning up */
+        pd_free(&x->x_ob.ob_pd);
+        return (0);
+    }
+    x->x_noteout = outlet_new(&x->x_ob, gensym("float"));
+    x->x_attackout = outlet_new(&x->x_ob, gensym("bang"));
+    for (i = 0; i < x->x_npitch; i++)
+        x->x_hist[i].h_outlet = outlet_new(&x->x_ob, gensym("list"));
+    x->x_envout = outlet_new(&x->x_ob, gensym("float"));
+    if (x->x_npeakout)
+        x->x_peakout = outlet_new(&x->x_ob, gensym("list"));
+    else x->x_peakout = 0;
+    x->x_clock = clock_new(&x->x_ob.ob_pd, (t_method)sigfiddle_bang);
+    return (x);
+}
+
+void fiddle_tilde_setup(void)
+{
+    sigfiddle_class = class_new(gensym("fiddle~"), (t_newmethod)sigfiddle_new,
+        (t_method)sigfiddle_ff, sizeof(t_sigfiddle), 0,
+            A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0);
+    class_addmethod(sigfiddle_class, (t_method)sigfiddle_dsp,
+        gensym("dsp"), 0);
+    class_addmethod(sigfiddle_class, (t_method)sigfiddle_debug,
+        gensym("debug"), 0);
+    class_addmethod(sigfiddle_class, (t_method)sigfiddle_setnpoints,
+        gensym("npoints"), A_FLOAT, 0);
+    class_addmethod(sigfiddle_class, (t_method)sigfiddle_amprange,
+        gensym("amp-range"), A_FLOAT, A_FLOAT, 0);
+    class_addmethod(sigfiddle_class, (t_method)sigfiddle_reattack,
+        gensym("reattack"), A_FLOAT, A_FLOAT, 0);
+    class_addmethod(sigfiddle_class, (t_method)sigfiddle_vibrato,
+        gensym("vibrato"), A_FLOAT, A_FLOAT, 0);
+    class_addmethod(sigfiddle_class, (t_method)sigfiddle_npartial,
+        gensym("npartial"), A_FLOAT, 0);
+    class_addmethod(sigfiddle_class, (t_method)sigfiddle_auto,
+        gensym("auto"), A_FLOAT, 0);
+    class_addmethod(sigfiddle_class, (t_method)sigfiddle_print,
+        gensym("print"), 0);
+    class_addmethod(sigfiddle_class, nullfn, gensym("signal"), 0);
+    class_addbang(sigfiddle_class, sigfiddle_bang);
+    class_addcreator((t_newmethod)sigfiddle_new, gensym("fiddle"),
+        A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0);
+    post(fiddle_version);
+}
+
+void fiddle_setup(void)
+{
+    fiddle_tilde_setup();
+}
+#endif /* PD */
+
+#ifdef MAX26
+
+void cu_fiddle(float *in1, t_sigfiddle *x, int n)
+{
+    int count;
+    float *fp,  *fp2;
+    for (count = 0, fp = x->x_inbuf + x->x_phase;
+            count < n; count++) *fp++ = *in1++;
+    if (fp == x->x_inbuf + x->x_hop)
+    {
+        sigfiddle_doit(x);
+        x->x_phase = 0;
+        if (x->x_auto) clock_delay(x->x_clock, 0L);
+        if (x->x_nprint) x->x_nprint--;
+    }
+    else x->x_phase += n;
+}
+
+void sigfiddle_put(t_sigfiddle *x, long whether)
+{
+    if (whether)
+    {
+        u_stdout(x);
+        x->x_sr = x->x_io[0]->s_sr;
+        sigfiddle_reattack(x, x->x_attacktime, x->x_attackthresh);
+        sigfiddle_vibrato(x, x->x_vibtime, x->x_vibdepth);
+        dspchain_addc(cu_fiddle, 3,
+            x->x_io[0]->s_shit, x, x->x_io[0]->s_n);
+    }
+}
+
+void sigfiddle_tick(t_sigfiddle *x)     /* callback function for the clock */
+{
+    int i;
+    t_pitchhist *ph;
+    outlet_float(x->x_envout, x->x_dbs[x->x_histphase]);
+    for (i = 0,  ph = x->x_hist; i < x->x_npitch; i++,  ph++)
+    {
+        t_atom at[2];
+        SETFLOAT(at, ph->h_pitches[x->x_histphase]);
+        SETFLOAT(at+1, ph->h_amps[x->x_histphase]);
+        outlet_list(ph->h_outlet, NIL, 2, at);
+    }
+    if (x->x_attackvalue) outlet_bang(x->x_attackout);
+    for (i = 0,  ph = x->x_hist; i < x->x_npitch; i++,  ph++)
+        if (ph->h_pitch) outlet_float(x->x_noteout, ph->h_pitch);
+}
+
+void sigfiddle_ff(t_sigfiddle *x)               /* cleanup on free */
+{
+    if (x->x_inbuf)
+    {
+        freebytes(x->x_inbuf, sizeof(float) * x->x_hop);
+        freebytes(x->x_lastanalysis, sizeof(float) * (2*x->x_hop + 4 * FILTSIZE));
+        freebytes(x->x_spiral, sizeof(float) * 2*x->x_hop);
+        clock_free(x->x_clock);
+        u_clean(x);
+    }
+}
+
+t_externclass *sigfiddle_class;
+
+void *sigfiddle_new(long npoints, long npitch,
+    long npeakanal, long npeakout)
+{
+    t_sigfiddle *x = (t_sigfiddle *)obj_new(&sigfiddle_class, 0);
+    int i;
+
+    if (!sigfiddle_doinit(x, npoints, npitch, npeakanal, npeakout))
+    {
+        x->x_inbuf = 0;     /* prevent the free routine from cleaning up */
+        obj_free(x);
+        return (0);
+    }
+    u_setup(x, IN1, OUT0);
+    x->x_envout = outlet_new(x, gensym("float"));
+    for (i = 0; i < x->x_npitch; i++)
+        x->x_hist[i].h_outlet = outlet_new(x, gensym("list"));
+    x->x_attackout = outlet_new(x, gensym("bang"));
+    x->x_noteout = outlet_new(x, gensym("float"));
+    x->x_clock = clock_new(x, sigfiddle_tick);
+    return (x);
+}
+
+void fiddle_setup()
+{
+    c_extern(&sigfiddle_class, sigfiddle_new, sigfiddle_ff,
+        gensym("fiddle"), sizeof(t_sigfiddle), 0, A_DEFLONG, A_DEFLONG,
+            A_DEFLONG, A_DEFLONG, 0);
+    c_addmess(sigfiddle_put, gensym("put"), A_CANT, 0);
+    c_addmess(sigfiddle_debug, gensym("debug"), 0);
+    c_addmess(sigfiddle_amprange, gensym("amp-range"), A_FLOAT, A_FLOAT, 0);
+    c_addmess(sigfiddle_reattack, gensym("reattack"), A_FLOAT, A_FLOAT, 0);
+    c_addmess(sigfiddle_vibrato, gensym("vibrato"), A_LONG, A_FLOAT, 0);
+    c_addmess(sigfiddle_npartial, gensym("npartial"), A_FLOAT, 0);
+    c_addmess(sigfiddle_print, gensym("print"), 0);
+    u_inletmethod(0);   /* one signal input */
+#ifdef MAX
+    post(fiddle_version);
+#endif
+}
+
+#endif /* MAX26 */
+
+/************* Beginning of MSP Code ******************************/
+
+#ifdef MSP
+
+static t_int *fiddle_perform(t_int *w)
+{
+    t_float *in = (t_float *)(w[1]);
+    t_sigfiddle *x = (t_sigfiddle *)(w[2]);
+    int n = (int)(w[3]);
+    int count,inc = x->x_downsample;
+    float *fp;
+
+    if (x->x_obj.z_disabled)
+        goto skip;
+    for (count = 0, fp = x->x_inbuf + x->x_phase; count < n; count+=inc) {
+        *fp++ = *in;
+        in += inc;
+    }
+    if (fp == x->x_inbuf + x->x_hop)
+    {
+                sigfiddle_doit(x);
+                x->x_phase = 0;
+                if (x->x_auto) clock_delay(x->x_clock, 0L);
+                if (x->x_nprint) x->x_nprint--;
+    }
+    else x->x_phase += n;
+skip:
+    return (w+4);
+}
+
+void sigfiddle_dsp(t_sigfiddle *x, t_signal **sp)
+{
+     if (sp[0]->s_n > x->x_hop) {
+        x->x_downsample = sp[0]->s_n / x->x_hop;
+        post("* warning: fiddle~: will downsample input by %ld",x->x_downsample);
+        x->x_sr = sp[0]->s_sr / x->x_downsample;
+    } else {
+        x->x_downsample = 1;
+                x->x_sr = sp[0]->s_sr;
+        }
+        sigfiddle_reattack(x, x->x_attacktime, x->x_attackthresh);
+    sigfiddle_vibrato(x, x->x_vibtime, x->x_vibdepth);
+    dsp_add(fiddle_perform, 3, sp[0]->s_vec, x, sp[0]->s_n);
+}
+
+void sigfiddle_tick(t_sigfiddle *x)     /* callback function for the clock MSP*/
+{
+    int i;
+    t_pitchhist *ph;
+    if (x->x_npeakout)
+    {
+        int npeakout = x->x_npeakout;
+        t_peakout *po;
+        for (i = 0, po = x->x_peakbuf; i < npeakout; i++, po++)
+        {
+                t_atom at[3];
+                SETINT(at, i+1);
+                SETFLOAT(at+1, po->po_freq);
+                SETFLOAT(at+2, po->po_amp);
+                outlet_list(x->x_peakout, 0, 3, at);
+                }
+    }
+    outlet_float(x->x_envout, x->x_dbs[x->x_histphase]);
+    for (i = 0,  ph = x->x_hist; i < x->x_npitch; i++,  ph++)
+    {
+        t_atom at[2];
+        SETFLOAT(at, ph->h_pitches[x->x_histphase]);
+        SETFLOAT(at+1, ph->h_amps[x->x_histphase]);
+        outlet_list(ph->h_outlet, 0, 2, at);
+    }
+    if (x->x_attackvalue) outlet_bang(x->x_attackout);
+    for (i = 0,  ph = x->x_hist; i < x->x_npitch; i++,  ph++)
+        if (ph->h_pitch) outlet_float(x->x_noteout, ph->h_pitch);
+}
+
+void sigfiddle_bang(t_sigfiddle *x)             
+{
+    int i;
+    t_pitchhist *ph;
+    if (x->x_npeakout)
+    {
+        int npeakout = x->x_npeakout;
+        t_peakout *po;
+        for (i = 0, po = x->x_peakbuf; i < npeakout; i++, po++)
+        {
+            t_atom at[3];
+            SETLONG(at, i+1);
+            SETFLOAT(at+1, po->po_freq);
+            SETFLOAT(at+2, po->po_amp);
+            outlet_list(x->x_peakout, 0, 3, at);
+        }
+    }
+    outlet_float(x->x_envout, x->x_dbs[x->x_histphase]);
+    for (i = 0,  ph = x->x_hist; i < x->x_npitch; i++,  ph++)
+    {
+        t_atom at[2];
+        SETFLOAT(at, ph->h_pitches[x->x_histphase]);
+        SETFLOAT(at+1, ph->h_amps[x->x_histphase]);
+        outlet_list(ph->h_outlet, 0, 2, at);
+    }
+    if (x->x_attackvalue) outlet_bang(x->x_attackout);
+    for (i = 0,  ph = x->x_hist; i < x->x_npitch; i++,  ph++)
+        if (ph->h_pitch) outlet_float(x->x_noteout, ph->h_pitch);
+}
+
+
+void sigfiddle_ff(t_sigfiddle *x)               /* cleanup on free  MSP  */
+{
+
+    if (x->x_inbuf)
+    {
+        t_freebytes(x->x_inbuf, sizeof(float) * x->x_hop);
+        t_freebytes(x->x_lastanalysis, sizeof(float) * (2*x->x_hop + 4 *
+FILTSIZE));
+        t_freebytes(x->x_spiral, sizeof(float) * 2*x->x_hop);
+        t_freebytes(x->x_peakbuf, sizeof(*x->x_peakbuf) * x->x_npeakout);
+    }
+     dsp_free((t_pxobject *)x);
+}
+
+void *sigfiddle_class;
+
+void *sigfiddle_new(long npoints, long npitch,
+    long npeakanal, long npeakout)
+{
+    t_sigfiddle *x = (t_sigfiddle *)newobject(sigfiddle_class);
+    int i;
+
+    if (!sigfiddle_doinit(x, npoints, npitch, npeakanal, npeakout))
+    {
+        x->x_inbuf = 0;     /* prevent the free routine from cleaning up */
+        return (0);
+    }
+    dsp_setup((t_pxobject *)x,1);
+
+    x->x_clock = clock_new(x, (method)sigfiddle_tick);
+     if (x->x_npeakout)
+        x->x_peakout = listout((t_object *)x);
+    else x->x_peakout = 0;
+    x->x_envout = floatout((t_object *)x);
+    for (i = 0; i < x->x_npitch; i++)
+                x->x_hist[i].h_outlet = listout((t_object *)x);
+        x->x_attackout = bangout((t_object *)x);
+        x->x_noteout = floatout((t_object *)x);
+          return (x);
+
+
+}
+
+void main()
+{
+        setup(&sigfiddle_class, sigfiddle_new, (method)sigfiddle_ff,
+                (short)sizeof(t_sigfiddle), 0L, A_DEFLONG, A_DEFLONG,
+A_DEFLONG, A_DEFLONG, 0);
+        addmess((method)sigfiddle_dsp,          "dsp",
+        A_CANT, 0);
+    addmess((method)sigfiddle_debug,    "debug",                0);
+    addmess((method)sigfiddle_setnpoints, "npoints",    A_FLOAT, 0);
+    addmess((method)sigfiddle_amprange, "amp-range",    A_FLOAT, A_FLOAT, 0);
+    addmess((method)sigfiddle_reattack, "reattack",     A_FLOAT, A_FLOAT, 0);
+    addmess((method)sigfiddle_vibrato,  "vibrato",              A_FLOAT,
+A_FLOAT, 0);
+    addmess((method)sigfiddle_npartial, "npartial",     A_FLOAT, 0);
+    addmess((method)sigfiddle_auto,             "auto",
+        A_FLOAT, 0);
+    addmess((method)sigfiddle_print,    "print",                0);
+        addmess((method)sigfiddle_assist,       "assist",
+        A_CANT, 0);
+        addbang((method)sigfiddle_bang);
+    dsp_initclass();
+    rescopy('STR#',3748);
+    post(fiddle_version);
+}
+
+void sigfiddle_assist(t_sigfiddle *x, void *b, long m, long a, char *s)
+{
+        assist_string(3748,m,a,1,2,s);
+}
+
+void msp_fft(float *buf, long np, long inv)
+{
+        float *src,*real,*rp,*imag,*ip;
+        long i;
+
+        /*
+        // because this fft algorithm uses separate real and imaginary
+        // buffers
+        // we must split the real and imaginary parts into two buffers,
+        // then do the opposite on output
+        // a more ambitious person would either do an in-place conversion
+        // or rewrite the fft algorithm
+        */
+    
+        real = rp = msp_ffttemp;
+        imag = ip = real + MAXPOINTS;
+        src = buf;
+        for (i = 0; i < np; i++) {
+                *rp++ = *src++;
+                *ip++ = *src++;
+        }
+        if (inv)
+                ifft(np,real,imag);
+        else
+                fft(np,real,imag);
+        rp = real;
+        ip = imag;
+        src = buf;
+        for (i = 0; i < np; i++) {
+                *src++ = *rp++;
+                *src++ = *ip++;
+        }
+}
+
+#endif /* MSP */
diff --git a/extra/fiddle~/makefile b/extra/fiddle~/makefile
new file mode 100644
index 0000000000000000000000000000000000000000..247c905e63949ca49cce3985834625af1e2e7aad
--- /dev/null
+++ b/extra/fiddle~/makefile
@@ -0,0 +1,4 @@
+NAME=fiddle~
+CSYM=fiddle_tilde
+
+include ../makefile
diff --git a/extra/loop~/loop~-help.pd b/extra/loop~/loop~-help.pd
new file mode 100644
index 0000000000000000000000000000000000000000..a445b805eb55fa768f99352caf438b150650d248
--- /dev/null
+++ b/extra/loop~/loop~-help.pd
@@ -0,0 +1,74 @@
+#N canvas 33 0 647 662 12;
+#X floatatom 41 204 0 0 0 0 - - -;
+#X obj 254 382 print~;
+#X msg 254 347 bang;
+#X obj 41 338 loop~;
+#X floatatom 66 279 0 0 0 0 - - -;
+#X msg 55 252 bang;
+#X obj 183 382 print~;
+#X msg 183 347 bang;
+#N canvas 0 0 450 300 graph1 0;
+#X array array2 150000 float 0;
+#X coords 0 1 150000 -1 200 150 1;
+#X restore 393 464 graph;
+#X msg 393 622 \; array2 resize 150000;
+#X obj 25 613 soundfiler;
+#X obj 16 453 tabread4~ array2;
+#X obj 16 407 *~;
+#X obj 16 522 dac~;
+#X obj 16 499 hip~ 5;
+#X obj 62 411 samphold~;
+#X obj 16 430 +~;
+#X floatatom 96 303 0 0 0 0 - - -;
+#X obj 96 326 *~ 1000;
+#X msg 43 568 read ../doc/sound/bell.aiff array2;
+#X msg 43 591 read ../doc/sound/vocal.aiff array2;
+#X msg 47 229 set 0.5;
+#X text 95 196 left signal input is transposition (1 is normal \, 2
+is up an octave \, etc);
+#X text 82 4 loop~ - phase generator for looping samplers;
+#X text 116 228 set phase (0 to 1);
+#X text 104 253 reset phase to 0;
+#X text 104 278 right signal input is window size in samples;
+#X text 134 302 here's how to handle onsets;
+#X obj 16 476 *~;
+#X floatatom 167 432 0 0 0 0 - - -;
+#X obj 167 501 line~;
+#X obj 167 455 dbtorms;
+#X obj 167 478 pack 0 50;
+#X text 201 431 output level 0-100;
+#X text 187 326 print outputs;
+#X text 33 32 loop~ takes input signals to set a window size and transposition
+\, and outputs a phase and a sampled window size. The window size only
+changes at phase zero crossings and the phase output is adjusted so
+that changing window size doesn't change the transposition.;
+#X text 33 112 You can send "bang" or "set" message to force the phase
+to zero--you should mute the output before doing so. This may be desirable
+if you've set a large window size but then want to decrease it without
+waiting for the next phase crossing.;
+#X connect 0 0 3 0;
+#X connect 2 0 1 0;
+#X connect 3 0 6 0;
+#X connect 3 0 12 0;
+#X connect 3 0 15 1;
+#X connect 3 1 1 0;
+#X connect 3 1 12 1;
+#X connect 4 0 3 1;
+#X connect 5 0 3 0;
+#X connect 7 0 6 0;
+#X connect 11 0 28 0;
+#X connect 12 0 16 0;
+#X connect 14 0 13 0;
+#X connect 14 0 13 1;
+#X connect 15 0 16 1;
+#X connect 16 0 11 0;
+#X connect 17 0 18 0;
+#X connect 18 0 15 0;
+#X connect 19 0 10 0;
+#X connect 20 0 10 0;
+#X connect 21 0 3 0;
+#X connect 28 0 14 0;
+#X connect 29 0 31 0;
+#X connect 30 0 28 1;
+#X connect 31 0 32 0;
+#X connect 32 0 30 0;
diff --git a/extra/loop~/loop~.c b/extra/loop~/loop~.c
new file mode 100644
index 0000000000000000000000000000000000000000..2f440030750209ae2e9f0df0b852da79258e0a5b
--- /dev/null
+++ b/extra/loop~/loop~.c
@@ -0,0 +1,164 @@
+/* loop~ -- loop generator for sampling */
+
+/*  Copyright 1997-1999 Miller Puckette.
+Permission is granted to use this software for any purpose provided you
+keep this copyright notice intact.
+
+THE AUTHOR AND HIS EMPLOYERS MAKE NO WARRANTY, EXPRESS OR IMPLIED,
+IN CONNECTION WITH THIS SOFTWARE.
+
+This file is downloadable from http://www.crca.ucsd.edu/~msp .
+
+*/
+
+#ifdef PD
+#include "m_pd.h"
+#endif
+
+typedef struct _loopctl
+{
+    double l_phase;
+    float l_invwindow;
+    float l_window;
+    int l_resync;
+} t_loopctl;
+
+static void loopctl_run(t_loopctl *x, float *transposein,
+        float *windowin, float *rawout, float *windowout, int n)
+{
+    float window, invwindow;
+    double phase = x->l_phase;
+    if (x->l_resync)
+    {
+        window = *windowin;
+        if (window < 0)
+        {
+            if (window > -1)
+                window = -1;
+            invwindow = -1/window;
+        }
+        else
+        {
+            if (window < 1)
+                window = 1;
+            invwindow = 1/window;
+        }
+        x->l_resync = 0;
+    }
+    else
+    {
+        window = x->l_window;
+        phase = x->l_phase;
+        invwindow = x->l_invwindow;
+    }
+    while (n--)
+    {
+        double phaseinc = invwindow * *transposein++;
+        double newphase;
+        float nwind = *windowin++;
+        if (phaseinc >= 1 || phaseinc < 0)
+            phaseinc = 0;
+        newphase = phase + phaseinc;
+        if (newphase >= 1)
+        {
+            window = nwind;
+            if (window < 0)
+            {
+                if (window > -1)
+                    window = -1;
+                invwindow = -1/window;
+            }
+            else
+            {
+                if (window < 1)
+                    window = 1;
+                invwindow = 1/window;
+            }
+            newphase -= 1.;
+        }
+        phase = newphase;
+        *rawout++ = (float)phase;
+        *windowout++ = window;
+    }
+    x->l_invwindow = invwindow;
+    x->l_window = window;
+    x->l_phase = phase;
+}
+
+static void loopctl_init(t_loopctl *x)
+{
+    x->l_window = 1;
+    x->l_invwindow = 1;
+    x->l_phase = 0;
+}
+
+static void loopctl_set(t_loopctl *x, float val)
+{
+    if (val < 0 || val > 1)
+        val = 0;
+    x->l_phase = val;
+    x->l_resync = 1;
+}
+
+#ifdef PD
+
+typedef struct _loop
+{
+    t_object x_obj;
+    t_float x_f;
+    t_loopctl x_loopctl;
+} t_loop;
+
+static t_class *loop_class;
+
+static void *loop_new(void)
+{
+    t_loop *x = (t_loop *)pd_new(loop_class);
+    loopctl_init(&x->x_loopctl);
+    inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal);
+    outlet_new(&x->x_obj, gensym("signal"));
+    outlet_new(&x->x_obj, gensym("signal"));
+    return (x);
+}
+
+static t_int *loop_perform(t_int *w)
+{
+    t_loopctl *ctl = (t_loopctl *)(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]);
+    int n = (int)(w[6]);
+    loopctl_run(ctl, in1, in2, out1, out2, n);
+    return (w+7);
+}
+
+static void loop_dsp(t_loop *x, t_signal **sp)
+{
+    dsp_add(loop_perform, 6,
+        &x->x_loopctl, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec,
+            sp[0]->s_n);
+}
+
+static void loop_set(t_loop *x, t_floatarg val)
+{
+    loopctl_set(&x->x_loopctl, val);
+}
+
+static void loop_bang(t_loop *x)
+{
+    loopctl_set(&x->x_loopctl, 0);
+}
+
+void loop_tilde_setup(void)
+{
+    loop_class = class_new(gensym("loop~"), (t_newmethod)loop_new, 0,
+        sizeof(t_loop), 0, 0);
+    class_addmethod(loop_class, (t_method)loop_dsp, gensym("dsp"), A_CANT, 0);
+    CLASS_MAINSIGNALIN(loop_class, t_loop, x_f);
+    class_addmethod(loop_class, (t_method)loop_set, gensym("set"),
+        A_DEFFLOAT, 0);
+    class_addbang(loop_class, loop_bang);
+}
+
+#endif /* PD */
diff --git a/extra/loop~/makefile b/extra/loop~/makefile
new file mode 100644
index 0000000000000000000000000000000000000000..fd21f2b4cfb50667614d0c44b672bb200b57a0d3
--- /dev/null
+++ b/extra/loop~/makefile
@@ -0,0 +1,4 @@
+NAME=loop~
+CSYM=loop_tilde
+
+include ../makefile
diff --git a/extra/loop~/test-loop~.pd b/extra/loop~/test-loop~.pd
new file mode 100644
index 0000000000000000000000000000000000000000..9966483dfc683c1e504c9f1e9fec01aee09dc50e
--- /dev/null
+++ b/extra/loop~/test-loop~.pd
@@ -0,0 +1,58 @@
+#N canvas 33 0 680 609 12;
+#X floatatom 52 262 0 0 0 0 - - -;
+#X obj 261 346 print~;
+#X msg 47 373 bang;
+#X msg 274 313 bang;
+#X obj 52 306 loop~;
+#X floatatom 102 245 0 0 0 0 - - -;
+#N canvas 0 0 450 300 graph1 0;
+#X array array1 44100 float 0;
+#X coords 0 10 44100 0 200 150 1;
+#X restore 65 17 graph;
+#X msg 43 204 \; array1 resize 44100;
+#X obj 25 401 tabwrite~ array1;
+#X msg 208 371 bang;
+#X obj 176 402 tabwrite~ array1;
+#X msg 194 261 bang;
+#X obj 204 347 print~;
+#X msg 217 314 bang;
+#N canvas 0 0 450 300 graph1 0;
+#X array array2 150000 float 0;
+#X coords 0 1 150000 -1 200 150 1;
+#X restore 332 398 graph;
+#X msg 326 274 \; array2 resize 150000;
+#X obj 103 529 tabread4~ array2;
+#X obj 64 481 *~;
+#X obj 107 581 dac~;
+#X obj 105 552 hip~ 5;
+#X obj 123 482 samphold~;
+#X obj 102 506 +~;
+#X floatatom 106 430 0 0 0 0 - - -;
+#X obj 108 453 *~ 1000;
+#X obj 312 215 soundfiler;
+#X msg 330 170 read ../doc/sound/bell.aiff array2;
+#X msg 330 193 read ../doc/sound/vocal.aiff array2;
+#X connect 0 0 4 0;
+#X connect 2 0 8 0;
+#X connect 3 0 1 0;
+#X connect 4 0 12 0;
+#X connect 4 0 17 0;
+#X connect 4 0 8 0;
+#X connect 4 0 20 1;
+#X connect 4 1 10 0;
+#X connect 4 1 1 0;
+#X connect 4 1 17 1;
+#X connect 5 0 4 1;
+#X connect 9 0 10 0;
+#X connect 11 0 4 0;
+#X connect 13 0 12 0;
+#X connect 16 0 19 0;
+#X connect 17 0 21 0;
+#X connect 19 0 18 0;
+#X connect 19 0 18 1;
+#X connect 20 0 21 1;
+#X connect 21 0 16 0;
+#X connect 22 0 23 0;
+#X connect 23 0 20 0;
+#X connect 25 0 24 0;
+#X connect 26 0 24 0;
diff --git a/extra/lrshift~/lrshift~-help.pd b/extra/lrshift~/lrshift~-help.pd
new file mode 100644
index 0000000000000000000000000000000000000000..fdf7b0c53f0d22f20bb55d26e089c70b71c3b9de
--- /dev/null
+++ b/extra/lrshift~/lrshift~-help.pd
@@ -0,0 +1,33 @@
+#N canvas 143 0 673 325 12;
+#X msg 268 277 bang;
+#X obj 244 303 print~;
+#X msg 185 278 bang;
+#X obj 161 304 print~;
+#X text 53 117 click here first;
+#X msg 72 270 bang;
+#X obj 48 296 print~;
+#X text 162 222 shift left;
+#X text 243 224 shift right;
+#X obj 161 252 lrshift~ 1;
+#X obj 244 251 lrshift~ -1;
+#X text 39 37 Acting at whatever vector size the window is running
+at \, lrshift~ shifts samples to the left (toward the beginning sample)
+or to the right. The argument gives the direction and the amount of
+the shift. The rightmost (or leftmost) samples are set to zero.;
+#N canvas 0 0 450 300 (subpatch) 0;
+#X array shiftin 64 float 0;
+#X coords 0 1 63 0 200 140 1;
+#X restore 448 118 graph;
+#X text 115 11 -- shift signal vector elements left or right;
+#X msg 54 138 \; pd dsp 1 \; shiftin 1 1;
+#X obj 48 204 tabreceive~ shiftin;
+#X text 525 308 Updated for Pd 0.31.;
+#X obj 47 11 lrshift~;
+#X connect 0 0 1 0;
+#X connect 2 0 3 0;
+#X connect 5 0 6 0;
+#X connect 9 0 3 0;
+#X connect 10 0 1 0;
+#X connect 15 0 6 0;
+#X connect 15 0 9 0;
+#X connect 15 0 10 0;
diff --git a/extra/lrshift~/lrshift~.c b/extra/lrshift~/lrshift~.c
new file mode 100644
index 0000000000000000000000000000000000000000..166facc161ae686d8a12498054ff9b5dc3c8daf6
--- /dev/null
+++ b/extra/lrshift~/lrshift~.c
@@ -0,0 +1,76 @@
+#include "m_pd.h"
+
+/* ------------------------ lrshift~ ----------------------------- */
+
+static t_class *lrshift_tilde_class;
+
+typedef struct _lrshift_tilde
+{
+    t_object x_obj;
+    int x_n;
+    float x_f;
+} t_lrshift_tilde;
+
+static t_int *leftshift_perform(t_int *w)
+{
+    t_float *in = (t_float *)(w[1]);
+    t_float *out= (t_float *)(w[2]);
+    int n = (int)(w[3]);
+    int shift = (int)(w[4]);
+    in += shift;
+    n -= shift;
+    while (n--)
+        *out++ = *in++;
+    while (shift--)
+        *out++ = 0;
+    return (w+5);
+}
+
+static t_int *rightshift_perform(t_int *w)
+{
+    t_float *in = (t_float *)(w[1]);
+    t_float *out= (t_float *)(w[2]);
+    int n = (int)(w[3]);
+    int shift = (int)(w[4]);
+    n -= shift;
+    in -= shift;
+    while (n--)
+        *--out = *--in;
+    while (shift--)
+        *--out = 0;
+    return (w+5);
+}
+
+static void lrshift_tilde_dsp(t_lrshift_tilde *x, t_signal **sp)
+{
+    int n = sp[0]->s_n;
+    int shift = x->x_n;
+    if (shift > n)
+        shift = n;
+    if (shift < -n)
+        shift = -n;
+    if (shift < 0)
+        dsp_add(rightshift_perform, 4,
+            sp[0]->s_vec + n, sp[1]->s_vec + n, n, -shift);
+    else dsp_add(leftshift_perform, 4,
+            sp[0]->s_vec, sp[1]->s_vec, n, shift);
+}
+
+static void *lrshift_tilde_new(t_floatarg f)
+{
+    t_lrshift_tilde *x = (t_lrshift_tilde *)pd_new(lrshift_tilde_class);
+    x->x_n = f;
+    x->x_f = 0;
+    outlet_new(&x->x_obj, gensym("signal"));
+    return (x);
+}
+
+void lrshift_tilde_setup(void)
+{
+    lrshift_tilde_class = class_new(gensym("lrshift~"),
+        (t_newmethod)lrshift_tilde_new, 0, sizeof(t_lrshift_tilde), 0, 
+            A_DEFFLOAT, 0);
+    CLASS_MAINSIGNALIN(lrshift_tilde_class, t_lrshift_tilde, x_f);
+    class_addmethod(lrshift_tilde_class, (t_method)lrshift_tilde_dsp,
+        gensym("dsp"), 0);
+}
diff --git a/extra/lrshift~/makefile b/extra/lrshift~/makefile
new file mode 100644
index 0000000000000000000000000000000000000000..d6a24cfe3ccdffb1dd822d1ea65cacccaf54bafb
--- /dev/null
+++ b/extra/lrshift~/makefile
@@ -0,0 +1,4 @@
+NAME=lrshift~
+CSYM=lrshift_tilde
+
+include ../makefile
diff --git a/extra/pd~/makefile b/extra/pd~/makefile
new file mode 100644
index 0000000000000000000000000000000000000000..d069c73dc5ae6db2521c25df751ff5c21b04cec8
--- /dev/null
+++ b/extra/pd~/makefile
@@ -0,0 +1,15 @@
+NAME=pd~
+CSYM=pd_tilde
+
+include ../makefile
+
+pd_linux: pdsched.pd_linux
+
+d_fat: pdsched.d_fat
+d_ppc: pdsched.d_ppc
+
+pdsched.pd_linux: pdsched.c
+	$(CC) $(LINUXCFLAGS) $(LINUXINCLUDE) -o $*.o -c $*.c
+	$(CC) -shared -o $*.pd_linux $*.o -lc -lm
+	strip --strip-unneeded $*.pd_linux
+	rm -f $*.o
diff --git a/extra/pd~/notes.txt b/extra/pd~/notes.txt
new file mode 100644
index 0000000000000000000000000000000000000000..59129d5abb0f5830b7e9b575a9a880817d7e7f15
--- /dev/null
+++ b/extra/pd~/notes.txt
@@ -0,0 +1,8 @@
+pd -schedlib `pwd`/pdsched
+
+dolist:
+pd~ to delay starting subproc until asked
+figure out about setting nchannels from command line
+fix maximum nchannels in and out
+
+
diff --git a/extra/pd~/pdsched.c b/extra/pd~/pdsched.c
new file mode 100644
index 0000000000000000000000000000000000000000..7efe49a959607e17c86387de6ae8a2abe258fef5
--- /dev/null
+++ b/extra/pd~/pdsched.c
@@ -0,0 +1,85 @@
+/* Copyright 2008 Miller Puckette.  Berkeley license; see the
+file LICENSE.txt in this distribution. */
+
+/* A plug-in scheduler that turns Pd into a filter that inputs and
+outputs audio and messages. */
+
+/* todo: 
+    fix schedlib code to use extent2
+    figure out about  if (sys_externalschedlib) { return; } in s_audio.c
+    make buffer size ynamically growable
+
+*/    
+#include "m_pd.h"
+#include "s_stuff.h"
+#include <stdio.h>
+
+#define BUFSIZE 65536
+static char inbuf[BUFSIZE];
+
+int pd_extern_sched(char *flags)
+{
+    int naudioindev, audioindev[MAXAUDIOINDEV], chindev[MAXAUDIOINDEV];
+    int naudiooutdev, audiooutdev[MAXAUDIOOUTDEV], choutdev[MAXAUDIOOUTDEV];
+    int i, j, rate, advance, callback, chin, chout, fill = 0, c;
+    t_binbuf *b = binbuf_new();
+
+    sys_get_audio_params(&naudioindev, audioindev, chindev,
+        &naudiooutdev, audiooutdev, choutdev, &rate, &advance, &callback);
+
+    chin = (naudioindev < 1 ? 0 : chindev[0]);
+    chout = (naudiooutdev < 1 ? 0 : choutdev[0]);
+
+    fprintf(stderr, "Pd plug-in scheduler called, chans %d %d, sr %d\n",
+        chin, chout, (int)rate);
+    sys_setchsr(chin, chout, rate);
+    sys_audioapi = API_NONE;
+    while ((c = getchar()) != EOF)
+    {
+        if (c == ';')
+        {
+            int n;
+            t_atom *ap;
+            binbuf_text(b, inbuf, fill);
+            n = binbuf_getnatom(b);
+            ap = binbuf_getvec(b);
+            fill = 0;
+            if (n > 0 && ap[0].a_type == A_FLOAT)
+            {
+                /* a list -- take it as incoming signals. */
+                int chan, nchan = n/DEFDACBLKSIZE;
+                t_sample *fp;
+                for (i = chan = 0, fp = sys_soundin; chan < nchan; chan++)
+                    for (j = 0; j < DEFDACBLKSIZE; j++)
+                        *fp++ = atom_getfloat(ap++);
+                for (; chan < chin; chan++)
+                    for (j = 0; j < DEFDACBLKSIZE; j++)
+                        *fp++ = 0;
+                sched_tick(sys_time+sys_time_per_dsp_tick);
+                sys_pollgui();
+                printf(";\n");
+                for (i = chout*DEFDACBLKSIZE, fp = sys_soundout; i--; fp++)
+                {
+                    printf("%g\n", *fp);
+                    *fp = 0;
+                }
+                printf(";\n");
+                fflush(stdout);
+            }
+            else if (n > 1 && ap[0].a_type == A_SYMBOL)
+            {
+                t_pd *whom = ap[0].a_w.w_symbol->s_thing;
+                if (!whom)
+                    error("%s: no such object", ap[0].a_w.w_symbol->s_name);
+                else if (ap[1].a_type == A_SYMBOL)
+                    typedmess(whom, ap[1].a_w.w_symbol, n-2, ap+2);
+                else pd_list(whom, 0, n-1, ap+1);
+            }
+        }
+        else if (fill < BUFSIZE)
+            inbuf[fill++] = c;
+        else if (fill == BUFSIZE)
+            fprintf(stderr, "pd-extern: input buffer overflow\n");
+    }
+    return (0);
+}
diff --git a/extra/pd~/pd~-help.pd b/extra/pd~/pd~-help.pd
new file mode 100644
index 0000000000000000000000000000000000000000..8bc357e0c7b62b9809a578b0cd0751825bc89efb
--- /dev/null
+++ b/extra/pd~/pd~-help.pd
@@ -0,0 +1,75 @@
+#N canvas 12 0 566 872 12;
+#X msg 31 406 foo bar baz;
+#X obj 189 466 osc~ 440;
+#X obj 127 645 env~ 8192;
+#X floatatom 127 694 5 0 0 0 - - -;
+#X msg 434 807 \; pd dsp 1;
+#X msg 24 332 pd~ stop;
+#X obj 127 670 i;
+#X obj 241 643 env~ 8192;
+#X floatatom 241 693 5 0 0 0 - - -;
+#X obj 241 669 i;
+#X obj 123 489 *~;
+#X obj 158 490 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0
+1;
+#X obj 189 490 *~;
+#X obj 224 491 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0
+1;
+#X obj 434 781 loadbang;
+#X obj 14 691 print x;
+#X msg 15 309 pd~ start pd~-subprocess.pd;
+#X obj 14 532 pd~ -ninsig 2 -noutsig 2 -fifo 20;
+#X obj 37 20 pd~;
+#X text 69 22 - run a pd sub-process;
+#X text 27 57 The pd~ object starts and manages a Pd sub-process that
+can communicate with the super-process (this one) via audio channels
+and/or Pd messages. In this way you can take advantage of multi-core
+CPUs \, and/or use Pd features from within Max (if you're using the
+Max version of pd~).;
+#X text 24 251 Sending a new "start" message will stop the sub-process
+and start a new one. If you just want to stop the sub-process \, send
+"stop".;
+#X text 33 353 Any message besides "pd~" is sent to the sub-process.
+For instance \, the message below sends "bar baz" to any object in
+the sub-process named "foo" \, such as a "receive" object.;
+#X text 43 430 Audio signals appear in adc~ objects in the sub-process.
+The sub-process doesn't open real audio devices.;
+#X text 281 473 Creation args:;
+#X text 265 490 -insig <n> sets input audio channels;
+#X text 266 508 -outsig <n> sets output channels;
+#X text 269 542 -fifo <n> sets round-trip delay in blocks;
+#X text 272 559 -pddir <s> sets Pd directory \, e.g. \,;
+#X text 299 574 .../Pd-0.42.app/Contents/Resources;
+#X text 272 590 -scheddir <s> sets scheduler dir \, e.g. \,;
+#X text 297 607 .../.../Resources/extra/pd~;
+#X text 267 524 -sr <n> sets sample rate;
+#X text 20 716 The first outlet reports messages the sub-process sends
+us via "stdout" objects. Any other outlets are signals corresponding
+to "dac~" objects in the sub-process.;
+#X text 10 784 ATTENTION: DSP must be running in this process for the
+sub-process to run. This is because its clock is slaved to audio I/O
+it gets from us!;
+#X text 359 849 Updated for Pd version 0.42.;
+#X text 24 138 Messages with "pd~" selector control the sub-process.
+"pd~ start" takes as arguments any startup arguments you wish to send
+the sub-process. For example \, specify "-nogui" to stop the sub-process's
+GUI from appearing. You don't have to specify the number of channels
+in and out \, since that's set by creation arguments below. Audio config
+arguments arguments (-audiobuf \, -audiodev \, etc.) are ignored.;
+#X connect 0 0 17 0;
+#X connect 1 0 10 0;
+#X connect 1 0 12 0;
+#X connect 2 0 6 0;
+#X connect 5 0 17 0;
+#X connect 6 0 3 0;
+#X connect 7 0 9 0;
+#X connect 9 0 8 0;
+#X connect 10 0 17 0;
+#X connect 11 0 10 1;
+#X connect 12 0 17 1;
+#X connect 13 0 12 1;
+#X connect 14 0 4 0;
+#X connect 16 0 17 0;
+#X connect 17 0 15 0;
+#X connect 17 1 2 0;
+#X connect 17 2 7 0;
diff --git a/extra/pd~/pd~-subprocess.pd b/extra/pd~/pd~-subprocess.pd
new file mode 100644
index 0000000000000000000000000000000000000000..1d883ab18862f32895c2aafeb63910822fdbf9cf
--- /dev/null
+++ b/extra/pd~/pd~-subprocess.pd
@@ -0,0 +1,60 @@
+#N canvas 577 21 563 559 12;
+#X obj 202 395 r foo;
+#X obj 202 423 print foo;
+#X obj 87 174 adc~;
+#X obj 72 442 stdout;
+#X msg 72 364 a b c;
+#X msg 455 441 \; pd dsp 1;
+#X obj 87 201 env~ 8192;
+#X floatatom 87 250 5 0 0 0 - - -;
+#X obj 87 226 i;
+#X obj 263 253 dac~;
+#X obj 262 185 osc~ 440;
+#X obj 262 219 *~;
+#X obj 297 220 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0
+1;
+#X obj 332 186 osc~ 440;
+#X obj 332 220 *~;
+#X obj 367 221 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0
+1;
+#X msg 86 411 bang;
+#X obj 455 417 loadbang;
+#X obj 160 201 env~ 8192;
+#X floatatom 160 250 5 0 0 0 - - -;
+#X obj 160 226 i;
+#X msg 86 388 4;
+#X text 62 8 This is a test patch to demonstrate the Pd~ object. It's
+intended as the patch to run in the sub-process. The sub-process (which
+is a separate instance of Pd) can be called from a Max or Pd super-process.
+;
+#X text 63 73 Audio inlets and outlets on the Pd~ object (in the super-process)
+talk to adc~ and dac~ objects here - so \, for instance \, the first
+adc~ here is the first inlet of the pd~ object \, and the first chanel
+of dac~ goes to the second outlet of pd~ (because the first one is
+for messages \, as shown further below.);
+#X text 58 283 Any message sent to a stdout object in this sub-process
+(below) appears on the first \, message outlet of the pd~ object in
+the super-process. The super-process can send messages to any "receive"
+object in this sub-process.;
+#X text 137 478 We turn DSP on at load for convenience - control objects
+in this patch will still work without it (unlike in the super-process
+\, where DSP must be on for time to move forward in the sub-process.)
+;
+#X text 351 538 Updated for Pd version 0.42.;
+#X connect 0 0 1 0;
+#X connect 2 0 6 0;
+#X connect 2 1 18 0;
+#X connect 4 0 3 0;
+#X connect 6 0 8 0;
+#X connect 8 0 7 0;
+#X connect 10 0 11 0;
+#X connect 11 0 9 0;
+#X connect 12 0 11 1;
+#X connect 13 0 14 0;
+#X connect 14 0 9 1;
+#X connect 15 0 14 1;
+#X connect 16 0 3 0;
+#X connect 17 0 5 0;
+#X connect 18 0 20 0;
+#X connect 20 0 19 0;
+#X connect 21 0 3 0;
diff --git a/extra/pd~/pd~.c b/extra/pd~/pd~.c
new file mode 100644
index 0000000000000000000000000000000000000000..165065f8a90e2a64d6c4b80a90355b0a569b3207
--- /dev/null
+++ b/extra/pd~/pd~.c
@@ -0,0 +1,765 @@
+/*
+  pd~.c - embed a Pd process within Pd or Max.
+
+  Copyright 2008 Miller Puckette
+  BSD license; see README.txt in this distribution for details.
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#ifdef NT
+#pragma warning (disable: 4305 4244)
+#endif
+
+#ifdef MSP
+#include "ext.h"
+#include "z_dsp.h"
+#include "math.h"
+#include "ext_support.h"
+#include "ext_proto.h"
+#include "ext_obex.h"
+
+typedef double t_floatarg;
+#define w_symbol w_sym
+#define A_SYMBOL A_SYM
+#define getbytes t_getbytes
+#define freebytes t_freebytes
+#define ERROR error(
+void *pd_tilde_class;
+#define MAXPDSTRING 4096
+#define DEFDACBLKSIZE 64
+#endif /* MSP */
+
+#ifdef PD
+#include "m_pd.h"
+#include "s_stuff.h"
+static t_class *pd_tilde_class;
+char *class_gethelpdir(t_class *c);
+#define ERROR pd_error(x, 
+
+#endif
+
+#ifdef __linux__
+#ifdef __x86_64__
+static char pd_tilde_dllextent[] = ".l_ia64",
+    pd_tilde_dllextent2[] = ".pd_linux";
+#else
+static char pd_tilde_dllextent[] = ".l_i386",
+    pd_tilde_dllextent2[] = ".pd_linux";
+#endif
+#endif
+#ifdef __APPLE__
+static char pd_tilde_dllextent[] = ".d_fat",
+    pd_tilde_dllextent2[] = ".pd_darwin";
+#endif
+
+/* ------------------------ pd_tilde~ ----------------------------- */
+
+#define MSGBUFSIZE 65536
+
+typedef struct _pd_tilde
+{
+#ifdef PD
+    t_object x_obj;
+    t_clock *x_clock;
+    t_outlet *x_outlet1;        /* for messages back from subproc */
+    t_canvas *x_canvas;
+#endif /* PD */
+#ifdef MSP
+    t_pxobject x_obj;
+    void *x_outlet1;
+    void *x_clock;
+#endif /* MSP */
+    FILE *x_infd;
+    FILE *x_outfd;
+    char *x_msgbuf;
+    int x_msgbufsize;
+    int x_infill;
+    int x_childpid;
+    int x_ninsig;
+    int x_noutsig;
+    int x_fifo;
+    float x_sr;
+    t_symbol *x_pddir;
+    t_symbol *x_schedlibdir;
+    t_sample **x_insig;
+    t_sample **x_outsig;
+} t_pd_tilde;
+
+#ifdef MSP
+static void *pd_tilde_new(t_symbol *s, long ac, t_atom *av);
+static void pd_tilde_tick(t_pd_tilde *x);
+static t_int *pd_tilde_perform(t_int *w);
+static void pd_tilde_dsp(t_pd_tilde *x, t_signal **sp);
+void pd_tilde_assist(t_pd_tilde *x, void *b, long m, long a, char *s);
+static void pd_tilde_free(t_pd_tilde *x);
+void pd_tilde_setup(void);
+int main();
+void pd_tilde_minvel_set(t_pd_tilde *x, void *attr, long ac, t_atom *av);
+char *strcpy(char *s1, const char *s2);
+#endif
+
+static void pd_tilde_tick(t_pd_tilde *x);
+static void pd_tilde_close(t_pd_tilde *x)
+{
+    if (x->x_outfd)
+        fclose(x->x_outfd);
+    if (x->x_infd)
+        fclose(x->x_infd);
+    if (x->x_childpid > 0)
+        waitpid(x->x_childpid, 0, 0);
+    if (x->x_msgbuf)
+        free(x->x_msgbuf);
+    x->x_infd = x->x_outfd = 0;
+    x->x_childpid = -1;
+    x->x_msgbuf = 0;
+    x->x_msgbufsize = 0;
+}
+
+static void pd_tilde_readmessages(t_pd_tilde *x)
+{
+    int gotsomething = 0, setclock = 0, wasempty = (x->x_infill == 0);
+    FILE *infd = x->x_infd;
+    while (1)
+    {
+        int c = getc(infd);
+        if (c == EOF)
+        {
+            ERROR "pd~: %s", strerror(errno));
+            pd_tilde_close(x);
+            break;
+        }
+        if (x->x_infill >= x->x_msgbufsize)
+        {
+            char *z = realloc(x->x_msgbuf, x->x_msgbufsize+MSGBUFSIZE);
+            if (!z)
+            {
+                ERROR "pd~: failed to grow input buffer");
+                pd_tilde_close(x);
+                break;
+            }
+            x->x_msgbuf = z;
+            x->x_msgbufsize += MSGBUFSIZE;
+        }
+        x->x_msgbuf[x->x_infill++] = c;
+        if (c == ';')
+        {
+            if (!gotsomething)
+                break;
+            gotsomething = 0;
+        }
+        else if (!isspace(c))
+            gotsomething = setclock = 1;
+    }
+    if (setclock)
+        clock_delay(x->x_clock, 0);
+    else if (wasempty)
+        x->x_infill = 0;
+}
+
+static void pd_tilde_donew(t_pd_tilde *x, char *pddir, char *schedlibdir,
+    char *patchdir, char *pdargs, int ninsig, int noutsig, int fifo,
+    float samplerate)
+{
+    int i, pid, pipe1[2], pipe2[2];
+    char cmdbuf[MAXPDSTRING], pdexecbuf[MAXPDSTRING], schedbuf[MAXPDSTRING];
+    struct stat statbuf;
+    x->x_infd = x->x_outfd = 0;
+    x->x_childpid = -1;
+    snprintf(pdexecbuf, MAXPDSTRING, "%s/bin/pd", pddir);
+    if (stat(pdexecbuf, &statbuf) < 0)
+    {
+        snprintf(pdexecbuf, MAXPDSTRING, "%s/../../../bin/pd", pddir);
+        if (stat(pdexecbuf, &statbuf) < 0)
+        {
+            snprintf(pdexecbuf, MAXPDSTRING, "%s/pd", pddir);
+            if (stat(pdexecbuf, &statbuf) < 0)
+            {
+                ERROR "pd~: can't stat %s", pdexecbuf);
+                goto fail1;
+            }
+        }
+    }
+    snprintf(schedbuf, MAXPDSTRING, "%s/pdsched%s", schedlibdir, 
+        pd_tilde_dllextent);
+    if (stat(schedbuf, &statbuf) < 0)
+    {
+        snprintf(schedbuf, MAXPDSTRING, "%s/pdsched%s", schedlibdir, 
+            pd_tilde_dllextent2);
+        if (stat(schedbuf, &statbuf) < 0)
+        {
+            ERROR "pd~: can't stat %s", schedbuf);
+            goto fail1;
+        }       
+    }
+    snprintf(cmdbuf, MAXPDSTRING,
+"%s -schedlib %s/pdsched -path %s -inchannels %d -outchannels %d -r %g %s\n",
+        pdexecbuf, schedlibdir, patchdir, ninsig, noutsig, samplerate, pdargs);
+#if 0
+#ifdef PD
+    fprintf(stderr, "%s", cmdbuf);
+#endif
+    post("cmd: %s", cmdbuf);
+#endif
+    if (pipe(pipe1) < 0)   
+    {
+        ERROR "pd~: can't create pipe");
+        goto fail1;
+    }
+    if (pipe(pipe2) < 0)   
+    {
+        ERROR "pd~: can't create pipe");
+        goto fail2;
+    }
+    if ((pid = fork()) < 0)
+    {
+        ERROR "pd~: can't fork");
+        goto fail3;
+    }
+    else if (pid == 0)
+    {
+        /* child process */
+        if (pipe2[1] == 0)
+        {
+            dup2(pipe2[1], 20);
+            close(pipe2[1]);
+            pipe2[1] = 20;
+        }
+        dup2(pipe1[0], 0);
+        dup2(pipe2[1], 1);
+        if (pipe1[0] >= 2)
+            close(pipe1[0]);
+        if (pipe1[1] >= 2)
+            close(pipe1[1]);
+        if (pipe2[0] >= 2)
+            close(pipe2[0]);
+        if (pipe2[1] >= 2)
+            close(pipe2[1]);
+        execl("/bin/sh", "sh", "-c", cmdbuf, (char*)0);
+        _exit(1);
+    }
+        /* OK, we're parent */
+    close(pipe1[0]);
+    close(pipe2[1]);
+    x->x_outfd = fdopen(pipe1[1], "w");
+    x->x_infd = fdopen(pipe2[0], "r");
+    x->x_childpid = pid;
+    for (i = 0; i < fifo; i++)
+        fprintf(x->x_outfd, "%s", ";\n0;\n");
+    fflush(x->x_outfd);
+    if (!(x->x_msgbuf = calloc(MSGBUFSIZE, 1)))
+    {
+        ERROR "pd~: can't allocate message buffer");
+        goto fail3;
+    }
+    x->x_msgbufsize = MSGBUFSIZE;
+    x->x_infill = 0;
+    /* fprintf(stderr, "read...\n"); */
+    pd_tilde_readmessages(x);
+    /* fprintf(stderr, "... done.\n"); */
+    return;
+fail3:
+    close(pipe2[0]);
+    close(pipe2[1]);
+    if (x->x_childpid > 0)
+        waitpid(x->x_childpid, 0, 0);
+fail2:
+    close(pipe1[0]);
+    close(pipe1[1]);
+fail1:
+    x->x_infd = x->x_outfd = 0;
+    x->x_childpid = -1;
+    return;
+}
+
+static t_int *pd_tilde_perform(t_int *w)
+{
+    t_pd_tilde *x = (t_pd_tilde *)(w[1]);
+    int n = (int)(w[2]), i, j, numbuffill = 0, c;
+    char numbuf[80];
+    FILE *infd = x->x_infd;
+    if (!infd)
+        goto zeroit;
+    fprintf(x->x_outfd, ";\n");
+    if (!x->x_ninsig)
+        fprintf(x->x_outfd, "0\n");
+    else for (i = 0; i < x->x_ninsig; i++)
+    {
+        t_sample *fp = x->x_insig[i];
+        for (j = 0; j < n; j++)
+            fprintf(x->x_outfd, "%g\n", *fp++);
+        for (; j < DEFDACBLKSIZE; j++)
+            fprintf(x->x_outfd, "0\n");
+    }
+    fprintf(x->x_outfd, ";\n");
+    fflush(x->x_outfd);
+    i = j = 0;
+    while (1)
+    {
+        while (1)
+        {
+            c = getc(infd);
+            if (c == EOF)
+            {
+                if (errno)
+                    ERROR "pd~: %s", strerror(errno));
+                else ERROR "pd~: subprocess exited");
+                pd_tilde_close(x);
+                goto zeroit;
+            }
+            else if (!isspace(c) && c != ';')
+            {
+                if (numbuffill < (80-1))
+                    numbuf[numbuffill++] = c;
+            }
+            else
+            {
+                t_sample z;
+                if (numbuffill)
+                {
+                    numbuf[numbuffill] = 0;
+                    if (sscanf(numbuf, "%f", &z) < 1)
+                        continue;
+                    if (i < x->x_noutsig)
+                        x->x_outsig[i][j] = z;
+                    if (++j >= DEFDACBLKSIZE)
+                        j = 0, i++;
+                }
+                numbuffill = 0;
+                break;
+            }
+        }
+        /* message terminated */
+        if (c == ';')
+            break;
+    }
+    for (; i < x->x_noutsig; i++, j = 0)
+    {
+        for (; j < DEFDACBLKSIZE; j++)
+            x->x_outsig[i][j] = 0;
+    }
+    pd_tilde_readmessages(x);
+    return (w+3);
+zeroit:
+    for (i = 0; i < x->x_noutsig; i++)
+    {
+        for (j = 0; j < DEFDACBLKSIZE; j++)
+            x->x_outsig[i][j] = 0;
+    }
+    return (w+3);
+}
+
+static void pd_tilde_dsp(t_pd_tilde *x, t_signal **sp)
+{
+    int i, n = (x->x_ninsig || x->x_noutsig ? sp[0]->s_n : 1);
+    t_sample **g;
+        
+    for (i = 0, g = x->x_insig; i < x->x_ninsig; i++, g++)
+        *g = (*(sp++))->s_vec;
+    
+    for (i = 0, g = x->x_outsig; i < x->x_noutsig; i++, g++)
+        *g = (*(sp++))->s_vec;
+    
+    dsp_add(pd_tilde_perform, 2, x, n);
+}
+
+static void pd_tilde_pdtilde(t_pd_tilde *x, t_symbol *s,
+    int argc, t_atom *argv)
+{
+    t_symbol *sel = ((argc > 0 && argv->a_type == A_SYMBOL) ?
+        argv->a_w.w_symbol : gensym("?")), *schedlibdir;
+    char *patchdir;
+    if (sel == gensym("start"))
+    {
+        char pdargstring[MAXPDSTRING];
+        if (x->x_infd)
+            pd_tilde_close(x);
+        pdargstring[0] = 0;
+        argc--; argv++;
+#ifdef PD
+        while (argc--)
+        {
+            atom_string(argv++, pdargstring + strlen(pdargstring), 
+                MAXPDSTRING - strlen(pdargstring));
+            if (strlen(pdargstring) < MAXPDSTRING-1)
+                strcat(pdargstring, " ");
+        }
+        patchdir = canvas_getdir(x->x_canvas)->s_name;
+#endif
+#ifdef MSP
+        while (argc--)
+        {
+                /* because Mac pathnames sometimes have an evil preceeding
+                colon character, we test for and silently eat them */
+            if (argv->a_type == A_SYM)
+                strncat(pdargstring, (*argv->a_w.w_sym->s_name == ':'?
+                    argv->a_w.w_sym->s_name+1 : argv->a_w.w_sym->s_name),
+                    MAXPDSTRING - strlen(pdargstring)-3);
+            else if (argv->a_type == A_LONG)
+                snprintf(pdargstring+strlen(pdargstring),
+                    MAXPDSTRING - strlen(pdargstring)-3, "%ld",
+                        argv->a_w.w_long);
+            else if (argv->a_type == A_FLOAT)
+                snprintf(pdargstring+strlen(pdargstring),
+                    MAXPDSTRING - strlen(pdargstring)-3, "%f",
+                        argv->a_w.w_float);
+            strcat(pdargstring, " ");
+            argv++;
+        }
+        patchdir = ".";
+#endif
+        schedlibdir = x->x_schedlibdir;
+        if (schedlibdir == gensym(".") && x->x_pddir != gensym("."))
+        {
+            char *pds = x->x_pddir->s_name, scheddirstring[MAXPDSTRING];
+            int l = strlen(pds);
+            if (l >= 4 && (!strcmp(pds+l-3, "bin") || !strcmp(pds+l-4, "bin/")))
+                snprintf(scheddirstring, MAXPDSTRING, "%s/../extra/pd~", pds);
+            else snprintf(scheddirstring, MAXPDSTRING, "%s/extra/pd~", pds);
+            schedlibdir = gensym(scheddirstring);
+        }
+        pd_tilde_donew(x, x->x_pddir->s_name, schedlibdir->s_name,
+            patchdir, pdargstring, x->x_ninsig, x->x_noutsig, x->x_fifo,
+                x->x_sr);
+    }
+    else if (sel == gensym("stop"))
+    {
+        if (x->x_infd)
+            pd_tilde_close(x);
+    }
+    else if (sel == gensym("pddir"))
+    {
+        if ((argc > 1) && argv[1].a_type == A_SYMBOL)
+        {
+            t_symbol *sym = argv[1].a_w.w_symbol;
+#ifdef MSP
+            if (sym->s_name[0] == ':')
+                sym = gensym(s->s_name+1);
+#endif
+            x->x_pddir = sym;
+        }
+        else ERROR "pd~ pddir: needs symbol argument");
+    }
+    else ERROR "pd~: unknown control message: %s", sel->s_name);
+}
+
+static void pd_tilde_free(t_pd_tilde *x)
+{
+#ifdef MSP
+    dsp_free((t_pxobject *)x);
+#endif
+    pd_tilde_close(x);
+    clock_free(x->x_clock);
+}
+
+/* -------------------------- Pd glue ------------------------- */
+#ifdef PD
+
+static void pd_tilde_tick(t_pd_tilde *x)
+{
+    int messstart = 0, i, n;
+    t_atom *vec;
+    t_binbuf *b;
+    if (!x->x_msgbuf)
+        return;
+    b = binbuf_new();
+    binbuf_text(b, x->x_msgbuf, x->x_infill);
+    /* binbuf_print(b); */
+    n = binbuf_getnatom(b);
+    vec = binbuf_getvec(b);
+    for (i = 0; i < n; i++)
+    {
+        if (vec[i].a_type == A_SEMI)
+        {
+            if (i > messstart && vec[messstart].a_type == A_SYMBOL)
+                outlet_anything(x->x_outlet1, vec[messstart].a_w.w_symbol,
+                    i-(messstart+1), vec+(messstart+1));
+            else if (i > messstart)
+                outlet_list(x->x_outlet1, 0, i-messstart, vec+messstart);
+            messstart = i+1;
+        }
+    }
+    binbuf_free(b);
+    x->x_infill = 0;
+}
+
+static void pd_tilde_anything(t_pd_tilde *x, t_symbol *s,
+    int argc, t_atom *argv)
+{
+    char msgbuf[MAXPDSTRING];
+    if (!x->x_outfd)
+        return;
+    fprintf(x->x_outfd, "%s ", s->s_name);
+    while (argc--)
+    {
+        atom_string(argv++, msgbuf, MAXPDSTRING);
+        fprintf(x->x_outfd, "%s ", msgbuf);
+    }
+    fprintf(x->x_outfd, ";\n");
+}
+
+static void *pd_tilde_new(t_symbol *s, int argc, t_atom *argv)
+{
+    t_pd_tilde *x = (t_pd_tilde *)pd_new(pd_tilde_class);
+    int ninsig = 2, noutsig = 2, j, fifo = 5;
+    float sr = sys_getsr();
+    t_sample **g;
+    t_symbol *pddir = sys_guidir,
+        *scheddir = gensym(class_gethelpdir(pd_tilde_class));
+    /* fprintf(stderr, "pd %s, sched %s\n", pddir->s_name, scheddir->s_name); */
+    while (argc > 0)
+    {
+        t_symbol *firstarg = atom_getsymbolarg(0, argc, argv);
+        if (!strcmp(firstarg->s_name, "-sr") && argc > 1)
+        {
+            sr = atom_getfloatarg(1, argc, argv);
+            argc -= 2; argv += 2;
+        }
+        else if (!strcmp(firstarg->s_name, "-ninsig") && argc > 1)
+        {
+            ninsig = atom_getfloatarg(1, argc, argv);
+            argc -= 2; argv += 2;
+        }
+        else if (!strcmp(firstarg->s_name, "-noutsig") && argc > 1)
+        {
+            noutsig = atom_getfloatarg(1, argc, argv);
+            argc -= 2; argv += 2;
+        }
+        else if (!strcmp(firstarg->s_name, "-fifo") && argc > 1)
+        {
+            fifo = atom_getfloatarg(1, argc, argv);
+            argc -= 2; argv += 2;
+        }
+        else if (!strcmp(firstarg->s_name, "-pddir") && argc > 1)
+        {
+            pddir = atom_getsymbolarg(1, argc, argv);
+            argc -= 2; argv += 2;
+        }
+        else if (!strcmp(firstarg->s_name, "-scheddir") && argc > 1)
+        {
+            scheddir = atom_getsymbolarg(1, argc, argv);
+            argc -= 2; argv += 2;
+        }
+        else break;
+    }
+
+    if (argc)
+    {
+        pd_error(x,
+"usage: pd~ [-sr #] [-ninsig #] [-noutsig #] [-fifo #] [-pddir <>]");
+        post(
+"... [-scheddir <>]");
+    }
+
+    x->x_clock = clock_new(x, (t_method)pd_tilde_tick);
+    x->x_insig = (t_sample **)getbytes(ninsig * sizeof(*x->x_insig));
+    x->x_outsig = (t_sample **)getbytes(noutsig * sizeof(*x->x_outsig));
+    x->x_ninsig = ninsig;
+    x->x_noutsig = noutsig;
+    x->x_fifo = fifo;
+    x->x_sr = sr;
+    x->x_pddir = pddir;
+    x->x_schedlibdir = scheddir;
+    x->x_infd = 0;
+    x->x_outfd = 0;
+    x->x_outfd = 0;
+    x->x_childpid = -1;
+    x->x_msgbuf = 0;
+    x->x_canvas = canvas_getcurrent();
+    for (j = 1, g = x->x_insig; j < ninsig; j++, g++)
+        inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal);
+    x->x_outlet1 = outlet_new(&x->x_obj, 0);
+    for (j = 0, g = x->x_outsig; j < noutsig; j++, g++)
+        outlet_new(&x->x_obj, &s_signal);
+    signal(SIGPIPE, SIG_IGN);
+
+    return (x);
+}
+
+void pd_tilde_setup(void)
+{
+    pd_tilde_class = class_new(gensym("pd~"), (t_newmethod)pd_tilde_new,
+        (t_method)pd_tilde_free, sizeof(t_pd_tilde), 0, A_GIMME, 0);
+    class_addmethod(pd_tilde_class, nullfn, gensym("signal"), 0);
+    class_addmethod(pd_tilde_class, (t_method)pd_tilde_dsp, gensym("dsp"), 0);
+    class_addmethod(pd_tilde_class, (t_method)pd_tilde_pdtilde, gensym("pd~"), A_GIMME, 0);
+    class_addanything(pd_tilde_class, pd_tilde_anything);
+    post("pd~ version 0.2");
+}
+#endif
+
+/* -------------------------- MSP glue ------------------------- */
+#ifdef MSP
+
+#define LOTS 10000
+
+static void pd_tilde_tick(t_pd_tilde *x)
+{
+    int messstart = 0, i, n = 0;
+    t_atom vec[LOTS];
+    long z1 = 0, z2 = 0;
+    void *b;
+    if (!x->x_msgbuf)
+        return;
+    b = binbuf_new();
+    binbuf_text(b, &x->x_msgbuf, x->x_infill);
+    /* binbuf_print(b); */
+    while (!binbuf_getatom(b, &z1, &z2, vec+n))
+    if (++n >= LOTS)
+        break;
+    for (i = 0; i < n; i++)
+    {
+        if (vec[i].a_type == A_SEMI)
+        {
+            if (i > messstart + 1)
+            {
+                void *whom;
+                if (vec[messstart].a_type == A_SYM)
+                    outlet_anything(x->x_outlet1, vec[messstart].a_w.w_sym,
+                        i-messstart-1, vec+(messstart+1));
+                else if (vec[messstart].a_type == A_FLOAT && i == messstart+1)
+                    outlet_float(x->x_outlet1, vec[messstart].a_w.w_float);
+                else if (vec[messstart].a_type == A_LONG && i == messstart+1)
+                    outlet_int(x->x_outlet1, vec[messstart].a_w.w_long);
+                else outlet_list(x->x_outlet1, gensym("list"),
+                    i-messstart, vec+(messstart));
+            }
+            messstart = i+1;
+        }
+    }
+    binbuf_free(b);
+    x->x_infill = 0;
+}
+
+static void pd_tilde_anything(t_pd_tilde *x, t_symbol *s,
+    long ac, t_atom *av)
+{
+    char msgbuf[MAXPDSTRING], *sp, *ep = msgbuf+MAXPDSTRING;
+    if (!x->x_outfd)
+        return;
+    msgbuf[0] = 0;
+    strncpy(msgbuf, s->s_name, MAXPDSTRING);
+    msgbuf[MAXPDSTRING-1] = 0;
+    sp = msgbuf + strlen(msgbuf);
+    while (ac--)
+    {
+        if (sp < ep-1)
+            sp[0] = ' ', sp[1] = 0, sp++;
+        if (sp < ep - 80)
+        {
+            if (av->a_type == A_SYM && strlen(av->a_w.w_sym->s_name) < ep - sp-20)
+                strcpy(sp, av->a_w.w_sym->s_name);
+            else if (av->a_type == A_LONG)
+                sprintf(sp, "%ld" ,av->a_w.w_long);
+            else if (av->a_type == A_FLOAT)
+                sprintf(sp, "%g" ,av->a_w.w_float);
+        }
+        sp += strlen(sp);
+        av++;
+    }
+    fprintf(x->x_outfd, "%s;\n", msgbuf);
+}
+
+int main()
+{       
+    t_class *c;
+
+    c = class_new("pd_tilde~", (method)pd_tilde_new, (method)pd_tilde_free, sizeof(t_pd_tilde), (method)0L, A_GIMME, 0);
+
+    class_addmethod(c, (method)pd_tilde_dsp, "dsp", A_CANT, 0);
+    class_addmethod(c, (method)pd_tilde_assist, "assist", A_CANT, 0);
+    class_addmethod(c, (method)pd_tilde_pdtilde, "pd~", A_GIMME, 0);
+    class_addmethod(c, (method)pd_tilde_anything, "anything", A_GIMME, 0);
+    class_dspinit(c);
+
+    class_register(CLASS_BOX, c);
+    pd_tilde_class = c;
+    post("pd~ version 0.2");
+    return (0);
+}
+
+static void *pd_tilde_new(t_symbol *s, long ac, t_atom *av)
+{
+    int ninsig = 2, noutsig = 2, fifo = 5, j;
+    float sr = sys_getsr();
+    t_symbol *pddir = gensym("."), *scheddir = gensym(".");
+    t_pd_tilde *x;
+
+    if (x = (t_pd_tilde *)object_alloc(pd_tilde_class))
+    {
+        while (ac > 0 && av[0].a_type == A_SYM)
+        {
+            char *flag = av[0].a_w.w_sym->s_name;
+            if (!strcmp(flag, "-sr") && ac > 1)
+            {
+                sr = (av[1].a_type == A_FLOAT ? av[1].a_w.w_float :
+                    (av[1].a_type == A_LONG ? av[1].a_w.w_long : 0));
+                ac -= 2; av += 2;
+            }
+            else if (!strcmp(flag, "-ninsig") && ac > 1)
+            {
+                ninsig = (av[1].a_type == A_FLOAT ? av[1].a_w.w_float :
+                    (av[1].a_type == A_LONG ? av[1].a_w.w_long : 0));
+                ac -= 2; av += 2;
+            }
+            else if (!strcmp(flag, "-noutsig") && ac > 1)
+            {
+                noutsig = (av[1].a_type == A_FLOAT ? av[1].a_w.w_float :
+                    (av[1].a_type == A_LONG ? av[1].a_w.w_long : 0));
+                ac -= 2; av += 2;
+            }
+            else if (!strcmp(flag, "-fifo") && ac > 1)
+            {
+                fifo = (av[1].a_type == A_FLOAT ? av[1].a_w.w_float :
+                    (av[1].a_type == A_LONG ? av[1].a_w.w_long : 0));
+                ac -= 2; av += 2;
+            }
+            else if (!strcmp(flag, "-pddir") && ac > 1)
+            {
+                pddir = (av[1].a_type == A_SYM ? av[1].a_w.w_sym : gensym("."));
+                ac -= 2; av += 2;
+            }
+            else if (!strcmp(flag, "-scheddir") && ac > 1)
+            {
+                scheddir = (av[1].a_type == A_SYM ? av[1].a_w.w_sym : gensym("."));
+                ac -= 2; av += 2;
+            }
+            else break;
+        }
+        if (ac)
+            post("pd~: warning: ignoring extra arguments");
+        dsp_setup((t_pxobject *)x, ninsig);
+        x->x_outlet1 = outlet_new(&x->x_obj, 0);
+        for (j = 0; j < noutsig; j++)
+            outlet_new((t_pxobject *)x, "signal");
+        x->x_clock = clock_new(x, (method)pd_tilde_tick);
+        x->x_insig = (t_sample **)getbytes(ninsig * sizeof(*x->x_insig));
+        x->x_outsig = (t_sample **)getbytes(noutsig * sizeof(*x->x_outsig));
+        x->x_ninsig = ninsig;
+        x->x_noutsig = noutsig;
+        x->x_fifo = fifo;
+        x->x_sr = sr;
+        x->x_pddir = pddir;
+        x->x_schedlibdir = scheddir;
+        x->x_infd = 0;
+        x->x_outfd = 0;
+        x->x_outfd = 0;
+        x->x_childpid = -1;
+        x->x_msgbuf = 0;
+    }
+    return (x);
+}
+
+void pd_tilde_assist(t_pd_tilde *x, void *b, long m, long a, char *s)
+{
+}
+
+#endif /* MSP */
diff --git a/extra/pd~/z.pd b/extra/pd~/z.pd
new file mode 100644
index 0000000000000000000000000000000000000000..373201dae810491301d0a2b2208c4b069a2be81c
--- /dev/null
+++ b/extra/pd~/z.pd
@@ -0,0 +1,15 @@
+#N canvas 686 241 450 300 10;
+#X obj 65 58 r foo;
+#X obj 62 100 print foo;
+#X obj 244 59 adc~;
+#X obj 238 102 env~ 8192;
+#X floatatom 236 140 5 0 0 0 - - -;
+#X obj 155 234 dac~;
+#X obj 155 191 osc~ 440;
+#X obj 287 204 stdout;
+#X msg 307 153 a b c;
+#X connect 0 0 1 0;
+#X connect 2 0 3 0;
+#X connect 3 0 4 0;
+#X connect 6 0 5 0;
+#X connect 8 0 7 0;
diff --git a/extra/pique/pique.pd_linux b/extra/pique/pique.pd_linux
deleted file mode 100755
index 1cb271dd65076c394b61ecc35604fe678fd0bdb4..0000000000000000000000000000000000000000
Binary files a/extra/pique/pique.pd_linux and /dev/null differ
diff --git a/extra/sigmund~/makefile b/extra/sigmund~/makefile
new file mode 100644
index 0000000000000000000000000000000000000000..3dc176b3b4e7509e2a93b2813ad17554e513ab99
--- /dev/null
+++ b/extra/sigmund~/makefile
@@ -0,0 +1,4 @@
+NAME=sigmund~
+CSYM=sigmund_tilde
+
+include ../makefile
diff --git a/extra/sigmund~/sigmund~-help.pd b/extra/sigmund~/sigmund~-help.pd
new file mode 100644
index 0000000000000000000000000000000000000000..5ddbf6d1b21243b161fa27db053ba83f206f373d
--- /dev/null
+++ b/extra/sigmund~/sigmund~-help.pd
@@ -0,0 +1,194 @@
+#N canvas 167 -7 580 617 12;
+#X text 42 4 sigmund~ - sinusoidal analysis and pitch tracking;
+#N canvas 432 117 573 597 using-with-tables 0;
+#X obj 29 368 print peak;
+#N canvas 0 0 450 300 (subpatch) 0;
+#X array insignal 1024 float 2;
+#X coords 0 1 1023 -1 200 140 1;
+#X restore 83 426 graph;
+#X obj 314 513 phasor~;
+#X obj 294 429 loadbang;
+#X obj 314 461 440;
+#X floatatom 313 488 5 0 0 0 - - -;
+#X obj 305 544 tabwrite~ insignal;
+#X obj 290 516 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X text 114 11 Using sigmund~ on arrays;
+#X text 42 33 If invoked with the "-t" flag (as a creation argument)
+\, sigmund~ analyzes waveforms stored in arrays. Instead of an incoming
+signal \, feed it "list" messages with the following arguments:;
+#X text 37 118 table name (a symbol);
+#X text 38 137 number of points;
+#X obj 29 342 sigmund~ -t -npeak 10 -maxfreq 5000 peaks;
+#X msg 29 316 list insignal 1024 0 44100 0;
+#X text 37 158 index of first point;
+#X text 39 179 sample rate;
+#X text 38 200 debug flag (print debugging info if nonzero);
+#X text 23 232 In this mode \, only the "env" \, "pitch" \, and "peaks"
+outputs are meaningful.;
+#X text 31 294 click here to test:;
+#X connect 2 0 6 0;
+#X connect 3 0 4 0;
+#X connect 4 0 5 0;
+#X connect 5 0 2 0;
+#X connect 5 0 7 0;
+#X connect 7 0 6 0;
+#X connect 12 0 0 0;
+#X connect 13 0 12 0;
+#X restore 330 553 pd using-with-tables;
+#X obj 40 512 phasor~;
+#X obj 40 425 loadbang;
+#X floatatom 40 471 5 0 120 0 - - -;
+#X floatatom 39 561 5 0 0 0 - - -;
+#X floatatom 245 563 5 0 0 0 - - -;
+#X obj 40 490 mtof;
+#X obj 40 448 69;
+#X text 38 579 pitch;
+#X text 222 582 envelope;
+#X text 13 28 Sigmund~ analyzes an incoming sound into sinusoidal components
+\, which may be reported individually or combined to form a pitch estimate.
+Possible outputs are specified as creation arguments:;
+#X text 56 95 pitch - output pitch continuously;
+#N canvas 518 74 588 728 setting-parameters 0;
+#X msg 182 66 print;
+#X floatatom 192 92 5 0 0 0 - - -;
+#X msg 192 113 minpower \$1;
+#X obj 182 139 sigmund~ -minpower 40;
+#X text 39 14 You can set parameters either by creation arguments \,
+or else using messages. The "print" message gives you the current values
+of all the parameters:;
+#X text 28 169 npts: number of points used in an analysis. Must be
+a power of two \, at least 128 The minimum frequency that can be tracked
+is about 2(sample_rate)/npts.;
+#X text 26 219 hop: number of points between analyses. Must be a power
+of two \, at least the DSP vector size (usually 64). This regulates
+the number of analyses done per unit of time.;
+#X text 28 271 npeak: maximum number of sinusoidal peaks to look for.
+The computation time is quadratic in the number of peaks actually found
+(this number only sets an upper limit). Use it to balance CPU time
+with quality of results.;
+#X text 30 336 maxfreq: maximum frequency of sinusoidal peaks to look
+for. This can be useful in situations where background noise creates
+high-frequency \, spurious peaks..;
+#X text 37 388 vibrato: maximum deviation from "pitch" to accept as
+normal vibrato (affects "notes" output only). If the value is too small.
+vibratos will appear as trills. If too large \, very small melodic
+intervals may not be reported as new notes.;
+#X text 33 457 stabletime: time period to wait before reporting a note
+(affects "notes" output only). The "pitch" must be present and must
+not vary more than "vibrato" for this entire period to report a note.
+If too large \, the "notes" will be unnecessarily delayed. If too small
+\, spurious notes get output.;
+#X text 31 551 minpower: minimum measured RMS level to report a pitch
+(affects "pitch" and "notes" output only). Signals quieter than this
+will be assumed to be crosstalk and ignored.;
+#X text 32 602 growth: minimum measured RMS growth to report a new
+note (affects "notes" output only). The RMS level must rise by this
+many dB (within a time period given by "stabletime") to report a repetition
+of a note at or near the previously output pitch.;
+#X connect 0 0 3 0;
+#X connect 1 0 2 0;
+#X connect 2 0 3 0;
+#X restore 330 531 pd setting-parameters;
+#N canvas 67 29 641 815 sinusoid-tracking 0;
+#X obj 124 267 sigmund~ -npeak 10 peaks;
+#X obj 124 214 phasor~;
+#X obj 124 144 loadbang;
+#X floatatom 124 190 5 0 120 0 - - -;
+#X obj 124 295 route 0 1 2 3 4 5 6 7 8 9;
+#X obj 82 339 unpack 0 0 0 0;
+#X floatatom 82 461 5 0 0 0 - - -;
+#X floatatom 122 431 5 0 0 0 - - -;
+#X floatatom 162 406 5 0 0 0 - - -;
+#X obj 124 167 440;
+#X floatatom 203 380 5 0 0 0 - - -;
+#X obj 322 349 unpack 0 0 0 0;
+#X floatatom 322 471 5 0 0 0 - - -;
+#X floatatom 362 441 5 0 0 0 - - -;
+#X floatatom 402 416 5 0 0 0 - - -;
+#X floatatom 443 390 5 0 0 0 - - -;
+#X text 385 475 frequency (Hz.);
+#X text 419 442 peak amplitude (linear);
+#X text 464 416 cosine component;
+#X text 499 390 sine component;
+#X text 79 505 loudest partial;
+#X text 332 508 quietest partial;
+#X text 36 4 You can ask for sinusoidal peaks in decreasing order of
+amplitude or arranged into maximally continuous tracks for resynthesis.
+(Or you can ask for both.) If you ask for peaks \, out come lists of
+five numbers \, one for each sinusoid at each analysis period. The
+first is the index number of the sinusoid (so you can use "route" to
+claw them apart). The other four are as shown:;
+#X obj 204 611 osc~ 440;
+#X obj 204 635 *~;
+#X obj 205 689 unpack 0 0 0 0;
+#X floatatom 205 782 5 0 0 0 - - -;
+#X floatatom 245 760 5 0 0 0 - - -;
+#X floatatom 285 737 5 0 0 0 - - -;
+#X floatatom 326 713 5 0 0 0 - - -;
+#X obj 246 638 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0
+1;
+#X text 43 535 If you ask for "tracks" \, the output is four numbers:
+index \, frequency \, and amplitude as before \, and finally a flag
+which is one for a new track \, zero for a continuation \, minus one
+for an empty track.;
+#X obj 205 662 sigmund~ -npts 16384 -hop 8192 -npeak 1 tracks;
+#X connect 0 0 4 0;
+#X connect 1 0 0 0;
+#X connect 2 0 9 0;
+#X connect 3 0 1 0;
+#X connect 4 0 5 0;
+#X connect 4 9 11 0;
+#X connect 5 0 6 0;
+#X connect 5 1 7 0;
+#X connect 5 2 8 0;
+#X connect 5 3 10 0;
+#X connect 9 0 3 0;
+#X connect 11 0 12 0;
+#X connect 11 1 13 0;
+#X connect 11 2 14 0;
+#X connect 11 3 15 0;
+#X connect 23 0 24 0;
+#X connect 24 0 32 0;
+#X connect 25 0 26 0;
+#X connect 25 1 27 0;
+#X connect 25 2 28 0;
+#X connect 25 3 29 0;
+#X connect 30 0 24 1;
+#X connect 32 0 25 0;
+#X restore 330 508 pd sinusoid-tracking;
+#X text 52 165 tracks - output sinusoidal peaks organized into tracks
+;
+#X text 56 111 notes - output pitch at the beginning of notes;
+#X text 339 485 more details:;
+#X text 10 184 Parameters you may set (in creation arguments or messages):
+;
+#X text 60 207 npts - number of points in each analysis window (1024)
+;
+#X text 60 225 hop - number of points between each analysis (512);
+#X text 60 242 npeak - number of sinusoidal peaks (20);
+#X text 61 279 vibrato - depth of vibrato to expect in 1/2-tones (1)
+;
+#X text 60 298 stabletime - time (msec) to wait to report notes (50)
+;
+#X obj 39 535 sigmund~ -hop 4096 pitch env;
+#X text 62 316 minpower - minimum power (dB) to report a pitch (50)
+;
+#X text 62 335 growth - growth (dB) to report a new note (7);
+#X text 54 147 peaks - output all sinusoidal peaks in order of amplitude
+;
+#X text 11 356 The npts and hop parameters are in samples \, and are
+powers of two. The example below specifies a huge hop of 4096 (to slow
+the output down) and to output "pitch" and "env". (Those are the default
+outputs.);
+#X text 61 260 maxfreq - maximum sinusoid frequency in Hz. (1000000)
+;
+#X text 55 128 env - output amplitude continuously;
+#X text 380 596 updated for Pd v0.41;
+#X connect 2 0 24 0;
+#X connect 3 0 8 0;
+#X connect 4 0 7 0;
+#X connect 7 0 2 0;
+#X connect 8 0 4 0;
+#X connect 24 0 5 0;
+#X connect 24 1 6 0;
diff --git a/extra/sigmund~/sigmund~.c b/extra/sigmund~/sigmund~.c
new file mode 100644
index 0000000000000000000000000000000000000000..92604b7ea2ed54d203f0307c9e34406da709edf5
--- /dev/null
+++ b/extra/sigmund~/sigmund~.c
@@ -0,0 +1,1656 @@
+/* Copyright (c) 2005 Miller Puckette.  BSD licensed.  No warranties. */
+
+/*
+    fix parameter settings
+    not to report pitch if evidence too scanty?
+    note-on detection triggered by falling envelope (a posteriori)
+    reentrancy bug setting loud flag (other parameters too?)
+    tweaked freqs still not stable enough
+    implement block ("-b") mode
+*/
+
+/* From here to the first "#ifdef PD" or "#ifdef Max" should be extractable
+and usable in other contexts.  The one external requirement is a real
+single-precision FFT, invoked as in the Mayer one: */
+
+#ifdef NT
+__declspec(dllimport) extern
+#endif
+void mayer_realfft(int npoints, float *buf);
+
+/* this routine is passed a buffer of npoints values, and returns the
+N/2+1 real parts of the DFT (frequency zero through Nyquist), followed
+by the N/2-1 imaginary points, in order of decreasing frequency.  Pd 0.41,
+for example, defines this in the file d_fft_mayer.c or d_fft_fftsg.c. */
+
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+#ifdef _WIN32
+#include <malloc.h>
+#else
+#include <alloca.h>
+#endif
+#include <stdlib.h>
+#ifdef _MSC_VER
+#pragma warning( disable : 4244 )
+#pragma warning( disable : 4305 )
+#endif
+
+typedef struct peak
+{
+    float p_freq;
+    float p_amp;
+    float p_ampreal;
+    float p_ampimag;
+    float p_pit;
+    float p_db;
+    float p_salience;
+    float p_tmp;
+} t_peak;
+
+/********************** service routines **************************/
+
+/* these three are dapted from elsewhere in Pd but included here for
+cmolpeteness */
+static int sigmund_ilog2(int n)
+{
+    int ret = -1;
+    while (n)
+    {
+        n >>= 1;
+        ret++;
+    }
+    return (ret);
+}
+
+static float sigmund_ftom(float f)
+{
+    return (f > 0 ? 17.3123405046 * log(.12231220585 * f) : -1500);
+}
+
+#define LOGTEN 2.302585092994
+static float sigmund_powtodb(float f)
+{
+    if (f <= 0) return (0);
+    else
+    {
+        float val = 100 + 10./LOGTEN * log(f);
+        return (val < 0 ? 0 : val);
+    }
+}
+
+/* parameters for von Hann window (change these to get Hamming if desired) */
+#define W_ALPHA 0.5
+#define W_BETA 0.5
+#define NEGBINS 4   /* number of bins of negative frequency we'll need */
+
+#define PI 3.14159265
+#define LOG2  0.69314718
+#define LOG10 2.30258509
+
+static float sinx(float theta, float sintheta)
+{
+    if (theta > -0.003 && theta < 0.003)
+        return (1);
+    else return (sintheta/theta);
+}
+
+static float window_hann_mag(float pidetune, float sinpidetune)
+{
+    return (W_ALPHA * sinx(pidetune, sinpidetune)
+        - 0.5 * W_BETA *
+            (sinx(pidetune+PI, sinpidetune) + sinx(pidetune-PI, sinpidetune)));
+}
+
+static float window_mag(float pidetune, float cospidetune)
+{
+    return (sinx(pidetune + (PI/2), cospidetune)
+        + sinx(pidetune - (PI/2), -cospidetune));
+}
+
+/*********** Routines to analyze a window into sinusoidal peaks *************/
+
+static int sigmund_cmp_freq(const void *p1, const void *p2)
+{
+    if ((*(t_peak **)p1)->p_freq > (*(t_peak **)p2)->p_freq)
+        return (1);
+    else if ((*(t_peak **)p1)->p_freq < (*(t_peak **)p2)->p_freq)
+        return (-1);
+    else return (0);
+}
+
+static void sigmund_tweak(int npts, float *ftreal, float *ftimag,
+    int npeak, t_peak *peaks, float fperbin, int loud)
+{
+    t_peak **peakptrs = (t_peak **)alloca(sizeof (*peakptrs) * (npeak+1));
+    t_peak negpeak;
+    int peaki, j, k;
+    float ampreal[3], ampimag[3];
+    float binperf = 1./fperbin;
+    float phaseperbin = (npts-0.5)/npts, oneovern = 1./npts;
+    if (npeak < 1)
+        return;
+    for (peaki = 0; peaki < npeak; peaki++)
+        peakptrs[peaki+1] = &peaks[peaki];
+    qsort(peakptrs+1, npeak, sizeof (*peakptrs), sigmund_cmp_freq);
+    peakptrs[0] = &negpeak;
+    negpeak.p_ampreal = peakptrs[1]->p_ampreal;
+    negpeak.p_ampimag = -peakptrs[1]->p_ampimag;
+    negpeak.p_freq = -peakptrs[1]->p_freq;
+    for (peaki = 1; peaki <= npeak; peaki++)
+    {
+        int cbin = peakptrs[peaki]->p_freq*binperf + 0.5;
+        int nsub = (peaki == npeak ? 1:2);
+        float windreal, windimag, windpower, detune, pidetune, sinpidetune,
+            cospidetune, ampcorrect, ampout, ampoutreal, ampoutimag, freqout;
+        /* post("3 nsub %d amp %f freq %f", nsub,
+            peakptrs[peaki]->p_amp, peakptrs[peaki]->p_freq); */
+        if (cbin < 0 || cbin > 2*npts - 3)
+            continue;
+        for (j = 0; j < 3; j++)
+            ampreal[j] = ftreal[cbin+2*j-2], ampimag[j] = ftimag[cbin+2*j-2];
+        /* post("a %f %f", ampreal[1], ampimag[1]); */
+        for (j = 0; j < nsub; j++)
+        {
+            t_peak *neighbor = peakptrs[(peaki-1) + 2*j];
+            float neighborreal = npts * neighbor->p_ampreal;
+            float neighborimag = npts * neighbor->p_ampimag;
+            for (k = 0; k < 3; k++)
+            {
+                float freqdiff = (0.5*PI) * ((cbin + 2*k-2)
+                    -binperf * neighbor->p_freq);
+                float sx = sinx(freqdiff, sin(freqdiff));
+                float phasere = cos(freqdiff * phaseperbin);
+                float phaseim = sin(freqdiff * phaseperbin);
+                ampreal[k] -=
+                    sx * (phasere * neighborreal - phaseim * neighborimag);
+                ampimag[k] -=
+                    sx * (phaseim * neighborreal + phasere * neighborimag);
+            }       
+            /* post("b %f %f", ampreal[1], ampimag[1]); */
+        }
+
+        windreal = W_ALPHA * ampreal[1] -
+            (0.5 * W_BETA) * (ampreal[0] + ampreal[2]);
+        windimag = W_ALPHA * ampimag[1] -
+            (0.5 * W_BETA) * (ampimag[0] + ampimag[2]);
+        windpower = windreal * windreal + windimag * windimag;
+        detune = (
+            W_BETA*(ampreal[0] - ampreal[2]) * 
+                (2.0*W_ALPHA * ampreal[1] - W_BETA * (ampreal[0] + ampreal[2]))
+                    +
+            W_BETA*(ampimag[0] - ampimag[2]) *
+                (2.0*W_ALPHA * ampimag[1] - W_BETA * (ampimag[0] + ampimag[2]))
+                        ) / (4.0 * windpower);
+        if (detune > 0.5)
+            detune = 0.5;
+        else if (detune < -0.5)
+            detune = -0.5;
+        /* if (loud > 0)
+            post("tweak: windpower %f, bin %d, detune %f",
+                windpower, cbin, detune); */
+        pidetune = PI * detune;
+        sinpidetune = sin(pidetune);
+        cospidetune = cos(pidetune);
+
+        ampcorrect = 1.0 / window_hann_mag(pidetune, sinpidetune);
+
+        ampout = oneovern * ampcorrect *sqrt(windpower);
+        ampoutreal = oneovern * ampcorrect *
+            (windreal * cospidetune - windimag * sinpidetune);
+        ampoutimag = oneovern * ampcorrect *
+            (windreal * sinpidetune + windimag * cospidetune);
+        freqout = (cbin + 2*detune) * fperbin;
+        /* if (loud > 1)
+            post("amp %f, freq %f", ampout, freqout); */
+        
+        peakptrs[peaki]->p_freq = freqout;
+        peakptrs[peaki]->p_amp = ampout;
+        peakptrs[peaki]->p_ampreal = ampoutreal;
+        peakptrs[peaki]->p_ampimag = ampoutimag;
+    }
+}
+
+static void sigmund_remask(int maxbin, int bestindex, float powmask, 
+    float maxpower, float *maskbuf)
+{
+    int bin;
+    int bin1 = (bestindex > 52 ? bestindex-50:2);
+    int bin2 = (maxbin < bestindex + 50 ? bestindex + 50 : maxbin);
+    for (bin = bin1; bin < bin2; bin++)
+    {
+        float bindiff = bin - bestindex;
+        float mymask;
+        mymask = powmask/ (1. + bindiff * bindiff * bindiff * bindiff);
+        if (bindiff < 2 && bindiff > -2)
+            mymask = 2*maxpower;
+        if (mymask > maskbuf[bin])
+            maskbuf[bin] = mymask;
+    } 
+}
+
+static void sigmund_getrawpeaks(int npts, float *insamps,
+    int npeak, t_peak *peakv, int *nfound, float *power, float srate, int loud,
+    float param1, float param2, float param3, float hifreq)
+{
+    float oneovern = 1.0/ (float)npts;
+    float fperbin = 0.5 * srate * oneovern, totalpower = 0;
+    int npts2 = 2*npts, i, bin;
+    int peakcount = 0;
+    float *fp1, *fp2;
+    float *rawreal, *rawimag, *maskbuf, *powbuf;
+    float *bigbuf = alloca(sizeof (float ) * (2*NEGBINS + 6*npts));
+    int maxbin = hifreq/fperbin;
+    int tweak = (param3 == 0);
+    if (maxbin > npts - NEGBINS)
+        maxbin = npts - NEGBINS;
+    /* if (loud) post("tweak %d", tweak); */
+    maskbuf = bigbuf + npts2;
+    powbuf = maskbuf + npts;
+    rawreal = powbuf + npts+NEGBINS;
+    rawimag = rawreal+npts+NEGBINS;
+    for (i = 0; i < npts; i++)
+        maskbuf[i] = 0;
+
+    for (i = 0; i < npts; i++)
+        bigbuf[i] = insamps[i];
+    for (i = npts; i < 2*npts; i++)
+        bigbuf[i] = 0;
+    mayer_realfft(npts2, bigbuf);
+    for (i = 0; i < npts; i++)
+        rawreal[i] = bigbuf[i];
+    for (i = 1; i < npts-1; i++)
+        rawimag[i] = bigbuf[npts2-i];
+    rawreal[-1] = rawreal[1];
+    rawreal[-2] = rawreal[2];
+    rawreal[-3] = rawreal[3];
+    rawreal[-4] = rawreal[4];
+    rawimag[0] = rawimag[npts-1] = 0;
+    rawimag[-1] = -rawimag[1];
+    rawimag[-2] = -rawimag[2];
+    rawimag[-3] = -rawimag[3];
+    rawimag[-4] = -rawimag[4];
+#if 1
+    for (i = 0, fp1 = rawreal, fp2 = rawimag; i < maxbin; i++, fp1++, fp2++)
+    {
+        float x1 = fp1[1] - fp1[-1], x2 = fp2[1] - fp2[-1], p = powbuf[i] = x1*x1+x2*x2; 
+        if (i >= 2)
+           totalpower += p;
+    }
+    powbuf[maxbin] = powbuf[maxbin+1] = 0;
+    *power = 0.5 * totalpower *oneovern * oneovern;
+#endif
+    for (peakcount = 0; peakcount < npeak; peakcount++)
+    {
+        float pow1, maxpower = 0, windreal, windimag, windpower,
+            detune, pidetune, sinpidetune, cospidetune, ampcorrect, ampout,
+            ampoutreal, ampoutimag, freqout, powmask;
+        int bestindex = -1;
+
+        for (bin = 2, fp1 = rawreal+2, fp2 = rawimag+2;
+            bin < maxbin; bin++, fp1++, fp2++)
+        {
+            pow1 = powbuf[bin];
+            if (pow1 > maxpower && pow1 > maskbuf[bin])
+            {
+                float thresh = param2 * (powbuf[bin-2]+powbuf[bin+2]);
+                if (pow1 > thresh)
+                    maxpower = pow1, bestindex = bin;
+            }
+        }
+
+        if (totalpower <= 0 || maxpower < 1e-10*totalpower || bestindex < 0)
+            break;
+        fp1 = rawreal+bestindex;
+        fp2 = rawimag+bestindex;
+        powmask = maxpower * exp(-param1 * log(10.) / 10.);
+        /* if (loud > 2)
+            post("maxpower %f, powmask %f, param1 %f",
+                maxpower, powmask, param1); */
+        sigmund_remask(maxbin, bestindex, powmask, maxpower, maskbuf);
+        
+        /* if (loud > 1)
+            post("best index %d, total power %f", bestindex, totalpower); */
+
+        windreal = fp1[1] - fp1[-1];
+        windimag = fp2[1] - fp2[-1];
+        windpower = windreal * windreal + windimag * windimag;
+        detune = ((fp1[1] * fp1[1] - fp1[-1]*fp1[-1]) 
+            + (fp2[1] * fp2[1] - fp2[-1]*fp2[-1])) / (2 * windpower);
+
+        if (detune > 0.5)
+            detune = 0.5;
+        else if (detune < -0.5)
+            detune = -0.5;
+        /* if (loud > 1)
+            post("windpower %f, index %d, detune %f",
+                windpower, bestindex, detune); */
+        pidetune = PI * detune;
+        sinpidetune = sin(pidetune);
+        cospidetune = cos(pidetune);
+        ampcorrect = 1.0 / window_mag(pidetune, cospidetune);
+
+        ampout = ampcorrect *sqrt(windpower);
+        ampoutreal = ampcorrect *
+            (windreal * cospidetune - windimag * sinpidetune);
+        ampoutimag = ampcorrect *
+            (windreal * sinpidetune + windimag * cospidetune);
+
+            /* the frequency is the sum of the bin frequency and detuning */
+
+        peakv[peakcount].p_freq = (freqout = (bestindex + 2*detune)) * fperbin;
+        peakv[peakcount].p_amp = oneovern * ampout;
+        peakv[peakcount].p_ampreal = oneovern * ampoutreal;
+        peakv[peakcount].p_ampimag = oneovern * ampoutimag;
+    }
+    if (tweak)
+    {
+        sigmund_tweak(npts, rawreal, rawimag, peakcount, peakv, fperbin, loud);
+        sigmund_tweak(npts, rawreal, rawimag, peakcount, peakv, fperbin, loud);
+    }
+    for (i = 0; i < peakcount; i++)
+    {
+        peakv[i].p_pit = sigmund_ftom(peakv[i].p_freq);
+        peakv[i].p_db = sigmund_powtodb(peakv[i].p_amp);
+    }
+    *nfound = peakcount;
+}
+
+/*************** Routines for finding fundamental pitch *************/
+
+#define PITCHNPEAK 12
+#define PITCHUNCERTAINTY 0.3
+#define HALFTONEINC 0.059
+#define SUBHARMONICS 16
+#define DBPERHALFTONE 0.0
+
+static void sigmund_getpitch(int npeak, t_peak *peakv, float *freqp,
+    float npts, float srate, int loud)
+{
+    float fperbin = 0.5 * srate / npts;
+    int npit = 48 * sigmund_ilog2(npts), i, j, k, nsalient;
+    float bestbin, bestweight, sumamp, sumweight, sumfreq, freq;
+    float *weights =  (float *)alloca(sizeof(float) * npit);
+    t_peak *bigpeaks[PITCHNPEAK];
+    if (npeak < 1)
+    {
+        freq = 0;
+        goto done;
+    }
+    for (i = 0; i < npit; i++)
+        weights[i] = 0;
+    for (i = 0; i < npeak; i++)
+    {
+        peakv[i].p_tmp = 0;
+        peakv[i].p_salience = peakv[i].p_db - DBPERHALFTONE * peakv[i].p_pit;
+    }
+    for (nsalient = 0; nsalient < PITCHNPEAK; nsalient++)
+    {
+        t_peak *bestpeak = 0;
+        float bestsalience = -1e20;
+        for (j = 0; j < npeak; j++)
+            if (peakv[j].p_tmp == 0 && peakv[j].p_salience > bestsalience)
+        {
+            bestsalience = peakv[j].p_salience;
+            bestpeak = &peakv[j];
+        }
+        if (!bestpeak)
+            break;
+        bigpeaks[nsalient] = bestpeak;
+        bestpeak->p_tmp = 1;
+        /* post("peak f=%f a=%f", bestpeak->p_freq, bestpeak->p_amp); */
+    }
+    sumweight = 0;
+    for (i = 0; i < nsalient; i++)
+    {
+        t_peak *thispeak = bigpeaks[i];
+        float weightindex = (48./LOG2) *
+            log(thispeak->p_freq/(2.*fperbin));
+        float loudness = sqrt(thispeak->p_amp);
+        /* post("index %f, uncertainty %f", weightindex, pitchuncertainty); */
+        for (j = 0; j < SUBHARMONICS; j++)
+        {
+            float subindex = weightindex -
+                (48./LOG2) * log(j + 1.);
+            int loindex = subindex - 0.5;
+            int hiindex = loindex+2;
+            if (hiindex < 0)
+                break;
+            if (hiindex >= npit)
+                continue;
+            if (loindex < 0)
+                loindex = 0;
+            for (k = loindex; k <= hiindex; k++)
+                weights[k] += loudness * 6. / (6. + j);
+        }
+        sumweight += loudness;
+    }
+    bestbin = -1;
+    bestweight = -1e20;
+    for (i = 0; i < npit; i++)
+        if (weights[i] > bestweight)
+            bestweight = weights[i], bestbin = i;
+    if (bestweight < sumweight * 0.4)
+        bestbin = -1;
+    
+    if (bestbin < 0)
+    {
+        freq = 0;
+        goto done;
+    }
+    if (bestbin > 0 && bestbin < npit-1)
+    {
+        int ibest = bestbin;
+        bestbin += (weights[ibest+1] - weights[ibest-1]) /
+            (weights[ibest+1] +  weights[ibest] + weights[ibest-1]);
+    }
+    freq = 2*fperbin * exp((LOG2/48.)*bestbin);
+    for (sumamp = sumweight = sumfreq = 0, i = 0; i < nsalient; i++)
+    {
+        t_peak *thispeak = bigpeaks[i];
+        float thisloudness = thispeak->p_amp;
+        float thisfreq = thispeak->p_freq;
+        float harmonic = thisfreq/freq;
+        float intpart = (int)(0.5 + harmonic);
+        float inharm = harmonic - intpart;
+#if 0
+        if (loud)
+            post("freq %f intpart %f inharm %f", freq, intpart, inharm);
+#endif
+        if (intpart >= 1 && intpart <= 16 &&
+            inharm < 0.015 * intpart && inharm > - (0.015 * intpart))
+        {
+            float weight = thisloudness * intpart;
+            sumweight += weight;
+            sumfreq += weight*thisfreq/intpart;
+#if 0
+            if (loud)
+                post("weight %f freq %f", weight, thisfreq);
+#endif
+        }
+    }
+    if (sumweight > 0)
+        freq = sumfreq / sumweight;
+done:
+    if (!(freq >= 0 || freq <= 0))
+    {
+        /* post("freq nan cancelled"); */
+        freq = 0;
+    }
+    *freqp = freq;
+}
+
+/*************** gather peak lists into sinusoidal tracks *************/
+
+static void sigmund_peaktrack(int ninpeak, t_peak *inpeakv, 
+    int noutpeak, t_peak *outpeakv, int loud)
+{
+    int incnt, outcnt;
+    for (outcnt = 0; outcnt < noutpeak; outcnt++)
+        outpeakv[outcnt].p_tmp = -1;
+        
+        /* first pass. Match each "in" peak with the closest previous
+        "out" peak, but no two to the same one. */
+    for (incnt = 0; incnt < ninpeak; incnt++)
+    {
+        float besterror = 1e20;
+        int bestcnt = -1;
+        inpeakv[incnt].p_tmp = -1;
+        for (outcnt = 0; outcnt < noutpeak; outcnt++)
+        {
+            float thiserror =
+                inpeakv[incnt].p_freq - outpeakv[outcnt].p_freq;
+            if (thiserror < 0)
+                thiserror = -thiserror;
+            if (thiserror < besterror)
+            {
+                besterror = thiserror;
+                bestcnt = outcnt;
+            }
+        }
+        if (outpeakv[bestcnt].p_tmp < 0)
+        {
+            outpeakv[bestcnt] = inpeakv[incnt];
+            inpeakv[incnt].p_tmp = 0;
+            outpeakv[bestcnt].p_tmp = 0;
+        }
+    }
+        /* second pass.  Unmatched "in" peaks assigned to free "out"
+        peaks */
+    for (incnt = 0; incnt < ninpeak; incnt++)
+        if (inpeakv[incnt].p_tmp < 0)
+    {
+        for (outcnt = 0; outcnt < noutpeak; outcnt++)
+            if (outpeakv[outcnt].p_tmp < 0)
+        {
+            outpeakv[outcnt] = inpeakv[incnt];
+            inpeakv[incnt].p_tmp = 0;
+            outpeakv[outcnt].p_tmp = 1;
+            break;
+        }
+    }
+    for (outcnt = 0; outcnt < noutpeak; outcnt++)
+        if (outpeakv[outcnt].p_tmp == -1)
+            outpeakv[outcnt].p_amp = 0;
+}
+
+/**************** parse continuous pitch into note starts ***************/
+
+#define NHISTPOINT 100
+
+typedef struct _histpoint
+{
+    float h_freq;
+    float h_power;
+} t_histpoint;
+
+typedef struct _notefinder
+{
+    float n_age;
+    float n_hifreq;
+    float n_lofreq;
+    int n_peaked;
+    t_histpoint n_hist[NHISTPOINT];
+    int n_histphase;
+} t_notefinder;
+
+
+static void notefinder_init(t_notefinder *x)
+{
+    int i;
+    x->n_peaked = x->n_age = 0;
+    x->n_hifreq = x->n_lofreq = 0;
+    x->n_histphase = 0;
+    for (i = 0; i < NHISTPOINT; i++)
+        x->n_hist[i].h_freq =x->n_hist[i].h_power = 0;
+}
+
+static void notefinder_doit(t_notefinder *x, float freq, float power,
+    float *note, float vibrato, int stableperiod, float powerthresh,
+        float growththresh, int loud)
+{
+        /* calculate frequency ratio between allowable vibrato extremes
+        (equal to twice the vibrato deviation from center) */
+    float vibmultiple = exp((2*LOG2/12) * vibrato);
+    int oldhistphase, i, k;
+    if (stableperiod > NHISTPOINT - 1)
+        stableperiod = NHISTPOINT - 1;
+    else if (stableperiod < 1)
+        stableperiod = 1;
+    if (++x->n_histphase == NHISTPOINT)
+        x->n_histphase = 0;
+    x->n_hist[x->n_histphase].h_freq = freq;
+    x->n_hist[x->n_histphase].h_power = power;
+    x->n_age++;
+    *note = 0;
+#if 0
+    if (loud)
+    {
+        post("stable %d, age %d, vibmultiple %f, powerthresh %f, hifreq %f",
+            stableperiod, (int)x->n_age ,vibmultiple, powerthresh, x->n_hifreq);
+        post("histfreq %f %f %f %f",
+            x->n_hist[x->n_histphase].h_freq,
+            x->n_hist[(x->n_histphase+NHISTPOINT-1)%NHISTPOINT].h_freq,
+            x->n_hist[(x->n_histphase+NHISTPOINT-2)%NHISTPOINT].h_freq,
+            x->n_hist[(x->n_histphase+NHISTPOINT-3)%NHISTPOINT].h_freq);
+        post("power %f %f %f %f",
+            x->n_hist[x->n_histphase].h_power,
+            x->n_hist[(x->n_histphase+NHISTPOINT-1)%NHISTPOINT].h_power,
+            x->n_hist[(x->n_histphase+NHISTPOINT-2)%NHISTPOINT].h_power,
+            x->n_hist[(x->n_histphase+NHISTPOINT-3)%NHISTPOINT].h_power);
+        for (i = 0, k = x->n_histphase; i < stableperiod; i++)
+        {
+            post("pit %5.1f  pow %f", sigmund_ftom(x->n_hist[k].h_freq),
+                x->n_hist[k].h_power);
+            if (--k < 0)
+                k = NHISTPOINT - 1;
+        }
+    }
+#endif
+       /* look for shorter notes than "stableperiod" in length.
+       The amplitude must rise and then fall while the pitch holds
+       steady. */
+    if (x->n_hifreq <= 0 && x->n_age > stableperiod)
+    {
+        float maxpow = 0, freqatmaxpow = 0,
+            localhifreq = -1e20, locallofreq = 1e20;
+        int startphase = x->n_histphase - stableperiod + 1;
+        if (startphase < 0)
+            startphase += NHISTPOINT;
+        for (i = 0, k = startphase; i < stableperiod; i++)
+        {
+            if (x->n_hist[k].h_freq <= 0)
+                break;
+            if (x->n_hist[k].h_power > maxpow)
+                maxpow = x->n_hist[k].h_power,
+                    freqatmaxpow = x->n_hist[k].h_freq;
+            if (x->n_hist[k].h_freq > localhifreq)
+                localhifreq = x->n_hist[k].h_freq;
+            if (x->n_hist[k].h_freq < locallofreq)
+                locallofreq = x->n_hist[k].h_freq;
+            if (localhifreq > locallofreq * vibmultiple)
+                break;
+            if (maxpow > power * growththresh &&
+                maxpow > x->n_hist[startphase].h_power * growththresh &&
+                    localhifreq < vibmultiple * locallofreq
+                        && freqatmaxpow > 0 && maxpow > powerthresh)
+            {
+                x->n_hifreq = x->n_lofreq = *note = freqatmaxpow;
+                x->n_age = 0;
+                x->n_peaked = 0;
+                /* post("got short note"); */
+                return;
+            }
+            if (++k >= NHISTPOINT)
+                k = 0;
+        }
+        
+    }
+    if (x->n_hifreq > 0)
+    {
+            /* test if we're within "vibrato" range, and if so update range */
+        if (freq * vibmultiple >= x->n_hifreq &&
+            x->n_lofreq * vibmultiple >= freq)
+        {
+            if (freq > x->n_hifreq)
+                x->n_hifreq = freq;
+            if (freq < x->n_lofreq)
+                x->n_lofreq = freq;
+        }
+        else if (x->n_hifreq > 0 && x->n_age > stableperiod)
+        {
+                /* if we've been out of range at least 1/2 the
+                last "stableperiod+1" analyses, clear the note */
+            int nbad = 0;
+            for (i = 0, k = x->n_histphase; i < stableperiod + 1; i++)
+            {
+                if (--k < 0)
+                    k = NHISTPOINT - 1;
+                if (x->n_hist[k].h_freq * vibmultiple <= x->n_hifreq ||
+                    x->n_lofreq * vibmultiple <= x->n_hist[k].h_freq)
+                        nbad++;
+            }
+            if (2 * nbad >= stableperiod + 1)
+            {
+                x->n_hifreq = x->n_lofreq = 0;
+                x->n_age = 0;
+            }
+        }
+    }
+
+    oldhistphase = x->n_histphase - stableperiod;
+    if (oldhistphase < 0)
+        oldhistphase += NHISTPOINT;
+        
+        /* look for envelope attacks */
+
+    if (x->n_hifreq > 0 && x->n_peaked)
+    {
+        if (freq > 0 && power > powerthresh &&
+            power > x->n_hist[oldhistphase].h_power *
+                exp((LOG10*0.1)*growththresh))
+        {
+                /* clear it and fall through for new stable-note test */
+            x->n_peaked = 0;
+            x->n_hifreq = x->n_lofreq = 0;
+            x->n_age = 0;
+        }
+    }
+    else if (!x->n_peaked)
+    {
+        if (x->n_hist[oldhistphase].h_power > powerthresh &&
+            x->n_hist[oldhistphase].h_power > power)
+                x->n_peaked = 1;
+    }
+
+        /* test for a new note using a stability criterion. */
+
+    if (freq >= 0 &&
+        (x->n_hifreq <= 0 || freq > x->n_hifreq || freq < x->n_lofreq))
+    {
+        float testfhi = freq, testflo = freq,
+            maxpow = x->n_hist[x->n_histphase].h_freq;
+        for (i = 0, k = x->n_histphase; i < stableperiod-1; i++)
+        {
+            if (--k < 0)
+                k = NHISTPOINT - 1;
+            if (x->n_hist[k].h_freq > testfhi)
+                testfhi = x->n_hist[k].h_freq;
+            if (x->n_hist[k].h_freq < testflo)
+                testflo = x->n_hist[k].h_freq;
+            if (x->n_hist[k].h_power > maxpow)
+                maxpow = x->n_hist[k].h_power;
+        }
+#if 0
+        if (loud)
+            post("freq %.2g testfhi %.2g  testflo %.2g maxpow %.2g",
+                freq, testfhi, testflo, maxpow);
+#endif
+        if (testflo > 0 && testfhi <= vibmultiple * testflo
+            && maxpow > powerthresh)
+        {
+                /* report new note */
+            float sumf = 0, sumw = 0, thisw;
+            for (i = 0, k = x->n_histphase; i < stableperiod; i++)
+            {
+                thisw = x->n_hist[k].h_power;
+                sumw += thisw;
+                sumf += thisw*x->n_hist[k].h_freq;
+                if (--k < 0)
+                    k = NHISTPOINT - 1;
+            }
+            x->n_hifreq = x->n_lofreq = *note = (sumw > 0 ? sumf/sumw : 0);
+#if 0
+                /* debugging printout */
+            for (i = 0; i < stableperiod; i++)
+            {
+                int k3 = x->n_histphase - i;
+                if (k3 < 0)
+                    k3 += NHISTPOINT;
+                startpost("%5.1f ", sigmund_ftom(x->n_hist[k3].h_freq));
+            }
+            post("");
+#endif
+            x->n_age = 0;
+            x->n_peaked = 0;
+            return;
+        }
+    }
+    *note = 0;
+    return;
+}
+
+/**************** object structure for Pd and Max. *********************/ 
+
+/* From here onward, the code is specific to eithr Pd, Max, or both.  If
+neither "PD 'nor "MSP" is defined, none of this is compiled, so that the
+whole file can be included in other, non-PD and non-Max projects.  */
+#ifdef PD
+#include "m_pd.h"
+#endif
+#ifdef MSP
+#include "ext.h"
+#include "z_dsp.h"
+#include "ext_support.h"
+#include "ext_proto.h"
+#include "ext_obex.h"
+typedef float t_floatarg;
+#define t_resizebytes(a, b, c) t_resizebytes((char *)(a), (b), (c))
+#endif
+
+#if (defined(PD) || defined (MSP))
+
+#define NHIST 100
+
+#define MODE_STREAM 1
+#define MODE_BLOCK 2        /* unimplemented */
+#define MODE_TABLE 3
+
+#define NPOINTS_DEF 1024
+#define NPOINTS_MIN 128
+
+#define HOP_DEF 512
+#define NPEAK_DEF 20
+
+#define VIBRATO_DEF 1
+#define STABLETIME_DEF 50
+#define MINPOWER_DEF 50
+#define GROWTH_DEF 7
+
+#define OUT_PITCH 0
+#define OUT_ENV 1
+#define OUT_NOTE 2
+#define OUT_PEAKS 3
+#define OUT_TRACKS 4
+#define OUT_SMSPITCH 5
+#define OUT_SMSNONPITCH 6
+
+typedef struct _varout
+{
+#ifdef PD
+    t_outlet *v_outlet;
+#endif /* PD */
+#ifdef MSP
+    void *v_outlet;
+#endif /* MSP */
+    int v_what;
+} t_varout;
+
+typedef struct _sigmund
+{
+#ifdef PD
+    t_object x_obj;
+    t_clock *x_clock;
+    float x_f;          /* for main signal inlet */
+#endif /* PD */
+#ifdef MSP
+    t_pxobject x_obj;
+    void *obex;
+    void *x_clock;
+    t_sample *x_inbuf2; /* extra input buffer to eat clock/DSP jitter */
+#endif /* MSP */
+    t_varout *x_varoutv;
+    int x_nvarout;
+    float x_sr;         /* sample rate */
+    int x_mode;         /* MODE_STREAM, etc. */
+    int x_npts;         /* number of points in analysis window */
+    int x_npeak;        /* number of peaks to find */
+    int x_loud;         /* debug level */
+    t_sample *x_inbuf;  /* input buffer */
+    int x_infill;       /* number of points filled */
+    int x_countdown;    /* countdown to start filling buffer */
+    int x_hop;          /* samples between analyses */ 
+    float x_maxfreq;    /* highest-frequency peak to report */ 
+    float x_vibrato;    /* vibrato depth in half tones */ 
+    float x_stabletime; /* period of stability needed for note */ 
+    float x_growth;     /* growth to set off a new note */ 
+    float x_minpower;   /* minimum power, in DB, for a note */ 
+    float x_param1;     /* three parameters for temporary use */
+    float x_param2;
+    float x_param3;
+    t_notefinder x_notefinder;  /* note parsing state */
+    t_peak *x_trackv;           /* peak tracking state */
+    int x_ntrack;               /* number of peaks tracked */
+    unsigned int x_dopitch:1;   /* which things to calculate */
+    unsigned int x_donote:1;
+    unsigned int x_dotracks:1;
+} t_sigmund;
+
+static void sigmund_preinit(t_sigmund *x)
+{
+    x->x_npts = NPOINTS_DEF;
+    x->x_param1 = 0;
+    x->x_param2 = 0.6;
+    x->x_param3 = 0;
+    x->x_hop = HOP_DEF;
+    x->x_mode = MODE_STREAM;
+    x->x_npeak = NPEAK_DEF;
+    x->x_vibrato = VIBRATO_DEF;
+    x->x_stabletime = STABLETIME_DEF;
+    x->x_growth = GROWTH_DEF;
+    x->x_minpower = MINPOWER_DEF;
+    x->x_maxfreq = 1000000;
+    x->x_loud = 0;
+    x->x_sr = 1;
+    x->x_nvarout = 0;
+    x->x_varoutv = (t_varout *)getbytes(0);
+    x->x_trackv = 0;
+    x->x_ntrack = 0;
+    x->x_dopitch = x->x_donote = x->x_dotracks = 0;
+    x->x_inbuf = 0;
+#ifdef MSP
+    x->x_inbuf2 = 0;
+#endif
+}
+
+static void sigmund_npts(t_sigmund *x, t_floatarg f)
+{
+    int nwas = x->x_npts, npts = f;
+        /* check parameter ranges */
+    if (npts < NPOINTS_MIN)
+        post("sigmund~: minimum points %d", NPOINTS_MIN),
+            npts = NPOINTS_MIN;
+    if (npts != (1 << sigmund_ilog2(npts)))
+        post("sigmund~: adjusting analysis size to %d points",
+            (npts = (1 << sigmund_ilog2(npts))));
+    if (npts != nwas)
+        x->x_countdown = x->x_infill  = 0;
+    if (x->x_mode == MODE_STREAM)
+    {
+        if (x->x_inbuf)
+        {
+            x->x_inbuf = (t_sample *)t_resizebytes(x->x_inbuf,
+                sizeof(*x->x_inbuf) * nwas, sizeof(*x->x_inbuf) * npts);
+#ifdef MSP
+            x->x_inbuf2 = (t_sample *)t_resizebytes(x->x_inbuf2,
+                sizeof(*x->x_inbuf2) * nwas, sizeof(*x->x_inbuf2) * npts);
+#endif
+        }
+        else
+        {
+            x->x_inbuf = (t_sample *)getbytes(sizeof(*x->x_inbuf) * npts);
+            memset((char *)(x->x_inbuf), 0, sizeof(*x->x_inbuf) * npts);
+#ifdef MSP
+            x->x_inbuf2 = (t_sample *)getbytes(sizeof(*x->x_inbuf2) * npts);
+            memset((char *)(x->x_inbuf2), 0, sizeof(*x->x_inbuf2) * npts);
+#endif
+        }
+    }
+    else x->x_inbuf = 0;
+    x->x_npts = npts;
+}
+
+static void sigmund_hop(t_sigmund *x, t_floatarg f)
+{
+    x->x_hop = f;
+        /* check parameter ranges */
+    if (x->x_hop != (1 << sigmund_ilog2(x->x_hop)))
+        post("sigmund~: adjusting analysis size to %d points",
+            (x->x_hop = (1 << sigmund_ilog2(x->x_hop))));
+}
+
+static void sigmund_npeak(t_sigmund *x, t_floatarg f)
+{
+    if (f < 1)
+        f = 1;
+    x->x_npeak = f;
+}
+
+static void sigmund_maxfreq(t_sigmund *x, t_floatarg f)
+{
+    x->x_maxfreq = f;
+}
+
+static void sigmund_vibrato(t_sigmund *x, t_floatarg f)
+{
+    if (f < 0)
+        f = 0;
+    x->x_vibrato = f;
+}
+
+static void sigmund_stabletime(t_sigmund *x, t_floatarg f)
+{
+    if (f < 0)
+        f = 0;
+    x->x_stabletime = f;
+}
+
+static void sigmund_growth(t_sigmund *x, t_floatarg f)
+{
+    if (f < 0)
+        f = 0;
+    x->x_growth = f;
+}
+
+static void sigmund_minpower(t_sigmund *x, t_floatarg f)
+{
+    if (f < 0)
+        f = 0;
+    x->x_minpower = f;
+}
+
+static void sigmund_doit(t_sigmund *x, int npts, float *arraypoints,
+    int loud, float srate)
+{
+    t_peak *peakv = (t_peak *)alloca(sizeof(t_peak) * x->x_npeak);
+    int nfound, i, cnt;
+    float freq = 0, power, note = 0;
+    sigmund_getrawpeaks(npts, arraypoints, x->x_npeak, peakv,
+        &nfound, &power, srate, loud, x->x_param1, x->x_param2, x->x_param3,
+        x->x_maxfreq);
+    if (x->x_dopitch)
+        sigmund_getpitch(nfound, peakv, &freq, npts, srate, loud);
+    if (x->x_donote)
+        notefinder_doit(&x->x_notefinder, freq, power, &note, x->x_vibrato, 
+            1 + x->x_stabletime * 0.001f * x->x_sr / (float)x->x_hop,
+                exp(LOG10*0.1*(x->x_minpower - 100)), x->x_growth, loud);
+    if (x->x_dotracks)
+        sigmund_peaktrack(nfound, peakv, x->x_ntrack, x->x_trackv, loud);
+    
+    for (cnt = x->x_nvarout; cnt--;)
+    {
+        t_varout *v = &x->x_varoutv[cnt];
+        switch (v->v_what)
+        {
+        case OUT_PITCH:
+            outlet_float(v->v_outlet, sigmund_ftom(freq));
+            break;
+        case OUT_ENV:
+            outlet_float(v->v_outlet, sigmund_powtodb(power));
+            break;
+        case OUT_NOTE:
+            if (note > 0)
+                outlet_float(v->v_outlet, sigmund_ftom(note));
+            break;
+        case OUT_PEAKS:
+            for (i = 0; i < nfound; i++)
+            {
+                t_atom at[5];
+                SETFLOAT(at, (float)i);
+                SETFLOAT(at+1, peakv[i].p_freq);
+                SETFLOAT(at+2, 2*peakv[i].p_amp);
+                SETFLOAT(at+3, 2*peakv[i].p_ampreal);
+                SETFLOAT(at+4, 2*peakv[i].p_ampimag);
+                outlet_list(v->v_outlet, 0, 5, at);   
+            }
+            break;
+        case OUT_TRACKS:
+            for (i = 0; i < x->x_ntrack; i++)
+            {
+                t_atom at[4];
+                SETFLOAT(at, (float)i);
+                SETFLOAT(at+1, x->x_trackv[i].p_freq);
+                SETFLOAT(at+2, 2*x->x_trackv[i].p_amp);
+                SETFLOAT(at+3, x->x_trackv[i].p_tmp);
+                outlet_list(v->v_outlet, 0, 4, at);   
+            }
+            break;
+        }
+    }
+}
+
+static t_int *sigmund_perform(t_int *w);
+static void sigmund_dsp(t_sigmund *x, t_signal **sp)
+{
+    if (x->x_mode == MODE_STREAM)
+    {
+        if (x->x_hop % sp[0]->s_n)
+            post("sigmund: adjusting hop size to %d",
+                (x->x_hop = sp[0]->s_n * (x->x_hop / sp[0]->s_n)));
+        x->x_sr = sp[0]->s_sr;
+        dsp_add(sigmund_perform, 3, x, sp[0]->s_vec, sp[0]->s_n);
+    }
+}
+
+static void sigmund_print(t_sigmund *x)
+{
+    post("sigmund~ settings:");
+    post("npts %d", (int)x->x_npts);
+    post("hop %d", (int)x->x_hop);
+    post("npeak %d", (int)x->x_npeak);
+    post("maxfreq %g", x->x_maxfreq);
+    post("vibrato %g", x->x_vibrato);
+    post("stabletime %g", x->x_stabletime);
+    post("growth %g", x->x_growth);
+    post("minpower %g", x->x_minpower);
+    x->x_loud = 1;
+}
+
+static void sigmund_free(t_sigmund *x)
+{
+    if (x->x_inbuf)
+    {
+        freebytes(x->x_inbuf, x->x_npts * sizeof(*x->x_inbuf));
+#ifdef MSP
+        freebytes(x->x_inbuf2, x->x_npts * sizeof(*x->x_inbuf2));
+#endif
+    }
+    if (x->x_trackv)
+        freebytes(x->x_trackv, x->x_ntrack * sizeof(*x->x_trackv));
+    clock_free(x->x_clock);
+}
+
+#endif /* PD or MSP */
+/*************************** Glue for Pd ************************/
+#ifdef PD
+
+static t_class *sigmund_class;
+
+static void sigmund_tick(t_sigmund *x);
+static void sigmund_clear(t_sigmund *x);
+static void sigmund_npts(t_sigmund *x, t_floatarg f);
+static void sigmund_hop(t_sigmund *x, t_floatarg f);
+static void sigmund_npeak(t_sigmund *x, t_floatarg f);
+static void sigmund_maxfreq(t_sigmund *x, t_floatarg f);
+static void sigmund_vibrato(t_sigmund *x, t_floatarg f);
+static void sigmund_stabletime(t_sigmund *x, t_floatarg f);
+static void sigmund_growth(t_sigmund *x, t_floatarg f);
+static void sigmund_minpower(t_sigmund *x, t_floatarg f);
+
+static void sigmund_tick(t_sigmund *x)
+{
+    if (x->x_infill == x->x_npts)
+    {
+        sigmund_doit(x, x->x_npts, x->x_inbuf, x->x_loud, x->x_sr);
+        if (x->x_hop >= x->x_npts)
+        {
+            x->x_infill = 0;
+            x->x_countdown = x->x_hop - x->x_npts;
+        }
+        else
+        {
+            memmove(x->x_inbuf, x->x_inbuf + x->x_hop,
+                (x->x_infill = x->x_npts - x->x_hop) * sizeof(*x->x_inbuf));
+            x->x_countdown = 0;
+        }
+        if (x->x_loud)
+            x->x_loud--;
+    }
+}
+
+static t_int *sigmund_perform(t_int *w)
+{
+    t_sigmund *x = (t_sigmund *)(w[1]);
+    float *in = (float *)(w[2]);
+    int n = (int)(w[3]);
+
+    if (x->x_hop % n)
+        return (w+4);
+    if (x->x_countdown > 0)
+        x->x_countdown -= n;
+    else if (x->x_infill != x->x_npts)
+    {
+        int j;
+        float *fp = x->x_inbuf + x->x_infill;
+        for (j = 0; j < n; j++)
+            *fp++ = *in++;
+        x->x_infill += n;
+        if (x->x_infill == x->x_npts)
+            clock_delay(x->x_clock, 0);
+    }
+    return (w+4);
+}
+
+static void *sigmund_new(t_symbol *s, int argc, t_atom *argv)
+{
+    t_sigmund *x = (t_sigmund *)pd_new(sigmund_class);
+    sigmund_preinit(x);
+
+    while (argc > 0)
+    {
+        t_symbol *firstarg = atom_getsymbolarg(0, argc, argv);
+        if (!strcmp(firstarg->s_name, "-t"))
+        {
+            x->x_mode = MODE_TABLE;
+            argc--, argv++;
+        }
+        else if (!strcmp(firstarg->s_name, "-s"))
+        {
+            x->x_mode = MODE_STREAM;
+            argc--, argv++;
+        }
+#if 0
+        else if (!strcmp(firstarg->s_name, "-b"))
+        {
+            x->x_mode = MODE_BLOCK;
+            argc--, argv++;
+        }
+#endif
+        else if (!strcmp(firstarg->s_name, "-npts") && argc > 1)
+        {
+            x->x_npts = atom_getfloatarg(1, argc, argv);
+            argc -= 2; argv += 2;
+        }
+        else if (!strcmp(firstarg->s_name, "-hop") && argc > 1)
+        {
+            sigmund_hop(x, atom_getfloatarg(1, argc, argv));
+            argc -= 2; argv += 2;
+        }
+        else if (!strcmp(firstarg->s_name, "-npeak") && argc > 1)
+        {
+            sigmund_npeak(x, atom_getfloatarg(1, argc, argv));
+            argc -= 2; argv += 2;
+        }
+        else if (!strcmp(firstarg->s_name, "-maxfreq") && argc > 1)
+        {
+            sigmund_maxfreq(x, atom_getfloatarg(1, argc, argv));
+            argc -= 2; argv += 2;
+        }
+        else if (!strcmp(firstarg->s_name, "-vibrato") && argc > 1)
+        {
+            sigmund_vibrato(x, atom_getfloatarg(1, argc, argv));
+            argc -= 2; argv += 2;
+        }
+        else if (!strcmp(firstarg->s_name, "-stabletime") && argc > 1)
+        {
+            sigmund_stabletime(x, atom_getfloatarg(1, argc, argv));
+            argc -= 2; argv += 2;
+        }
+        else if (!strcmp(firstarg->s_name, "-growth") && argc > 1)
+        {
+            sigmund_growth(x, atom_getfloatarg(1, argc, argv));
+            argc -= 2; argv += 2;
+        }
+        else if (!strcmp(firstarg->s_name, "-minpower") && argc > 1)
+        {
+            sigmund_minpower(x, atom_getfloatarg(1, argc, argv));
+            argc -= 2; argv += 2;
+        }
+        else if (!strcmp(firstarg->s_name, "pitch"))
+        {
+            int n2 = x->x_nvarout+1;
+            x->x_varoutv = (t_varout *)t_resizebytes(x->x_varoutv,
+                x->x_nvarout*sizeof(t_varout), n2*sizeof(t_varout));
+            x->x_varoutv[x->x_nvarout].v_outlet =
+                outlet_new(&x->x_obj, &s_float);
+            x->x_varoutv[x->x_nvarout].v_what = OUT_PITCH;
+            x->x_nvarout = n2;
+            x->x_dopitch = 1;
+            argc--, argv++;
+        }
+        else if (!strcmp(firstarg->s_name, "env"))
+        {
+            int n2 = x->x_nvarout+1;
+            x->x_varoutv = (t_varout *)t_resizebytes(x->x_varoutv,
+                x->x_nvarout*sizeof(t_varout), n2*sizeof(t_varout));
+            x->x_varoutv[x->x_nvarout].v_outlet =
+                outlet_new(&x->x_obj, &s_float);
+            x->x_varoutv[x->x_nvarout].v_what = OUT_ENV;
+            x->x_nvarout = n2;
+            argc--, argv++;
+        }
+        else if (!strcmp(firstarg->s_name, "note")
+            || !strcmp(firstarg->s_name, "notes"))
+        {
+            int n2 = x->x_nvarout+1;
+            x->x_varoutv = (t_varout *)t_resizebytes(x->x_varoutv,
+                x->x_nvarout*sizeof(t_varout), n2*sizeof(t_varout));
+            x->x_varoutv[x->x_nvarout].v_outlet =
+                outlet_new(&x->x_obj, &s_float);
+            x->x_varoutv[x->x_nvarout].v_what = OUT_NOTE;
+            x->x_nvarout = n2;
+            x->x_dopitch = x->x_donote = 1;
+            argc--, argv++;
+        }
+        else if (!strcmp(firstarg->s_name, "peaks"))
+        {
+            int n2 = x->x_nvarout+1;
+            x->x_varoutv = (t_varout *)t_resizebytes(x->x_varoutv,
+                x->x_nvarout*sizeof(t_varout), n2*sizeof(t_varout));
+            x->x_varoutv[x->x_nvarout].v_outlet =
+                outlet_new(&x->x_obj, &s_list);
+            x->x_varoutv[x->x_nvarout].v_what = OUT_PEAKS;
+            x->x_nvarout = n2;
+            argc--, argv++;
+        }
+        else if (!strcmp(firstarg->s_name, "tracks"))
+        {
+            int n2 = x->x_nvarout+1;
+            x->x_varoutv = (t_varout *)t_resizebytes(x->x_varoutv,
+                x->x_nvarout*sizeof(t_varout), n2*sizeof(t_varout));
+            x->x_varoutv[x->x_nvarout].v_outlet =
+                outlet_new(&x->x_obj, &s_list);
+            x->x_varoutv[x->x_nvarout].v_what = OUT_TRACKS;
+            x->x_nvarout = n2;
+            x->x_dotracks = 1;
+            argc--, argv++;
+        }
+        else
+        {
+            pd_error(x, "sigmund: %s: unknown flag or argument missing",
+                firstarg->s_name);
+            argc--, argv++;
+        }
+    }
+    if (!x->x_nvarout)
+    {
+        x->x_varoutv = (t_varout *)t_resizebytes(x->x_varoutv,
+            0, 2*sizeof(t_varout));
+        x->x_varoutv[0].v_outlet = outlet_new(&x->x_obj, &s_float);
+        x->x_varoutv[0].v_what = OUT_PITCH;
+        x->x_varoutv[1].v_outlet = outlet_new(&x->x_obj, &s_float);
+        x->x_varoutv[1].v_what = OUT_ENV;
+        x->x_nvarout = 2;
+        x->x_dopitch = 1;
+    }
+    if (x->x_dotracks)
+    {
+        x->x_ntrack = x->x_npeak;
+        x->x_trackv = (t_peak *)getbytes(x->x_ntrack * sizeof(*x->x_trackv));
+    }
+    x->x_clock = clock_new(&x->x_obj.ob_pd, (t_method)sigmund_tick);
+    
+    x->x_infill = 0;
+    x->x_countdown = 0;
+    sigmund_npts(x, x->x_npts);
+    notefinder_init(&x->x_notefinder);
+    sigmund_clear(x);
+    return (x);
+}
+
+static void sigmund_list(t_sigmund *x, t_symbol *s, int argc, t_atom *argv)
+{
+    t_symbol *syminput = atom_getsymbolarg(0, argc, argv);
+    int npts = atom_getintarg(1, argc, argv);
+    int onset = atom_getintarg(2, argc, argv);
+    float srate = atom_getfloatarg(3, argc, argv);
+    int loud = atom_getfloatarg(4, argc, argv);
+    int arraysize, totstorage, nfound, i;
+    t_garray *a;
+    float *arraypoints, pit;
+    t_word *wordarray = 0;
+    if (argc < 5)
+    {
+        post(
+         "sigmund: array-name, npts, array-onset, samplerate, loud");
+        return;
+    }
+    if (npts < 64 || npts != (1 << ilog2(npts))) 
+    {
+        error("sigmund: bad npoints");
+        return;
+    }
+    if (onset < 0)
+    {
+        error("sigmund: negative onset");
+        return;
+    }
+    arraypoints = alloca(sizeof(float)*npts);
+    if (!(a = (t_garray *)pd_findbyclass(syminput, garray_class)) ||
+        !garray_getfloatwords(a, &arraysize, &wordarray) ||
+            arraysize < onset + npts)
+    {
+        error("%s: array missing or too small", syminput->s_name);
+        return;
+    }
+    if (arraysize < npts)
+    {
+        error("sigmund~: too few points in array");
+        return;
+    }
+    for (i = 0; i < npts; i++)
+        arraypoints[i] = wordarray[i+onset].w_float;
+    sigmund_doit(x, npts, arraypoints, loud, srate);
+}
+
+static void sigmund_clear(t_sigmund *x)
+{
+    if (x->x_trackv)
+        memset(x->x_trackv, 0, x->x_ntrack * sizeof(*x->x_trackv));
+    x->x_infill = x->x_countdown = 0;
+}
+
+    /* these are for testing; their meanings vary... */
+static void sigmund_param1(t_sigmund *x, t_floatarg f)
+{
+    x->x_param1 = f;
+}
+
+static void sigmund_param2(t_sigmund *x, t_floatarg f)
+{
+    x->x_param2 = f;
+}
+
+static void sigmund_param3(t_sigmund *x, t_floatarg f)
+{
+    x->x_param3 = f;
+}
+
+static void sigmund_printnext(t_sigmund *x, t_float f)
+{
+    x->x_loud = f;
+}
+
+void sigmund_tilde_setup(void)
+{
+    sigmund_class = class_new(gensym("sigmund~"), (t_newmethod)sigmund_new,
+        (t_method)sigmund_free, sizeof(t_sigmund), 0, A_GIMME, 0);
+    class_addlist(sigmund_class, sigmund_list);
+    class_addmethod(sigmund_class, (t_method)sigmund_dsp, gensym("dsp"), 0);
+    CLASS_MAINSIGNALIN(sigmund_class, t_sigmund, x_f);
+    class_addmethod(sigmund_class, (t_method)sigmund_param1,
+        gensym("param1"), A_FLOAT, 0);
+    class_addmethod(sigmund_class, (t_method)sigmund_param2,
+        gensym("param2"), A_FLOAT, 0);
+    class_addmethod(sigmund_class, (t_method)sigmund_param3,
+        gensym("param3"), A_FLOAT, 0);
+    class_addmethod(sigmund_class, (t_method)sigmund_npts,
+        gensym("npts"), A_FLOAT, 0);
+    class_addmethod(sigmund_class, (t_method)sigmund_hop,
+        gensym("hop"), A_FLOAT, 0);
+    class_addmethod(sigmund_class, (t_method)sigmund_maxfreq,
+        gensym("maxfreq"), A_FLOAT, 0);
+    class_addmethod(sigmund_class, (t_method)sigmund_npeak,
+        gensym("npeak"), A_FLOAT, 0);
+    class_addmethod(sigmund_class, (t_method)sigmund_vibrato,
+        gensym("vibrato"), A_FLOAT, 0);
+    class_addmethod(sigmund_class, (t_method)sigmund_stabletime,
+        gensym("stabletime"), A_FLOAT, 0);
+    class_addmethod(sigmund_class, (t_method)sigmund_growth,
+        gensym("growth"), A_FLOAT, 0);
+    class_addmethod(sigmund_class, (t_method)sigmund_minpower,
+        gensym("minpower"), A_FLOAT, 0);
+    class_addmethod(sigmund_class, (t_method)sigmund_print,
+        gensym("print"), 0);
+    class_addmethod(sigmund_class, (t_method)sigmund_printnext,
+        gensym("printnext"), A_FLOAT, 0);
+    post("sigmund~ version 0.07");
+}
+
+#endif /* PD */
+
+/************************ Max/MSP glue **********************************/
+
+/* -------------------------- MSP glue ------------------------- */
+#ifdef MSP
+static void *sigmund_class;
+
+/* Max/MSP has laxer sync between DSP and "tick"s - so in the perf routine we
+keep a circular buffer that is rectified into inbuf only when the tick comes. */
+
+static void sigmund_tick(t_sigmund *x)
+{
+    int i, j, npts = x->x_npts;
+    if (!x->x_inbuf)
+        return;
+    for (i = x->x_infill, j = 0; i < npts; i++, j++)
+        x->x_inbuf[j] = x->x_inbuf2[i];
+    for (i = 0; j < npts; i++, j++)
+        x->x_inbuf[j] = x->x_inbuf2[i];
+    sigmund_doit(x, x->x_npts, x->x_inbuf, x->x_loud, x->x_sr);
+    x->x_loud = 0;
+}
+
+static t_int *sigmund_perform(t_int *w)
+{
+    t_sigmund *x = (t_sigmund *)(w[1]);
+    float *in = (float *)(w[2]);
+    int n = (int)(w[3]), j;
+    int infill = x->x_infill;
+    float *fp = x->x_inbuf2 + infill;
+
+    if (x->x_obj.z_disabled) /* return if in muted MSP subpatch -Rd */
+        return (w+4);
+
+    if (infill < 0 || infill >= x->x_npts)
+        infill = 0;
+        /* for some reason this sometimes happens: */
+    if (!x->x_inbuf2)
+        return (w+4);
+    for (j = 0; j < n; j++)
+    {
+         *fp++ = *in++;
+         if (++infill == x->x_npts)
+            infill = 0, fp = x->x_inbuf2;
+    }
+    x->x_infill = infill;
+    if (x->x_countdown <= 0)
+    {
+        x->x_countdown = x->x_hop;
+        clock_delay(x->x_clock, 0);
+    }
+    x->x_countdown -= n;
+    return (w+4);
+}
+
+static void *sigmund_new(t_symbol *s, long ac, t_atom *av)
+{
+    t_sigmund *x;
+    t_varout *g;
+    int i, j;
+    if (!(x = (t_sigmund *)object_alloc(sigmund_class)))
+        return (0);
+    sigmund_preinit(x);
+    attr_args_process(x, ac, av);   
+    dsp_setup((t_pxobject *)x, 1);
+    object_obex_store(x, gensym("dumpout"), outlet_new(x, NULL));
+    
+    for (i = 0; i < ac; i++)
+        if (av[i].a_type == A_SYM)
+    {
+        char *s = av[i].a_w.w_sym->s_name;
+        if (!strcmp(s, "pitch"))
+        {
+            int n2 = x->x_nvarout+1;
+            x->x_varoutv = (t_varout *)t_resizebytes(x->x_varoutv,
+                x->x_nvarout*sizeof(t_varout), n2*sizeof(t_varout));
+            x->x_varoutv[x->x_nvarout].v_what = OUT_PITCH;
+            x->x_nvarout = n2;
+            x->x_dopitch = 1;
+        }
+        else if (!strcmp(s, "env"))
+        {
+            int n2 = x->x_nvarout+1;
+            x->x_varoutv = (t_varout *)t_resizebytes(x->x_varoutv,
+                x->x_nvarout*sizeof(t_varout), n2*sizeof(t_varout));
+            x->x_varoutv[x->x_nvarout].v_what = OUT_ENV;
+            x->x_nvarout = n2;
+        }
+        else if (!strcmp(s, "note") || !strcmp(s, "notes"))
+        {
+            int n2 = x->x_nvarout+1;
+            x->x_varoutv = (t_varout *)t_resizebytes(x->x_varoutv,
+                x->x_nvarout*sizeof(t_varout), n2*sizeof(t_varout));
+            x->x_varoutv[x->x_nvarout].v_what = OUT_NOTE;
+            x->x_nvarout = n2;
+            x->x_dopitch = x->x_donote = 1;
+        }
+        else if (!strcmp(s, "peaks"))
+        {
+            int n2 = x->x_nvarout+1;
+            x->x_varoutv = (t_varout *)t_resizebytes(x->x_varoutv,
+                x->x_nvarout*sizeof(t_varout), n2*sizeof(t_varout));
+            x->x_varoutv[x->x_nvarout].v_what = OUT_PEAKS;
+            x->x_nvarout = n2;
+        }
+        else if (!strcmp(s, "tracks"))
+        {
+            int n2 = x->x_nvarout+1;
+            x->x_varoutv = (t_varout *)t_resizebytes(x->x_varoutv,
+                x->x_nvarout*sizeof(t_varout), n2*sizeof(t_varout));
+            x->x_varoutv[x->x_nvarout].v_what = OUT_TRACKS;
+            x->x_nvarout = n2;
+            x->x_dotracks = 1;
+        }
+        else if (s[0] != '@')
+            post("sigmund: ignoring unknown argument '%s'" ,s);
+    }
+    if (!x->x_nvarout)
+    {
+        x->x_varoutv = (t_varout *)t_resizebytes(x->x_varoutv,
+            0, 2*sizeof(t_varout));
+        x->x_varoutv[0].v_what = OUT_PITCH;
+        x->x_varoutv[1].v_what = OUT_ENV;
+        x->x_nvarout = 2;
+        x->x_dopitch = 1;
+    }
+    for (j = 0, g = x->x_varoutv + x->x_nvarout-1; j < x->x_nvarout; j++, g--)
+        g->v_outlet = ((g->v_what == OUT_PITCH  || g->v_what == OUT_ENV ||
+            g->v_what == OUT_NOTE) ?
+                floatout((t_object *)x) : listout((t_object *)x));
+    if (x->x_dotracks)
+    {
+        x->x_ntrack = x->x_npeak;
+        x->x_trackv = (t_peak *)getbytes(x->x_ntrack * sizeof(*x->x_trackv));
+    }
+    x->x_clock = clock_new(x, (method)sigmund_tick);
+    x->x_infill = 0;
+    x->x_countdown = 0;
+    sigmund_npts(x, x->x_npts);
+    notefinder_init(&x->x_notefinder);
+    return (x);
+}
+
+/* Attribute setters. */
+void sigmund_npts_set(t_sigmund *x, void *attr, long ac, t_atom *av)
+{
+    if (ac && av)
+        sigmund_npts(x, atom_getfloat(av));
+}
+
+void sigmund_hop_set(t_sigmund *x, void *attr, long ac, t_atom *av)
+{
+    if (ac && av)
+        sigmund_hop(x, atom_getfloat(av));
+}
+
+void sigmund_npeak_set(t_sigmund *x, void *attr, long ac, t_atom *av)
+{
+    if (ac && av)
+        sigmund_npeak(x, atom_getfloat(av));
+}
+
+void sigmund_maxfreq_set(t_sigmund *x, void *attr, long ac, t_atom *av)
+{
+    if (ac && av)
+        sigmund_maxfreq(x, atom_getfloat(av));
+}
+
+void sigmund_vibrato_set(t_sigmund *x, void *attr, long ac, t_atom *av)
+{
+    if (ac && av)
+        sigmund_vibrato(x, atom_getfloat(av));
+}
+
+void sigmund_stabletime_set(t_sigmund *x, void *attr, long ac, t_atom *av)
+{
+    if (ac && av)
+        sigmund_stabletime(x, atom_getfloat(av));
+}
+
+void sigmund_growth_set(t_sigmund *x, void *attr, long ac, t_atom *av)
+{
+    if (ac && av)
+        sigmund_growth(x, atom_getfloat(av));
+}
+
+void sigmund_minpower_set(t_sigmund *x, void *attr, long ac, t_atom *av)
+{
+    if (ac && av)
+        sigmund_minpower(x, atom_getfloat(av));
+}
+
+/* end attr setters */
+
+void sigmund_assist(t_sigmund *x, void *b, long m, long a, char *s)
+{
+}
+
+int main()
+{       
+    t_class *c;
+    long attrflags = 0;
+    t_symbol *sym_long = gensym("long"), *sym_float32 = gensym("float32");
+    
+    c = class_new("sigmund~", (method)sigmund_new,
+        (method)sigmund_free, sizeof(t_sigmund), (method)0L, A_GIMME, 0);
+    
+    class_obexoffset_set(c, calcoffset(t_sigmund, obex));
+    
+    class_addattr(c, attr_offset_new("npts", sym_long, attrflags,
+        (method)0L, (method)sigmund_npts_set,
+            calcoffset(t_sigmund, x_npts)));
+    class_addattr(c ,attr_offset_new("hop", sym_long, attrflags,
+        (method)0L, (method)sigmund_hop_set,
+            calcoffset(t_sigmund, x_hop)));
+    class_addattr(c ,attr_offset_new("maxfreq", sym_float32, attrflags,
+        (method)0L, (method)sigmund_maxfreq_set,
+            calcoffset(t_sigmund, x_maxfreq)));
+    class_addattr(c ,attr_offset_new("npeak", sym_long, attrflags,
+        (method)0L, (method)sigmund_npeak_set,
+            calcoffset(t_sigmund, x_npeak)));
+    class_addattr(c ,attr_offset_new("vibrato", sym_float32, attrflags,
+        (method)0L, (method)sigmund_vibrato_set,
+            calcoffset(t_sigmund, x_vibrato)));
+    class_addattr(c ,attr_offset_new("stabletime", sym_float32, attrflags,
+        (method)0L, (method)sigmund_stabletime_set,
+            calcoffset(t_sigmund, x_stabletime)));
+    class_addattr(c ,attr_offset_new("growth", sym_float32, attrflags,
+        (method)0L, (method)sigmund_growth_set,
+            calcoffset(t_sigmund, x_growth)));
+    class_addattr(c ,attr_offset_new("minpower", sym_float32, attrflags,
+        (method)0L, (method)sigmund_minpower_set,
+            calcoffset(t_sigmund, x_minpower)));
+
+    class_addmethod(c, (method)sigmund_dsp, "dsp", A_CANT, 0);
+    class_addmethod(c, (method)sigmund_print, "print", 0);
+    class_addmethod(c, (method)sigmund_print, "printnext", A_DEFFLOAT, 0);
+    class_addmethod(c, (method)sigmund_assist, "assist", A_CANT, 0);
+    
+    class_addmethod(c, (method)object_obex_dumpout, "dumpout", A_CANT, 0);
+    class_addmethod(c, (method)object_obex_quickref, "quickref", A_CANT, 0);
+    
+    class_dspinit(c);
+
+    class_register(CLASS_BOX, c);
+    sigmund_class = c;
+    
+    post("sigmund~ version 0.07");
+    return (0);
+}
+
+
+#endif /* MSP */
+
+
diff --git a/extra/stdout/stdout.pd_linux b/extra/stdout/stdout.pd_linux
deleted file mode 100755
index 73254ff1a5793ff52e60d61bd0df11efc7159cf8..0000000000000000000000000000000000000000
Binary files a/extra/stdout/stdout.pd_linux and /dev/null differ
diff --git a/src/ todo b/src/ todo
new file mode 100644
index 0000000000000000000000000000000000000000..829257e899ebdff1ec9339ca45b85de902a42f2a
--- /dev/null
+++ b/src/ todo	
@@ -0,0 +1,16 @@
+fix going outside boundaries
+fix drawing when using const or drawing at the threshold
+
+struct _garray
+{
+    t_gobj x_gobj;
+    t_scalar *x_scalar;     /* scalar "containing" the array */
+    t_glist *x_glist;       /* containing glist */
+    t_symbol *x_name;       /* unexpanded name (possibly with leading '$') */
+    t_symbol *x_realname;   /* expanded name (symbol we're bound to) */
+    char x_usedindsp;       /* true if some DSP routine is using this */
+    char x_saveit;          /* true if we should save this with parent */
+    char x_listviewing;     /* true if list view window is open */
+    char x_hidename;        /* don't print name above graph */
+	t_symbol *x_send;		/* send_changed hook */
+};
diff --git a/src/d_delay.c.orig b/src/d_delay.c.orig
new file mode 100644
index 0000000000000000000000000000000000000000..3571e89a6e79994e402bfdc89d07c4a7519e3f9a
--- /dev/null
+++ b/src/d_delay.c.orig
@@ -0,0 +1,325 @@
+/* Copyright (c) 1997-1999 Miller Puckette.
+* For information on usage and redistribution, and for a DISCLAIMER OF ALL
+* WARRANTIES, see the file, "LICENSE.txt," in this distribution.  */
+
+/*  send~, delread~, throw~, catch~ */
+
+#include "m_pd.h"
+extern int ugen_getsortno(void);
+
+#define DEFDELVS 64             /* LATER get this from canvas at DSP time */
+static int delread_zero = 0;    /* four bytes of zero for delread~, vd~ */
+
+/* ----------------------------- delwrite~ ----------------------------- */
+static t_class *sigdelwrite_class;
+
+typedef struct delwritectl
+{
+    int c_n;
+    t_sample *c_vec;
+    int c_phase;
+} t_delwritectl;
+
+typedef struct _sigdelwrite
+{
+    t_object x_obj;
+    t_symbol *x_sym;
+    t_delwritectl x_cspace;
+    int x_sortno;   /* DSP sort number at which this was last put on chain */
+    int x_rsortno;  /* DSP sort # for first delread or write in chain */
+    int x_vecsize;  /* vector size for delread~ to use */
+    t_float x_f;
+} t_sigdelwrite;
+
+#define XTRASAMPS 4
+#define SAMPBLK 4
+
+    /* routine to check that all delwrites/delreads/vds have same vecsize */
+static void sigdelwrite_checkvecsize(t_sigdelwrite *x, int vecsize)
+{
+    if (x->x_rsortno != ugen_getsortno())
+    {
+        x->x_vecsize = vecsize;
+        x->x_rsortno = ugen_getsortno();
+    }
+    /*
+        LATER this should really check sample rate and blocking, once that is
+        supported.  Probably we don't actually care about vecsize.
+        For now just suppress this check. */
+#if 0
+    else if (vecsize != x->x_vecsize)
+        pd_error(x, "delread/delwrite/vd vector size mismatch");
+#endif
+}
+
+#include <stdio.h>
+
+static void *sigdelwrite_new(t_symbol *s, t_floatarg msec)
+{
+    int nsamps;
+    t_sigdelwrite *x = (t_sigdelwrite *)pd_new(sigdelwrite_class);
+    if (!*s->s_name) s = gensym("delwrite~");
+    pd_bind(&x->x_obj.ob_pd, s);
+    x->x_sym = s;
+	if (msec == 0) msec = 1000;
+    nsamps = msec * sys_getsr() * (t_float)(0.001f);
+    if (nsamps < 1) nsamps = 1;
+    nsamps += ((- nsamps) & (SAMPBLK - 1));
+    nsamps += DEFDELVS;
+    x->x_cspace.c_n = nsamps;
+    x->x_cspace.c_vec =
+        (t_sample *)getbytes((nsamps + XTRASAMPS) * sizeof(t_sample));
+    x->x_cspace.c_phase = XTRASAMPS;
+    x->x_sortno = 0;
+    x->x_vecsize = 0;
+    x->x_f = 0;
+    return (x);
+}
+
+static t_int *sigdelwrite_perform(t_int *w)
+{
+    t_sample *in = (t_sample *)(w[1]);
+    t_delwritectl *c = (t_delwritectl *)(w[2]);
+    int n = (int)(w[3]);
+    int phase = c->c_phase, nsamps = c->c_n;
+    t_sample *vp = c->c_vec, *bp = vp + phase, *ep = vp + (c->c_n + XTRASAMPS);
+    phase += n;
+
+    while (n--)
+    {
+        t_sample f = *in++;
+        if (PD_BIGORSMALL(f))
+            f = 0;
+        *bp++ = f;
+        if (bp == ep)
+        {
+            vp[0] = ep[-4];
+            vp[1] = ep[-3];
+            vp[2] = ep[-2];
+            vp[3] = ep[-1];
+            bp = vp + XTRASAMPS;
+            phase -= nsamps;
+        }
+    }
+    bp = vp + c->c_phase;
+
+    c->c_phase = phase; 
+    return (w+4);
+}
+
+static void sigdelwrite_dsp(t_sigdelwrite *x, t_signal **sp)
+{
+    dsp_add(sigdelwrite_perform, 3, sp[0]->s_vec, &x->x_cspace, sp[0]->s_n);
+    x->x_sortno = ugen_getsortno();
+    sigdelwrite_checkvecsize(x, sp[0]->s_n);
+}
+
+static void sigdelwrite_free(t_sigdelwrite *x)
+{
+    pd_unbind(&x->x_obj.ob_pd, x->x_sym);
+    freebytes(x->x_cspace.c_vec,
+        (x->x_cspace.c_n + XTRASAMPS) * sizeof(t_sample));
+}
+
+static void sigdelwrite_setup(void)
+{
+    sigdelwrite_class = class_new(gensym("delwrite~"), 
+        (t_newmethod)sigdelwrite_new, (t_method)sigdelwrite_free,
+        sizeof(t_sigdelwrite), 0, A_DEFSYM, A_DEFFLOAT, 0);
+    CLASS_MAINSIGNALIN(sigdelwrite_class, t_sigdelwrite, x_f);
+    class_addmethod(sigdelwrite_class, (t_method)sigdelwrite_dsp,
+        gensym("dsp"), 0);
+}
+
+/* ----------------------------- delread~ ----------------------------- */
+static t_class *sigdelread_class;
+
+typedef struct _sigdelread
+{
+    t_object x_obj;
+    t_symbol *x_sym;
+    t_float x_deltime;  /* delay in msec */
+    int x_delsamps;     /* delay in samples */
+    t_float x_sr;       /* samples per msec */
+    t_float x_n;        /* vector size */
+    int x_zerodel;      /* 0 or vecsize depending on read/write order */
+} t_sigdelread;
+
+static void sigdelread_float(t_sigdelread *x, t_float f);
+
+static void *sigdelread_new(t_symbol *s, t_floatarg f)
+{
+    t_sigdelread *x = (t_sigdelread *)pd_new(sigdelread_class);
+    x->x_sym = s;
+    x->x_sr = 1;
+    x->x_n = 1;
+    x->x_zerodel = 0;
+    sigdelread_float(x, f);
+    outlet_new(&x->x_obj, &s_signal);
+    return (x);
+}
+
+static void sigdelread_float(t_sigdelread *x, t_float f)
+{
+    int samps;
+    t_sigdelwrite *delwriter =
+        (t_sigdelwrite *)pd_findbyclass(x->x_sym, sigdelwrite_class);
+    x->x_deltime = f;
+    if (delwriter)
+    {
+        int delsize = delwriter->x_cspace.c_n;
+        x->x_delsamps = (int)(0.5 + x->x_sr * x->x_deltime)
+            + x->x_n - x->x_zerodel;
+        if (x->x_delsamps < x->x_n) x->x_delsamps = x->x_n;
+        else if (x->x_delsamps > delwriter->x_cspace.c_n - DEFDELVS)
+            x->x_delsamps = delwriter->x_cspace.c_n - DEFDELVS;
+    }
+}
+
+static t_int *sigdelread_perform(t_int *w)
+{
+    t_sample *out = (t_sample *)(w[1]);
+    t_delwritectl *c = (t_delwritectl *)(w[2]);
+    int delsamps = *(int *)(w[3]);
+    int n = (int)(w[4]);
+    int phase = c->c_phase - delsamps, nsamps = c->c_n;
+    t_sample *vp = c->c_vec, *bp, *ep = vp + (c->c_n + XTRASAMPS);
+    if (phase < 0) phase += nsamps;
+    bp = vp + phase;
+
+    while (n--)
+    {
+        *out++ = *bp++;
+        if (bp == ep) bp -= nsamps;
+    }
+    return (w+5);
+}
+
+static void sigdelread_dsp(t_sigdelread *x, t_signal **sp)
+{
+    t_sigdelwrite *delwriter =
+        (t_sigdelwrite *)pd_findbyclass(x->x_sym, sigdelwrite_class);
+    x->x_sr = sp[0]->s_sr * 0.001;
+    x->x_n = sp[0]->s_n;
+    if (delwriter)
+    {
+        sigdelwrite_checkvecsize(delwriter, sp[0]->s_n);
+        x->x_zerodel = (delwriter->x_sortno == ugen_getsortno() ?
+            0 : delwriter->x_vecsize);
+        sigdelread_float(x, x->x_deltime);
+        dsp_add(sigdelread_perform, 4,
+            sp[0]->s_vec, &delwriter->x_cspace, &x->x_delsamps, sp[0]->s_n);
+    }
+    else if (*x->x_sym->s_name)
+        error("delread~: %s: no such delwrite~",x->x_sym->s_name);
+}
+
+static void sigdelread_setup(void)
+{
+    sigdelread_class = class_new(gensym("delread~"),
+        (t_newmethod)sigdelread_new, 0,
+        sizeof(t_sigdelread), 0, A_DEFSYM, A_DEFFLOAT, 0);
+    class_addmethod(sigdelread_class, (t_method)sigdelread_dsp,
+        gensym("dsp"), 0);
+    class_addfloat(sigdelread_class, (t_method)sigdelread_float);
+}
+
+
+/* ----------------------------- vd~ ----------------------------- */
+static t_class *sigvd_class;
+
+typedef struct _sigvd
+{
+    t_object x_obj;
+    t_symbol *x_sym;
+    t_float x_sr;       /* samples per msec */
+    int x_zerodel;      /* 0 or vecsize depending on read/write order */
+    t_float x_f;
+} t_sigvd;
+
+static void *sigvd_new(t_symbol *s)
+{
+    t_sigvd *x = (t_sigvd *)pd_new(sigvd_class);
+    if (!*s->s_name) s = gensym("vd~");
+    x->x_sym = s;
+    x->x_sr = 1;
+    x->x_zerodel = 0;
+    outlet_new(&x->x_obj, &s_signal);
+    x->x_f = 0;
+    return (x);
+}
+
+static t_int *sigvd_perform(t_int *w)
+{
+    t_sample *in = (t_sample *)(w[1]);
+    t_sample *out = (t_sample *)(w[2]);
+    t_delwritectl *ctl = (t_delwritectl *)(w[3]);
+    t_sigvd *x = (t_sigvd *)(w[4]);
+    int n = (int)(w[5]);
+
+    int nsamps = ctl->c_n;
+    t_sample limit = nsamps - n - 1;
+    t_sample fn = n-1;
+    t_sample *vp = ctl->c_vec, *bp, *wp = vp + ctl->c_phase;
+    t_sample zerodel = x->x_zerodel;
+    while (n--)
+    {
+        t_sample delsamps = x->x_sr * *in++ - zerodel, frac;
+        int idelsamps;
+        t_sample a, b, c, d, cminusb;
+        if (delsamps < 1.00001f) delsamps = 1.00001f;
+        if (delsamps > limit) delsamps = limit;
+        delsamps += fn;
+        fn = fn - 1.0f;
+        idelsamps = delsamps;
+        frac = delsamps - (t_sample)idelsamps;
+        bp = wp - idelsamps;
+        if (bp < vp + 4) bp += nsamps;
+        d = bp[-3];
+        c = bp[-2];
+        b = bp[-1];
+        a = bp[0];
+        cminusb = c-b;
+        *out++ = b + frac * (
+            cminusb - 0.1666667f * (1.-frac) * (
+                (d - a - 3.0f * cminusb) * frac + (d + 2.0f*a - 3.0f*b)
+            )
+        );
+    }
+    return (w+6);
+}
+
+static void sigvd_dsp(t_sigvd *x, t_signal **sp)
+{
+    t_sigdelwrite *delwriter =
+        (t_sigdelwrite *)pd_findbyclass(x->x_sym, sigdelwrite_class);
+    x->x_sr = sp[0]->s_sr * 0.001;
+    if (delwriter)
+    {
+        sigdelwrite_checkvecsize(delwriter, sp[0]->s_n);
+        x->x_zerodel = (delwriter->x_sortno == ugen_getsortno() ?
+            0 : delwriter->x_vecsize);
+        dsp_add(sigvd_perform, 5,
+            sp[0]->s_vec, sp[1]->s_vec,
+                &delwriter->x_cspace, x, sp[0]->s_n);
+    }
+    else error("vd~: %s: no such delwrite~",x->x_sym->s_name);
+}
+
+static void sigvd_setup(void)
+{
+    sigvd_class = class_new(gensym("vd~"), (t_newmethod)sigvd_new, 0,
+        sizeof(t_sigvd), 0, A_DEFSYM, 0);
+    class_addmethod(sigvd_class, (t_method)sigvd_dsp, gensym("dsp"), 0);
+    CLASS_MAINSIGNALIN(sigvd_class, t_sigvd, x_f);
+}
+
+/* ----------------------- global setup routine ---------------- */
+
+void d_delay_setup(void)
+{
+    sigdelwrite_setup();
+    sigdelread_setup();
+    sigvd_setup();
+}
+
diff --git a/src/g_canvas.c b/src/g_canvas.c
index c8b5aa79836a8a7f66aa730399260d36b11cd481..0fee01389f44f284daab0a0bc7d58b65175c0c01 100644
--- a/src/g_canvas.c
+++ b/src/g_canvas.c
@@ -709,40 +709,55 @@ void canvas_map(t_canvas *x, t_floatarg f)
     t_gobj *y;
     if (flag)
     {
-		//fprintf(stderr,"canvas_map 1\n");
-        //if (!glist_isvisible(x))
-        //{
-			//fprintf(stderr,"canvas_map 1 isvisible\n");
-        t_selection *sel;
-        if (!x->gl_havewindow)
+        if (!glist_isvisible(x))
         {
-            bug("canvas_map");
-            canvas_vis(x, 1);
-        }
-
-		if (!x->gl_list) {
-			//if there are no objects on the canvas
-			canvas_create_editor(x);
-		}
-        else for (y = x->gl_list; y; y = y->g_next) {
-            gobj_vis(y, x, 1);
+            t_selection *sel;
+            if (!x->gl_havewindow)
+            {
+                bug("canvas_map");
+                canvas_vis(x, 1);
+            }
+			else if (x->gl_mapped == 0)
+				canvas_vis(x, 1);
+
+			/* 	if parent has editor enabled and we're a sub-patch,
+				(but not an abstraction) match its edit mode to that
+				of its parent patch. */
+			/*t_glist *parentx;
+			if (!canvas_isabstraction(x)) {
+				if (x->gl_owner) {
+					parentx = x->gl_owner;
+					while (parentx->gl_owner)
+						parentx = parentx->gl_owner;
+					if (parentx->gl_edit)
+						canvas_editmode(x, 1);
+					else if (x->gl_edit)
+						canvas_editmode(x, 0);
+				}
+			}*/
+			/*	for parent windows, let's make sure the cursor is updated
+				as soon as the window is open (if in edit mode) */
+			//else if (x->gl_edit) {
+				//canvas_setcursor(x, CURSOR_EDITMODE_NOTHING);
+			//}
+
+            for (y = x->gl_list; y; y = y->g_next)
+                gobj_vis(y, x, 1);
 			if (x->gl_editor && x->gl_editor->e_selection)
-	        	for (sel = x->gl_editor->e_selection; sel; sel = sel->sel_next)
-	            	gobj_select(sel->sel_what, x, 1);
-		}
-        x->gl_mapped = 1;
-        canvas_drawlines(x);
-        if (x->gl_isgraph && x->gl_goprect)
-            canvas_drawredrect(x, 1);
-        sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", x);
-        //}
+            	for (sel = x->gl_editor->e_selection; sel; sel = sel->sel_next)
+                	gobj_select(sel->sel_what, x, 1);
+            x->gl_mapped = 1;
+            canvas_drawlines(x);
+            if (x->gl_isgraph && x->gl_goprect)
+                canvas_drawredrect(x, 1);
+            sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", x);
+        }
     }
     else
     {
-		//fprintf(stderr,"canvas_map 0\n");
         if (glist_isvisible(x))
         {
-            /* just clear out the whole canvas */
+                /* just clear out the whole canvas */
 			sys_vgui(".x%lx.c dtag all selected\n", x);
             sys_vgui(".x%lx.c delete all\n", x);
             x->gl_mapped = 0;
@@ -816,9 +831,13 @@ void canvas_free(t_canvas *x)
 {
     t_gobj *y;
     int dspstate = canvas_suspend_dsp();
-
+    // jsarlo
     if (x->gl_magic_glass)
       magicGlass_free(x->gl_magic_glass);
+    // end jsarlo
+
+	//delete clock for gl_destroy
+	//if (x->gl_destroy) clock_free(x->gl_destroy);
 
     canvas_noundo(x);
     if (canvas_editing == x)
diff --git a/src/g_canvas.c.orig b/src/g_canvas.c.orig
new file mode 100644
index 0000000000000000000000000000000000000000..2f032a12d6ef37c4983669f6072f170bfd3dbfeb
--- /dev/null
+++ b/src/g_canvas.c.orig
@@ -0,0 +1,1819 @@
+/* Copyright (c) 1997-2001 Miller Puckette and others.
+* For information on usage and redistribution, and for a DISCLAIMER OF ALL
+* WARRANTIES, see the file, "LICENSE.txt," in this distribution.  */
+
+/* this file defines the "glist" class, also known as "canvas" (the two used
+to be different but are now unified except for some fossilized names.) */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "m_pd.h"
+#include "m_imp.h"
+#include "s_stuff.h"
+#include "g_canvas.h"
+#include <string.h>
+#include "g_all_guis.h"
+#include "g_magicglass.h"
+
+// jsarlo
+typedef struct _magicGlass
+{
+    t_object x_obj;
+    t_object *x_connectedObj;
+    int x_connectedOutno;
+    int x_visible;
+    char x_string[4096];
+    char x_old_string[4096];
+    int x_x;
+    int x_y;
+    int x_c;
+    float x_sigF;
+    int x_dspOn;
+    int x_viewOn;
+    float x_maxSample;
+    int x_sampleCount;
+    t_clock *x_clearClock;
+	t_clock *x_flashClock;
+	unsigned int x_maxSize;
+	unsigned int x_issignal;
+};
+// end jsarlo
+
+    /* LATER consider adding font size to this struct (see glist_getfont()) */
+struct _canvasenvironment
+{
+    t_symbol *ce_dir;      /* directory patch lives in */
+    int ce_argc;           /* number of "$" arguments */
+    t_atom *ce_argv;       /* array of "$" arguments */
+    int ce_dollarzero;     /* value of "$0" */
+    t_namelist *ce_path;   /* search path */
+};
+
+#define GLIST_DEFCANVASWIDTH 450
+#define GLIST_DEFCANVASHEIGHT 300
+
+#ifdef __APPLE__
+#define GLIST_DEFCANVASYLOC 22
+#else
+#define GLIST_DEFCANVASYLOC 0
+#endif
+
+/* ---------------------- variables --------------------------- */
+
+extern t_pd *newest;
+t_class *canvas_class;
+int canvas_dspstate;                /* whether DSP is on or off */  
+t_canvas *canvas_editing;           /* last canvas to start text edting */ 
+t_canvas *canvas_whichfind;         /* last canvas we did a find in */ 
+t_canvas *canvas_list;              /* list of all root canvases */
+
+/* ------------------ forward function declarations --------------- */
+static void canvas_start_dsp(void);
+static void canvas_stop_dsp(void);
+static void canvas_drawlines(t_canvas *x);
+static void canvas_setbounds(t_canvas *x, int x1, int y1, int x2, int y2);
+void canvas_reflecttitle(t_canvas *x);
+static void canvas_addtolist(t_canvas *x);
+static void canvas_takeofflist(t_canvas *x);
+static void canvas_pop(t_canvas *x, t_floatarg fvis);
+
+/* --------- functions to handle the canvas environment ----------- */
+
+static t_symbol *canvas_newfilename = &s_;
+static t_symbol *canvas_newdirectory = &s_;
+static int canvas_newargc;
+static t_atom *canvas_newargv;
+
+static void glist_doupdatewindowlist(t_glist *gl, char *sbuf)
+{
+    t_gobj *g;
+    if (glist_amreloadingabstractions)  /* not if we're in a reload */
+        return;
+    if (!gl->gl_owner)
+    {
+        /* this is a canvas; if we have a window, put on "windows" list */
+        t_canvas *canvas = (t_canvas *)gl;
+        if (canvas->gl_havewindow)
+        {
+            if (strlen(sbuf) + strlen(gl->gl_name->s_name) + 100 <= 1024)
+            {
+                char tbuf[1024];
+                sprintf(tbuf, "{{%s} .x%lx} ", gl->gl_name->s_name,
+                    (t_int)canvas);
+                strcat(sbuf, tbuf);
+            }
+        }
+    }
+    for (g = gl->gl_list; g; g = g->g_next)
+    {
+        if (pd_class(&g->g_pd) == canvas_class)
+            glist_doupdatewindowlist((t_glist *)g, sbuf);
+    }
+    return;
+}
+
+    /* maintain the list of visible toplevels for the GUI's "windows" menu */
+void canvas_updatewindowlist( void)
+{
+    t_canvas *x;
+    char sbuf[1024];
+    strcpy(sbuf, "set menu_windowlist {");
+        /* find all root canvases */
+    for (x = canvas_list; x; x = x->gl_next)
+        glist_doupdatewindowlist(x, sbuf);
+    /* next line updates the window menu state before -postcommand tries it */
+    strcat(sbuf, "}\npdtk_fixwindowmenu\n");
+    sys_gui(sbuf);
+}
+
+    /* add a glist the list of "root" canvases (toplevels without parents.) */
+static void canvas_addtolist(t_canvas *x)
+{
+    x->gl_next = canvas_list;
+    canvas_list = x;
+}
+
+static void canvas_takeofflist(t_canvas *x)
+{
+        /* take it off the window list */
+    if (x == canvas_list) canvas_list = x->gl_next;
+    else
+    {
+        t_canvas *z;
+        for (z = canvas_list; z->gl_next != x; z = z->gl_next)
+            ;
+        z->gl_next = x->gl_next;
+    }
+}
+
+
+void canvas_setargs(int argc, t_atom *argv)
+{
+        /* if there's an old one lying around free it here.  This
+        happens if an abstraction is loaded but never gets as far
+        as calling canvas_new(). */
+    if (canvas_newargv)
+        freebytes(canvas_newargv, canvas_newargc * sizeof(t_atom));
+    canvas_newargc = argc;
+    canvas_newargv = copybytes(argv, argc * sizeof(t_atom));
+}
+
+void glob_setfilename(void *dummy, t_symbol *filesym, t_symbol *dirsym)
+{
+    canvas_newfilename = filesym;
+    canvas_newdirectory = dirsym;
+}
+
+t_canvas *canvas_getcurrent(void)
+{
+    return ((t_canvas *)pd_findbyclass(&s__X, canvas_class));
+}
+
+void canvas_setcurrent(t_canvas *x)
+{
+    pd_pushsym(&x->gl_pd);
+}
+
+void canvas_unsetcurrent(t_canvas *x)
+{
+    pd_popsym(&x->gl_pd);
+}
+
+t_canvasenvironment *canvas_getenv(t_canvas *x)
+{
+    if (!x) bug("canvas_getenv");
+    while (!x->gl_env)
+        if (!(x = x->gl_owner))
+            bug("t_canvasenvironment");
+    return (x->gl_env);
+}
+
+int canvas_getdollarzero( void)
+{
+    t_canvas *x = canvas_getcurrent();
+    t_canvasenvironment *env = (x ? canvas_getenv(x) : 0);
+    if (env)
+        return (env->ce_dollarzero);
+    else return (0);
+}
+
+void canvas_getargs(int *argcp, t_atom **argvp)
+{
+    t_canvasenvironment *e = canvas_getenv(canvas_getcurrent());
+    *argcp = e->ce_argc;
+    *argvp = e->ce_argv;
+}
+
+t_symbol *canvas_realizedollar(t_canvas *x, t_symbol *s)
+{
+    t_symbol *ret;
+    char *name = s->s_name;
+    if (strchr(name, '$'))
+    {
+        t_canvasenvironment *env = canvas_getenv(x);
+        canvas_setcurrent(x);
+        ret = binbuf_realizedollsym(s, env->ce_argc, env->ce_argv, 1);
+        canvas_unsetcurrent(x);
+    }
+    else ret = s;
+    return (ret);
+}
+
+t_symbol *canvas_getcurrentdir(void)
+{
+    t_canvasenvironment *e = canvas_getenv(canvas_getcurrent());
+    return (e->ce_dir);
+}
+
+t_symbol *canvas_getdir(t_canvas *x)
+{
+    t_canvasenvironment *e = canvas_getenv(x);
+    return (e->ce_dir);
+}
+
+void canvas_makefilename(t_canvas *x, char *file, char *result, int resultsize)
+{
+    char *dir = canvas_getenv(x)->ce_dir->s_name;
+    if (file[0] == '/' || (file[0] && file[1] == ':') || !*dir)
+    {
+        strncpy(result, file, resultsize);
+        result[resultsize-1] = 0;
+    }
+    else
+    {
+        int nleft;
+        strncpy(result, dir, resultsize);
+        result[resultsize-1] = 0;
+        nleft = resultsize - strlen(result) - 1;
+        if (nleft <= 0) return;
+        strcat(result, "/");
+        strncat(result, file, nleft);
+        result[resultsize-1] = 0;
+    }           
+}
+
+void canvas_rename(t_canvas *x, t_symbol *s, t_symbol *dir)
+{
+    if (strcmp(x->gl_name->s_name, "Pd"))
+        pd_unbind(&x->gl_pd, canvas_makebindsym(x->gl_name));
+    x->gl_name = s;
+    if (strcmp(x->gl_name->s_name, "Pd"))
+        pd_bind(&x->gl_pd, canvas_makebindsym(x->gl_name));
+    if (glist_isvisible(x))
+        canvas_reflecttitle(x);
+    if (dir && dir != &s_)
+    {
+        t_canvasenvironment *e = canvas_getenv(x);
+        e->ce_dir = dir;
+    }
+}
+
+/* --------------- traversing the set of lines in a canvas ----------- */
+
+int canvas_getindex(t_canvas *x, t_gobj *y)
+{
+    t_gobj *y2;
+    int indexno;
+    for (indexno = 0, y2 = x->gl_list; y2 && y2 != y; y2 = y2->g_next)
+        indexno++;
+    return (indexno);
+}
+
+void linetraverser_start(t_linetraverser *t, t_canvas *x)
+{
+    t->tr_ob = 0;
+    t->tr_x = x;
+    t->tr_nextoc = 0;
+    t->tr_nextoutno = t->tr_nout = 0;
+}
+
+t_outconnect *linetraverser_next(t_linetraverser *t)
+{
+    t_outconnect *rval = t->tr_nextoc;
+    int outno;
+    while (!rval)
+    {
+        outno = t->tr_nextoutno;
+        while (outno == t->tr_nout)
+        {
+            t_gobj *y;
+            t_object *ob = 0;
+            if (!t->tr_ob) y = t->tr_x->gl_list;
+            else y = t->tr_ob->ob_g.g_next;
+            for (; y; y = y->g_next)
+                if (ob = pd_checkobject(&y->g_pd)) break;
+            if (!ob) return (0);
+            t->tr_ob = ob;
+            t->tr_nout = obj_noutlets(ob);
+            outno = 0;
+            if (glist_isvisible(t->tr_x))
+                gobj_getrect(y, t->tr_x,
+                    &t->tr_x11, &t->tr_y11, &t->tr_x12, &t->tr_y12);
+            else t->tr_x11 = t->tr_y11 = t->tr_x12 = t->tr_y12 = 0;
+        }
+        t->tr_nextoutno = outno + 1;
+        rval = obj_starttraverseoutlet(t->tr_ob, &t->tr_outlet, outno);
+        t->tr_outno = outno;
+    }
+    t->tr_nextoc = obj_nexttraverseoutlet(rval, &t->tr_ob2,
+        &t->tr_inlet, &t->tr_inno);
+    t->tr_nin = obj_ninlets(t->tr_ob2);
+    if (!t->tr_nin) bug("drawline");
+    if (glist_isvisible(t->tr_x))
+    {
+        int inplus = (t->tr_nin == 1 ? 1 : t->tr_nin - 1);
+        int outplus = (t->tr_nout == 1 ? 1 : t->tr_nout - 1);
+        gobj_getrect(&t->tr_ob2->ob_g, t->tr_x,
+            &t->tr_x21, &t->tr_y21, &t->tr_x22, &t->tr_y22);
+        t->tr_lx1 = t->tr_x11 +
+            ((t->tr_x12 - t->tr_x11 - IOWIDTH) * t->tr_outno) /
+                outplus + IOMIDDLE;
+        t->tr_ly1 = t->tr_y12;
+        t->tr_lx2 = t->tr_x21 +
+            ((t->tr_x22 - t->tr_x21 - IOWIDTH) * t->tr_inno)/inplus +
+                IOMIDDLE;
+        t->tr_ly2 = t->tr_y21;
+    }
+    else
+    {
+        t->tr_x21 = t->tr_y21 = t->tr_x22 = t->tr_y22 = 0;
+        t->tr_lx1 = t->tr_ly1 = t->tr_lx2 = t->tr_ly2 = 0;
+    }
+    return (rval);
+}
+
+void linetraverser_skipobject(t_linetraverser *t)
+{
+    t->tr_nextoc = 0;
+    t->tr_nextoutno = t->tr_nout;
+}
+
+/* -------------------- the canvas object -------------------------- */
+int glist_valid = 10000;
+
+//static void canvas_manual_pd_free(t_canvas *x) {
+//	sys_flushtogui();
+//	pd_free(&x->gl_pd);
+//}
+
+void glist_init(t_glist *x)
+{
+        /* zero out everyone except "pd" field */
+    memset(((char *)x) + sizeof(x->gl_pd), 0, sizeof(*x) - sizeof(x->gl_pd));
+    x->gl_stub = gstub_new(x, 0);
+    x->gl_valid = ++glist_valid;
+    x->gl_xlabel = (t_symbol **)t_getbytes(0);
+    x->gl_ylabel = (t_symbol **)t_getbytes(0);
+}
+
+    /* make a new glist.  It will either be a "root" canvas or else
+    it appears as a "text" object in another window (canvas_getcurrent() 
+    tells us which.) */
+t_canvas *canvas_new(void *dummy, t_symbol *sel, int argc, t_atom *argv)
+{
+	/*	first alloc one byte or redundant memory to prevent creation of objects with the same "name"
+		which leads to double-action invoked from every single action and eventually possible crashes
+
+		we keep a list of these redundant allocations and destroy them when pd quits */
+	//if (x->gl_owner && x->gl_env) {
+/*
+		t_redundant_mem *new_rm = (t_redundant_mem *)t_getbytes(sizeof(*new_rm));
+		new_rm->rm_what = (int)getbytes(1);
+		if (rm_start == NULL) {
+			//fprintf(stderr,"first allocation\n");
+			rm_start = new_rm;
+			rm_end = new_rm;
+		}
+		else if (rm_start == rm_end) {
+			//fprintf(stderr,"second allocation\n");
+			rm_end = new_rm;
+			rm_start->rm_next = rm_end;
+		}
+		else {
+			//fprintf(stderr,"allocation\n");
+			rm_end->rm_next = new_rm;
+			rm_end = new_rm;
+		}
+*/
+	//}
+
+    t_canvas *x = (t_canvas *)pd_new(canvas_class);
+
+	/* now that we've created a new canvas, add canvas info to the new_rm */
+	//new_rm->rm_canvas = x;
+
+    t_canvas *owner = canvas_getcurrent();
+    t_symbol *s = &s_;
+    int vis = 0, width = GLIST_DEFCANVASWIDTH, height = GLIST_DEFCANVASHEIGHT;
+    int xloc = 0, yloc = GLIST_DEFCANVASYLOC;
+    int font = (owner ? owner->gl_font : sys_defaultfont);
+
+    glist_init(x);
+    // jsarlo
+    x->gl_magic_glass = magicGlass_new((int)x);
+    // end jsarlo
+
+	//if we are root canvas set the clock for script based destructor of the window
+	//if (!owner) {
+	//	x->gl_destroy = clock_new(x, (t_method)canvas_manual_pd_free);
+	//}
+
+    x->gl_obj.te_type = T_OBJECT;
+    if (!owner)
+        canvas_addtolist(x);
+    /* post("canvas %lx, owner %lx", x, owner); */
+
+    if (argc == 5)  /* toplevel: x, y, w, h, font */
+    {
+        xloc = atom_getintarg(0, argc, argv);
+        yloc = atom_getintarg(1, argc, argv);
+        width = atom_getintarg(2, argc, argv);
+        height = atom_getintarg(3, argc, argv);
+        font = atom_getintarg(4, argc, argv);
+    }
+    else if (argc == 6)  /* subwindow: x, y, w, h, name, vis */
+    {
+        xloc = atom_getintarg(0, argc, argv);
+        yloc = atom_getintarg(1, argc, argv);
+        width = atom_getintarg(2, argc, argv);
+        height = atom_getintarg(3, argc, argv);
+        s = atom_getsymbolarg(4, argc, argv);
+        vis = atom_getintarg(5, argc, argv);
+    }
+        /* (otherwise assume we're being created from the menu.) */
+
+    if (canvas_newdirectory->s_name[0])
+    {
+        static int dollarzero = 1000;
+        t_canvasenvironment *env = x->gl_env =
+            (t_canvasenvironment *)getbytes(sizeof(*x->gl_env));
+        if (!canvas_newargv)
+            canvas_newargv = getbytes(0);
+        env->ce_dir = canvas_newdirectory;
+        env->ce_argc = canvas_newargc;
+        env->ce_argv = canvas_newargv;
+        env->ce_dollarzero = dollarzero++;
+        env->ce_path = 0;
+        canvas_newdirectory = &s_;
+        canvas_newargc = 0;
+        canvas_newargv = 0;
+    }
+    else x->gl_env = 0;
+
+    if (yloc < GLIST_DEFCANVASYLOC)
+        yloc = GLIST_DEFCANVASYLOC;
+    if (xloc < 0)
+        xloc = 0;
+    x->gl_x1 = 0;
+    x->gl_y1 = 0;
+    x->gl_x2 = 1;
+    x->gl_y2 = 1;
+    canvas_setbounds(x, xloc, yloc, xloc + width, yloc + height);
+    x->gl_owner = owner;
+    x->gl_name = (*s->s_name ? s : 
+        (canvas_newfilename ? canvas_newfilename : gensym("Pd")));
+    if (strcmp(x->gl_name->s_name, "Pd"))
+        pd_bind(&x->gl_pd, canvas_makebindsym(x->gl_name));
+    x->gl_loading = 1;
+	//fprintf(stderr,"loading = 1 .x%lx owner=.x%lx\n", x, x->gl_owner);
+    x->gl_goprect = 0;      /* no GOP rectangle unless it's turned on later */
+        /* cancel "vis" flag if we're a subpatch of an
+         abstraction inside another patch.  A separate mechanism prevents
+         the toplevel abstraction from showing up. */
+    if (vis && gensym("#X")->s_thing && 
+        ((*gensym("#X")->s_thing) == canvas_class))
+    {
+        t_canvas *zzz = (t_canvas *)(gensym("#X")->s_thing);
+        while (zzz && !zzz->gl_env)
+            zzz = zzz->gl_owner;
+        if (zzz && canvas_isabstraction(zzz) && zzz->gl_owner)
+            vis = 0;
+    }
+    x->gl_willvis = vis;
+    x->gl_edit = !strncmp(x->gl_name->s_name, "Untitled", 8);
+    x->gl_font = sys_nearestfontsize(font);
+    pd_pushsym(&x->gl_pd);
+
+    return(x);
+}
+
+void canvas_setgraph(t_glist *x, int flag, int nogoprect);
+
+static void canvas_coords(t_glist *x, t_symbol *s, int argc, t_atom *argv)
+{
+    x->gl_x1 = atom_getfloatarg(0, argc, argv);
+    x->gl_y1 = atom_getfloatarg(1, argc, argv);
+    x->gl_x2 = atom_getfloatarg(2, argc, argv);
+    x->gl_y2 = atom_getfloatarg(3, argc, argv);
+    x->gl_pixwidth = atom_getintarg(4, argc, argv);
+    x->gl_pixheight = atom_getintarg(5, argc, argv);
+    if (argc <= 7)
+        canvas_setgraph(x, atom_getintarg(6, argc, argv), 1);
+    else
+    {
+        x->gl_xmargin = atom_getintarg(7, argc, argv);
+        x->gl_ymargin = atom_getintarg(8, argc, argv);
+        canvas_setgraph(x, atom_getintarg(6, argc, argv), 0);
+    }
+}
+
+    /* make a new glist and add it to this glist.  It will appear as
+    a "graph", not a text object.  */
+t_glist *glist_addglist(t_glist *g, t_symbol *sym,
+    t_float x1, t_float y1, t_float x2, t_float y2,
+    t_float px1, t_float py1, t_float px2, t_float py2)
+{
+    static int gcount = 0;
+    int zz;
+    int menu = 0;
+    char *str;
+    t_glist *x = (t_glist *)pd_new(canvas_class);
+    glist_init(x);
+    x->gl_obj.te_type = T_OBJECT;
+    if (!*sym->s_name)
+    {
+        char buf[40];
+        sprintf(buf, "graph%d", ++gcount);
+        sym = gensym(buf);
+        menu = 1;
+    }
+    else if (!strncmp((str = sym->s_name), "graph", 5)
+        && (zz = atoi(str + 5)) > gcount)
+            gcount = zz;
+        /* in 0.34 and earlier, the pixel rectangle and the y bounds were
+        reversed; this would behave the same, except that the dialog window
+        would be confusing.  The "correct" way is to have "py1" be the value
+        that is higher on the screen. */
+    if (py2 < py1)
+    {
+        t_float zz;
+        zz = y2;
+        y2 = y1;
+        y1 = zz;
+        zz = py2;
+        py2 = py1;
+        py1 = zz;
+    }
+    if (x1 == x2 || y1 == y2)
+        x1 = 0, x2 = 100, y1 = 1, y2 = -1;
+	if (px1 != 0 && px2 == 0) px2 = px1 + GLIST_DEFGRAPHWIDTH;
+	if (py1 != 0 && py2 == py1) py2 = py1 + GLIST_DEFGRAPHHEIGHT;
+    if (px1 >= px2 || py1 >= py2)
+        px1 = 100, py1 = 20, px2 = 100 + GLIST_DEFGRAPHWIDTH,
+            py2 = 20 + GLIST_DEFGRAPHHEIGHT;
+
+    x->gl_name = sym;
+    x->gl_x1 = x1;
+    x->gl_x2 = x2;
+    x->gl_y1 = y1;
+    x->gl_y2 = y2;
+    x->gl_obj.te_xpix = px1;
+    x->gl_obj.te_ypix = py1;
+    x->gl_pixwidth = px2 - px1;
+    x->gl_pixheight = py2 - py1;
+    x->gl_font =  (canvas_getcurrent() ?
+        canvas_getcurrent()->gl_font : sys_defaultfont);
+    x->gl_screenx1 = x->gl_screeny1 = 0;
+    x->gl_screenx2 = 450;
+    x->gl_screeny2 = 300;
+    if (strcmp(x->gl_name->s_name, "Pd"))
+        pd_bind(&x->gl_pd, canvas_makebindsym(x->gl_name));
+    x->gl_owner = g;
+    x->gl_isgraph = 1;
+    x->gl_goprect = 0;
+    x->gl_obj.te_binbuf = binbuf_new();
+    binbuf_addv(x->gl_obj.te_binbuf, "s", gensym("graph"));
+    if (!menu)
+        pd_pushsym(&x->gl_pd);
+    glist_add(g, &x->gl_gobj);
+	sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", (long unsigned int)glist_getcanvas(g));
+    return (x);
+}
+
+    /* call glist_addglist from a Pd message */
+void glist_glist(t_glist *g, t_symbol *s, int argc, t_atom *argv)
+{
+	pd_vmess(&g->gl_pd, gensym("editmode"), "i", 1);
+    t_symbol *sym = atom_getsymbolarg(0, argc, argv);
+	/* if we wish to put a graph where the mouse is we need to replace bogus name */
+	if (!strcmp(sym->s_name, "NULL")) sym = &s_;  
+    t_float x1 = atom_getfloatarg(1, argc, argv);  
+    t_float y1 = atom_getfloatarg(2, argc, argv);  
+    t_float x2 = atom_getfloatarg(3, argc, argv);  
+    t_float y2 = atom_getfloatarg(4, argc, argv);  
+    t_float px1 = atom_getfloatarg(5, argc, argv);  
+    t_float py1 = atom_getfloatarg(6, argc, argv);  
+    t_float px2 = atom_getfloatarg(7, argc, argv);  
+    t_float py2 = atom_getfloatarg(8, argc, argv);
+    glist_addglist(g, sym, x1, y1, x2, y2, px1, py1, px2, py2);
+}
+
+    /* return true if the glist should appear as a graph on parent;
+    otherwise it appears as a text box. */
+int glist_isgraph(t_glist *x)
+{
+  return (x->gl_isgraph|(x->gl_hidetext<<1));
+}
+
+    /* This is sent from the GUI to inform a toplevel that its window has been
+    moved or resized. */
+static void canvas_setbounds(t_canvas *x, int x1, int y1, int x2, int y2)
+{
+    int heightwas = y2 - y1;
+    int heightchange = y2 - y1 - (x->gl_screeny2 - x->gl_screeny1);
+    if (x->gl_screenx1 == x1 && x->gl_screeny1 == y1 &&
+        x->gl_screenx2 == x2 && x->gl_screeny2 == y2)
+            return;
+    x->gl_screenx1 = x1;
+    x->gl_screeny1 = y1;
+    x->gl_screenx2 = x2;
+    x->gl_screeny2 = y2;
+    if (!glist_isgraph(x) && (x->gl_y2 < x->gl_y1)) 
+    {
+            /* if it's flipped so that y grows upward,
+            fix so that zero is bottom edge and redraw.  This is
+            only appropriate if we're a regular "text" object on the
+            parent. */
+        t_float diff = x->gl_y1 - x->gl_y2;
+        t_gobj *y;
+        x->gl_y1 = heightwas * diff;
+        x->gl_y2 = x->gl_y1 - diff;
+            /* and move text objects accordingly; they should stick
+            to the bottom, not the top. */
+        for (y = x->gl_list; y; y = y->g_next)
+            if (pd_checkobject(&y->g_pd))
+                gobj_displace(y, x, 0, heightchange);
+        canvas_redraw(x);
+    }
+}
+
+t_symbol *canvas_makebindsym(t_symbol *s)
+{
+    char buf[MAXPDSTRING];
+    strcpy(buf, "pd-");
+    strcat(buf, s->s_name);
+    return (gensym(buf));
+}
+
+void canvas_reflecttitle(t_canvas *x)
+{
+	//fprintf(stderr,"canvas_reflecttitle\n");
+    char namebuf[MAXPDSTRING];
+    t_canvasenvironment *env = canvas_getenv(x);
+    if (env->ce_argc)
+    {
+        int i;
+        strcpy(namebuf, " (");
+        for (i = 0; i < env->ce_argc; i++)
+        {
+            if (strlen(namebuf) > MAXPDSTRING/2 - 5)
+                break;
+            if (i != 0)
+                strcat(namebuf, " ");
+            atom_string(&env->ce_argv[i], namebuf + strlen(namebuf), 
+                MAXPDSTRING/2);
+        }
+        strcat(namebuf, ")");
+    }
+    else namebuf[0] = 0;
+#ifdef __APPLE__
+    sys_vgui("wm attributes .x%lx -modified %d -titlepath {%s/%s}\n",
+        x, x->gl_dirty, canvas_getdir(x)->s_name, x->gl_name->s_name);
+    sys_vgui("wm title .x%lx {%s%s}\n", x, x->gl_name->s_name, namebuf);
+#else
+	if(glist_istoplevel(x) || !x->gl_isgraph || x->gl_isgraph && x->gl_havewindow || x->gl_loading || x->gl_dirty) {
+		/*fprintf(stderr,"%d %d %d %d %d\n", glist_istoplevel(x), !x->gl_isgraph,
+			x->gl_isgraph && x->gl_havewindow, x->gl_loading,
+			x->gl_dirty);*/
+	    sys_vgui("wm title .x%lx {%s%c%s - %s}\n", 
+	        x, x->gl_name->s_name, (x->gl_dirty? '*' : ' '), namebuf,
+            canvas_getdir(x)->s_name);
+	}
+#endif
+}
+
+    /* mark a glist dirty or clean */
+void canvas_dirty(t_canvas *x, t_floatarg n)
+{
+    t_canvas *x2 = canvas_getrootfor(x);
+    if (glist_amreloadingabstractions)
+        return;
+    if ((unsigned)n != x2->gl_dirty)
+    {
+        x2->gl_dirty = n;
+        if (glist_isvisible(x2))
+            canvas_reflecttitle(x2);
+    }
+}
+
+void canvas_drawredrect(t_canvas *x, int doit)
+{
+    if (doit)
+        sys_vgui(".x%lx.c create line\
+            %d %d %d %d %d %d %d %d %d %d -fill #ff8080 -tags GOP\n",
+            glist_getcanvas(x),
+            x->gl_xmargin, x->gl_ymargin,
+            x->gl_xmargin + x->gl_pixwidth, x->gl_ymargin,
+            x->gl_xmargin + x->gl_pixwidth, x->gl_ymargin + x->gl_pixheight,
+            x->gl_xmargin, x->gl_ymargin + x->gl_pixheight,
+            x->gl_xmargin, x->gl_ymargin);
+    else sys_vgui(".x%lx.c delete GOP\n",  glist_getcanvas(x));
+}
+
+    /* the window becomes "mapped" (visible and not miniaturized) or
+    "unmapped" (either miniaturized or just plain gone.)  This should be
+    called from the GUI after the fact to "notify" us that we're mapped. */
+void canvas_map(t_canvas *x, t_floatarg f)
+{
+	//fprintf(stderr,"canvas_map\n");
+    int flag = (f != 0);
+    t_gobj *y;
+    if (flag)
+    {
+        if (!glist_isvisible(x))
+        {
+            t_selection *sel;
+            if (!x->gl_havewindow)
+            {
+                bug("canvas_map");
+                canvas_vis(x, 1);
+            }
+
+			/* 	if parent has editor enabled and we're a sub-patch,
+				(but not an abstraction) match its edit mode to that
+				of its parent patch. */
+			/*t_glist *parentx;
+			if (!canvas_isabstraction(x)) {
+				if (x->gl_owner) {
+					parentx = x->gl_owner;
+					while (parentx->gl_owner)
+						parentx = parentx->gl_owner;
+					if (parentx->gl_edit)
+						canvas_editmode(x, 1);
+					else if (x->gl_edit)
+						canvas_editmode(x, 0);
+				}
+			}*/
+			/*	for parent windows, let's make sure the cursor is updated
+				as soon as the window is open (if in edit mode) */
+			//else if (x->gl_edit) {
+				//canvas_setcursor(x, CURSOR_EDITMODE_NOTHING);
+			//}
+
+            for (y = x->gl_list; y; y = y->g_next)
+                gobj_vis(y, x, 1);
+            for (sel = x->gl_editor->e_selection; sel; sel = sel->sel_next)
+                gobj_select(sel->sel_what, x, 1);
+            x->gl_mapped = 1;
+            canvas_drawlines(x);
+            if (x->gl_isgraph && x->gl_goprect)
+                canvas_drawredrect(x, 1);
+            sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", x);
+        }
+    }
+    else
+    {
+        if (glist_isvisible(x))
+        {
+                /* just clear out the whole canvas */
+			sys_vgui(".x%lx.c dtag all selected\n", x);
+            sys_vgui(".x%lx.c delete all\n", x);
+            x->gl_mapped = 0;
+        }
+    }
+}
+
+void canvas_redraw(t_canvas *x)
+{
+    if (glist_isvisible(x))
+    {
+        canvas_map(x, 0);
+        canvas_map(x, 1);
+		
+		/* now re-highlight our selection */
+	    t_selection *y;
+    	for (y = x->gl_editor->e_selection; y; y = y->sel_next)		
+			gobj_select(y->sel_what, x, 1);
+    }
+}
+
+
+    /* we call this on a non-toplevel glist to "open" it into its
+    own window. */
+void glist_menu_open(t_glist *x)
+{
+    if (glist_isvisible(x) && !glist_istoplevel(x))
+    {
+        t_glist *gl2 = x->gl_owner;
+        if (!gl2) 
+            bug("glist_menu_open");  /* shouldn't happen but not dangerous */
+        else
+        {
+                /* erase ourself in parent window */
+            gobj_vis(&x->gl_gobj, gl2, 0);
+                    /* get rid of our editor (and subeditors) */
+            if (x->gl_editor)
+                canvas_destroy_editor(x);
+            x->gl_havewindow = 1;
+                    /* redraw ourself in parent window (blanked out this time) */
+            gobj_vis(&x->gl_gobj, gl2, 1);
+        }
+    }
+    canvas_vis(x, 1);
+}
+
+int glist_isvisible(t_glist *x)
+{
+    return ((!x->gl_loading) && glist_getcanvas(x)->gl_mapped);
+}
+
+int glist_istoplevel(t_glist *x)
+{
+        /* we consider a graph "toplevel" if it has its own window
+        or if it appears as a box in its parent window so that we
+        don't draw the actual contents there. */
+    return (x->gl_havewindow || !x->gl_isgraph);
+}
+
+int glist_getfont(t_glist *x)
+{
+    while (!x->gl_env)
+        if (!(x = x->gl_owner))
+            bug("t_canvasenvironment");
+    return (x->gl_font);
+}
+
+void canvas_free(t_canvas *x)
+{
+    t_gobj *y;
+    int dspstate = canvas_suspend_dsp();
+    // jsarlo
+    if (x->gl_magic_glass)
+      magicGlass_free(x->gl_magic_glass);
+    // end jsarlo
+
+	//delete clock for gl_destroy
+	//if (x->gl_destroy) clock_free(x->gl_destroy);
+
+    canvas_noundo(x);
+    if (canvas_editing == x)
+        canvas_editing = 0;
+    if (canvas_whichfind == x)
+        canvas_whichfind = 0;
+    glist_noselect(x);
+    while (y = x->gl_list)
+        glist_delete(x, y);
+    if (x == glist_getcanvas(x))
+        canvas_vis(x, 0);
+
+    if (strcmp(x->gl_name->s_name, "Pd"))
+        pd_unbind(&x->gl_pd, canvas_makebindsym(x->gl_name));
+    if (x->gl_env)
+    {
+        freebytes(x->gl_env->ce_argv, x->gl_env->ce_argc * sizeof(t_atom));
+        freebytes(x->gl_env, sizeof(*x->gl_env));
+    }
+    canvas_resume_dsp(dspstate);
+    glist_cleanup(x);
+    gfxstub_deleteforkey(x);        /* probably unnecessary */
+    if (!x->gl_owner)
+        canvas_takeofflist(x);
+}
+
+/* ----------------- lines ---------- */
+
+static void canvas_drawlines(t_canvas *x)
+{
+    t_linetraverser t;
+    t_outconnect *oc;
+    int issignal;
+    
+        linetraverser_start(&t, x);
+        while (oc = linetraverser_next(&t))
+    {
+        issignal = (outlet_getsymbol(t.tr_outlet) == &s_signal ? 1 : 0);
+        sys_vgui(".x%lx.c create line %d %d %d %d -width %d -fill %s \
+-tags {l%lx all_cords}\n",
+                 glist_getcanvas(x), t.tr_lx1, t.tr_ly1, t.tr_lx2, t.tr_ly2, 
+                 (issignal ? 2:1), (issignal ? "$signal_cord" : "$msg_cord"),
+                 oc);
+    }
+}
+
+void canvas_fixlinesfor(t_canvas *x, t_text *text)
+{
+    t_linetraverser t;
+    t_outconnect *oc;
+
+    linetraverser_start(&t, x);
+    while (oc = linetraverser_next(&t))
+    {
+        if (t.tr_ob == text || t.tr_ob2 == text)
+        {
+            sys_vgui(".x%lx.c coords l%lx %d %d %d %d\n",
+                glist_getcanvas(x), oc,
+                    t.tr_lx1, t.tr_ly1, t.tr_lx2, t.tr_ly2);
+        }
+    }
+}
+
+    /* kill all lines for the object */
+void canvas_deletelinesfor(t_canvas *x, t_text *text)
+{
+    t_linetraverser t;
+    t_outconnect *oc;
+    linetraverser_start(&t, x);
+    while (oc = linetraverser_next(&t))
+    {
+        if (t.tr_ob == text || t.tr_ob2 == text)
+        {
+            if (x->gl_editor)
+            {
+                sys_vgui(".x%lx.c delete l%lx\n",
+                    glist_getcanvas(x), oc);
+            }
+            obj_disconnect(t.tr_ob, t.tr_outno, t.tr_ob2, t.tr_inno);
+        }
+    }
+}
+
+    /* 	delete all lines for the object 
+		for efficient redrawing of connections */
+void canvas_eraselinesfor(t_canvas *x, t_text *text)
+{
+    t_linetraverser t;
+    t_outconnect *oc;
+    linetraverser_start(&t, x);
+    while (oc = linetraverser_next(&t))
+    {
+        if (t.tr_ob == text || t.tr_ob2 == text)
+        {
+            if (x->gl_editor)
+            {
+                sys_vgui(".x%lx.c delete l%lx\n",
+                    glist_getcanvas(x), oc);
+            }
+        }
+    }
+}
+
+
+    /* kill all lines for one inlet or outlet */
+void canvas_deletelinesforio(t_canvas *x, t_text *text,
+    t_inlet *inp, t_outlet *outp)
+{
+    t_linetraverser t;
+    t_outconnect *oc;
+    linetraverser_start(&t, x);
+    while (oc = linetraverser_next(&t))
+    {
+        if ((t.tr_ob == text && t.tr_outlet == outp) ||
+            (t.tr_ob2 == text && t.tr_inlet == inp))
+        {
+            if (x->gl_editor)
+            {
+                sys_vgui(".x%lx.c delete l%lx\n",
+                    glist_getcanvas(x), oc);
+            }
+            obj_disconnect(t.tr_ob, t.tr_outno, t.tr_ob2, t.tr_inno);
+        }
+    }
+}
+
+static void canvas_pop(t_canvas *x, t_floatarg fvis)
+{
+    if (fvis != 0)
+        canvas_vis(x, 1);
+    pd_popsym(&x->gl_pd);
+    canvas_resortinlets(x);
+    canvas_resortoutlets(x);
+    x->gl_loading = 0;
+	//fprintf(stderr,"loading = 0 .x%lx owner=.x%lx\n", x, x->gl_owner);
+}
+
+void canvas_objfor(t_glist *gl, t_text *x, int argc, t_atom *argv);
+
+
+void canvas_restore(t_canvas *x, t_symbol *s, int argc, t_atom *argv)
+{
+    t_pd *z;
+    if (argc > 3)
+    {
+        t_atom *ap=argv+3;
+        if (ap->a_type == A_SYMBOL)
+        {
+            t_canvasenvironment *e = canvas_getenv(canvas_getcurrent());
+            canvas_rename(x, binbuf_realizedollsym(ap->a_w.w_symbol,
+                e->ce_argc, e->ce_argv, 1), 0);
+        }
+    }
+    canvas_pop(x, x->gl_willvis);
+
+    if (!(z = gensym("#X")->s_thing)) error("canvas_restore: out of context");
+    else if (*z != canvas_class) error("canvas_restore: wasn't a canvas");
+    else
+    {
+        t_canvas *x2 = (t_canvas *)z;
+        x->gl_owner = x2;
+        canvas_objfor(x2, &x->gl_obj, argc, argv);
+    }
+}
+
+static void canvas_loadbangabstractions(t_canvas *x)
+{
+    t_gobj *y;
+    t_symbol *s = gensym("loadbang");
+    for (y = x->gl_list; y; y = y->g_next)
+        if (pd_class(&y->g_pd) == canvas_class)
+    {
+        if (canvas_isabstraction((t_canvas *)y))
+            canvas_loadbang((t_canvas *)y);
+        else
+            canvas_loadbangabstractions((t_canvas *)y);
+    }
+}
+
+void canvas_loadbangsubpatches(t_canvas *x)
+{
+    t_gobj *y;
+    t_symbol *s = gensym("loadbang");
+    for (y = x->gl_list; y; y = y->g_next)
+        if (pd_class(&y->g_pd) == canvas_class)
+    {
+        if (!canvas_isabstraction((t_canvas *)y))
+            canvas_loadbangsubpatches((t_canvas *)y);
+    }
+    for (y = x->gl_list; y; y = y->g_next)
+        if ((pd_class(&y->g_pd) != canvas_class) &&
+            zgetfn(&y->g_pd, s))
+                pd_vmess(&y->g_pd, s, "");
+}
+
+void canvas_loadbang(t_canvas *x)
+{
+    t_gobj *y;
+    canvas_loadbangabstractions(x);
+    canvas_loadbangsubpatches(x);
+}
+/* JMZ:
+ * initbang is emitted after the canvas is done, but before the parent canvas is done
+ * therefore, initbangs cannot reach to the outlets
+ */
+void canvas_initbang(t_canvas *x)
+{
+    t_gobj *y;
+    t_symbol *s = gensym("initbang");
+    /* run "initbang" for all subpatches, but NOT for the child abstractions */
+    for (y = x->gl_list; y; y = y->g_next)
+      if (pd_class(&y->g_pd) == canvas_class)
+        {
+          if (!canvas_isabstraction((t_canvas *)y))
+            canvas_initbang((t_canvas *)y);
+        }
+
+    /* call the initbang()-method for objects that have one */
+    for (y = x->gl_list; y; y = y->g_next)
+      {
+        if ((pd_class(&y->g_pd) != canvas_class) && zgetfn(&y->g_pd, s))
+          {
+            pd_vmess(&y->g_pd, s, "");
+          }
+      }
+}
+/* JMZ:
+ * closebang is emitted before the canvas is destroyed
+ * and BEFORE subpatches/abstractions in this canvas are destroyed
+ */
+void canvas_closebang(t_canvas *x)
+{
+    t_gobj *y;
+    t_symbol *s = gensym("closebang");
+
+    /* call the closebang()-method for objects that have one 
+     * but NOT for subpatches/abstractions: these are called separately
+     * from g_graph:glist_delete()
+     */
+    for (y = x->gl_list; y; y = y->g_next)
+      {
+        if ((pd_class(&y->g_pd) != canvas_class) && zgetfn(&y->g_pd, s))
+          {
+            pd_vmess(&y->g_pd, s, "");
+          }
+      }
+}
+
+/* needed for readjustment of garrays */
+extern t_array *garray_getarray(t_garray *x);
+extern void garray_fittograph(t_garray *x, int n);
+extern t_rtext *glist_findrtext(t_glist *gl, t_text *who);
+extern void rtext_gettext(t_rtext *x, char **buf, int *bufsize);
+
+static void canvas_relocate(t_canvas *x, t_symbol *canvasgeom,
+    t_symbol *topgeom)
+{
+    int cxpix, cypix, cw, ch, txpix, typix, tw, th;
+    if (sscanf(canvasgeom->s_name, "%dx%d+%d+%d", &cw, &ch, &cxpix, &cypix)
+        < 4 ||
+        sscanf(topgeom->s_name, "%dx%d+%d+%d", &tw, &th, &txpix, &typix) < 4)
+        bug("canvas_relocate");
+            /* for some reason this is initially called with cw=ch=1 so
+            we just suppress that here. */
+    if (cw > 5 && ch > 5)
+        canvas_setbounds(x, txpix, typix,
+            txpix + cw, typix + ch);
+	/* readjust garrays (if any) */
+	t_gobj *g, *gg = NULL;
+	t_garray *ga = NULL;
+	t_array *a = NULL;
+	int  num_elem = 0;
+
+	for (g = x->gl_list; g; g = g->g_next) {
+		//fprintf(stderr, "searching\n");
+
+		//for subpatch garrays
+		if (pd_class(&g->g_pd) == garray_class) {
+			//fprintf(stderr,"found ya\n");
+			ga = (t_garray *)g;
+			if (ga) {
+				a = garray_getarray(ga);
+				num_elem = a->a_n;
+				garray_fittograph(ga, num_elem);
+			}
+		}
+	}
+}
+
+void canvas_popabstraction(t_canvas *x)
+{
+    newest = &x->gl_pd;
+    pd_popsym(&x->gl_pd);
+    //x->gl_loading = 1;
+	//fprintf(stderr,"loading = 1 .x%lx owner=.x%lx\n", x, x->gl_owner);
+    canvas_resortinlets(x);
+    canvas_resortoutlets(x);
+    x->gl_loading = 0;
+	//fprintf(stderr,"loading = 0 .x%lx owner=.x%lx\n", x, x->gl_owner);
+}
+
+void canvas_logerror(t_object *y)
+{
+#ifdef LATER
+    canvas_vis(x, 1);
+    if (!glist_isselected(x, &y->ob_g))
+        glist_select(x, &y->ob_g);
+#endif
+}
+
+/* -------------------------- subcanvases ---------------------- */
+
+static void *subcanvas_new(t_symbol *s)
+{
+    t_atom a[6];
+    t_canvas *x, *z = canvas_getcurrent();
+    if (!*s->s_name) s = gensym("/SUBPATCH/");
+    SETFLOAT(a, 0);
+    SETFLOAT(a+1, GLIST_DEFCANVASYLOC);
+    SETFLOAT(a+2, GLIST_DEFCANVASWIDTH);
+    SETFLOAT(a+3, GLIST_DEFCANVASHEIGHT);
+    SETSYMBOL(a+4, s);
+    SETFLOAT(a+5, 1);
+    x = canvas_new(0, 0, 6, a);
+    x->gl_owner = z;
+    canvas_pop(x, 1);
+    return (x);
+}
+
+static void canvas_click(t_canvas *x,
+    t_floatarg xpos, t_floatarg ypos,
+        t_floatarg shift, t_floatarg ctrl, t_floatarg alt)
+{
+    canvas_vis(x, 1);
+}
+
+
+    /* find out from subcanvas contents how much to fatten the box */
+void canvas_fattensub(t_canvas *x,
+    int *xp1, int *yp1, int *xp2, int *yp2)
+{
+    t_gobj *y;
+    *xp2 += 50;     /* fake for now */
+    *yp2 += 50;
+}
+
+static void canvas_rename_method(t_canvas *x, t_symbol *s, int ac, t_atom *av)
+{
+    if (ac && av->a_type == A_SYMBOL)
+        canvas_rename(x, av->a_w.w_symbol, 0);
+    else if (ac && av->a_type == A_DOLLSYM)
+    {
+        t_canvasenvironment *e = canvas_getenv(x);
+        canvas_setcurrent(x);
+        canvas_rename(x, binbuf_realizedollsym(av->a_w.w_symbol,
+            e->ce_argc, e->ce_argv, 1), 0); 
+        canvas_unsetcurrent(x);
+    }
+    else canvas_rename(x, gensym("Pd"), 0);
+}
+
+/* ------------------ table ---------------------------*/
+
+static int tabcount = 0;
+
+static void *table_new(t_symbol *s, t_floatarg f)
+{
+    t_atom a[9];
+    t_glist *gl;
+    t_canvas *x, *z = canvas_getcurrent();
+    if (s == &s_)
+    {
+         char  tabname[255];
+         t_symbol *t = gensym("table"); 
+         sprintf(tabname, "%s%d", t->s_name, tabcount++);
+         s = gensym(tabname); 
+    }
+    if (f <= 1)
+        f = 100;
+    SETFLOAT(a, 0);
+    SETFLOAT(a+1, GLIST_DEFCANVASYLOC);
+    SETFLOAT(a+2, 600);
+    SETFLOAT(a+3, 400);
+    SETSYMBOL(a+4, s);
+    SETFLOAT(a+5, 0);
+    x = canvas_new(0, 0, 6, a);
+
+    x->gl_owner = z;
+
+        /* create a graph for the table */
+    gl = glist_addglist((t_glist*)x, &s_, 0, -1, (f > 1 ? f-1 : 1), 1,
+        50, 350, 550, 50);
+
+    graph_array(gl, s, &s_float, f, 0);
+
+    canvas_pop(x, 0); 
+
+    return (x);
+}
+
+    /* return true if the "canvas" object is an abstraction (so we don't
+    save its contents, fogr example.)  */
+int canvas_isabstraction(t_canvas *x)
+{
+    return (x->gl_env != 0);
+}
+
+    /* return true if the "canvas" object is a "table". */
+int canvas_istable(t_canvas *x)
+{
+    t_atom *argv = (x->gl_obj.te_binbuf? binbuf_getvec(x->gl_obj.te_binbuf):0);
+    int argc = (x->gl_obj.te_binbuf? binbuf_getnatom(x->gl_obj.te_binbuf) : 0);
+    int istable = (argc && argv[0].a_type == A_SYMBOL &&
+        argv[0].a_w.w_symbol == gensym("table"));
+    return (istable);
+}
+
+    /* return true if the "canvas" object should be treated as a text
+    object.  This is true for abstractions but also for "table"s... */
+/* JMZ: add a flag to gop-abstractions to hide the title */
+int canvas_showtext(t_canvas *x)
+{
+    t_atom *argv = (x->gl_obj.te_binbuf? binbuf_getvec(x->gl_obj.te_binbuf):0);
+    int argc = (x->gl_obj.te_binbuf? binbuf_getnatom(x->gl_obj.te_binbuf) : 0);
+    int isarray = (argc && argv[0].a_type == A_SYMBOL &&
+        argv[0].a_w.w_symbol == gensym("graph"));
+    if(x->gl_hidetext)
+      return 0;
+    else
+      return (!isarray);
+}
+
+    /* get the document containing this canvas */
+t_canvas *canvas_getrootfor(t_canvas *x)
+{
+    if ((!x->gl_owner) || canvas_isabstraction(x))
+        return (x);
+    else return (canvas_getrootfor(x->gl_owner));
+}
+
+/* ------------------------- DSP chain handling ------------------------- */
+
+EXTERN_STRUCT _dspcontext;
+#define t_dspcontext struct _dspcontext
+
+void ugen_start(void);
+void ugen_stop(void);
+
+t_dspcontext *ugen_start_graph(int toplevel, t_signal **sp,
+    int ninlets, int noutlets);
+void ugen_add(t_dspcontext *dc, t_object *x);
+void ugen_connect(t_dspcontext *dc, t_object *x1, int outno,
+    t_object *x2, int inno);
+void ugen_done_graph(t_dspcontext *dc);
+
+    /* schedule one canvas for DSP.  This is called below for all "root"
+    canvases, but is also called from the "dsp" method for sub-
+    canvases, which are treated almost like any other tilde object.  */
+
+static void canvas_dodsp(t_canvas *x, int toplevel, t_signal **sp)
+{
+    t_linetraverser t;
+    t_outconnect *oc;
+    t_gobj *y;
+    t_object *ob;
+    t_symbol *dspsym = gensym("dsp");
+    t_dspcontext *dc;    
+
+        /* create a new "DSP graph" object to use in sorting this canvas.
+        If we aren't toplevel, there are already other dspcontexts around. */
+
+    dc = ugen_start_graph(toplevel, sp,
+        obj_nsiginlets(&x->gl_obj),
+        obj_nsigoutlets(&x->gl_obj));
+
+        /* find all the "dsp" boxes and add them to the graph */
+
+    ob = &x->gl_magic_glass->x_obj;
+    if (ob && x->gl_magic_glass->x_connectedObj) {
+		//fprintf(stderr,"adding cord inspector to dsp\n");
+		ugen_add(dc, ob);  // this t_canvas could be an array, hence no gl_magic_glass
+	}
+    
+    for (y = x->gl_list; y; y = y->g_next)
+        if ((ob = pd_checkobject(&y->g_pd)) && zgetfn(&y->g_pd, dspsym))
+            ugen_add(dc, ob);
+
+        /* ... and all dsp interconnections */
+    linetraverser_start(&t, x);
+    while (oc = linetraverser_next(&t))
+        if (obj_issignaloutlet(t.tr_ob, t.tr_outno))
+            ugen_connect(dc, t.tr_ob, t.tr_outno, t.tr_ob2, t.tr_inno);
+
+        /* finally, sort them and add them to the DSP chain */
+    ugen_done_graph(dc);
+}
+
+static void canvas_dsp(t_canvas *x, t_signal **sp)
+{
+    canvas_dodsp(x, 0, sp);
+}
+
+    /* this routine starts DSP for all root canvases. */
+static void canvas_start_dsp(void)
+{
+    t_canvas *x;
+    if (canvas_dspstate) ugen_stop();
+    else sys_gui("pdtk_pd_dsp ON\n");
+    ugen_start();
+    
+    for (x = canvas_list; x; x = x->gl_next)
+        canvas_dodsp(x, 1, 0);
+    
+    canvas_dspstate = 1;
+}
+
+static void canvas_stop_dsp(void)
+{
+    if (canvas_dspstate)
+    {
+        ugen_stop();
+        sys_gui("pdtk_pd_dsp OFF\n");
+        canvas_dspstate = 0;
+    }
+}
+
+    /* DSP can be suspended before, and resumed after, operations which
+    might affect the DSP chain.  For example, we suspend before loading and
+    resume afterward, so that DSP doesn't get resorted for every DSP object
+    int the patch. */
+
+int canvas_suspend_dsp(void)
+{
+    int rval = canvas_dspstate;
+    if (rval) canvas_stop_dsp();
+    return (rval);
+}
+
+void canvas_resume_dsp(int oldstate)
+{
+    if (oldstate) canvas_start_dsp();
+}
+
+    /* this is equivalent to suspending and resuming in one step. */
+void canvas_update_dsp(void)
+{
+    if (canvas_dspstate) canvas_start_dsp();
+}
+
+void glob_dsp(void *dummy, t_symbol *s, int argc, t_atom *argv)
+{
+    int newstate;
+    if (argc)
+    {
+        newstate = atom_getintarg(0, argc, argv);
+        if (newstate && !canvas_dspstate)
+        {
+            sys_set_audio_state(1);
+            canvas_start_dsp();
+        }
+        else if (!newstate && canvas_dspstate)
+        {
+            canvas_stop_dsp();
+            sys_set_audio_state(0);
+        }
+    }
+    else post("dsp state %d", canvas_dspstate);
+}
+
+void *canvas_getblock(t_class *blockclass, t_canvas **canvasp)
+{
+    t_canvas *canvas = *canvasp;
+    t_gobj *g;
+    void *ret = 0;
+    for (g = canvas->gl_list; g; g = g->g_next)
+    {
+        if (g->g_pd == blockclass)
+            ret = g;
+    }
+    *canvasp = canvas->gl_owner;
+    return(ret);
+}
+    
+/******************* redrawing  data *********************/
+
+    /* redraw all "scalars" (do this if a drawing command is changed.) 
+    LATER we'll use the "template" information to select which ones we
+    redraw.   Action = 0 for redraw, 1 for draw only, 2 for erase. */
+static void glist_redrawall(t_glist *gl, int action)
+{
+    t_gobj *g;
+    int vis = glist_isvisible(gl);
+    for (g = gl->gl_list; g; g = g->g_next)
+    {
+        t_class *cl;
+        if (vis && g->g_pd == scalar_class)
+        {
+            if (action == 1)
+            {
+                if (glist_isvisible(gl))
+                    gobj_vis(g, gl, 1);
+            }
+            else if (action == 2)
+            {
+                if (glist_isvisible(gl))
+                    gobj_vis(g, gl, 0);
+            }
+            else scalar_redraw((t_scalar *)g, gl);
+        }
+        else if (g->g_pd == canvas_class)
+            glist_redrawall((t_glist *)g, action);
+    }
+}
+
+    /* public interface for above. */
+void canvas_redrawallfortemplate(t_template *template, int action)
+{
+    t_canvas *x;
+        /* find all root canvases */
+    for (x = canvas_list; x; x = x->gl_next)
+        glist_redrawall(x, action);
+}
+
+    /* find the template defined by a canvas, and redraw all elements
+    for that */
+void canvas_redrawallfortemplatecanvas(t_canvas *x, int action)
+{
+    t_gobj *g;
+    t_template *tmpl;
+    t_symbol *s1 = gensym("struct");
+    for (g = x->gl_list; g; g = g->g_next)
+    {
+        t_object *ob = pd_checkobject(&g->g_pd);
+        t_atom *argv;
+        if (!ob || ob->te_type != T_OBJECT ||
+            binbuf_getnatom(ob->te_binbuf) < 2)
+            continue;
+        argv = binbuf_getvec(ob->te_binbuf);
+        if (argv[0].a_type != A_SYMBOL || argv[1].a_type != A_SYMBOL
+            || argv[0].a_w.w_symbol != s1)
+                continue;
+        tmpl = template_findbyname(argv[1].a_w.w_symbol);
+        canvas_redrawallfortemplate(tmpl, action);
+    }
+    canvas_redrawallfortemplate(0, action);
+}
+
+/* ------------------------------- declare ------------------------ */
+
+/* put "declare" objects in a patch to tell it about the environment in
+which objects should be created in this canvas.  This includes directories to
+search ("-path", "-stdpath") and object libraries to load
+("-lib" and "-stdlib").  These must be set before the patch containing
+the "declare" object is filled in with its contents; so when the patch is
+saved,  we throw early messages to the canvas to set the environment
+before any objects are created in it. */
+
+static t_class *declare_class;
+extern t_class *import_class;
+
+typedef struct _declare
+{
+    t_object x_obj;
+    t_canvas *x_canvas;
+    int x_useme;
+} t_declare;
+
+static void *declare_new(t_symbol *s, int argc, t_atom *argv)
+{
+    t_declare *x = (t_declare *)pd_new(declare_class);
+    x->x_useme = 1;
+    x->x_canvas = canvas_getcurrent();
+        /* LATER update environment and/or load libraries */
+    return (x);
+}
+
+static void declare_free(t_declare *x)
+{
+    x->x_useme = 0;
+        /* LATER update environment */
+}
+
+void canvas_savedeclarationsto(t_canvas *x, t_binbuf *b)
+{
+    t_gobj *y;
+
+    for (y = x->gl_list; y; y = y->g_next)
+    {
+        if (pd_class(&y->g_pd) == declare_class)
+        {
+            binbuf_addv(b, "s", gensym("#X"));
+            binbuf_addbinbuf(b, ((t_declare *)y)->x_obj.te_binbuf);
+            binbuf_addv(b, ";");
+        }
+        else if (pd_class(&y->g_pd) == import_class)
+        {
+            int i, argc;
+            t_atom *argv;
+            binbuf_addv(b, "s", gensym("#X"));
+            binbuf_addv(b, "s", gensym("declare"));
+            argc = binbuf_getnatom(((t_object *)y)->te_binbuf) - 1;
+            argv = binbuf_getvec(((t_object *)y)->te_binbuf) + 1;
+            for(i = 0; i < argc; ++i)
+            {
+                binbuf_addv(b, "s", gensym("-lib"));
+                binbuf_add(b, 1, argv + i);
+            }
+            binbuf_addv(b, ";");
+        }
+        else if (pd_class(&y->g_pd) == canvas_class)
+            canvas_savedeclarationsto((t_canvas *)y, b);
+    }
+}
+
+static void canvas_completepath(char *from, char *to, int bufsize)
+{
+    if (sys_isabsolutepath(from))
+    {
+        to[0] = '\0';
+    }
+    else
+    {   // if not absolute path, append Pd lib dir
+        strncpy(to, sys_libdir->s_name, bufsize-4);
+        to[bufsize-3] = '\0';
+        strcat(to, "/");
+    }
+    strncat(to, from, bufsize-strlen(to));
+    to[bufsize-1] = '\0';
+}
+
+static void canvas_declare(t_canvas *x, t_symbol *s, int argc, t_atom *argv)
+{
+    int i;
+    t_canvasenvironment *e = canvas_getenv(x);
+#if 0
+    startpost("declare:: %s", s->s_name);
+    postatom(argc, argv);
+    endpost();
+#endif
+    for (i = 0; i < argc; i++)
+    {
+        char strbuf[FILENAME_MAX];
+        char *flag = atom_getsymbolarg(i, argc, argv)->s_name;
+        if ((argc > i+1) && !strcmp(flag, "-path"))
+        {
+            e->ce_path = namelist_append(e->ce_path, 
+                atom_getsymbolarg(i+1, argc, argv)->s_name, 0);
+            i++;
+        }
+        else if ((argc > i+1) && !strcmp(flag, "-stdpath"))
+        {
+            canvas_completepath(atom_getsymbolarg(i+1, argc, argv)->s_name,
+                strbuf, FILENAME_MAX);
+            e->ce_path = namelist_append(e->ce_path, strbuf, 0);
+            i++;
+        }
+        else if ((argc > i+1) && !strcmp(flag, "-lib"))
+        {
+            sys_load_lib(x, atom_getsymbolarg(i+1, argc, argv)->s_name);
+            i++;
+        }
+        else if ((argc > i+1) && !strcmp(flag, "-stdlib"))
+        {
+            canvas_completepath(atom_getsymbolarg(i+1, argc, argv)->s_name,
+                strbuf, FILENAME_MAX);
+            sys_load_lib(0, strbuf);
+            i++;
+        }
+        else post("declare: %s: unknown declaration", flag);
+    }
+}
+
+    /* utility function to read a file, looking first down the canvas's search
+    path (set with "declare" objects in the patch and recursively in calling
+    patches), then down the system one.  The filename is the concatenation of
+    "name" and "ext".  "Name" may be absolute, or may be relative with
+    slashes.  If anything can be opened, the true directory
+    ais put in the buffer dirresult (provided by caller), which should
+    be "size" bytes.  The "nameresult" pointer will be set somewhere in
+    the interior of "dirresult" and will give the file basename (with
+    slashes trimmed).  If "bin" is set a 'binary' open is
+    attempted, otherwise ASCII (this only matters on Microsoft.) 
+    If "x" is zero, the file is sought in the directory "." or in the
+    global path.*/
+
+int canvas_open(t_canvas *x, const char *name, const char *ext,
+    char *dirresult, char **nameresult, unsigned int size, int bin)
+{
+    t_namelist *nl, thislist;
+    int fd = -1;
+    t_canvas *y;
+
+        /* first check if "name" is absolute (and if so, try to open) */
+    if (sys_open_absolute(name, ext, dirresult, nameresult, size, bin, &fd))
+        return (fd);
+    
+        /* otherwise "name" is relative; start trying in directories named
+        in this and parent environments */
+    for (y = x; y; y = y->gl_owner)
+        if (y->gl_env)
+    {
+        t_namelist *nl;
+        t_canvas *x2 = x;
+        char *dir;
+        while (x2 && x2->gl_owner)
+            x2 = x2->gl_owner;
+        dir = (x2 ? canvas_getdir(x2)->s_name : ".");
+        for (nl = y->gl_env->ce_path; nl; nl = nl->nl_next)
+        {
+            char realname[FILENAME_MAX];
+            if (sys_isabsolutepath(nl->nl_string))
+            {
+                realname[0] = '\0';
+            }
+            else
+            {   /* if not absolute path, append Pd lib dir */
+                strncpy(realname, dir, FILENAME_MAX);
+                realname[FILENAME_MAX-3] = 0;
+                strcat(realname, "/");
+            }
+            strncat(realname, nl->nl_string, FILENAME_MAX-strlen(realname));
+            realname[FILENAME_MAX-1] = 0;
+            if ((fd = sys_trytoopenone(realname, name, ext,
+                dirresult, nameresult, size, bin)) >= 0)
+                    return (fd);
+        }
+    }
+    return (open_via_path((x ? canvas_getdir(x)->s_name : "."), name, ext,
+        dirresult, nameresult, size, bin));
+}
+
+/* ------------------------------- setup routine ------------------------ */
+
+    /* why are some of these "glist" and others "canvas"? */
+extern void glist_text(t_glist *x, t_symbol *s, int argc, t_atom *argv);
+extern void canvas_obj(t_glist *gl, t_symbol *s, int argc, t_atom *argv);
+extern void canvas_bng(t_glist *gl, t_symbol *s, int argc, t_atom *argv);
+extern void canvas_toggle(t_glist *gl, t_symbol *s, int argc, t_atom *argv);
+extern void canvas_vslider(t_glist *gl, t_symbol *s, int argc, t_atom *argv);
+extern void canvas_hslider(t_glist *gl, t_symbol *s, int argc, t_atom *argv);
+extern void canvas_vdial(t_glist *gl, t_symbol *s, int argc, t_atom *argv);
+    /* old version... */
+extern void canvas_hdial(t_glist *gl, t_symbol *s, int argc, t_atom *argv);
+extern void canvas_hdial(t_glist *gl, t_symbol *s, int argc, t_atom *argv);
+    /* new version: */
+extern void canvas_hradio(t_glist *gl, t_symbol *s, int argc, t_atom *argv);
+extern void canvas_vradio(t_glist *gl, t_symbol *s, int argc, t_atom *argv);
+extern void canvas_vumeter(t_glist *gl, t_symbol *s, int argc, t_atom *argv);
+extern void canvas_mycnv(t_glist *gl, t_symbol *s, int argc, t_atom *argv);
+extern void canvas_numbox(t_glist *gl, t_symbol *s, int argc, t_atom *argv);
+extern void canvas_msg(t_glist *gl, t_symbol *s, int argc, t_atom *argv);
+extern void canvas_floatatom(t_glist *gl, t_symbol *s, int argc, t_atom *argv);
+extern void canvas_symbolatom(t_glist *gl, t_symbol *s, int argc, t_atom *argv);
+extern void glist_scalar(t_glist *canvas, t_symbol *s, int argc, t_atom *argv);
+
+void g_graph_setup(void);
+void g_editor_setup(void);
+void g_readwrite_setup(void);
+extern void canvas_properties(t_gobj *z);
+
+void g_canvas_setup(void)
+{
+        /* we prevent the user from typing "canvas" in an object box
+        by sending 0 for a creator function. */
+    canvas_class = class_new(gensym("canvas"), 0,
+        (t_method)canvas_free, sizeof(t_canvas), CLASS_NOINLET, 0);
+            /* here is the real creator function, invoked in patch files
+            by sending the "canvas" message to #N, which is bound
+            to pd_camvasmaker. */
+    class_addmethod(pd_canvasmaker, (t_method)canvas_new, gensym("canvas"),
+        A_GIMME, 0);
+    class_addmethod(canvas_class, (t_method)canvas_restore,
+        gensym("restore"), A_GIMME, 0);
+    class_addmethod(canvas_class, (t_method)canvas_coords,
+        gensym("coords"), A_GIMME, 0);
+
+/* -------------------------- objects ----------------------------- */
+    class_addmethod(canvas_class, (t_method)canvas_obj,
+        gensym("obj"), A_GIMME, A_NULL);
+    class_addmethod(canvas_class, (t_method)canvas_msg,
+        gensym("msg"), A_GIMME, A_NULL);
+    class_addmethod(canvas_class, (t_method)canvas_floatatom,
+        gensym("floatatom"), A_GIMME, A_NULL);
+    class_addmethod(canvas_class, (t_method)canvas_symbolatom,
+        gensym("symbolatom"), A_GIMME, A_NULL);
+    class_addmethod(canvas_class, (t_method)glist_text,
+        gensym("text"), A_GIMME, A_NULL);
+    class_addmethod(canvas_class, (t_method)glist_glist, gensym("graph"),
+        A_GIMME, A_NULL);
+    class_addmethod(canvas_class, (t_method)glist_scalar,
+        gensym("scalar"), A_GIMME, A_NULL);
+
+/* -------------- IEMGUI: button, toggle, slider, etc.  ------------ */
+    class_addmethod(canvas_class, (t_method)canvas_bng, gensym("bng"),
+                    A_GIMME, A_NULL);
+    class_addmethod(canvas_class, (t_method)canvas_toggle, gensym("toggle"),
+                    A_GIMME, A_NULL);
+    class_addmethod(canvas_class, (t_method)canvas_vslider, gensym("vslider"),
+                    A_GIMME, A_NULL);
+    class_addmethod(canvas_class, (t_method)canvas_hslider, gensym("hslider"),
+                    A_GIMME, A_NULL);
+    class_addmethod(canvas_class, (t_method)canvas_hdial, gensym("hdial"),
+                    A_GIMME, A_NULL);
+    class_addmethod(canvas_class, (t_method)canvas_vdial, gensym("vdial"),
+                    A_GIMME, A_NULL);
+    class_addmethod(canvas_class, (t_method)canvas_hradio, gensym("hradio"),
+                    A_GIMME, A_NULL);
+    class_addmethod(canvas_class, (t_method)canvas_vradio, gensym("vradio"),
+                    A_GIMME, A_NULL);
+    class_addmethod(canvas_class, (t_method)canvas_vumeter, gensym("vumeter"),
+                    A_GIMME, A_NULL);
+    class_addmethod(canvas_class, (t_method)canvas_mycnv, gensym("mycnv"),
+                    A_GIMME, A_NULL);
+    class_addmethod(canvas_class, (t_method)canvas_numbox, gensym("numbox"),
+                    A_GIMME, A_NULL);
+
+/* ------------------------ gui stuff --------------------------- */
+    class_addmethod(canvas_class, (t_method)canvas_pop, gensym("pop"),
+        A_DEFFLOAT, A_NULL);
+    class_addmethod(canvas_class, (t_method)canvas_loadbang,
+        gensym("loadbang"), A_NULL);
+    class_addmethod(canvas_class, (t_method)canvas_relocate,
+        gensym("relocate"), A_SYMBOL, A_SYMBOL, A_NULL);
+    class_addmethod(canvas_class, (t_method)canvas_vis,
+        gensym("vis"), A_FLOAT, A_NULL);
+    class_addmethod(canvas_class, (t_method)glist_menu_open,
+        gensym("menu-open"), A_NULL);
+    class_addmethod(canvas_class, (t_method)canvas_map,
+        gensym("map"), A_FLOAT, A_NULL);
+    class_addmethod(canvas_class, (t_method)canvas_dirty,
+        gensym("dirty"), A_FLOAT, A_NULL);
+    class_setpropertiesfn(canvas_class, (t_propertiesfn)canvas_properties);
+
+/* ---------------------- list handling ------------------------ */
+    class_addmethod(canvas_class, (t_method)glist_clear, gensym("clear"),
+        A_NULL);
+
+/* ----- subcanvases, which you get by typing "pd" in a box ---- */
+    class_addcreator((t_newmethod)subcanvas_new, gensym("pd"), A_DEFSYMBOL, 0);
+    class_addcreator((t_newmethod)subcanvas_new, gensym("page"),  A_DEFSYMBOL, 0);
+
+    class_addmethod(canvas_class, (t_method)canvas_click,
+        gensym("click"), A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0);
+    class_addmethod(canvas_class, (t_method)canvas_dsp, gensym("dsp"), 0);
+    class_addmethod(canvas_class, (t_method)canvas_rename_method,
+        gensym("rename"), A_GIMME, 0);
+
+/*---------------------------- tables -- GG ------------------- */
+
+    class_addcreator((t_newmethod)table_new, gensym("table"),
+        A_DEFSYM, A_DEFFLOAT, 0);
+
+/*---------------------------- declare ------------------- */
+    declare_class = class_new(gensym("declare"), (t_newmethod)declare_new,
+        (t_method)declare_free, sizeof(t_declare), CLASS_NOINLET, A_GIMME, 0);
+    class_addmethod(canvas_class, (t_method)canvas_declare,
+        gensym("declare"), A_GIMME, 0);
+
+/* -------------- setups from other files for canvas_class ---------------- */
+    g_graph_setup();
+    g_editor_setup();
+    g_readwrite_setup();
+}
diff --git a/src/g_editor.c b/src/g_editor.c
index 8daf7f82359b34427486c5d4d26b772495bf9989..a716a3fa7358b063d86d75b099f466de6a31c352 100644
--- a/src/g_editor.c
+++ b/src/g_editor.c
@@ -48,7 +48,6 @@ static int outlet_issignal = 0;
 static int inlet_issignal = 0;
 static int last_inlet_filter = 0;
 static int last_outlet_filter = 0;
-static int copyfromexternalbuffer = 0;
 struct _outlet
 {
     t_object *o_owner;
@@ -349,10 +348,8 @@ void glist_noselect(t_glist *x)
 {
     if (x->gl_editor)
     {
-		if (x->gl_editor->e_selection) {
-		    while (x->gl_editor->e_selection)
-		        glist_deselect(x, x->gl_editor->e_selection->sel_what);
-		}
+        while (x->gl_editor->e_selection)
+            glist_deselect(x, x->gl_editor->e_selection->sel_what);
         if (x->gl_editor->e_selectedline)
             glist_deselectline(x);
 		if (c_selection == x)
@@ -433,14 +430,11 @@ static const char *canvas_undo_name;
 void canvas_setundo(t_canvas *x, t_undofn undofn, void *buf,
     const char *name)
 {
-	//fprintf(stderr,"canvas_setundo %s\n", name);
-
     int hadone = 0;
         /* blow away the old undo information.  In one special case the
         old undo info is re-used; if so we shouldn't free it here. */
     if (canvas_undo_fn && canvas_undo_buf && (buf != canvas_undo_buf))
     {
-		//fprintf(stderr,"hadone canvas_setundo\n");
         (*canvas_undo_fn)(canvas_undo_canvas, canvas_undo_buf, UNDO_FREE);
         hadone = 1;
     }
@@ -611,24 +605,22 @@ static void *canvas_undo_set_cut(t_canvas *x, int mode)
         /* store connections into/out of the selection */
     buf->u_reconnectbuf = binbuf_new();
     linetraverser_start(&t, x);
-	if (linetraverser_next(&t)) {
-		while (oc = linetraverser_next(&t))
-		{
-		    int issel1 = glist_isselected(x, &t.tr_ob->ob_g);
-		    int issel2 = glist_isselected(x, &t.tr_ob2->ob_g);
-		    if (issel1 != issel2)
-		    {
-		        binbuf_addv(buf->u_reconnectbuf, "ssiiii;",
-		            gensym("#X"), gensym("connect"),
-		            (issel1 ? nnotsel : 0)
-		                + glist_selectionindex(x, &t.tr_ob->ob_g, issel1),
-		            t.tr_outno,
-		            (issel2 ? nnotsel : 0) +
-		                glist_selectionindex(x, &t.tr_ob2->ob_g, issel2),
-		            t.tr_inno);
-		    }
-		}
-	}
+    while (oc = linetraverser_next(&t))
+    {
+        int issel1 = glist_isselected(x, &t.tr_ob->ob_g);
+        int issel2 = glist_isselected(x, &t.tr_ob2->ob_g);
+        if (issel1 != issel2)
+        {
+            binbuf_addv(buf->u_reconnectbuf, "ssiiii;",
+                gensym("#X"), gensym("connect"),
+                (issel1 ? nnotsel : 0)
+                    + glist_selectionindex(x, &t.tr_ob->ob_g, issel1),
+                t.tr_outno,
+                (issel2 ? nnotsel : 0) +
+                    glist_selectionindex(x, &t.tr_ob2->ob_g, issel2),
+                t.tr_inno);
+        }
+    }
     if (mode == UCUT_TEXT)
     {
         buf->u_objectbuf = canvas_docopy(x);
@@ -711,7 +703,7 @@ static void canvas_undo_cut(t_canvas *x, void *z, int action)
             binbuf_free(buf->u_reconnectbuf);
         if (buf->u_redotextbuf)
             binbuf_free(buf->u_redotextbuf);
-        if (buf != NULL) t_freebytes(buf, sizeof(*buf));
+        t_freebytes(buf, sizeof(*buf));
     }
 }
 
@@ -1164,31 +1156,57 @@ typedef struct _undo_canvas_properties
     unsigned int gl_hidetext:1;     /* hide object-name + args when doing graph on parent */
 } t_undo_canvas_properties;
 
-t_undo_canvas_properties global_buf;
+t_undo_canvas_properties *global_buf; /* we need this to avoid redundant undo creation when pressing apply and then ok in the canvas properties menu */
 
 static void *canvas_undo_set_canvas(t_canvas *x)
 {
+    //t_undo_canvas_properties *buf;
+
 	/* enable editor (in case it is disabled) and select the object we are working on */
 	if (!x->gl_edit)
 		canvas_editmode(x, 1);
 
-	global_buf.gl_pixwidth = x->gl_pixwidth;
-	global_buf.gl_pixheight = x->gl_pixheight;
-	global_buf.gl_x1 = x->gl_x1;
-	global_buf.gl_y1 = x->gl_y1;
-	global_buf.gl_x2 = x->gl_x2;
-	global_buf.gl_y2 = x->gl_y2;
-	global_buf.gl_screenx1 = x->gl_screenx1;
-	global_buf.gl_screeny1 = x->gl_screeny1;
-	global_buf.gl_screenx2 = x->gl_screenx2;
-	global_buf.gl_screeny2 = x->gl_screeny2;
-	global_buf.gl_xmargin = x->gl_xmargin;
-	global_buf.gl_ymargin = x->gl_ymargin;
-	global_buf.gl_goprect = x->gl_goprect;
-	global_buf.gl_isgraph = x->gl_isgraph;
-	global_buf.gl_hidetext = x->gl_hidetext;
+    if (global_buf == NULL) {
+		global_buf = (t_undo_canvas_properties *)getbytes(sizeof(*global_buf));
+		//fprintf(stderr,"creating a new buffer for canvas properties\n");
+	}
+
+	/*if (
+		global_buf->gl_pixwidth != x->gl_pixwidth ||
+		global_buf->gl_pixheight != x->gl_pixheight ||
+		global_buf->gl_x1 != x->gl_x1 ||
+		global_buf->gl_y1 != x->gl_y1 ||
+		global_buf->gl_x2 != x->gl_x2 ||
+		global_buf->gl_y2 != x->gl_y2 ||
+		global_buf->gl_screenx1 != x->gl_screenx1 ||
+		global_buf->gl_screeny1 != x->gl_screeny1 ||
+		global_buf->gl_screenx2 != x->gl_screenx2 ||
+		global_buf->gl_screeny2 != x->gl_screeny2 ||
+		global_buf->gl_xmargin != x->gl_xmargin ||
+		global_buf->gl_ymargin != x->gl_ymargin ||
+		global_buf->gl_goprect != x->gl_goprect ||
+		global_buf->gl_isgraph != x->gl_isgraph ||
+		global_buf->gl_hidetext != x->gl_hidetext)
+	{*/
+		//fprintf(stderr,"changing values\n");
+		global_buf->gl_pixwidth = x->gl_pixwidth;
+		global_buf->gl_pixheight = x->gl_pixheight;
+		global_buf->gl_x1 = x->gl_x1;
+		global_buf->gl_y1 = x->gl_y1;
+		global_buf->gl_x2 = x->gl_x2;
+		global_buf->gl_y2 = x->gl_y2;
+		global_buf->gl_screenx1 = x->gl_screenx1;
+		global_buf->gl_screeny1 = x->gl_screeny1;
+		global_buf->gl_screenx2 = x->gl_screenx2;
+		global_buf->gl_screeny2 = x->gl_screeny2;
+		global_buf->gl_xmargin = x->gl_xmargin;
+		global_buf->gl_ymargin = x->gl_ymargin;
+		global_buf->gl_goprect = x->gl_goprect;
+		global_buf->gl_isgraph = x->gl_isgraph;
+		global_buf->gl_hidetext = x->gl_hidetext;
+	//}
 	
-    return (&global_buf);
+    return (global_buf);
 }
 
 extern int gfxstub_haveproperties(void *key);
@@ -1196,7 +1214,7 @@ extern int gfxstub_haveproperties(void *key);
 static void canvas_undo_canvas_apply(t_canvas *x, void *z, int action)
 {
     t_undo_canvas_properties *buf = z;
-    t_undo_canvas_properties tmp;
+    t_undo_canvas_properties *tmp;
 
 	if (!x->gl_edit)
 		canvas_editmode(x, 1);
@@ -1206,25 +1224,29 @@ static void canvas_undo_canvas_apply(t_canvas *x, void *z, int action)
 		//close properties window first
 		t_int properties = gfxstub_haveproperties((void *)x);
 		if (properties) {
+			fprintf(stderr,"have it\n");
 			sys_vgui("destroy .gfxstub%lx\n", properties);
 		}
 
+		//create a temporary data holder
+		tmp = (t_undo_canvas_properties *)getbytes(sizeof(*tmp));
+
 		//store current canvas values into temporary data holder
-		tmp.gl_pixwidth = x->gl_pixwidth;
-		tmp.gl_pixheight = x->gl_pixheight;
-		tmp.gl_x1 = x->gl_x1;
-		tmp.gl_y1 = x->gl_y1;
-		tmp.gl_x2 = x->gl_x2;
-		tmp.gl_y2 = x->gl_y2;
-		tmp.gl_screenx1 = x->gl_screenx1;
-		tmp.gl_screeny1 = x->gl_screeny1;
-		tmp.gl_screenx2 = x->gl_screenx2;
-		tmp.gl_screeny2 = x->gl_screeny2;
-		tmp.gl_xmargin = x->gl_xmargin;
-		tmp.gl_ymargin = x->gl_ymargin;
-		tmp.gl_goprect = x->gl_goprect;
-		tmp.gl_isgraph = x->gl_isgraph;
-		tmp.gl_hidetext = x->gl_hidetext;
+		tmp->gl_pixwidth = x->gl_pixwidth;
+		tmp->gl_pixheight = x->gl_pixheight;
+		tmp->gl_x1 = x->gl_x1;
+		tmp->gl_y1 = x->gl_y1;
+		tmp->gl_x2 = x->gl_x2;
+		tmp->gl_y2 = x->gl_y2;
+		tmp->gl_screenx1 = x->gl_screenx1;
+		tmp->gl_screeny1 = x->gl_screeny1;
+		tmp->gl_screenx2 = x->gl_screenx2;
+		tmp->gl_screeny2 = x->gl_screeny2;
+		tmp->gl_xmargin = x->gl_xmargin;
+		tmp->gl_ymargin = x->gl_ymargin;
+		tmp->gl_goprect = x->gl_goprect;
+		tmp->gl_isgraph = x->gl_isgraph;
+		tmp->gl_hidetext = x->gl_hidetext;
 
 		//change canvas values with the ones from the undo buffer
 		x->gl_pixwidth = buf->gl_pixwidth;
@@ -1244,21 +1266,24 @@ static void canvas_undo_canvas_apply(t_canvas *x, void *z, int action)
 		x->gl_hidetext = buf->gl_hidetext;
 
 		//copy data values from the temporary data to the undo buffer
-		buf->gl_pixwidth = tmp.gl_pixwidth;
-		buf->gl_pixheight = tmp.gl_pixheight;
-		buf->gl_x1 = tmp.gl_x1;
-		buf->gl_y1 = tmp.gl_y1;
-		buf->gl_x2 = tmp.gl_x2;
-		buf->gl_y2 = tmp.gl_y2;
-		buf->gl_screenx1 = tmp.gl_screenx1;
-		buf->gl_screeny1 = tmp.gl_screeny1;
-		buf->gl_screenx2 = tmp.gl_screenx2;
-		buf->gl_screeny2 = tmp.gl_screeny2;
-		buf->gl_xmargin = tmp.gl_xmargin;
-		buf->gl_ymargin = tmp.gl_ymargin;
-		buf->gl_goprect = tmp.gl_goprect;
-		buf->gl_isgraph = tmp.gl_isgraph;
-		buf->gl_hidetext = tmp.gl_hidetext;
+		buf->gl_pixwidth = tmp->gl_pixwidth;
+		buf->gl_pixheight = tmp->gl_pixheight;
+		buf->gl_x1 = tmp->gl_x1;
+		buf->gl_y1 = tmp->gl_y1;
+		buf->gl_x2 = tmp->gl_x2;
+		buf->gl_y2 = tmp->gl_y2;
+		buf->gl_screenx1 = tmp->gl_screenx1;
+		buf->gl_screeny1 = tmp->gl_screeny1;
+		buf->gl_screenx2 = tmp->gl_screenx2;
+		buf->gl_screeny2 = tmp->gl_screeny2;
+		buf->gl_xmargin = tmp->gl_xmargin;
+		buf->gl_ymargin = tmp->gl_ymargin;
+		buf->gl_goprect = tmp->gl_goprect;
+		buf->gl_isgraph = tmp->gl_isgraph;
+		buf->gl_hidetext = tmp->gl_hidetext;
+
+		//delete temporary data holder
+		t_freebytes(tmp, sizeof(*tmp));
 
 		//redraw
 		canvas_setgraph(x, x->gl_isgraph, 0);
@@ -1268,6 +1293,7 @@ static void canvas_undo_canvas_apply(t_canvas *x, void *z, int action)
 		}
 		if (x->gl_owner && glist_isvisible(x->gl_owner))
 		{
+			//fprintf(stderr,"we got gop\n");
 			glist_noselect(x);
 		    gobj_vis(&x->gl_gobj, x->gl_owner, 0);
 		    gobj_vis(&x->gl_gobj, x->gl_owner, 1);
@@ -1276,17 +1302,13 @@ static void canvas_undo_canvas_apply(t_canvas *x, void *z, int action)
 		//update scrollbars when GOP potentially exceeds window size
 		t_canvas *canvas=(t_canvas *)glist_getcanvas(x);
 		//if gop is being disabled go one level up
-		if (!x->gl_isgraph && x->gl_owner) {
-			canvas=canvas->gl_owner;
-			canvas_redraw(canvas);
-		}
-		sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", (t_int)x);
+		if (!x->gl_isgraph) canvas=canvas->gl_owner;
 		sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", (t_int)canvas);
 	}
 
     else if (action == UNDO_FREE)
     {
-		//do nothing since undo apply uses a global_buf struct rather than a pointer
+        t_freebytes(buf, sizeof(*buf));
     }
 }
 
@@ -1295,89 +1317,6 @@ void canvas_canvas_setundo(t_canvas *x)
 	canvas_setundo(x, canvas_undo_canvas_apply, canvas_undo_set_canvas(x), "apply");
 }
 
-/* --------- 8. create ----------- */
-
-typedef struct _undo_create      
-{
-    int u_index;    /* index of the created object object */
-    t_binbuf *u_objectbuf;      /* the object cleared or typed into */
-    t_binbuf *u_reconnectbuf;   /* connections into and out of object */
-} t_undo_create;
-
-void *canvas_undo_set_create(t_canvas *x)
-{
-    t_gobj *y, *last;
-    t_linetraverser t;
-    t_outconnect *oc;
-
-    t_undo_create *buf = (t_undo_create *)getbytes(sizeof(*buf));
-    buf->u_index = glist_getindex(x, 0) - 1;
-    int nnotsel= glist_selectionindex(x, 0, 0);
-
-    buf->u_objectbuf = binbuf_new();
-	if (x->gl_list) {
-		for (y = x->gl_list; y; y = y->g_next)
-		{
-		    if (glist_isselected(x, y)) {
-		        gobj_save(y, buf->u_objectbuf);
-			}
-		}
-	}
-    buf->u_reconnectbuf = binbuf_new();
-    linetraverser_start(&t, x);
-	if (linetraverser_next(&t)) {
-		while (oc = linetraverser_next(&t))
-		{
-		    int issel1 = glist_isselected(x, &t.tr_ob->ob_g);
-		    int issel2 = glist_isselected(x, &t.tr_ob2->ob_g);
-		    if (issel1 != issel2)
-		    {
-		        binbuf_addv(buf->u_reconnectbuf, "ssiiii;",
-		            gensym("#X"), gensym("connect"),
-		            (issel1 ? nnotsel : 0)
-		                + glist_selectionindex(x, &t.tr_ob->ob_g, issel1),
-		            t.tr_outno,
-		            (issel2 ? nnotsel : 0) +
-		                glist_selectionindex(x, &t.tr_ob2->ob_g, issel2),
-		            t.tr_inno);
-		    }
-		}
-	}
-    return (buf);
-}
-
-void canvas_undo_create(t_canvas *x, void *z, int action)
-{
-    t_undo_create *buf = z;
-    t_gobj *y;
-
-	//fprintf(stderr,"canvas = %lx buf->u_index = %d\n", (t_int)x, buf->u_index);
-
-    if (action == UNDO_UNDO)
-    {
-        glist_noselect(x);
-        y = glist_nth(x, buf->u_index);
-        glist_select(x, y);
-        canvas_doclear(x);
-    }
-    else if (action == UNDO_REDO)
-    {
-        pd_bind(&x->gl_pd, gensym("#X"));
-   		binbuf_eval(buf->u_objectbuf, 0, 0, 0);
-    	pd_unbind(&x->gl_pd, gensym("#X"));
-        pd_bind(&x->gl_pd, gensym("#X"));
-   		binbuf_eval(buf->u_reconnectbuf, 0, 0, 0);
-    	pd_unbind(&x->gl_pd, gensym("#X"));
-        y = glist_nth(x, buf->u_index);
-        glist_select(x, y);
-    }
-	else if (action == UNDO_FREE) {
-		binbuf_free(buf->u_objectbuf);
-		binbuf_free(buf->u_reconnectbuf);
-        t_freebytes(buf, sizeof(*buf));
-	}
-}
-
 /* ------------------------ event handling ------------------------ */
 
 static char *cursorlist[] = {
@@ -1522,10 +1461,10 @@ void canvas_destroy_editor(t_glist *x)
         	    if (ob = pd_checkobject(&y->g_pd))
         	        rtext_free(glist_findrtext(x, ob));
 		}
-		//if (x->gl_editor) {
-		editor_free(x->gl_editor, x);
-		x->gl_editor = 0;
-		//}
+		if (x->gl_editor) {
+			editor_free(x->gl_editor, x);
+			x->gl_editor = 0;
+		}
 	}
 }
 
@@ -1683,14 +1622,11 @@ void canvas_setgraph(t_glist *x, int flag, int nogoprect)
             canvas_destroy_editor(x);
         x->gl_isgraph = 0;
 		x->gl_hidetext = 0;
-		//x->gl_editor = 0;
         if (x->gl_owner && !x->gl_loading && glist_isvisible(x->gl_owner))
         {
             gobj_vis(&x->gl_gobj, x->gl_owner, 1);
             canvas_fixlinesfor(x->gl_owner, &x->gl_obj);
         }
-		//if (x->gl_havewindow && hadeditor)
-		//	canvas_editmode(x, 1);
     }
     else if (flag)
     {
@@ -1831,7 +1767,6 @@ static void canvas_donecanvasdialog(t_glist *x,
     canvas_setgraph(x, graphme, 0);
     canvas_dirty(x, 1);
     if (x->gl_havewindow) {
-		//fprintf(stderr,"donecanvasdialog canvas_redraw\n");
         canvas_redraw(x);
 	}
     else if (x->gl_owner && glist_isvisible(x->gl_owner))
@@ -3293,62 +3228,56 @@ void canvas_restoreconnections(t_canvas *x)
 
 static t_binbuf *canvas_docopy(t_canvas *x)
 {
-	//fprintf(stderr,"canvas_docopy\n");
+	//fprintf(stderr,"docopy\n");
     t_gobj *y, *last;
     t_linetraverser t;
     t_outconnect *oc;
     t_binbuf *b = binbuf_new();
+	//int c = 0;
     for (y = x->gl_list; y; y = y->g_next)
     {
         if (glist_isselected(x, y)) {
-			//fprintf(stderr,"saving object\n");
+			//c++;
+			//fprintf(stderr, "saving object num %d\n", c);
+			//fprintf(stderr, "saving object >.x%lx<\n", (t_int)y);
+			/* introduce redundant comment to avoid recreation of old abstractions
+			   with the same canvas id which results in all commands being registered
+			   multiple times--apparently after much searching it appears that this
+			   is yet another bug in tcl/tk which means that canvas tries to do some
+			   kind of caching behind the curtains resulting in objects not always
+			   having unique ids, contrary to tcl/tk's canvas man page */
+			/*if (c==1) {
+            	binbuf_addv(b, "ssiis;", gensym("#X"), gensym("text"),
+                (int)((t_text *)y)->te_xpix-30, (int)((t_text *)y)->te_ypix-30, gensym("tcltksucks"));
+			}*/
             gobj_save(y, b);
 		}
     }
+	//fprintf(stderr,"done saving objects\n");
     linetraverser_start(&t, x);
+	//c = 0;
     while (oc = linetraverser_next(&t))
     {
-		//fprintf(stderr,"found some lines %d %d\n", glist_isselected(x, &t.tr_ob->ob_g), glist_isselected(x, &t.tr_ob2->ob_g));
         if (glist_isselected(x, &t.tr_ob->ob_g)
             && glist_isselected(x, &t.tr_ob2->ob_g))
         {
-			//fprintf(stderr,"saving lines leading into selected object\n");
+			//fprintf(stderr, "lines need to be copied\n");
+			//c = 1;
             binbuf_addv(b, "ssiiii;", gensym("#X"), gensym("connect"),
                 glist_selectionindex(x, &t.tr_ob->ob_g, 1), t.tr_outno,
                 glist_selectionindex(x, &t.tr_ob2->ob_g, 1), t.tr_inno);
+//                glist_selectionindex(x, &t.tr_ob->ob_g, 1)+1, t.tr_outno,
+//                glist_selectionindex(x, &t.tr_ob2->ob_g, 1)+1, t.tr_inno);
         }
     }
+	//if (!c) fprintf(stderr, "no lines copied\n");
     return (b);
 }
 
-static void canvas_copyfromexternalbuffer(t_canvas *x, t_symbol *s, int ac, t_atom *av)
-{
-	if (!x->gl_editor)
-		return;
-	/*
-	if (ac == 0) {
-		//fprintf(stderr,"init\n");
-		copyfromexternalbuffer = 1;
-		binbuf_free(copy_binbuf);
-		copy_binbuf = binbuf_new();
-	} else {
-		if (av[0].a_type == A_SYMBOL && strcmp(av[0].a_w.w_symbol->s_name, "#N")) {
-			//fprintf(stderr,"fill %d\n", ac);
-			binbuf_add(copy_binbuf, ac, av);
-			binbuf_addsemi(copy_binbuf);
-		} else {
-			//probably should resize window size and position here...
-			//fprintf(stderr,"ignoring canvas\n");
-		}
-	}
-	*/
-}
-
 static void canvas_copy(t_canvas *x)
 {
     if (!x->gl_editor || !x->gl_editor->e_selection)
         return;
-	copyfromexternalbuffer = 0;
     binbuf_free(copy_binbuf);
 	//fprintf(stderr, "canvas_copy\n");
     copy_binbuf = canvas_docopy(x);
@@ -3473,7 +3402,7 @@ static void canvas_cut(t_canvas *x)
     if (x->gl_editor && x->gl_editor->e_selectedline)
         canvas_clearline(x);
 	/* if we are cutting text */
-    else if (x->gl_editor && x->gl_editor->e_textedfor)
+    else if (x->gl_editor->e_textedfor)
     {
         char *buf;
         int bufsize;
@@ -3629,7 +3558,7 @@ static void canvas_dopaste(t_canvas *x, t_binbuf *b)
 		//reset canvas_undo_already_set_move
 		canvas_undo_already_set_move = 0;
 	}
-	else if (canvas_undo_name && !strcmp(canvas_undo_name, "paste") && !copyfromexternalbuffer) {
+	else if (canvas_undo_name && !strcmp(canvas_undo_name, "paste") ) {
 		canvas_paste_atmouse(x);
 		//fprintf(stderr,"doing a paste\n");
 	}
@@ -3772,10 +3701,6 @@ extern t_class *text_class;
 void canvas_connect(t_canvas *x, t_floatarg fwhoout, t_floatarg foutno,
     t_floatarg fwhoin, t_floatarg finno)
 {
-	if (!x->gl_list) {
-		post("paste error: no objects to connect, probably incomplete clipboard copy from an external source (e.g. from a text editor)");
-		return;		
-	}
     int whoout = fwhoout, outno = foutno, whoin = fwhoin, inno = finno;
     t_gobj *src = 0, *sink = 0;
     t_object *objsrc, *objsink;
@@ -4144,8 +4069,6 @@ void g_editor_setup(void)
         gensym("donecanvasdialog"), A_GIMME, A_NULL);
     class_addmethod(canvas_class, (t_method)glist_arraydialog,
         gensym("arraydialog"), A_GIMME, A_NULL);
-    class_addmethod(canvas_class, (t_method)canvas_copyfromexternalbuffer,
-        gensym("copyfromexternalbuffer"), A_GIMME, A_NULL);
 
 /* -------------- connect method used in reading files ------------------ */
     class_addmethod(canvas_class, (t_method)canvas_connect,
diff --git a/src/g_editor_patch b/src/g_editor_patch
new file mode 100644
index 0000000000000000000000000000000000000000..8011283ac8426be58b64372b8fd1815ee79e106f
--- /dev/null
+++ b/src/g_editor_patch
@@ -0,0 +1,31 @@
+--- g_editor.c.old	2011-02-17 20:02:34.000000000 -0500
++++ g_editor.c	2011-02-18 13:02:41.000000000 -0500
+@@ -240,6 +240,8 @@
+ {
+     if (x->gl_editor)
+     {
++		if (c_selection && c_selection != x)
++			glist_noselect(c_selection);
+         t_selection *sel = (t_selection *)getbytes(sizeof(*sel));
+         if (x->gl_editor->e_selectedline)
+             glist_deselectline(x);
+@@ -3211,7 +3213,10 @@
+     int dspstate = canvas_suspend_dsp(), nbox, count;
+ 
+     canvas_editmode(x, 1.);
+-    glist_noselect(x);
++	if (c_selection && c_selection != x)
++		glist_noselect(c_selection);
++	else
++    	glist_noselect(x);
+     for (g2 = x->gl_list, nbox = 0; g2; g2 = g2->g_next) nbox++;
+     
+ 	/* found the end of the queue */
+@@ -3296,7 +3301,6 @@
+ 		} else {
+ 		    canvas_setundo(x, canvas_undo_paste, canvas_undo_set_paste(x),
+ 		        "duplicate");
+-			glist_noselect(c_selection);
+ 		    canvas_dopaste(x, copy_binbuf);
+ 		    //canvas_paste_xyoffset(x);
+ 		    canvas_dirty(x, 1);
diff --git a/src/g_graph.c b/src/g_graph.c
index f48b0f114c840ee7c6acbd336ca10e7023eeea05..3ac48c68ac35fa8bf38ac6b41da882e459f011b9 100644
--- a/src/g_graph.c
+++ b/src/g_graph.c
@@ -29,27 +29,17 @@ void canvas_drawredrect(t_canvas *x, int doit);
 
 void glist_add(t_glist *x, t_gobj *y)
 {
-	//fprintf(stderr,"glist_add %lx %d\n", (t_int)x, (x->gl_editor ? 1 : 0));    
-	t_object *ob;
+    t_object *ob;
     y->g_next = 0;
-	int index = 0;
-
     if (!x->gl_list) x->gl_list = y;
     else
     {
         t_gobj *y2;
-        for (y2 = x->gl_list; y2->g_next; y2 = y2->g_next)
-			index++;
+        for (y2 = x->gl_list; y2->g_next; y2 = y2->g_next);
         y2->g_next = y;
     }
-    if (x->gl_editor && (ob = pd_checkobject(&y->g_pd))) {
+    if (x->gl_editor && (ob = pd_checkobject(&y->g_pd)))
         rtext_new(x, ob);
-		//let's now set up create undo
-		//glist_select(x, y);
-		//canvas_setundo(x, canvas_undo_create, canvas_undo_set_create(x, index),
-        //    "create");
-		//glist_noselect(x);
-	}
     if (x->gl_editor && x->gl_isgraph && !x->gl_goprect
         && pd_checkobject(&y->g_pd))
     {
@@ -79,86 +69,74 @@ void canvas_closebang(t_canvas *x);
     /* delete an object from a glist and free it */
 void glist_delete(t_glist *x, t_gobj *y)
 {
-	if (x->gl_list) {
-
-		t_gobj *g;
-		t_object *ob;
-		t_gotfn chkdsp = zgetfn(&y->g_pd, gensym("dsp"));
-		t_canvas *canvas = glist_getcanvas(x);
-		int drawcommand = class_isdrawcommand(y->g_pd);
-		int wasdeleting;
-
-		if (pd_class(&y->g_pd) == canvas_class) {
-		  /* JMZ: send a closebang to the canvas */
-		  canvas_closebang((t_canvas *)y);
-		}
-	 
-		wasdeleting = canvas_setdeleting(canvas, 1);
-		if (x->gl_editor)
-		{
-		    if (x->gl_editor->e_grab == y) x->gl_editor->e_grab = 0;
-		    if (glist_isselected(x, y)) glist_deselect(x, y);
-
-		        /* HACK -- we had phantom outlets not getting erased on the
-		        screen because the canvas_setdeleting() mechanism is too
-		        crude.  LATER carefully set up rules for when the rtexts
-		        should exist, so that they stay around until all the
-		        steps of becoming invisible are done.  In the meantime, just
-		        zap the inlets and outlets here... */
-		    if (pd_class(&y->g_pd) == canvas_class)
-		    {
-		        t_glist *gl = (t_glist *)y;
-		        if (gl->gl_isgraph)
-		        {
-		            char tag[80];
-		            //sprintf(tag, "graph%lx", (t_int)gl);
-					//t_glist *yy = (t_glist *)y;
-					sprintf(tag, "%s", rtext_gettag(glist_findrtext(x, &gl->gl_obj)));
-		            glist_eraseiofor(x, &gl->gl_obj, tag);
-		            text_eraseborder(&gl->gl_obj, x,
-		                rtext_gettag(glist_findrtext(x, &gl->gl_obj)));
-		        }
-		        else
-		        {
-		            text_eraseborder(&gl->gl_obj, x,
-		                rtext_gettag(glist_findrtext(x, &gl->gl_obj)));
-		        }
-		    }
-		}
-		    /* if we're a drawing command, erase all scalars now, before deleting
-		    it; we'll redraw them once it's deleted below. */
-		if (drawcommand)
-		    canvas_redrawallfortemplate(template_findbyname(canvas_makebindsym(
-		        glist_getcanvas(x)->gl_name)), 2);
-		if (glist_isvisible(canvas))
-		    gobj_vis(y, x, 0);
-		if (x->gl_editor && (ob = pd_checkobject(&y->g_pd)))
-		    rtext_new(x, ob);
-		if (x->gl_list == y) {
-			if (y->g_next)		
-				x->gl_list = y->g_next;
-			else
-				x->gl_list = NULL;
-		}
-		else for (g = x->gl_list; g; g = g->g_next)
-		{
-		    if (g->g_next == y)
-			{
-				if (y->g_next)
-				    g->g_next = y->g_next;
-				else g->g_next = NULL;
-		    	break;
-			}
-		}
-		gobj_delete(y, x);
-		pd_free(&y->g_pd);
-		if (chkdsp) canvas_update_dsp();
-		if (drawcommand)
-		    canvas_redrawallfortemplate(template_findbyname(canvas_makebindsym(
-		        glist_getcanvas(x)->gl_name)), 1);
-		canvas_setdeleting(canvas, wasdeleting);
-		x->gl_valid = ++glist_valid;
-	}
+    t_gobj *g;
+    t_object *ob;
+    t_gotfn chkdsp = zgetfn(&y->g_pd, gensym("dsp"));
+    t_canvas *canvas = glist_getcanvas(x);
+    int drawcommand = class_isdrawcommand(y->g_pd);
+    int wasdeleting;
+
+    if (pd_class(&y->g_pd) == canvas_class) {
+      /* JMZ: send a closebang to the canvas */
+      canvas_closebang((t_canvas *)y);
+    }
+ 
+    wasdeleting = canvas_setdeleting(canvas, 1);
+    if (x->gl_editor)
+    {
+        if (x->gl_editor->e_grab == y) x->gl_editor->e_grab = 0;
+        if (glist_isselected(x, y)) glist_deselect(x, y);
+
+            /* HACK -- we had phantom outlets not getting erased on the
+            screen because the canvas_setdeleting() mechanism is too
+            crude.  LATER carefully set up rules for when the rtexts
+            should exist, so that they stay around until all the
+            steps of becoming invisible are done.  In the meantime, just
+            zap the inlets and outlets here... */
+        if (pd_class(&y->g_pd) == canvas_class)
+        {
+            t_glist *gl = (t_glist *)y;
+            if (gl->gl_isgraph)
+            {
+                char tag[80];
+                //sprintf(tag, "graph%lx", (t_int)gl);
+				//t_glist *yy = (t_glist *)y;
+				sprintf(tag, "%s", rtext_gettag(glist_findrtext(x, &gl->gl_obj)));
+                glist_eraseiofor(x, &gl->gl_obj, tag);
+                text_eraseborder(&gl->gl_obj, x,
+                    rtext_gettag(glist_findrtext(x, &gl->gl_obj)));
+            }
+            else
+            {
+                text_eraseborder(&gl->gl_obj, x,
+                    rtext_gettag(glist_findrtext(x, &gl->gl_obj)));
+            }
+        }
+    }
+        /* if we're a drawing command, erase all scalars now, before deleting
+        it; we'll redraw them once it's deleted below. */
+    if (drawcommand)
+        canvas_redrawallfortemplate(template_findbyname(canvas_makebindsym(
+            glist_getcanvas(x)->gl_name)), 2);
+    if (glist_isvisible(canvas))
+        gobj_vis(y, x, 0);
+    if (x->gl_editor && (ob = pd_checkobject(&y->g_pd)))
+        rtext_new(x, ob);
+    if (x->gl_list == y) x->gl_list = y->g_next;
+    else for (g = x->gl_list; g; g = g->g_next)
+        if (g->g_next == y)
+    {
+        g->g_next = y->g_next;
+        break;
+    }
+    gobj_delete(y, x);
+    pd_free(&y->g_pd);
+    if (chkdsp) canvas_update_dsp();
+    if (drawcommand)
+        canvas_redrawallfortemplate(template_findbyname(canvas_makebindsym(
+            glist_getcanvas(x)->gl_name)), 1);
+    canvas_setdeleting(canvas, wasdeleting);
+    x->gl_valid = ++glist_valid;
 }
 
     /* remove every object from a glist.  Experimental. */
diff --git a/src/g_magicglass.c.orig b/src/g_magicglass.c.orig
new file mode 100644
index 0000000000000000000000000000000000000000..2b30e528f0f85fb844431a70fa2810fe10c83c0c
--- /dev/null
+++ b/src/g_magicglass.c.orig
@@ -0,0 +1,432 @@
+#include "m_pd.h"
+#include <stdio.h>
+#include "string.h"
+#include "m_pd.h"
+#include "m_imp.h"
+#include "s_stuff.h"
+#define MG_CLOCK_CLEAR_DELAY 500.5
+#define MG_CLOCK_FLASH_DELAY 50
+#define MG_SAMPLE_COUNT 2205
+
+EXTERN int glist_getfont(t_glist *x);
+
+t_class *magicGlass_class;
+
+typedef struct _magicGlass
+{
+    t_object x_obj;
+    t_object *x_connectedObj;
+    int x_connectedOutno;
+    int x_visible;
+    char x_string[4096];
+    char x_old_string[4096];
+    int x_x;
+    int x_y;
+    int x_c;
+    float x_sigF;
+    int x_dspOn;
+    int x_viewOn;
+    float x_maxSample;
+    int x_sampleCount;
+    t_clock *x_clearClock;
+	t_clock *x_flashClock;
+	unsigned int x_maxSize;
+	unsigned int x_issignal;
+	int x_display_font;
+} t_magicGlass;
+
+void magicGlass_clearText(t_magicGlass *x);
+
+void magicGlass_bind(t_magicGlass *x, t_object *obj, int outno)
+{
+	//fprintf(stderr,"magicglass_bind\n");
+    if (x->x_connectedObj != obj)
+    {
+        if (x->x_connectedObj)
+        {
+            obj_disconnect(x->x_connectedObj,
+                           x->x_connectedOutno,
+                           &x->x_obj,
+                           0);
+        }
+        x->x_connectedObj = obj;
+        x->x_connectedOutno = outno;
+		x->x_maxSize = 1;
+		magicGlass_clearText(x);
+        obj_connect(obj, outno, &x->x_obj, 0);
+    }
+}
+
+void magicGlass_unbind(t_magicGlass *x)
+{
+	//fprintf(stderr,"magicglass_unbind\n");
+    if (x->x_connectedObj)
+    {
+        obj_disconnect(x->x_connectedObj,
+                       x->x_connectedOutno,
+                       &x->x_obj,
+                       0);
+    }
+    x->x_dspOn = 0;
+    x->x_maxSample = -999999;
+    x->x_sampleCount = 0;
+    x->x_connectedObj = NULL;
+    x->x_connectedOutno = 0;
+	x->x_maxSize = 1;
+}
+
+void magicGlass_updateText(t_magicGlass *x, int moved)
+{
+	//fprintf(stderr,"magicglass_updateText\n");
+    int bgSize;
+	/* change second argument (10.0) to provide optimal scaling in the following entry */
+	float font = (float)(sys_hostfontsize(glist_getfont((t_glist *)(x->x_c))))/10.0;
+	if (font <= 1.0) {
+		x->x_display_font = 9;
+		font = 1.0;
+	} else {
+		x->x_display_font = sys_hostfontsize(glist_getfont((t_glist *)(x->x_c)));
+	}
+
+    if (x->x_visible)
+    {
+		if (!moved) {
+			char *color;
+			if (x->x_issignal || strcmp(x->x_old_string, x->x_string)) {
+				color = "#ffffff";
+			}
+			else {
+				color = "#e87216";
+				clock_delay(x->x_flashClock, MG_CLOCK_FLASH_DELAY);
+			}
+		    sys_vgui(".x%x.c itemconfigure magicGlassText -text {%s} -fill %s\n",
+		            x->x_c,
+		            x->x_string,
+					color);
+		} else {
+		    sys_vgui(".x%x.c itemconfigure magicGlassText -text {%s}\n",
+		            x->x_c,
+		            x->x_string);
+		}
+
+        if (strlen(x->x_string) > 0)
+        {
+			if (strlen(x->x_string) > x->x_maxSize) x->x_maxSize = strlen(x->x_string);
+        }
+		bgSize = x->x_x + (int)((30.0 * font) + ((font * 7.0) * (float)x->x_maxSize));
+        sys_vgui(".x%x.c coords magicGlassText %d %d\n",
+                 x->x_c,
+                 x->x_x + 20,
+                 x->x_y);
+        sys_vgui(".x%x.c coords magicGlassLine %d %d %d %d %d %d\n",
+                 x->x_c,
+                 x->x_x + 3,
+                 x->x_y,
+                 x->x_x + 13,
+                 x->x_y + 5,
+                 x->x_x + 13,
+                 x->x_y - 5);
+        sys_vgui(".x%x.c coords magicGlassBg %d %d %d %d\n",
+                 x->x_c,
+                 x->x_x + 13,
+                 x->x_y - (int)(12.0 * font),
+                 bgSize,
+                 x->x_y + (int)(12.0 * font));
+    }
+}
+
+void magicGlass_drawNew(t_magicGlass *x)
+{
+	//fprintf(stderr,"magicglass_drawNew\n");
+    sys_vgui(".x%x.c create rectangle 0 0 0 0 -outline #ffffff -fill #000000 -tags magicGlassBg\n",
+             x->x_c);
+    sys_vgui(".x%x.c create polygon 0 0 0 0 0 0 -fill #000000 -width 4 -tags magicGlassLine\n",
+             x->x_c);
+    sys_vgui(".x%x.c create text 0 0 -text {} -anchor w -fill #e87216 -font {{%s} %d %s} -tags magicGlassText\n",
+             x->x_c, sys_font, x->x_display_font, sys_fontweight);
+    sys_vgui(".x%x.c raise magicGlassBg\n",
+             x->x_c);
+    sys_vgui(".x%x.c raise magicGlassText\n",
+             x->x_c);
+    magicGlass_updateText(x, 0);
+	clock_delay(x->x_flashClock, MG_CLOCK_FLASH_DELAY);
+}
+
+void magicGlass_undraw(t_magicGlass *x)
+{
+	//fprintf(stderr,"magicglass_undraw\n");
+    sys_vgui(".x%x.c delete magicGlassBg\n", x->x_c);
+    sys_vgui(".x%x.c delete magicGlassLine\n", x->x_c);
+    sys_vgui(".x%x.c delete magicGlassText\n", x->x_c);
+}
+
+void magicGlass_flashText(t_magicGlass *x)
+{
+	//fprintf(stderr,"magicglass_flashText\n");
+    sys_vgui(".x%x.c itemconfigure magicGlassText -fill #ffffff\n",
+         x->x_c);
+}
+
+void magicGlass_clearText(t_magicGlass *x)
+{
+	//fprintf(stderr,"magicglass_clearText\n");
+	strcpy(x->x_old_string, x->x_string);
+    x->x_string[0] = 0;
+    magicGlass_updateText(x, 0);
+}
+
+void magicGlass_bang(t_magicGlass *x) 
+{
+	x->x_issignal = 0;
+	strcpy(x->x_old_string, x->x_string);
+    strcpy(x->x_string, "bang");
+    magicGlass_updateText(x, 0);
+    clock_delay(x->x_clearClock, MG_CLOCK_CLEAR_DELAY);
+}
+
+void magicGlass_float(t_magicGlass *x, t_float f) 
+{
+	x->x_issignal = 0;
+	strcpy(x->x_old_string, x->x_string);
+    sprintf(x->x_string, "%g", f);
+    magicGlass_updateText(x, 0);
+    clock_delay(x->x_clearClock, MG_CLOCK_CLEAR_DELAY);
+}
+
+void magicGlass_symbol(t_magicGlass *x, t_symbol *sym)
+{
+	x->x_issignal = 0;
+	strcpy(x->x_old_string, x->x_string);
+    sprintf(x->x_string, "symbol %s", sym->s_name);
+    magicGlass_updateText(x, 0);
+    clock_delay(x->x_clearClock, MG_CLOCK_CLEAR_DELAY);
+}
+
+void magicGlass_anything(t_magicGlass *x, t_symbol *sym, int argc, t_atom *argv)
+{
+    char aString[4096];
+    char valueString[4096];
+    int i;
+
+	x->x_issignal = 0;
+
+	strcpy(x->x_old_string, x->x_string);
+    strcpy(aString, sym->s_name);
+    valueString[0] = 0;
+    for (i = 0; i < argc; i++)
+    {
+        if (argv[i].a_type == A_SYMBOL)
+        {
+            sprintf(valueString, " %s", argv[i].a_w.w_symbol->s_name);
+            strcat(aString, valueString);
+        }
+        else if (argv[i].a_type == A_FLOAT)
+        {
+            sprintf(valueString, " %g", argv[i].a_w.w_float);
+            strcat(aString, valueString);
+        }
+    }
+    strcpy(x->x_string, aString);
+    magicGlass_updateText(x, 0);
+    clock_delay(x->x_clearClock, MG_CLOCK_CLEAR_DELAY);
+}
+
+void magicGlass_list(t_magicGlass *x, t_symbol *sym, int argc, t_atom *argv)
+{
+    char aString[4096];
+    char valueString[4096];
+    int i;
+
+	x->x_issignal = 0;
+
+    aString[0] = 0;
+    valueString[0] = 0;
+
+	strcpy(x->x_old_string, x->x_string);
+	strcpy(aString, sym->s_name);
+    for (i = 0; i < argc; i++)
+    {
+        if (argv[i].a_type == A_SYMBOL)
+        {
+            sprintf(valueString, " %s", argv[i].a_w.w_symbol->s_name);
+            strcat(aString, valueString);
+        }
+        else if (argv[i].a_type == A_FLOAT)
+        {
+            sprintf(valueString, " %g", argv[i].a_w.w_float);
+            strcat(aString, valueString);
+        }
+    }
+    strcpy(x->x_string, aString);
+    magicGlass_updateText(x, 0);
+    clock_delay(x->x_clearClock, MG_CLOCK_CLEAR_DELAY);
+}
+
+void magicGlass_setCanvas(t_magicGlass *x, int c)
+{
+    x->x_c = c;
+}
+
+void magicGlass_show(t_magicGlass *x)
+{
+	//fprintf(stderr,"magicglass_show\n");
+    if (!x->x_visible) {
+		x->x_sampleCount = 0;
+		x->x_maxSample = -999999;
+		x->x_string[0] = 0;
+        x->x_visible = 1;
+        magicGlass_drawNew(x);
+    }
+}
+
+void magicGlass_hide(t_magicGlass *x)
+{
+	//fprintf(stderr,"magicglass_hide\n");
+    if (x->x_visible) {
+        magicGlass_undraw(x);
+		x->x_sampleCount = 0;
+		x->x_maxSample = -999999;
+		x->x_string[0] = 0;
+		x->x_visible = 0;
+	}
+}
+
+void magicGlass_moveText(t_magicGlass *x, int pX, int pY)
+{
+	//fprintf(stderr,"magicglass_moveText\n");
+    int bgSize;
+    
+    x->x_x = pX;
+    x->x_y = pY;
+    magicGlass_updateText(x, 1);
+}
+
+int magicGlass_bound(t_magicGlass *x)
+{
+	//fprintf(stderr,"magicglass_bound\n");
+    if (x->x_connectedObj)
+        return 1;
+    else
+        return 0;
+}
+
+int magicGlass_isOn(t_magicGlass *x)
+{
+	//fprintf(stderr,"magicglass_isOn\n");
+    if (x->x_viewOn)
+        return 1;
+    else
+        return 0;
+}
+
+void magicGlass_setOn(t_magicGlass *x, int i)
+{
+	//fprintf(stderr,"magicglass_setOn\n");
+    if (i)
+    {
+        x->x_viewOn = 1;
+    }
+    else
+    {
+        x->x_viewOn = 0;
+    }
+}
+
+void magicGlass_setDsp(t_magicGlass *x, int i)
+{
+	//fprintf(stderr,"magicglass_setDsp\n");
+	if (i != x->x_dspOn) {
+		if (i)
+		{
+		    x->x_dspOn = 1;
+		    x->x_sampleCount = 0;
+		    x->x_maxSample = -999999;
+		}
+		else
+		{
+		    x->x_dspOn = 0;
+		}
+	}
+}
+
+t_int *magicGlass_perform(t_int *w)
+{
+    t_magicGlass *x = (t_magicGlass *)(w[1]);
+    if (x->x_dspOn && x->x_connectedObj)
+    {
+		//fprintf(stderr,"magicglass_perform\n");
+		float *in = (float *)(w[2]);
+		int N = (int)(w[3]);
+		int i;
+        for (i = 0; i < N; i++)
+        {
+            if (in[i] > x->x_maxSample)
+                x->x_maxSample = in[i];
+            x->x_sampleCount++;
+            if (x->x_sampleCount >= MG_SAMPLE_COUNT)
+            {
+                sprintf(x->x_string, "~ %g", x->x_maxSample);
+                magicGlass_updateText(x, 0);
+                x->x_maxSample = -999999;
+                x->x_sampleCount = 0;
+            }
+        }
+    }
+    return (w + 4);
+}
+
+void magicGlass_dsp(t_magicGlass *x, t_signal **sp)
+{
+	//fprintf(stderr,"magicglass_dsp\n");
+    dsp_add(magicGlass_perform, 3, x, sp[0]->s_vec, sp[0]->s_n);
+	x->x_issignal = 1;
+}
+
+void *magicGlass_new(int c)
+{
+	//fprintf(stderr,"magicglass_new\n");
+    t_magicGlass *x = (t_magicGlass *)pd_new(magicGlass_class);
+    x->x_connectedObj= NULL;
+    x->x_connectedOutno = 0;
+    x->x_visible = 0;
+    x->x_c = c;
+    x->x_sigF = 0;
+    x->x_dspOn = 0;
+    x->x_viewOn = 0;
+    x->x_maxSample = -999999;
+    x->x_sampleCount = 0;
+    x->x_clearClock = clock_new(x, (t_method)magicGlass_clearText);
+    x->x_flashClock = clock_new(x, (t_method)magicGlass_flashText);
+	x->x_maxSize = 1;
+	x->x_issignal = 0;
+	x->x_display_font = 9;
+    return x;
+}
+
+void magicGlass_free(t_magicGlass *x)
+{
+	//fprintf(stderr,"magicglass_free\n");
+    x->x_dspOn = 0;
+    clock_free(x->x_clearClock);
+}
+
+void magicGlass_setup(void)
+{
+    magicGlass_class = class_new(gensym("magicGlass"),
+                                 0,
+                                 (t_method)magicGlass_free,
+                                 sizeof(t_magicGlass),
+                                 0,
+                                 A_DEFFLOAT,
+                                 0);
+    CLASS_MAINSIGNALIN(magicGlass_class, t_magicGlass, x_sigF);
+    class_addmethod(magicGlass_class,
+      	            (t_method)magicGlass_dsp,
+	            gensym("dsp"),
+	            0);
+    class_addbang(magicGlass_class, (t_method)magicGlass_bang);
+    class_addfloat(magicGlass_class, (t_method)magicGlass_float);
+    class_addsymbol(magicGlass_class, (t_method)magicGlass_symbol);
+    class_addanything(magicGlass_class, (t_method)magicGlass_anything);
+    class_addlist(magicGlass_class, (t_method)magicGlass_list);
+}
diff --git a/src/g_magicglass.h.orig b/src/g_magicglass.h.orig
new file mode 100644
index 0000000000000000000000000000000000000000..b6a80fd2a5f7ba47ac203632b3296ab8c54f0ff1
--- /dev/null
+++ b/src/g_magicglass.h.orig
@@ -0,0 +1,19 @@
+EXTERN void magicGlass_bind(t_magicGlass *x, t_object *obj, int outno);
+EXTERN void magicGlass_unbind(t_magicGlass *x);
+EXTERN void magicGlass_bang(t_magicGlass *x); 
+EXTERN void magicGlass_float(t_magicGlass *x, t_float f); 
+EXTERN void magicGlass_symbol(t_magicGlass *x, t_symbol *sym);
+EXTERN void magicGlass_anything(t_magicGlass *x, t_symbol *sym, int argc, t_atom *argv);
+EXTERN void magicGlass_list(t_magicGlass *x, t_symbol *sym, int argc, t_atom *argv);
+EXTERN void magicGlass_setCanvas(t_magicGlass *x, int c);
+EXTERN void magicGlass_show(t_magicGlass *x);
+EXTERN void magicGlass_hide(t_magicGlass *x);
+EXTERN void magicGlass_moveText(t_magicGlass *x, int pX, int pY);
+EXTERN int magicGlass_bound(t_magicGlass *x);
+EXTERN int magicGlass_isOn(t_magicGlass *x);
+EXTERN void magicGlass_setOn(t_magicGlass *x, int i);
+EXTERN void magicGlass_setDsp(t_magicGlass *x, int i);
+EXTERN void *magicGlass_new(int c);
+EXTERN void magicGlass_free(t_magicGlass *x);
+EXTERN void magicGlass_setup(void);
+
diff --git a/src/g_rtext.c b/src/g_rtext.c
index a8efb11d29a87490c21769ce3f2bc1876afc9631..163615161198b0abf804b53afa4cdf0227a7b73c 100644
--- a/src/g_rtext.c
+++ b/src/g_rtext.c
@@ -358,9 +358,8 @@ t_rtext *glist_findrtext(t_glist *gl, t_text *who)
     t_rtext *x;
     if (!gl->gl_editor)
         canvas_create_editor(gl);
-	if (gl->gl_editor->e_rtext)
-	    for (x = gl->gl_editor->e_rtext; x && x->x_text != who; x = x->x_next)
-    	    ;
+    for (x = gl->gl_editor->e_rtext; x && x->x_text != who; x = x->x_next)
+        ;
     if (!x) bug("glist_findrtext");
     return (x);
 }
diff --git a/src/g_text.c b/src/g_text.c
index 104fa3d1cc25598151d0fb3dbb3e5dea4a669415..0ff6a3980e6c0aa3f06484f6916fabc791319e08 100644
--- a/src/g_text.c
+++ b/src/g_text.c
@@ -30,10 +30,7 @@ t_widgetbehavior text_widgetbehavior;
 
 static char *invalid_fill = "\"#ffdddd\"";
 
-extern void canvas_apply_setundo(t_canvas *x, t_gobj *y);
-extern void canvas_setundo(t_canvas *x, t_undofn undofn, void *buf, const char *name);
-extern void *canvas_undo_set_create(t_canvas *x);
-extern void canvas_undo_create(t_canvas *x, void *z, int action);
+EXTERN void canvas_apply_setundo(t_canvas *x, t_gobj *y);
 
 /* ----------------- the "text" object.  ------------------ */
 
@@ -92,7 +89,7 @@ void canvas_getargs(int *argcp, t_atom **argvp);
 static void canvas_objtext(t_glist *gl, int xpix, int ypix, int selected,
     t_binbuf *b)
 {
-	//fprintf(stderr,"canvas_objtext\n");
+	//fprintf(stderr,"objtext\n");
     t_text *x;
     int argc;
     t_atom *argv;
@@ -205,7 +202,6 @@ void canvas_howputnew(t_canvas *x, int *connectp, int *xpixp, int *ypixp,
 
 void canvas_obj(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
 {
-	//fprintf(stderr,"canvas_obj\n");
     t_text *x;
     if (argc >= 2)
     {
@@ -228,7 +224,6 @@ void canvas_obj(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
         if (connectme)
             canvas_connect(gl, indx, 0, nobj, 0);
         else canvas_startmotion(glist_getcanvas(gl));
-		canvas_setundo(glist_getcanvas(gl), canvas_undo_create, canvas_undo_set_create(gl), "create");
     }
 }
 
@@ -270,7 +265,6 @@ void canvas_iemguis(t_glist *gl, t_symbol *guiobjname)
     //glist_getnextxy(gl, &xpix, &ypix);
     //canvas_objtext(gl, xpix, ypix, 1, b);
     else canvas_startmotion(glist_getcanvas(gl));
-	canvas_setundo(glist_getcanvas(gl), canvas_undo_create, canvas_undo_set_create(gl), "create");
 }
 
 void canvas_bng(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
@@ -541,7 +535,6 @@ void canvas_msg(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
         if (connectme)
             canvas_connect(gl, indx, 0, nobj, 0);
         else canvas_startmotion(glist_getcanvas(gl));
-		canvas_setundo(glist_getcanvas(gl), canvas_undo_create, canvas_undo_set_create(gl), "create");
     }
 }
 
@@ -928,7 +921,6 @@ static void gatom_vis(t_gobj *z, t_glist *glist, int vis)
 void canvas_atom(t_glist *gl, t_atomtype type,
     t_symbol *s, int argc, t_atom *argv)
 {
-	//fprintf(stderr,"canvas_atom\n");
     t_gatom *x = (t_gatom *)pd_new(gatom_class);
     t_atom at;
     x->a_text.te_width = 0;                        /* don't know it yet. */
@@ -1001,7 +993,6 @@ void canvas_atom(t_glist *gl, t_atomtype type,
         if (connectme)
             canvas_connect(gl, indx, 0, nobj, 0);
         else canvas_startmotion(glist_getcanvas(gl));
-		canvas_setundo(glist_getcanvas(gl), canvas_undo_create, canvas_undo_set_create(gl), "create");
     }
 }
 
diff --git a/src/m_binbuf.c b/src/m_binbuf.c
index 6c7a8af943ad426601c081465b72df21a5e66c6f..d39e18821e5532bab424439f94fb40f5a98e680c 100644
--- a/src/m_binbuf.c
+++ b/src/m_binbuf.c
@@ -39,7 +39,6 @@ void binbuf_free(t_binbuf *x)
 {
     t_freebytes(x->b_vec, x->b_n * sizeof(*x->b_vec));
     t_freebytes(x,  sizeof(*x));
-	x = NULL;
 }
 
 t_binbuf *binbuf_duplicate(t_binbuf *y)
@@ -60,7 +59,6 @@ void binbuf_clear(t_binbuf *x)
     /* convert text to a binbuf */
 void binbuf_text(t_binbuf *x, char *text, size_t size)
 {
-	//fprintf(stderr, "current text: %s || %c %d %d\n", text, text[size-1], strlen(text), (int)size);
     char buf[MAXPDSTRING+1], *bufp, *ebuf = buf+MAXPDSTRING;
     const char *textp = text, *etext = text+size;
     t_atom *ap;
@@ -387,7 +385,6 @@ void binbuf_addsemi(t_binbuf *x)
     t_atom a;
     SETSEMI(&a);
     binbuf_add(x, 1, &a);
-    binbuf_add(x, 1, '\0');
 }
 
 /* Supply atoms to a binbuf from a message, making the opposite changes
diff --git a/src/m_class.c b/src/m_class.c
index 1dd0c9f9e783cba28ea310760c9cfdcf497790e9..abb9561cce6b0ca8f7e416d0cc8fe83867cc78d6 100644
--- a/src/m_class.c
+++ b/src/m_class.c
@@ -708,8 +708,8 @@ void pd_typedmess(t_pd *x, t_symbol *s, int argc, t_atom *argv)
         return;
     }
     for (i = c->c_nmethod, m = c->c_methods; i--; m++)
-        //if (m->me_name == s)
-		if (m && m->me_name == s)
+        if (m->me_name == s)
+		//if (m && m->me_name == s)
     {
 		//fprintf(stderr,"me_name %s\n", m->me_name);
         wp = m->me_arg;
diff --git a/src/m_obj.c b/src/m_obj.c
index 393b159628c0e07ee0be3a3d8d576e7d611d4790..71166aca4a9b18f90915f76de7939ce75f9f751c 100644
--- a/src/m_obj.c
+++ b/src/m_obj.c
@@ -554,11 +554,10 @@ done:
 
 int obj_noutlets(t_object *x)
 {
-    int n = 0;
+    int n;
     t_outlet *o;
-	if (x && x->ob_outlet)
-	    for (o = x->ob_outlet, n = 0; o; o = o->o_next) n++;
-   	return (n);
+    for (o = x->ob_outlet, n = 0; o; o = o->o_next) n++;
+    return (n);
 }
 
 int obj_ninlets(t_object *x)
diff --git a/src/m_pd.h b/src/m_pd.h
index 8fc774716c759dfbf9fcc86da68e726b9530dbed..81e440765d42f4d063ba8c4a6baf3671c3d99e45 100644
--- a/src/m_pd.h
+++ b/src/m_pd.h
@@ -11,7 +11,7 @@ extern "C" {
 #define PD_MAJOR_VERSION 0
 #define PD_MINOR_VERSION 42
 #define PD_BUGFIX_VERSION 5
-#define PD_TEST_VERSION "extended-l2ork-20111025"
+#define PD_TEST_VERSION "extended-l2ork-20110920"
 
 /* old name for "MSW" flag -- we have to take it for the sake of many old
 "nmakefiles" for externs, which will define NT and not MSW */
diff --git a/src/main.pd b/src/main.pd
new file mode 100644
index 0000000000000000000000000000000000000000..2c0dccfdc79df0c0de7d118efb435a94c688b6bc
--- /dev/null
+++ b/src/main.pd
@@ -0,0 +1,7 @@
+#N canvas 718 319 450 300 10;
+#X floatatom 152 85 5 0 0 0 - - -;
+#N canvas 473 357 450 300 something 0;
+#X floatatom 126 128 5 0 0 0 - - -;
+#X coords 0 -1 1 1 85 60 1 100 100;
+#X restore 232 145 pd something;
+#X obj 235 244;
diff --git a/src/makefile b/src/makefile
deleted file mode 100644
index 3ebb96a298798ac94cae5d8d5c811aa08e72bbb8..0000000000000000000000000000000000000000
--- a/src/makefile
+++ /dev/null
@@ -1,311 +0,0 @@
-# On Mac OS X, this needs to be defined to enable dlopen and weak linking
-# support.  Its safe on other platforms since gcc only checks this env var on
-# Apple's gcc.  <hans@at.or.at>
-ifeq ($(shell uname -s),Darwin)
-export MACOSX_DEPLOYMENT_TARGET = 10.3
-endif
-
-VPATH = ../obj:./
-OBJ_DIR = ../obj
-BIN_DIR = ../bin
-PDEXEC = $(BIN_DIR)/pd-l2ork
-EXT= pd_linux
-GUINAME= pd-gui
-
-prefix = /usr/local
-exec_prefix = ${prefix}
-bindir = ${exec_prefix}/bin
-includedir = ${prefix}/include
-libdir = ${exec_prefix}/lib
-mandir = ${prefix}/share/man
-
-GFLAGS = -DINSTALL_PREFIX=\"$(prefix)\"
-
-# varibles to match packages/Makefile.buildlayout so that they can be easily
-# overridden when building Pd-extended builds. <hans@at.or.at>
-libpddir = $(libdir)/pd-l2ork
-pddocdir = $(libpddir)/doc
-libpdbindir = $(libpddir)/bin
-
-CPPFLAGS = -DDL_OPEN -DPA_USE_OSS -DUNIX -DUNISTD        -DUSEAPI_OSS         -fno-strict-aliasing -DPA_USE_ALSA -DUSEAPI_ALSA
-MORECFLAGS =  -O6 -funroll-loops -fomit-frame-pointer -DUSEAPI_JACK -D_LARGEFILE64_SOURCE
-# if on 10.6/Intel, then build GUI as 32-bit
-ifeq ($(shell uname -r | sed 's|\([0-9][0-9]*\)\.[0-9][0-9]*\.[0-9][0-9]*|\1|'), 10)
-  GINCLUDE = -arch i386 $(CPPFLAGS) -framework Tcl -framework Tk
-else
-  GINCLUDE = $(CPPFLAGS)  -I/usr/include/tcl8.5
-endif
-GLIB = -ltk8.5 -ltcl8.5  -lrt -ljack -ljack
-
-LDFLAGS = -Wl,-export-dynamic -lasound -lrt -ljack
-LIB =   -ldl -lm -lpthread -lasound
-
-WARN_CFLAGS = -Wall -W -Wstrict-prototypes \
-    -Wno-unused -Wno-parentheses -Wno-switch
-ARCH_CFLAGS = -DPD 
-
-CFLAGS = -g -O2 $(ARCH_CFLAGS) $(WARN_CFLAGS) $(CPPFLAGS) $(MORECFLAGS)
-
-# the sources
-
-SYSSRC += s_midi_oss.c s_audio_oss.c s_audio_alsa.c s_audio_alsamm.c s_midi_alsa.c s_audio_jack.c d_fft_mayer.c d_fftroutine.c
-
-ASIOSRC = 
-
-ASIOOBJ = $(ASIOSRC:.cpp=.o)
-
-# these files cause a warning when using auto-vectorization:
-# "warning: dereferencing type-punned pointer will break strict-aliasing rules"
-TYPE_PUNNING_SRC = d_ctl.c d_array.c d_delay.c d_filter.c d_math.c d_osc.c d_soundfile.c
-
-# these are safe for full gcc 4.x optimization
-OPT_SAFE_SRC = g_canvas.c g_graph.c g_text.c g_rtext.c g_array.c g_template.c g_io.c \
-    g_scalar.c g_traversal.c g_guiconnect.c g_readwrite.c g_editor.c \
-    g_all_guis.c g_bang.c g_hdial.c g_hslider.c g_mycanvas.c g_numbox.c \
-    g_toggle.c g_vdial.c g_vslider.c g_vumeter.c g_magicglass.c \
-    m_pd.c m_class.c m_obj.c m_atom.c m_memory.c m_binbuf.c \
-    m_conf.c m_glob.c m_sched.c \
-    s_main.c s_inter.c s_file.c s_print.c \
-    s_loader.c s_path.c s_entry.c s_audio.c s_midi.c \
-    d_ugen.c d_arithmetic.c d_dac.c d_misc.c \
-    d_fft.c d_global.c \
-    d_resample.c \
-    x_arithmetic.c x_connective.c x_interface.c x_midi.c x_misc.c \
-    x_time.c x_acoustics.c x_net.c x_qlist.c x_gui.c x_list.c \
-	import.c \
-    $(SYSSRC)
-
-SRC = $(TYPE_PUNNING_SRC) $(OPT_SAFE_SRC)
-
-TYPE_PUNNING_OBJ = $(TYPE_PUNNING_SRC:.c=.o) 
-OPT_SAFE_OBJ = $(OPT_SAFE_SRC:.c=.o) 
-OBJ = $(SRC:.c=.o) 
-
-GSRC =  t_main.c t_tkcmd.c
-
-GOBJ = $(GSRC:.c=.o)
-
-# get version from m_pd.h to use in doc/1.manual/1.introduction.txt
-PD_MAJOR_VERSION := $(shell grep PD_MAJOR_VERSION m_pd.h | \
-	sed 's|^.define *PD_MAJOR_VERSION *\([0-9]*\).*|\1|' )
-PD_MINOR_VERSION := $(shell grep PD_MINOR_VERSION m_pd.h | \
-	sed 's|^.define *PD_MINOR_VERSION *\([0-9]*\).*|\1|' )
-PD_BUGFIX_VERSION := $(shell grep PD_BUGFIX_VERSION m_pd.h | \
-	sed 's|^.define *PD_BUGFIX_VERSION *\([0-9]*\).*|\1|' )
-PD_TEST_VERSION := $(shell grep PD_TEST_VERSION m_pd.h | \
-	sed 's|^.define *PD_TEST_VERSION *"\(.*\)".*|\1|' )
-PD_VERSION := $(PD_MAJOR_VERSION).$(PD_MINOR_VERSION).$(PD_BUGFIX_VERSION)
-ifneq ($(PD_TEST_VERSION),)
-	PD_VERSION := $(PD_VERSION)-$(PD_TEST_VERSION)
-endif
-
-#
-#  ------------------ targets ------------------------------------
-#
-
-.PHONY: pd gui externs all
-
-all: pd $(BIN_DIR)/pd-watchdog gui $(BIN_DIR)/pdsend \
-    $(BIN_DIR)/pdreceive externs
-
-bin: pd $(BIN_DIR)/pd-watchdog gui $(BIN_DIR)/pdsend \
-    $(BIN_DIR)/pdreceive
-
-$(OPT_SAFE_OBJ) : %.o : %.c
-	$(CC) $(CFLAGS) $(OPT_CFLAGS) $(GFLAGS) $(INCLUDE) -c -o $(OBJ_DIR)/$*.o $*.c 
-
-$(TYPE_PUNNING_OBJ) : %.o : %.c
-	$(CC) $(CFLAGS) $(GFLAGS) $(INCLUDE) -c -o $(OBJ_DIR)/$*.o $*.c 
-
-$(GOBJ) : %.o : %.c
-	$(CC) $(CFLAGS) $(GFLAGS) $(GINCLUDE) -c -o $(OBJ_DIR)/$*.o $*.c 
-
-$(ASIOOBJ): %.o : %.cpp
-	$(CXX) $(CFLAGS) $(INCLUDE) -c -o $(OBJ_DIR)/$*.o $*.cpp
-
-pd: $(PDEXEC)
-
-ifneq ($(GSRC),)
-gui: $(BIN_DIR)/$(GUINAME)
-else
-gui:
-endif
-
-pd-watchdog: $(BIN_DIR)/pd-watchdog
-
-$(BIN_DIR):
-	test -d $(BIN_DIR) || mkdir -p $(BIN_DIR)
-
-$(BIN_DIR)/pd-watchdog: s_watchdog.c $(BIN_DIR)
-	$(CC) $(CFLAGS) $(STRIPFLAG) -o $(BIN_DIR)/pd-watchdog s_watchdog.c
-
-$(BIN_DIR)/pdsend: u_pdsend.c $(BIN_DIR)
-	$(CC) $(CFLAGS)  $(STRIPFLAG) -o $(BIN_DIR)/pdsend u_pdsend.c
-
-$(BIN_DIR)/pdreceive: u_pdreceive.c $(BIN_DIR)
-	$(CC) $(CFLAGS)  $(STRIPFLAG) -o $(BIN_DIR)/pdreceive u_pdreceive.c
-
-$(PDEXEC): $(OBJ) $(BIN_DIR)
-	cd ../obj;  $(CC) $(LDFLAGS) $(DBG_CFLAGS) -o $(PDEXEC) $(OBJ) $(LIB)
-
-$(BIN_DIR)/pd-gui: $(GOBJ) $(GSRC)
-	cd ../obj; $(CC) $(INCLUDE) -o $(BIN_DIR)/$(GUINAME) $(GOBJ) $(GLIB)
-
-# if on 10.6/Intel, then force build GUI as 32-bit
-ifeq ($(shell uname -r | sed 's|\([0-9][0-9]*\)\.[0-9][0-9]*\.[0-9][0-9]*|\1|'), 10)
-  ARCH_FLAG = -arch i386
-else
-  ARCH_FLAG = 
-endif
-#this is for Max OSX only...
-$(BIN_DIR)/libPdTcl.dylib: $(GOBJ) $(GSRC)
-	cd ../obj && $(CC) $(ARCH_FLAG) $(CFLAGS) -dynamiclib -read_only_relocs warning  \
-		-o $(BIN_DIR)/libPdTcl.dylib $(GOBJ)  \
-		-F \
-		-framework Tcl  -framework Tk  -framework System  \
-		-Wl,-install_name,@executable_path/../Resources/bin/libPdTcl.dylib
-	install_name_tool -change /Tcl.framework/Versions/8.4/Tcl\
-		 @executable_path/../Frameworks/Tcl.framework/Versions/8.4/Tcl \
-		 -change /Tk.framework/Versions/8.4/Tk \
-		 @executable_path/../Frameworks/Tk.framework/Versions/8.4/Tk \
-		../bin/libPdTcl.dylib
-
-# this is for Windows/MinGW (only?)
-$(BIN_DIR)/pdtcl.dll: $(GOBJ)
-	cd $(BIN_DIR); dllwrap --export-all-symbols --output-def pdtcl.def \
-	--output-lib=pdtcl.a --dllname=$(GUINAME) $(OBJ_DIR)/t_tkcmd.o $(LIB) $(GLIB)
-	strip --strip-unneeded $(BIN_DIR)/pdtcl.dll
-
-externs: 
-	make -C ../extra/bonk~    
-	make -C ../extra/choice   
-	make -C ../extra/expr~    
-	make -C ../extra/fiddle~  
-	make -C ../extra/loop~    
-	make -C ../extra/lrshift~ 
-	make -C ../extra/pique    
-	make -C ../extra/sigmund~ 
-	make -C ../extra/pd~      
-	make -C ../extra/stdout   
-
-BINARYMODE=-m755
-
-ABOUT_FILE=$(DESTDIR)$(pddocdir)/1.manual/1.introduction.txt
-install:  all
-	install -d $(DESTDIR)$(libpdbindir)
-	install $(BIN_DIR)/$(GUINAME) $(DESTDIR)$(libpdbindir)/$(GUINAME)
-	install $(BIN_DIR)/pd-watchdog $(DESTDIR)$(libpdbindir)/pd-watchdog
-	install -m644 pd.tk $(DESTDIR)$(libpdbindir)/pd.tk
-	install -m644 pkgIndex.tcl $(DESTDIR)$(libpdbindir)/pkgIndex.tcl
-	install -m644 helpbrowser.tcl $(DESTDIR)$(libpdbindir)/helpbrowser.tcl
-	install -d $(DESTDIR)$(bindir)
-	install $(BINARYMODE) $(PDEXEC) $(DESTDIR)$(bindir)/pd-l2ork
-# kludge to allow pd~ to work by default in pd-l2ork
-	rm -f $(DESTDIR)$(libpddir)/pd
-	ln -s $(bindir)/pd-l2ork $(DESTDIR)$(libpddir)/pd
-	install -m755 $(BIN_DIR)/pdsend $(DESTDIR)$(bindir)/pdsend
-	install -m755 $(BIN_DIR)/pdreceive $(DESTDIR)$(bindir)/pdreceive 
-	for dir in $(shell ls -1 ../doc | grep -v CVS); do \
-		echo "installing $$dir"; \
-		install -d $(DESTDIR)$(pddocdir)/$$dir ; \
-		install -m644 -p ../doc/$$dir/*.* $(DESTDIR)$(pddocdir)/$$dir ; \
-	done
-	for dir in $(shell ls -1 ../doc/7.stuff | grep -v CVS); do \
-		echo "installing 7.stuff/$$dir"; \
-		install -d $(DESTDIR)$(pddocdir)/7.stuff/$$dir ; \
-		install -m644 -p ../doc/7.stuff/$$dir/*.* \
-                    $(DESTDIR)$(pddocdir)/7.stuff/$$dir ; \
-	done
-	mv $(ABOUT_FILE) $(ABOUT_FILE).tmp
-	cat $(ABOUT_FILE).tmp | sed 's|PD_VERSION|Pd version $(PD_VERSION)|' \
-		> $(ABOUT_FILE)
-	rm $(ABOUT_FILE).tmp
-	rsync -ax --exclude=.git --exclude=.svn ../extra $(DESTDIR)$(libpddir)/
-	install -d $(DESTDIR)$(includedir)/pdl2ork
-	install -m644 m_pd.h $(DESTDIR)$(includedir)/pdl2ork/m_pd.h
-	install -m644 m_imp.h $(DESTDIR)$(includedir)/pdl2ork/m_imp.h
-	install -m644 g_canvas.h $(DESTDIR)$(includedir)/pdl2ork/g_canvas.h
-	install -m644 s_stuff.h $(DESTDIR)$(includedir)/pdl2ork/s_stuff.h
-	install -m644 g_all_guis.h $(DESTDIR)$(includedir)/pdl2ork/g_all_guis.h
-	install -d $(DESTDIR)$(mandir)/man1
-	gzip < ../man/pd.1 >  $(DESTDIR)$(mandir)/man1/pd-l2ork.1.gz
-	chmod 644 $(DESTDIR)$(mandir)/man1/pd-l2ork.1.gz
-	gzip < ../man/pdsend.1 >  $(DESTDIR)$(mandir)/man1/pdsend.1.gz
-	chmod 644 $(DESTDIR)$(mandir)/man1/pdsend.1.gz
-	gzip < ../man/pdreceive.1 >  $(DESTDIR)$(mandir)/man1/pdreceive.1.gz
-	chmod 644 $(DESTDIR)$(mandir)/man1/pdreceive.1.gz
-	@echo "Pd install succeeded."
-
-local-clean:	
-	-rm -f -- $(OBJ)
-	-rm -f ../obj/* $(PDEXEC) $(BIN_DIR)/$(GUINAME) $(BIN_DIR)/pdsend \
-	    $(BIN_DIR)/pdreceive $(BIN_DIR)/pd-watchdog m_stamp.c
-	-rm -f -- *~
-	-(cd ../doc/6.externs; rm -f *.pd_linux)
-	-rm -f makefile.dependencies
-	touch makefile.dependencies
-	chmod 666 makefile.dependencies
-
-extra-clean:
-	-rm -f `find ../extra/ -name "*.pd_*"`
-	-rm -f tags
-
-clean: extra-clean local-clean
-
-distclean: clean
-	-rm -f config.cache config.log config.status makefile tags \
-		autom4te.cache/output.* autom4te.cache/traces.* autom4te.cache/requests
-	-rmdir autom4te.cache
-	-rm -rf autom4te-*.cache
-
-tags: $(SRC) $(GSRC); ctags *.[ch]
-
-depend: makefile.dependencies
-
-makefile.dependencies: makefile
-	$(CC) $(CPPFLAGS) -M $(SRC) > makefile.dependencies
-
-uninstall:
-	rm -f -r $(DESTDIR)$(libpddir)
-	rm -f $(DESTDIR)$(bindir)/pd-l2ork
-	rm -f $(DESTDIR)$(bindir)/pdsend
-	rm -f $(DESTDIR)$(bindir)/pdreceive
-	rm -f $(DESTDIR)$(includedir)/m_pd.h
-	rm -f $(DESTDIR)$(includedir)/m_imp.h
-	rm -f $(DESTDIR)$(includedir)/s_stuff.h
-	rm -f $(DESTDIR)$(includedir)/g_all_guis.h
-	rm -f $(DESTDIR)$(includedir)/g_canvas.
-	rm -f $(DESTDIR)$(mandir)/man1/pd.1.gz
-	rm -f $(DESTDIR)$(mandir)/man1/pdsend.1.gz
-	rm -f $(DESTDIR)$(mandir)/man1/pdreceive.1.gz
-
-include makefile.dependencies
-
-
-TAGS: etags
-
-etags:
-	etags *.h $(SRC) $(SYSSRC)
-	etags --append --language=none --regex="/proc[ \t]+\([^ \t]+\)/\1/" pd.tk *.tcl
-	find /usr/include -type f -name \*.h -exec etags -a '{}' \;
-	make etags_`uname -s`
-
-etags_Darwin:
-	find /System/Library/Frameworks  -type f -name \*.h -exec etags -a '{}' \;
-	find /Library/Frameworks  -type f -name \*.h -exec etags -a '{}' \;
-	find /sw/include -type f -name \*.h -exec etags -a '{}' \;
-
-etags_Linux:
-
-etags_MINGW:
-	find /usr/local/include/ -type f -name \*.h -exec etags -a '{}' \;
-
-
-
-
-
-
-
-
-
-
diff --git a/src/makefile.dependencies b/src/makefile.dependencies
index 255b80c76e3603d93b3fe8fba92db0372004e465..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644
--- a/src/makefile.dependencies
+++ b/src/makefile.dependencies
@@ -1,1132 +0,0 @@
-d_ctl.o: d_ctl.c m_pd.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h /usr/include/math.h \
- /usr/include/features.h /usr/include/bits/predefs.h \
- /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
- /usr/include/gnu/stubs.h /usr/include/gnu/stubs-32.h \
- /usr/include/bits/huge_val.h /usr/include/bits/huge_valf.h \
- /usr/include/bits/huge_vall.h /usr/include/bits/inf.h \
- /usr/include/bits/nan.h /usr/include/bits/mathdef.h \
- /usr/include/bits/mathcalls.h
-d_array.o: d_array.c m_pd.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h /usr/include/endian.h \
- /usr/include/features.h /usr/include/bits/predefs.h \
- /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
- /usr/include/gnu/stubs.h /usr/include/gnu/stubs-32.h \
- /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
- /usr/include/sys/types.h /usr/include/bits/types.h \
- /usr/include/bits/typesizes.h /usr/include/time.h \
- /usr/include/sys/select.h /usr/include/bits/select.h \
- /usr/include/bits/sigset.h /usr/include/bits/time.h \
- /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h
-d_delay.o: d_delay.c m_pd.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h /usr/include/string.h \
- /usr/include/features.h /usr/include/bits/predefs.h \
- /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
- /usr/include/gnu/stubs.h /usr/include/gnu/stubs-32.h \
- /usr/include/xlocale.h /usr/include/stdio.h /usr/include/bits/types.h \
- /usr/include/bits/typesizes.h /usr/include/libio.h \
- /usr/include/_G_config.h /usr/include/wchar.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stdarg.h \
- /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h
-d_filter.o: d_filter.c m_pd.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h /usr/include/math.h \
- /usr/include/features.h /usr/include/bits/predefs.h \
- /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
- /usr/include/gnu/stubs.h /usr/include/gnu/stubs-32.h \
- /usr/include/bits/huge_val.h /usr/include/bits/huge_valf.h \
- /usr/include/bits/huge_vall.h /usr/include/bits/inf.h \
- /usr/include/bits/nan.h /usr/include/bits/mathdef.h \
- /usr/include/bits/mathcalls.h
-d_math.o: d_math.c m_pd.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h /usr/include/math.h \
- /usr/include/features.h /usr/include/bits/predefs.h \
- /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
- /usr/include/gnu/stubs.h /usr/include/gnu/stubs-32.h \
- /usr/include/bits/huge_val.h /usr/include/bits/huge_valf.h \
- /usr/include/bits/huge_vall.h /usr/include/bits/inf.h \
- /usr/include/bits/nan.h /usr/include/bits/mathdef.h \
- /usr/include/bits/mathcalls.h /usr/include/sys/types.h \
- /usr/include/bits/types.h /usr/include/bits/typesizes.h \
- /usr/include/time.h /usr/include/endian.h /usr/include/bits/endian.h \
- /usr/include/bits/byteswap.h /usr/include/sys/select.h \
- /usr/include/bits/select.h /usr/include/bits/sigset.h \
- /usr/include/bits/time.h /usr/include/sys/sysmacros.h \
- /usr/include/bits/pthreadtypes.h
-d_osc.o: d_osc.c m_pd.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h /usr/include/math.h \
- /usr/include/features.h /usr/include/bits/predefs.h \
- /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
- /usr/include/gnu/stubs.h /usr/include/gnu/stubs-32.h \
- /usr/include/bits/huge_val.h /usr/include/bits/huge_valf.h \
- /usr/include/bits/huge_vall.h /usr/include/bits/inf.h \
- /usr/include/bits/nan.h /usr/include/bits/mathdef.h \
- /usr/include/bits/mathcalls.h /usr/include/endian.h \
- /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
- /usr/include/sys/types.h /usr/include/bits/types.h \
- /usr/include/bits/typesizes.h /usr/include/time.h \
- /usr/include/sys/select.h /usr/include/bits/select.h \
- /usr/include/bits/sigset.h /usr/include/bits/time.h \
- /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h
-d_soundfile.o: d_soundfile.c config.h /usr/include/unistd.h \
- /usr/include/features.h /usr/include/bits/predefs.h \
- /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
- /usr/include/gnu/stubs.h /usr/include/gnu/stubs-32.h \
- /usr/include/bits/posix_opt.h /usr/include/bits/types.h \
- /usr/include/bits/typesizes.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h \
- /usr/include/bits/confname.h /usr/include/getopt.h /usr/include/fcntl.h \
- /usr/include/bits/fcntl.h /usr/include/sys/types.h /usr/include/time.h \
- /usr/include/endian.h /usr/include/bits/endian.h \
- /usr/include/bits/byteswap.h /usr/include/sys/select.h \
- /usr/include/bits/select.h /usr/include/bits/sigset.h \
- /usr/include/bits/time.h /usr/include/sys/sysmacros.h \
- /usr/include/bits/pthreadtypes.h /usr/include/pthread.h \
- /usr/include/sched.h /usr/include/bits/sched.h /usr/include/xlocale.h \
- /usr/include/signal.h /usr/include/bits/setjmp.h /usr/include/stdio.h \
- /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stdarg.h \
- /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
- /usr/include/string.h /usr/include/errno.h /usr/include/bits/errno.h \
- /usr/include/linux/errno.h /usr/include/asm/errno.h \
- /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h \
- m_pd.h
-g_canvas.o: g_canvas.c /usr/include/stdlib.h /usr/include/features.h \
- /usr/include/bits/predefs.h /usr/include/sys/cdefs.h \
- /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
- /usr/include/gnu/stubs-32.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h \
- /usr/include/sys/types.h /usr/include/bits/types.h \
- /usr/include/bits/typesizes.h /usr/include/time.h /usr/include/endian.h \
- /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
- /usr/include/sys/select.h /usr/include/bits/select.h \
- /usr/include/bits/sigset.h /usr/include/bits/time.h \
- /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
- /usr/include/alloca.h /usr/include/stdio.h /usr/include/libio.h \
- /usr/include/_G_config.h /usr/include/wchar.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stdarg.h \
- /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h m_pd.h \
- m_imp.h s_stuff.h g_magicglass.h g_canvas.h /usr/include/string.h \
- /usr/include/xlocale.h g_all_guis.h
-g_graph.o: g_graph.c /usr/include/stdlib.h /usr/include/features.h \
- /usr/include/bits/predefs.h /usr/include/sys/cdefs.h \
- /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
- /usr/include/gnu/stubs-32.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h \
- /usr/include/sys/types.h /usr/include/bits/types.h \
- /usr/include/bits/typesizes.h /usr/include/time.h /usr/include/endian.h \
- /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
- /usr/include/sys/select.h /usr/include/bits/select.h \
- /usr/include/bits/sigset.h /usr/include/bits/time.h \
- /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
- /usr/include/alloca.h m_pd.h m_imp.h t_tk.h g_canvas.h s_stuff.h \
- /usr/include/stdio.h /usr/include/libio.h /usr/include/_G_config.h \
- /usr/include/wchar.h /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stdarg.h \
- /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
- /usr/include/string.h /usr/include/xlocale.h
-g_text.o: g_text.c /usr/include/stdlib.h /usr/include/features.h \
- /usr/include/bits/predefs.h /usr/include/sys/cdefs.h \
- /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
- /usr/include/gnu/stubs-32.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h \
- /usr/include/sys/types.h /usr/include/bits/types.h \
- /usr/include/bits/typesizes.h /usr/include/time.h /usr/include/endian.h \
- /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
- /usr/include/sys/select.h /usr/include/bits/select.h \
- /usr/include/bits/sigset.h /usr/include/bits/time.h \
- /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
- /usr/include/alloca.h m_pd.h m_imp.h s_stuff.h t_tk.h g_canvas.h \
- /usr/include/stdio.h /usr/include/libio.h /usr/include/_G_config.h \
- /usr/include/wchar.h /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stdarg.h \
- /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
- /usr/include/string.h /usr/include/xlocale.h /usr/include/math.h \
- /usr/include/bits/huge_val.h /usr/include/bits/huge_valf.h \
- /usr/include/bits/huge_vall.h /usr/include/bits/inf.h \
- /usr/include/bits/nan.h /usr/include/bits/mathdef.h \
- /usr/include/bits/mathcalls.h
-g_rtext.o: g_rtext.c /usr/include/stdlib.h /usr/include/features.h \
- /usr/include/bits/predefs.h /usr/include/sys/cdefs.h \
- /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
- /usr/include/gnu/stubs-32.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h \
- /usr/include/sys/types.h /usr/include/bits/types.h \
- /usr/include/bits/typesizes.h /usr/include/time.h /usr/include/endian.h \
- /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
- /usr/include/sys/select.h /usr/include/bits/select.h \
- /usr/include/bits/sigset.h /usr/include/bits/time.h \
- /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
- /usr/include/alloca.h /usr/include/string.h /usr/include/xlocale.h \
- /usr/include/stdio.h /usr/include/libio.h /usr/include/_G_config.h \
- /usr/include/wchar.h /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stdarg.h \
- /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
- /usr/include/ctype.h m_pd.h m_imp.h s_stuff.h g_canvas.h t_tk.h
-g_array.o: g_array.c /usr/include/stdlib.h /usr/include/features.h \
- /usr/include/bits/predefs.h /usr/include/sys/cdefs.h \
- /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
- /usr/include/gnu/stubs-32.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h \
- /usr/include/sys/types.h /usr/include/bits/types.h \
- /usr/include/bits/typesizes.h /usr/include/time.h /usr/include/endian.h \
- /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
- /usr/include/sys/select.h /usr/include/bits/select.h \
- /usr/include/bits/sigset.h /usr/include/bits/time.h \
- /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
- /usr/include/alloca.h /usr/include/string.h /usr/include/xlocale.h \
- /usr/include/stdio.h /usr/include/libio.h /usr/include/_G_config.h \
- /usr/include/wchar.h /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stdarg.h \
- /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h m_pd.h \
- g_canvas.h /usr/include/math.h /usr/include/bits/huge_val.h \
- /usr/include/bits/huge_valf.h /usr/include/bits/huge_vall.h \
- /usr/include/bits/inf.h /usr/include/bits/nan.h \
- /usr/include/bits/mathdef.h /usr/include/bits/mathcalls.h
-g_template.o: g_template.c /usr/include/stdlib.h /usr/include/features.h \
- /usr/include/bits/predefs.h /usr/include/sys/cdefs.h \
- /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
- /usr/include/gnu/stubs-32.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h \
- /usr/include/sys/types.h /usr/include/bits/types.h \
- /usr/include/bits/typesizes.h /usr/include/time.h /usr/include/endian.h \
- /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
- /usr/include/sys/select.h /usr/include/bits/select.h \
- /usr/include/bits/sigset.h /usr/include/bits/time.h \
- /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
- /usr/include/alloca.h /usr/include/string.h /usr/include/xlocale.h \
- /usr/include/stdio.h /usr/include/libio.h /usr/include/_G_config.h \
- /usr/include/wchar.h /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stdarg.h \
- /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h m_pd.h \
- s_stuff.h g_canvas.h
-g_io.o: g_io.c m_pd.h /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h \
- g_canvas.h /usr/include/string.h /usr/include/features.h \
- /usr/include/bits/predefs.h /usr/include/sys/cdefs.h \
- /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
- /usr/include/gnu/stubs-32.h /usr/include/xlocale.h
-g_scalar.o: g_scalar.c /usr/include/stdlib.h /usr/include/features.h \
- /usr/include/bits/predefs.h /usr/include/sys/cdefs.h \
- /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
- /usr/include/gnu/stubs-32.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h \
- /usr/include/sys/types.h /usr/include/bits/types.h \
- /usr/include/bits/typesizes.h /usr/include/time.h /usr/include/endian.h \
- /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
- /usr/include/sys/select.h /usr/include/bits/select.h \
- /usr/include/bits/sigset.h /usr/include/bits/time.h \
- /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
- /usr/include/alloca.h /usr/include/string.h /usr/include/xlocale.h \
- /usr/include/stdio.h /usr/include/libio.h /usr/include/_G_config.h \
- /usr/include/wchar.h /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stdarg.h \
- /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h m_pd.h \
- g_canvas.h
-g_traversal.o: g_traversal.c /usr/include/stdlib.h \
- /usr/include/features.h /usr/include/bits/predefs.h \
- /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
- /usr/include/gnu/stubs.h /usr/include/gnu/stubs-32.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h \
- /usr/include/sys/types.h /usr/include/bits/types.h \
- /usr/include/bits/typesizes.h /usr/include/time.h /usr/include/endian.h \
- /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
- /usr/include/sys/select.h /usr/include/bits/select.h \
- /usr/include/bits/sigset.h /usr/include/bits/time.h \
- /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
- /usr/include/alloca.h /usr/include/string.h /usr/include/xlocale.h \
- /usr/include/stdio.h /usr/include/libio.h /usr/include/_G_config.h \
- /usr/include/wchar.h /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stdarg.h \
- /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h m_pd.h \
- g_canvas.h
-g_guiconnect.o: g_guiconnect.c m_pd.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h g_canvas.h
-g_readwrite.o: g_readwrite.c /usr/include/stdlib.h \
- /usr/include/features.h /usr/include/bits/predefs.h \
- /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
- /usr/include/gnu/stubs.h /usr/include/gnu/stubs-32.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h \
- /usr/include/sys/types.h /usr/include/bits/types.h \
- /usr/include/bits/typesizes.h /usr/include/time.h /usr/include/endian.h \
- /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
- /usr/include/sys/select.h /usr/include/bits/select.h \
- /usr/include/bits/sigset.h /usr/include/bits/time.h \
- /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
- /usr/include/alloca.h /usr/include/stdio.h /usr/include/libio.h \
- /usr/include/_G_config.h /usr/include/wchar.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stdarg.h \
- /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h m_pd.h \
- g_canvas.h /usr/include/string.h /usr/include/xlocale.h
-g_editor.o: g_editor.c /usr/include/stdlib.h /usr/include/features.h \
- /usr/include/bits/predefs.h /usr/include/sys/cdefs.h \
- /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
- /usr/include/gnu/stubs-32.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h \
- /usr/include/sys/types.h /usr/include/bits/types.h \
- /usr/include/bits/typesizes.h /usr/include/time.h /usr/include/endian.h \
- /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
- /usr/include/sys/select.h /usr/include/bits/select.h \
- /usr/include/bits/sigset.h /usr/include/bits/time.h \
- /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
- /usr/include/alloca.h /usr/include/stdio.h /usr/include/libio.h \
- /usr/include/_G_config.h /usr/include/wchar.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stdarg.h \
- /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h m_pd.h \
- m_imp.h s_stuff.h g_magicglass.h g_canvas.h /usr/include/string.h \
- /usr/include/xlocale.h
-g_all_guis.o: g_all_guis.c config.h /usr/include/stdlib.h \
- /usr/include/features.h /usr/include/bits/predefs.h \
- /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
- /usr/include/gnu/stubs.h /usr/include/gnu/stubs-32.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h \
- /usr/include/sys/types.h /usr/include/bits/types.h \
- /usr/include/bits/typesizes.h /usr/include/time.h /usr/include/endian.h \
- /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
- /usr/include/sys/select.h /usr/include/bits/select.h \
- /usr/include/bits/sigset.h /usr/include/bits/time.h \
- /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
- /usr/include/alloca.h /usr/include/string.h /usr/include/xlocale.h \
- /usr/include/stdio.h /usr/include/libio.h /usr/include/_G_config.h \
- /usr/include/wchar.h /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stdarg.h \
- /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
- /usr/include/ctype.h m_pd.h g_canvas.h t_tk.h g_all_guis.h \
- /usr/include/math.h /usr/include/bits/huge_val.h \
- /usr/include/bits/huge_valf.h /usr/include/bits/huge_vall.h \
- /usr/include/bits/inf.h /usr/include/bits/nan.h \
- /usr/include/bits/mathdef.h /usr/include/bits/mathcalls.h \
- /usr/include/unistd.h /usr/include/bits/posix_opt.h \
- /usr/include/bits/confname.h /usr/include/getopt.h
-g_bang.o: g_bang.c config.h /usr/include/stdlib.h /usr/include/features.h \
- /usr/include/bits/predefs.h /usr/include/sys/cdefs.h \
- /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
- /usr/include/gnu/stubs-32.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h \
- /usr/include/sys/types.h /usr/include/bits/types.h \
- /usr/include/bits/typesizes.h /usr/include/time.h /usr/include/endian.h \
- /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
- /usr/include/sys/select.h /usr/include/bits/select.h \
- /usr/include/bits/sigset.h /usr/include/bits/time.h \
- /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
- /usr/include/alloca.h /usr/include/string.h /usr/include/xlocale.h \
- /usr/include/stdio.h /usr/include/libio.h /usr/include/_G_config.h \
- /usr/include/wchar.h /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stdarg.h \
- /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
- /usr/include/ctype.h m_pd.h g_canvas.h t_tk.h g_all_guis.h \
- /usr/include/math.h /usr/include/bits/huge_val.h \
- /usr/include/bits/huge_valf.h /usr/include/bits/huge_vall.h \
- /usr/include/bits/inf.h /usr/include/bits/nan.h \
- /usr/include/bits/mathdef.h /usr/include/bits/mathcalls.h \
- /usr/include/unistd.h /usr/include/bits/posix_opt.h \
- /usr/include/bits/confname.h /usr/include/getopt.h
-g_hdial.o: g_hdial.c config.h /usr/include/stdlib.h \
- /usr/include/features.h /usr/include/bits/predefs.h \
- /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
- /usr/include/gnu/stubs.h /usr/include/gnu/stubs-32.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h \
- /usr/include/sys/types.h /usr/include/bits/types.h \
- /usr/include/bits/typesizes.h /usr/include/time.h /usr/include/endian.h \
- /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
- /usr/include/sys/select.h /usr/include/bits/select.h \
- /usr/include/bits/sigset.h /usr/include/bits/time.h \
- /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
- /usr/include/alloca.h /usr/include/string.h /usr/include/xlocale.h \
- /usr/include/stdio.h /usr/include/libio.h /usr/include/_G_config.h \
- /usr/include/wchar.h /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stdarg.h \
- /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
- /usr/include/ctype.h m_pd.h g_canvas.h t_tk.h g_all_guis.h \
- /usr/include/math.h /usr/include/bits/huge_val.h \
- /usr/include/bits/huge_valf.h /usr/include/bits/huge_vall.h \
- /usr/include/bits/inf.h /usr/include/bits/nan.h \
- /usr/include/bits/mathdef.h /usr/include/bits/mathcalls.h \
- /usr/include/unistd.h /usr/include/bits/posix_opt.h \
- /usr/include/bits/confname.h /usr/include/getopt.h
-g_hslider.o: g_hslider.c config.h /usr/include/stdlib.h \
- /usr/include/features.h /usr/include/bits/predefs.h \
- /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
- /usr/include/gnu/stubs.h /usr/include/gnu/stubs-32.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h \
- /usr/include/sys/types.h /usr/include/bits/types.h \
- /usr/include/bits/typesizes.h /usr/include/time.h /usr/include/endian.h \
- /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
- /usr/include/sys/select.h /usr/include/bits/select.h \
- /usr/include/bits/sigset.h /usr/include/bits/time.h \
- /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
- /usr/include/alloca.h /usr/include/string.h /usr/include/xlocale.h \
- /usr/include/stdio.h /usr/include/libio.h /usr/include/_G_config.h \
- /usr/include/wchar.h /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stdarg.h \
- /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
- /usr/include/ctype.h m_pd.h g_canvas.h t_tk.h g_all_guis.h \
- /usr/include/math.h /usr/include/bits/huge_val.h \
- /usr/include/bits/huge_valf.h /usr/include/bits/huge_vall.h \
- /usr/include/bits/inf.h /usr/include/bits/nan.h \
- /usr/include/bits/mathdef.h /usr/include/bits/mathcalls.h \
- /usr/include/unistd.h /usr/include/bits/posix_opt.h \
- /usr/include/bits/confname.h /usr/include/getopt.h
-g_mycanvas.o: g_mycanvas.c config.h /usr/include/stdlib.h \
- /usr/include/features.h /usr/include/bits/predefs.h \
- /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
- /usr/include/gnu/stubs.h /usr/include/gnu/stubs-32.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h \
- /usr/include/sys/types.h /usr/include/bits/types.h \
- /usr/include/bits/typesizes.h /usr/include/time.h /usr/include/endian.h \
- /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
- /usr/include/sys/select.h /usr/include/bits/select.h \
- /usr/include/bits/sigset.h /usr/include/bits/time.h \
- /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
- /usr/include/alloca.h /usr/include/string.h /usr/include/xlocale.h \
- /usr/include/stdio.h /usr/include/libio.h /usr/include/_G_config.h \
- /usr/include/wchar.h /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stdarg.h \
- /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
- /usr/include/ctype.h m_pd.h g_canvas.h t_tk.h g_all_guis.h \
- /usr/include/math.h /usr/include/bits/huge_val.h \
- /usr/include/bits/huge_valf.h /usr/include/bits/huge_vall.h \
- /usr/include/bits/inf.h /usr/include/bits/nan.h \
- /usr/include/bits/mathdef.h /usr/include/bits/mathcalls.h \
- /usr/include/unistd.h /usr/include/bits/posix_opt.h \
- /usr/include/bits/confname.h /usr/include/getopt.h
-g_numbox.o: g_numbox.c config.h /usr/include/stdlib.h \
- /usr/include/features.h /usr/include/bits/predefs.h \
- /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
- /usr/include/gnu/stubs.h /usr/include/gnu/stubs-32.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h \
- /usr/include/sys/types.h /usr/include/bits/types.h \
- /usr/include/bits/typesizes.h /usr/include/time.h /usr/include/endian.h \
- /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
- /usr/include/sys/select.h /usr/include/bits/select.h \
- /usr/include/bits/sigset.h /usr/include/bits/time.h \
- /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
- /usr/include/alloca.h /usr/include/string.h /usr/include/xlocale.h \
- /usr/include/stdio.h /usr/include/libio.h /usr/include/_G_config.h \
- /usr/include/wchar.h /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stdarg.h \
- /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
- /usr/include/ctype.h m_pd.h g_canvas.h t_tk.h g_all_guis.h \
- /usr/include/math.h /usr/include/bits/huge_val.h \
- /usr/include/bits/huge_valf.h /usr/include/bits/huge_vall.h \
- /usr/include/bits/inf.h /usr/include/bits/nan.h \
- /usr/include/bits/mathdef.h /usr/include/bits/mathcalls.h \
- /usr/include/unistd.h /usr/include/bits/posix_opt.h \
- /usr/include/bits/confname.h /usr/include/getopt.h
-g_toggle.o: g_toggle.c config.h /usr/include/stdlib.h \
- /usr/include/features.h /usr/include/bits/predefs.h \
- /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
- /usr/include/gnu/stubs.h /usr/include/gnu/stubs-32.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h \
- /usr/include/sys/types.h /usr/include/bits/types.h \
- /usr/include/bits/typesizes.h /usr/include/time.h /usr/include/endian.h \
- /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
- /usr/include/sys/select.h /usr/include/bits/select.h \
- /usr/include/bits/sigset.h /usr/include/bits/time.h \
- /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
- /usr/include/alloca.h /usr/include/string.h /usr/include/xlocale.h \
- /usr/include/stdio.h /usr/include/libio.h /usr/include/_G_config.h \
- /usr/include/wchar.h /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stdarg.h \
- /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
- /usr/include/ctype.h m_pd.h g_canvas.h t_tk.h g_all_guis.h \
- /usr/include/math.h /usr/include/bits/huge_val.h \
- /usr/include/bits/huge_valf.h /usr/include/bits/huge_vall.h \
- /usr/include/bits/inf.h /usr/include/bits/nan.h \
- /usr/include/bits/mathdef.h /usr/include/bits/mathcalls.h \
- /usr/include/unistd.h /usr/include/bits/posix_opt.h \
- /usr/include/bits/confname.h /usr/include/getopt.h
-g_vdial.o: g_vdial.c /usr/include/stdlib.h /usr/include/features.h \
- /usr/include/bits/predefs.h /usr/include/sys/cdefs.h \
- /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
- /usr/include/gnu/stubs-32.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h \
- /usr/include/sys/types.h /usr/include/bits/types.h \
- /usr/include/bits/typesizes.h /usr/include/time.h /usr/include/endian.h \
- /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
- /usr/include/sys/select.h /usr/include/bits/select.h \
- /usr/include/bits/sigset.h /usr/include/bits/time.h \
- /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
- /usr/include/alloca.h /usr/include/string.h /usr/include/xlocale.h \
- /usr/include/stdio.h /usr/include/libio.h /usr/include/_G_config.h \
- /usr/include/wchar.h /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stdarg.h \
- /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
- /usr/include/ctype.h m_pd.h g_canvas.h t_tk.h g_all_guis.h \
- /usr/include/math.h /usr/include/bits/huge_val.h \
- /usr/include/bits/huge_valf.h /usr/include/bits/huge_vall.h \
- /usr/include/bits/inf.h /usr/include/bits/nan.h \
- /usr/include/bits/mathdef.h /usr/include/bits/mathcalls.h
-g_vslider.o: g_vslider.c config.h /usr/include/stdlib.h \
- /usr/include/features.h /usr/include/bits/predefs.h \
- /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
- /usr/include/gnu/stubs.h /usr/include/gnu/stubs-32.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h \
- /usr/include/sys/types.h /usr/include/bits/types.h \
- /usr/include/bits/typesizes.h /usr/include/time.h /usr/include/endian.h \
- /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
- /usr/include/sys/select.h /usr/include/bits/select.h \
- /usr/include/bits/sigset.h /usr/include/bits/time.h \
- /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
- /usr/include/alloca.h /usr/include/string.h /usr/include/xlocale.h \
- /usr/include/stdio.h /usr/include/libio.h /usr/include/_G_config.h \
- /usr/include/wchar.h /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stdarg.h \
- /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
- /usr/include/ctype.h m_pd.h g_canvas.h t_tk.h g_all_guis.h \
- /usr/include/math.h /usr/include/bits/huge_val.h \
- /usr/include/bits/huge_valf.h /usr/include/bits/huge_vall.h \
- /usr/include/bits/inf.h /usr/include/bits/nan.h \
- /usr/include/bits/mathdef.h /usr/include/bits/mathcalls.h \
- /usr/include/unistd.h /usr/include/bits/posix_opt.h \
- /usr/include/bits/confname.h /usr/include/getopt.h
-g_vumeter.o: g_vumeter.c config.h /usr/include/stdlib.h \
- /usr/include/features.h /usr/include/bits/predefs.h \
- /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
- /usr/include/gnu/stubs.h /usr/include/gnu/stubs-32.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h \
- /usr/include/sys/types.h /usr/include/bits/types.h \
- /usr/include/bits/typesizes.h /usr/include/time.h /usr/include/endian.h \
- /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
- /usr/include/sys/select.h /usr/include/bits/select.h \
- /usr/include/bits/sigset.h /usr/include/bits/time.h \
- /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
- /usr/include/alloca.h /usr/include/string.h /usr/include/xlocale.h \
- /usr/include/stdio.h /usr/include/libio.h /usr/include/_G_config.h \
- /usr/include/wchar.h /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stdarg.h \
- /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
- /usr/include/ctype.h m_pd.h g_canvas.h t_tk.h g_all_guis.h \
- /usr/include/math.h /usr/include/bits/huge_val.h \
- /usr/include/bits/huge_valf.h /usr/include/bits/huge_vall.h \
- /usr/include/bits/inf.h /usr/include/bits/nan.h \
- /usr/include/bits/mathdef.h /usr/include/bits/mathcalls.h \
- /usr/include/unistd.h /usr/include/bits/posix_opt.h \
- /usr/include/bits/confname.h /usr/include/getopt.h
-g_magicglass.o: g_magicglass.c m_pd.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h /usr/include/stdio.h \
- /usr/include/features.h /usr/include/bits/predefs.h \
- /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
- /usr/include/gnu/stubs.h /usr/include/gnu/stubs-32.h \
- /usr/include/bits/types.h /usr/include/bits/typesizes.h \
- /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stdarg.h \
- /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
- /usr/include/string.h /usr/include/xlocale.h m_imp.h s_stuff.h \
- g_magicglass.h
-m_pd.o: m_pd.c /usr/include/stdlib.h /usr/include/features.h \
- /usr/include/bits/predefs.h /usr/include/sys/cdefs.h \
- /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
- /usr/include/gnu/stubs-32.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h \
- /usr/include/sys/types.h /usr/include/bits/types.h \
- /usr/include/bits/typesizes.h /usr/include/time.h /usr/include/endian.h \
- /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
- /usr/include/sys/select.h /usr/include/bits/select.h \
- /usr/include/bits/sigset.h /usr/include/bits/time.h \
- /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
- /usr/include/alloca.h m_pd.h m_imp.h g_canvas.h /usr/include/stdio.h \
- /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stdarg.h \
- /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h
-m_class.o: m_class.c config.h m_pd.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h m_imp.h s_stuff.h \
- /usr/include/stdlib.h /usr/include/features.h \
- /usr/include/bits/predefs.h /usr/include/sys/cdefs.h \
- /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
- /usr/include/gnu/stubs-32.h /usr/include/sys/types.h \
- /usr/include/bits/types.h /usr/include/bits/typesizes.h \
- /usr/include/time.h /usr/include/endian.h /usr/include/bits/endian.h \
- /usr/include/bits/byteswap.h /usr/include/sys/select.h \
- /usr/include/bits/select.h /usr/include/bits/sigset.h \
- /usr/include/bits/time.h /usr/include/sys/sysmacros.h \
- /usr/include/bits/pthreadtypes.h /usr/include/alloca.h \
- /usr/include/unistd.h /usr/include/bits/posix_opt.h \
- /usr/include/bits/confname.h /usr/include/getopt.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stdarg.h /usr/include/string.h \
- /usr/include/xlocale.h /usr/include/stdio.h /usr/include/libio.h \
- /usr/include/_G_config.h /usr/include/wchar.h \
- /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h
-m_obj.o: m_obj.c m_pd.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h m_imp.h
-m_atom.o: m_atom.c m_pd.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h /usr/include/stdio.h \
- /usr/include/features.h /usr/include/bits/predefs.h \
- /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
- /usr/include/gnu/stubs.h /usr/include/gnu/stubs-32.h \
- /usr/include/bits/types.h /usr/include/bits/typesizes.h \
- /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stdarg.h \
- /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
- /usr/include/string.h /usr/include/xlocale.h
-m_memory.o: m_memory.c /usr/include/stdlib.h /usr/include/features.h \
- /usr/include/bits/predefs.h /usr/include/sys/cdefs.h \
- /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
- /usr/include/gnu/stubs-32.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h \
- /usr/include/sys/types.h /usr/include/bits/types.h \
- /usr/include/bits/typesizes.h /usr/include/time.h /usr/include/endian.h \
- /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
- /usr/include/sys/select.h /usr/include/bits/select.h \
- /usr/include/bits/sigset.h /usr/include/bits/time.h \
- /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
- /usr/include/alloca.h /usr/include/string.h /usr/include/xlocale.h \
- m_pd.h m_imp.h
-m_binbuf.o: m_binbuf.c config.h /usr/include/stdlib.h \
- /usr/include/features.h /usr/include/bits/predefs.h \
- /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
- /usr/include/gnu/stubs.h /usr/include/gnu/stubs-32.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h \
- /usr/include/sys/types.h /usr/include/bits/types.h \
- /usr/include/bits/typesizes.h /usr/include/time.h /usr/include/endian.h \
- /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
- /usr/include/sys/select.h /usr/include/bits/select.h \
- /usr/include/bits/sigset.h /usr/include/bits/time.h \
- /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
- /usr/include/alloca.h m_pd.h s_stuff.h /usr/include/stdio.h \
- /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stdarg.h \
- /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
- /usr/include/unistd.h /usr/include/bits/posix_opt.h \
- /usr/include/bits/confname.h /usr/include/getopt.h /usr/include/fcntl.h \
- /usr/include/bits/fcntl.h /usr/include/string.h /usr/include/xlocale.h
-m_conf.o: m_conf.c m_pd.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h
-m_glob.o: m_glob.c m_pd.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h m_imp.h
-m_sched.o: m_sched.c config.h m_pd.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h m_imp.h s_stuff.h \
- /usr/include/pthread.h /usr/include/features.h \
- /usr/include/bits/predefs.h /usr/include/sys/cdefs.h \
- /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
- /usr/include/gnu/stubs-32.h /usr/include/endian.h \
- /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
- /usr/include/sched.h /usr/include/bits/types.h \
- /usr/include/bits/typesizes.h /usr/include/time.h \
- /usr/include/bits/sched.h /usr/include/bits/time.h \
- /usr/include/xlocale.h /usr/include/signal.h /usr/include/bits/sigset.h \
- /usr/include/bits/pthreadtypes.h /usr/include/bits/setjmp.h \
- /usr/include/unistd.h /usr/include/bits/posix_opt.h \
- /usr/include/bits/confname.h /usr/include/getopt.h
-s_main.o: s_main.c m_pd.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h m_imp.h s_stuff.h \
- /usr/include/sys/types.h /usr/include/features.h \
- /usr/include/bits/predefs.h /usr/include/sys/cdefs.h \
- /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
- /usr/include/gnu/stubs-32.h /usr/include/bits/types.h \
- /usr/include/bits/typesizes.h /usr/include/time.h /usr/include/endian.h \
- /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
- /usr/include/sys/select.h /usr/include/bits/select.h \
- /usr/include/bits/sigset.h /usr/include/bits/time.h \
- /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
- /usr/include/sys/stat.h /usr/include/bits/stat.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include-fixed/limits.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include-fixed/syslimits.h \
- /usr/include/limits.h /usr/include/bits/posix1_lim.h \
- /usr/include/bits/local_lim.h /usr/include/linux/limits.h \
- /usr/include/bits/posix2_lim.h /usr/include/string.h \
- /usr/include/xlocale.h /usr/include/stdio.h /usr/include/libio.h \
- /usr/include/_G_config.h /usr/include/wchar.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stdarg.h \
- /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
- /usr/include/fcntl.h /usr/include/bits/fcntl.h /usr/include/stdlib.h \
- /usr/include/alloca.h /usr/include/unistd.h \
- /usr/include/bits/posix_opt.h /usr/include/bits/confname.h \
- /usr/include/getopt.h
-s_inter.o: s_inter.c config.h m_pd.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h s_stuff.h m_imp.h \
- g_canvas.h /usr/include/unistd.h /usr/include/features.h \
- /usr/include/bits/predefs.h /usr/include/sys/cdefs.h \
- /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
- /usr/include/gnu/stubs-32.h /usr/include/bits/posix_opt.h \
- /usr/include/bits/types.h /usr/include/bits/typesizes.h \
- /usr/include/bits/confname.h /usr/include/getopt.h \
- /usr/include/sys/socket.h /usr/include/sys/uio.h \
- /usr/include/sys/types.h /usr/include/time.h /usr/include/endian.h \
- /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
- /usr/include/sys/select.h /usr/include/bits/select.h \
- /usr/include/bits/sigset.h /usr/include/bits/time.h \
- /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
- /usr/include/bits/uio.h /usr/include/bits/socket.h \
- /usr/include/bits/sockaddr.h /usr/include/asm/socket.h \
- /usr/include/asm-generic/socket.h /usr/include/asm/sockios.h \
- /usr/include/asm-generic/sockios.h /usr/include/netinet/in.h \
- /usr/include/stdint.h /usr/include/bits/wchar.h /usr/include/bits/in.h \
- /usr/include/netinet/tcp.h /usr/include/netdb.h /usr/include/rpc/netdb.h \
- /usr/include/bits/netdb.h /usr/include/stdlib.h /usr/include/alloca.h \
- /usr/include/sys/time.h /usr/include/sys/mman.h /usr/include/bits/mman.h \
- /usr/include/sys/resource.h /usr/include/bits/resource.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stdarg.h /usr/include/signal.h \
- /usr/include/bits/signum.h /usr/include/bits/siginfo.h \
- /usr/include/bits/sigaction.h /usr/include/bits/sigcontext.h \
- /usr/include/bits/sigstack.h /usr/include/bits/sigthread.h \
- /usr/include/fcntl.h /usr/include/bits/fcntl.h /usr/include/errno.h \
- /usr/include/bits/errno.h /usr/include/linux/errno.h \
- /usr/include/asm/errno.h /usr/include/asm-generic/errno.h \
- /usr/include/asm-generic/errno-base.h /usr/include/string.h \
- /usr/include/xlocale.h /usr/include/stdio.h /usr/include/libio.h \
- /usr/include/_G_config.h /usr/include/wchar.h \
- /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
- /usr/include/execinfo.h /usr/include/sched.h /usr/include/bits/sched.h
-s_file.o: s_file.c config.h m_pd.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h s_stuff.h \
- /usr/include/string.h /usr/include/features.h \
- /usr/include/bits/predefs.h /usr/include/sys/cdefs.h \
- /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
- /usr/include/gnu/stubs-32.h /usr/include/xlocale.h /usr/include/stdlib.h \
- /usr/include/sys/types.h /usr/include/bits/types.h \
- /usr/include/bits/typesizes.h /usr/include/time.h /usr/include/endian.h \
- /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
- /usr/include/sys/select.h /usr/include/bits/select.h \
- /usr/include/bits/sigset.h /usr/include/bits/time.h \
- /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
- /usr/include/alloca.h /usr/include/stdio.h /usr/include/libio.h \
- /usr/include/_G_config.h /usr/include/wchar.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stdarg.h \
- /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
- /usr/include/errno.h /usr/include/bits/errno.h \
- /usr/include/linux/errno.h /usr/include/asm/errno.h \
- /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h \
- /usr/include/unistd.h /usr/include/bits/posix_opt.h \
- /usr/include/bits/confname.h /usr/include/getopt.h \
- /usr/include/sys/stat.h /usr/include/bits/stat.h /usr/include/fcntl.h \
- /usr/include/bits/fcntl.h
-s_print.o: s_print.c m_pd.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h /usr/include/stdlib.h \
- /usr/include/features.h /usr/include/bits/predefs.h \
- /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
- /usr/include/gnu/stubs.h /usr/include/gnu/stubs-32.h \
- /usr/include/sys/types.h /usr/include/bits/types.h \
- /usr/include/bits/typesizes.h /usr/include/time.h /usr/include/endian.h \
- /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
- /usr/include/sys/select.h /usr/include/bits/select.h \
- /usr/include/bits/sigset.h /usr/include/bits/time.h \
- /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
- /usr/include/alloca.h /usr/include/stdio.h /usr/include/libio.h \
- /usr/include/_G_config.h /usr/include/wchar.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stdarg.h \
- /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
- /usr/include/string.h /usr/include/xlocale.h /usr/include/errno.h \
- /usr/include/bits/errno.h /usr/include/linux/errno.h \
- /usr/include/asm/errno.h /usr/include/asm-generic/errno.h \
- /usr/include/asm-generic/errno-base.h s_stuff.h
-s_loader.o: s_loader.c /usr/include/dlfcn.h /usr/include/features.h \
- /usr/include/bits/predefs.h /usr/include/sys/cdefs.h \
- /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
- /usr/include/gnu/stubs-32.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h \
- /usr/include/bits/dlfcn.h /usr/include/stdlib.h /usr/include/sys/types.h \
- /usr/include/bits/types.h /usr/include/bits/typesizes.h \
- /usr/include/time.h /usr/include/endian.h /usr/include/bits/endian.h \
- /usr/include/bits/byteswap.h /usr/include/sys/select.h \
- /usr/include/bits/select.h /usr/include/bits/sigset.h \
- /usr/include/bits/time.h /usr/include/sys/sysmacros.h \
- /usr/include/bits/pthreadtypes.h /usr/include/alloca.h \
- /usr/include/unistd.h /usr/include/bits/posix_opt.h \
- /usr/include/bits/confname.h /usr/include/getopt.h \
- /usr/include/sys/stat.h /usr/include/bits/stat.h /usr/include/string.h \
- /usr/include/xlocale.h m_pd.h s_stuff.h /usr/include/stdio.h \
- /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stdarg.h \
- /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h
-s_path.o: s_path.c /usr/include/stdlib.h /usr/include/features.h \
- /usr/include/bits/predefs.h /usr/include/sys/cdefs.h \
- /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
- /usr/include/gnu/stubs-32.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h \
- /usr/include/sys/types.h /usr/include/bits/types.h \
- /usr/include/bits/typesizes.h /usr/include/time.h /usr/include/endian.h \
- /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
- /usr/include/sys/select.h /usr/include/bits/select.h \
- /usr/include/bits/sigset.h /usr/include/bits/time.h \
- /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
- /usr/include/alloca.h /usr/include/unistd.h \
- /usr/include/bits/posix_opt.h /usr/include/bits/confname.h \
- /usr/include/getopt.h /usr/include/sys/stat.h /usr/include/bits/stat.h \
- /usr/include/string.h /usr/include/xlocale.h m_pd.h m_imp.h s_stuff.h \
- /usr/include/stdio.h /usr/include/libio.h /usr/include/_G_config.h \
- /usr/include/wchar.h /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stdarg.h \
- /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
- /usr/include/fcntl.h /usr/include/bits/fcntl.h /usr/include/ctype.h
-s_entry.o: s_entry.c
-s_audio.o: s_audio.c config.h m_pd.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h s_stuff.h \
- /usr/include/stdio.h /usr/include/features.h /usr/include/bits/predefs.h \
- /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
- /usr/include/gnu/stubs.h /usr/include/gnu/stubs-32.h \
- /usr/include/bits/types.h /usr/include/bits/typesizes.h \
- /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stdarg.h \
- /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
- /usr/include/unistd.h /usr/include/bits/posix_opt.h \
- /usr/include/bits/confname.h /usr/include/getopt.h \
- /usr/include/sys/time.h /usr/include/time.h /usr/include/bits/time.h \
- /usr/include/sys/select.h /usr/include/bits/select.h \
- /usr/include/bits/sigset.h /usr/include/sys/resource.h \
- /usr/include/bits/resource.h /usr/include/stdlib.h \
- /usr/include/sys/types.h /usr/include/endian.h \
- /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
- /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
- /usr/include/alloca.h /usr/include/string.h /usr/include/xlocale.h \
- /usr/include/errno.h /usr/include/bits/errno.h \
- /usr/include/linux/errno.h /usr/include/asm/errno.h \
- /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h
-s_midi.o: s_midi.c config.h m_pd.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h s_stuff.h m_imp.h \
- /usr/include/unistd.h /usr/include/features.h \
- /usr/include/bits/predefs.h /usr/include/sys/cdefs.h \
- /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
- /usr/include/gnu/stubs-32.h /usr/include/bits/posix_opt.h \
- /usr/include/bits/types.h /usr/include/bits/typesizes.h \
- /usr/include/bits/confname.h /usr/include/getopt.h \
- /usr/include/sys/time.h /usr/include/time.h /usr/include/bits/time.h \
- /usr/include/sys/select.h /usr/include/bits/select.h \
- /usr/include/bits/sigset.h /usr/include/string.h /usr/include/xlocale.h \
- /usr/include/stdio.h /usr/include/libio.h /usr/include/_G_config.h \
- /usr/include/wchar.h /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stdarg.h \
- /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
- /usr/include/signal.h /usr/include/bits/signum.h \
- /usr/include/bits/siginfo.h /usr/include/bits/sigaction.h \
- /usr/include/bits/sigcontext.h /usr/include/bits/sigstack.h \
- /usr/include/bits/pthreadtypes.h /usr/include/bits/sigthread.h
-d_ugen.o: d_ugen.c m_pd.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h m_imp.h \
- /usr/include/stdlib.h /usr/include/features.h \
- /usr/include/bits/predefs.h /usr/include/sys/cdefs.h \
- /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
- /usr/include/gnu/stubs-32.h /usr/include/sys/types.h \
- /usr/include/bits/types.h /usr/include/bits/typesizes.h \
- /usr/include/time.h /usr/include/endian.h /usr/include/bits/endian.h \
- /usr/include/bits/byteswap.h /usr/include/sys/select.h \
- /usr/include/bits/select.h /usr/include/bits/sigset.h \
- /usr/include/bits/time.h /usr/include/sys/sysmacros.h \
- /usr/include/bits/pthreadtypes.h /usr/include/alloca.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stdarg.h
-d_arithmetic.o: d_arithmetic.c m_pd.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h
-d_dac.o: d_dac.c m_pd.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h s_stuff.h
-d_misc.o: d_misc.c m_pd.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h /usr/include/stdio.h \
- /usr/include/features.h /usr/include/bits/predefs.h \
- /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
- /usr/include/gnu/stubs.h /usr/include/gnu/stubs-32.h \
- /usr/include/bits/types.h /usr/include/bits/typesizes.h \
- /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stdarg.h \
- /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
- /usr/include/string.h /usr/include/xlocale.h
-d_fft.o: d_fft.c m_pd.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h
-d_global.o: d_global.c m_pd.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h /usr/include/string.h \
- /usr/include/features.h /usr/include/bits/predefs.h \
- /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
- /usr/include/gnu/stubs.h /usr/include/gnu/stubs-32.h \
- /usr/include/xlocale.h
-d_resample.o: d_resample.c m_pd.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h
-x_arithmetic.o: x_arithmetic.c config.h m_pd.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h /usr/include/math.h \
- /usr/include/features.h /usr/include/bits/predefs.h \
- /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
- /usr/include/gnu/stubs.h /usr/include/gnu/stubs-32.h \
- /usr/include/bits/huge_val.h /usr/include/bits/huge_valf.h \
- /usr/include/bits/huge_vall.h /usr/include/bits/inf.h \
- /usr/include/bits/nan.h /usr/include/bits/mathdef.h \
- /usr/include/bits/mathcalls.h
-x_connective.o: x_connective.c m_pd.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h /usr/include/string.h \
- /usr/include/features.h /usr/include/bits/predefs.h \
- /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
- /usr/include/gnu/stubs.h /usr/include/gnu/stubs-32.h \
- /usr/include/xlocale.h /usr/include/stdio.h /usr/include/bits/types.h \
- /usr/include/bits/typesizes.h /usr/include/libio.h \
- /usr/include/_G_config.h /usr/include/wchar.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stdarg.h \
- /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h
-x_interface.o: x_interface.c m_pd.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h
-x_midi.o: x_midi.c m_pd.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h
-x_misc.o: x_misc.c config.h m_pd.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h s_stuff.h \
- /usr/include/math.h /usr/include/features.h /usr/include/bits/predefs.h \
- /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
- /usr/include/gnu/stubs.h /usr/include/gnu/stubs-32.h \
- /usr/include/bits/huge_val.h /usr/include/bits/huge_valf.h \
- /usr/include/bits/huge_vall.h /usr/include/bits/inf.h \
- /usr/include/bits/nan.h /usr/include/bits/mathdef.h \
- /usr/include/bits/mathcalls.h /usr/include/stdio.h \
- /usr/include/bits/types.h /usr/include/bits/typesizes.h \
- /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stdarg.h \
- /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
- /usr/include/string.h /usr/include/xlocale.h /usr/include/unistd.h \
- /usr/include/bits/posix_opt.h /usr/include/bits/confname.h \
- /usr/include/getopt.h /usr/include/sys/types.h /usr/include/time.h \
- /usr/include/endian.h /usr/include/bits/endian.h \
- /usr/include/bits/byteswap.h /usr/include/sys/select.h \
- /usr/include/bits/select.h /usr/include/bits/sigset.h \
- /usr/include/bits/time.h /usr/include/sys/sysmacros.h \
- /usr/include/bits/pthreadtypes.h /usr/include/sys/time.h \
- /usr/include/sys/times.h /usr/include/sys/param.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include-fixed/limits.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include-fixed/syslimits.h \
- /usr/include/limits.h /usr/include/bits/posix1_lim.h \
- /usr/include/bits/local_lim.h /usr/include/linux/limits.h \
- /usr/include/bits/posix2_lim.h /usr/include/linux/param.h \
- /usr/include/asm/param.h /usr/include/asm-generic/param.h
-x_time.o: x_time.c m_pd.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h /usr/include/stdio.h \
- /usr/include/features.h /usr/include/bits/predefs.h \
- /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
- /usr/include/gnu/stubs.h /usr/include/gnu/stubs-32.h \
- /usr/include/bits/types.h /usr/include/bits/typesizes.h \
- /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stdarg.h \
- /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h
-x_acoustics.o: x_acoustics.c m_pd.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h /usr/include/math.h \
- /usr/include/features.h /usr/include/bits/predefs.h \
- /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
- /usr/include/gnu/stubs.h /usr/include/gnu/stubs-32.h \
- /usr/include/bits/huge_val.h /usr/include/bits/huge_valf.h \
- /usr/include/bits/huge_vall.h /usr/include/bits/inf.h \
- /usr/include/bits/nan.h /usr/include/bits/mathdef.h \
- /usr/include/bits/mathcalls.h
-x_net.o: x_net.c m_pd.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h s_stuff.h \
- /usr/include/sys/types.h /usr/include/features.h \
- /usr/include/bits/predefs.h /usr/include/sys/cdefs.h \
- /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
- /usr/include/gnu/stubs-32.h /usr/include/bits/types.h \
- /usr/include/bits/typesizes.h /usr/include/time.h /usr/include/endian.h \
- /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
- /usr/include/sys/select.h /usr/include/bits/select.h \
- /usr/include/bits/sigset.h /usr/include/bits/time.h \
- /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
- /usr/include/string.h /usr/include/xlocale.h /usr/include/sys/socket.h \
- /usr/include/sys/uio.h /usr/include/bits/uio.h \
- /usr/include/bits/socket.h /usr/include/bits/sockaddr.h \
- /usr/include/asm/socket.h /usr/include/asm-generic/socket.h \
- /usr/include/asm/sockios.h /usr/include/asm-generic/sockios.h \
- /usr/include/netinet/in.h /usr/include/stdint.h \
- /usr/include/bits/wchar.h /usr/include/bits/in.h \
- /usr/include/netinet/tcp.h /usr/include/netdb.h /usr/include/rpc/netdb.h \
- /usr/include/bits/netdb.h /usr/include/stdio.h /usr/include/libio.h \
- /usr/include/_G_config.h /usr/include/wchar.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stdarg.h \
- /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h
-x_qlist.o: x_qlist.c config.h m_pd.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h /usr/include/string.h \
- /usr/include/features.h /usr/include/bits/predefs.h \
- /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
- /usr/include/gnu/stubs.h /usr/include/gnu/stubs-32.h \
- /usr/include/xlocale.h /usr/include/unistd.h \
- /usr/include/bits/posix_opt.h /usr/include/bits/types.h \
- /usr/include/bits/typesizes.h /usr/include/bits/confname.h \
- /usr/include/getopt.h
-x_gui.o: x_gui.c config.h m_pd.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h /usr/include/stdio.h \
- /usr/include/features.h /usr/include/bits/predefs.h \
- /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
- /usr/include/gnu/stubs.h /usr/include/gnu/stubs-32.h \
- /usr/include/bits/types.h /usr/include/bits/typesizes.h \
- /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stdarg.h \
- /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
- /usr/include/string.h /usr/include/xlocale.h /usr/include/unistd.h \
- /usr/include/bits/posix_opt.h /usr/include/bits/confname.h \
- /usr/include/getopt.h
-x_list.o: x_list.c config.h m_pd.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h /usr/include/malloc.h \
- /usr/include/features.h /usr/include/bits/predefs.h \
- /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
- /usr/include/gnu/stubs.h /usr/include/gnu/stubs-32.h \
- /usr/include/stdio.h /usr/include/bits/types.h \
- /usr/include/bits/typesizes.h /usr/include/libio.h \
- /usr/include/_G_config.h /usr/include/wchar.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stdarg.h \
- /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
- /usr/include/alloca.h
-import.o: import.c m_pd.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h s_stuff.h g_canvas.h \
- /usr/include/stdio.h /usr/include/features.h /usr/include/bits/predefs.h \
- /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
- /usr/include/gnu/stubs.h /usr/include/gnu/stubs-32.h \
- /usr/include/bits/types.h /usr/include/bits/typesizes.h \
- /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stdarg.h \
- /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
- /usr/include/stdlib.h /usr/include/sys/types.h /usr/include/time.h \
- /usr/include/endian.h /usr/include/bits/endian.h \
- /usr/include/bits/byteswap.h /usr/include/sys/select.h \
- /usr/include/bits/select.h /usr/include/bits/sigset.h \
- /usr/include/bits/time.h /usr/include/sys/sysmacros.h \
- /usr/include/bits/pthreadtypes.h /usr/include/alloca.h \
- /usr/include/string.h /usr/include/xlocale.h
-s_midi_oss.o: s_midi_oss.c config.h /usr/include/stdio.h \
- /usr/include/features.h /usr/include/bits/predefs.h \
- /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
- /usr/include/gnu/stubs.h /usr/include/gnu/stubs-32.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h \
- /usr/include/bits/types.h /usr/include/bits/typesizes.h \
- /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stdarg.h \
- /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
- /usr/include/unistd.h /usr/include/bits/posix_opt.h \
- /usr/include/bits/confname.h /usr/include/getopt.h /usr/include/stdlib.h \
- /usr/include/sys/types.h /usr/include/time.h /usr/include/endian.h \
- /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
- /usr/include/sys/select.h /usr/include/bits/select.h \
- /usr/include/bits/sigset.h /usr/include/bits/time.h \
- /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
- /usr/include/alloca.h /usr/include/sys/stat.h /usr/include/bits/stat.h \
- /usr/include/fcntl.h /usr/include/bits/fcntl.h /usr/include/errno.h \
- /usr/include/bits/errno.h /usr/include/linux/errno.h \
- /usr/include/asm/errno.h /usr/include/asm-generic/errno.h \
- /usr/include/asm-generic/errno-base.h m_pd.h s_stuff.h
-s_audio_oss.o: s_audio_oss.c /usr/include/linux/soundcard.h \
- /usr/include/linux/ioctl.h /usr/include/asm/ioctl.h \
- /usr/include/asm-generic/ioctl.h /usr/include/endian.h \
- /usr/include/features.h /usr/include/bits/predefs.h \
- /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
- /usr/include/gnu/stubs.h /usr/include/gnu/stubs-32.h \
- /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
- /usr/include/linux/patchkey.h m_pd.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h s_stuff.h \
- /usr/include/errno.h /usr/include/bits/errno.h \
- /usr/include/linux/errno.h /usr/include/asm/errno.h \
- /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h \
- /usr/include/stdio.h /usr/include/bits/types.h \
- /usr/include/bits/typesizes.h /usr/include/libio.h \
- /usr/include/_G_config.h /usr/include/wchar.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stdarg.h \
- /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
- /usr/include/unistd.h /usr/include/bits/posix_opt.h \
- /usr/include/bits/confname.h /usr/include/getopt.h /usr/include/stdlib.h \
- /usr/include/sys/types.h /usr/include/time.h /usr/include/sys/select.h \
- /usr/include/bits/select.h /usr/include/bits/sigset.h \
- /usr/include/bits/time.h /usr/include/sys/sysmacros.h \
- /usr/include/bits/pthreadtypes.h /usr/include/alloca.h \
- /usr/include/string.h /usr/include/xlocale.h /usr/include/sys/time.h \
- /usr/include/sys/stat.h /usr/include/bits/stat.h \
- /usr/include/sys/ioctl.h /usr/include/bits/ioctls.h \
- /usr/include/asm/ioctls.h /usr/include/asm-generic/ioctls.h \
- /usr/include/bits/ioctl-types.h /usr/include/sys/ttydefaults.h \
- /usr/include/fcntl.h /usr/include/bits/fcntl.h /usr/include/sched.h \
- /usr/include/bits/sched.h /usr/include/sys/mman.h \
- /usr/include/bits/mman.h
-s_audio_alsa.o: s_audio_alsa.c /usr/include/alsa/asoundlib.h \
- /usr/include/unistd.h /usr/include/features.h \
- /usr/include/bits/predefs.h /usr/include/sys/cdefs.h \
- /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
- /usr/include/gnu/stubs-32.h /usr/include/bits/posix_opt.h \
- /usr/include/bits/types.h /usr/include/bits/typesizes.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h \
- /usr/include/bits/confname.h /usr/include/getopt.h /usr/include/stdio.h \
- /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stdarg.h \
- /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
- /usr/include/stdlib.h /usr/include/sys/types.h /usr/include/time.h \
- /usr/include/endian.h /usr/include/bits/endian.h \
- /usr/include/bits/byteswap.h /usr/include/sys/select.h \
- /usr/include/bits/select.h /usr/include/bits/sigset.h \
- /usr/include/bits/time.h /usr/include/sys/sysmacros.h \
- /usr/include/bits/pthreadtypes.h /usr/include/alloca.h \
- /usr/include/string.h /usr/include/xlocale.h /usr/include/fcntl.h \
- /usr/include/bits/fcntl.h /usr/include/assert.h /usr/include/sys/poll.h \
- /usr/include/bits/poll.h /usr/include/errno.h /usr/include/bits/errno.h \
- /usr/include/linux/errno.h /usr/include/asm/errno.h \
- /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h \
- /usr/include/alsa/asoundef.h /usr/include/alsa/version.h \
- /usr/include/alsa/global.h /usr/include/alsa/input.h \
- /usr/include/alsa/output.h /usr/include/alsa/error.h \
- /usr/include/alsa/conf.h /usr/include/alsa/pcm.h \
- /usr/include/alsa/rawmidi.h /usr/include/alsa/timer.h \
- /usr/include/alsa/hwdep.h /usr/include/alsa/control.h \
- /usr/include/alsa/mixer.h /usr/include/alsa/seq_event.h \
- /usr/include/alsa/seq.h /usr/include/alsa/seqmid.h \
- /usr/include/alsa/seq_midi_event.h m_pd.h s_stuff.h \
- /usr/include/sys/time.h /usr/include/sys/stat.h /usr/include/bits/stat.h \
- /usr/include/sys/ioctl.h /usr/include/bits/ioctls.h \
- /usr/include/asm/ioctls.h /usr/include/asm-generic/ioctls.h \
- /usr/include/linux/ioctl.h /usr/include/asm/ioctl.h \
- /usr/include/asm-generic/ioctl.h /usr/include/bits/ioctl-types.h \
- /usr/include/sys/ttydefaults.h /usr/include/sched.h \
- /usr/include/bits/sched.h /usr/include/sys/mman.h \
- /usr/include/bits/mman.h s_audio_alsa.h
-s_audio_alsamm.o: s_audio_alsamm.c /usr/include/alsa/asoundlib.h \
- /usr/include/unistd.h /usr/include/features.h \
- /usr/include/bits/predefs.h /usr/include/sys/cdefs.h \
- /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
- /usr/include/gnu/stubs-32.h /usr/include/bits/posix_opt.h \
- /usr/include/bits/types.h /usr/include/bits/typesizes.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h \
- /usr/include/bits/confname.h /usr/include/getopt.h /usr/include/stdio.h \
- /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stdarg.h \
- /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
- /usr/include/stdlib.h /usr/include/sys/types.h /usr/include/time.h \
- /usr/include/endian.h /usr/include/bits/endian.h \
- /usr/include/bits/byteswap.h /usr/include/sys/select.h \
- /usr/include/bits/select.h /usr/include/bits/sigset.h \
- /usr/include/bits/time.h /usr/include/sys/sysmacros.h \
- /usr/include/bits/pthreadtypes.h /usr/include/alloca.h \
- /usr/include/string.h /usr/include/xlocale.h /usr/include/fcntl.h \
- /usr/include/bits/fcntl.h /usr/include/assert.h /usr/include/sys/poll.h \
- /usr/include/bits/poll.h /usr/include/errno.h /usr/include/bits/errno.h \
- /usr/include/linux/errno.h /usr/include/asm/errno.h \
- /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h \
- /usr/include/alsa/asoundef.h /usr/include/alsa/version.h \
- /usr/include/alsa/global.h /usr/include/alsa/input.h \
- /usr/include/alsa/output.h /usr/include/alsa/error.h \
- /usr/include/alsa/conf.h /usr/include/alsa/pcm.h \
- /usr/include/alsa/rawmidi.h /usr/include/alsa/timer.h \
- /usr/include/alsa/hwdep.h /usr/include/alsa/control.h \
- /usr/include/alsa/mixer.h /usr/include/alsa/seq_event.h \
- /usr/include/alsa/seq.h /usr/include/alsa/seqmid.h \
- /usr/include/alsa/seq_midi_event.h m_pd.h s_stuff.h \
- /usr/include/sys/time.h /usr/include/sys/stat.h /usr/include/bits/stat.h \
- /usr/include/sys/ioctl.h /usr/include/bits/ioctls.h \
- /usr/include/asm/ioctls.h /usr/include/asm-generic/ioctls.h \
- /usr/include/linux/ioctl.h /usr/include/asm/ioctl.h \
- /usr/include/asm-generic/ioctl.h /usr/include/bits/ioctl-types.h \
- /usr/include/sys/ttydefaults.h /usr/include/sched.h \
- /usr/include/bits/sched.h s_audio_alsa.h
-s_midi_alsa.o: s_midi_alsa.c config.h /usr/include/stdio.h \
- /usr/include/features.h /usr/include/bits/predefs.h \
- /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
- /usr/include/gnu/stubs.h /usr/include/gnu/stubs-32.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h \
- /usr/include/bits/types.h /usr/include/bits/typesizes.h \
- /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stdarg.h \
- /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
- /usr/include/unistd.h /usr/include/bits/posix_opt.h \
- /usr/include/bits/confname.h /usr/include/getopt.h /usr/include/stdlib.h \
- /usr/include/sys/types.h /usr/include/time.h /usr/include/endian.h \
- /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
- /usr/include/sys/select.h /usr/include/bits/select.h \
- /usr/include/bits/sigset.h /usr/include/bits/time.h \
- /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
- /usr/include/alloca.h /usr/include/sys/stat.h /usr/include/bits/stat.h \
- /usr/include/fcntl.h /usr/include/bits/fcntl.h /usr/include/errno.h \
- /usr/include/bits/errno.h /usr/include/linux/errno.h \
- /usr/include/asm/errno.h /usr/include/asm-generic/errno.h \
- /usr/include/asm-generic/errno-base.h /usr/include/alsa/asoundlib.h \
- /usr/include/string.h /usr/include/xlocale.h /usr/include/assert.h \
- /usr/include/sys/poll.h /usr/include/bits/poll.h \
- /usr/include/alsa/asoundef.h /usr/include/alsa/version.h \
- /usr/include/alsa/global.h /usr/include/alsa/input.h \
- /usr/include/alsa/output.h /usr/include/alsa/error.h \
- /usr/include/alsa/conf.h /usr/include/alsa/pcm.h \
- /usr/include/alsa/rawmidi.h /usr/include/alsa/timer.h \
- /usr/include/alsa/hwdep.h /usr/include/alsa/control.h \
- /usr/include/alsa/mixer.h /usr/include/alsa/seq_event.h \
- /usr/include/alsa/seq.h /usr/include/alsa/seqmid.h \
- /usr/include/alsa/seq_midi_event.h m_pd.h s_stuff.h
-s_audio_jack.o: s_audio_jack.c
-d_fft_mayer.o: d_fft_mayer.c m_pd.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h
-d_fftroutine.o: d_fftroutine.c /usr/include/stdio.h \
- /usr/include/features.h /usr/include/bits/predefs.h \
- /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
- /usr/include/gnu/stubs.h /usr/include/gnu/stubs-32.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h \
- /usr/include/bits/types.h /usr/include/bits/typesizes.h \
- /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
- /usr/lib/gcc/i486-linux-gnu/4.4.3/include/stdarg.h \
- /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
- /usr/include/math.h /usr/include/bits/huge_val.h \
- /usr/include/bits/huge_valf.h /usr/include/bits/huge_vall.h \
- /usr/include/bits/inf.h /usr/include/bits/nan.h \
- /usr/include/bits/mathdef.h /usr/include/bits/mathcalls.h \
- /usr/include/stdlib.h /usr/include/sys/types.h /usr/include/time.h \
- /usr/include/endian.h /usr/include/bits/endian.h \
- /usr/include/bits/byteswap.h /usr/include/sys/select.h \
- /usr/include/bits/select.h /usr/include/bits/sigset.h \
- /usr/include/bits/time.h /usr/include/sys/sysmacros.h \
- /usr/include/bits/pthreadtypes.h /usr/include/alloca.h m_pd.h
diff --git a/src/pd.tk b/src/pd.tk
index 0adbdb41e333b7c8c7e56566f2844812e33218f1..38ade0c3c0b3496dacfbaa88f906ad820b9f9678 100644
--- a/src/pd.tk
+++ b/src/pd.tk
@@ -330,8 +330,6 @@ set pointer_y_global 0
 set copytexttocanvas 0
 
 set global_clipboard 0
-# used for comparison to avoid redundant copyfromexternalbuffer
-set last_clipboard 0
 set global_selection 0
 
 # x:y location tooltip during dragging
@@ -1600,7 +1598,7 @@ proc menu_copy {name} {
 	if {![string match .gfxstub* $name] && ![string match .printout* $name] && ![string match *entry $name]} {
 	    pd [concat $name copy \;]
 		set copytexttocanvas 0
-		clipboard clear
+		# clipboard clear
 	} else {
 		# pdtk_post "this_is_text\n"
 		set copytexttocanvas 1
@@ -1614,12 +1612,12 @@ proc menu_paste {name} {
 	# pdtk_post "pasting..."
 	if {![string match .gfxstub* $name] && ![string match .printout* $name] && ![string match *entry $name]} {
 		# puts stderr "this is not an entry $copytexttocanvas\n"
-		# if {$copytexttocanvas} {
-		#	pdtk_pastetext
-		#} else {
+		if {$copytexttocanvas} {
+			pdtk_pastetext
+		} else {
 			pd [concat $name paste \;]
 			pdtk_canvas_getscroll $name.c
-		#}
+		}
 	} else {
 		# puts stderr "pasting text..."
 		pdtk_pastetext
@@ -1756,66 +1754,40 @@ proc menu_mycnv {name accel} {
 
 # correct edit menu, enabling or disabling undo/redo/cut/copy/paste
 proc menu_fixeditmenu {name} {
-	catch {
-		# pdtk_post "fixeditmenu $name\n"
-
-		global pd_undoaction
-		global pd_redoaction
-		global pd_undocanvas
-
-		global global_selection
-		global global_clipboard
-		global last_clipboard
-
-		# investigate if we have already something copied from an external source
-		set current_clipboard 0
-		catch {set current_clipboard [clipboard get]}
-		if {$current_clipboard != 0} {
-			# make sure the clipboard contents have not changed
-			if { [string compare $last_clipboard $current_clipboard] } {
-				set data [split $current_clipboard "\n"]
-				set first 0
-				foreach line $data { 
-					if { !$first } {
-						pd [concat $name copyfromexternalbuffer\;]
-						pd [concat $name copyfromexternalbuffer $line\;]
-						set first 1
-					} else {
-						pd [concat $name copyfromexternalbuffer $line\;]
-					}
-				}
-				set global_clipboard 1
-				set last_clipboard $current_clipboard
-				pdtk_canvas_update_edit_menu $name 1
-			}
-		}
+	# pdtk_post "fixeditmenu $name\n"
 
-		#    puts stderr [concat menu_fixeditmenu $name $pd_undocanvas $pd_undoaction]
-		if {$name == $pd_undocanvas && $pd_undoaction != "no"} {
-		    $name.m.edit entryconfigure "Undo*" -state normal \
-		        -label [concat "Undo " $pd_undoaction]
-		} else {
-		    $name.m.edit entryconfigure "Undo*" -state disabled -label "Undo"
-		}
-		if {$name == $pd_undocanvas && $pd_redoaction != "no"} {
-		    $name.m.edit entryconfigure "Redo*" -state normal\
-		        -label [concat "Redo " $pd_redoaction]
-		} else {
-		    $name.m.edit entryconfigure "Redo*" -state disabled
-		}
+    global pd_undoaction
+    global pd_redoaction
+    global pd_undocanvas
 
-		if {$global_selection == 1} {
-		    $name.m.edit entryconfigure "Duplicate" -state normal
-		} else {
-		    $name.m.edit entryconfigure "Duplicate" -state disabled
-		}
+	global global_selection
+	global global_clipboard
 
-		if {$global_clipboard == 1} {
-		    $name.m.edit entryconfigure "Paste" -state normal
-		} else {
-		    $name.m.edit entryconfigure "Paste" -state disabled
-		}
-	}
+    #    puts stderr [concat menu_fixeditmenu $name $pd_undocanvas $pd_undoaction]
+    if {$name == $pd_undocanvas && $pd_undoaction != "no"} {
+        $name.m.edit entryconfigure "Undo*" -state normal \
+            -label [concat "Undo " $pd_undoaction]
+    } else {
+        $name.m.edit entryconfigure "Undo*" -state disabled -label "Undo"
+    }
+    if {$name == $pd_undocanvas && $pd_redoaction != "no"} {
+        $name.m.edit entryconfigure "Redo*" -state normal\
+            -label [concat "Redo " $pd_redoaction]
+    } else {
+        $name.m.edit entryconfigure "Redo*" -state disabled
+    }
+
+    if {$global_selection == 1} {
+        $name.m.edit entryconfigure "Duplicate" -state normal
+    } else {
+        $name.m.edit entryconfigure "Duplicate" -state disabled
+    }
+
+    if {$global_clipboard == 1} {
+        $name.m.edit entryconfigure "Paste" -state normal
+    } else {
+        $name.m.edit entryconfigure "Paste" -state disabled
+    }
 }
 
 # message from Pd to update the currently available undo/redo action
@@ -2457,6 +2429,7 @@ proc pdtk_canvas_new {name width height geometry editable} {
     }   
     bind $name.c <Map> {pdtk_canvas_map %W}
     bind $name.c <Unmap> {pdtk_canvas_unmap %W}
+    focus $name.c
 
     switch $pd_nt { 0 {
         bind $name.c <Button-4>  "pdtk_canvas_scroll $name.c y -1"
@@ -2481,7 +2454,6 @@ proc pdtk_canvas_new {name width height geometry editable} {
     set pdtk_canvas_mouseup_name ""
 
 	bind $name <FocusIn> "menu_fixeditmenu $name"
-    focus $name
 }
 
 #### jsarlo #####
diff --git a/src/test.pd b/src/test.pd
new file mode 100644
index 0000000000000000000000000000000000000000..bea66522bdb7a20b89eb047c3dd7958b6c18bedd
--- /dev/null
+++ b/src/test.pd
@@ -0,0 +1,6 @@
+#N canvas 1 52 450 300 10;
+#X obj 130 81 inlet;
+#X obj 130 103 + 1;
+#X obj 130 125 outlet;
+#X connect 0 0 1 0;
+#X connect 1 0 2 0;
diff --git a/tcl/pd_menus.tcl~ b/tcl/pd_menus.tcl~
new file mode 100644
index 0000000000000000000000000000000000000000..94e6a9cd53961ccd5993352df948359ab8d2002a
--- /dev/null
+++ b/tcl/pd_menus.tcl~
@@ -0,0 +1,473 @@
+# Copyright (c) 1997-2009 Miller Puckette.
+#(c) 2008 WordTech Communications LLC. License: standard Tcl license, http://www.tcl.tk/software/tcltk/license.html
+
+package provide pd_menus 0.1
+
+package require pd_menucommands
+package require Tk
+#package require tile
+## replace Tk widgets with Ttk widgets on 8.5
+#namespace import -force ttk::*
+
+# TODO figure out Undo/Redo/Cut/Copy/Paste state changes for menus
+# TODO figure out parent window/window list for Window menu
+# TODO what is the Tcl package constructor or init()?
+# TODO $::pd_menus::menubar or .menubar globally?
+
+# since there is one menubar that is used for all windows, the menu -commands
+# use {} quotes so that $::focused_window is interpreted when the menu item
+# is called, not when the command is mapped to the menu item.  This is the
+# opposite of the 'bind' commands in pd_bindings.tcl
+    
+
+# ------------------------------------------------------------------------------
+# global variables
+
+# TODO this should properly be inside the pd_menus namespace, now it is global
+namespace import ::pd_menucommands::* 
+
+namespace eval ::pd_menus:: {
+    variable accelerator
+    variable menubar ".menubar"
+    variable current_toplevel ".pdwindow"
+    
+    namespace export create_menubar
+    namespace export configure_for_pdwindow
+    namespace export configure_for_canvas
+    namespace export configure_for_dialog
+
+    # turn off tearoff menus globally
+    option add *tearOff 0
+}
+
+# ------------------------------------------------------------------------------
+# 
+proc ::pd_menus::create_menubar {} {
+    variable accelerator
+    variable menubar
+    if {$::windowingsystem eq "aqua"} {
+        set accelerator "Cmd"
+    } else {
+        set accelerator "Ctrl"
+    }
+    menu $menubar
+    set menulist "file edit put find media window help"
+    if { $::windowingsystem eq "aqua" } {create_apple_menu $menubar}
+    # FIXME why does the following (if uncommented) kill my menubar?
+    # if { $::windowingsystem eq "win32" } {create_system_menu $menubar}
+    foreach mymenu $menulist {    
+        menu $menubar.$mymenu
+        $menubar add cascade -label [_ [string totitle $mymenu]] \
+            -menu $menubar.$mymenu
+        [format build_%s_menu $mymenu] $menubar.$mymenu .
+        if {$::windowingsystem eq "win32"} {
+            # fix menu font size on Windows with tk scaling = 1
+            $menubar.$mymenu configure -font menufont
+        }
+    }
+}
+
+proc ::pd_menus::configure_for_pdwindow {} {
+    variable menubar
+    # these are meaningless for the Pd window, so disable them
+    set file_items_to_disable {"Save" "Save As..." "Print..." "Close"}
+    foreach menuitem $file_items_to_disable {
+        $menubar.file entryconfigure [_ $menuitem] -state disabled
+    }
+    set edit_items_to_disable {"Undo" "Redo" "Duplicate" "Tidy Up" "Edit Mode"}
+    foreach menuitem $edit_items_to_disable {
+        $menubar.edit entryconfigure [_ $menuitem] -state disabled
+    }
+    # disable everything on the Put menu
+    for {set i 0} {$i <= [$menubar.put index end]} {incr i} {
+        # catch errors that happen when trying to disable separators
+        catch {$menubar.put entryconfigure $i -state disabled }
+    }
+}
+
+proc ::pd_menus::configure_for_canvas {mytoplevel} {
+    variable menubar
+    set file_items_to_disable {"Save" "Save As..." "Print..." "Close"}
+    foreach menuitem $file_items_to_disable {
+        $menubar.file entryconfigure [_ $menuitem] -state normal
+    }
+    set edit_items_to_disable {"Undo" "Redo" "Duplicate" "Tidy Up" "Edit Mode"}
+    foreach menuitem $edit_items_to_disable {
+        $menubar.edit entryconfigure [_ $menuitem] -state normal
+    }
+    for {set i 0} {$i <= [$menubar.put index end]} {incr i} {
+        # catch errors that happen when trying to disable separators
+        catch {$menubar.put entryconfigure $i -state normal }
+    }
+    # TODO set "Edit Mode" state using editmode($mytoplevel)
+}
+
+proc ::pd_menus::configure_for_dialog {mytoplevel} {
+    variable menubar
+    # these are meaningless for the dialog panels, so disable them
+    set file_items_to_disable {"Save" "Save As..." "Print..." "Close"}
+    foreach menuitem $file_items_to_disable {
+        $menubar.file entryconfigure [_ $menuitem] -state disabled
+    }
+    set edit_items_to_disable {"Undo" "Redo" "Duplicate" "Tidy Up" "Edit Mode"}
+    foreach menuitem $edit_items_to_disable {
+        $menubar.edit entryconfigure [_ $menuitem] -state disabled
+    }
+    # disable everything on the Put menu
+    for {set i 0} {$i <= [$menubar.put index end]} {incr i} {
+        # catch errors that happen when trying to disable separators
+        catch {$menubar.put entryconfigure $i -state disabled }
+    }
+}
+
+
+# ------------------------------------------------------------------------------
+# menu building functions
+proc ::pd_menus::build_file_menu {mymenu mytoplevel} {
+    [format build_file_menu_%s $::windowingsystem] $mymenu
+    $mymenu entryconfigure [_ "New"]        -command {menu_new}
+    $mymenu entryconfigure [_ "Open"]       -command {menu_open}
+    $mymenu entryconfigure [_ "Save"]       -command {pdsend "$::focused_window menusave"}
+    $mymenu entryconfigure [_ "Save As..."] -command {pdsend "$::focused_window menusaveas"}
+    #$mymenu entryconfigure [_ "Revert*"]    -command {menu_revert $current_toplevel}
+    $mymenu entryconfigure [_ "Close"]      -command {pdsend "$::focused_window menuclose 0"}
+    $mymenu entryconfigure [_ "Message"]    -command {menu_message_dialog}
+    $mymenu entryconfigure [_ "Print..."]   -command {menu_print $::focused_window}
+}
+
+proc ::pd_menus::build_edit_menu {mymenu mytoplevel} {
+    variable accelerator
+    $mymenu add command -label [_ "Undo"]       -accelerator "$accelerator+Z" \
+        -command {menu_undo $::focused_window}
+    $mymenu add command -label [_ "Redo"]       -accelerator "Shift+$accelerator+Z" \
+        -command {menu_redo $::focused_window}
+    $mymenu add  separator
+    $mymenu add command -label [_ "Cut"]        -accelerator "$accelerator+X" \
+        -command {pdsend "$::focused_window cut"}
+    $mymenu add command -label [_ "Copy"]       -accelerator "$accelerator+C" \
+        -command {pdsend "$::focused_window copy"}
+    $mymenu add command -label [_ "Paste"]      -accelerator "$accelerator+V" \
+        -command {pdsend "$::focused_window paste"}
+    $mymenu add command -label [_ "Duplicate"]  -accelerator "$accelerator+D" \
+        -command {pdsend "$::focused_window duplicate"}
+    $mymenu add command -label [_ "Select All"] -accelerator "$accelerator+A" \
+        -command {pdsend "$::focused_window selectall"}
+    $mymenu add  separator
+    if {$::windowingsystem eq "aqua"} {
+        $mymenu add command -label [_ "Text Editor"] \
+            -command {menu_texteditor $::focused_window}
+        $mymenu add command -label [_ "Font"]  -accelerator "$accelerator+T" \
+            -command {menu_font_dialog $::focused_window}
+    } else {
+        $mymenu add command -label [_ "Text Editor"] -accelerator "$accelerator+T"\
+            -command {menu_texteditor $::focused_window}
+        $mymenu add command -label [_ "Font"] \
+            -command {menu_font_dialog $::focused_window}
+    }
+    $mymenu add command -label [_ "Tidy Up"] \
+        -command {pdsend "$::focused_window tidy"}
+    $mymenu add command -label [_ "Toggle Console"] -accelerator "Shift+$accelerator+R" \
+        -command {.controls.switches.console invoke}
+    $mymenu add command -label [_ "Clear Console"] -accelerator "Shift+$accelerator+L" \
+        -command {menu_clear_console}
+    $mymenu add  separator
+	$mymenu add checkbutton -label [_ "Edit Mode"] \
+		-accelerator "$accelerator+E" -variable ::editmode_button \
+        -command {menu_editmode $::editmode_button}
+		-command {pdsend "$::focused_window editmode 0"}
+    #if { ! [catch {console hide}]} { 
+    # TODO set up menu item to show/hide the Tcl/Tk console, if it available
+    #}
+
+    if {$::windowingsystem ne "aqua"} {
+        $mymenu add  separator
+        $mymenu add command -label [_ "Preferences"] \
+            -command {menu_preferences_dialog}
+    }
+}
+
+proc ::pd_menus::build_put_menu {mymenu mytoplevel} {
+    variable accelerator
+    $mymenu add command -label [_ "Object"] -accelerator "$accelerator+1" \
+        -command {pdsend "$::focused_window obj 0"} 
+    $mymenu add command -label [_ "Message"] -accelerator "$accelerator+2" \
+        -command {pdsend "$::focused_window msg 0"}
+    $mymenu add command -label [_ "Number"] -accelerator "$accelerator+3" \
+        -command {pdsend "$::focused_window floatatom  0"}
+    $mymenu add command -label [_ "Symbol"] -accelerator "$accelerator+4" \
+        -command {pdsend "$::focused_window symbolatom  0"}
+    $mymenu add command -label [_ "Comment"] -accelerator "$accelerator+5" \
+        -command {pdsend "$::focused_window text  0"}
+    $mymenu add  separator
+    $mymenu add command -label [_ "Bang"]    -accelerator "Shift+$accelerator+B" \
+        -command {pdsend "$::focused_window bng  0"}
+    $mymenu add command -label [_ "Toggle"]  -accelerator "Shift+$accelerator+T" \
+        -command {pdsend "$::focused_window toggle  0"}
+    $mymenu add command -label [_ "Number2"] -accelerator "Shift+$accelerator+N" \
+        -command {pdsend "$::focused_window numbox  0"}
+    $mymenu add command -label [_ "Vslider"] -accelerator "Shift+$accelerator+V" \
+        -command {pdsend "$::focused_window vslider  0"}
+    $mymenu add command -label [_ "Hslider"] -accelerator "Shift+$accelerator+H" \
+        -command {pdsend "$::focused_window hslider  0"}
+    $mymenu add command -label [_ "Vradio"]  -accelerator "Shift+$accelerator+D" \
+        -command {pdsend "$::focused_window vradio  0"}
+    $mymenu add command -label [_ "Hradio"]  -accelerator "Shift+$accelerator+I" \
+        -command {pdsend "$::focused_window hradio  0"}
+    $mymenu add command -label [_ "VU Meter"] -accelerator "Shift+$accelerator+U"\
+        -command {pdsend "$::focused_window vumeter  0"}
+    $mymenu add command -label [_ "Canvas"]  -accelerator "Shift+$accelerator+C" \
+        -command {pdsend "$::focused_window mycnv  0"}
+    $mymenu add  separator
+    $mymenu add command -label [_ "Graph"] -command {pdsend "$::focused_window graph"} 
+    $mymenu add command -label [_ "Array"] -command {pdsend "$::focused_window menuarray"}
+}
+
+proc ::pd_menus::build_find_menu {mymenu mytoplevel} {
+    variable accelerator
+    $mymenu add command -label [_ "Find..."]    -accelerator "$accelerator+F" \
+        -command {::dialog_find::menu_find_dialog $::focused_window}
+    $mymenu add command -label [_ "Find Again"] -accelerator "$accelerator+G" \
+        -command {pdsend "$::focused_window findagain"}
+    $mymenu add command -label [_ "Find Last Error"] \
+        -command {pdsend "$::focused_window finderror"} 
+}
+
+proc ::pd_menus::build_media_menu {mymenu mytoplevel} {
+    variable accelerator
+    $mymenu add radiobutton -label [_ "DSP On"] -accelerator "$accelerator+/" \
+        -variable ::dsp -value 1 -command {pdsend "pd dsp 1"}
+    $mymenu add radiobutton -label [_ "DSP Off"] -accelerator "$accelerator+." \
+        -variable ::dsp -value 0 -command {pdsend "pd dsp 0"}
+    $mymenu add  separator
+
+    set audioapi_list_length [llength $::audioapi_list]
+    for {set x 0} {$x<$audioapi_list_length} {incr x} {
+        # pdtk_post "audio [lindex [lindex $::audioapi_list $x] 0]"
+        $mymenu add radiobutton -label [lindex [lindex $::audioapi_list $x] 0] \
+            -command {menu_audio 0} -variable ::pd_whichapi \
+            -value [lindex [lindex $::audioapi_list $x] 1]\
+            -command {pdsend "pd audio-setapi $::pd_whichapi"}
+    }
+    if {$audioapi_list_length > 0} {$mymenu add separator}
+
+    set midiapi_list_length [llength $::midiapi_list]
+    for {set x 0} {$x<$midiapi_list_length} {incr x} {
+        # pdtk_post "midi [lindex [lindex $::midiapi_list $x] 0]"
+        $mymenu add radiobutton -label [lindex [lindex $::midiapi_list $x] 0] \
+            -command {menu_midi 0} -variable ::pd_whichmidiapi \
+            -value [lindex [lindex $::midiapi_list $x] 1]\
+            -command {pdsend "pd midi-setapi $::pd_whichmidiapi"}
+    }
+    if {$midiapi_list_length > 0} {$mymenu add separator}
+
+    if {$::windowingsystem ne "aqua"} {
+        $mymenu add command -label [_ "Audio settings..."] \
+            -command {pdsend "pd audio-properties"}
+        $mymenu add command -label [_ "MIDI settings..."] \
+            -command {pdsend "pd midi-properties"} 
+        $mymenu add  separator
+    }
+    $mymenu add command -label [_ "Test Audio and MIDI..."] \
+        -command {menu_doc_open doc/7.stuff/tools testtone.pd} 
+    $mymenu add command -label [_ "Load Meter"] \
+        -command {menu_doc_open doc/7.stuff/tools load-meter.pd} 
+}
+
+proc ::pd_menus::build_window_menu {mymenu mytoplevel} {
+    variable accelerator
+    if {$::windowingsystem eq "aqua"} {
+        $mymenu add command -label [_ "Minimize"] -command {menu_minimize .} \
+            -accelerator "$accelerator+M"
+        $mymenu add command -label [_ "Zoom"] -command {menu_zoom .}
+        $mymenu add  separator
+    }
+    $mymenu add command -label [_ "Parent Window"] \
+        -command {pdsend "$::focused_window findparent"}
+    $mymenu add command -label [_ "Pd window"] -command {menu_raise_pdwindow} \
+        -accelerator "$accelerator+R"
+    $mymenu add  separator
+    if {$::windowingsystem eq "aqua"} {
+        $mymenu add command -label [_ "Bring All to Front"] \
+            -command {menu_bringalltofront}
+        $mymenu add  separator
+    }
+}
+
+proc ::pd_menus::build_help_menu {mymenu mytoplevel} {
+    if {$::windowingsystem ne "aqua"} {
+        $mymenu add command -label [_ "About Pd"] \
+            -command {menu_doc_open doc/1.manual 1.introduction.txt} 
+    }
+    $mymenu add command -label [_ "HTML Manual..."] \
+        -command {menu_doc_open doc/1.manual index.htm}
+    $mymenu add command -label [_ "Browser..."] \
+        -command {placeholder menu_helpbrowser \$help_top_directory} 
+}
+
+# ------------------------------------------------------------------------------
+# update the menu entries for opening recent files
+proc ::pd_menus::update_recentfiles_menu {} {
+    variable menubar
+    switch -- $::windowingsystem {
+        "aqua" {::pd_menus::update_openrecent_menu_aqua .openrecent}
+        "win32" {update_recentfiles_on_menu $menubar.file}
+        "x11" {update_recentfiles_on_menu $menubar.file}
+    }
+}
+
+proc ::pd_menus::clear_recentfiles_menu {} {
+    set ::recentfiles_list {}
+    ::pd_menus::update_recentfiles_menu
+}
+
+proc ::pd_menus::update_openrecent_menu_aqua {mymenu} {
+    if {! [winfo exists $mymenu]} {menu $mymenu}
+    $mymenu delete 0 end
+    foreach filename $::recentfiles_list {
+        puts "creating menu item for $filename"
+        $mymenu add command -label [file tail $filename] \
+            -command "open_file $filename"
+    }
+    $mymenu add  separator
+    $mymenu add command -label [_ "Clear Menu"] \
+        -command "::pd_menus::clear_recentfiles_menu"
+}
+
+# this expects to be run on the File menu, and to insert above the last separator
+proc ::pd_menus::update_recentfiles_on_menu {mymenu} {
+    set lastitem [$mymenu index end]
+    set i 1
+    while {[$mymenu type [expr $lastitem-$i]] ne "separator"} {incr i}
+    set bottom_separator [expr $lastitem-$i]
+    incr i
+    while {[$mymenu type [expr $lastitem-$i]] ne "separator"} {incr i}
+    set top_separator [expr $lastitem-$i]
+    if {$top_separator < [expr $bottom_separator-1]} {
+        $mymenu delete [expr $top_separator+1] [expr $bottom_separator-1]
+    }
+    set i 0
+    foreach filename $::recentfiles_list {
+        $mymenu insert [expr $top_separator+$i+1] command \
+            -label [file tail $filename] -command "open_file $filename"
+        incr i
+    }
+}
+
+# ------------------------------------------------------------------------------
+# menu building functions for Mac OS X/aqua
+
+# for Mac OS X only
+proc ::pd_menus::create_apple_menu {mymenu} {
+    # TODO this should open a Pd patch called about.pd
+    menu $mymenu.apple
+    $mymenu.apple add command -label [_ "About Pd"] \
+        -command {menu_doc_open doc/1.manual 1.introduction.txt} 
+    $mymenu add cascade -label "Apple" -menu $mymenu.apple
+    $mymenu.apple add  separator
+    # starting in 8.4.14, this is created automatically
+    set patchlevel [split [info patchlevel] .]
+    if {[lindex $patchlevel 1] < 5 && [lindex $patchlevel 2] < 14} {
+        $mymenu.apple add command -label [_ "Preferences..."] \
+            -command {menu_preferences_dialog" -accelerator "Cmd+,}
+    }
+}
+
+proc ::pd_menus::build_file_menu_aqua {mymenu} {
+    variable accelerator
+    $mymenu add command -label [_ "New"]       -accelerator "$accelerator+N"
+    $mymenu add command -label [_ "Open"]      -accelerator "$accelerator+O"
+    ::pd_menus::update_openrecent_menu_aqua .openrecent
+    $mymenu add cascade -label [_ "Open Recent"] -menu .openrecent
+    $mymenu add  separator
+    $mymenu add command -label [_ "Close"]     -accelerator "$accelerator+W"
+    $mymenu add command -label [_ "Save"]      -accelerator "$accelerator+S"
+    $mymenu add command -label [_ "Save As..."] -accelerator "$accelerator+Shift+S"
+    #$mymenu add command -label [_ "Save All"]
+    #$mymenu add command -label [_ "Revert to Saved"]
+    $mymenu add  separator
+    $mymenu add command -label [_ "Message"]
+    $mymenu add  separator
+    $mymenu add command -label [_ "Print..."]   -accelerator "$accelerator+P"
+}
+
+# the "Edit", "Put", and "Find" menus do not have cross-platform differences
+
+proc ::pd_menus::build_media_menu_aqua {mymenu} {
+}
+
+proc ::pd_menus::build_window_menu_aqua {mymenu} {
+}
+
+# the "Help" does not have cross-platform differences
+ 
+# ------------------------------------------------------------------------------
+# menu building functions for UNIX/X11
+
+proc ::pd_menus::build_file_menu_x11 {mymenu} {
+    variable accelerator
+    $mymenu add command -label [_ "New"]        -accelerator "$accelerator+N"
+    $mymenu add command -label [_ "Open"]       -accelerator "$accelerator+O"
+    $mymenu add  separator
+    $mymenu add command -label [_ "Save"]       -accelerator "$accelerator+S"
+    $mymenu add command -label [_ "Save As..."] -accelerator "Shift+$accelerator+S"
+    #    $mymenu add command -label "Revert"
+    $mymenu add  separator
+    $mymenu add command -label [_ "Message"]    -accelerator "$accelerator+M"
+    $mymenu add command -label [_ "Print..."]   -accelerator "$accelerator+P"
+    $mymenu add  separator
+    # the recent files get inserted in here by update_recentfiles_on_menu
+    $mymenu add  separator
+    $mymenu add command -label [_ "Close"]      -accelerator "$accelerator+W"
+    $mymenu add command -label [_ "Quit"]       -accelerator "$accelerator+Q" \
+        -command {pdsend "pd verifyquit"}
+}
+
+# the "Edit", "Put", and "Find" menus do not have cross-platform differences
+
+proc ::pd_menus::build_media_menu_x11 {mymenu} {
+}
+
+proc ::pd_menus::build_window_menu_x11 {mymenu} {
+}
+
+# the "Help" does not have cross-platform differences
+
+# ------------------------------------------------------------------------------
+# menu building functions for Windows/Win32
+
+# for Windows only
+proc ::pd_menus::create_system_menu {mymenu} {
+    $mymenu add cascade -menu [menu $mymenu.system]
+    # TODO add Close, Minimize, etc and whatever else is on the little menu
+    # that is on the top left corner of the window frame
+}
+
+proc ::pd_menus::build_file_menu_win32 {mymenu} {
+    variable accelerator
+    $mymenu add command -label [_ "New"]      -accelerator "$accelerator+N"
+    $mymenu add command -label [_ "Open"]     -accelerator "$accelerator+O"
+    $mymenu add  separator
+    $mymenu add command -label [_ "Save"]      -accelerator "$accelerator+S"
+    $mymenu add command -label [_ "Save As..."] -accelerator "Shift+$accelerator+S"
+    #    $mymenu add command -label "Revert"
+    $mymenu add  separator
+    $mymenu add command -label [_ "Message"]  -accelerator "$accelerator+M"
+    $mymenu add command -label [_ "Print..."] -accelerator "$accelerator+P"
+    $mymenu add  separator
+    # the recent files get inserted in here by update_recentfiles_on_menu
+    $mymenu add  separator
+    $mymenu add command -label [_ "Close"]    -accelerator "$accelerator+W"
+    $mymenu add command -label [_ "Quit"]     -accelerator "$accelerator+Q"\
+        -command {pdsend "pd verifyquit"}
+}
+
+# the "Edit", "Put", and "Find" menus do not have cross-platform differences
+
+proc ::pd_menus::build_media_menu_win32 {mymenu} {
+}
+
+proc ::pd_menus::build_window_menu_win32 {mymenu} {
+}
+
+# the "Help" does not have cross-platform differences
+