[PD-cvs] externals/maxlib/src allow.c,1.3,1.4 arbran.c,1.6,1.7 arraycopy.c,1.3,1.4 average.c,1.4,1.5 beat.c,1.4,1.5 beta.c,1.5,1.6 bilex.c,1.4,1.5 borax.c,1.4,1.5 cauchy.c,1.4,1.5 chord.c,1.5,1.6 delta.c,1.4,1.5 deny.c,1.3,1.4 dist.c,1.4,1.5 divide.c,1.4,1.5 divmod.c,1.4,1.5 edge.c,1.4,1.5 expo.c,1.5,1.6 fifo.c,1.5,1.6 gauss.c,1.4,1.5 gestalt.c,1.5,1.6 history.c,1.4,1.5 ignore.c,1.4,1.5 iso.c,1.4,1.5 lifo.c,1.5,1.6 limit.c,1.4,1.5 linear.c,1.5,1.6 listfifo.c,1.3,1.4 listfunnel.c,1.4,1.5 match.c,1.4,1.5 minus.c,1.4,1.5 mlife.c,1.5,1.6 multi.c,1.4,1.5 nchange.c,1.3,1.4 netclient.c,1.8,1.9 netdist.c,1.7,1.8 netrec.c,1.9,1.10 netserver.c,1.9,1.10 nroute.c,1.5,1.6 pitch.c,1.5,1.6 plus.c,1.5,1.6 poisson.c,1.5,1.6 pong.c,1.5,1.6 pulse.c,1.5,1.6 remote.c,1.6,1.7 rewrap.c,1.5,1.6 rhythm.c,1.5,1.6 scale.c,1.4,1.5 score.c,1.5,1.6 speedlim.c,1.4,1.5 split.c,1.4,1.5 step.c,1.5,1.6 subst.c,1.5,1.6 sync.c,1.3,1.4 temperature.c,1.5,1.6 tilt.c,1.5,1.6 timebang.c,1.4,1.5 triang.c,1.5,1.6 unroute.c,1.5,1.6 urn.c,1.5,1.6 velocity.c,1.4,1.5 weibull.c,1.4,1.5 wrap.c,1.4,1.5

Hans-Christoph Steiner eighthave at users.sourceforge.net
Sat Mar 20 06:56:33 CET 2004


Update of /cvsroot/pure-data/externals/maxlib/src
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv2641/src

Added Files:
	allow.c arbran.c arraycopy.c average.c beat.c beta.c bilex.c 
	borax.c cauchy.c chord.c delta.c deny.c dist.c divide.c 
	divmod.c edge.c expo.c fifo.c gauss.c gestalt.c history.c 
	ignore.c iso.c lifo.c limit.c linear.c listfifo.c listfunnel.c 
	match.c minus.c mlife.c multi.c nchange.c netclient.c 
	netdist.c netrec.c netserver.c nroute.c pitch.c plus.c 
	poisson.c pong.c pulse.c remote.c rewrap.c rhythm.c scale.c 
	score.c speedlim.c split.c step.c subst.c sync.c temperature.c 
	tilt.c timebang.c triang.c unroute.c urn.c velocity.c 
	weibull.c wrap.c 
Log Message:
things back to Olaf's 1.5.2

--- NEW FILE: borax.c ---
/* ------------------------- borax   ------------------------------------------ */
/*                                                                              */
/* "swiss army knife" for music analysis. Inspired by 'borax' for Max.          */
/* Written by Olaf Matthes (olaf.matthes at gmx.de)                                */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

#include "m_pd.h"

#define MAX_POLY 128                /* maximum number of notes played at a time */

static char *version = "borax v0.1, written by Olaf Matthes <olaf.matthes at gmx.de>";
 
typedef struct borax
{
  t_object x_ob;
  t_inlet  *x_invelo;               /* inlet for velocity */
  t_inlet  *x_inreset;              /* inlet to reset the object */
  t_outlet *x_outnotecount;         /* counts notes */
  t_outlet *x_outvoicealloc;        /* assigns every note a unique number */
  t_outlet *x_outpoly;              /* number of notes playing (polyphony) */
  t_outlet *x_outpitch;             /* pitch of current note */
  t_outlet *x_outvelo;              /* velocity of current note */
  t_outlet *x_outdurcount;          /* number assigned to duration value */
  t_outlet *x_outdurval;            /* duration value */
  t_outlet *x_outtimecount;         /* number assigned to delta time value */
  t_outlet *x_outtimeval;           /* delta time value */


  t_float  x_notecount;
  t_int    x_pitch;
  t_int    x_velo;
  t_float  x_voicecount;
  t_int    x_voicealloc;
  t_int    x_poly;
  t_float  x_durcount;
  t_float  x_durval;
  t_float  x_timecount;
  t_float  x_timeval;
	/* helpers needed to do the calculations */
  double   x_starttime[MAX_POLY];
  double   x_laststarttime;
  t_int    x_alloctable[MAX_POLY];

} t_borax;

static void borax_float(t_borax *x, t_floatarg f)
{
	t_int velo = x->x_velo;
	t_int allloc = 0;
	int i;

	x->x_pitch = (t_int)f;

	if(velo == 0)
	{
			/* note off received... */
		if(x->x_poly > 0)x->x_poly--; /* polyphony has decreased by one */
		x->x_durcount++;              /* we can calculate the duration */
		for(i = 0; i < MAX_POLY; i++) /* search for voice allocation number */
		{
				/* search for corresponding alloc number */
			if(x->x_alloctable[i] == x->x_pitch)
			{
				x->x_voicealloc = i;
				x->x_alloctable[i] = 0;     /* free the alloc number */
				break;
			}
				/* couldn't find it ? */
			if(i == MAX_POLY - 1)
			{
				post("borax: no corresponding note-on found (ignored)");
				return;
			}
		}
		x->x_durval = clock_gettimesince(x->x_starttime[x->x_voicealloc]);
	}
	else if(velo != 0)
	{
			/* note on received... */
		x->x_poly++;                  /* number of currently playing notes has increased */
		x->x_notecount++;             /* total number of notes has increased */
			/* assign a voice allocation number */
		for(i = 0; i < MAX_POLY; i++)
		{
				/* search for free alloc number */
			if(x->x_alloctable[i] == 0)
			{
				x->x_voicealloc = i;               /* take the number */
				x->x_alloctable[i] = x->x_pitch;   /* ... and store pitch */
				break;
			}
				/* couldn't find any ? */
			if(i == MAX_POLY - 1)
			{
				post("borax: too many note-on messages (ignored)");
				return;
			}
		}
			/* calculate time in case it's not the first note */
		if(x->x_notecount > 1)
		{
			x->x_timecount++;
			x->x_timeval = clock_gettimesince(x->x_laststarttime);
		}
			/* save the new start time */
		x->x_laststarttime = x->x_starttime[x->x_voicealloc] = clock_getlogicaltime();
	}
		/* output values from right to left */
	outlet_float(x->x_outtimeval, x->x_timeval);
	outlet_float(x->x_outtimecount, x->x_timecount);
	outlet_float(x->x_outdurval, x->x_durval);
	outlet_float(x->x_outdurcount, x->x_durcount);
	outlet_float(x->x_outvelo, velo);
	outlet_float(x->x_outpitch, x->x_pitch);
	outlet_float(x->x_outpoly, x->x_poly);
	outlet_float(x->x_outvoicealloc, x->x_voicealloc);
	outlet_float(x->x_outnotecount, x->x_notecount);
}

static void borax_ft1(t_borax *x, t_floatarg f)
{
	x->x_velo = (t_int)f;
}

static void borax_reset(t_borax *x)
{
	int i;
	post("borax: reset");
	x->x_notecount = 0;
	x->x_pitch = 0;
	x->x_velo = 0;
	x->x_voicecount = 0;
	x->x_voicealloc = 0;
	x->x_poly = 0;
	x->x_durcount = 0;
	x->x_durval = 0;
	x->x_timecount = 0;
	x->x_timeval = 0;
	outlet_float(x->x_outtimeval, x->x_timeval);
	outlet_float(x->x_outtimecount, x->x_timecount);
	outlet_float(x->x_outdurval, x->x_durval);
	outlet_float(x->x_outdurcount, x->x_durcount);
	for(i = 0; i < MAX_POLY; i++)
	{	
		if(x->x_alloctable[i] != 0)
		{
			x->x_poly--;
				/* send note-off */
			outlet_float(x->x_outvelo, 0);
			outlet_float(x->x_outpitch, x->x_alloctable[i]);
			outlet_float(x->x_outpoly, x->x_poly);
			outlet_float(x->x_outvoicealloc, i);
		}
		x->x_alloctable[i] = 0;
	}
	outlet_float(x->x_outvelo, x->x_velo);
	outlet_float(x->x_outpitch, x->x_pitch);
	outlet_float(x->x_outpoly, x->x_poly);
	outlet_float(x->x_outvoicealloc, x->x_voicealloc);
	outlet_float(x->x_outnotecount, x->x_notecount);
}

static t_class *borax_class;

static void *borax_new(void)
{
	int i;

    t_borax *x = (t_borax *)pd_new(borax_class);
    x->x_invelo = inlet_new(&x->x_ob, &x->x_ob.ob_pd, gensym("float"), gensym("ft1"));
    x->x_inreset = inlet_new(&x->x_ob, &x->x_ob.ob_pd, gensym("bang"), gensym("ft2"));
	x->x_outnotecount = outlet_new(&x->x_ob, gensym("float"));
	x->x_outvoicealloc = outlet_new(&x->x_ob, gensym("float"));
	x->x_outpoly = outlet_new(&x->x_ob, gensym("float"));
	x->x_outpitch = outlet_new(&x->x_ob, gensym("float"));
	x->x_outvelo = outlet_new(&x->x_ob, gensym("float"));
	x->x_outdurcount = outlet_new(&x->x_ob, gensym("float"));
	x->x_outdurval = outlet_new(&x->x_ob, gensym("float"));
	x->x_outtimecount = outlet_new(&x->x_ob, gensym("float"));
	x->x_outtimeval = outlet_new(&x->x_ob, gensym("float"));

	for(i = 0; i < MAX_POLY; i++)x->x_alloctable[i] = 0;
	x->x_notecount = 0;
	x->x_pitch = 0;
	x->x_velo = 0;
	x->x_voicecount = 0;
	x->x_voicealloc = 0;
	x->x_poly = 0;
	x->x_durcount = 0;
	x->x_durval = 0;
	x->x_timecount = 0;
	x->x_timeval = 0;

    return (void *)x;
}

#ifndef MAXLIB
void borax_setup(void)
{
    borax_class = class_new(gensym("borax"), (t_newmethod)borax_new,
    	0, sizeof(t_borax), 0, 0);
#else
void maxlib_borax_setup(void)
{
    borax_class = class_new(gensym("maxlib_borax"), (t_newmethod)borax_new,
    	0, sizeof(t_borax), 0, 0);
#endif
    class_addmethod(borax_class, (t_method)borax_reset, gensym("reset"), 0);
    class_addmethod(borax_class, (t_method)borax_ft1, gensym("ft1"), A_FLOAT, 0);
    class_addmethod(borax_class, (t_method)borax_reset, gensym("ft2"), A_GIMME, 0);
    class_addfloat(borax_class, borax_float);
#ifndef MAXLIB
    class_sethelpsymbol(borax_class, gensym("help-borax.pd"));
    post(version);
#else
	class_addcreator((t_newmethod)borax_new, gensym("borax"), 0);
    class_sethelpsymbol(borax_class, gensym("maxlib/help-borax.pd"));
#endif
}


--- NEW FILE: temperature.c ---
/* -------------------------- temperature ------------------------------------- */
/*                                                                              */
/* Calculates temperature: number of 'events' within N milliseconds.            */
/* Written by Olaf Matthes <olaf.matthes at gmx.de>                                */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/              */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

#include "m_pd.h"
#include <math.h>

static char *version = "temperature v0.1, written by Olaf Matthes <olaf.matthes at gmx.de>";
 
typedef struct temperature
{
  t_object x_ob;
  t_clock  *x_clock;
  t_outlet *x_outfloat;             /* output the temperature */
  t_int    x_index;                 /* the number of elements to average */
  t_int    x_time;

} t_temperature;

static void temperature_tick(t_temperature *x)
{
	outlet_float(x->x_outfloat, x->x_index);
	x->x_index = 0;
	clock_delay(x->x_clock, x->x_time);
}

static void temperature_float(t_temperature *x, t_floatarg f)
{
	x->x_index++;	/* just count number of 'events' */
}

static void temperature_anything(t_temperature *x, t_symbol *s, int argc, t_atom *argv)
{
	x->x_index++;	/* just count number of 'events' */
}

static void temperature_time(t_temperature *x, t_floatarg f)
{
	x->x_time = (t_int)f;
	if(x->x_time < 1) x->x_time = 1;
	clock_unset(x->x_clock);
	clock_delay(x->x_clock, x->x_time);
}

static void temperature_reset(t_temperature *x)
{
	x->x_index = 0;
    post("temperature: reset");
}

static void temperature_free(t_temperature *x)
{
	clock_free(x->x_clock);
}

static t_class *temperature_class;

static void *temperature_new(t_floatarg f)
{
    t_temperature *x = (t_temperature *)pd_new(temperature_class);
	inlet_new(&x->x_ob, &x->x_ob.ob_pd, gensym("float"), gensym("time"));
	x->x_outfloat = outlet_new(&x->x_ob, gensym("float"));
	x->x_clock = clock_new(x, (t_method)temperature_tick);

	x->x_time = (t_int)f;
	if(x->x_time < 1)
	{
		x->x_time = 1;
		post("temperature: set time to %d ms", x->x_time);
	}
	x->x_index = 0;
	clock_delay(x->x_clock, x->x_time);
    return (void *)x;
}

#ifndef MAXLIB
void temperature_setup(void)
{
    temperature_class = class_new(gensym("temperature"), (t_newmethod)temperature_new,
    	(t_method)temperature_free, sizeof(t_temperature), 0, A_DEFFLOAT, 0);
    class_addmethod(temperature_class, (t_method)temperature_reset, gensym("reset"), 0);
    class_addfloat(temperature_class, temperature_float);
	class_addmethod(temperature_class, (t_method)temperature_time, gensym("time"), A_FLOAT, 0);
	class_addanything(temperature_class, temperature_anything);
    class_sethelpsymbol(temperature_class, gensym("help-temperature.pd"));
    post(version);
}
#else
void maxlib_temperature_setup(void)
{
    temperature_class = class_new(gensym("maxlib_temperature"), (t_newmethod)temperature_new,
    	(t_method)temperature_free, sizeof(t_temperature), 0, A_DEFFLOAT, 0);
	class_addcreator((t_newmethod)temperature_new, gensym("temperature"), A_DEFFLOAT, 0);
    class_addmethod(temperature_class, (t_method)temperature_reset, gensym("reset"), 0);
    class_addfloat(temperature_class, temperature_float);
	class_addmethod(temperature_class, (t_method)temperature_time, gensym("time"), A_FLOAT, 0);
	class_addanything(temperature_class, temperature_anything);
    class_sethelpsymbol(temperature_class, gensym("maxlib/help-temperature.pd"));
}
#endif

--- NEW FILE: edge.c ---
/* ---------------------------  edge  ----------------------------------------- */
/*                                                                              */
/* Detect rising or falling edge of float input.                                */
/* Written by Olaf Matthes (olaf.matthes at gmx.de)                                */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

#include "m_pd.h"
#include <stdio.h>

static char *version = "edge v0.1, written by Olaf Matthes <olaf.matthes at gmx.de>";
 
typedef struct edge
{
  t_object x_ob;
  t_outlet *x_out1;                 /* bang on rising edge */
  t_outlet *x_out2;                 /* bang on falling edge */
  t_float  x_lastval;               /* last input value */
} t_edge;

static void edge_float(t_edge *x, t_floatarg f)
{
	if((x->x_lastval <= 0) && (f >= 1))	/* rising edge */
		outlet_bang(x->x_out1);
	else if((x->x_lastval >= 1) && (f <= 0))	/* falling edge */
		outlet_bang(x->x_out2);

	x->x_lastval = f;	/* save last value */
}

static t_class *edge_class;

static void *edge_new(t_floatarg f)
{
	int i;

    t_edge *x = (t_edge *)pd_new(edge_class);
	x->x_out1 = outlet_new(&x->x_ob, gensym("bang"));
	x->x_out2 = outlet_new(&x->x_ob, gensym("bang"));

	x->x_lastval = f;

    return (void *)x;
}

#ifndef MAXLIB
void edge_setup(void)
{
    edge_class = class_new(gensym("edge"), (t_newmethod)edge_new,
    	0, sizeof(t_edge), 0, A_DEFFLOAT, 0);
    class_addfloat(edge_class, edge_float);
    class_sethelpsymbol(edge_class, gensym("help-edge.pd"));
    post(version);
}
#else
void maxlib_edge_setup(void)
{
    edge_class = class_new(gensym("maxlib_edge"), (t_newmethod)edge_new,
    	0, sizeof(t_edge), 0, A_DEFFLOAT, 0);
    class_addfloat(edge_class, edge_float);
	class_addcreator((t_newmethod)edge_new, gensym("edge"), A_DEFFLOAT, 0);
    class_sethelpsymbol(edge_class, gensym("maxlib/help-edge.pd"));
}
#endif


--- NEW FILE: iso.c ---
/* ---------------------------- iso ------------------------------------------- */
/*                                                                              */
/* Queue up pitch and attack point series.                                      */
/* Written by Olaf Matthes (olaf.matthes at gmx.de)                                */
/* Based on iso for Max by Charlie Baker (baker at foxtrot.ccmrc.ucsb.edu).        */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

#include "m_pd.h"
#include <stdio.h>

#define MAXPOLY 32

static char *version = "iso v0.1, written for Max by Charlie Baker <baker at foxtrot.ccmrc.ucsb.edu>\n"
                       "          ported to Pd by Olaf Matthes <olaf.matthes at gmx.de>";

/* Iso object data structure */

typedef struct iso
{
	t_object iso_ob;		
	t_outlet *iso_out1;			/* outlet 1*/
	t_outlet *iso_out2;			/* outlet 2*/
	t_inlet *iso_in2;           /* inlet 2 (attack list) */
	t_clock *iso_clock;
	t_int ptchlength,atklength,curptch,curatk;
	t_float pitches[MAXPOLY];   
	t_float atks[MAXPOLY];
	t_int loop,stop;
	t_float hook,duty;
} t_iso;

static t_class *iso_class;

/* take list and create matrix */

static void iso_bang(t_iso *x)
{
	x->stop = 0;
	x->curptch = 0;
	x->curatk = 0;
	clock_delay(x->iso_clock, 0);
}


static void iso_clock_fun(t_iso *x)
{
	if (!x->stop) {
		clock_delay(x->iso_clock, (double)(x->atks[x->curatk] * x->hook)); 
		outlet_float(x->iso_out2,(t_float)(x->atks[x->curatk] * x->hook * x->duty)); 
		outlet_float(x->iso_out1,x->pitches[x->curptch] );
		if (x->loop) {
				x->curatk = ((x->curatk + 1) % x->atklength);
				x->curptch = ((x->curptch + 1) % x->ptchlength);
		}
		else {
			if (((x->curatk + 1) >= x->atklength) || ((x->curptch + 1) >= x->ptchlength)) 
				 x->stop = 1;
			else { 
				x->curptch += 1;
				x->curatk += 1;
			}
		}
	}
}

static void iso_hook(t_iso *x, t_floatarg hook)
{
	if (hook < 1.0) hook = 1.0;
	x->hook = (t_float)hook;
}
	
static void iso_duty(t_iso *x, t_floatarg duty)
{
	if (duty < 1.0) duty = 1.0;
	x->duty = (t_float)duty;
}

static void iso_list(t_iso *x, t_symbol *s, t_int argc, t_atom* argv)
{
	int i;
	if (argc > MAXPOLY) post("iso: only %d values max. allowed in list!", MAXPOLY);
	for (i = 0; i < argc; i++) x->atks[i] = argv[i].a_w.w_float;
	x->atklength = argc;
}

static void iso_pitch(t_iso *x, t_symbol *s, t_int argc, t_atom* argv)
{
	int i;
	if (argc > MAXPOLY) post("iso: only %d values max. allowed in list!", MAXPOLY);
	for (i = 0; i < argc; i++)  x->pitches[i] = argv[i].a_w.w_float;
	x->ptchlength = argc;
}

static void iso_start(t_iso *x, t_symbol *s, t_int argc, t_atom* argv)
{
	t_int start = atom_getfloatarg(0, argc, argv);
	x->stop = 0;
	if (start) {
		x->curptch = (t_int)((start - 1) % x->ptchlength);
		x->curatk = (t_int)((start - 1) % x->atklength);
			   }
	else	{
		x->curptch = 0;
		x->curatk = 0;
	}
	clock_delay(x->iso_clock, 0);
}

static void iso_stop(t_iso *x)
{
	x->stop = 1;
	x->curatk = 0;
	x->curptch = 0;
}

static void iso_pause(t_iso *x)
{
	x->stop = 1;
}

static void iso_loop(t_iso *x)
{
	x->loop = 1;
}

static void iso_resume(t_iso *x)
{
	x->stop = 0;
	clock_delay(x->iso_clock, 0);
}

static void iso_unloop(t_iso *x)
{
	x->loop = 0;
}


static void *iso_new(void) {
	t_iso *x = (t_iso *)pd_new(iso_class);	/* allocates memory and sticks in an inlet */
	x->iso_clock = clock_new(x, (t_method)iso_clock_fun);
	x->iso_out1 = outlet_new(&x->iso_ob, gensym("float"));
	x->iso_out2 = outlet_new(&x->iso_ob, gensym("float"));
	x->iso_in2 = inlet_new(&x->iso_ob, &x->iso_ob.ob_pd, gensym("list"), gensym("attack"));
	x->stop = 0;
	x->loop = 1;
	x->hook = 1.0;
	x->curptch = 0;
	x->curatk = 0;
	x->ptchlength = 1;
	x->atklength = 1;
	x->pitches[0] = 60;
	x->atks[0] = 500;
	x->duty = 1.0;

	return (x);					/* always return a copy of the created object */
}

static void iso_free(t_iso *x) {

	clock_free(x->iso_clock);
}

#ifndef MAXLIB
void iso_setup(void) {

    iso_class = class_new(gensym("iso"), (t_newmethod)iso_new,
    	(t_method)iso_free, sizeof(t_iso), 0, 0);
    class_addmethod(iso_class, (t_method)iso_duty, gensym("duty"), A_FLOAT, 0);
	class_addmethod(iso_class, (t_method)iso_list, gensym("attack"), A_GIMME, 0);
    class_addmethod(iso_class, (t_method)iso_start, gensym("start"), A_GIMME, 0);
    class_addmethod(iso_class, (t_method)iso_stop, gensym("stop"), 0);
    class_addmethod(iso_class, (t_method)iso_pause, gensym("pause"), 0);
    class_addmethod(iso_class, (t_method)iso_loop, gensym("loop"), 0);
    class_addmethod(iso_class, (t_method)iso_unloop, gensym("unloop"), 0);
    class_addmethod(iso_class, (t_method)iso_resume, gensym("resume"), 0);
    class_addmethod(iso_class, (t_method)iso_hook, gensym("hook"), A_FLOAT, 0);
    class_addbang(iso_class, iso_bang);
	class_addlist(iso_class, iso_pitch);
    class_sethelpsymbol(iso_class, gensym("help-iso.pd"));
	post(version);
}
#else
void maxlib_iso_setup(void) {

    iso_class = class_new(gensym("maxlib_iso"), (t_newmethod)iso_new,
    	(t_method)iso_free, sizeof(t_iso), 0, 0);
	class_addcreator((t_newmethod)iso_new, gensym("iso"), 0);
    class_addmethod(iso_class, (t_method)iso_duty, gensym("duty"), A_FLOAT, 0);
	class_addmethod(iso_class, (t_method)iso_list, gensym("attack"), A_GIMME, 0);
    class_addmethod(iso_class, (t_method)iso_start, gensym("start"), A_GIMME, 0);
    class_addmethod(iso_class, (t_method)iso_stop, gensym("stop"), 0);
    class_addmethod(iso_class, (t_method)iso_pause, gensym("pause"), 0);
    class_addmethod(iso_class, (t_method)iso_loop, gensym("loop"), 0);
    class_addmethod(iso_class, (t_method)iso_unloop, gensym("unloop"), 0);
    class_addmethod(iso_class, (t_method)iso_resume, gensym("resume"), 0);
    class_addmethod(iso_class, (t_method)iso_hook, gensym("hook"), A_FLOAT, 0);
    class_addbang(iso_class, iso_bang);
	class_addlist(iso_class, iso_pitch);
    class_sethelpsymbol(iso_class, gensym("maxlib/help-iso.pd"));
}
#endif

--- NEW FILE: triang.c ---
/* ---------------------------- rand_triang ----------------------------------- */
/*                                                                              */
/* rand_triang generates a triangularly distributed random variable.            */
/* Written by Olaf Matthes (olaf.matthes at gmx.de)                                */
/* Based on code found in Dodge/Jerse "Computer Music"                          */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

#include "m_pd.h"
#include <stdlib.h>
#include <time.h>
#include <math.h>

#define fran()         (t_float)rand()/(t_float)RAND_MAX

static char *version = "triang v0.1, generates triangularly distributed random variable\n"
                       "             written by Olaf Matthes <olaf.matthes at gmx.de>";

/* -------------------------- rand_triang ------------------------------ */

static t_class *rand_triang_class;

typedef struct _rand_triang
{
    t_object x_obj;
} t_rand_triang;

static void *rand_triang_new(t_floatarg f)
{
    t_rand_triang *x = (t_rand_triang *)pd_new(rand_triang_class);
    srand( (unsigned)time( NULL ) );
    outlet_new(&x->x_obj, &s_float);
    return (x);
}

static void rand_triang_bang(t_rand_triang *x)
{
	t_float u1, u2;
    u1 = fran();
    u2 = fran();
    outlet_float(x->x_obj.ob_outlet, 0.5*(u1+u2));
}

#ifndef MAXLIB
void triang_setup(void)
{
    rand_triang_class = class_new(gensym("triang"), (t_newmethod)rand_triang_new, 0,
    	sizeof(t_rand_triang), 0, A_DEFFLOAT, 0);
#else
void maxlib_triang_setup(void)
{
    rand_triang_class = class_new(gensym("maxlib_triang"), (t_newmethod)rand_triang_new, 0,
    	sizeof(t_rand_triang), 0, A_DEFFLOAT, 0);
	class_addcreator((t_newmethod)rand_triang_new, gensym("triang"), A_DEFFLOAT, 0);
#endif
    class_addbang(rand_triang_class, rand_triang_bang);
#ifndef MAXLIB
	class_sethelpsymbol(rand_triang_class, gensym("help-triang.pd"));
    post(version);
#else
	class_sethelpsymbol(rand_triang_class, gensym("maxlib/help-triang.pd"));
#endif
}

--- NEW FILE: gauss.c ---
/* ---------------------------- rand_gauss ----------------------------------- */
/*                                                                              */
/* rand_gauss generates a gauss distributed random variable.                  */
/* Written by Olaf Matthes (olaf.matthes at gmx.de)                                */
/* Based on code found in Dodge/Jerse "Computer Music"                          */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

#include "m_pd.h"
#include <stdlib.h>
#include <time.h>
#include <math.h>

#define fran()         (t_float)rand()/(t_float)RAND_MAX

static char *version = "gauss v0.1, generates a Gaussian distributed random variable\n"
                       "            with mean 'mu' and standard deviation 'sigma',\n"
                       "            written by Olaf Matthes <olaf.matthes at gmx.de>";

/* -------------------------- rand_gauss ------------------------------ */

static t_class *rand_gauss_class;

typedef struct _rand_gauss
{
    t_object x_obj;
	t_float  x_sigma;
	t_float  x_mu;
} t_rand_gauss;

static void *rand_gauss_new(t_floatarg fs, t_floatarg fm)
{
    t_rand_gauss *x = (t_rand_gauss *)pd_new(rand_gauss_class);
    srand( (unsigned)time( NULL ) );
    floatinlet_new(&x->x_obj, &x->x_sigma);
    floatinlet_new(&x->x_obj, &x->x_mu);
    outlet_new(&x->x_obj, &s_float);
	x->x_sigma = fs;
    return (x);
}

static void rand_gauss_bang(t_rand_gauss *x)
{
	t_float u, halfN = 6.0, sum = 0, scale;
	t_int k, N = 12;
	scale = 1/sqrt(N/12);
	for(k = 1; k <= N; k++)
		sum += fran();
    outlet_float(x->x_obj.ob_outlet, x->x_sigma*scale*(sum-halfN)+x->x_mu);
}

#ifndef MAXLIB
void gauss_setup(void)
{
    rand_gauss_class = class_new(gensym("gauss"), (t_newmethod)rand_gauss_new, 0,
    	sizeof(t_rand_gauss), 0, A_DEFFLOAT, A_DEFFLOAT, 0);
    class_addbang(rand_gauss_class, rand_gauss_bang);
	class_sethelpsymbol(rand_gauss_class, gensym("help-gauss.pd"));
    post(version);
}
#else
void maxlib_gauss_setup(void)
{
    rand_gauss_class = class_new(gensym("maxlib_gauss"), (t_newmethod)rand_gauss_new, 0,
    	sizeof(t_rand_gauss), 0, A_DEFFLOAT, A_DEFFLOAT, 0);
	class_addcreator((t_newmethod)rand_gauss_new, gensym("gauss"), A_DEFFLOAT, 0);
    class_addbang(rand_gauss_class, rand_gauss_bang);
	class_sethelpsymbol(rand_gauss_class, gensym("maxlib/help-gauss.pd"));
}
#endif


--- NEW FILE: nchange.c ---
/* ------------------------- ignore ------------------------------------------- */
/*                                                                              */
/* A 'new' change object for more than just floats.                             */
/* Written by Olaf Matthes <olaf.matthes at gmx.de>                                */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

#define A_LIST 254;
#define A_ANYTHING 255;

#include "m_pd.h"

// #include <string.h>
// #include <stdio.h>

/* -------------------------- nchange ------------------------------ */
static char *version = "nchange v0.1, written by Olaf Matthes <olaf.matthes at gmx.de>";

static t_class *nchange_class;

typedef struct _nchange
{
    t_object x_obj;
    t_atom   x_a[256];
	int      x_c;
	int	x_type;
} t_nchange;

static void *nchange_new(t_symbol *s)
{
	int i;

    t_nchange *x = (t_nchange *)pd_new(nchange_class);

	if(s == gensym("s"))
	{
		x->x_type = A_SYMBOL;
	    outlet_new(&x->x_obj, &s_symbol);
	}
	else if(s == gensym("f"))
	{
		x->x_type = A_FLOAT;
	    outlet_new(&x->x_obj, &s_float);
	}
	else if(s == gensym("l"))
	{
		x->x_type = A_LIST;
	    outlet_new(&x->x_obj, &s_list);
	}
	else
	{
		x->x_type = A_ANYTHING;
	    outlet_new(&x->x_obj, &s_anything);
	}

    return (x);
}

static void nchange_bang(t_nchange *x)
{
    if (x->x_type == A_FLOAT)
		outlet_float(x->x_obj.ob_outlet, x->x_a->a_w.w_float);
    else if (x->x_type == A_SYMBOL)
		outlet_symbol(x->x_obj.ob_outlet, x->x_a->a_w.w_symbol);
    else
		outlet_list(x->x_obj.ob_outlet, NULL, x->x_c, x->x_a);
}

static void nchange_float(t_nchange *x, t_float f)
{
 	if (x->x_type == A_FLOAT)
	{
		if (f != x->x_a->a_w.w_float)
		{
    		// x->x_f = f;
			SETFLOAT(x->x_a, f);
			outlet_float(x->x_obj.ob_outlet, x->x_a->a_w.w_float);
		}
	}
}

static void nchange_symbol(t_nchange *x, t_symbol *s)
{
	if (x->x_type == A_SYMBOL)
	{
		if (s != x->x_a->a_w.w_symbol)
		{
    		// x->x_s = s;
			SETSYMBOL(x->x_a, s);
			outlet_symbol(x->x_obj.ob_outlet, x->x_a->a_w.w_symbol);
		}
	}
}

static void nchange_list(t_nchange *x, t_symbol *s, int argc, t_atom *argv)
{
	int i, change = 0;
	int c = argc;

	if(c == x->x_c)	// same number of elements
		for (i = 0; i < c; i++)
		{
		/*	if(x->x_a[i].a_type != argv[i].a_type)
			{
				change = 1;
				break;
			}	*/
			if (x->x_a[i].a_type == A_FLOAT)
			{
				if (argv[i].a_type != A_FLOAT || x->x_a[i].a_w.w_float != argv[i].a_w.w_float)
				{
					change = 1;
					break;
				}
			}
			else if (x->x_a[i].a_type == A_SYMBOL)
			{
				if (argv[i].a_type != A_SYMBOL || x->x_a[i].a_w.w_symbol != argv[i].a_w.w_symbol)
				{
					change = 1;
					break;
				}
			}
		}
	else change = 1;	// different number of elems.

    if (change)
    {
		x->x_c = c;
		for (i = 0; i < c; i++)	// same new list
		{
			x->x_a[i] = argv[i];
		}
		outlet_list(x->x_obj.ob_outlet, s, argc, argv);
    }
}

static void nchange_set(t_nchange *x, t_symbol *s, int argc, t_atom *argv)
{
	int i;

	if (x->x_type == A_SYMBOL)
	{
		SETSYMBOL(x->x_a, argv->a_w.w_symbol);
	}
 	else if (x->x_type == A_FLOAT)
	{
		SETFLOAT(x->x_a, argv->a_w.w_float);
	}
	else	// list or anything
    {
		x->x_c = argc;
		for (i = 0; i < argc; i++)
		{
			x->x_a[i] = argv[i];
		}
    }
}

#ifndef MAXLIB
void nchange_setup(void)
{
    nchange_class = class_new(gensym("nchange"), (t_newmethod)nchange_new, 0,
    	sizeof(t_nchange), 0, A_SYMBOL, 0);
    class_addbang(nchange_class, nchange_bang);
    class_addfloat(nchange_class, nchange_float);
    class_addsymbol(nchange_class, nchange_symbol);
    class_addlist(nchange_class, nchange_list);
    class_addanything(nchange_class, nchange_list);
    class_addmethod(nchange_class, (t_method)nchange_set, gensym("set"), A_GIMME, 0);
    class_sethelpsymbol(nchange_class, gensym("help-nchange.pd"));
    post(version);
}
#else
void maxlib_nchange_setup(void)
{
    nchange_class = class_new(gensym("maxlib_nchange"), (t_newmethod)nchange_new, 0,
    	sizeof(t_nchange), 0, A_SYMBOL, 0);
	class_addcreator((t_newmethod)nchange_new, gensym("nchange"), A_SYMBOL, 0);
    class_addbang(nchange_class, nchange_bang);
    class_addfloat(nchange_class, nchange_float);
    class_addsymbol(nchange_class, nchange_symbol);
    class_addlist(nchange_class, nchange_list);
    class_addanything(nchange_class, nchange_list);
    class_addmethod(nchange_class, (t_method)nchange_set, gensym("set"), A_GIMME, 0);
    class_sethelpsymbol(nchange_class, gensym("maxlib/help-nchange.pd"));
}
#endif

--- NEW FILE: wrap.c ---
/* -------------------------  wrap  ------------------------------------------ */
/*                                                                              */
/* wraps input to lie within an output range.                                  */
/* Written by Olaf Matthes <olaf.matthes at gmx.de>                                */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

#include "m_pd.h"
#include <stdio.h>
#include <math.h>

static char *version = "wrap v0.1, written by Olaf Matthes <olaf.matthes at gmx.de>";
 
typedef struct wrap
{
  t_object x_ob;
  t_float  x_min;                  /* low border of input range */
  t_float  x_max;                  /* high border of input range */
  t_outlet *x_outlet1;             /* path-through outlet */
  t_outlet *x_outlet2;             /* wrap outlet */
} t_wrap;

static void wrap_float(t_wrap *x, t_floatarg f)
{
  t_float min = x->x_min;
  t_float max = x->x_max;
  t_float range = max - min;
  t_int i;

  if(range == 0.0f)
    {
      f = min;
      outlet_float(x->x_outlet2, 0);
    }
  else if(f < min)
    {
      t_float diff = min - f;
      t_float n = ceil(diff / range);

      f += n * range;

      outlet_float(x->x_outlet2, -(t_int)n);
    }
  else if (f >= max)
    {
      t_float diff = f - max;
      t_float n = floor(diff / range) + 1.0f;

      f -= n * range;

      outlet_float(x->x_outlet2, (t_int)n);
    }      
  else
    outlet_float(x->x_outlet2, 0.0f);

  outlet_float(x->x_outlet1, f);
}

static void wrap_a(t_wrap *x, t_floatarg a)
{
	t_float max = x->x_max;

	if(a <= max)
		x->x_min = a;
	else
	{
		x->x_min = max;
		x->x_max = a;
	}
}

static void wrap_b(t_wrap *x, t_floatarg b)
{
	t_float min = x->x_min;

	if(b >= min)
		x->x_max = b;
	else
	{
		x->x_max = min;
		x->x_min = b;
	}
}

static t_class *wrap_class;

static void *wrap_new(t_floatarg fmin, t_floatarg fmax)
{
    t_wrap *x = (t_wrap *)pd_new(wrap_class);

    inlet_new(&x->x_ob, &x->x_ob.ob_pd, gensym("float"), gensym("a"));
    inlet_new(&x->x_ob, &x->x_ob.ob_pd, gensym("float"), gensym("b"));

	x->x_outlet1 = outlet_new(&x->x_ob, gensym("float"));
	x->x_outlet2 = outlet_new(&x->x_ob, gensym("float"));

	x->x_min = fmin;
	wrap_b(x, fmax);

    return (void *)x;
}

#ifndef MAXLIB
void wrap_setup(void)
{
    wrap_class = class_new(gensym("wrap"), (t_newmethod)wrap_new,
    	0, sizeof(t_wrap), 0, A_DEFFLOAT, A_DEFFLOAT, 0);
#else
void maxlib_wrap_setup(void)
{
    wrap_class = class_new(gensym("maxlib_wrap"), (t_newmethod)wrap_new,
    	0, sizeof(t_wrap), 0, A_DEFFLOAT, A_DEFFLOAT, 0);
	class_addcreator((t_newmethod)wrap_new, gensym("wrap"), A_DEFFLOAT, A_DEFFLOAT, 0);
#endif
    class_addfloat(wrap_class, wrap_float);
	class_addmethod(wrap_class, (t_method)wrap_a, gensym("a"), A_FLOAT, 0);
	class_addmethod(wrap_class, (t_method)wrap_b, gensym("b"), A_FLOAT, 0);
#ifndef MAXLIB
    class_sethelpsymbol(wrap_class, gensym("help-wrap.pd"));
    post(version);
#else
    class_sethelpsymbol(wrap_class, gensym("maxlib/help-wrap.pd"));
#endif
}


--- NEW FILE: ignore.c ---
/* ------------------------- ignore ------------------------------------------- */
/*                                                                              */
/* Ignores input that is followed by next value faster than N ms.               */
/* Written by Olaf Matthes (olaf.matthes at gmx.de)                                */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

#include "m_pd.h"

static char *version = "ignore v0.1, written by Olaf Matthes <olaf.matthes at gmx.de>";
 
typedef struct ignore
{
  t_object x_ob;
  t_clock  *x_clock;
  t_inlet  *x_intime;
  t_outlet *x_outfloat;
  t_float  x_input;
  t_float  x_lastinput;
  t_int    x_limit;                 /* indicates if input is 'blocked' (1) */
  t_int    x_time;                  /* the time in ms */
} t_ignore;

static void ignore_tick(t_ignore *x)
{
	x->x_limit = 0;
		/* output in case nothing has changed */
	if(x->x_lastinput == x->x_input)
		outlet_float(x->x_outfloat, x->x_lastinput);
}

static void ignore_float(t_ignore *x, t_floatarg f)
{
	x->x_input = f;
	if(!x->x_limit)
	{
		x->x_limit = 1;		                /* ignore input within next N ms */
		clock_delay(x->x_clock, x->x_time); /* start clock */
	}
	else	/* ignore / start clock again */
	{
		x->x_lastinput = x->x_input;        /* save current as last valid value */
		clock_unset(x->x_clock);            /* throw out last clock */
		clock_delay(x->x_clock, x->x_time); /* start new clock */
	}
}

static void ignore_time(t_ignore *x, t_floatarg f)
{
	x->x_time = (t_int)f;
}

static void ignore_reset(t_ignore *x)
{
	x->x_limit = 0;
    post("ignore: reset");
}

static void ignore_free(t_ignore *x)
{
	clock_free(x->x_clock);
}

static t_class *ignore_class;

static void *ignore_new(t_floatarg f)
{
    t_ignore *x = (t_ignore *)pd_new(ignore_class);
	x->x_intime = inlet_new(&x->x_ob, &x->x_ob.ob_pd, gensym("float"), gensym("time"));
	x->x_outfloat = outlet_new(&x->x_ob, gensym("float"));
    x->x_clock = clock_new(x, (t_method)ignore_tick);

	x->x_time = (t_int)f;
	x->x_lastinput = 0;

    return (void *)x;
}

#ifndef MAXLIB
void ignore_setup(void)
{
    ignore_class = class_new(gensym("ignore"), (t_newmethod)ignore_new,
    	(t_method)ignore_free, sizeof(t_ignore), 0, A_DEFFLOAT, 0);
    class_addmethod(ignore_class, (t_method)ignore_reset, gensym("reset"), 0);
    class_addmethod(ignore_class, (t_method)ignore_time, gensym("time"), A_FLOAT, 0);
    class_addfloat(ignore_class, ignore_float);
    class_sethelpsymbol(ignore_class, gensym("help-ignore.pd"));
    post(version);
}
#else
void maxlib_ignore_setup(void)
{
    ignore_class = class_new(gensym("maxlib_ignore"), (t_newmethod)ignore_new,
    	(t_method)ignore_free, sizeof(t_ignore), 0, A_DEFFLOAT, 0);
	class_addcreator((t_newmethod)ignore_new, gensym("ignore"), A_DEFFLOAT, 0);
    class_addmethod(ignore_class, (t_method)ignore_reset, gensym("reset"), 0);
    class_addmethod(ignore_class, (t_method)ignore_time, gensym("time"), A_FLOAT, 0);
    class_addfloat(ignore_class, ignore_float);
    class_sethelpsymbol(ignore_class, gensym("maxlib/help-ignore.pd"));
}
#endif


--- NEW FILE: unroute.c ---
/* --------------------------  unroute   ------------------------------------- */
/*                                                                              */
/* Opposit to croute.                                                           */
/* Written by Olaf Matthes <olaf.matthes at gmx.de>                                */
/* Get source at http://www.akustische-kunst.org/puredata/                      */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

#include "m_pd.h"

#define MAX_INLET 256

static char *version = "unroute v0.1, written by Olaf Matthes <olaf.matthes at gmx.de>";
 
typedef struct unroute
{
  t_object x_obj;
  t_outlet *x_outlet;
  t_int    x_ninstance;
  t_atom   x_id;
} t_unroute;

typedef struct proxy
{
	t_object obj;
	t_int index;		/* number of proxy inlet(s) */
	t_atom id;
	t_unroute *x;		/* we'll put the other struct in here */
} t_proxy;

static void unroute_any(t_unroute *x, t_symbol *s, int argc, t_atom *argv)
{
	int i;
	t_atom at[MAXPDSTRING];

	for(i = 0; i < argc; i++)
	{
		at[i + 2] = argv[i];
	}
	argc += 2;
	SETSYMBOL(at+1, s);

	at[0] = x->x_id;	/* prepend id of that inlet */

	outlet_list(x->x_outlet, NULL, argc, at);
}

static void unroute_list(t_unroute *x, t_symbol *s, int argc, t_atom *argv)
{
	int i;
	t_atom at[MAXPDSTRING];

	for(i = 0; i < argc; i++)
	{
		at[i + 1] = argv[i];
	}
	argc++;

	at[0] = x->x_id;	/* prepend id of that inlet */

	outlet_list(x->x_outlet, NULL, argc, at);
}

static void unroute_float(t_unroute *x, t_floatarg f)
{
	t_atom list[2];

	list[0] = x->x_id;	/* prepend id of that inlet */
	SETFLOAT(list+1, f);
	outlet_list(x->x_outlet, NULL, 2, list);
}

static void unroute_input(t_proxy *p, t_symbol *s, int argc, t_atom *argv)
{
	t_unroute *x = (t_unroute *)(p->x);
	int i;
	t_atom at[MAXPDSTRING];

	if(s == gensym("list"))
	{
		for(i = 0; i < argc; i++)
		{
			at[i + 1] = argv[i];
		}
		argc++;
	}
	else
	{
		for(i = 0; i < argc; i++)
		{
			at[i + 2] = argv[i];
		}
		argc += 2;
		SETSYMBOL(at+1, s);
	}

	at[0] = p->id;	/* prepend id for that inlet */

	outlet_list(x->x_outlet, NULL, argc, at);
}


static t_class *unroute_class;
static t_class *proxy_class;

static void *unroute_new(t_symbol *s, int argc, t_atom *argv)
{
	int i;

    t_unroute *x = (t_unroute *)pd_new(unroute_class);
	t_proxy *inlet[MAX_INLET];

	x->x_ninstance	= argc;
	x->x_id = argv[0];

	for(i = 0; i < x->x_ninstance - 1; i++)
	{
		inlet[i] = (t_proxy *)pd_new(proxy_class);
		inlet[i]->x = x;		/* make x visible to the proxy inlets */
		inlet[i]->index = i;	/* remember our number */
		inlet[i]->id = argv[i+1];
			/* the inlet we're going to create belongs to the object 
		       't_unroute' but the destination is the instance 'i'
		       of the proxy class 't_proxy'                           */
		inlet_new(&x->x_obj, &inlet[i]->obj.ob_pd, 0,0);
	}
	x->x_outlet = outlet_new(&x->x_obj, gensym("float"));

    return (void *)x;
}

#ifndef MAXLIB
void unroute_setup(void)
{
    unroute_class = class_new(gensym("unroute"), (t_newmethod)unroute_new,
    	0, sizeof(t_unroute), 0, A_GIMME, 0);
#else
void maxlib_unroute_setup(void)
{
    unroute_class = class_new(gensym("maxlib_unroute"), (t_newmethod)unroute_new,
    	0, sizeof(t_unroute), 0, A_GIMME, 0);
#endif
		/* a class for the proxy inlet: */
	proxy_class = class_new(gensym("maxlib_unroute_proxy"), NULL, NULL, sizeof(t_proxy),
		CLASS_PD|CLASS_NOINLET, A_NULL);

	class_addanything(proxy_class, unroute_input);

    class_addfloat(unroute_class, unroute_float);
    class_addlist(unroute_class, unroute_list);
    class_addanything(unroute_class, unroute_any);
#ifndef MAXLIB
    class_sethelpsymbol(unroute_class, gensym("help-unroute.pd"));
    post(version);
#else
	class_addcreator((t_newmethod)unroute_new, gensym("unroute"), A_GIMME, 0);
    class_sethelpsymbol(unroute_class, gensym("maxlib/help-unroute.pd"));
#endif
}

--- NEW FILE: limit.c ---
/* -------------------------  limit  ------------------------------------------ */
/*                                                                              */
/* limits input to lie within an output range.                                  */
/* Written by Olaf Matthes <olaf.matthes at gmx.de>                                */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

#include "m_pd.h"
#include <stdio.h>
#include <math.h>

static char *version = "limit v0.1, written by Olaf Matthes <olaf.matthes at gmx.de>";
 
typedef struct limit
{
  t_object x_ob;
  t_float  x_ol;                   /* low border of output range */
  t_float  x_oh;                   /* high border of output range */
  t_float  x_ratio;                /* 'compression ratio' */
  t_outlet *x_outlet1;             /* result */
  t_float  x_f;
} t_limit;

static void limit_float(t_limit *x, t_floatarg f)
{
	if(x->x_oh < x->x_ol)	/* swap values */
	{
		int i = x->x_oh;
		x->x_oh = x->x_ol;
		x->x_ol = i;
	}
	if(x->x_ratio == 0)	/* 'clip' mode */
	{
		if(f > x->x_oh)f = x->x_oh;
		else if(f < x->x_ol)f = x->x_ol;
	}
	else	/* 'compress' mode */
	{
		int diff;
		if(f > x->x_oh)
		{
			diff = f - x->x_oh;
			f = x->x_oh + (diff / x->x_ratio);
		}
		else if(f < x->x_ol)
		{
			diff = x->x_ol - f;
			f = x->x_ol - (diff / x->x_ratio);
		}
	}
	outlet_float(x->x_outlet1, f);
	x->x_f = f;
}

static void limit_bang(t_limit *x)
{
	limit_float(x, x->x_f);	/* recalculate result */
}

static t_class *limit_class;

static void *limit_new(t_floatarg fol, t_floatarg foh, t_floatarg fr)
{
    t_limit *x = (t_limit *)pd_new(limit_class);

	floatinlet_new(&x->x_ob, &x->x_ol);
	floatinlet_new(&x->x_ob, &x->x_oh);
	floatinlet_new(&x->x_ob, &x->x_ratio);

	x->x_outlet1 = outlet_new(&x->x_ob, gensym("float"));

		/* default values taken from Max's limit */
	x->x_ol = fol;
	x->x_oh = foh;
	if(x->x_oh < x->x_ol)	/* swap values */
	{
		int i = x->x_oh;
		x->x_oh = x->x_ol;
		x->x_ol = i;
	}
	x->x_ratio = fr;
	x->x_f = 0;

    return (void *)x;
}

#ifndef MAXLIB
void limit_setup(void)
{
    limit_class = class_new(gensym("limit"), (t_newmethod)limit_new,
    	0, sizeof(t_limit), 0, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0);
#else
void maxlib_limit_setup(void)
{
    limit_class = class_new(gensym("maxlib_limit"), (t_newmethod)limit_new,
    	0, sizeof(t_limit), 0, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0);
	class_addcreator((t_newmethod)limit_new, gensym("limit"), A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0);
#endif
    class_addfloat(limit_class, limit_float);
    class_addbang(limit_class, limit_bang);
#ifndef MAXLIB
    class_sethelpsymbol(limit_class, gensym("help-limit.pd"));
    post(version);
#else
    class_sethelpsymbol(limit_class, gensym("maxlib/help-limit.pd"));
#endif
}


--- NEW FILE: netrec.c ---
/* --------------------------  netrec  ---------------------------------------- */
/*                                                                              */
/* A 'netreceive' that tells the IP of the connecting netsend.                  */
/* Written by Olaf Matthes <olaf.matthes at gmx.de>                                */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

#ifdef PD_0_37
#include "m_pd.h"
#include "s_stuff.h"
#endif
#include "m_imp.h"

#include <sys/types.h>
#include <stdarg.h>
#include <signal.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#ifdef UNIX
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/time.h>
#define SOCKET_ERROR -1
#else
#include <io.h>
#include <fcntl.h>
#include <winsock.h>
#endif

#define MAX_CONNECT  32		/* maximum number of connections */
#define INBUFSIZE    4096   /* size of receiving data buffer */

static char *version = "netrec v0.1, written by Olaf Matthes <olaf.matthes at gmx.de>";

/* ----------------------------- netrec ------------------------- */

static t_class *netrec_class;
static t_binbuf *inbinbuf;

typedef void (*t_netrec_socketnotifier)(void *x);
typedef void (*t_netrec_socketreceivefn)(void *x, t_binbuf *b);

typedef struct _netrec
{
    t_object x_obj;
    t_outlet *x_msgout;
    t_outlet *x_connectout;
	t_outlet *x_clientno;
	t_outlet *x_connectionip;
	t_symbol *x_host[MAX_CONNECT];
	t_int    x_fd[MAX_CONNECT];
	t_int    x_sock_fd;
    int x_connectsocket;
    int x_nconnections;
    int x_udp;
} t_netrec;

typedef struct _netrec_socketreceiver
{
    char *sr_inbuf;
    int sr_inhead;
    int sr_intail;
    void *sr_owner;
    int sr_udp;
    t_netrec_socketnotifier sr_notifier;
    t_netrec_socketreceivefn sr_socketreceivefn;
} t_netrec_socketreceiver;

static t_netrec_socketreceiver *netrec_socketreceiver_new(void *owner, t_netrec_socketnotifier notifier,
    t_netrec_socketreceivefn socketreceivefn, int udp)
{
    t_netrec_socketreceiver *x = (t_netrec_socketreceiver *)getbytes(sizeof(*x));
    x->sr_inhead = x->sr_intail = 0;
    x->sr_owner = owner;
    x->sr_notifier = notifier;
    x->sr_socketreceivefn = socketreceivefn;
    x->sr_udp = udp;
    if (!(x->sr_inbuf = malloc(INBUFSIZE))) bug("t_netrec_socketreceiver");
    return (x);
}

    /* this is in a separately called subroutine so that the buffer isn't
    sitting on the stack while the messages are getting passed. */
static int netrec_socketreceiver_doread(t_netrec_socketreceiver *x)
{
    char messbuf[INBUFSIZE], *bp = messbuf;
    int indx;
    int inhead = x->sr_inhead;
    int intail = x->sr_intail;
    char *inbuf = x->sr_inbuf;
    if (intail == inhead) return (0);
    for (indx = intail; indx != inhead; indx = (indx+1)&(INBUFSIZE-1))
    {
    	char c = *bp++ = inbuf[indx];
    	if (c == ';' && (!indx || inbuf[indx-1] != '\\'))
    	{
    	    intail = (indx+1)&(INBUFSIZE-1);
    	    binbuf_text(inbinbuf, messbuf, bp - messbuf);
    	    x->sr_inhead = inhead;
    	    x->sr_intail = intail;
    	    return (1);
    	}
    }
    return (0);
}

static void netrec_socketreceiver_getudp(t_netrec_socketreceiver *x, int fd)
{
    char buf[INBUFSIZE+1];
    int ret = recv(fd, buf, INBUFSIZE, 0);
    if (ret < 0)
    {
		sys_sockerror("recv");
		sys_rmpollfn(fd);
		sys_closesocket(fd);
    }
    else if (ret > 0)
    {
	buf[ret] = 0;
#if 0
	post("%s", buf);
#endif
    	if (buf[ret-1] != '\n')
	{
#if 0
	    buf[ret] = 0;
	    error("dropped bad buffer %s\n", buf);
#endif
	}
	else
	{
	    char *semi = strchr(buf, ';');
	    if (semi) 
	    	*semi = 0;
    	    binbuf_text(inbinbuf, buf, strlen(buf));
	    outlet_setstacklim();
	    if (x->sr_socketreceivefn)
		(*x->sr_socketreceivefn)(x->sr_owner, inbinbuf);
    	    else bug("netrec_socketreceiver_getudp");
    	}
    }
}

static void netrec_socketreceiver_read(t_netrec_socketreceiver *x, int fd)
{
    if (x->sr_udp)   /* UDP ("datagram") socket protocol */
    	netrec_socketreceiver_getudp(x, fd);
    else  /* TCP ("streaming") socket protocol */
    {
		char *semi;
		int readto =
			(x->sr_inhead >= x->sr_intail ? INBUFSIZE : x->sr_intail-1);
		int ret;

		t_netrec *y = x->sr_owner;

		y->x_sock_fd = fd;

    			/* the input buffer might be full.  If so, drop the whole thing */
		if (readto == x->sr_inhead)
		{
    			fprintf(stderr, "netrec: dropped message");
    			x->sr_inhead = x->sr_intail = 0;
    			readto = INBUFSIZE;
		}
		else
		{
			ret = recv(fd, x->sr_inbuf + x->sr_inhead,
	    		readto - x->sr_inhead, 0);
			if (ret < 0)
			{
				sys_sockerror("recv");
	    		if (x->sr_notifier) (*x->sr_notifier)(x->sr_owner);
	    		sys_rmpollfn(fd);
	    		sys_closesocket(fd);
			}
			else if (ret == 0)
			{
	    		post("netrec: connection closed on socket %d", fd);
				if (x->sr_notifier) (*x->sr_notifier)(x->sr_owner);
	    		sys_rmpollfn(fd);
	    		sys_closesocket(fd);
			}
			else
			{
    			x->sr_inhead += ret;
    			if (x->sr_inhead >= INBUFSIZE) x->sr_inhead = 0;
    			while (netrec_socketreceiver_doread(x))
				{
					outlet_setstacklim();
					if (x->sr_socketreceivefn)
		    			(*x->sr_socketreceivefn)(x->sr_owner, inbinbuf);
    				else binbuf_eval(inbinbuf, 0, 0, 0);
 	    		}
			}
		}
    }
}

static void netrec_socketreceiver_free(t_netrec_socketreceiver *x)
{
    free(x->sr_inbuf);
    freebytes(x, sizeof(*x));
}

/* ---------------- main netrec stuff --------------------- */

static void netrec_notify(t_netrec *x)
{
	int i, k;
		/* remove connection from list */
	for(i = 0; i < x->x_nconnections; i++)
	{
			if(x->x_fd[i] == x->x_sock_fd)
			{
				x->x_nconnections--;
				post("netrec: \"%s\" removed from list of clients", x->x_host[i]->s_name);
				x->x_host[i] = NULL;	/* delete entry */
				x->x_fd[i] = -1;
					/* rearrange list now: move entries to close the gap */
				for(k = i; k < x->x_nconnections; k++)
				{
					x->x_host[k] = x->x_host[k + 1];
					x->x_fd[k] = x->x_fd[k + 1];
				}
			}
	}
    outlet_float(x->x_connectout, x->x_nconnections);
}

static void netrec_doit(void *z, t_binbuf *b)
{
    t_atom messbuf[1024];
    t_netrec *x = (t_netrec *)z;
    int msg, natom = binbuf_getnatom(b);
    t_atom *at = binbuf_getvec(b);
	int i;
		/* output clients IP and socket no */
	for(i = 0; i < x->x_nconnections; i++)
	{
		if(x->x_fd[i] == x->x_sock_fd)
		{
			outlet_symbol(x->x_connectionip, x->x_host[i]);
			break;
		}
	}
	outlet_float(x->x_clientno, x->x_sock_fd);
		/* process data */
    for (msg = 0; msg < natom;)
    {
    	int emsg;
		for (emsg = msg; emsg < natom && at[emsg].a_type != A_COMMA
			&& at[emsg].a_type != A_SEMI; emsg++);

		if (emsg > msg)
		{
			int ii;
			for (ii = msg; ii < emsg; ii++)
	    		if (at[ii].a_type == A_DOLLAR || at[ii].a_type == A_DOLLSYM)
				{
	    			pd_error(x, "netrec: got dollar sign in message");
					goto nodice;
				}
			if (at[msg].a_type == A_FLOAT)
			{
	    		if (emsg > msg + 1)
					outlet_list(x->x_msgout, 0, emsg-msg, at + msg);
				else outlet_float(x->x_msgout, at[msg].a_w.w_float);
			}
			else if (at[msg].a_type == A_SYMBOL)
	    		outlet_anything(x->x_msgout, at[msg].a_w.w_symbol,
				emsg-msg-1, at + msg + 1);
		}
		nodice:
    		msg = emsg + 1;
    }
}

static void netrec_connectpoll(t_netrec *x)
{
    struct sockaddr_in incomer_address;
    int sockaddrl = (int) sizeof( struct sockaddr );
    int fd = accept(x->x_connectsocket, (struct sockaddr*)&incomer_address, &sockaddrl);
    if (fd < 0) post("netrec: accept failed");
    else
    {
    	t_netrec_socketreceiver *y = netrec_socketreceiver_new((void *)x, 
    	    (t_netrec_socketnotifier)netrec_notify,
	    	(x->x_msgout ? netrec_doit : 0), 0);
    	sys_addpollfn(fd, (t_fdpollfn)netrec_socketreceiver_read, y);
		x->x_nconnections++;
		x->x_host[x->x_nconnections - 1] = gensym(inet_ntoa(incomer_address.sin_addr));
		x->x_fd[x->x_nconnections - 1] = fd;

		// outlet_symbol( x->x_connectionip, x->x_host[x->x_nconnections - 1]);
		post("netrec: accepted connection from %s on socket %d", 
			x->x_host[x->x_nconnections - 1]->s_name, x->x_fd[x->x_nconnections - 1]);
    	outlet_float(x->x_connectout, x->x_nconnections);
    }
}

static void netrec_print(t_netrec *x)
{
	int i;
	if(x->x_nconnections > 0)
	{
		post("netrec: %d open connections:", x->x_nconnections);

		for(i = 0; i < x->x_nconnections; i++)
		{
			post("        \"%s\" on socket %d", 
				x->x_host[i]->s_name, x->x_fd[i]);
		}
	} else post("netrec: no open connections");
}

static void *netrec_new(t_symbol *compatflag,
    t_floatarg fportno, t_floatarg udpflag)
{
    t_netrec *x;
	int i;
    struct sockaddr_in server;
    int sockfd, portno = fportno, udp = (udpflag != 0);
    int old = !strcmp(compatflag->s_name , "old");
    	/* create a socket */
    sockfd = socket(AF_INET, (udp ? SOCK_DGRAM : SOCK_STREAM), 0);
#if 1
    post("netrec: receive socket %d\n", sockfd);
#endif
    if (sockfd < 0)
    {
    	sys_sockerror("socket");
    	return (0);
    }
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = INADDR_ANY;

#ifdef IRIX
    	/* this seems to work only in IRIX but is unnecessary in
	Linux.  Not sure what NT needs in place of this. */
    if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, 0, 0) < 0)
    	post("setsockopt failed\n");
#endif

    	/* assign server port number */
    server.sin_port = htons((u_short)portno);

    	/* name the socket */
    if (bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0)
    {
    	sys_sockerror("bind");
    	sys_closesocket(sockfd);
    	return (0);
    }
    x = (t_netrec *)pd_new(netrec_class);
    if (old)
    {
    	/* old style, nonsecure version */
		x->x_msgout = 0;
    }
    else x->x_msgout = outlet_new(&x->x_obj, &s_anything);

    if (udp)	    /* datagram protocol */
    {
    	t_netrec_socketreceiver *y = netrec_socketreceiver_new((void *)x, 
    	    (t_netrec_socketnotifier)netrec_notify,
	    	(x->x_msgout ? netrec_doit : 0), 1);
		sys_addpollfn(sockfd, (t_fdpollfn)netrec_socketreceiver_read, y);
		x->x_connectout = 0;
    }
    else    	/* streaming protocol */
    {
		if (listen(sockfd, 5) < 0)
		{
    		sys_sockerror("listen");
    		sys_closesocket(sockfd);
			sockfd = -1;
		}
    	else
		{
			sys_addpollfn(sockfd, (t_fdpollfn)netrec_connectpoll, x);
    		x->x_connectout = outlet_new(&x->x_obj, &s_float);
			x->x_clientno = outlet_new(&x->x_obj, &s_float);
			x->x_connectionip = outlet_new(&x->x_obj, &s_symbol);
			inbinbuf = binbuf_new();
		}
    }
    x->x_connectsocket = sockfd;
    x->x_nconnections = 0;
    x->x_udp = udp;
	for(i = 0; i < MAX_CONNECT; i++)x->x_fd[i] = -1;

    return (x);
}

static void netrec_free(t_netrec *x)
{
    	/* LATER make me clean up open connections */
    if (x->x_connectsocket >= 0)
    {
    	sys_rmpollfn(x->x_connectsocket);
    	sys_closesocket(x->x_connectsocket);
    }
	binbuf_free(inbinbuf);
}

#ifndef MAXLIB
void netrec_setup(void)
{
    netrec_class = class_new(gensym("netrec"),(t_newmethod)netrec_new, (t_method)netrec_free,
    	sizeof(t_netrec), 0, A_DEFFLOAT, A_DEFFLOAT, A_DEFSYM, 0);
	class_addmethod(netrec_class, (t_method)netrec_print, gensym("print"), 0);
	class_sethelpsymbol(netrec_class, gensym("help-netrec.pd"));
    post(version);
}
#else
void maxlib_netrec_setup(void)
{
    netrec_class = class_new(gensym("maxlib_netrec"),(t_newmethod)netrec_new, (t_method)netrec_free,
    	sizeof(t_netrec), 0, A_DEFFLOAT, A_DEFFLOAT, A_DEFSYM, 0);
	class_addcreator((t_newmethod)netrec_new, gensym("netrec"), A_DEFFLOAT, A_DEFFLOAT, A_DEFSYM, 0);
	class_addmethod(netrec_class, (t_method)netrec_print, gensym("print"), 0);
	class_sethelpsymbol(netrec_class, gensym("maxlib/help-netrec.pd"));
}
#endif

--- NEW FILE: bilex.c ---
/* ---------------------------- rand_bilex ------------------------------------ */
/*                                                                              */
/* rand_bilex generates a bilinear exponentially distributed random variable.   */
/* Written by Olaf Matthes (olaf.matthes at gmx.de)                                */
/* Based on code found in Dodge/Jerse "Computer Music"                          */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

#include "m_pd.h"
#include <stdlib.h>
#include <time.h>
#include <math.h>

#define fran()         (t_float)rand()/(t_float)RAND_MAX

static char *version = "bilex v0.1, generates bilinear exponentially distributed random\n"
                       "            variable, written by Olaf Matthes <olaf.matthes at gmx.de>";

/* -------------------------- rand_bilex ------------------------------ */

static t_class *rand_bilex_class;

typedef struct _rand_bilex
{
    t_object x_obj;
	t_float  x_lambda;
} t_rand_bilex;

static void *rand_bilex_new(t_floatarg f)
{
    t_rand_bilex *x = (t_rand_bilex *)pd_new(rand_bilex_class);
    srand( (unsigned)time( NULL ) );
    floatinlet_new(&x->x_obj, &x->x_lambda);
    outlet_new(&x->x_obj, &s_float);
	x->x_lambda = f;
    return (x);
}

static void rand_bilex_bang(t_rand_bilex *x)
{
	t_float u, s = 1, l;
	l = (x->x_lambda <= 0 ? 0.0001 : x->x_lambda);
	do
	{
		u = 2*fran();
	}
	while(u == 0 || u == 2);
	if(u > 1)
	{
		u = 2-u;
		s=-1;
	}
    outlet_float(x->x_obj.ob_outlet, s*log(u)/l);
}

#ifndef MAXLIB
void bilex_setup(void)
{
    rand_bilex_class = class_new(gensym("bilex"), (t_newmethod)rand_bilex_new, 0,
    	sizeof(t_rand_bilex), 0, A_DEFFLOAT, 0);
    class_addbang(rand_bilex_class, rand_bilex_bang);
	class_sethelpsymbol(rand_bilex_class, gensym("help-bilex.pd"));
    post(version);
}
#else
void maxlib_bilex_setup(void)
{
    rand_bilex_class = class_new(gensym("maxlib_bilex"), (t_newmethod)rand_bilex_new, 0,
    	sizeof(t_rand_bilex), 0, A_DEFFLOAT, 0);
    class_addbang(rand_bilex_class, rand_bilex_bang);
	class_addcreator((t_newmethod)rand_bilex_new, gensym("bilex"), A_DEFFLOAT, 0);
	class_sethelpsymbol(rand_bilex_class, gensym("maxlib/help-bilex.pd"));
}
#endif

--- NEW FILE: expo.c ---
/* ---------------------------- rand_expo ------------------------------------- */
/*                                                                              */
/* rand_expo generates a exponentially distributed random variable.             */
/* Written by Olaf Matthes (olaf.matthes at gmx.de)                                */
/* Based on code found in Dodge/Jerse "Computer Music"                          */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

#include "m_pd.h"
#include <stdlib.h>
#include <time.h>
#include <math.h>

#define fran()         (t_float)rand()/(t_float)RAND_MAX

static char *version = "expo v0.1, generates exponentially distributed random variable\n"
                       "           written by Olaf Matthes <olaf.matthes at gmx.de>";

/* -------------------------- rand_expo ------------------------------ */

static t_class *rand_expo_class;

typedef struct _rand_expo
{
    t_object x_obj;
	t_float  x_lambda;
} t_rand_expo;

static void *rand_expo_new(t_floatarg f)
{
    t_rand_expo *x = (t_rand_expo *)pd_new(rand_expo_class);
    srand( (unsigned)time( NULL ) );
    floatinlet_new(&x->x_obj, &x->x_lambda);
    outlet_new(&x->x_obj, &s_float);
	x->x_lambda = f;
    return (x);
}

static void rand_expo_bang(t_rand_expo *x)
{
	t_float u, l;
	l = (x->x_lambda <= 0 ? 0.0001 : x->x_lambda);
	do
	{
		u = fran();
	}
	while(u == 0);
    outlet_float(x->x_obj.ob_outlet, -log(u)/l);
}

#ifndef MAXLIB
void expo_setup(void)
{
    rand_expo_class = class_new(gensym("expo"), (t_newmethod)rand_expo_new, 0,
    	sizeof(t_rand_expo), 0, A_DEFFLOAT, 0);
    class_addbang(rand_expo_class, rand_expo_bang);
	class_sethelpsymbol(rand_expo_class, gensym("help-expo.pd"));
    post(version);
}
#else
void maxlib_expo_setup(void)
{
    rand_expo_class = class_new(gensym("maxlib_expo"), (t_newmethod)rand_expo_new, 0,
    	sizeof(t_rand_expo), 0, A_DEFFLOAT, 0);
    class_addbang(rand_expo_class, rand_expo_bang);
	class_addcreator((t_newmethod)rand_expo_new, gensym("expo"), A_DEFFLOAT, 0);
	class_sethelpsymbol(rand_expo_class, gensym("maxlib/help-expo.pd"));
}
#endif

--- NEW FILE: poisson.c ---
/* ---------------------------- rand_poisson ---------------------------------- */
/*                                                                              */
/* rand_poisson generates a poisson distributed random variable.                */
/* Written by Olaf Matthes (olaf.matthes at gmx.de)                                */
/* Based on code found in Dodge/Jerse "Computer Music"                          */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

#include "m_pd.h"
#include <stdlib.h>
#include <time.h>
#include <math.h>

#define fran()         (t_float)rand()/(t_float)RAND_MAX
#ifndef M_PI
#define M_PI           3.1415927
#endif

static char *version = "poisson v0.1, generates a poisson distributed random variable\n"
                       "              written by Olaf Matthes <olaf.matthes at gmx.de>";

/* -------------------------- rand_poisson ------------------------------ */

static t_class *rand_poisson_class;

typedef struct _rand_poisson
{
    t_object x_obj;
	t_float  x_lambda;
} t_rand_poisson;

static void *rand_poisson_new(t_floatarg f)
{
    t_rand_poisson *x = (t_rand_poisson *)pd_new(rand_poisson_class);
    srand( (unsigned)time( NULL ) );
    floatinlet_new(&x->x_obj, &x->x_lambda);
    outlet_new(&x->x_obj, &s_float);
	x->x_lambda = f;
    return (x);
}

static void rand_poisson_bang(t_rand_poisson *x)
{
	t_float u, v;
	t_int n = 0;
	v = exp(-x->x_lambda);
	u = fran();
	while(u > v)
	{
		u *= fran();
		n++;
	}
    outlet_float(x->x_obj.ob_outlet, n);
}

#ifndef MAXLIB
void poisson_setup(void)
{
    rand_poisson_class = class_new(gensym("poisson"), (t_newmethod)rand_poisson_new, 0,
    	sizeof(t_rand_poisson), 0, A_DEFFLOAT, 0);
    class_addbang(rand_poisson_class, rand_poisson_bang);
	class_sethelpsymbol(rand_poisson_class, gensym("help-poisson.pd"));
    post(version);
}
#else
void maxlib_poisson_setup(void)
{
    rand_poisson_class = class_new(gensym("maxlib_poisson"), (t_newmethod)rand_poisson_new, 0,
    	sizeof(t_rand_poisson), 0, A_DEFFLOAT, 0);
	class_addcreator((t_newmethod)rand_poisson_new, gensym("poisson"), A_DEFFLOAT, 0);
    class_addbang(rand_poisson_class, rand_poisson_bang);
	class_sethelpsymbol(rand_poisson_class, gensym("maxlib/help-poisson.pd"));
}
#endif

--- NEW FILE: tilt.c ---
/* ------------------------- tilt --------------------------------------------- */
/*                                                                              */
/* Monitor input for changes.                                                   */
/* Written by Olaf Matthes (olaf.matthes at gmx.de)                                */
/* Inspired by code written by Trond Lossius.                                   */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

#include "m_pd.h"
#include <stdio.h>
#include <stdlib.h>

#define MAXSIZE 32

static char *version = "tilt v0.1, written by Olaf Matthes <olaf.matthes at gmx.de>";
 
typedef struct tilt
{
  t_object x_ob;
  t_outlet *x_out;                  /* result */
  t_clock  *x_clock;

  t_float  x_tilt;                  /* the result */
  t_float  x_start_tilt;
  t_float  x_t;
  t_float  x_sa;
  t_float  x_sb;
  t_float  x_offset;
  t_float  x_time;
  t_float  x_wait;
  t_float  x_hi_limit;
  t_float  x_low_limit;
  t_float  x_trip_point;
} t_tilt;

static void tilt_tick(t_tilt *x)
{
	x->x_sb = x->x_t - x->x_offset;
	if((x->x_sb - x->x_sa) > x->x_hi_limit)
	{
		x->x_sa = x->x_sb;
		clock_delay(x->x_clock, x->x_wait);
		return;
	}
	else
	{
		if((x->x_sb - x->x_sa) > x->x_trip_point)
		{
			outlet_bang(x->x_out);
			clock_delay(x->x_clock, x->x_wait);
			return;
		}
		if((x->x_sb - x->x_sa) < x->x_low_limit)
		{
			x->x_time++;
			if(x->x_time > 15)
			{
				x->x_start_tilt = x->x_sa;
				x->x_time = 0;
			}
		}
		if((x->x_sb - x->x_start_tilt) > x->x_tilt)
		{
			outlet_bang(x->x_out);
			clock_delay(x->x_clock, x->x_wait);
		}
		else
		{
			x->x_sa = x->x_sb;
			clock_delay(x->x_clock, x->x_wait);
			return;
		}
	}
}

static void tilt_float(t_tilt *x, t_floatarg f)
{
	x->x_t = f;
}

static void tilt_intv(t_tilt *x, t_floatarg f)
{
	x->x_wait = f;
}

static void tilt_tilt(t_tilt *x, t_floatarg f)
{
	x->x_tilt = f;
	post("tilt: set tilt to %g", x->x_tilt);
}

static void tilt_hi_limit(t_tilt *x, t_floatarg f)
{
	x->x_hi_limit = f;
	post("tilt: set high limit to %g", x->x_hi_limit);
}

static void tilt_low_limit(t_tilt *x, t_floatarg f)
{
	x->x_low_limit = f;
	post("tilt: set low limit to %g", x->x_low_limit);
}

static void tilt_trip_point(t_tilt *x, t_floatarg f)
{
	x->x_trip_point = f;
	post("tilt: set trip point to %g", x->x_trip_point);
}

static void tilt_free(t_tilt *x)
{
	clock_free(x->x_clock);
}

static t_class *tilt_class;

static void *tilt_new(t_floatarg f, t_floatarg f2)
{
	int i;

    t_tilt *x = (t_tilt *)pd_new(tilt_class);
	inlet_new(&x->x_ob, &x->x_ob.ob_pd, gensym("float"), gensym("intv"));
	x->x_out = outlet_new(&x->x_ob, gensym("float"));
	x->x_clock = clock_new(x, (t_method)tilt_tick);

	x->x_t = f;	/* set initial value */
	if(f2 > 4)
		x->x_wait = f2;
	else
		x->x_wait = 4000;
	x->x_offset = 0;
	x->x_sa = 0;
	x->x_sb = 0;
	x->x_time = 0;
	x->x_tilt = 0;
	x->x_start_tilt = x->x_sa = x->x_t - x->x_offset;
	x->x_hi_limit = x->x_low_limit = x->x_trip_point = 0;
	clock_delay(x->x_clock, x->x_wait);	/* wait 4 sec and start calculation */

	post("tilt: set interval to %g msec", x->x_wait);
    return (void *)x;
}

#ifndef MAXLIB
void tilt_setup(void)
{
    tilt_class = class_new(gensym("tilt"), (t_newmethod)tilt_new,
    	(t_method)tilt_free, sizeof(t_tilt), 0, A_DEFFLOAT, A_DEFFLOAT, 0);
    class_addfloat(tilt_class, tilt_float);
	class_addmethod(tilt_class, (t_method)tilt_intv, gensym("intv"), A_FLOAT, 0);
	class_addmethod(tilt_class, (t_method)tilt_tilt, gensym("tilt"), A_FLOAT, 0);
	class_addmethod(tilt_class, (t_method)tilt_hi_limit, gensym("hi"), A_FLOAT, 0);
	class_addmethod(tilt_class, (t_method)tilt_low_limit, gensym("low"), A_FLOAT, 0);
	class_addmethod(tilt_class, (t_method)tilt_trip_point, gensym("trip"), A_FLOAT, 0);
    class_sethelpsymbol(tilt_class, gensym("help-tilt.pd"));
    post(version);
}
#else
void maxlib_tilt_setup(void)
{
    tilt_class = class_new(gensym("maxlib_tilt"), (t_newmethod)tilt_new,
    	(t_method)tilt_free, sizeof(t_tilt), 0, A_DEFFLOAT, A_DEFFLOAT, 0);
	class_addcreator((t_newmethod)tilt_new, gensym("tilt"), A_DEFFLOAT, A_DEFFLOAT, 0);
    class_addfloat(tilt_class, tilt_float);
	class_addmethod(tilt_class, (t_method)tilt_intv, gensym("intv"), A_FLOAT, 0);
	class_addmethod(tilt_class, (t_method)tilt_tilt, gensym("tilt"), A_FLOAT, 0);
	class_addmethod(tilt_class, (t_method)tilt_hi_limit, gensym("hi"), A_FLOAT, 0);
	class_addmethod(tilt_class, (t_method)tilt_low_limit, gensym("low"), A_FLOAT, 0);
	class_addmethod(tilt_class, (t_method)tilt_trip_point, gensym("trip"), A_FLOAT, 0);
    class_sethelpsymbol(tilt_class, gensym("maxlib/help-tilt.pd"));
}
#endif

--- NEW FILE: plus.c ---
/* --------------------------- plus  ------------------------------------------ */
/*                                                                              */
/* Like '+', but calculates output whenever _any_ of the inlets changes.        */
/* Written by Olaf Matthes (olaf.matthes at gmx.de)                                */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

#include "m_pd.h"
#include <stdio.h>

#define MAXSIZE 32

static char *version = "plus v0.2, written by Olaf Matthes <olaf.matthes at gmx.de>";
 
typedef struct plus
{
  t_object x_ob;
  t_inlet  *x_inleft;               /* leftmost inlet */
  t_inlet  *x_inright;              /* right inlet */
  t_outlet *x_outlet;               /* result */
  t_int    x_numvalues;             /* number of values / inlets */

  t_float  x_plusvalue[MAXSIZE];

} t_plus;

static void plus_bang(t_plus *x)
{
	int i;
	t_float result = x->x_plusvalue[0];
	for(i = 1; i < x->x_numvalues; i++)
		result += x->x_plusvalue[i];
	outlet_float(x->x_outlet, result);
}

static void plus_float(t_plus *x, t_floatarg f)
{
	x->x_plusvalue[0] = f;
	plus_bang(x);	/* calculate result */
}

static void plus_ft1(t_plus *x, t_floatarg f)
{
	x->x_plusvalue[1] = f;
	plus_bang(x);	/* calculate result */
}

static t_class *plus_class;

static void *plus_new(t_symbol *s, t_int argc, t_atom* argv)
{
	int i;

    t_plus *x = (t_plus *)pd_new(plus_class);
    x->x_inright = inlet_new(&x->x_ob, &x->x_ob.ob_pd, gensym("float"), gensym("ft1"));
	for(i = 2; i < argc; i++)	/* create additional inlets, if any */
	{
		floatinlet_new(&x->x_ob, &x->x_plusvalue[i]);
	}
	x->x_outlet = outlet_new(&x->x_ob, gensym("float"));

	for(i = 0; i < argc; i++)
	{
		x->x_plusvalue[i] = atom_getfloatarg(i, argc, argv);;
	}
	x->x_numvalues = i;

    return (void *)x;
}

#ifndef MAXLIB
void plus_setup(void)
{
    plus_class = class_new(gensym("plus"), (t_newmethod)plus_new,
    	0, sizeof(t_plus), 0, A_GIMME, 0);
    class_addfloat(plus_class, plus_float);
    class_addmethod(plus_class, (t_method)plus_ft1, gensym("ft1"), A_FLOAT, 0);
	class_addbang(plus_class, (t_method)plus_bang);
    class_sethelpsymbol(plus_class, gensym("help-plus.pd"));
    post(version);
}
#else
void maxlib_plus_setup(void)
{
    plus_class = class_new(gensym("maxlib_plus"), (t_newmethod)plus_new,
    	0, sizeof(t_plus), 0, A_GIMME, 0);
	class_addcreator((t_newmethod)plus_new, gensym("plus"), A_GIMME, 0);
    class_addfloat(plus_class, plus_float);
    class_addmethod(plus_class, (t_method)plus_ft1, gensym("ft1"), A_FLOAT, 0);
	class_addbang(plus_class, (t_method)plus_bang);
    class_sethelpsymbol(plus_class, gensym("maxlib/help-plus.pd"));
}
#endif

--- NEW FILE: timebang.c ---
/* -------------------------  timebang  --------------------------------------- */
/*                                                                              */
/* Send out bangs at given times (time of day!).                                */
/* Written by Olaf Matthes <olaf.matthes at gmx.de>                                */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

#include "m_pd.h"
#include <stdio.h>
#include <math.h>
#include <time.h>

#define MAX_TIMES 256			/* maximum number of times to process */

static char *version = "timebang v0.2, written by Olaf Matthes <olaf.matthes at gmx.de>";
 
typedef struct timebang
{
  t_object x_ob;
  t_clock  *x_clock;
  t_outlet *x_outlet[MAX_TIMES];   /* the bang outlets */
  t_int    x_sec[MAX_TIMES];       /* seconds (0 - 59) */
  t_int    x_min[MAX_TIMES];       /* minutes (0 - 59) */
  t_int    x_hour[MAX_TIMES];      /* hours (0 - 11) */
  t_int    x_mday[MAX_TIMES];      /* day of month (1 - 31) */
  t_int    x_mon[MAX_TIMES];       /* month (0 - 11) */
  t_int    x_year[MAX_TIMES];      /* year (current year minus 1900) */
  t_int    x_wday[MAX_TIMES];      /* day of week (0 - 6, Sunday = 0, -1 = all days) */
  t_int    x_over[MAX_TIMES];      /* indicate that time is over */
  t_int    x_notimes;              /* number of times to bang */
} t_timebang;


static void timebang_tick(t_timebang *x)
{
	time_t now = time(NULL);
	struct tm *newtime;
	int i;

	newtime = localtime(&now);  /* convert to local time. */
	for(i = 0; i < x->x_notimes; i++)
	{
		if(!x->x_over[i])
		{
			if(newtime->tm_hour == x->x_hour[i] && 
			   newtime->tm_min == x->x_min[i] &&
			   newtime->tm_sec >= x->x_sec[i])
			{
				x->x_over[i] = 1;				/* mark as 'time is over' */
				outlet_bang(x->x_outlet[i]);	/* send corresponding bang */
			}
		}
		else if(newtime->tm_hour != x->x_hour[i])
			x->x_over[i] = 0;					/* reactivate time one hour later */
	}

	clock_delay(x->x_clock, 1000);	/* come back in one second */
}

static void timebang_set(t_timebang *x, t_symbol *s, int ac, t_atom *av)
{
	int i;

	if(ac == x->x_notimes * 3)
	{
		for(i = 0; i < ac; i += 3)
		{
			if (av[i].a_type == A_FLOAT) x->x_hour[x->x_notimes] = av[i].a_w.w_float;
			else { post ("timebang: first argument must be (int) hours"); return; }
			if (av[i+1].a_type == A_FLOAT) x->x_min[x->x_notimes] = av[i+1].a_w.w_float;
			else { post ("timebang: second argument must be (int) minutes"); return; }
			if (av[i+2].a_type == A_FLOAT) x->x_sec[x->x_notimes] = av[i+2].a_w.w_float;
			else { post ("timebang: third argument must be (int) seconds"); return; }
			x->x_over[i] = 0;
		}
		post("timebang: read in %d times of day:", x->x_notimes);
		for(i = 0; i < x->x_notimes; i++)
		{
			post("          %02d:%02d:%02d", x->x_hour[i], x->x_min[i], x->x_sec[i]);
		}
	}
	else post("timebang: wrong number of parameter");
}

static void timebang_bang(t_timebang *x)
{
	time_t now = time(NULL);
	struct tm *newtime = localtime(&now);  /* convert to local time. */
	post("timebang: local time is %02d:%02d:%02d", newtime->tm_hour, newtime->tm_min, newtime->tm_sec);
}

static t_class *timebang_class;

static void *timebang_new(t_symbol *s, int ac, t_atom *av)
{
	int i;
    t_timebang *x = (t_timebang *)pd_new(timebang_class);

	x->x_clock = clock_new(x, (t_method)timebang_tick);

	if(ac > MAX_TIMES * 3)
	{
		post("timebang: too many creation arguments");
		ac = MAX_TIMES * 3;
	}

	x->x_notimes = 0;
	for(i = 0; i < ac; i += 3)
	{
		if (av[i].a_type == A_FLOAT) x->x_hour[x->x_notimes] = av[i].a_w.w_float;
		else { post ("timebang: first argument must be (int) hours"); return 0; }
		if (av[i+1].a_type == A_FLOAT) x->x_min[x->x_notimes] = av[i+1].a_w.w_float;
		else { post ("timebang: second argument must be (int) minutes"); return 0; }
		if (av[i+2].a_type == A_FLOAT) x->x_sec[x->x_notimes] = av[i+2].a_w.w_float;
		else { post ("timebang: third argument must be (int) seconds"); return 0; }
		x->x_over[x->x_notimes] = 0;
		x->x_notimes++;
	}
	post("timebang: read in %d times of day:", x->x_notimes);
	for(i = 0; i < x->x_notimes; i++)
	{
		x->x_outlet[i] = outlet_new(&x->x_ob, gensym("bang"));	/* create specific bang outlet for time */
		post("          %02d:%02d:%02d", x->x_hour[i], x->x_min[i], x->x_sec[i]);
	}

	clock_set(x->x_clock, 0);

    return (void *)x;
}

static void timebang_free(t_timebang *x)
{
	clock_free(x->x_clock);
}

#ifndef MAXLIB
void timebang_setup(void)
{
    timebang_class = class_new(gensym("timebang"), (t_newmethod)timebang_new,
    	(t_method)timebang_free, sizeof(t_timebang), 0, A_GIMME, 0);
#else
void maxlib_timebang_setup(void)
{
    timebang_class = class_new(gensym("maxlib_timebang"), (t_newmethod)timebang_new,
    	(t_method)timebang_free, sizeof(t_timebang), 0, A_GIMME, 0);
	class_addcreator((t_newmethod)timebang_new, gensym("timebang"), A_GIMME, 0);
#endif
	class_addmethod(timebang_class, (t_method)timebang_set, gensym("set"), A_GIMME, 0);
	class_addbang(timebang_class, (t_method)timebang_bang);
#ifndef MAXLIB
    class_sethelpsymbol(timebang_class, gensym("help-timebang.pd"));
    post(version);
#else
    class_sethelpsymbol(timebang_class, gensym("maxlib/help-timebang.pd"));
#endif
}


--- NEW FILE: netserver.c ---
/* --------------------------  netserver  ------------------------------------- */
/*                                                                              */
/* A server for bidirectional communication from within Pd.                     */
/* Allows to send back data to specific clients connected to the server.        */
/* Written by Olaf Matthes <olaf.matthes at gmx.de>                                */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib                */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

#ifdef PD_0_37
#include "m_pd.h"
#include "s_stuff.h"
#endif
#include "m_imp.h"

#include <sys/types.h>
#include <stdarg.h>
#include <signal.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <pthread.h>
#ifdef UNIX
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/time.h>
#define SOCKET_ERROR -1
#else
#include <io.h>
#include <fcntl.h>
#include <winsock.h>
#endif

#define MAX_CONNECT  32		/* maximum number of connections */
#define INBUFSIZE    4096   /* size of receiving data buffer */

static char *version = "netserver v0.2 :: bidirectional communication for Pd\n"
                       "                  written by Olaf Matthes <olaf.matthes at gmx.de>";

/* ----------------------------- netserver ------------------------- */

static t_class *netserver_class;
static t_binbuf *inbinbuf;

typedef void (*t_netserver_socketnotifier)(void *x);
typedef void (*t_netserver_socketreceivefn)(void *x, t_binbuf *b);

typedef struct _netserver
{
    t_object x_obj;
    t_outlet *x_msgout;
    t_outlet *x_connectout;
	t_outlet *x_clientno;
	t_outlet *x_connectionip;
	t_symbol *x_host[MAX_CONNECT];
	t_int    x_fd[MAX_CONNECT];
	t_int    x_sock_fd;
    t_int    x_connectsocket;
    t_int    x_nconnections;
} t_netserver;

typedef struct _netserver_socketreceiver
{
    char *sr_inbuf;
    int sr_inhead;
    int sr_intail;
    void *sr_owner;
    t_netserver_socketnotifier sr_notifier;
    t_netserver_socketreceivefn sr_socketreceivefn;
} t_netserver_socketreceiver;

static t_netserver_socketreceiver *netserver_socketreceiver_new(void *owner, t_netserver_socketnotifier notifier,
    t_netserver_socketreceivefn socketreceivefn)
{
    t_netserver_socketreceiver *x = (t_netserver_socketreceiver *)getbytes(sizeof(*x));
    x->sr_inhead = x->sr_intail = 0;
    x->sr_owner = owner;
    x->sr_notifier = notifier;
    x->sr_socketreceivefn = socketreceivefn;
    if (!(x->sr_inbuf = malloc(INBUFSIZE))) bug("t_netserver_socketreceiver");
    return (x);
}

    /* this is in a separately called subroutine so that the buffer isn't
    sitting on the stack while the messages are getting passed. */
static int netserver_socketreceiver_doread(t_netserver_socketreceiver *x)
{
    char messbuf[INBUFSIZE], *bp = messbuf;
    int indx;
    int inhead = x->sr_inhead;
    int intail = x->sr_intail;
    char *inbuf = x->sr_inbuf;
    if (intail == inhead) return (0);
    for (indx = intail; indx != inhead; indx = (indx+1)&(INBUFSIZE-1))
    {
    	char c = *bp++ = inbuf[indx];
    	if (c == ';' && (!indx || inbuf[indx-1] != '\\'))
    	{
    	    intail = (indx+1)&(INBUFSIZE-1);
    	    binbuf_text(inbinbuf, messbuf, bp - messbuf);
    	    x->sr_inhead = inhead;
    	    x->sr_intail = intail;
    	    return (1);
    	}
    }
    return (0);
}

static void netserver_socketreceiver_read(t_netserver_socketreceiver *x, int fd)
{
	char *semi;
	int readto = (x->sr_inhead >= x->sr_intail ? INBUFSIZE : x->sr_intail-1);
	int ret;

	t_netserver *y = x->sr_owner;

	y->x_sock_fd = fd;

    		/* the input buffer might be full.  If so, drop the whole thing */
	if (readto == x->sr_inhead)
	{
    		post("netserver: dropped message");
    		x->sr_inhead = x->sr_intail = 0;
    		readto = INBUFSIZE;
	}
	else
	{
		ret = recv(fd, x->sr_inbuf + x->sr_inhead,
	    	readto - x->sr_inhead, 0);
		if (ret < 0)
		{
			sys_sockerror("recv");
	    	if (x->sr_notifier) (*x->sr_notifier)(x->sr_owner);
	    	sys_rmpollfn(fd);
	    	sys_closesocket(fd);
		}
		else if (ret == 0)
		{
	    	post("netserver: << connection closed on socket %d", fd);
			if (x->sr_notifier) (*x->sr_notifier)(x->sr_owner);
	    	sys_rmpollfn(fd);
	    	sys_closesocket(fd);
		}
		else
		{
    		x->sr_inhead += ret;
    		if (x->sr_inhead >= INBUFSIZE) x->sr_inhead = 0;
    		while (netserver_socketreceiver_doread(x))
			{
				outlet_setstacklim();
				if (x->sr_socketreceivefn)
		    		(*x->sr_socketreceivefn)(x->sr_owner, inbinbuf);
    			else binbuf_eval(inbinbuf, 0, 0, 0);
 	    	}
		}
	}
}

static void netserver_socketreceiver_free(t_netserver_socketreceiver *x)
{
    free(x->sr_inbuf);
    freebytes(x, sizeof(*x));
}

/* ---------------- main netserver (send) stuff --------------------- */

/* send message to client using socket number */
static void netserver_send(t_netserver *x, t_symbol *s, int argc, t_atom *argv)
{
	int sockfd, client = -1, i;
	if(x->x_nconnections < 0)
	{
		post("netserver: no clients connected");
		return;
	}
	if(argc < 2)
	{
		post("netserver: nothing to send");
		return;
	}
		/* get socket number of connection (first element in list) */
	if(argv[0].a_type == A_FLOAT)
	{
		sockfd = atom_getfloatarg(0, argc, argv);
		for(i = 0; i < x->x_nconnections; i++)	/* check if connection exists */
		{
			if(x->x_fd[i] == sockfd)
			{
				client = i;	/* the client we're sending to */
				break;
			}
		}
		if(client == -1)
		{
			post("netserver: no connection on socket %d", sockfd);
			return;
		}
	}
	else
	{
		post("netserver: no socket specified");
		return;
	}
		/* process & send data */
	if(sockfd > 0)
	{
		t_binbuf *b = binbuf_new();
		char *buf, *bp;
		int length, sent;
		t_atom at;
		binbuf_add(b, argc - 1, argv + 1);	/* skip first element */
		SETSEMI(&at);
		binbuf_add(b, 1, &at);
		binbuf_gettext(b, &buf, &length);

		post("netserver: sending data to client %d on socket %d", client + 1, sockfd);
		// post("netserver: sending \"%s\"", buf);

		for (bp = buf, sent = 0; sent < length;)
		{
			static double lastwarntime;
			static double pleasewarn;
			double timebefore = clock_getlogicaltime();
    		int res = send(sockfd, buf, length-sent, 0);
    		double timeafter = clock_getlogicaltime();
    		int late = (timeafter - timebefore > 0.005);
    		if (late || pleasewarn)
    		{
    	    	if (timeafter > lastwarntime + 2)
    	    	{
    	    		 post("netserver blocked %d msec",
    	    	     	(int)(1000 * ((timeafter - timebefore) + pleasewarn)));
    	    		 pleasewarn = 0;
    	    		 lastwarntime = timeafter;
    	    	}
    	    	else if (late) pleasewarn += timeafter - timebefore;
    		}
    		if (res <= 0)
    		{
    			sys_sockerror("netserver");
				post("netserver: could not send data to client");
    			break;
    		}
    		else
    		{
    			sent += res;
    			bp += res;
    		}
		}
		t_freebytes(buf, length);
		binbuf_free(b);
	}
	else post("netserver: not a valid socket number (%d)", sockfd);
}

/* send message to client using client number 
   note that the client numbers might change in case a client disconnects! */
static void netserver_client_send(t_netserver *x, t_symbol *s, int argc, t_atom *argv)
{
	int sockfd, client;
	if(x->x_nconnections < 0)
	{
		post("netserver: no clients connected");
		return;
	}
	if(argc < 2)
	{
		post("netserver: nothing to send");
		return;
	}
		/* get number of client (first element in list) */
	if(argv[0].a_type == A_FLOAT)
		client = atom_getfloatarg(0, argc, argv);
	else
	{
		post("netserver: no client specified");
		return;
	}
	sockfd = x->x_fd[client - 1];	/* get socket number for that client */

		/* process & send data */
	if(sockfd > 0)
	{
		t_binbuf *b = binbuf_new();
		char *buf, *bp;
		int length, sent;
		t_atom at;
		binbuf_add(b, argc - 1, argv + 1);	/* skip first element */
		SETSEMI(&at);
		binbuf_add(b, 1, &at);
		binbuf_gettext(b, &buf, &length);

		post("netserver: sending data to client %d on socket %d", client, sockfd);
		// post("netserver: >> sending \"%s\"", buf);

		for (bp = buf, sent = 0; sent < length;)
		{
			static double lastwarntime;
			static double pleasewarn;
			double timebefore = clock_getlogicaltime();
    		int res = send(sockfd, buf, length-sent, 0);
    		double timeafter = clock_getlogicaltime();
    		int late = (timeafter - timebefore > 0.005);
    		if (late || pleasewarn)
    		{
    	    	if (timeafter > lastwarntime + 2)
    	    	{
    	    		 post("netserver blocked %d msec",
    	    	     	(int)(1000 * ((timeafter - timebefore) + pleasewarn)));
    	    		 pleasewarn = 0;
    	    		 lastwarntime = timeafter;
    	    	}
    	    	else if (late) pleasewarn += timeafter - timebefore;
    		}
    		if (res <= 0)
    		{
    			sys_sockerror("netserver");
				post("netserver: could not send data to cient");
    			break;
    		}
    		else
    		{
    			sent += res;
    			bp += res;
    		}
		}
		t_freebytes(buf, length);
		binbuf_free(b);
	}
	else post("netserver: not a valid socket number (%d)", sockfd);
}

	/* broadcasts a message to all connected clients */
static void netserver_broadcast(t_netserver *x, t_symbol *s, int argc, t_atom *argv)
{
	int i, client = x->x_nconnections;	/* number of clients to send to */
	t_atom at[256];
	for(i = 0; i < argc; i++)
	{
		at[i + 1] = argv[i];
	}
	argc++;
    /* enumerate through the clients and send each the message */
    while(client--)
	{
		SETFLOAT(at, client + 1);	/* prepend number of client */
        netserver_client_send(x, s, argc, at);
    }
}


/* ---------------- main netserver (receive) stuff --------------------- */

static void netserver_notify(t_netserver *x)
{
	int i, k;
		/* remove connection from list */
	for(i = 0; i < x->x_nconnections; i++)
	{
			if(x->x_fd[i] == x->x_sock_fd)
			{
				x->x_nconnections--;
				post("netserver: \"%s\" removed from list of clients", x->x_host[i]->s_name);
				x->x_host[i] = NULL;	/* delete entry */
				x->x_fd[i] = -1;
					/* rearrange list now: move entries to close the gap */
				for(k = i; k < x->x_nconnections; k++)
				{
					x->x_host[k] = x->x_host[k + 1];
					x->x_fd[k] = x->x_fd[k + 1];
				}
			}
	}
    outlet_float(x->x_connectout, x->x_nconnections);
}

static void netserver_doit(void *z, t_binbuf *b)
{
    t_atom messbuf[1024];
    t_netserver *x = (t_netserver *)z;
    int msg, natom = binbuf_getnatom(b);
    t_atom *at = binbuf_getvec(b);
	int i;
		/* output clients IP and socket no. */
	for(i = 0; i < x->x_nconnections; i++)	/* search for corresponding IP */
	{
		if(x->x_fd[i] == x->x_sock_fd)
		{
			outlet_symbol(x->x_connectionip, x->x_host[i]);
			break;
		}
	}
	outlet_float(x->x_clientno, x->x_sock_fd);	/* the socket number */
		/* process data */
    for (msg = 0; msg < natom;)
    {
    	int emsg;
		for (emsg = msg; emsg < natom && at[emsg].a_type != A_COMMA
			&& at[emsg].a_type != A_SEMI; emsg++);

		if (emsg > msg)
		{
			int ii;
			for (ii = msg; ii < emsg; ii++)
	    		if (at[ii].a_type == A_DOLLAR || at[ii].a_type == A_DOLLSYM)
				{
	    			pd_error(x, "netserver: got dollar sign in message");
					goto nodice;
				}
			if (at[msg].a_type == A_FLOAT)
			{
	    		if (emsg > msg + 1)
					outlet_list(x->x_msgout, 0, emsg-msg, at + msg);
				else outlet_float(x->x_msgout, at[msg].a_w.w_float);
			}
			else if (at[msg].a_type == A_SYMBOL)
	    		outlet_anything(x->x_msgout, at[msg].a_w.w_symbol,
				emsg-msg-1, at + msg + 1);
		}
		nodice:
    		msg = emsg + 1;
    }
}

static void netserver_connectpoll(t_netserver *x)
{
    struct sockaddr_in incomer_address;
    int sockaddrl = (int) sizeof( struct sockaddr );
    int fd = accept(x->x_connectsocket, (struct sockaddr*)&incomer_address, &sockaddrl);
    if (fd < 0) post("netserver: accept failed");
    else
    {
    	t_netserver_socketreceiver *y = netserver_socketreceiver_new((void *)x, 
    	    (t_netserver_socketnotifier)netserver_notify,
	    	(x->x_msgout ? netserver_doit : 0));
    	sys_addpollfn(fd, (t_fdpollfn)netserver_socketreceiver_read, y);
		x->x_nconnections++;
		x->x_host[x->x_nconnections - 1] = gensym(inet_ntoa(incomer_address.sin_addr));
		x->x_fd[x->x_nconnections - 1] = fd;

		post("netserver: ** accepted connection from %s on socket %d", 
			x->x_host[x->x_nconnections - 1]->s_name, x->x_fd[x->x_nconnections - 1]);
    	outlet_float(x->x_connectout, x->x_nconnections);
    }
}

static void netserver_print(t_netserver *x)
{
	int i;
	if(x->x_nconnections > 0)
	{
		post("netserver: %d open connections:", x->x_nconnections);

		for(i = 0; i < x->x_nconnections; i++)
		{
			post("        \"%s\" on socket %d", 
				x->x_host[i]->s_name, x->x_fd[i]);
		}
	} else post("netserver: no open connections");
}

static void *netserver_new(t_floatarg fportno)
{
    t_netserver *x;
	int i;
    struct sockaddr_in server;
    int sockfd, portno = fportno;
    	/* create a socket */
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
#if 0
    post("netserver: receive socket %d", sockfd);
#endif
    if (sockfd < 0)
    {
    	sys_sockerror("socket");
    	return (0);
    }
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = INADDR_ANY;

#ifdef IRIX
    	/* this seems to work only in IRIX but is unnecessary in
	Linux.  Not sure what NT needs in place of this. */
    if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, 0, 0) < 0)
    	post("setsockopt failed\n");
#endif

    	/* assign server port number */
    server.sin_port = htons((u_short)portno);

    	/* name the socket */
    if (bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0)
    {
    	sys_sockerror("bind");
    	sys_closesocket(sockfd);
    	return (0);
    }
    x = (t_netserver *)pd_new(netserver_class);
    x->x_msgout = outlet_new(&x->x_obj, &s_anything);

	/* streaming protocol */
	if (listen(sockfd, 5) < 0)
	{
    	sys_sockerror("listen");
    	sys_closesocket(sockfd);
		sockfd = -1;
	}
    else
	{
		sys_addpollfn(sockfd, (t_fdpollfn)netserver_connectpoll, x);
    	x->x_connectout = outlet_new(&x->x_obj, &s_float);
		x->x_clientno = outlet_new(&x->x_obj, &s_float);
		x->x_connectionip = outlet_new(&x->x_obj, &s_symbol);
		inbinbuf = binbuf_new();
	}
    x->x_connectsocket = sockfd;
    x->x_nconnections = 0;
	for(i = 0; i < MAX_CONNECT; i++)x->x_fd[i] = -1;

    return (x);
}

static void netserver_free(t_netserver *x)
{
	int i;
	for(i = 0; i < x->x_nconnections; i++)
	{
		sys_rmpollfn(x->x_fd[i]);
    	sys_closesocket(x->x_fd[i]);
	}
    if (x->x_connectsocket >= 0)
    {
    	sys_rmpollfn(x->x_connectsocket);
    	sys_closesocket(x->x_connectsocket);
    }
	binbuf_free(inbinbuf);
}

#ifndef MAXLIB
void netserver_setup(void)
{
    netserver_class = class_new(gensym("netserver"),(t_newmethod)netserver_new, (t_method)netserver_free,
    	sizeof(t_netserver), 0, A_DEFFLOAT, 0);
	class_addmethod(netserver_class, (t_method)netserver_print, gensym("print"), 0);
	class_addmethod(netserver_class, (t_method)netserver_send, gensym("send"), A_GIMME, 0);
	class_addmethod(netserver_class, (t_method)netserver_client_send, gensym("client"), A_GIMME, 0);
	class_addmethod(netserver_class, (t_method)netserver_broadcast, gensym("broadcast"), A_GIMME, 0);
	class_sethelpsymbol(netserver_class, gensym("help-netserver.pd"));
    post(version);
}
#else
void maxlib_netserver_setup(void)
{
    netserver_class = class_new(gensym("maxlib_netserver"),(t_newmethod)netserver_new, (t_method)netserver_free,
    	sizeof(t_netserver), 0, A_DEFFLOAT, 0);
	class_addcreator((t_newmethod)netserver_new, gensym("netserver"), A_DEFFLOAT, 0);
	class_addmethod(netserver_class, (t_method)netserver_print, gensym("print"), 0);
	class_addmethod(netserver_class, (t_method)netserver_send, gensym("send"), A_GIMME, 0);
	class_addmethod(netserver_class, (t_method)netserver_client_send, gensym("client"), A_GIMME, 0);
	class_addmethod(netserver_class, (t_method)netserver_broadcast, gensym("broadcast"), A_GIMME, 0);
	class_sethelpsymbol(netserver_class, gensym("maxlib/help-netserver.pd"));
}
#endif

--- NEW FILE: pitch.c ---
/* ------------------------- pitch   ------------------------------------------ */
/*                                                                              */
/* Get a lot of info about an incoming pitch (class, register, interval...).    */
/* Written by Olaf Matthes (olaf.matthes at gmx.de)                                */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

#include "m_pd.h"
#include <stdio.h>

static char *version = "pitch v0.1b, written by Olaf Matthes <olaf.matthes at gmx.de>";
 
typedef struct pitch
{
  t_object x_ob;
  t_inlet  *x_inpitch;              /* inlet for pitch */
  t_outlet *x_outpitchval;          /* pitch as MIDI note number */
  t_outlet *x_outpitchname;         /* pitch name, e.g. "C1" */
  t_outlet *x_outpitchclass;        /* pitch class */
  t_outlet *x_outintv;              /* interval */
  t_outlet *x_outregister;          /* register */

  t_int    x_lastpitch;

} t_pitch;

static void pitch_float(t_pitch *x, t_floatarg f) {

	char buf[8];
	int r, c, interval = 0, pitch;
	
	char* notes_up[12] = {"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"};
	char* notes_down[12] = {"C", "Db", "D", "Eb", "E", "F", "Gb", "G", "Ab", "A", "Bb", "B"};

	pitch = (t_int)f;
	if(pitch < 1) pitch = 0;
	if(pitch > 127) pitch = 127;

	if(x->x_lastpitch != 0)interval = pitch - x->x_lastpitch;
	x->x_lastpitch = pitch;

	r = (pitch / 12) - 1;
	c = pitch % 12;
	if(interval >= 0)
	{
		sprintf(buf, "%s%d", notes_up[c], r);
	}
	else
	{
		sprintf(buf, "%s%d", notes_down[c], r);
	}
	// post("note: %s %d", notes[c], r);

		/* output values from right to left */
	outlet_float(x->x_outregister, r);
	outlet_float(x->x_outintv, interval);
	outlet_float(x->x_outpitchclass, c);
	outlet_symbol(x->x_outpitchname, gensym(buf));
	outlet_float(x->x_outpitchval, pitch);
}

static t_class *pitch_class;

static void *pitch_new(t_floatarg f)
{
    t_pitch *x = (t_pitch *)pd_new(pitch_class);
    x->x_inpitch = inlet_new(&x->x_ob, &x->x_ob.ob_pd, gensym("float"), gensym("ft1"));
	x->x_outpitchval = outlet_new(&x->x_ob, gensym("float"));
	x->x_outpitchname = outlet_new(&x->x_ob, gensym("symbol"));
	x->x_outpitchclass = outlet_new(&x->x_ob, gensym("float"));
	x->x_outintv = outlet_new(&x->x_ob, gensym("float"));
	x->x_outregister = outlet_new(&x->x_ob, gensym("float"));

	x->x_lastpitch = f;

    return (void *)x;
}

#ifndef MAXLIB
void pitch_setup(void)
{
    pitch_class = class_new(gensym("pitch"), (t_newmethod)pitch_new,
    	0, sizeof(t_pitch), 0, A_DEFFLOAT, 0);
    class_addfloat(pitch_class, pitch_float);
    class_sethelpsymbol(pitch_class, gensym("help-pitch.pd"));
    post(version);
}
#else
void maxlib_pitch_setup(void)
{
    pitch_class = class_new(gensym("maxlib_pitch"), (t_newmethod)pitch_new,
    	0, sizeof(t_pitch), 0, A_DEFFLOAT, 0);
	class_addcreator((t_newmethod)pitch_new, gensym("pitch"), A_DEFFLOAT, 0);
    class_addfloat(pitch_class, pitch_float);
    class_sethelpsymbol(pitch_class, gensym("maxlib/help-pitch.pd"));
}
#endif

--- NEW FILE: divmod.c ---
/* -------------------------  divmod  ----------------------------------------- */
/*                                                                              */
/* Calculates / and % together.                                                 */
/* Written by Olaf Matthes (olaf.matthes at gmx.de)                                */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

#include "m_pd.h"
#include <stdio.h>

static char *version = "divmod v0.1, written by Olaf Matthes <olaf.matthes at gmx.de>";
 
typedef struct divmod
{
  t_object x_ob;
  t_inlet  *x_inleft;               /* leftmost inlet */
  t_inlet  *x_inright;              /* right inlet */
  t_outlet *x_outlet1;              /* result of division */
  t_outlet *x_outlet2;              /* result of modulo */

  t_int    x_leftvalue;
  t_int    x_rightvalue;

} t_divmod;

static void divmod_float(t_divmod *x, t_floatarg f)
{
	x->x_leftvalue = (t_int)f;
	outlet_float(x->x_outlet1, x->x_leftvalue / x->x_rightvalue);
	outlet_float(x->x_outlet2, x->x_leftvalue % x->x_rightvalue);
}

static void divmod_ft1(t_divmod *x, t_floatarg f)
{
	x->x_rightvalue = (t_int)f;
	outlet_float(x->x_outlet1, x->x_leftvalue / x->x_rightvalue);
	outlet_float(x->x_outlet2, x->x_leftvalue % x->x_rightvalue);
}

static void divmod_bang(t_divmod *x)
{
	outlet_float(x->x_outlet1, x->x_leftvalue / x->x_rightvalue);
	outlet_float(x->x_outlet2, x->x_leftvalue % x->x_rightvalue);
}

static t_class *divmod_class;

static void *divmod_new(t_floatarg fl, t_floatarg fr)
{
    t_divmod *x = (t_divmod *)pd_new(divmod_class);
    x->x_inright = inlet_new(&x->x_ob, &x->x_ob.ob_pd, gensym("float"), gensym("ft1"));
	x->x_outlet1 = outlet_new(&x->x_ob, gensym("float"));
	x->x_outlet2 = outlet_new(&x->x_ob, gensym("float"));

	x->x_rightvalue = fr;
	x->x_leftvalue = fl;

    return (void *)x;
}

#ifndef MAXLIB
void divmod_setup(void)
{
    divmod_class = class_new(gensym("divmod"), (t_newmethod)divmod_new,
    	0, sizeof(t_divmod), 0, A_DEFFLOAT, A_DEFFLOAT, 0);
#else
void maxlib_divmod_setup(void)
{
    divmod_class = class_new(gensym("maxlib_divmod"), (t_newmethod)divmod_new,
    	0, sizeof(t_divmod), 0, A_DEFFLOAT, A_DEFFLOAT, 0);
#endif
    class_addfloat(divmod_class, divmod_float);
    class_addmethod(divmod_class, (t_method)divmod_ft1, gensym("ft1"), A_FLOAT, 0);
	class_addbang(divmod_class, (t_method)divmod_bang);
#ifndef MAXLIB
    class_sethelpsymbol(divmod_class, gensym("help-divmod.pd"));
    post(version);
#else
	class_addcreator((t_newmethod)divmod_new, gensym("divmod"), A_DEFFLOAT, A_DEFFLOAT, 0);
    class_sethelpsymbol(divmod_class, gensym("maxlib/help-divmod.pd"));
#endif
}


--- NEW FILE: mlife.c ---
/* -------------------------  mlife  ------------------------------------------ */
/*                                                                              */
/* A linear cellular automata object for PureData.                              */
/* Based on 'mlife' by pauld at koncon.nl                                          */
/* Written by Olaf Matthes (olaf.matthes at gmx.de)                                */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */
#include "m_pd.h"


static char *version = "mlife v0.1, a linear cellular automata object for Pd\n"
                       "            written by Olaf Matthes <olaf.matthes at gmx.de>";

#undef DEBUG
//#define DEBUG


#define INTSIZE sizeof(unsigned int) * 8
#define LONGSIZE sizeof(unsigned long) * 8
#define DEFAULT_DIE_LO 2
#define DEFAULT_DIE_HI 3
#define DEFAULT_N_SIZE 3	

#define MAXSIZE 1024

#include <stdio.h>
#include <stdlib.h>

/* -------------------- random stuff -------------------- */
static union {
	unsigned long		next;
	struct {
		unsigned short		: 1;
		unsigned short		n : 15;
	}					bits;
} seed = { 1 };


/*
 *  rand - pseudo-random number generator
 *
 */

static int my_rand(void)
{
	seed.next = seed.next * 1103515245 + 12345;
	return(seed.bits.n);
}


/*
 *  srand - seed pseudo-random number generator
 *
 */

static void my_srand(unsigned n)
{
	seed.next = n;
}
/* --------------------------------------------------------- */

//
// Maxlife object data structure
//
typedef struct maxlife
{
	t_object ml_ob;				// must begin every object 
	t_int universe[MAXSIZE];	// array of cells - alive and dead	
	t_outlet *out[MAXSIZE];		// outlets 
	t_int size;					// size of the CA field/world
	t_int view_start;			// Start of viewport
	t_int view_size;			// length of viewport and number of outlets
	t_int rule_die_lo;			// death if less than this
	t_int rule_die_hi;			// death if greater then this
	t_int neighbourhood_size;	// # of cells either side to check
	t_int closed;				// closed universe if true
} t_maxlife;

//
// Function prototypes for our methods and functions
//
static t_class *mlife_class;		// global variable that points to the Maxlife class

//
// ml_nextgeneration
// Step through the array, applying the rules and reset each cell
// accordingly.  For each cell:
//		- 	Check the number of neighbours (watch for "closed") 
//			using neighbourhood_size
//
//		-	If neighbours < rule_die_lo the cell is cleared (0)
//
//		-	If neighbours > rule_die_hi the cell is cleared (0)
//
//		-	Else the cell is filled (1)
//
//  not called by Pd itself
//
static void ml_nextgeneration(t_maxlife *mlp)
{
	register long i, j, k;
	register long size, neighbourhood_size, max_neighbours, min_neighbours, neighbours;
	register int closed, out_of_bounds;
	
	// get the important info a little closer to hand
	size = mlp->size;
	closed = mlp->closed;
	neighbourhood_size = mlp->neighbourhood_size;
	max_neighbours = mlp->rule_die_hi;
	min_neighbours = mlp->rule_die_lo;
	
#ifdef DEBUG
	post("mlife:next_generation called, vars n_size=%ld, n_max=%ld, n_min=%ld", 
		neighbourhood_size, max_neighbours, min_neighbours);
#endif
	// for each cell...
	for(i=0; i<size; i++)
	{
		neighbours = 0L;	// reset count of neighbours
		
		// for each neighbourhood, count the neighbours
		for(j = i-neighbourhood_size; j <= i+neighbourhood_size; j++)
		{
			k = j;	// k is the index into the array, decoupled from j
			// don't go outside our array, or wrap if closed
			if(closed)
			{
				if(j < 0)
					k = size + j;		// j is a negative number.  size-1?
				if(j > size-1L)
					k = j - size - 1L;	// not size-1 ???

				if(j != i)			// skip our own location in this roundup
					if(mlp->universe[k])	// if there's a neighbour inc count
						neighbours++;
			}
			else		// not closed
			{
				out_of_bounds = 0;
				if(k < 0L)			// start of array
				{
					out_of_bounds = 1;
					k = 0L;
				}
				if(k > size-1L)
				{
					out_of_bounds = 1;
					k = size-1L;	// end of array
				}
			
				if((j != i)	&& !out_of_bounds)	// skip our own location in this roundup
					if(mlp->universe[k])	// if there's a neighbour inc count
						neighbours++;
			}
			
		}	// end of neighbour search
		
		// based on number of neighbours, fill or clear this cell (i)
		if((neighbours < min_neighbours) || (neighbours > max_neighbours))
			mlp->universe[i] = 0;
		else
			mlp->universe[i] = 1;
	}
}

//
// method to set the die_lo number
//
static void ml_set_die_lo(t_maxlife *mlp, t_floatarg die_lo)
{
	mlp->rule_die_lo = (t_int)die_lo;
}

//
// method to set the die_hi number
//
static void ml_set_die_hi(t_maxlife *mlp, t_floatarg die_hi)
{
	mlp->rule_die_hi = (t_int)die_hi;
}

//
// method to set the die_lo number
//
static void ml_set_neighbourhood(t_maxlife *mlp, t_floatarg n_size)
{
	mlp->neighbourhood_size = (t_int)n_size;
}

//
// bang method outputs bangs for filled cells within the view port
//
static void ml_bang(t_maxlife *mlp)	// argument is a pointer to an instance
{	
	register long i, view_start;
	
#ifdef DEBUG
	post("mlife:ml_bang called, sending bangs");
#endif

	view_start = mlp->view_start;

	// loop through the outlets right->left sending bangs if alive
	for(i=view_start+mlp->view_size-2; i>=view_start-1; i--)
	{
		// send a bang out the appropriate outlet 
		if(mlp->universe[i])
			outlet_bang(mlp->out[i-view_start+1]);
	}

	ml_nextgeneration(mlp);
}

//
// int method outputs ints for ALL cells in the view port (1=filled, 0=not)
//
static void ml_int(t_maxlife *mlp, t_floatarg dummy)
{	
	t_int i, view_start;
	
#ifdef DEBUG
	post("mlife:ml_int method called");
#endif

	view_start = mlp->view_start;

	// loop through the outlets right -> left sending ints
	for(i = view_start + mlp->view_size - 2; i >= view_start - 1; i--)
	{
		//outlet_int(mlp->out[i-view_start+1], mlp->universe[i]);
		if(mlp->universe[i] == 1)
			outlet_float(mlp->out[i-view_start+1], 1);
		else if(mlp->universe[i] == 0)
			outlet_float(mlp->out[i-view_start+1], 0);
		else
			error("mlife: corrupted data in universe[] array!");
	}

	ml_nextgeneration(mlp);
}


//
// method to print out the array
//
static void ml_display(t_maxlife *mlp)
{
	register long i;
	char s[MAXSIZE];
	
#ifdef DEBUG	
	post("mlife: display method called");
#endif

	for(i = 0; i < mlp->size; i++)			// print the universe array
	{
		//s[i] = itoa(mlp->universe[i]); // my very primitive itoa()
		if(mlp->universe[i])
			s[i] = '1';
		else 
			s[i] = '0';
	}
	s[mlp->size] = '\0';	// null terminate the string
	post("%s", s);
}

//
// method to fill the array with a number
//
static void ml_fill(t_maxlife *mlp, t_floatarg fill_no)
{
	t_int  n;
	register long i, j;
	
	for(i=mlp->size-1; i >= 0; i--)	// fill the universe array from the back
	{
		n = (t_int)fill_no;

		for(j=(long)INTSIZE; j>0; j--, i--, n>>=1)
		{
			if(i < 0L)
			{
				return;
			}
			if(n & 01)
				mlp->universe[i] = 1;
			else
				mlp->universe[i] = 0;
		}
	}
}

//
// method to fill the array with a random number
//
static void ml_randfill(t_maxlife *mlp)
{
	unsigned int s, rnum;
	register unsigned int n;
	register long i, j;
	
#ifdef DEBUG	
	post("mlife: randfill method called");
#endif

	s = (unsigned int)clock_getlogicaltime();	// set seed to a new number
	my_srand(s);					// reseed the 'random' generator 
	rnum = (unsigned int)my_rand();

	for(i=mlp->size - 1; i>=0; i--)		// fill the universe array from the back
	{
		n = rnum;

		for(j=(long)INTSIZE; j>0; j--, i--, n>>=1)
		{
			if(i < 0L)
			{
				return;
			}
			if(n & 01)
				mlp->universe[i] = 1;
			else
				mlp->universe[i] = 0;
		}
	}
}

//
// method to seed the array with a number
//
static void ml_seed(t_maxlife *mlp, t_floatarg start, t_floatarg fill_no)
{
	t_int n;
	register long i, st, end;
	
#ifdef DEBUG	
	post("mlife: seed method called");
#endif

	st = (t_int)start;
	n = (t_int)fill_no;

	if(st+(t_int)INTSIZE > mlp->size)
		i = mlp->size - 1;
	else
		i = st+(long)INTSIZE - 1;

	// init the universe array from the back i>=start?
	for(; i >= start - 1; i--, n>>=1)
	{
		if(n & 01)
			mlp->universe[i] = 1;
		else
			mlp->universe[i] = 0;
	}
}

//
// method to seed the array with a random number
//
static void ml_randseed(t_maxlife *mlp, t_floatarg start)
{
	unsigned long s, rnum;
	register unsigned long n;
	register long i, st;
	
#ifdef DEBUG	
	post("mlife: randseed method called, INTSIZE=%ld", (long)INTSIZE);
#endif
	//if((start < 1) || (start > mlp->size-(long)INTSIZE))
	if(start < 1)
	{
		error("Randseed start parameter must be between 1 and %ld", mlp->size);
		return;
	}

	s = (unsigned long)clock_getlogicaltime();	// set seed to a new number
	my_srand(s);					// reseed the 'random' generator 
	rnum = (unsigned long)my_rand();
	n = (unsigned int)rnum;
	st = start;

	if(st+(t_int)INTSIZE > mlp->size)
		i = mlp->size - 1;
	else
		i = st+(t_int)INTSIZE - 1;

	// init the universe array from the back
	for(; i>=st-1; i--, n>>=1)
	{
		if(n & 01)
			mlp->universe[i] = 1;
		else
			mlp->universe[i] = 0;

	}
}


//
// function to create an instance of the mlife class
//
static void *ml_new(t_floatarg size, t_floatarg view_start, t_floatarg view_size, t_floatarg closed)
{
	long i;
	t_maxlife *mlp = (t_maxlife *)pd_new(mlife_class);

	// check all args...
	if((size>MAXSIZE) || (size<1))
	{
		post("mlife: size argument must be between 1 and %ld", MAXSIZE);
		size = 1.0;
	}
	if(view_start < 1)
	{
		post("mlife: view_start argument must be between 1 and %ld", size);
		view_start = 1.0;
	}
	if((view_size < 1) || (view_size+view_start > size+1))
	{
		post("mlife: viewsize argument must be between 1 and %ld", size-view_start);
		view_size = 1.0;
	}


	// set up our structure
	mlp->size = (t_int)size;			
	mlp->view_start = (t_int)view_start;
	mlp->view_size = (t_int)view_size;
	mlp->rule_die_lo = DEFAULT_DIE_LO;			// 2
	mlp->rule_die_hi = DEFAULT_DIE_HI;			// 3
	mlp->neighbourhood_size = DEFAULT_N_SIZE;	// 3
	mlp->closed = (t_int)closed;
	for(i=0; i<MAXSIZE; i++)
		mlp->universe[i] = 0;
	
	// create outlets - last first!
	for(i = 0; i < mlp->view_size; i++)
		mlp->out[i] = outlet_new(&mlp->ml_ob, gensym("float"));
		
#ifdef DEBUG	
	post("mlife: finished building object");
	post("mlife: INTSIZE=%ld, LONGSIZE=%ld", (long)INTSIZE, (long)LONGSIZE);
#endif

	post("mlife: defaults are: lo=%ld, hi=%ld, nset=%ld", (long)DEFAULT_DIE_LO, (long)DEFAULT_DIE_HI, DEFAULT_N_SIZE);

	return(mlp);				// always return a copy of the created object 
}

static void ml_free(t_maxlife *mlp)
{
	long i;
	
#ifdef DEBUG	
	post("mlife:freeing outlet memory");
#endif
/*	for(i=mlp->view_size-1; i>=0; i--)
		freeobject(mlp->out[i]); */
}

#ifndef MAXLIB
void mlife_setup(void)
{
    mlife_class = class_new(gensym("mlife"), (t_newmethod)ml_new,
    	(t_method)ml_free, sizeof(t_maxlife), 0, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0);
    class_addmethod(mlife_class, (t_method)ml_randfill, gensym("randfill"), 0);
	class_addmethod(mlife_class, (t_method)ml_fill, gensym("fill"), A_FLOAT, 0);
    class_addmethod(mlife_class, (t_method)ml_set_die_lo, gensym("lo"), A_FLOAT, 0);
    class_addmethod(mlife_class, (t_method)ml_set_die_hi, gensym("hi"), A_FLOAT, 0);
    class_addmethod(mlife_class, (t_method)ml_set_neighbourhood, gensym("nset"), A_FLOAT, 0);
    class_addmethod(mlife_class, (t_method)ml_randseed, gensym("randseed"), A_FLOAT, 0);
	class_addmethod(mlife_class, (t_method)ml_seed, gensym("seed"), A_FLOAT, A_FLOAT, 0);
	class_addmethod(mlife_class, (t_method)ml_display, gensym("display"), 0);
    class_addfloat(mlife_class, ml_int);
	class_addbang(mlife_class, ml_bang);
    class_sethelpsymbol(mlife_class, gensym("help-mlife.pd"));
    post(version);
}
#else
void maxlib_mlife_setup(void)
{
    mlife_class = class_new(gensym("maxlib_mlife"), (t_newmethod)ml_new,
    	(t_method)ml_free, sizeof(t_maxlife), 0, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0);
	class_addcreator((t_newmethod)ml_new, gensym("mlife"), A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0);
    class_addmethod(mlife_class, (t_method)ml_randfill, gensym("randfill"), 0);
	class_addmethod(mlife_class, (t_method)ml_fill, gensym("fill"), A_FLOAT, 0);
    class_addmethod(mlife_class, (t_method)ml_set_die_lo, gensym("lo"), A_FLOAT, 0);
    class_addmethod(mlife_class, (t_method)ml_set_die_hi, gensym("hi"), A_FLOAT, 0);
    class_addmethod(mlife_class, (t_method)ml_set_neighbourhood, gensym("nset"), A_FLOAT, 0);
    class_addmethod(mlife_class, (t_method)ml_randseed, gensym("randseed"), A_FLOAT, 0);
	class_addmethod(mlife_class, (t_method)ml_seed, gensym("seed"), A_FLOAT, A_FLOAT, 0);
	class_addmethod(mlife_class, (t_method)ml_display, gensym("display"), 0);
    class_addfloat(mlife_class, ml_int);
	class_addbang(mlife_class, ml_bang);
    class_sethelpsymbol(mlife_class, gensym("maxlib/help-mlife.pd"));
}
#endif

--- NEW FILE: deny.c ---
/* ----------------------------  deny  --------------------------------------- */
/*                                                                              */
/* Lets only floats/symbols through that are denyed to do so.                  */
/* Written by Olaf Matthes <olaf.matthes at gmx.de>                                */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

#include "m_pd.h"
#include <string.h>

static char *version = "deny v0.1, written by Olaf Matthes <olaf.matthes at gmx.de>";

typedef struct deny
{
	t_object x_obj;	
	t_outlet *x_out;
	t_atom   *x_elem;		// list of elemets that are denyed to pass
	t_int    x_numelem;		// the number of elemetns in our deny-list
} t_deny;

	/* we got a symbol... */
static void deny_symbol(t_deny *x, t_symbol *s)
{
	int i, deny = 0;
	for(i = 0; i < x->x_numelem; i++)
	{
		if(x->x_elem[i].a_type == A_SYMBOL)	// compare with all symbols in our list
			if(atom_getsymbolarg(i, x->x_numelem, x->x_elem) == s)
			{
				deny = 1;
				return;
			}
	}
	if(!deny)outlet_symbol(x->x_out, s);
}

	/* we got a float... */
static void deny_float(t_deny *x, t_floatarg f)
{
	int i, deny = 0;
	for(i = 0; i < x->x_numelem; i++)
	{
		if(x->x_elem[i].a_type == A_FLOAT)	// compare with all floats in our list
			if(atom_getfloatarg(i, x->x_numelem, x->x_elem) == f)
			{
				deny = 1;	// input is in deny-list
				return;
			}
	}
	if(!deny)outlet_float(x->x_out, f);
}

static t_class *deny_class;

static void deny_free(t_deny *x)
{
	freebytes(x->x_elem, x->x_numelem*sizeof(t_atom));
}

static void *deny_new(t_symbol *s, int argc, t_atom *argv)
{
    t_deny *x = (t_deny *)pd_new(deny_class);

	x->x_numelem = argc;	// get the number of elements
	x->x_elem = getbytes(argc*sizeof(t_atom));
	memcpy(x->x_elem, argv, argc*sizeof(t_atom));

	x->x_out = outlet_new(&x->x_obj, gensym("anything"));

	// post("deny: got %d elements", x->x_numelem);

	return (x);
}

#ifndef MAXLIB
void deny_setup(void)
{
	/* the object's class: */
    deny_class = class_new(gensym("deny"), (t_newmethod)deny_new,
    	(t_method)deny_free, sizeof(t_deny), 0, A_GIMME, 0);
#else
void maxlib_deny_setup(void)
{
	/* the object's class: */
    deny_class = class_new(gensym("maxlib_deny"), (t_newmethod)deny_new,
    	(t_method)deny_free, sizeof(t_deny), 0, A_GIMME, 0);
	class_addcreator((t_newmethod)deny_new, gensym("deny"), A_GIMME, 0);
#endif
    class_addsymbol(deny_class, deny_symbol);
    class_addfloat(deny_class, deny_float);
#ifndef MAXLIB
    class_sethelpsymbol(deny_class, gensym("help-deny.pd"));
    post(version);
#else
    class_sethelpsymbol(deny_class, gensym("maxlib/help-deny.pd"));
#endif
}

--- NEW FILE: divide.c ---
/* ------------------------- divide  ------------------------------------------ */
/*                                                                              */
/* Like '/', but calculates output whenever _any_ of the inlets changes.        */
/* Written by Olaf Matthes (olaf.matthes at gmx.de)                                */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

#include "m_pd.h"
#include <stdio.h>

#define MAXSIZE 32

static char *version = "divide v0.2, written by Olaf Matthes <olaf.matthes at gmx.de>";
 
typedef struct divide
{
  t_object x_ob;
  t_inlet  *x_inleft;               /* leftmost inlet */
  t_inlet  *x_inright;              /* right inlet */
  t_outlet *x_outlet;               /* result */
  t_int    x_numvalues;             /* number of values / inlets */

  t_float  x_dividevalue[MAXSIZE];

} t_divide;

static void divide_bang(t_divide *x)
{
	int i;
	t_float result = x->x_dividevalue[0];
	for(i = 1; i < x->x_numvalues; i++)
		result /= x->x_dividevalue[i];
	outlet_float(x->x_outlet, result);
}

static void divide_float(t_divide *x, t_floatarg f)
{
	x->x_dividevalue[0] = f;
	divide_bang(x);	/* calculate result */
}

static void divide_ft1(t_divide *x, t_floatarg f)
{
	x->x_dividevalue[1] = f;
	divide_bang(x);	/* calculate result */
}

static t_class *divide_class;

static void *divide_new(t_symbol *s, t_int argc, t_atom* argv)
{
	int i;

    t_divide *x = (t_divide *)pd_new(divide_class);
    x->x_inright = inlet_new(&x->x_ob, &x->x_ob.ob_pd, gensym("float"), gensym("ft1"));
	for(i = 2; i < argc; i++)	/* create additional inlets, if any */
	{
		floatinlet_new(&x->x_ob, &x->x_dividevalue[i]);
	}
	x->x_outlet = outlet_new(&x->x_ob, gensym("float"));

	for(i = 0; i < argc; i++)
	{
		x->x_dividevalue[i] = atom_getfloatarg(i, argc, argv);
	}
	x->x_numvalues = i;

    return (void *)x;
}

#ifndef MAXLIB
void divide_setup(void)
{
    divide_class = class_new(gensym("divide"), (t_newmethod)divide_new,
    	0, sizeof(t_divide), 0, A_GIMME, 0);
#else
void maxlib_divide_setup(void)
{
    divide_class = class_new(gensym("maxlib_divide"), (t_newmethod)divide_new,
    	0, sizeof(t_divide), 0, A_GIMME, 0);
#endif
    class_addfloat(divide_class, divide_float);
    class_addmethod(divide_class, (t_method)divide_ft1, gensym("ft1"), A_FLOAT, 0);
	class_addbang(divide_class, (t_method)divide_bang);
#ifndef MAXLIB
    class_sethelpsymbol(divide_class, gensym("help-divide.pd"));
    post(version);
#else
	class_addcreator((t_newmethod)divide_new, gensym("divide"), A_GIMME, 0);
    class_sethelpsymbol(divide_class, gensym("maxlib/help-divide.pd"));
#endif
}


--- NEW FILE: linear.c ---
/* ---------------------------- rand_linear ----------------------------------- */
/*                                                                              */
/* rand_linear generates a linearly distributed random variable.                */
/* Written by Olaf Matthes (olaf.matthes at gmx.de)                                */
/* Based on code found in Dodge/Jerse "Computer Music"                          */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

#include "m_pd.h"
#include <stdlib.h>
#include <time.h>
#include <math.h>

#define fran()         (t_float)rand()/(t_float)RAND_MAX

static char *version = "linear v0.1, generates linearly distributed random variable\n"
                       "             written by Olaf Matthes <olaf.matthes at gmx.de>";

/* -------------------------- rand_linear ------------------------------ */

static t_class *rand_linear_class;

typedef struct _rand_linear
{
    t_object x_obj;
} t_rand_linear;

static void *rand_linear_new(t_floatarg f)
{
    t_rand_linear *x = (t_rand_linear *)pd_new(rand_linear_class);
    srand( (unsigned)time( NULL ) );
    outlet_new(&x->x_obj, &s_float);
    return (x);
}

static void rand_linear_bang(t_rand_linear *x)
{
	t_float u1, u2;
    u1 = fran();
    u2 = fran();
	if(u2 < u1)
		u1 = u2;
    outlet_float(x->x_obj.ob_outlet, u1);
}

#ifndef MAXLIB
void linear_setup(void)
{
    rand_linear_class = class_new(gensym("linear"), (t_newmethod)rand_linear_new, 0,
    	sizeof(t_rand_linear), 0, A_DEFFLOAT, 0);
    class_addbang(rand_linear_class, rand_linear_bang);
	class_sethelpsymbol(rand_linear_class, gensym("help-linear.pd"));
    post(version);
}		
#else
void maxlib_linear_setup(void)
{
    rand_linear_class = class_new(gensym("maxlib_linear"), (t_newmethod)rand_linear_new, 0,
    	sizeof(t_rand_linear), 0, A_DEFFLOAT, 0);
	class_addcreator((t_newmethod)rand_linear_new, gensym("linear"), A_DEFFLOAT, 0);
    class_addbang(rand_linear_class, rand_linear_bang);
	class_sethelpsymbol(rand_linear_class, gensym("maxlib/help-linear.pd"));
}		
#endif

--- NEW FILE: multi.c ---
/* -------------------------- multi  ------------------------------------------ */
/*                                                                              */
/* Like '*', but calculates output whenever _any_ of the inlets changes.        */
/* Written by Olaf Matthes (olaf.matthes at gmx.de)                                */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

#include "m_pd.h"
#include <stdio.h>

#define MAXSIZE 32

static char *version = "multi v0.2, written by Olaf Matthes <olaf.matthes at gmx.de>";
 
typedef struct multi
{
  t_object x_ob;
  t_inlet  *x_inleft;               /* leftmost inlet */
  t_inlet  *x_inright;              /* right inlet */
  t_outlet *x_outlet;               /* result */
  t_int    x_numvalues;             /* number of values / inlets */

  t_float  x_multivalue[MAXSIZE];

} t_multi;

static void multi_bang(t_multi *x)
{
	int i;
	t_float result = x->x_multivalue[0];
	for(i = 1; i < x->x_numvalues; i++)
		result *= x->x_multivalue[i];
	outlet_float(x->x_outlet, result);
}

static void multi_float(t_multi *x, t_floatarg f)
{
	x->x_multivalue[0] = f;
	multi_bang(x);	/* calculate result */
}

static void multi_ft1(t_multi *x, t_floatarg f)
{
	x->x_multivalue[1] = f;
	multi_bang(x);	/* calculate result */
}

static t_class *multi_class;

static void *multi_new(t_symbol *s, t_int argc, t_atom* argv)
{
	int i;

    t_multi *x = (t_multi *)pd_new(multi_class);
    x->x_inright = inlet_new(&x->x_ob, &x->x_ob.ob_pd, gensym("float"), gensym("ft1"));
	for(i = 2; i < argc; i++)	/* create additional inlets, if any */
	{
		floatinlet_new(&x->x_ob, &x->x_multivalue[i]);
	}
	x->x_outlet = outlet_new(&x->x_ob, gensym("float"));

	for(i = 0; i < argc; i++)
	{
		x->x_multivalue[i] = atom_getfloatarg(i, argc, argv);;
	}
	x->x_numvalues = i;

    return (void *)x;
}

#ifndef MAXLIB
void multi_setup(void)
{
    multi_class = class_new(gensym("multi"), (t_newmethod)multi_new,
    	0, sizeof(t_multi), 0, A_GIMME, 0);
    class_addfloat(multi_class, multi_float);
    class_addmethod(multi_class, (t_method)multi_ft1, gensym("ft1"), A_FLOAT, 0);
	class_addbang(multi_class, (t_method)multi_bang);
    class_sethelpsymbol(multi_class, gensym("help-multi.pd"));
    post(version);
}
#else
void maxlib_multi_setup(void)
{
    multi_class = class_new(gensym("maxlib_multi"), (t_newmethod)multi_new,
    	0, sizeof(t_multi), 0, A_GIMME, 0);
	class_addcreator((t_newmethod)multi_new, gensym("multi"), A_GIMME, 0);
    class_addfloat(multi_class, multi_float);
    class_addmethod(multi_class, (t_method)multi_ft1, gensym("ft1"), A_FLOAT, 0);
	class_addbang(multi_class, (t_method)multi_bang);
    class_sethelpsymbol(multi_class, gensym("maxlib/help-multi.pd"));
}
#endif

--- NEW FILE: minus.c ---
/* ------------------------- minus   ------------------------------------------ */
/*                                                                              */
/* Like '-', but calculates output whenever _any_ of the inlets changes.        */
/* Written by Olaf Matthes (olaf.matthes at gmx.de)                                */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

#include "m_pd.h"
#include <stdio.h>

#define MAXSIZE 32

static char *version = "minus v0.2, written by Olaf Matthes <olaf.matthes at gmx.de>";
 
typedef struct minus
{
  t_object x_ob;
  t_inlet  *x_inleft;               /* leftmost inlet */
  t_inlet  *x_inright;              /* right inlet */
  t_outlet *x_outlet;               /* result */
  t_int    x_numvalues;             /* number of values / inlets */

  t_float  x_minusvalue[MAXSIZE];

} t_minus;

static void minus_bang(t_minus *x)
{
	int i;
	t_float result = x->x_minusvalue[0];
	for(i = 1; i < x->x_numvalues; i++)
		result -= x->x_minusvalue[i];
	outlet_float(x->x_outlet, result);
}

static void minus_float(t_minus *x, t_floatarg f)
{
	x->x_minusvalue[0] = f;
	minus_bang(x);	/* calculate result */
}

static void minus_ft1(t_minus *x, t_floatarg f)
{
	x->x_minusvalue[1] = f;
	minus_bang(x);	/* calculate result */
}

static t_class *minus_class;

static void *minus_new(t_symbol *s, t_int argc, t_atom* argv)
{
	int i;

    t_minus *x = (t_minus *)pd_new(minus_class);
    x->x_inright = inlet_new(&x->x_ob, &x->x_ob.ob_pd, gensym("float"), gensym("ft1"));
	for(i = 2; i < argc; i++)	/* create additional inlets, if any */
	{
		// inlet_new(&x->x_ob, &x->x_ob.ob_pd, gensym("float"), gensym("ft1"));
		floatinlet_new(&x->x_ob, &x->x_minusvalue[i]);
	}
	x->x_outlet = outlet_new(&x->x_ob, gensym("float"));

	for(i = 0; i < argc; i++)
	{
		x->x_minusvalue[i] = atom_getfloatarg(i, argc, argv);
	}
	x->x_numvalues = i;

    return (void *)x;
}

#ifndef MAXLIB
void minus_setup(void)
{
    minus_class = class_new(gensym("minus"), (t_newmethod)minus_new,
    	0, sizeof(t_minus), 0, A_GIMME, 0);
    class_addfloat(minus_class, minus_float);
    class_addmethod(minus_class, (t_method)minus_ft1, gensym("ft1"), A_FLOAT, 0);
	class_addbang(minus_class, (t_method)minus_bang);
    class_sethelpsymbol(minus_class, gensym("help-minus.pd"));
    post(version);
}
#else
void maxlib_minus_setup(void)
{
    minus_class = class_new(gensym("maxlib_minus"), (t_newmethod)minus_new,
    	0, sizeof(t_minus), 0, A_GIMME, 0);
	class_addcreator((t_newmethod)minus_new, gensym("minus"), A_GIMME, 0);
    class_addfloat(minus_class, minus_float);
    class_addmethod(minus_class, (t_method)minus_ft1, gensym("ft1"), A_FLOAT, 0);
	class_addbang(minus_class, (t_method)minus_bang);
    class_sethelpsymbol(minus_class, gensym("maxlib/help-minus.pd"));
}
#endif

--- NEW FILE: arbran.c ---
/* ---------------------------- rand_arbran ----------------------------------- */
/*                                                                              */
/* rand_arbran generates a random variable that conforms to the                 */
/* piecewise probability density in two arrays                                  */
/* Written by Olaf Matthes (olaf.matthes at gmx.de)                                */
/* Based on code found in Dodge/Jerse "Computer Music"                          */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

#include "m_pd.h"
#include <stdlib.h>
#include <time.h>
#include <math.h>

#define fran()         (t_float)rand()/(t_float)RAND_MAX
#ifndef M_PI
#define M_PI           3.1415927
#endif

static char *version = "arbran v0.1b, generates a random variable that conforms to the\n"
                       "              piecewise probability density in two arrays\n"
                       "              written by Olaf Matthes <olaf.matthes at gmx.de>";

/* -------------------------- rand_arbran ------------------------------ */

static t_class *rand_arbran_class;

typedef struct _rand_arbran
{
    t_object x_obj;
	t_symbol *x_x;
	t_symbol *x_p;
    t_garray *x_bufx;
    t_garray *x_bufp;
} t_rand_arbran;

static void rand_arbran_pdfscale(t_rand_arbran *x)
{
	t_garray *bx = x->x_bufx, *bp = x->x_bufp;
	t_float a = 0;
	t_int k = 0;
	t_float *tx, *tp;
	t_int ix, ip;
	if (!garray_getfloatarray(bx, &ix, &tx))
	{
		post("arbran: couldn't read from array!");
		return;
	}
	if (!garray_getfloatarray(bp, &ip, &tp))
	{
		post("arbran: couldn't read from array!");
		return;
	}

	for(k = 1; k < ix; k++)
	{
		a += (tx[k]-tx[k-1])*(tp[k]+tp[k-1])/2.0;
	}
	for(k = 0; k < ix; k++)
	{
		tp[k] = tp[k]/a;
	}
	garray_redraw(x->x_bufp);
}

static void rand_arbran_bang(t_rand_arbran *x)
{
	t_garray *bx = x->x_bufx, *bp = x->x_bufp;
	t_float a, u, a0, slope, b, d, r;
	t_int k = 0;
	t_float *tx, *tp;
	t_int ix, ip;
	if (!garray_getfloatarray(bx, &ix, &tx))
	{
		post("arbran: couldn't read from array!");
		return;
	}
	if (!garray_getfloatarray(bp, &ip, &tp))
	{
		post("arbran: couldn't read from array!");
		return;
	}

	a = 0;
	a0 = 0;
	u = fran();
	while(u > a)
	{
		a0 = (tx[k+1]-tx[k])*(tp[k+1]+tp[k])/2.0;
		a += a0;
		k++;
	}
	k--;
	slope = (tp[k+1]-tp[k])/(tx[k+1]-tx[k]);
	if(slope == 0)
	{
		r = (u-a+a0)/tp[k]+tx[k];
	}
	else
	{
		b=tp[k]/slope-tx[k];
		d=b*b+tx[k]*tx[k]+2*b*tx[k]+2*(u-a+a0)/slope;
		if(slope > 0)
			r=-b+sqrt(d);
		else
			r=-b-sqrt(d);
	}
    outlet_float(x->x_obj.ob_outlet, r);
}

static void rand_arbran_set(t_rand_arbran *x)
{
	t_garray *b, *b2;
	
	if ((b = (t_garray *)pd_findbyclass(x->x_x, garray_class)))
	{
		post("arbran: array set to \"%s\"", x->x_x->s_name);
		x->x_bufx = b;
	} else {
		post("arbran: no array \"%s\" (error %d)", x->x_x->s_name, b);
		x->x_bufx = 0;
	}
	if ((b2 = (t_garray *)pd_findbyclass(x->x_p, garray_class)))
	{
		post("arbran: array set to \"%s\"", x->x_p->s_name);
		x->x_bufp = b2;
	} else {
		post("arbran: no array \"%s\" (error %d)", x->x_p->s_name, b);
		x->x_bufp = 0;
	}
}

static void rand_arbran_setarrays(t_rand_arbran *x, t_symbol *s1, t_symbol *s2)
{
	x->x_x = s1;
	x->x_p = s2;
	rand_arbran_set(x);
}

static void *rand_arbran_new(t_symbol *s1, t_symbol *s2)
{
    t_rand_arbran *x = (t_rand_arbran *)pd_new(rand_arbran_class);
    srand( (unsigned)time( NULL ) );
    outlet_new(&x->x_obj, &s_float);
	x->x_x = s1;
	x->x_p = s2;
	rand_arbran_set(x);
    return (x);
}

#ifndef MAXLIB
void arbran_setup(void)
{
    rand_arbran_class = class_new(gensym("arbran"), (t_newmethod)rand_arbran_new, 0,
    	sizeof(t_rand_arbran), 0, A_SYMBOL, A_SYMBOL, 0);
#else
void maxlib_arbran_setup(void)
{
    rand_arbran_class = class_new(gensym("maxlib_arbran"), (t_newmethod)rand_arbran_new, 0,
    	sizeof(t_rand_arbran), 0, A_SYMBOL, A_SYMBOL, 0);
#endif
    class_addbang(rand_arbran_class, rand_arbran_bang);
	class_addmethod(rand_arbran_class, (t_method)rand_arbran_pdfscale, gensym("pdfscale"), 0);
	class_addmethod(rand_arbran_class, (t_method)rand_arbran_setarrays, gensym("set"), A_SYMBOL, A_SYMBOL, 0);
#ifndef MAXLIB
	class_sethelpsymbol(rand_arbran_class, gensym("help-arbran.pd"));
    post(version);
#else
	class_addcreator((t_newmethod)rand_arbran_new, gensym("arbran"), A_SYMBOL, A_SYMBOL, 0);
	class_sethelpsymbol(rand_arbran_class, gensym("maxlib/help-arbran.pd"));
#endif
}

--- NEW FILE: history.c ---
/* -------------------------- history ----------------------------------------- */
/*                                                                              */
/* Calculates the average value of the elements within the last N seconds.      */
/* Written by Olaf Matthes (olaf.matthes at gmx.de)                                */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

#include "m_pd.h"
#include <math.h>

#define MAX_ARG   1024              /* maximum number of items to average */
#define MAX_TIME  60000             /* maximum time to look back */

static char *version = "history v0.1, written by Olaf Matthes <olaf.matthes at gmx.de>";
 
typedef struct history
{
  t_object x_ob;
  t_clock  *x_clock;
  t_inlet  *x_inindex;
  t_outlet *x_outfloat;             /* output the history */
  t_outlet *x_outtendency;          /* outputs the tendency of the average */
  t_int    x_limit;                 /* indicates if input is 'blocked' (1) */
  t_int    x_index;                 /* the number of elements to average */
  t_float  x_input[MAX_ARG];        /* stores the input values we need for averaging */
  double   x_intime[MAX_ARG];       /* stores the time of arrival of an element */
  t_int    x_inpointer;             /* actual position in above array */
  t_float  x_average;               /* what do you guess ? */
  t_float  x_lastaverage;
  t_int    x_mode;                  /* how to history: linear or geometric */
  t_int    x_time;

} t_history;

	/* there must be a function for this in math.h but how is the 
	   german 'Fakultät' called in english ????  */
static int normalise(int i)
{
	int ret = i;
	while(i--)
	{
		if(i == 0)break;
		ret += i;
	}
	return (ret);
}

static void history_tick(t_history *x)
{
	t_float tendency = 0.0;
	if(x->x_lastaverage < x->x_average)
	{
		tendency = 1.0;	/* getting more */
	}
	else if(x->x_lastaverage > x->x_average)
	{
		tendency = -1.0;	/* getting less */
	}
	else tendency = 0.0;	/* nothing has changed */
	outlet_float(x->x_outtendency, tendency);
	x->x_lastaverage = x->x_average;
	clock_delay(x->x_clock, x->x_time);
}

static void history_float(t_history *x, t_floatarg f)
{
	int i, j = 0, k = 0, l;
	t_float geo = 1.0;

	x->x_average = 0;
		/* put value into array */
	x->x_input[x->x_inpointer] = f;
	x->x_intime[x->x_inpointer] = clock_getlogicaltime();
		/* look for elements that are too old */
	x->x_index = 0;
	for(i = 0; i < MAX_ARG; i++)	/* check all valid elements */
	{
		if(x->x_intime[i] != 0)
		{
			if(clock_gettimesince(x->x_intime[i]) <= x->x_time)	/* it's in our time window */
			{
				x->x_index++;	/* count valid entries */
			}
			else	/* too old, delete entry */
			{
				x->x_intime[i] = 0;
			}
		}
	}
	if(x->x_index > 1)
	{
			/* calulate history */
		for(i = 0; i < MAX_ARG; i++)	/* check all valid elements */
		{
			if(x->x_intime[i] != 0)	/* it's a valid entry */
			{
				k++;
				l = MAX_ARG;

				if(x->x_mode == 0)	/* linear */
				{
					x->x_average += x->x_input[i] * (1.0 / (float)x->x_index);
				}
				else if(x->x_mode == 1)	/* geometric */
				{
					if(x->x_input[i] == 0)x->x_input[i] = 0.001;	/* need to cheat a bit... */
					geo *= x->x_input[i];
					if(k == x->x_index)
						x->x_average = pow(geo, (1.0/(float)x->x_index));
				}
				else if(x->x_mode == 2)	/* weighted */
				{
						/* normalise output */
					if(k == x->x_index)
					{
						x->x_average += x->x_input[(j + x->x_inpointer + MAX_ARG) % MAX_ARG] * (float)(x->x_index - k);
						x->x_average = x->x_average / (float)normalise(x->x_index - 1);
					}
					else
					{
						x->x_average += x->x_input[(j + x->x_inpointer + MAX_ARG) % MAX_ARG] * (float)(x->x_index - k);
						j--;	/* go back in array */
						while(l--)	/* check if this will result in a valid value */
						{
							if(x->x_intime[(j + x->x_inpointer + MAX_ARG) % MAX_ARG] == 0)
							{
								j--;	/* go back more if necessary */
							}
							else break;	/* finished on first non-zero */
						}
					}
				} else post("history: internal error!");
			}
		}
	}
	else x->x_average = x->x_input[x->x_inpointer];

	if(++x->x_inpointer > MAX_ARG)
	{
		x->x_inpointer = 0;
	}
	outlet_float(x->x_outfloat, x->x_average);
}

static void history_time(t_history *x, t_floatarg f)
{
	x->x_time = (t_int)f;
	if(x->x_time < 1) x->x_time = 1;
	if(x->x_time > MAX_TIME)x->x_time = MAX_TIME;
	clock_unset(x->x_clock);
	clock_delay(x->x_clock, 0);
}

static void history_reset(t_history *x)
{
	int i;
		/* zeroe out the array */
	for(i = 0; i < MAX_ARG; i++)
	{
		x->x_input[i] = 0.0;
		x->x_intime[i] = 0.0;
	}
	x->x_index = 0;
	x->x_inpointer = 0;
	x->x_average = 0;
	x->x_lastaverage = 0;
    post("history: reset");
}

static void history_linear(t_history *x)
{
	x->x_mode = 0;
    post("history: linear");
}

static void history_geometric(t_history *x)
{
	x->x_mode = 1;
    post("history: geometric");
}

static void history_weight(t_history *x)
{
	x->x_mode = 2;
    post("history: weighted");
}

static void history_free(t_history *x)
{
	clock_free(x->x_clock);
}

static t_class *history_class;

static void *history_new(t_floatarg f)
{
	int i;

    t_history *x = (t_history *)pd_new(history_class);
	x->x_inindex = inlet_new(&x->x_ob, &x->x_ob.ob_pd, gensym("float"), gensym("time"));
	x->x_outfloat = outlet_new(&x->x_ob, gensym("float"));
	x->x_outtendency = outlet_new(&x->x_ob, gensym("float"));
	x->x_clock = clock_new(x, (t_method)history_tick);
		/* zeroe out the array */
	for(i = 0; i < MAX_ARG; i++)
	{
		x->x_input[i] = 0.0;
		x->x_intime[i] = 0.0;
	}
	x->x_time = (t_int)f;
	if(x->x_time < 1) x->x_time = 1;
	if(x->x_time > MAX_TIME)
	{
		x->x_time = MAX_TIME;
		post("history: set number time to %d", x->x_time);
	}
	x->x_index = 0;
	x->x_inpointer = 0;
	x->x_average = 0;
	x->x_mode = 0;
	clock_delay(x->x_clock, 0);

    return (void *)x;
}

#ifndef MAXLIB
void history_setup(void)
{
    history_class = class_new(gensym("history"), (t_newmethod)history_new,
    	(t_method)history_free, sizeof(t_history), 0, A_DEFFLOAT, 0);
    class_addmethod(history_class, (t_method)history_reset, gensym("reset"), 0);
    class_addmethod(history_class, (t_method)history_linear, gensym("linear"), 0);
    class_addmethod(history_class, (t_method)history_geometric, gensym("geometric"), 0);
    class_addmethod(history_class, (t_method)history_weight, gensym("weight"), 0);
    class_addfloat(history_class, history_float);
	class_addmethod(history_class, (t_method)history_time, gensym("time"), A_FLOAT, 0);
    class_sethelpsymbol(history_class, gensym("help-history.pd"));
    post(version);
}
#else
void maxlib_history_setup(void)
{
    history_class = class_new(gensym("maxlib_history"), (t_newmethod)history_new,
    	(t_method)history_free, sizeof(t_history), 0, A_DEFFLOAT, 0);
	class_addcreator((t_newmethod)history_new, gensym("history"), A_DEFFLOAT, 0);
    class_addmethod(history_class, (t_method)history_reset, gensym("reset"), 0);
    class_addmethod(history_class, (t_method)history_linear, gensym("linear"), 0);
    class_addmethod(history_class, (t_method)history_geometric, gensym("geometric"), 0);
    class_addmethod(history_class, (t_method)history_weight, gensym("weight"), 0);
    class_addfloat(history_class, history_float);
	class_addmethod(history_class, (t_method)history_time, gensym("time"), A_FLOAT, 0);
    class_sethelpsymbol(history_class, gensym("maxlib/help-history.pd"));
}
#endif

--- NEW FILE: match.c ---
/* ------------------------- match   ------------------------------------------ */
/*                                                                              */
/* Outputs a list when a list of input values matches the creation args.        */
/* Written by Krzysztof Czaja for his cyclone library.                          */
/* Modified to fit into maxlib by Olaf Matthes <olaf.matthes at gmx.de>.           */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

/* this is the original copyright notice: */

/* Copyright (c) 1997-2002 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.  */


#include <string.h>
#include "m_pd.h"

#define MATCH_INISIZE  16  /* LATER rethink */

typedef struct _match
{
    t_object  x_ob;
    int       x_size;    /* as allocated */
    int       x_patlen;  /* as used */
    t_atom   *x_pattern;
    t_atom    x_patini[MATCH_INISIZE];
    int       x_quelen;
    t_atom   *x_queue;
    t_atom    x_queini[MATCH_INISIZE];
    t_atom   *x_queend;
    t_atom   *x_queptr;  /* writing head, post-incremented (oldest-pointing) */
    int       x_;
} t_match;

static t_class *match_class;

/* a caller must check for nrequested > *sizep */
/* returns actual number of atoms: requested (success)
   or a default value of initial size (failure) */
/* the result is guaranteed to be >= min(nrequested, inisize) */
static int match_grow(int nrequested, int *sizep, t_atom **bufp,
		int inisize, t_atom *bufini)
{
    int newsize = *sizep * 2;
    while (newsize < nrequested) newsize *= 2;
    if (*bufp == bufini)
	*bufp = (t_atom *)getbytes(newsize * sizeof(**bufp));
    else
	*bufp = (t_atom *)resizebytes(*bufp, *sizep * sizeof(**bufp),
				      newsize * sizeof(**bufp));
    if (*bufp)
	*sizep = newsize;
    else
    {
	*bufp = bufini;
	nrequested = *sizep = inisize;
    }
    return (nrequested);
}

static void match_clear(t_match *x)
{
    x->x_quelen = 0;
    x->x_queptr = x->x_queue;
}

/* x->x_patlen > 0 is assumed */
/* LATER use a lock to disable reentrant calls.  I do not see any
   purpose of reentering match, but lets CHECKME first... */
static void match_checkin(t_match *x)
{
    int i, patlen = x->x_patlen;
    t_atom *queptr, *pp, *qp;
    if (x->x_queptr >= x->x_queend)
	x->x_queptr = x->x_queue;
    else x->x_queptr++;
    if (x->x_quelen < patlen && ++(x->x_quelen) < patlen)
	return;

    qp = queptr = x->x_queptr;
    for (i = 0, pp = x->x_pattern; i < patlen; i++, pp++)
    {
	if (pp->a_type == A_FLOAT)
	{
	    if (qp->a_type != A_FLOAT || qp->a_w.w_float != pp->a_w.w_float)
		break;
	}
	else if (pp->a_type == A_SYMBOL)
	{
	    if (qp->a_type != A_SYMBOL || qp->a_w.w_symbol != pp->a_w.w_symbol)
		break;
	}
	else if (pp->a_type == A_NULL)
	{
	    if (qp->a_type == A_FLOAT || qp->a_type == A_SYMBOL)
	    {
		/* instantiating a pattern */
		*pp = *qp;
		qp->a_type = A_NULL;
	    }
	    else break;  /* LATER rethink */
	}
	else break;  /* LATER rethink */
	if (qp >= x->x_queend)
	    qp = x->x_queue;
	else qp++;
    }
    if (i == patlen)
    {
	pp = x->x_pattern;
	if (pp->a_type == A_FLOAT)
	{
	    if (patlen == 1)
		outlet_float(((t_object *)x)->ob_outlet, pp->a_w.w_float);
	    else
		outlet_list(((t_object *)x)->ob_outlet, &s_list, patlen, pp);
	}
	else  /* assuming A_SYMBOL (see above) */
	{
	    if (pp->a_w.w_symbol == &s_symbol  /* bypassing typedmess() */
		&& patlen == 2 && pp[1].a_type == A_SYMBOL)
		outlet_symbol(((t_object *)x)->ob_outlet, pp[1].a_w.w_symbol);
	    else
		outlet_anything(((t_object *)x)->ob_outlet, pp->a_w.w_symbol,
				patlen - 1, pp + 1);
	}
	/* CHECKED: no implicit clear (resolving overlapping patterns) */
    }
    /* restoring a pattern */
    for (i = 0, pp = x->x_pattern; i < patlen; i++, pp++)
    {
	if (queptr->a_type == A_NULL)
	{
	    queptr->a_type = pp->a_type;
	    pp->a_type = A_NULL;
	}
	if (queptr >= x->x_queend)
	    queptr = x->x_queue;
	else queptr++;
    }
}

static void match_float(t_match *x, t_float f)
{
    if (x->x_patlen)
    {
	SETFLOAT(x->x_queptr, f);
	match_checkin(x);
    }
}

static void match_symbol(t_match *x, t_symbol *s)
{
    if (s && s != &s_ && x->x_patlen)
    {
	SETSYMBOL(x->x_queptr, s);
	match_checkin(x);
    }
}

/* LATER gpointer */

static void match_list(t_match *x, t_symbol *s, int ac, t_atom *av)
{
    while (ac--)
    {
	if (av->a_type == A_FLOAT) match_float(x, av->a_w.w_float);
	else if (av->a_type == A_SYMBOL) match_symbol(x, av->a_w.w_symbol);
	av++;
    }
}

static void match_anything(t_match *x, t_symbol *s, int ac, t_atom *av)
{
    match_symbol(x, s);
    match_list(x, 0, ac, av);
}

static void match_set(t_match *x, t_symbol *s, int ac, t_atom *av)
{
    if (ac)  /* CHECKED */
    {
	t_atom *pp;
	t_symbol *ps_nn;
	int newlen = ac * 2;
	if (newlen > x->x_size)
	{
	    newlen = match_grow(newlen, &x->x_size, &x->x_pattern,
				 MATCH_INISIZE * 2, x->x_patini);
	    if (newlen == MATCH_INISIZE * 2)
	    {
		x->x_queue = x->x_queini;
		ac = MATCH_INISIZE;
	    }
	    else x->x_queue = x->x_pattern + x->x_size / 2;
	}
	x->x_patlen = ac;
	x->x_queend = x->x_queue + ac - 1;
	match_clear(x);  /* CHECKED */
	memcpy(x->x_pattern, av, ac * sizeof(*x->x_pattern));
	pp = x->x_pattern;
	ps_nn = gensym("nn");
	while (ac--)
	{
	    if (pp->a_type == A_SYMBOL && pp->a_w.w_symbol == ps_nn)
		pp->a_type = A_NULL;
	    pp++;
	}
    }
}

static void match_free(t_match *x)
{
    if (x->x_pattern != x->x_patini)
	freebytes(x->x_pattern, 2 * x->x_size * sizeof(*x->x_pattern));
}

static void *match_new(t_symbol *s, int ac, t_atom *av)
{
    t_match *x = (t_match *)pd_new(match_class);
    x->x_size = MATCH_INISIZE * 2;
    x->x_patlen = 0;
    x->x_pattern = x->x_patini;
    x->x_queue = x->x_queini;
    /* x->x_queend is not used unless x->x_patlen > 0,
       LATER consider chosing a more defensive way... */
    outlet_new((t_object *)x, &s_anything);
    match_clear(x);
    match_set(x, 0, ac, av);
    return (x);
}

#ifndef MAXLIB
void match_setup(void)
{
    match_class = class_new(gensym("match"), (t_newmethod)match_new,
		(t_method)match_free, sizeof(t_match), 0, A_GIMME, 0);
#else
void maxlib_match_setup(void)
{
    match_class = class_new(gensym("maxlib_match"), (t_newmethod)match_new,
		(t_method)match_free, sizeof(t_match), 0, A_GIMME, 0);
	class_addcreator((t_newmethod)match_new, gensym("match"), A_GIMME, 0);
#endif
    class_addfloat(match_class, match_float);
    class_addsymbol(match_class, match_symbol);
    class_addlist(match_class, match_list);
    class_addanything(match_class, match_anything);
    class_addmethod(match_class, (t_method)match_set, gensym("set"), A_GIMME, 0);
    class_addmethod(match_class, (t_method)match_clear, gensym("clear"), 0);
#ifndef MAXLIB
    class_sethelpsymbol(match_class, gensym("help-match.pd"));
#else
    class_sethelpsymbol(match_class, gensym("maxlib/help-match.pd"));
#endif
}

--- NEW FILE: lifo.c ---
/* ---------------------------- lifo ------------------------------------------ */
/*                                                                              */
/* lifo buffer of floats, empties itselfe on every bang (in order of coming in) */
/* Written by Olaf Matthes (olaf.matthes at gmx.de)                                */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* Fifi-code based St. Rainstick fifo.c for Max,                                */
/* copyright St. Rainstick, Amsterdam 1995                                      */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

#include "m_pd.h"

static char *version = "lifo v0.1, written by Olaf Matthes <olaf.matthes at gmx.de>";

typedef struct lifo
{
	t_object d_ob;
	t_float *getal;
	t_int count, end, size, teller;
	t_outlet *out;

}t_lifo;

static t_class *lifo_class;

static void lifo_int(t_lifo *x, t_floatarg n)
{
	x->getal[x->count] = n;
	x->end = x->count;
	if (x->teller < x->size) x->teller++;
	x->count = (x->count + 1) % x->size;
}

static void lifo_bang(t_lifo *x)
{
	if (x->teller > 0){
		outlet_float(x->out,x->getal[x->end]);
		x->teller--;
		x->end = (x->end + x->size - 1) % x->size;
	}
}

static void lifo_clear(t_lifo *x)
{
	x->teller = 0;
}

static void lifo_free(t_lifo *x)
{
	freebytes(x->getal, x->size * sizeof(t_float));
}

static void *lifo_new(t_floatarg n)
{

	t_lifo *x = (t_lifo *)pd_new(lifo_class);
	if (n<10) n = 10;
	x->size = (t_int)n;
	x->teller = 0;
	x->end = 0;
	x->count = 0;
	x->getal = (t_float *)getbytes(x->size * sizeof(t_float));
	x->out = outlet_new(&x->d_ob, gensym("float"));

	return (x);
}

#ifndef MAXLIB
void lifo_setup(void)
{
    lifo_class = class_new(gensym("lifo"), (t_newmethod)lifo_new,
    	(t_method)lifo_free, sizeof(t_lifo), 0, A_DEFFLOAT, 0);
    class_addfloat(lifo_class, lifo_int);
	class_addbang(lifo_class, lifo_bang);
	class_addmethod(lifo_class, (t_method)lifo_clear, gensym("clear"), 0);
    class_sethelpsymbol(lifo_class, gensym("help-lifo.pd"));
    post(version);
}
#else
void maxlib_lifo_setup(void)
{
    lifo_class = class_new(gensym("maxlib_lifo"), (t_newmethod)lifo_new,
    	(t_method)lifo_free, sizeof(t_lifo), 0, A_DEFFLOAT, 0);
	class_addcreator((t_newmethod)lifo_new, gensym("lifo"), A_DEFFLOAT, 0);
    class_addfloat(lifo_class, lifo_int);
	class_addbang(lifo_class, lifo_bang);
	class_addmethod(lifo_class, (t_method)lifo_clear, gensym("clear"), 0);
    class_sethelpsymbol(lifo_class, gensym("maxlib/help-lifo.pd"));
}
#endif

--- NEW FILE: velocity.c ---
/* ------------------------- velocity ----------------------------------------- */
/*                                                                              */
/* Get velocity of input in digits per second.                                  */
/* Written by Olaf Matthes (olaf.matthes at gmx.de)                                */
/* Originally written for Max by Trond Lossius.                                 */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* You should have received a copy of the GNU Lesser General Public             */
/* License along with this library; if not, write to the                        */
/* Free Software Foundation, Inc., 59 Temple Place - Suite 330,                 */
/* Boston, MA  02111-1307, USA.                                                 */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

//	velocity.c: (1000*(x[n]-x[n-1]))/Æt
//	(C) Trond Lossius/BEK 2000
//	Last revision: 4/7 2000
//
//	Input:
//		float
//		int (converted to float)
//		set (set new value but no output)
//	Argument (optional, defaults to 0):
//		Initial stored value
//	Output:
//		float: Velocity as change per second (not ms)

#include "m_pd.h"

static char *version = "velocity v0.1, written by Olaf Matthes <olaf.matthes at gmx.de>";
 
typedef struct velocity
{
  t_object x_ob;
  t_outlet *x_out;
  t_float  x_xn1;               /* input (floats) */
  t_float  x_xn;
  double   x_lasttime;
} t_velocity;

static void velocity_bang(t_velocity *x)
{
	double thistime;
	t_float vel;
	
	thistime = clock_getlogicaltime();
	vel = (1000 * (x->x_xn - x->x_xn1) ) / (clock_gettimesince(x->x_lasttime));
	x->x_lasttime = thistime;
	outlet_float(x->x_out, vel);
}

static void velocity_float(t_velocity *x, t_floatarg f)
{
	x->x_xn1 = x->x_xn;
	x->x_xn = f;
	velocity_bang(x);
}

static void velocity_free(t_velocity *x)
{
	// nothing to do
}

static t_class *velocity_class;

static void *velocity_new(t_floatarg f)
{
    t_velocity *x = (t_velocity *)pd_new(velocity_class);
	x->x_out = outlet_new(&x->x_ob, gensym("float"));
	x->x_lasttime = clock_getlogicaltime();

    return (void *)x;
}

#ifndef MAXLIB
void velocity_setup(void)
{
    velocity_class = class_new(gensym("velocity"), (t_newmethod)velocity_new,
    	(t_method)velocity_free, sizeof(t_velocity), 0, A_DEFFLOAT, 0);
#else
void maxlib_velocity_setup(void)
{
    velocity_class = class_new(gensym("maxlib_velocity"), (t_newmethod)velocity_new,
    	(t_method)velocity_free, sizeof(t_velocity), 0, A_DEFFLOAT, 0);
	class_addcreator((t_newmethod)velocity_new, gensym("velocity"), A_DEFFLOAT, 0);
#endif
    class_addfloat(velocity_class, velocity_float);
	class_addbang(velocity_class, velocity_bang);
#ifndef MAXLIB
    class_sethelpsymbol(velocity_class, gensym("help-velocity.pd"));
    post(version);
#else
    class_sethelpsymbol(velocity_class, gensym("maxlib/help-velocity.pd"));
#endif
}


--- NEW FILE: netdist.c ---
/* --------------------------  netdist  --------------------------------------- */
/*                                                                              */
/* Distributes incoming data to a changeable list of netreceive objects.        */
/* Uses child thread to connect to clients. Thus needs pd0.35-test17 or later.  */
/* Written by Olaf Matthes (olaf.matthes at gmx.de)                                */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */


#include "m_pd.h"

#include <sys/types.h>
#include <string.h>
#include <pthread.h>
#ifdef UNIX
#include <sys/socket.h>
#include <sys/errno.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <unistd.h>
#define SOCKET_ERROR -1
#else
#include <winsock.h>
#endif

#define MAX_REC 32

static char *version = "netdist v0.1, written by Olaf Matthes <olaf.matthes at gmx.de>";

static t_class *netdist_class;

typedef struct _netdist
{
    t_object x_obj;
	t_clock *x_clock;
    int x_fd[MAX_REC];
	char *x_hostname[MAX_REC];
	int x_numconnect;
	int x_port[MAX_REC];
    int x_protocol;
		/* multithread stuff */
	pthread_t x_threadid;            /* id of child thread */
	pthread_attr_t x_threadattr;     /* attributes of child thread */
} t_netdist;

static void sys_sockerror(char *s)
{
#ifdef NT
    int err = WSAGetLastError();
    if (err == 10054) return;
#endif
#ifdef UNIX
    int err = errno;
#endif
    post("%s: %s (%d)\n", s, strerror(err), err);
}

static void sys_closesocket(int fd) {

#ifdef UNIX
    close(fd);
#endif
#ifdef NT
    closesocket(fd);
#endif
}


static void netdist_tick(t_netdist *x)
{
    outlet_float(x->x_obj.ob_outlet, x->x_numconnect + 1);
}

static void *netdist_new(t_floatarg udpflag)
{
	int i;
    t_netdist *x = (t_netdist *)pd_new(netdist_class);
    outlet_new(&x->x_obj, &s_float);
    x->x_clock = clock_new(x, (t_method)netdist_tick);
    for(i = 0; i < MAX_REC; i++)x->x_fd[i] = -1;
	x->x_numconnect = -1;
    x->x_protocol = (udpflag != 0 ? SOCK_DGRAM : SOCK_STREAM);

	/* prepare child thread */
    if(pthread_attr_init(&x->x_threadattr) < 0)
       post("netdist: warning: could not prepare child thread" );
    if(pthread_attr_setdetachstate(&x->x_threadattr, PTHREAD_CREATE_DETACHED) < 0)
       post("netdist: warning: could not prepare child thread" );
    return (x);
}

static void *netdist_child_connect(void *w)
{
	int i;

	t_netdist *x = (t_netdist*) w;
    struct sockaddr_in server;
    struct hostent *hp;
    int sockfd;
    int portno;
	i = x->x_numconnect + 1;
	portno = x->x_port[i];
    	/* create a socket */
    sockfd = socket(AF_INET, x->x_protocol, 0);
#if 0
    fprintf(stderr, "send socket %d\n", sockfd);
#endif
    if (sockfd < 0)
    {
    	sys_sockerror("socket");
    	return (x);
    }
		/* connect socket using hostname provided in command line */
    server.sin_family = AF_INET;
    hp = gethostbyname(x->x_hostname[i]);
    if (hp == 0)
    {
		post("bad host?\n");
		return (x);
    }
    memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length);

		/* assign client port number */
    server.sin_port = htons((u_short)portno);

    post("connecting to port %d", portno);
		/* try to connect */
    if (connect(sockfd, (struct sockaddr *) &server, sizeof (server)) < 0)
    {
    	sys_sockerror("connecting stream socket");
    	sys_closesocket(sockfd);
    	return (x);
    }
    x->x_fd[i] = sockfd;
		/* outlet_float is not threadsafe ! */
    // outlet_float(x->x_obj.ob_outlet, 1);
	x->x_numconnect++;	/* count connection */
		/* use callback instead to set outlet */
	clock_delay(x->x_clock, 0);
	return (x);
}

static void netdist_connect(t_netdist *x, t_symbol *hostname,
    t_floatarg fportno)
{
	int i;
		/* we get hostname and port and pass them on
		to the child thread that establishes the connection */
	for(i = 0; i <= x->x_numconnect; i++)
	{		/* check if we are already connected */
		if (hostname->s_name == x->x_hostname[i] && fportno == x->x_port[i])
		{
    		error("netdist_connect: already connected");
    		return;
		}
	}
	x->x_hostname[x->x_numconnect + 1] = hostname->s_name;
	x->x_port[x->x_numconnect + 1] = fportno;

		/* start child thread */
	if(pthread_create( &x->x_threadid, &x->x_threadattr, netdist_child_connect, x) < 0)
		post("netdist: could not create new thread");
}

static void netdist_disconnect(t_netdist *x, t_symbol *hostname, t_floatarg port)
{
	int i, j;
	for(i = 0; i <= x->x_numconnect; i++)
	{
		if((hostname->s_name == x->x_hostname[i]) && ((int)port == x->x_port[i]))
		{
				/* search for connection */
			if (x->x_fd[i] >= 0)
			{
    			sys_closesocket(x->x_fd[i]);
    			x->x_fd[i] = -1;
				x->x_numconnect--;
    			outlet_float(x->x_obj.ob_outlet, x->x_numconnect + 1);
				for(j = i; j <= x->x_numconnect; j++)
				{
					x->x_hostname[j] = x->x_hostname[j + 1];
					x->x_port[j] = x->x_port[j + 1];
					x->x_fd[j] = x->x_fd[j + 1];
				}
			}
		}
	}
}

static void netdist_send(t_netdist *x, t_symbol *s, int argc, t_atom *argv)
{
	int i = 0;

	for(i = 0; i <= x->x_numconnect; i++)
	{
		if (x->x_fd[i] >= 0)
		{
			t_binbuf *b = binbuf_new();
			char *buf, *bp;
			int length, sent;
			t_atom at;
			binbuf_add(b, argc, argv);
			SETSEMI(&at);
			binbuf_add(b, 1, &at);
			binbuf_gettext(b, &buf, &length);
			for (bp = buf, sent = 0; sent < length;)
			{
				static double lastwarntime;
				static double pleasewarn;
				double timebefore = clock_getlogicaltime();
    				int res = send(x->x_fd[i], buf, length-sent, 0);
    				double timeafter = clock_getlogicaltime();
    				int late = (timeafter - timebefore > 0.005);
    				if (late || pleasewarn)
    				{
    	    			if (timeafter > lastwarntime + 2)
    	    			{
    	    				 post("netdist blocked %d msec",
    	    	     			(int)(1000 * ((timeafter - timebefore) + pleasewarn)));
    	    				 pleasewarn = 0;
    	    				 lastwarntime = timeafter;
    	    			}
    	    			else if (late) pleasewarn += timeafter - timebefore;
    				}
    				if (res <= 0)
    				{
    					sys_sockerror("netdist");
    					netdist_disconnect(x, gensym(x->x_hostname[i]), x->x_port[i]);
    					break;
    				}
    				else
    				{
    					sent += res;
    					bp += res;
    				}
			}
			t_freebytes(buf, length);
			binbuf_free(b);
		}
	}
	if(x->x_numconnect == -1) error("netdist: not connected");
}

	/* disconnect all */
static void netdist_clear(t_netdist *x)
{
	int i, j, n;
	n = x->x_numconnect;
	for (i = n; i >= 0; i--)
	{
		netdist_disconnect(x, gensym(x->x_hostname[i]), x->x_port[i]);
	}
}

static void netdist_print(t_netdist *x)
{
	int i;
	post("netdist: %d connection(s) established:", x->x_numconnect + 1);
	for (i = x->x_numconnect; i >= 0; i--)
	{
		post("         \"%s\", port %d",x->x_hostname[i], x->x_port[i]);
	}
}

static void netdist_free(t_netdist *x)
{
    netdist_clear(x);
    clock_free(x->x_clock);
}

#ifndef MAXLIB
void netdist_setup(void)
{
    netdist_class = class_new(gensym("netdist"), (t_newmethod)netdist_new,
    	(t_method)netdist_free, sizeof(t_netdist), 0, A_DEFFLOAT, 0);
    class_addmethod(netdist_class, (t_method)netdist_connect, gensym("connect"), A_SYMBOL, A_FLOAT, 0);
    class_addmethod(netdist_class, (t_method)netdist_disconnect, gensym("disconnect"), A_SYMBOL, A_FLOAT, 0);
    class_addmethod(netdist_class, (t_method)netdist_send, gensym("send"), A_GIMME, 0);
	class_addmethod(netdist_class, (t_method)netdist_clear, gensym("clear"), 0);
	class_addmethod(netdist_class, (t_method)netdist_print, gensym("print"), 0);
	class_sethelpsymbol(netdist_class, gensym("help-netdist.pd"));
    post(version);
}
#else
void maxlib_netdist_setup(void)
{
    netdist_class = class_new(gensym("maxlib_netdist"), (t_newmethod)netdist_new,
    	(t_method)netdist_free, sizeof(t_netdist), 0, A_DEFFLOAT, 0);
	class_addcreator((t_newmethod)netdist_new, gensym("netdist"), A_DEFFLOAT, 0);
    class_addmethod(netdist_class, (t_method)netdist_connect, gensym("connect"), A_SYMBOL, A_FLOAT, 0);
    class_addmethod(netdist_class, (t_method)netdist_disconnect, gensym("disconnect"), A_SYMBOL, A_FLOAT, 0);
    class_addmethod(netdist_class, (t_method)netdist_send, gensym("send"), A_GIMME, 0);
	class_addmethod(netdist_class, (t_method)netdist_clear, gensym("clear"), 0);
	class_addmethod(netdist_class, (t_method)netdist_print, gensym("print"), 0);
	class_sethelpsymbol(netdist_class, gensym("maxlib/help-netdist.pd"));
}
#endif

--- NEW FILE: score.c ---
/* ------------------------- score   ------------------------------------------ */
/*                                                                              */
/* Simple score following / orientation. Incoming data gets compared to a       */
/* score stored in an array or table.                                           */
/* Written by Olaf Matthes (olaf.matthes at gmx.de)                                */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

#include "m_pd.h"

#define MAX_NOTES 32                /* maximum number of notes that can be stored */

static char *version = "score v0.1, score follower written by Olaf Matthes <olaf.matthes at gmx.de>";
 
typedef struct score
{
  t_object x_ob;
  t_inlet  *x_invelo;               /* inlet for velocity */
  t_inlet  *x_inreset;              /* inlet to reset the object */
  t_outlet *x_outindex;             /* index :: position in given score */
  t_outlet *x_outerror;             /* indicates lost orientation */
  t_symbol *x_sym;                  /* name of array that contains the score */
  t_garray *x_buf;                  /* the above array itselfe */

  t_int    x_state;                 /* indicates state of score following: */
                                    /* running = 1, record = -1, stop = 0  */
  t_int    x_skipindex;             /* max. number of notes to skip */
  t_float  x_skiptime;              /* max time in ms to skip */
  t_int    x_index;                 /* position in array / score */
  t_int    x_lastpitch;
  t_int    x_error;

  t_int    x_notecount;
  t_int    x_pitch;
  t_int    x_velo;
	/* helpers needed to do the calculations */
  double   x_starttime[MAX_NOTES];
  double   x_laststarttime;
  t_int    x_alloctable[MAX_NOTES];

} t_score;

static void score_float(t_score *x, t_floatarg f)
{
	/* This is the score following algorhythm:

	    first, we check if the note we got is in the score. In case
		it's not the next note, we'll search 'skipnotes' in advance.
		In case that fails we go back 'skipnotes' and check them. As
		extra these notes have to be 'younger' than 'skiptime' (to 
		avoid going back too far in case of slow melodies)
		As last resort we check if we probably just got the same not 
		again (double trigger from keyboard or the like) 
	                                                                 */

	t_int velo = x->x_velo;     /* get the velocity */
	t_garray *b = x->x_buf;		/* make local copy of array */
	float *tab;                 /* we'll store notes in here */
	int items;
	int i, j, n, check;

	x->x_pitch = (t_int)f;
	x->x_error = 0;

		/* check our array */
	if (!b)
	{
		post("score: no array selected!");
		x->x_error = 1;
		goto output;
	}
	if (!garray_getfloatarray(b, &items, &tab))
	{
		post("score: couldn't read from array!");
		x->x_error = 1;
		goto output;
	}

	if (x->x_state)	/* score follower is running */
	{
		n = check = x->x_notecount;		/* make local copys */

		if (x->x_velo != 0)		/* store note-on in alloctable */
		{
				/* store note in alloctable */
			x->x_alloctable[n] = (t_int)x->x_pitch;
				/* store note-on time */
			x->x_starttime[n] = clock_getlogicaltime();
			if(++x->x_notecount >= MAX_NOTES)x->x_notecount = 0;  /* total number of notes has increased */
		} else return;	/* we don't care about note-off's */

			/* first we try to find a match within the skip area */
			/* ( probably looking ahead in the score ) */
		for (i = x->x_index + 1; i < (x->x_index + x->x_skipindex + 1); i++)
		{
			// post("%d: %d -> %d", i, x->x_alloctable[n], (t_int)tab[i]);
			if(x->x_alloctable[n] == (t_int)tab[i])
			{
				if(i - x->x_index != 1) post("score: skipped %d notes!", i - x->x_index - 1);
				x->x_alloctable[n] = -1;		/* delete note, we've matched it! */
				x->x_index = i;
				goto output;
			}
		}

			/* then we look back within the boudaries of skiptime */
		for (i = x->x_index - 1; i > (x->x_index - x->x_skipindex) - 1; i--)
		{
			check = n;	/* get current notecount */

			for (j = 0; j < MAX_NOTES; j++)	/* check with every note from our alloctable */
			{ 
				if (x->x_alloctable[check] == (t_int)tab[i])	/* this one would fit */
				{
						/* check the time restrictions */
					if (clock_gettimesince(x->x_starttime[check]) < x->x_skiptime)
					{
						if (i != x->x_index) post("score: skipped %d notes in score!", x->x_index - i);
						if (j != 0) post("score: skipped %d notes from input!", j);
						post("score: going back by %g milliseconds!", clock_gettimesince(x->x_starttime[check]));
						x->x_index = i;
							/* new notecount: we assume the notes we skipped are errors made by the */
							/* performer. new notes will be added right behind the last valid one */
						x->x_notecount = (check++) % MAX_NOTES;
						x->x_alloctable[x->x_notecount - 1] = -1;	/* delete note since we've matched it */
						goto output;
					}
					else /* ough, too old ! */
					{
						post("score: matching note is too old! (ignored)");
						x->x_alloctable[check] = 0;		/* delete note since it's too old */
						x->x_error = 1;
						goto output;	/* stop with first match as all others would be far older */
					}
				}
				if(--check < 0) check = MAX_NOTES - 1;	/* decrease counter */
														/* as we want to go back in time */
			}
		}
			/* or is it just the same note again ??? (double trigger...) */
		if(x->x_pitch == x->x_lastpitch)
		{
			post("score: repetition! (ignored)");
			x->x_alloctable[x->x_notecount - 1] = -1; /* forget this one */
			return;
		}

			/* in case we found nothing: indicate that! */
		x->x_error = 1;
		post("score: couldn't find any matches !");
		x->x_lastpitch = x->x_pitch;
		goto output;
	}
	else return;

output:
		/* output index */
	outlet_float(x->x_outindex, x->x_index);
		/* bang in case of error */
	if(x->x_error) outlet_bang(x->x_outerror);
}

static void score_ft1(t_score *x, t_floatarg f)
{
	x->x_velo = (t_int)f;
}

	/* start following the previoisly recorded score */
static void score_start(t_score *x, t_symbol *s, t_int argc, t_atom* argv)
{
	x->x_index = (t_int)atom_getfloatarg(0, argc, argv);
	if(x->x_index > 0)
	{
		post("score: starting at note %d", x->x_index);
	}
	else post("score: start following");
	x->x_index--;	/* because our array starts with 0 */
	x->x_state = 1;
}
	/* resume following the previoisly recorded score */
static void score_resume(t_score *x)
{
	x->x_state = 1;
	post("score: resume following");
}

	/* stop following the previoisly recorded score */
static void score_stop(t_score *x)
{
	x->x_state = 0;
	post("score: stop following");
}

	/* choose the array that holds the score */
void score_set(t_score *x, t_symbol *s)
{
	t_garray *b;
	
	x->x_sym = s;

	if ((b = (t_garray *)pd_findbyclass(s, garray_class)))
	{
		post("score: array set to \"%s\"", s->s_name);
		x->x_buf = b;
	} else {
		post("score: no array \"%s\" (error %d)", s->s_name, b);
		x->x_buf = 0;
	}
}

static void score_reset(t_score *x)
{
	int i;

	x->x_state = 0;				/* don't follow */
	x->x_error = 0;
	x->x_index = -1;
	x->x_notecount = 0;
	x->x_lastpitch = 0;
	for(i = 0; i < MAX_NOTES; i++)x->x_alloctable[i] = -1;

	post("score: reset");
}

static void score_free(t_score *x)
{
	// nothing to do
}

static t_class *score_class;

static void *score_new(t_symbol *s, t_floatarg fskipindex, t_floatarg fskiptime)
{
	int i;

    t_score *x = (t_score *)pd_new(score_class);
    x->x_invelo = inlet_new(&x->x_ob, &x->x_ob.ob_pd, gensym("float"), gensym("ft1"));
    x->x_inreset = inlet_new(&x->x_ob, &x->x_ob.ob_pd, gensym("bang"), gensym("reset"));
	x->x_outindex = outlet_new(&x->x_ob, gensym("float"));
	x->x_outerror = outlet_new(&x->x_ob, gensym("float"));

	x->x_sym = s;				/* get name of array */
	score_set(x,x->x_sym);      /* set array */
	if(!fskipindex)fskipindex = 2;
	if(!fskiptime)fskiptime = 300.0;
	x->x_skipindex = (t_int)fskipindex;
	x->x_skiptime = (t_float)fskiptime;
	post("score: skipindex set to %d, skiptime set to %g milliseconds", x->x_skipindex, x->x_skiptime);

	x->x_state = 0;				/* don't follow */
	x->x_error = 0;
	x->x_index = -1;
	x->x_notecount = 0;
	x->x_pitch = x->x_lastpitch = -1;
	for(i = 0; i < MAX_NOTES; i++)x->x_alloctable[i] = -1;

    return (void *)x;
}

#ifndef MAXLIB
void score_setup(void)
{
    score_class = class_new(gensym("score"), (t_newmethod)score_new,
    	(t_method)score_free, sizeof(t_score), 0, A_SYMBOL, A_DEFFLOAT, A_DEFFLOAT, 0);
    class_addmethod(score_class, (t_method)score_reset, gensym("reset"), 0);
	class_addmethod(score_class, (t_method)score_resume, gensym("resume"), 0);
    class_addmethod(score_class, (t_method)score_start, gensym("start"), A_GIMME, 0);
    class_addmethod(score_class, (t_method)score_stop, gensym("stop"), 0);
    class_addmethod(score_class, (t_method)score_ft1, gensym("ft1"), A_FLOAT, 0);
    class_addmethod(score_class, (t_method)score_reset, gensym("reset"), A_GIMME, 0);
	class_addmethod(score_class, (t_method)score_set, gensym("set"), A_SYMBOL, 0);
    class_addfloat(score_class, score_float);
    class_sethelpsymbol(score_class, gensym("help-score.pd"));
    post(version);
}
#else
void maxlib_score_setup(void)
{
    score_class = class_new(gensym("maxlib_score"), (t_newmethod)score_new,
    	(t_method)score_free, sizeof(t_score), 0, A_SYMBOL, A_DEFFLOAT, A_DEFFLOAT, 0);
	class_addcreator((t_newmethod)score_new, gensym("score"), A_SYMBOL, A_DEFFLOAT, A_DEFFLOAT, 0);
    class_addmethod(score_class, (t_method)score_reset, gensym("reset"), 0);
	class_addmethod(score_class, (t_method)score_resume, gensym("resume"), 0);
    class_addmethod(score_class, (t_method)score_start, gensym("start"), A_GIMME, 0);
    class_addmethod(score_class, (t_method)score_stop, gensym("stop"), 0);
    class_addmethod(score_class, (t_method)score_ft1, gensym("ft1"), A_FLOAT, 0);
    class_addmethod(score_class, (t_method)score_reset, gensym("reset"), A_GIMME, 0);
	class_addmethod(score_class, (t_method)score_set, gensym("set"), A_SYMBOL, 0);
    class_addfloat(score_class, score_float);
    class_sethelpsymbol(score_class, gensym("maxlib/help-score.pd"));
}
#endif

--- NEW FILE: nroute.c ---
/* ------------------------- nroute  ------------------------------------------ */
/*                                                                              */
/* Route input according to Nth element.                                        */
/* Written by Olaf Matthes <olaf.matthes at gmx.de>                                */
/* Based on code found on the web.                                              */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

/*
   inlet 1: anything to be routed
   inlet 2: anything to be matched to
   inlet 3: position to match
   out   1: input if match found
   out   2: input if match not found
*/

#include "m_pd.h"

static char *version = "nroute v0.1, written by Olaf Matthes <olaf.matthes at gmx.de>";

typedef struct nroute
{
	t_object x_obj;		
	t_outlet *out1;	
	t_outlet *out2;
	t_int    pos;
	t_atom   match;
} t_nroute;

typedef struct proxy
{
	t_object obj;
	t_int index;		/* number of proxy inlet(s) */
	t_nroute *x;		/* we'll put the other struct in here */
} t_proxy;


	/* this is the routine that actually does the routing / matching */
	/* it get's called by all other routines that get any input and  */
	/* even handles the second (proxy) inlet !                       */
static void nroute_any(t_nroute *x, t_symbol *s, int argc, t_atom *argv)
{
	if(s)
	{
		if (x->pos == 1 && x->match.a_type == A_SYMBOL && x->match.a_w.w_symbol == s)
			outlet_anything (x->out1,s,argc,argv);
		else if (x->pos > 1 && x->pos <= argc + 1 && 
			argv[x->pos-2].a_type == x->match.a_type && 
			argv[x->pos-2].a_w.w_float == x->match.a_w.w_float)
				outlet_anything (x->out1,s,argc,argv);
		else outlet_anything (x->out2,s,argc,argv);
	}
	else
	{
		if (x->pos > 0 && x->pos <= argc && 
			argv[x->pos-1].a_type == x->match.a_type && 
			argv[x->pos-1].a_w.w_float == x->match.a_w.w_float)
			outlet_list (x->out1,0,argc,argv);
		else outlet_list (x->out2,0,argc,argv);
	}
}

static void nroute_float(t_nroute *x, float f)
{
	t_atom a;
	
	SETFLOAT (&a,f);
	nroute_any(x,0,1,&a);
}

static void nroute_list(t_nroute *x, t_symbol *s, int argc, t_atom *argv)
{
	nroute_any(x,0,argc,argv);
}

static void nroute_setmatch(t_proxy *p, t_symbol *s, int argc, t_atom *argv)
{
	t_nroute *x = (t_nroute *)(p->x);

	if(argc == 0)	/* have to match a symbol */
	{
		x->match.a_type = A_SYMBOL;
		x->match.a_w.w_symbol = s;
	}
	else	/* got a float */
	{
		if(argc > 1)
		{
			post("nroute: middle inlet accepts only (float,symbol) for match");
			return;
		}
		x->match.a_type = A_FLOAT;
		x->match.a_w.w_float = argv[0].a_w.w_float;
	}
}

static void nroute_setpos(t_nroute *x, t_floatarg f)
{
	x->pos = (t_int)f;
}

static t_class *nroute_class;
static t_class *proxy_class;

static void *nroute_new(t_symbol *s, int argc, t_atom *argv)
{
    t_nroute *x = (t_nroute *)pd_new(nroute_class);
	t_proxy *inlet = (t_proxy *)pd_new(proxy_class);	/* for the proxy inlet */

	inlet->x = x;	/* make x visible to the proxy inlets */

	x->pos = 1;
	x->match.a_type = A_NULL;
	if (argc > 2) { error ("nroute: extra arguments"); return 0; }
	if (argc > 1) {
		if (argv[1].a_type == A_FLOAT) x->pos = argv[1].a_w.w_float;
		else { post ("nroute: second argument must be (int) position"); return 0; }
	}
	if (argc > 0) {
		x->match.a_type = argv[0].a_type;
		x->match.a_w.w_float = argv[0].a_w.w_float;
	}
    inlet->index = 0;	/* we are going to create a proxy inlet no. 0 */
		/* it belongs to the object t_nroute but the destination is t_proxy */
    inlet_new(&x->x_obj, &inlet->obj.ob_pd, 0,0);
		/* and now a 'normal' third inlet */
    inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("right"));
	x->out1 = outlet_new(&x->x_obj, gensym("list"));
	x->out2 = outlet_new(&x->x_obj, gensym("list"));
	return (x);
}

#ifndef MAXLIB
void nroute_setup(void)
{
	/* the object's class: */
    nroute_class = class_new(gensym("nroute"), (t_newmethod)nroute_new,
    	0, sizeof(t_nroute), 0, A_GIMME, 0);
#else
void maxlib_nroute_setup(void)
{
	/* the object's class: */
    nroute_class = class_new(gensym("maxlib_nroute"), (t_newmethod)nroute_new,
    	0, sizeof(t_nroute), 0, A_GIMME, 0);
	class_addcreator((t_newmethod)nroute_new, gensym("nroute"), A_GIMME, 0);
#endif
	/* a class for the proxy inlet: */
	proxy_class = class_new(gensym("maxlib_nroute_proxy"), NULL, NULL, sizeof(t_proxy),
		CLASS_PD|CLASS_NOINLET, A_NULL);

	class_addmethod(nroute_class, (t_method)nroute_setpos, gensym("right"), A_FLOAT, 0);
    class_addfloat(nroute_class, nroute_float);
	class_addlist(nroute_class, nroute_list);
	class_addanything(nroute_class, nroute_any);
	class_addanything(proxy_class, nroute_setmatch);
#ifndef MAXLIB
    class_sethelpsymbol(nroute_class, gensym("help-nroute.pd"));
    post(version);
#else
    class_sethelpsymbol(nroute_class, gensym("maxlib/help-nroute.pd"));
#endif
}

--- NEW FILE: subst.c ---
/* ------------------------- subst   ------------------------------------------ */
/*                                                                              */
/* Performs 'self-similar' substitution of a given list of values.              */
/* Written by Olaf Matthes <olaf.matthes at gmx.de>                                */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */
#include "m_pd.h"


static char *version = "subst v0.1, self-similar substitution of rows (list or array)\n"
                       "            written by Olaf Matthes <olaf.matthes at gmx.de>";

#undef DEBUG
//#define DEBUG

#define MAXSIZE 1024

#include <stdio.h>
#include <stdlib.h>


//
// Maxlife object data structure
//
typedef struct subst
{
	t_object x_obj;				// must begin every object 
	t_outlet *x_outlist;		// outlet for the processed list 
	t_outlet *x_outlength;
	t_atom   x_row[MAXSIZE];	// row of values to get processed
	t_int    x_length;			// length of row
	t_int    x_order;			// size of the CA field/world
	t_symbol *x_array;			// name of array that holds the data
	t_garray *x_buf;			// content of that array
} t_subst;

//
// Function prototypes for our methods and functions
//
static t_class *subst_class;		// global variable that points to the Maxlife class

//
// get the sum of intervals from no a to no b
// Parameters: the row, it's length, intv a, intev b
//
static int sum_intv(t_atom *argv, int argc, int a, int b)
{
	int i;
	int summe = 0;			// sum of intervals

	if(a==b)
		return(0);			// same index
	if(atom_getintarg(a, argc, argv) == atom_getintarg(b, argc, argv))
		return(0);			// same value

	for(i=a;i<b;i++)		// for all values from a to b....
	{
		if(atom_getintarg(i + 1, argc, argv) > atom_getintarg(i, argc, argv))	// positive intv.
		{
			summe += ((atom_getintarg(i + 1, argc, argv) - atom_getintarg(i, argc, argv)) % 12);
		}
		else				// negative interval
		{
			summe -= ((atom_getintarg(i + 1, argc, argv) - atom_getintarg(i, argc, argv)) % 12);
		}
	}
	return(summe);
}
//----- Anzahl Partialreihen mit Interval d  -------------------------------
static int no_part(t_atom *argv, int argc, int a, int b, int d)		// nn
{
	int i,j,r = 0;

    if(a = b)return(0);

    for(i = a; i < b; i++)
    {
            for(j=a+1;j<b;j++)
            {
        	if(sum_intv(argv, argc, i, j) == d)
				r++;
            }
    }
    return(r);
}

//----- n-te Partialreihe der Länge l mit Interval d -----------------------
static int n_part_intv(t_atom *argv, int argc, int a, int b, int l, int d, int n) // nn
{
	int i,j, r = 0;
    if(n > no_part(argv, argc, a, b, d))
		return(-1);
    for(i = 1; i = (b - a); i++)
    {
        for(j = 1; j = b; j++)
        {
        	if(sum_intv(argv, argc, i, j) == d) 
				r++;
        }
    }
    return(r);
}
//----- Test, ob Partialreihe der Ordnung o mit Interval d existiert ----------
static int check_part_intv(t_atom *argv, int argc, int o, int d)
{
	int z;

    for(z = 0; z < argc - o; z++)
    {
            if(sum_intv(argv, argc, z, z + o) == d)
				return(z);	// Abstand von Reihenanfang
    }

    return(-1);
}

static int my_random(int range) {
	int ret = rand();
	ret = ret % range;	// limit to desired output range
	return(ret);
}

//
// the substitution algorhythm
//
static int subst_calc(t_subst *x, int n)
{
	int i,j,k,l,o = x->x_order;
    int s = -1;
    int intv;
	t_atom newrow[MAXSIZE];
	t_garray *A = x->x_buf;
	int npoints;
	t_float *vec;

	if(x->x_length <= 1)
	{
		post("subst: need some data first!");
		return(-1);
	}
    srand((unsigned int)clock_getlogicaltime());

    if(n == -1)	// no interval given: choose one by chance
	{
		do
		{
			n = my_random(x->x_length - 1);						// choose interval
			intv = sum_intv(x->x_row, x->x_length, n, n + 1);	// size of this interval
		}
		while(intv == 0);				// ...until we found one that is not 0!
	}
	else intv = sum_intv(x->x_row, x->x_length, n, n + 1);

#ifdef DEBUG
    post("subst: substitution of %dth interval (%d halftones)", n+1, intv);
#endif

    /* for-Schleife für möglichst lange Substitutionen
    for(j=anzahlReihe(alteReihe);j>2;j--)				*/
    for(j = x->x_order; j < x->x_length; j++)	// prefer lower orders (min. 2)
    {							// search for possible order...
            s = check_part_intv(x->x_row, x->x_length, j, intv);
            if(s != -1)			// check if there is a partial row with the interval we want
            {
                o = j;			// save actual order, might be larger then x->x_order
                break;			// ... do it!
            }
            if(o == j)break;	// found one
    }

    for(i = 0; i < x->x_length; i++)
    {
        if(i <= n)		// just copy values before substitution
        {
            newrow[i] = x->x_row[i];
        }
        if((i == n) && (s != -1))	// now substitute
        {
            for(k=1;k<o;k++)		// well get order - 1 new values...
            {
                SETFLOAT(newrow + (i + k), (atom_getintarg((i + k - 1), 1024, newrow) 
					+ sum_intv(x->x_row, x->x_length, s+k-1, s+k)));
#ifdef DEBUG
                post("subst: new interval[%d]: %d ", k, sum_intv(x->x_row, x->x_length, s+k-1, s+k));
#endif
            }
            post("subst: replaced interval %d (%d halftones) with %d new intervals", n, intv, o);
        }
        else if((i == n) && (s == -1))	// not partial row found
        {
            o = 1;		// order is 1 -> now substitution
            newrow[i] = x->x_row[i];	// copy the next value of the row
            post("subst: coundn't find any partial rows to fit in!");
        }

        if(i>n)		// behind substitution
        {
            newrow[i+(o-1)] = x->x_row[i];	// copy rest or row
        }
    }

    //  copy stuff back...
    x->x_length = l = x->x_length + o - 1;
	for(i = 0; i < x->x_length; i++)
		x->x_row[i] = newrow[i];

	// write to array
	if(x->x_array)if (!(A = (t_garray *)pd_findbyclass(x->x_array, garray_class)))
		error("subst: %s: no such array", x->x_array->s_name);
	else if (!garray_getfloatarray(A, &npoints, &vec))
		error("subst: %s: bad template ", x->x_array->s_name);
	else
	{
		i = 0;

		if (l >= npoints)	// keep end of array
		{
			while(npoints--)
			{
				*vec++ = atom_getfloat(x->x_row + i);
				i++;
			}
		}
		else				// update 
		{
			npoints -= l;
			while (l--)
			{
				*vec++ = atom_getfloat(x->x_row + i);
				i++;
			}
			while (npoints--) *vec++ = 0;
		}
		garray_redraw(A);
	}

	// output stuff
	outlet_float(x->x_outlength, x->x_length);
	outlet_list(x->x_outlist, NULL, x->x_length, x->x_row);

    return(0);
}

static void subst_list(t_subst *x, t_symbol *s, int argc, t_atom *argv)
{	
	t_garray *b = x->x_buf;		/* make local copy of array */
	float *tab;                 /* we'll store notes in here */
	int items;
	int i;

	for(i = 0; i < argc; i++)
	{
		x->x_row[i] = argv[i];		// just copy input
	}
	x->x_length = argc;

}

//
// choose the array that holds the processed row (output!!)
//
void subst_set(t_subst *x, t_symbol *s)
{
	t_garray *b;
	
	x->x_array = s;

	if ((b = (t_garray *)pd_findbyclass(s, garray_class)))
	{
		post("subst: array set to \"%s\"", s->s_name);
		x->x_buf = b;
	} else {
		post("subst: no array \"%s\" (error %d)", s->s_name, b);
		x->x_buf = 0;
	}
}

//
// load row from array (input!!)
//
static void subst_load(t_subst *x, t_symbol *s)
{	
	t_garray *b;		/* make local copy of array */
	t_float *tab;                 /* the content itselfe */
	int items, i;

	if ((b = (t_garray *)pd_findbyclass(s, garray_class)))
	{
		post("subst: array set to \"%s\"", s->s_name);
	} else {
		post("subst: no array \"%s\" (error %d)", s->s_name, b);
		return;
	}

		// read from our array
	if (!garray_getfloatarray(b, &items, &tab))
	{
		post("subst: couldn't read from array!");
		return;
	}
	for(i = 0; i < items; i++)
	{
		SETFLOAT(x->x_row + i, tab[i]);		// copy array into x->x_row
	}
	x->x_length = items;
	post("subst: loaded %d values from array \"%s\"", items, s->s_name);
}

//
// substitute an interval choosen by chance
//
static void subst_bang(t_subst *x)
{	
	subst_calc(x, -1);
}

//
// substitute the Nth interval
//
static void subst_intv(t_subst *x, t_floatarg f)
{	
	int i = (int)f;
	if(i > x->x_length) i = x->x_length;
	subst_calc(x, i);
}

//
// set the minimum order of substitution
//
static void subst_set_order(t_subst *x, t_floatarg f)
{
	x->x_order = (t_int)f;
	if(x->x_order < 2)x->x_order = 2;
	post("subst: set order to %d", x->x_order);
}

//
// method to print out: but what?
//
static void subst_display(t_subst *x)
{
}

//
// function to create an instance of the subst class
//
static void *subst_new(t_symbol *s, int argc, t_atom *argv)
{
	long i;
	t_symbol *sym;
	t_subst *x = (t_subst *)pd_new(subst_class);
	// read in order...
	x->x_order = 3;
	if(argc == 1)
	{
		x->x_order = atom_getintarg(0, argc, argv);
	}
	else if(argc == 2)
	{
		sym = atom_getsymbolarg(0, argc, argv);
		x->x_order = atom_getintarg(1, argc, argv);
		subst_set(x, sym);
	}

	// create outlets
	x->x_outlist = outlet_new(&x->x_obj, gensym("list"));
	x->x_outlength = outlet_new(&x->x_obj, gensym("float"));
		
	return(x);				// always return a copy of the created object 
}

static void subst_free(t_subst *x)
{
	/* nothing to do */
}

#ifndef MAXLIB
void subst_setup(void)
{
    subst_class = class_new(gensym("subst"), (t_newmethod)subst_new,
    	(t_method)subst_free, sizeof(t_subst), 0, A_GIMME, 0);
    class_addmethod(subst_class, (t_method)subst_set_order, gensym("order"), A_FLOAT, 0);
    class_addmethod(subst_class, (t_method)subst_intv, gensym("interval"), A_FLOAT, 0);
	class_addmethod(subst_class, (t_method)subst_set, gensym("set"), A_SYMBOL, 0);
	class_addmethod(subst_class, (t_method)subst_load, gensym("load"), A_SYMBOL, 0);
	class_addmethod(subst_class, (t_method)subst_display, gensym("display"), 0);
	class_addlist(subst_class, subst_list);
	class_addbang(subst_class, subst_bang);
    class_sethelpsymbol(subst_class, gensym("help-subst.pd"));
    post(version);
}
#else
void maxlib_subst_setup(void)
{
    subst_class = class_new(gensym("maxlib_subst"), (t_newmethod)subst_new,
    	(t_method)subst_free, sizeof(t_subst), 0, A_GIMME, 0);
	class_addcreator((t_newmethod)subst_new, gensym("subst"), A_GIMME, 0);
    class_addmethod(subst_class, (t_method)subst_set_order, gensym("order"), A_FLOAT, 0);
    class_addmethod(subst_class, (t_method)subst_intv, gensym("interval"), A_FLOAT, 0);
	class_addmethod(subst_class, (t_method)subst_set, gensym("set"), A_SYMBOL, 0);
	class_addmethod(subst_class, (t_method)subst_load, gensym("load"), A_SYMBOL, 0);
	class_addmethod(subst_class, (t_method)subst_display, gensym("display"), 0);
	class_addlist(subst_class, subst_list);
	class_addbang(subst_class, subst_bang);
    class_sethelpsymbol(subst_class, gensym("maxlib/help-subst.pd"));
}
#endif

--- NEW FILE: weibull.c ---
/* ---------------------------- rand_weibull ---------------------------------- */
/*                                                                              */
/* rand_weibull generates a weibull distributed random variable.                */
/* Written by Olaf Matthes (olaf.matthes at gmx.de)                                */
/* Based on code found in Dodge/Jerse "Computer Music"                          */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

#include "m_pd.h"
#include <stdlib.h>
#include <time.h>
#include <math.h>

#define fran()         (t_float)rand()/(t_float)RAND_MAX
#ifndef M_PI
#define M_PI           3.1415927
#endif

static char *version = "weibull v0.1, generates a weibull distributed random variable\n"
                       "              written by Olaf Matthes <olaf.matthes at gmx.de>";

/* -------------------------- rand_weibull ------------------------------ */

static t_class *rand_weibull_class;

typedef struct _rand_weibull
{
    t_object x_obj;
	t_float  x_s;
	t_float  x_t;
} t_rand_weibull;

static void *rand_weibull_new(t_floatarg s, t_floatarg t)
{
    t_rand_weibull *x = (t_rand_weibull *)pd_new(rand_weibull_class);
    srand( (unsigned)time( NULL ) );
    floatinlet_new(&x->x_obj, &x->x_s);
    floatinlet_new(&x->x_obj, &x->x_t);
    outlet_new(&x->x_obj, &s_float);
	x->x_s = s;
	x->x_t = t;
    return (x);
}

static void rand_weibull_bang(t_rand_weibull *x)
{
	t_float u, a, t, tinv;
	t = (x->x_t <= 0 ? 0.0001 : x->x_t);
	tinv = 1/t;
	do
	{
		u = fran();
	}
	while(u == 0 || u == 1);
	a = 1/(1 - u);
    outlet_float(x->x_obj.ob_outlet, x->x_s*pow(log(a), tinv));
}

#ifndef MAXLIB
void weibull_setup(void)
{
    rand_weibull_class = class_new(gensym("weibull"), (t_newmethod)rand_weibull_new, 0,
    	sizeof(t_rand_weibull), 0, A_DEFFLOAT, A_DEFFLOAT, 0);
#else
void maxlib_weibull_setup(void)
{
    rand_weibull_class = class_new(gensym("maxlib_weibull"), (t_newmethod)rand_weibull_new, 0,
    	sizeof(t_rand_weibull), 0, A_DEFFLOAT, A_DEFFLOAT, 0);
    class_addcreator((t_newmethod)rand_weibull_new, gensym("weibull"), A_DEFFLOAT, A_DEFFLOAT, 0);
#endif
	class_addbang(rand_weibull_class, rand_weibull_bang);
#ifndef MAXLIB
	class_sethelpsymbol(rand_weibull_class, gensym("help-weibull.pd"));
    post(version);
#else
	class_sethelpsymbol(rand_weibull_class, gensym("maxlib/help-weibull.pd"));
#endif
}

--- NEW FILE: step.c ---
/* --------------------------  step  ------------------------------------------ */
/*                                                                              */
/* Step to a new value in N milliseconds (similar to line).                     */
/* Written by Olaf Matthes (olaf.matthes at gmx.de)                                */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

#include "m_pd.h"

/* -------------------------- step ------------------------------ */
static char *version = "step v0.1, written by Olaf Matthes <olaf.matthes at gmx.de>";

static t_class *step_class;

typedef struct _step
{
    t_object x_obj;
    t_clock *x_clock;
    double x_targettime;
    t_float x_targetval;
    double x_prevtime;
    t_float x_setval;
    int x_gotinlet;
    t_float x_grain;        /* time interval for output */
	t_float x_step;			/* step size for output */
	t_float x_steptime;     /* length for one step */
	t_int   x_stepcall;
    double x_1overtimediff;
    double x_in1val;
} t_step;

static void step_tick(t_step *x)
{
	t_float outvalue;
    double timenow = clock_getsystime();
    double msectogo = - clock_gettimesince(x->x_targettime);
    if (msectogo < 1E-9)
    {
    	outlet_float(x->x_obj.ob_outlet, x->x_targetval);
    }
    else
    {
		if(x->x_setval < x->x_targetval)
		{		/* count upwards */
			outvalue = x->x_setval + x->x_stepcall * x->x_step;
		}
		else
		{		/* count downwards */
			outvalue = x->x_setval - x->x_stepcall * x->x_step;
		}
    	outlet_float(x->x_obj.ob_outlet, outvalue);
    	clock_delay(x->x_clock, (x->x_steptime > msectogo ? msectogo : x->x_steptime));
    }
	x->x_stepcall++;
}

static void step_float(t_step *x, t_float f)
{
    double timenow = clock_getsystime();
    if (x->x_gotinlet && x->x_in1val > 0 && x->x_step != 0 && f != x->x_setval)
    {
    	if (timenow > x->x_targettime) x->x_setval = x->x_targetval;
    	else x->x_setval = x->x_setval + x->x_1overtimediff *
    	    (timenow - x->x_prevtime)
    	    * (x->x_targetval - x->x_setval);
    	x->x_prevtime = timenow;
    	x->x_targetval = f;		/* where to end */
		x->x_stepcall = 0;
			/* how long does it take ? */
    	x->x_targettime = clock_getsystimeafter(x->x_in1val);
		if(x->x_setval < x->x_targetval)
		{
			x->x_steptime = x->x_in1val / (int)((x->x_targetval - x->x_setval) / x->x_step);
		}
		else
		{
			x->x_steptime = x->x_in1val / (int)((x->x_setval - x->x_targetval) / x->x_step);
		}
		// post("steptime %g", x->x_steptime);
    	step_tick(x);
    	x->x_gotinlet = 0;
    	x->x_1overtimediff = 1./ (x->x_targettime - timenow);
			/* call tick function */
    	clock_delay(x->x_clock, x->x_steptime);
    
    }
    else
    {
    	clock_unset(x->x_clock);
    	x->x_targetval = x->x_setval = f;
    	outlet_float(x->x_obj.ob_outlet, f);
    }
    x->x_gotinlet = 0;
}

static void step_ft1(t_step *x, t_floatarg g)
{
    x->x_in1val = g;
    x->x_gotinlet = 1;
}

static void step_ft2(t_step *x, t_floatarg g)
{
	if (g <= 0) g = 1;
	x->x_step = g;
    x->x_gotinlet = 1;
}

static void step_stop(t_step *x)
{
    x->x_targetval = x->x_setval;
    clock_unset(x->x_clock);
}

static void step_free(t_step *x)
{
    clock_free(x->x_clock);
}

static void *step_new(t_floatarg f, t_floatarg step, t_floatarg grain)
{
    t_step *x = (t_step *)pd_new(step_class);
    x->x_targetval = x->x_setval = f;
    x->x_gotinlet = 0;
    x->x_1overtimediff = 1;
    x->x_clock = clock_new(x, (t_method)step_tick);
    x->x_targettime = x->x_prevtime = clock_getsystime();
    if (grain <= 0) grain = 20;
    x->x_grain = grain;
    if (step <= 0) step = 1;
    x->x_step = step;
    outlet_new(&x->x_obj, gensym("float"));
    inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("ft1"));
	inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("ft2"));
    return (x);
}

#ifndef MAXLIB
void step_setup(void)
{
    step_class = class_new(gensym("step"), (t_newmethod)step_new,
    	(t_method)step_free, sizeof(t_step), 0, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0);
    class_addmethod(step_class, (t_method)step_ft1, gensym("ft1"), A_FLOAT, 0);
	class_addmethod(step_class, (t_method)step_ft2, gensym("ft2"), A_FLOAT, 0);
    class_addmethod(step_class, (t_method)step_stop, gensym("stop"), 0);
    class_addfloat(step_class, (t_method)step_float);
	class_sethelpsymbol(step_class, gensym("help-step.pd"));
    post(version);
}
#else
void maxlib_step_setup(void)
{
    step_class = class_new(gensym("maxlib_step"), (t_newmethod)step_new,
    	(t_method)step_free, sizeof(t_step), 0, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0);
	class_addcreator((t_newmethod)step_new, gensym("step"), A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0);
    class_addmethod(step_class, (t_method)step_ft1, gensym("ft1"), A_FLOAT, 0);
	class_addmethod(step_class, (t_method)step_ft2, gensym("ft2"), A_FLOAT, 0);
    class_addmethod(step_class, (t_method)step_stop, gensym("stop"), 0);
    class_addfloat(step_class, (t_method)step_float);
	class_sethelpsymbol(step_class, gensym("maxlib/help-step.pd"));
}
#endif

--- NEW FILE: pulse.c ---
/* --------------------------- pong  ------------------------------------------ */
/*                                                                              */
/* A more accurate replacement for the tempo object.                            */
/* Written by Olaf Matthes <olaf.matthes at gmx.de>                                */
/* Based on pulse for Max written by James McCartney.                           */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

/* pulse.c ---- a more accurate replacement for the tempo object   */
/*				updated for CW 68K / PPC summer 96 -RD             */
/*              written for Max by James McCartney                 */

#include "m_pd.h"
#include <stdio.h>

static char *version = "pulse v0.1b, written by James McCartney for Max <james at clyde.as.utexas.edu>\n"
                       "             ported to Pd by Olaf Matthes <olaf.matthes at gmx.de>";

/* Pulse object data structure */
typedef struct pulse
{
	t_object p_ob;		
	t_clock *p_clock;
	t_outlet *p_out1;			/* outlet */
	t_outlet *p_out2;			/* outlet */
	t_int p_onoff, p_changenumer, p_changedenom;
	t_int p_tempo, p_durnumer, p_durdenom, p_maxbeats, p_count;
	double p_starttime, p_endtime, p_startremain, p_endremain, p_mspbquotient;
	t_int p_newdurnumer, p_newdurdenom;
	t_int p_mspbnumer, p_mspbdenom, p_mspbremainder;
} Pulse;

static t_class *pulse_class;

static void durcalc(Pulse *x)
{
	/* recalc duration */
	x->p_mspbnumer = 240000 * x->p_durnumer;
	if (x->p_tempo * x->p_durdenom != 0) /* bug fix by Frank Barknecht */
		x->p_mspbdenom = x->p_tempo * x->p_durdenom;
	x->p_mspbquotient = x->p_mspbnumer / x->p_mspbdenom;
	x->p_mspbremainder = x->p_mspbnumer % x->p_mspbdenom;
	if (x->p_mspbquotient < 5) {
		x->p_mspbquotient = 5;
		x->p_mspbremainder = 0;
	}
}

static void pulse_onoff(Pulse *x, t_floatarg f)
{
	int i = (int)f;
	if (i && !x->p_onoff) {
		x->p_onoff = 1;
		x->p_count = 0;
		outlet_float(x->p_out1, x->p_count);
		if (x->p_changedenom) {
			x->p_durdenom = x->p_newdurdenom;
			x->p_changedenom = 0;
		} 
		if (x->p_changenumer) {
			x->p_durnumer = x->p_newdurnumer;
			x->p_changenumer = 0;
		}
		durcalc(x);
		x->p_startremain = 0;
		x->p_endremain = x->p_mspbremainder;
		x->p_starttime = clock_getlogicaltime();
		x->p_endtime = x->p_starttime + x->p_mspbquotient;
		// clock_set(x->p_clock, x->p_endtime);
		clock_delay(x->p_clock, x->p_mspbquotient);
	} else if (i==0 && x->p_onoff) {
		x->p_onoff = 0;
		clock_unset(x->p_clock);
	}
}

static void pulse_bang(Pulse *x)
{
	if (!x->p_onoff) {
		x->p_onoff = 1;
		x->p_count = 0;
		outlet_float(x->p_out1, x->p_count);
		if (x->p_changedenom) {
			x->p_durdenom = x->p_newdurdenom;
			x->p_changedenom = 0;
		} 
		if (x->p_changenumer) {
			x->p_durnumer = x->p_newdurnumer;
			x->p_changenumer = 0;
		}
		durcalc(x);
		x->p_startremain = 0;
		x->p_endremain = x->p_mspbremainder;
		x->p_starttime = clock_getlogicaltime();
		x->p_endtime = x->p_starttime + x->p_mspbquotient;
		clock_set(x->p_clock, x->p_endtime);
	} else {
		x->p_onoff = 0;
		clock_unset(x->p_clock);
	}
}

/* clock tick routine */
static void pulse_tick(Pulse *x)
{
	x->p_count ++;
	if ((x->p_maxbeats > 0) && (x->p_count >= x->p_maxbeats)) {	/* turn off time */
		x->p_onoff = 0;
		outlet_bang(x->p_out2);
	} else {
		outlet_float(x->p_out1, x->p_count);
		x->p_startremain = x->p_endremain;	/* save in case we have to re do it */
		if (x->p_changenumer || x->p_changedenom) {		/* duration changed */
			if (x->p_changedenom) {
				/* this statement may cause a slight drift of (1/(tempo*denom) msecs) */
				x->p_startremain = (x->p_startremain * x->p_newdurdenom + (x->p_durdenom>>1))
					/x->p_durdenom;
				x->p_durdenom = x->p_newdurdenom;
				x->p_changedenom = 0;
			} 
			if (x->p_changenumer) {
				x->p_durnumer = x->p_newdurnumer;
				x->p_changenumer = 0;
			}
			durcalc(x);
		}
		x->p_endremain = x->p_startremain + x->p_mspbremainder;
		x->p_starttime = x->p_endtime;
		x->p_endtime = x->p_starttime + x->p_mspbquotient;
		if (x->p_endremain >= x->p_mspbdenom) {		
			x->p_endremain -= x->p_mspbdenom;
			x->p_endtime ++;
		}
		// clock_set(x->p_clock, x->p_endtime);
		clock_delay(x->p_clock, x->p_mspbquotient); 
	}
}

/* deal with tempo change */
static void pulse_tempo(Pulse *x, t_floatarg t)
{
	double time, msecdur, tickdur, fracremain;
	t_int fracnumer, fracquotient, oldtempo;
	oldtempo = x->p_tempo;
	x->p_tempo = (t<5) ? 5 : ((t>500) ? 500 : t);
	if (x->p_onoff) {
		/* calculate fraction of the beat we have done */
		time = clock_getlogicaltime();
		if (time != x->p_endtime) {	
			/* if pulse_tempo is called as a result of a call from pulse_tick 
				(call chain from outlet_float())
				then this stuff doesn't need to be done (time will == x->p_endtime) 
			*/
			msecdur = time - x->p_starttime;
			tickdur = msecdur * x->p_mspbdenom - x->p_startremain;
			fracnumer = (t_int)(x->p_mspbnumer - tickdur);
		
			durcalc(x);
			
			/* calculate end time */
			fracquotient = fracnumer / x->p_mspbdenom;
			fracremain = fracnumer % x->p_mspbdenom;
	
			x->p_endtime = time + fracquotient;
			x->p_endremain = fracremain;
			
			/* recalculate starttime so future tempo changes work */
			x->p_starttime = x->p_endtime - x->p_mspbquotient;
			x->p_startremain = x->p_mspbdenom - x->p_mspbremainder + fracremain;
			if (x->p_mspbremainder > fracremain) {
				x->p_startremain = x->p_mspbdenom - x->p_mspbremainder + fracremain;
				x->p_starttime --;
			} else {
				x->p_startremain = fracremain - x->p_mspbremainder;
			}
			clock_unset(x->p_clock);
			clock_set(x->p_clock, x->p_endtime);
			// clock_delay(x->p_clock, fracquotient);
		}
	}
}

static void pulse_numer(Pulse *x, t_floatarg n)
{
	int i = (t_int)n;
	if(i >= 0)
	{
		if (x->p_onoff) {
			if (x->p_durnumer != i) {
				x->p_changenumer = 1;
				x->p_newdurnumer = i;
			}
		} else {
			x->p_durnumer = i;
		}
	}
}

static void pulse_denom(Pulse *x, t_floatarg n)
{
	int i = (t_int)n;
	if(i >= 0)
	{
		if (x->p_onoff) {
			if (x->p_durdenom != i) {
				x->p_changedenom = 1;
				x->p_newdurdenom = i;
			}
		} else {
			x->p_durdenom = i;
		}
	}
}

static void pulse_beat(Pulse *x, t_floatarg n)
{
	int i = (t_int)n;
	if(i >= 0)
	{
		x->p_maxbeats = i;
	}
}


static void pulse_free(Pulse *x)
{
	clock_free(x->p_clock);
}


/* function run to create a new instance of the Pulse class */
static void *pulse_new(t_floatarg t, t_floatarg n, t_floatarg d, t_floatarg b)
{
	Pulse *x;
	
	x = (Pulse *)pd_new(pulse_class);	/* allocates memory and sticks in an inlet */
		
	inlet_new(&x->p_ob, &x->p_ob.ob_pd, gensym("float"), gensym("tempo"));
	inlet_new(&x->p_ob, &x->p_ob.ob_pd, gensym("float"), gensym("numer"));
	inlet_new(&x->p_ob, &x->p_ob.ob_pd, gensym("float"), gensym("denom"));
	inlet_new(&x->p_ob, &x->p_ob.ob_pd, gensym("float"), gensym("beat"));
	x->p_out1 = outlet_new(&x->p_ob, gensym("float"));
	x->p_out2 = outlet_new(&x->p_ob, gensym("float"));
	x->p_clock = clock_new(x, (t_method)pulse_tick);
	x->p_tempo = (t==0) ? 120 : ((t<5) ? 5 : ((t>500) ? 500 : t));
	x->p_durnumer = (n<=0) ? 1 : n;
	x->p_durdenom = (d<=0) ? 4 : d;
	x->p_maxbeats = (b<=0) ? 0 : b;
	x->p_changenumer = 0;
	x->p_changedenom = 0;
	x->p_onoff = 0;

	return (x);					/* always return a copy of the created object */
}

#ifndef MAXLIB
void pulse_setup(void)
{
    pulse_class = class_new(gensym("pulse"), (t_newmethod)pulse_new,
    	(t_method)pulse_free, sizeof(Pulse), 0, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0);
    class_addmethod(pulse_class, (t_method)pulse_beat, gensym("beat"), A_FLOAT, 0);
	class_addmethod(pulse_class, (t_method)pulse_denom, gensym("denom"), A_FLOAT, 0);
    class_addmethod(pulse_class, (t_method)pulse_numer, gensym("numer"), A_FLOAT, 0);
    class_addmethod(pulse_class, (t_method)pulse_tempo, gensym("tempo"), A_FLOAT, 0);
    class_addfloat(pulse_class, pulse_onoff);
    class_addbang(pulse_class, pulse_bang);
    class_sethelpsymbol(pulse_class, gensym("help-pulse.pd"));
    post(version);
}
#else
void maxlib_pulse_setup(void)
{
    pulse_class = class_new(gensym("maxlib_pulse"), (t_newmethod)pulse_new,
    	(t_method)pulse_free, sizeof(Pulse), 0, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0);
	class_addcreator((t_newmethod)pulse_new, gensym("pulse"), A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0);
    class_addmethod(pulse_class, (t_method)pulse_beat, gensym("beat"), A_FLOAT, 0);
	class_addmethod(pulse_class, (t_method)pulse_denom, gensym("denom"), A_FLOAT, 0);
    class_addmethod(pulse_class, (t_method)pulse_numer, gensym("numer"), A_FLOAT, 0);
    class_addmethod(pulse_class, (t_method)pulse_tempo, gensym("tempo"), A_FLOAT, 0);
    class_addfloat(pulse_class, pulse_onoff);
    class_addbang(pulse_class, pulse_bang);
    class_sethelpsymbol(pulse_class, gensym("maxlib/help-pulse.pd"));
}
#endif

--- NEW FILE: chord.c ---
/* ------------------------- chord   ------------------------------------------ */
/*                                                                              */
/* Tries to detect a chord (or any harmonic relations) of incoming notes.       */
/* Written by Olaf Matthes (olaf.matthes at gmx.de)                                */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
[...1777 lines suppressed...]
{
    chord_class = class_new(gensym("chord"), (t_newmethod)chord_new,
    	0, sizeof(t_chord), 0, A_DEFFLOAT, 0);
#else
void maxlib_chord_setup(void)
{
    chord_class = class_new(gensym("maxlib_chord"), (t_newmethod)chord_new,
    	0, sizeof(t_chord), 0, A_DEFFLOAT, 0);
#endif
    class_addfloat(chord_class, chord_float);
    class_addmethod(chord_class, (t_method)chord_ft1, gensym("ft1"), A_FLOAT, 0);
#ifndef MAXLIB
    class_sethelpsymbol(chord_class, gensym("help-chord.pd"));
    post(version);
#else
	class_addcreator((t_newmethod)chord_new, gensym("chord"), A_DEFFLOAT, 0);
    class_sethelpsymbol(chord_class, gensym("maxlib/help-chord.pd"));
#endif
}


--- NEW FILE: rhythm.c ---
/* --------------------------- rhythm  ---------------------------------------- */
/*                                                                              */
/* Detect the beats per minute of a MIDI stream.                                */
/* Written by Olaf Matthes (olaf.matthes at gmx.de)                                */
/* Based on code written by Robert Rowe.                                        */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

#include "m_pd.h"
#include <stdio.h>
#include <math.h>
#ifdef UNIX
#include <stdlib.h>
#endif

#define ALPHA 10
#define ADAPT_ARRAY_SIZE  1000

#ifndef M_PI
#define M_PI 3.14159265358979
#endif
#ifndef TWO_PI
#define TWO_PI 2.0*M_PI
#endif

static char *version = "rhythm v0.1, written by Olaf Matthes <olaf.matthes at gmx.de>";

typedef struct rhythm
{
  t_object x_ob;
  t_clock  *x_tick;
  t_outlet *x_out_bpm;              /* beats per minute */
  t_outlet *x_out_period;           /* beats in milliseconds */
  t_outlet *x_out_pulse;
  t_int    x_print;                 /* switch printing to console window on / off */
  t_int    x_ticking;               /* indicates if clock is ticking or not */

  t_int    x_model;					/* algorhythm to use: 0 - Large & Kolen, 1 - Toiviainen */
  t_float  x_long_term[ADAPT_ARRAY_SIZE];
  t_float  x_short_term[ADAPT_ARRAY_SIZE];
  t_float  x_phi_at_pulse;			/* phase at latest pulse */
  t_float  x_phiVel_at_pulse;		/* phase velocity */

  t_float  x_adapt;
  t_float  x_errFunc;				/* error function */
  t_float  x_etaLong;				/* strength of long-term adaptation */
  t_float  x_etaShort;				/* strength of short-term adaptation */
  t_float  x_gamma;					/* gain parameter */
  double   x_lastIoi;				/* last inter-onset interval */
  double   x_lastPulseTime;			/* time of last pulse */
  t_float  x_output;				/* current output value of the oscillator */
  t_float  x_phi;					/* phase */
  double   x_expected;				/* estimated time of arrival */
  t_float  x_period;
  t_float  x_periodStrength;
  t_float  x_phaseStrength;
  double   x_startTime;

  t_int    x_pitch;
  t_int    x_velo;
	/* helpers needed to do the time calculations */
  double   x_last_input;
} t_rhythm;

/* --------------- rhythm  stuff ------------------------------------------------ */
	/* bang at the rhythm's pulse */
static void rhythm_tick(t_rhythm *x)
{
	outlet_bang(x->x_out_pulse);
	clock_delay(x->x_tick, x->x_period);
}

static t_float rhythm_get_adapt_long(t_rhythm *x, t_float arg)
{
	int address;
	if (arg > 1.0)
		address = ADAPT_ARRAY_SIZE - 1;
	else if (arg < -1.0)
		address = ADAPT_ARRAY_SIZE - 1;
	else
		address = abs((int)(arg*1000.0));
	return x->x_long_term[address];
}

static t_float rhythm_get_adapt_short(t_rhythm *x, t_float arg)
{
	int address;
	if (arg > 1.0)
		address = ADAPT_ARRAY_SIZE - 1;
	else if (arg < -1.0)
		address = ADAPT_ARRAY_SIZE - 1;
	else
		address = abs((int)(arg*1000.0));
	return x->x_short_term[address];
}


	/* Large & Kolen adaptation model */
static void rhythm_large(t_rhythm *x, t_int pulse, double time)
{
	while (time > (x->x_expected+(x->x_period/2)))		// move the expectation point
		x->x_expected += x->x_period;						// to be within one period of onset
	x->x_phi = (t_float)(time - x->x_expected) / x->x_period;		// calculate phi

	if (pulse) {								// if this was an onset
		x->x_adapt     = x->x_gamma * (cos(TWO_PI*x->x_phi)-1.0);
		x->x_adapt     = 1.0 / cosh(x->x_adapt);
		x->x_adapt    *= x->x_adapt;
		x->x_adapt    *= sin(TWO_PI*x->x_phi);
		x->x_adapt    *= (x->x_period / TWO_PI);
		x->x_period   += (x->x_periodStrength*x->x_adapt);		// update period
		x->x_expected += (x->x_phaseStrength *x->x_adapt);		// and phase
		x->x_phi       = (t_float)(time - x->x_expected) / x->x_period;
	}

	x->x_output = 1+tanh(x->x_gamma*(cos(TWO_PI*x->x_phi)-1.0)); // oscillator output
}
	/* Toiviainen adaptation model */
static void rhythm_toiviainen(t_rhythm *x, t_int pulse, double time)
{
	t_float deltaTime, varPhi, adaptLong, adaptShort;

	/* if just starting, initialize phi */
	if(x->x_lastPulseTime < 0)
	{
		x->x_phi = x->x_phi_at_pulse + x->x_phiVel_at_pulse * ((t_float)(time-x->x_startTime) / 1000.0);
	}
	else
	{
		deltaTime  = time - x->x_lastPulseTime;
		varPhi     = (deltaTime/1000.0) * x->x_phiVel_at_pulse;
		adaptLong  = rhythm_get_adapt_long(x, varPhi);	// get long adaptation from table
		adaptShort = rhythm_get_adapt_short(x, varPhi);	// get short adaptation from table
		x->x_phi = x->x_phi_at_pulse + varPhi + x->x_errFunc * (x->x_etaLong*adaptLong + x->x_etaShort*adaptShort);
		if (pulse)									// change tempo if on pulse
			x->x_phiVel_at_pulse = x->x_phiVel_at_pulse * (1 + x->x_etaLong * x->x_errFunc * adaptShort);
	}

	if (pulse) {
		x->x_output        = 1+tanh(x->x_gamma*(cos(TWO_PI*x->x_phi)-1.0));
		x->x_errFunc       = x->x_output * (x->x_output - 2.0) * sin(TWO_PI * x->x_phi);
		x->x_phi_at_pulse  = x->x_phi;
	}

	x->x_period = 1000.0 / x->x_phiVel_at_pulse;		// update period
}

static void rhythm_move(t_rhythm *x, t_int pulse, double time)
{
	switch (x->x_model)	/* choose adaptation model */
	{
		case 0:		
			rhythm_large(x, pulse, time);
			break;

		case 1:
			rhythm_toiviainen(x, pulse, time);
			break;
	}
	
	if(x->x_ticking == 0)
	{
		x->x_ticking = 1;	/* prevent us from further calls */
		clock_delay(x->x_tick, 0);	/* start pulse bangs */
	}
}

	/* main processing function */
static void rhythm_float(t_rhythm *x, t_floatarg f)
{
	t_int velo = x->x_velo;
	double time = clock_gettimesince(x->x_last_input);
	x->x_pitch = (t_int)f;

	if(velo != 0)	/* note-on received */
	{
		if (x->x_startTime == 0) {
			x->x_startTime = time;
			return;
		}
		
		if (x->x_period < 2.0) {
			x->x_period = (t_float)(time - x->x_startTime);
			x->x_phiVel_at_pulse = 1000.0 / x->x_period;
		}

		rhythm_move(x, 1, time);

		if (x->x_lastPulseTime >= 0)
		{
			x->x_lastIoi = time - x->x_lastPulseTime;
		}
		x->x_lastPulseTime = time; 
		x->x_last_input = clock_getlogicaltime();

		outlet_float(x->x_out_period, x->x_period);
		outlet_float(x->x_out_bpm, 60000.0/x->x_period);
	}
	return;
}
	/* get velocity */
static void rhythm_ft1(t_rhythm *x, t_floatarg f)
{
	x->x_velo = (t_int)f;
}

	/* toggle printing on/off (not used right now!) */
static void rhythm_print(t_rhythm *x)
{
	if(x->x_print)x->x_print = 0;
	else x->x_print = 1;
}
	/* initialise array for Toiviainen adaptation model */
static void rhythm_calculate_adaptations(t_rhythm *x)
{
	int i;
	t_float f;

	for(i = 0; i < ADAPT_ARRAY_SIZE; i++)
	{
		f = (t_float)i/(t_float)ADAPT_ARRAY_SIZE;
		x->x_long_term[i] = f+(ALPHA*f*f/2.0+2.0*f+3.0/ALPHA)*exp(-ALPHA*f)-3.0/ALPHA;
		x->x_short_term[i] = 1.0-(ALPHA*ALPHA*f*f/2.0+ALPHA*f+1.0)*exp(-ALPHA*f);
	}
}

static void rhythm_reset(t_rhythm *x)
{
	if(x->x_ticking)clock_unset(x->x_tick);
	x->x_ticking = 0;

	x->x_gamma          = 1.0;	/* default value for gain parameter */
	x->x_phi            = 0.0;
	x->x_output         = 1+tanh(x->x_gamma*(cos(TWO_PI*x->x_phi)-1.0));
	x->x_expected       = 0;
	x->x_lastIoi		= 0;
	x->x_lastPulseTime  = -1;
	x->x_period         = 1.0;
	x->x_periodStrength	= 0.2;
	x->x_phaseStrength	= 0.2;

	x->x_errFunc        = 0.0;
	x->x_etaLong		= 0.2;
	x->x_etaShort		= 0.2;
	x->x_phi_at_pulse   = 0.0;
	x->x_phiVel_at_pulse = 0.9;
	x->x_startTime		= 0;

	rhythm_calculate_adaptations(x);
}

static void rhythm_model(t_rhythm *x, t_floatarg f)
{
	if(f == 1)
	{
		x->x_model = 1;		/* Toiviainen model */
		rhythm_reset(x);
		post("rhythm: using \"Toiviainen\" adaptation model");
	}
	else
	{
		x->x_model = 0;		/* Large and Kolen model */
		rhythm_reset(x);
		post("rhythm: using \"Large and Kolen\" adaptation model");
	}
}

static t_class *rhythm_class;

static void rhythm_free(t_rhythm *x)
{
	clock_free(x->x_tick);
}

static void *rhythm_new(t_floatarg f)
{
    t_rhythm *x = (t_rhythm *)pd_new(rhythm_class);
    inlet_new(&x->x_ob, &x->x_ob.ob_pd, gensym("float"), gensym("ft1"));
	x->x_out_bpm = outlet_new(&x->x_ob, gensym("float"));
	x->x_out_period = outlet_new(&x->x_ob, gensym("float"));
	x->x_out_pulse = outlet_new(&x->x_ob, gensym("bang"));
	x->x_tick = clock_new(x, (t_method)rhythm_tick);

	rhythm_reset(x);

	if(f == 1)
	{
		x->x_model = 1;		/* Toiviainen model */
		post("rhythm: using \"Toiviainen\" adaptation model");
	}
	else
	{
		x->x_model = 0;		/* Large and Kolen model */
		post("rhythm: using \"Large and Kolen\" adaptation model");
	}

    return (void *)x;
}

#ifndef MAXLIB
void rhythm_setup(void)
{
    rhythm_class = class_new(gensym("rhythm"), (t_newmethod)rhythm_new,
    	(t_method)rhythm_free, sizeof(t_rhythm), 0, A_DEFFLOAT, 0);
    class_addfloat(rhythm_class, rhythm_float);
	class_addmethod(rhythm_class, (t_method)rhythm_ft1, gensym("ft1"), A_FLOAT, 0);
	class_addmethod(rhythm_class, (t_method)rhythm_model, gensym("model"), A_FLOAT, 0);
	class_addmethod(rhythm_class, (t_method)rhythm_reset, gensym("reset"), 0);
	class_addmethod(rhythm_class, (t_method)rhythm_print, gensym("print"), 0);
    class_sethelpsymbol(rhythm_class, gensym("help-rhythm.pd"));
    post(version);
}
#else
void maxlib_rhythm_setup(void)
{
    rhythm_class = class_new(gensym("maxlib_rhythm"), (t_newmethod)rhythm_new,
    	(t_method)rhythm_free, sizeof(t_rhythm), 0, A_DEFFLOAT, 0);
	class_addcreator((t_newmethod)rhythm_new, gensym("rhythm"), A_DEFFLOAT, 0);
    class_addfloat(rhythm_class, rhythm_float);
	class_addmethod(rhythm_class, (t_method)rhythm_ft1, gensym("ft1"), A_FLOAT, 0);
	class_addmethod(rhythm_class, (t_method)rhythm_model, gensym("model"), A_FLOAT, 0);
	class_addmethod(rhythm_class, (t_method)rhythm_reset, gensym("reset"), 0);
	class_addmethod(rhythm_class, (t_method)rhythm_print, gensym("print"), 0);
    class_sethelpsymbol(rhythm_class, gensym("maxlib/help-rhythm.pd"));
}
#endif

--- NEW FILE: beta.c ---
/* ---------------------------- rand_beta ------------------------------------- */
/*                                                                              */
/* rand_beta generates a beta distributed random variable.                      */
/* Written by Olaf Matthes (olaf.matthes at gmx.de)                                */
/* Based on code found in Dodge/Jerse "Computer Music"                          */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

#include "m_pd.h"
#include <stdlib.h>
#include <time.h>
#include <math.h>

#define fran()         (t_float)rand()/(t_float)RAND_MAX
#ifndef M_PI
#define M_PI           3.1415927
#endif

static char *version = "beta v0.1, generates a beta distributed random variable\n"
                       "           written by Olaf Matthes <olaf.matthes at gmx.de>";

/* -------------------------- rand_beta ------------------------------ */

static t_class *rand_beta_class;

typedef struct _rand_beta
{
    t_object x_obj;
	t_float  x_a;
	t_float  x_b;
} t_rand_beta;

static void *rand_beta_new(t_floatarg a, t_floatarg b)
{
    t_rand_beta *x = (t_rand_beta *)pd_new(rand_beta_class);
    srand( (unsigned)time( NULL ) );
    floatinlet_new(&x->x_obj, &x->x_a);
    floatinlet_new(&x->x_obj, &x->x_b);
    outlet_new(&x->x_obj, &s_float);
	x->x_a = a;
	x->x_b = b;
    return (x);
}

static void rand_beta_bang(t_rand_beta *x)
{
	t_float u1, u2, y01, y2, sum, a, b, ainv, binv;
	a = (x->x_a <= 0 ? 0.0001 : x->x_a);
	b = (x->x_b <= 0 ? 0.0001 : x->x_b);
	ainv = 1/a;
	binv = 1/b;
	do
	{
		do
		{
			u1 = fran();
		}
		while(u1 == 0);
		do
		{
			u2 = fran();
		}
		while(u2 == 0);
		y01 = pow(u1, ainv);
		y2 = pow(u2, binv);
		sum = y01 + y2;
	}
	while(sum > 1);
    outlet_float(x->x_obj.ob_outlet, y01/sum);
}

#ifndef MAXLIB
void beta_setup(void)
{
    rand_beta_class = class_new(gensym("beta"), (t_newmethod)rand_beta_new, 0,
    	sizeof(t_rand_beta), 0, A_DEFFLOAT, A_DEFFLOAT, 0);
    class_addbang(rand_beta_class, rand_beta_bang);
	class_sethelpsymbol(rand_beta_class, gensym("help-beta.pd"));
    post(version);
}
#else
void maxlib_beta_setup(void)
{
    rand_beta_class = class_new(gensym("maxlib_beta"), (t_newmethod)rand_beta_new, 0,
    	sizeof(t_rand_beta), 0, A_DEFFLOAT, A_DEFFLOAT, 0);
    class_addbang(rand_beta_class, rand_beta_bang);
	class_addcreator((t_newmethod)rand_beta_new, gensym("beta"), A_DEFFLOAT, A_DEFFLOAT, 0);
	class_sethelpsymbol(rand_beta_class, gensym("maxlib/help-beta.pd"));
}
#endif

--- NEW FILE: gestalt.c ---
/* ------------------------- gestalt   ---------------------------------------- */
/*                                                                              */
/* Find the 'gestalt' of the MIDI input.                                        */
/* Written by Olaf Matthes <olaf.matthes at gmx.de>                                */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

#include "m_pd.h"
#include <math.h>
#include <stdio.h>
#ifdef UNIX
#include <stdlib.h>
#endif

static char *version = "gestalt v0.1, written by Olaf Matthes <olaf.matthes at gmx.de>";
 
typedef struct gestalt
{
  t_object x_ob;
  t_inlet  *x_invelocity;             /* inlet for velocity */
  t_outlet *x_outgestalt;             /* calculated 'gestalt'-value */

  t_float  x_lastpitch;
  t_float  x_velocity;

  t_float  x_reftime;

  double   x_lastontime;

} t_gestalt;

static void gestalt_ft1(t_gestalt *x, t_floatarg f)
{
	x->x_velocity = f;
}

static void gestalt_ft2(t_gestalt *x, t_floatarg f)
{
	if(f > 0.0) x->x_reftime = f;
}

static void gestalt_float(t_gestalt *x, t_floatarg f)
{

	int interval, pitch, gestalt;
	double ontime = clock_getlogicaltime();
	
	if(x->x_velocity)	/* only process note-ons */
	{

		pitch = (t_int)f;
		if(pitch < 1) pitch = 0;
		if(pitch > 127) pitch = 127;

		interval = abs(pitch - x->x_lastpitch);
		gestalt = (clock_gettimesince(x->x_lastontime)/x->x_reftime) + interval;

		x->x_lastpitch = pitch;
		x->x_lastontime = ontime;

			/* output values from right to left */
		outlet_float(x->x_outgestalt, gestalt);
	}
}

static t_class *gestalt_class;

static void *gestalt_new(t_floatarg f)
{
    t_gestalt *x = (t_gestalt *)pd_new(gestalt_class);
    inlet_new(&x->x_ob, &x->x_ob.ob_pd, gensym("float"), gensym("ft1"));
	inlet_new(&x->x_ob, &x->x_ob.ob_pd, gensym("float"), gensym("ft2"));
	x->x_outgestalt = outlet_new(&x->x_ob, gensym("float"));

	x->x_lastontime = clock_getlogicaltime();

	x->x_reftime = f;
	if(x->x_reftime < 1) x->x_reftime = 1;

    return (void *)x;
}

#ifndef MAXLIB
void gestalt_setup(void)
{
    gestalt_class = class_new(gensym("gestalt"), (t_newmethod)gestalt_new,
    	0, sizeof(t_gestalt), 0, A_DEFFLOAT, 0);
    class_addfloat(gestalt_class, gestalt_float);
	class_addmethod(gestalt_class, (t_method)gestalt_ft1, gensym("ft1"), A_FLOAT, 0);
	class_addmethod(gestalt_class, (t_method)gestalt_ft2, gensym("ft2"), A_FLOAT, 0);
    class_sethelpsymbol(gestalt_class, gensym("help-gestalt.pd"));
    post(version);
}
#else
void maxlib_gestalt_setup(void)
{
    gestalt_class = class_new(gensym("maxlib_gestalt"), (t_newmethod)gestalt_new,
    	0, sizeof(t_gestalt), 0, A_DEFFLOAT, 0);
	class_addcreator((t_newmethod)gestalt_new, gensym("gestalt"), A_DEFFLOAT, 0);
    class_addfloat(gestalt_class, gestalt_float);
	class_addmethod(gestalt_class, (t_method)gestalt_ft1, gensym("ft1"), A_FLOAT, 0);
	class_addmethod(gestalt_class, (t_method)gestalt_ft2, gensym("ft2"), A_FLOAT, 0);
    class_sethelpsymbol(gestalt_class, gensym("maxlib/help-gestalt.pd"));
}
#endif


--- NEW FILE: pong.c ---
/* --------------------------- pong  ------------------------------------------ */
/*                                                                              */
/* A virtual bouncing ball.                                                     */
/* Written by Olaf Matthes <olaf.matthes at gmx.de>                                */
/* Based on pong (for Max) version 1.5 written by Richard Dudas.                */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

#include "m_pd.h"

static char *version = "pong v0.1, ported by Olaf Matthes <olaf.matthes at gmx.de>\n"
                       "           written for Max by Richard Dudas";

typedef struct pong
{
	t_object x_obj;		
	t_outlet *p_bounceout;
	t_outlet *p_handout;
	t_outlet *p_velout;
	t_outlet *p_heightout;
	t_clock  *p_klok;

	t_int    p_ms;  			// ms count
	t_float  p_time;			// current time div by warp
	t_float  p_timegrain;		// timegrain in seconds
	t_float  p_timegrainin;		// timegrain in ms
	t_float  p_warp;			// timewarp in ms
	
	t_float  p_dinit;			// init distance
	t_float  p_vinit;			// init velocity
	t_float  p_ainit;			// base acceleration def -100
	t_float  p_damping;			// realtime multiplicative damping
	t_float  p_dhand;			// virtual hand distance
	t_float  p_force;			// force of hand 1.0 = no force
 
	t_float  p_accel;			// current accel value
	t_float  p_vi;				// current velocity
	t_float  p_di;				// current distance
	t_float  p_dt;				// distance out
	t_float  p_dtprev;			// previous distance out for accel computation
	t_float  p_vt;				// velocity out
	t_int    p_prevchg;			// for logical transition
} t_pong;

/* ---------------------------------------------------------- */
/* ---- this stuff is mainly for the timer, on off etc... --- */
/* ---------------------------------------------------------- */

static void pong_reset(t_pong *x)
{
	x->p_di = x->p_dinit;
	x->p_dt = x->p_dinit;			// added
	x->p_dtprev = x->p_dinit;		// added
	x->p_vi = x->p_vinit;
	x->p_vt = x->p_vinit;			// added
	x->p_ms = 0;
	x->p_time = 0.;
	x->p_ainit = -100.;				// added, but currently disabled
	x->p_accel = -100.;				// reactivated (?)
	x->p_damping = 1.; 				// i.e. no initial damping
	x->p_prevchg = 0;				// added
	
/*	x->p_ms = 0;
	x->p_time = 0.;
	x->p_timegrain = 0.05;  // if ms grain = 50
	x->p_timegrainin = 50;
	
	x->p_vinit = 0.;
	x->p_dinit = 100.;	
	x->p_ainit = -100.;
	x->p_damping = 1.; 	// i.e. no initial damping 
	x->p_dhand = 100.;
	x->p_force = 1.;  // i.e. hand does nothing initially
	
	x->p_accel = -100.;
	x->p_vi = 0.;
	x->p_di = 100.;
	
	x->p_dt = 100.;			// changed from 0 to 100 
	x->p_dtprev = 100.;		// changed from 0 to 100 
	x->p_vt = 0.;
	x->p_prevchg = 0;
*/
}

/* ---------------------------------------------------------- */

static void pong_timein(t_pong *x, t_floatarg n)
{
	int thischg;
	
	x->p_time = n / x->p_warp;
	
	x->p_dt = ((x->p_accel * (x->p_time*x->p_time)) + (x->p_time * x->p_vi) + x->p_di);
	x->p_vt = ((x->p_dt - x->p_dtprev) / x->p_timegrain);
	
	if (x->p_dt < 0.)
	{
		x->p_dt *= -1.;
		
		x->p_di = 0.;
		x->p_vi = x->p_vt * (-1. * x->p_damping);  // -1 will eventually be a damping variable
		//post("vel at bounce %f", x->p_vi); 
		outlet_bang(x->p_bounceout);
		x->p_ms = 0;
		//x->p_dtprev= 0.;
	}
	//else
		x->p_dtprev = x->p_dt;
	
	/* ---------------------------------- virtual hand below ------------ */
	
	if (x->p_dt > x->p_dhand)  // presuming the hand is initially equal to the dinit
		thischg = 1;
	else
		thischg = 0;
		
	if (thischg != x->p_prevchg)
	{
		x->p_ms = 0;
		x->p_vi = x->p_vt;
		x->p_di = x->p_dhand;
		
		if (thischg == 0)
		{
			x->p_accel = -100.;   					// x->p_ainit in lieu of -100.
			outlet_float(x->p_handout, 0);
		}
		else
		{
			x->p_accel = (x->p_force * -100.);     // x->p_ainit in lieu of -100.
			outlet_float(x->p_handout, 1);
		}
	}
	
	x->p_prevchg = thischg;
	outlet_float(x->p_velout, x->p_vt);
	outlet_float(x->p_heightout, x->p_dt);
}

static void pong_onoff(t_pong *x, t_floatarg n)
{
	if (n != 0)
		clock_delay(x->p_klok, 0);
	else
		clock_unset(x->p_klok);
}

/* ---------------------------------------------------------- */

static void pong_bang(t_pong *x)
{
	x->p_ms = 0;
	clock_delay(x->p_klok, 0);
}

static void pong_stop(t_pong *x)
{
	clock_unset(x->p_klok);
}

/* ---------------------------------------------------------- */

static void pong_tick(t_pong *x)
{
	clock_delay(x->p_klok, (t_int)x->p_timegrainin);
	pong_timein(x, x->p_ms);
	//outlet_float(x->p_heightout, (float)x->p_ms);
	x->p_ms = x->p_ms + x->p_timegrainin;
}

/* ---------------------------------------------------------- */

static void pong_tgrain(t_pong *x, t_floatarg n)
{
	x->p_timegrain = n / x->p_warp;
	x->p_timegrainin = n;
	post("timegrain %f", x->p_timegrain);
}

/* ---------------------------------------------------------- */

static void pong_warpin(t_pong *x, t_floatarg n)
{
	x->p_warp = n;
	x->p_timegrain = x->p_timegrainin / x->p_warp;
	post("timewarp %f ms = one sec", x->p_warp);
}

/* ---------------------------------------------------------- */
/* ----- these are to receive and store the init values ----- */
/* ---------------------------------------------------------- */

static void pong_initdist(t_pong *x, t_floatarg n)
{
	x->p_dinit = n;
}

static void pong_initvel(t_pong *x, t_floatarg n)
{
	x->p_vinit = n;
}

static void pong_damp(t_pong *x, t_floatarg n)
{
	x->p_damping = n;
}

/* ---------------------------------------------------------- */

static void pong_baseacc(t_pong *x, t_floatarg n)
{
	//post ("baseaccel currently disabled", 0);
	 x->p_ainit = n; 
	 x->p_accel = x->p_ainit; 
}

/* ---------------------------------------------------------- */

static void pong_hand(t_pong *x, t_floatarg n)
{
	x->p_dhand = n;
}

static void pong_force(t_pong *x, t_floatarg n)
{
	x->p_force = n;
}

/* ---------------------------------------------------------- */


static t_class *pong_class;

static void *pong_new(t_floatarg n)
{
    t_pong *x = (t_pong *)pd_new(pong_class);

	x->p_klok = clock_new(x, (t_method)pong_tick);
	
	inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("dist"));	// distance
	inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("velo"));	// velocity
	inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("damp"));	// damping
	inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("force"));	// hand force 1.0 = no force
	inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("hand"));	// virtual hand (distance)

	
	if (n > 0)
		x->p_warp = n;
	else
		x->p_warp = 1000.;
	
	x->p_ms = 0;
	x->p_time = 0.;
	x->p_timegrain = 0.05;  // if ms grain = 50
	x->p_timegrainin = 50.0;
	
	x->p_vinit = 0.;
	x->p_dinit = 100.;	
	x->p_ainit = -100.;
	x->p_damping = 1.; 	// i.e. no initial damping
	x->p_dhand = 100.;
	x->p_force = 1.;  	// i.e. hand does nothing initially
	
	x->p_accel = -100.;
	x->p_vi = 0.;
	x->p_di = 100.;

	x->p_dt = 100.;			// changed from 0 to 100
	x->p_dtprev = 100.;		// changed from 0 to 100
	x->p_vt = 0.;
	x->p_prevchg = 0;
	
	x->p_bounceout = outlet_new(&x->x_obj, gensym("bang"));
	x->p_handout = outlet_new(&x->x_obj, gensym("float"));
	x->p_velout = outlet_new(&x->x_obj, gensym("float"));
	x->p_heightout = outlet_new(&x->x_obj, gensym("float"));

	return (x);
}

#ifndef MAXLIB
void pong_setup(void)
{
    pong_class = class_new(gensym("pong"), (t_newmethod)pong_new,
    	0, sizeof(t_pong), 0, A_DEFFLOAT, 0);
#else
void maxlib_pong_setup(void)
{
    pong_class = class_new(gensym("maxlib_pong"), (t_newmethod)pong_new,
    	0, sizeof(t_pong), 0, A_DEFFLOAT, 0);
	class_addcreator((t_newmethod)pong_new, gensym("pong"), A_DEFFLOAT, 0);
#endif
		/* method handlers for inlets */
	class_addmethod(pong_class, (t_method)pong_initdist, gensym("dist"), A_FLOAT, 0);
	class_addmethod(pong_class, (t_method)pong_initvel, gensym("velo"), A_FLOAT, 0);
	class_addmethod(pong_class, (t_method)pong_damp, gensym("damp"), A_FLOAT, 0);
	class_addmethod(pong_class, (t_method)pong_force, gensym("force"), A_FLOAT, 0);
	class_addmethod(pong_class, (t_method)pong_hand, gensym("hand"), A_FLOAT, 0);
		/* method handlers for other messages to first inlet */
	class_addmethod(pong_class, (t_method)pong_tgrain, gensym("timegrain"), A_FLOAT, 0);
	class_addmethod(pong_class, (t_method)pong_warpin, gensym("timewarp"), A_FLOAT, 0);
	class_addmethod(pong_class, (t_method)pong_baseacc, gensym("baseaccel"), A_FLOAT, 0);
	class_addmethod(pong_class, (t_method)pong_reset, gensym("reset"), 0);
	class_addmethod(pong_class, (t_method)pong_stop, gensym("stop"), 0);

    class_addfloat(pong_class, pong_onoff);
	class_addbang(pong_class, pong_bang);
#ifndef MAXLIB
    class_sethelpsymbol(pong_class, gensym("help-pong.pd"));
    post(version);
#else
    class_sethelpsymbol(pong_class, gensym("maxlib/help-pong.pd"));
#endif
}

--- NEW FILE: urn.c ---
/* -------------------------------  urn  -------------------------------------- */
/*                                                                              */
/* urn - urn selection model (random numbers without repetition).               */
/* Written by Olaf Matthes (olaf.matthes at gmx.de)                                */
/* Based on code found in Dodge/Jerse "Computer Music"                          */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

#include "m_pd.h"
#include <stdlib.h>
#include <time.h>
#include <math.h>

static char *version = "urn v0.1, urn selection model\n"
                       "          written by Olaf Matthes <olaf.matthes at gmx.de>";

/* -------------------------- urn ------------------------------ */

static t_class *urn_class;

typedef struct _urn
{
    t_object x_obj;
	t_outlet *x_numberout;
	t_outlet *x_notify;

	t_float  x_f;           /* number of numbers in urn */
	t_int    x_numbers;     /* numbers left in urn */
	t_int    *x_selected;
    unsigned int x_state;
} t_urn;

static int makeseed(void)
{
    static unsigned int random_nextseed = 1489853723;
    random_nextseed = random_nextseed * 435898247 + 938284287;
    return (random_nextseed & 0x7fffffff);
}

static void *urn_new(t_floatarg f)
{
    t_urn *x = (t_urn *)pd_new(urn_class);
    srand( (unsigned)time( NULL ) );
	x->x_numbers = x->x_f = f;
	if(x->x_f < 0)x->x_f = 0;
	x->x_selected = getbytes(((t_int)x->x_f+1)*sizeof(t_int));

    x->x_state = makeseed();

    inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("f"));

    x->x_numberout = outlet_new(&x->x_obj, &s_float);
    x->x_notify = outlet_new(&x->x_obj, &s_bang);
    return (x);
}

	/* set new size of urn */
static void urn_f(t_urn *x, t_floatarg f)
{
	int i;
	if(f < 0)
		f = 0;
	freebytes(x->x_selected, ((t_int)x->x_f+1)*sizeof(t_int));
	x->x_numbers = x->x_f = f;
	x->x_selected = getbytes(((t_int)x->x_f+1)*sizeof(t_int));
	for(i = 0; i <= x->x_f; i++)
		x->x_selected[i] = 0;
}

	/* clear (refill) urn */
static void urn_clear(t_urn *x)
{
	int i;
	x->x_numbers = x->x_f;
	for(i = 0; i <= x->x_f; i++)
		x->x_selected[i] = 0;
}

static void urn_seed(t_urn *x, float f, float glob)
{
    x->x_state = f;
}

	/* choose from urn */
static void urn_bang(t_urn *x)
{
    int n = x->x_f, nval;
    int range = (n < 1 ? 1 : n);
    unsigned int randval = x->x_state;
	if(x->x_numbers == 0)
		goto notify;
	do
	{
		x->x_state = randval = randval * 472940017 + 832416023;
		nval = ((double)range) * ((double)randval)
    		* (1./4294967296.);
		if (nval >= range) nval = range-1;
	}
	while(x->x_selected[nval]);

	x->x_selected[nval] = 1;

    outlet_float(x->x_numberout, nval);

	if(--x->x_numbers == 0)	/* urn is now empty */
		goto notify;
	return;

notify:
	outlet_bang(x->x_notify);
}

#ifndef MAXLIB
void urn_setup(void)
{
    urn_class = class_new(gensym("urn"), (t_newmethod)urn_new, 0,
    	sizeof(t_urn), 0, A_DEFFLOAT, 0);
#else
void maxlib_urn_setup(void)
{
    urn_class = class_new(gensym("maxlib_urn"), (t_newmethod)urn_new, 0,
    	sizeof(t_urn), 0, A_DEFFLOAT, 0);
	class_addcreator((t_newmethod)urn_new, gensym("urn"), A_DEFFLOAT, 0);
#endif
    class_addbang(urn_class, urn_bang);
	class_addmethod(urn_class, (t_method)urn_f, gensym("f"), A_FLOAT, 0);
	class_addmethod(urn_class, (t_method)urn_clear, gensym("clear"), 0);
    class_addmethod(urn_class, (t_method)urn_seed, gensym("seed"), A_FLOAT, 0);
#ifndef MAXLIB
	class_sethelpsymbol(urn_class, gensym("help-urn.pd"));
    post(version);
#else
	class_sethelpsymbol(urn_class, gensym("maxlib/help-urn.pd"));
#endif
}

--- NEW FILE: allow.c ---
/* ----------------------------  allow  --------------------------------------- */
/*                                                                              */
/* Lets only floats/symbols through that are allowed to do so.                  */
/* Written by Olaf Matthes <olaf.matthes at gmx.de>                                */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

#include "m_pd.h"
#include <string.h>

static char *version = "allow v0.1, written by Olaf Matthes <olaf.matthes at gmx.de>";

typedef struct allow
{
	t_object x_obj;	
	t_outlet *x_out;
	t_atom   *x_elem;		// list of elemets that are allowed to pass
	t_int    x_numelem;		// the number of elemetns in our allow-list
} t_allow;

	/* we got a symbol... */
static void allow_symbol(t_allow *x, t_symbol *s)
{
	int i;
	for(i = 0; i < x->x_numelem; i++)
	{
		if(x->x_elem[i].a_type == A_SYMBOL)	// compare with all symbols in our list
			if(atom_getsymbolarg(i, x->x_numelem, x->x_elem) == s)
			{
				outlet_symbol(x->x_out, s);
				return;
			}
	}			
}

	/* we got a float... */
static void allow_float(t_allow *x, t_floatarg f)
{
	int i;
	for(i = 0; i < x->x_numelem; i++)
	{
		if(x->x_elem[i].a_type == A_FLOAT)	// compare with all floats in our list
			if(atom_getfloatarg(i, x->x_numelem, x->x_elem) == f)
			{
				outlet_float(x->x_out, f);
				return;
			}
	}
}

static t_class *allow_class;

static void allow_free(t_allow *x)
{
	freebytes(x->x_elem, x->x_numelem*sizeof(t_atom));
}

static void *allow_new(t_symbol *s, int argc, t_atom *argv)
{
    t_allow *x = (t_allow *)pd_new(allow_class);

	x->x_numelem = argc;	// get the number of elements
	x->x_elem = getbytes(argc*sizeof(t_atom));
	memcpy(x->x_elem, argv, argc*sizeof(t_atom));

	x->x_out = outlet_new(&x->x_obj, gensym("anything"));

	// post("allow: got %d elements", x->x_numelem);

	return (x);
}

#ifndef MAXLIB
void allow_setup(void)
{
	/* the object's class: */
    allow_class = class_new(gensym("allow"), (t_newmethod)allow_new,
    	(t_method)allow_free, sizeof(t_allow), 0, A_GIMME, 0);
#else
void maxlib_allow_setup(void)
{
	/* the object's class: */
    allow_class = class_new(gensym("maxlib_allow"), (t_newmethod)allow_new,
    	(t_method)allow_free, sizeof(t_allow), 0, A_GIMME, 0);
	class_addcreator((t_newmethod)allow_new, gensym("allow"), A_GIMME, 0);
#endif
    class_addsymbol(allow_class, allow_symbol);
    class_addfloat(allow_class, allow_float);
#ifndef MAXLIB
    class_sethelpsymbol(allow_class, gensym("help-allow.pd"));
    post(version);
#else
    class_sethelpsymbol(allow_class, gensym("maxlib/help-allow.pd"));
#endif
}

--- NEW FILE: split.c ---
/* -------------------------  split  ------------------------------------------ */
/*                                                                              */
/* splits input to lie within an output range.                                  */
/* Written by Olaf Matthes <olaf.matthes at gmx.de>                                */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

#include "m_pd.h"
#include <stdio.h>
#include <math.h>

static char *version = "split v0.1, written by Olaf Matthes <olaf.matthes at gmx.de>";
 
typedef struct split
{
  t_object x_ob;
  t_float  x_min;                  /* low border of input range */
  t_float  x_max;                  /* high border of input range */
  t_int    x_revert;               /* range is inverted */
  t_outlet *x_outlet1;             /* path-through outlet */
  t_outlet *x_outlet2;             /* split outlet */
} t_split;

static void split_float(t_split *x, t_floatarg f)
{
	if(x->x_max >= x->x_min)
	{
		if(f <= x->x_max && f >= x->x_min)
			outlet_float(x->x_outlet1, f);
		else
			outlet_float(x->x_outlet2, f);
	}
	else
	{
		if(f >= x->x_max && f <= x->x_min)
			outlet_float(x->x_outlet1, f);
		else
			outlet_float(x->x_outlet2, f);
	}
}

static t_class *split_class;

static void *split_new(t_floatarg fmin, t_floatarg fmax)
{
    t_split *x = (t_split *)pd_new(split_class);

	floatinlet_new(&x->x_ob, &x->x_min);
	floatinlet_new(&x->x_ob, &x->x_max);

	x->x_outlet1 = outlet_new(&x->x_ob, gensym("float"));
	x->x_outlet2 = outlet_new(&x->x_ob, gensym("float"));

	x->x_min = fmin;
	x->x_max = fmax;

    return (void *)x;
}

#ifndef MAXLIB
void split_setup(void)
{
    split_class = class_new(gensym("split"), (t_newmethod)split_new,
    	0, sizeof(t_split), 0, A_DEFFLOAT, A_DEFFLOAT, 0);
    class_addfloat(split_class, split_float);
    class_sethelpsymbol(split_class, gensym("help-split.pd"));
    post(version);
}
#else
void maxlib_split_setup(void)
{
    split_class = class_new(gensym("maxlib_split"), (t_newmethod)split_new,
    	0, sizeof(t_split), 0, A_DEFFLOAT, A_DEFFLOAT, 0);
	class_addcreator((t_newmethod)split_new, gensym("split"), A_DEFFLOAT, A_DEFFLOAT, 0);
    class_addfloat(split_class, split_float);
    class_sethelpsymbol(split_class, gensym("maxlib/help-split.pd"));
}
#endif

--- NEW FILE: listfunnel.c ---
/* ------------------------- listfunnel   ------------------------------------- */
/*                                                                              */
/* Convert list into two-element lists with source index.                       */
/* Written by Olaf Matthes (olaf.matthes at gmx.de)                                */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

#include "m_pd.h"
#include <stdio.h>
#include <stdlib.h>

static char *version = "listfunnel v0.1, written by Olaf Matthes <olaf.matthes at gmx.de>";
 
typedef struct listfunnel
{
  t_object x_ob;
  t_outlet *x_outlet;               /* result */
} t_listfunnel;

static void listfunnel_list(t_listfunnel *x, t_symbol *s, int argc, t_atom *argv)
{
	int i;
	t_atom list[2];

	for(i = 0; i < argc; i++)
	{
		SETFLOAT(list, i);
		list[1] = argv[i]; // SETFLOAT(list+1, atom_getfloatarg(i, argc, argv));
		outlet_list(x->x_outlet, NULL, 2, list);
	}
}

static void listfunnel_float(t_listfunnel *x, t_floatarg f)
{
	t_atom list[2];

	SETFLOAT(list, 0);
	SETFLOAT(list+1, f);
	outlet_list(x->x_outlet, NULL, 2, list);
}

static t_class *listfunnel_class;

static void *listfunnel_new(void)
{
	int i;

    t_listfunnel *x = (t_listfunnel *)pd_new(listfunnel_class);
	x->x_outlet = outlet_new(&x->x_ob, gensym("float"));

    return (void *)x;
}

#ifndef MAXLIB
void listfunnel_setup(void)
{
    listfunnel_class = class_new(gensym("listfunnel"), (t_newmethod)listfunnel_new,
    	0, sizeof(t_listfunnel), 0, 0, 0);
    class_addfloat(listfunnel_class, listfunnel_float);
    class_addlist(listfunnel_class, listfunnel_list);
    class_sethelpsymbol(listfunnel_class, gensym("help-listfunnel.pd"));
    post(version);
}
#else
void maxlib_listfunnel_setup(void)
{
    listfunnel_class = class_new(gensym("maxlib_listfunnel"), (t_newmethod)listfunnel_new,
    	0, sizeof(t_listfunnel), 0, 0, 0);
	class_addcreator((t_newmethod)listfunnel_new, gensym("listfunnel"), 0);
    class_addfloat(listfunnel_class, listfunnel_float);
    class_addlist(listfunnel_class, listfunnel_list);
    class_sethelpsymbol(listfunnel_class, gensym("maxlib/help-listfunnel.pd"));
}
#endif


--- NEW FILE: beat.c ---
/* --------------------------- beat  ------------------------------------------ */
/*                                                                              */
/* Detect the beats per minute of a MIDI stream.                                */
/* Written by Olaf Matthes (olaf.matthes at gmx.de)                                */
/* Based on code written by Robert Rowe.                                        */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

#include "m_pd.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define BEAT_LONG 1500			/* longest time we take into concideration (40 bpm) */
#define BEAT_SHORT 300			/* shortest time we take into concideration (200 bpm) */

static char *version = "beat v0.1, written by Olaf Matthes <olaf.matthes at gmx.de>";

typedef struct
{
	t_int	points;					/* number of points assigned to this theory */
	double  expect;					/* time of next expected hit */
	t_int	onbeat;					/* whether (1) or not (0) it was on the beat */
} beat_theory;

typedef struct						/* used for sorting theories */
{
	t_int points;
	t_int theory;
} beat_sort_record;

 
typedef struct beat
{
  t_object x_ob;
  t_clock  *x_clock;
  t_outlet *x_outbpm;               /* beat as MIDI note number */
  t_outlet *x_outms;                /* beat in milliseconds */
  t_outlet *x_outbeat;				/* send a bang whenever beat is 'on beat' */
  t_int    x_print;                 /* switch printing to console window on / off */

  t_int    x_num_beats;				/* number of beats we've received */
  double   x_beat_period;			/* time in ms until next expected beat / beat pulse */
  beat_theory	x_beats[BEAT_LONG];
  double   x_beatexpect;			/* expected time for next beat */
  t_int    x_on_beat;				/* indicate if last event was on beat */
  t_int    x_band_percent;

  t_int    x_pitch;
  t_int    x_velo;
	/* helpers needed to do the time calculations */
  double   x_this_input;
  double   x_last_input;
  double   x_lasttime;
  double   x_lastlasttime;
} t_beat;

/* ---------------- mathematical functions to work with doubles  -------------- */
static double double_abs(double value)
{
	if(value < 0)
		return (value * -1);
	else
		return (value);
}

/* --------------- beat  stuff ------------------------------------------------ */
	/* evaluate results: find theory that is the most likely one and
       print out internal data to console window if print is enabled */
static int beat_evaluate(t_beat *x)
{
	int i, j, K;
	char string[256];
	char info[40];
	beat_sort_record theories[BEAT_LONG], *sortp, R;
	int value;	/* the result of the sorting */

	for (i = 0; i < BEAT_LONG; i++)
	{		/* prepare sort records */
		sortp         = &(theories[i]);
		sortp->points = x->x_beats[i].points;
		sortp->theory = i;
	}
	for (j = 2; j < BEAT_LONG; j++)
	{		/* sort */
		i = j - 1;
		K = theories[j].points;
		R = theories[j];
		while (i > 0)
		{
			if (K >= theories[i].points)
			{
				theories[i+1] = R;
				break;
			}
			else
			{
				theories[i+1] = theories[i];
				i -= 1;
			}
		}
		if (i==0) theories[i+1] = R;
	}
		/* get leading result */
	sortp = &(theories[BEAT_LONG - 1]);
	value = sortp->theory;	/* get our resulting theory */

	if(x->x_print)
	{
		post("         0         1         2         3         4         R            E");
		*string = '\0';						/* print out five leading theories */
		sprintf(info, "%4g", x->x_this_input);
		strcat(string, info);
		for(i = 1; i < 6; i++)
		{
			sortp = &(theories[BEAT_LONG - i]);
			sprintf(info, " %4d[%3d]", sortp->theory, sortp->points);
			strcat(string, info);
		}
		sprintf(info, "  %g %g", clock_getlogicaltime(), x->x_beatexpect);
		strcat(string, info);
		post(string);
	}

	return value;
}

	/* reduce duration to fit into our processing window */
	/* some sort of 'double modulo'...                   */
static double beat_reduce_offset(double duration)
{
	double temp	= duration;
	int divisor = 2;					/* first try dividing by two */
	while (temp > BEAT_LONG)		    /* while duration is too long */
		temp = duration / divisor++;    /* divide by progressively higher divisors */
	return temp;				        /* return a value in bounds */
}

/*
 * beat_eligible: determine whether an event is eligible for consideration
 * as a beat theory
 */
static int beat_eligible(double candidate, int* offsets, int num_offsets)
{
	double diff;
	int i;

	if (candidate >= BEAT_LONG)		/* if too long try subharmonics */
		candidate = beat_reduce_offset(candidate);
	
		/* if candidate is close to one already found */
	for(i = 0; i < num_offsets; i++)
	{
		diff = double_abs((candidate - offsets[i]));
		if (diff < offsets[i]/20) {
			if (candidate > offsets[i])
				++offsets[i]; else			/* pull existing one */
			if (candidate < offsets[i])		/* toward new candidate */
				--offsets[i];
			return 0;						/* declare candidate ineligible */
		}
	}
	return candidate;						/* otherwise return legal candidate */
}

static void beat_float(t_beat *x, t_floatarg f)
{
	t_int velo = x->x_velo;
	int i, j, indx;
	int num_offsets, candidate;
	int low_limit, high_limit, width, deviation;
	int points, band, center_offset, period;
	beat_theory* t;
	int offsets[7];
	static int factors[10] = 
		{ 200, 50, 300, 150, 66, 400, 600, 133, 33, 75 };
	double now = clock_getlogicaltime();
	t_float outvalue;

	x->x_pitch = (t_int)f;
	x->x_this_input = clock_gettimesince(x->x_last_input);

	if(velo != 0)	/* note-on received */
	{
		if(++x->x_num_beats == 1)
		{
			goto time;					/* only one event, no beats yet */
		}

		num_offsets = 0;
		candidate  = beat_eligible(x->x_this_input, offsets, num_offsets);
		if(candidate)
			offsets[num_offsets++] = candidate;				/* offset[0] set to incoming offset */
 
		if(x->x_num_beats > 2)
		{								/* if three events */
				/* check previous for eligibility */
			candidate = beat_eligible(x->x_lasttime, offsets, num_offsets);
			if (candidate)
				offsets[num_offsets++] = candidate;
			candidate  = x->x_this_input + x->x_lasttime;	/* add current and previous offsets */
			candidate  = beat_eligible(candidate, offsets, num_offsets);
			if (candidate)									/* add to list if eligible */
				offsets[num_offsets++] = candidate;
		}

		if(x->x_num_beats > 3)
		{
			candidate  = beat_eligible(x->x_lastlasttime, offsets, num_offsets);
			if (candidate)
				offsets[num_offsets++] = candidate;
			candidate += x->x_lasttime;
			candidate  = beat_eligible(candidate, offsets, num_offsets);
			if (candidate)
				offsets[num_offsets++] = candidate;
		}

		indx = 0;
		for(i = num_offsets; i < 7; i++)
		{
			offsets[i] = 0;
			if (indx >= 10) break;
			candidate  = 0;
			while ((indx < 10) && (!candidate))
				candidate = beat_eligible((x->x_this_input * factors[indx++])/100, offsets, num_offsets);
			if (candidate)
				offsets[num_offsets++] = candidate;
		}
		
		for(i = 0; i < num_offsets; i++)
		{
			band = offsets[i] * x->x_band_percent / 100;
			if ((low_limit = offsets[i] - band) < 0)		/* add points in a critical band */
				low_limit  = 0;								/* around calculated offset */
			if ((high_limit = offsets[i] + band) > BEAT_LONG)
				high_limit = BEAT_LONG;
			center_offset = offsets[i];						/* midpoint of increment */
			points = 0;
			for (j = low_limit; j < high_limit; j++)
			{
				if ((points = x->x_beats[j].points) > 0)
				{		/* if there is already activation */
					deviation = j - center_offset;			/* record deviation from midpoint */
					x->x_beats[j].points = 0;
					if (deviation < 0) {					/* if there is activation below midpoint */
						t = &(x->x_beats[j+1]);				/* take theory one above prior */
					} else
					if (deviation > 0) {					/* if there is activation above midpoint */
						t = &(x->x_beats[j-1]);				/* take theory one below prior */
					} else
						t = &(x->x_beats[j]);				/* landed right on it */
					t->points = points + (num_offsets-i);
					break;
				}
			}
			if (!points)
				x->x_beats[center_offset].points = num_offsets - i;
		}

			/* boost hits, and suppress theories with missed beats */
		period = 0;
		points = 0;
		for (i = BEAT_SHORT; i < BEAT_LONG; i++)
		{
			t = &(x->x_beats[i]);
			width = 5 > (t->expect / 7) ? 5 : (t->expect / 7);
			t->expect -= x->x_this_input;
			t->onbeat  = 0;
			if(double_abs(t->expect) <= width)	/* lies within range */
			{
				t->expect = i;
				t->onbeat = 1;
	 			if (t->points > 0)
					t->points += 4;				/* add 4 points */
			}
			else if(t->expect < 0)
			{
				t->points -= 8;
				t->expect  = i;
			}
			if (t->points < 0)   t->points =   0; else
			if (t->points > 200) t->points = 200;
			if (t->points > points)
			{
				points = t->points;
				period = i;
			}
		}



		x->x_beat_period    = (double)period;
		t					= &(x->x_beats[period]);
		x->x_beatexpect		= now + (double)t->expect;
		x->x_on_beat	    = t->onbeat;
		
time:
		x->x_lastlasttime = x->x_lasttime;
		x->x_lasttime = x->x_this_input; //now;
		x->x_last_input = now;

		if(x->x_on_beat)outlet_bang(x->x_outbeat);
		outvalue = (t_float)beat_evaluate(x);
		outlet_float(x->x_outms, outvalue);
		if(x->x_beat_period)outlet_float(x->x_outbpm, (t_float)(60000.0 / outvalue));
	}
	return;
}

static void beat_ft1(t_beat *x, t_floatarg f)
{
	x->x_velo = (t_int)f;
}

	/* toggle printing on/off */
static void beat_print(t_beat *x)
{
	if(x->x_print)x->x_print = 0;
	else x->x_print = 1;
}

static void beat_reset(t_beat *x)
{
	int i;

	for(i = 0; i < BEAT_LONG; i++)
	{
		x->x_beats[i].points = 0;
		x->x_beats[i].expect = i;
		x->x_beats[i].onbeat = 0;
	}
	x->x_lastlasttime = 0;
	x->x_lasttime = 0;
	x->x_num_beats = 0;
	x->x_beat_period = 0;
	x->x_on_beat = 0;
}

static t_class *beat_class;

static void beat_free(t_beat *x)
{
	/* nothing to do */
}

static void *beat_new(t_floatarg f)
{
    t_beat *x = (t_beat *)pd_new(beat_class);
    inlet_new(&x->x_ob, &x->x_ob.ob_pd, gensym("float"), gensym("ft1"));
	x->x_outbpm = outlet_new(&x->x_ob, gensym("float"));
	x->x_outms = outlet_new(&x->x_ob, gensym("float"));
	x->x_outbeat = outlet_new(&x->x_ob, gensym("bang"));

	beat_reset(x);
	x->x_band_percent = 4;	/* allow 4% 'jitter' by default */
	if(f)x->x_band_percent = (t_int)f;

	post("beat: band percentage set to %d", x->x_band_percent);

    return (void *)x;
}

#ifndef MAXLIB
void beat_setup(void)
{
    beat_class = class_new(gensym("beat"), (t_newmethod)beat_new,
    	(t_method)beat_free, sizeof(t_beat), 0, A_DEFFLOAT, 0);
#else
void maxlib_beat_setup(void)
{
    beat_class = class_new(gensym("maxlib_beat"), (t_newmethod)beat_new,
    	(t_method)beat_free, sizeof(t_beat), 0, A_DEFFLOAT, 0);
#endif
    class_addfloat(beat_class, beat_float);
	class_addmethod(beat_class, (t_method)beat_ft1, gensym("ft1"), A_FLOAT, 0);
	class_addmethod(beat_class, (t_method)beat_reset, gensym("reset"), 0);
	class_addmethod(beat_class, (t_method)beat_print, gensym("print"), 0);
#ifndef MAXLIB
    class_sethelpsymbol(beat_class, gensym("help-beat.pd"));
    post(version);
#else
	class_addcreator((t_newmethod)beat_new, gensym("beat"), A_DEFFLOAT, 0);
    class_sethelpsymbol(beat_class, gensym("maxlib/help-beat.pd"));
#endif
}


--- NEW FILE: rewrap.c ---
/* -------------------------  rewrap  ------------------------------------------ */
/*                                                                              */
/* rewraps input to lie within an output range.                                  */
/* Written by Olaf Matthes <olaf.matthes at gmx.de>                                */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

#include "m_pd.h"
#include <stdio.h>
#include <math.h>

static char *version = "rewrap v0.1, written by Olaf Matthes <olaf.matthes at gmx.de>";
 
typedef struct rewrap
{
  t_object x_ob;
  t_float  x_min;                  /* low border of input range */
  t_float  x_max;                  /* high border of input range */
  t_outlet *x_outlet1;             /* path-through outlet */
  t_outlet *x_outlet2;             /* rewrap outlet */
} t_rewrap;

static void rewrap_float(t_rewrap *x, t_floatarg f)
{
  t_float min = x->x_min;
  t_float max = x->x_max;
  t_float range = 2.0f * (max - min);
  t_int i;

  if(range == 0.0f)
    {
      f = min;
      outlet_float(x->x_outlet2, 0);
    }
  else if(f < min)
    {
      float diff = min - f;
      float n = ceil(diff / range);

      f += n * range;

      if(f >= max)
	{
	  f = 2 * max - f;
	  n -= 0.5;
	}

      outlet_float(x->x_outlet2, (t_int)(-2.0f * n));
    }
  else if (f >= max)
    {
      float diff = f - max;
      float n = floor(diff / range) + 1.0f;

      f -= n * range;

      if(f < min)
	{
	  f = 2 * min - f;
	  n -= 0.5;
	}

      outlet_float(x->x_outlet2, (t_int)(2.0f * n));
    }
  else
    outlet_float(x->x_outlet2, 0.0f);
    

  outlet_float(x->x_outlet1, f);
}

static void rewrap_a(t_rewrap *x, t_floatarg a)
{
	t_float max = x->x_max;

	if(a <= max)
		x->x_min = a;
	else
	{
		x->x_min = max;
		x->x_max = a;
	}
}

static void rewrap_b(t_rewrap *x, t_floatarg b)
{
	t_float min = x->x_min;

	if(b >= min)
		x->x_max = b;
	else
	{
		x->x_max = min;
		x->x_min = b;
	}
}

static t_class *rewrap_class;

static void *rewrap_new(t_floatarg fmin, t_floatarg fmax)
{
    t_rewrap *x = (t_rewrap *)pd_new(rewrap_class);

    inlet_new(&x->x_ob, &x->x_ob.ob_pd, gensym("float"), gensym("a"));
    inlet_new(&x->x_ob, &x->x_ob.ob_pd, gensym("float"), gensym("b"));

	x->x_outlet1 = outlet_new(&x->x_ob, gensym("float"));
	x->x_outlet2 = outlet_new(&x->x_ob, gensym("float"));

	x->x_min = fmin;
	rewrap_b(x, fmax);

    return (void *)x;
}

#ifndef MAXLIB
void rewrap_setup(void)
{
    rewrap_class = class_new(gensym("rewrap"), (t_newmethod)rewrap_new,
    	0, sizeof(t_rewrap), 0, A_DEFFLOAT, A_DEFFLOAT, 0);
    class_addfloat(rewrap_class, rewrap_float);
	class_addmethod(rewrap_class, (t_method)rewrap_a, gensym("a"), A_FLOAT, 0);
	class_addmethod(rewrap_class, (t_method)rewrap_b, gensym("b"), A_FLOAT, 0);
    class_sethelpsymbol(rewrap_class, gensym("help-rewrap.pd"));
    post(version);
}
#else
void maxlib_rewrap_setup(void)
{
    rewrap_class = class_new(gensym("maxlib_rewrap"), (t_newmethod)rewrap_new,
    	0, sizeof(t_rewrap), 0, A_DEFFLOAT, A_DEFFLOAT, 0);
	class_addcreator((t_newmethod)rewrap_new, gensym("rewrap"), A_DEFFLOAT, A_DEFFLOAT, 0);
    class_addfloat(rewrap_class, rewrap_float);
	class_addmethod(rewrap_class, (t_method)rewrap_a, gensym("a"), A_FLOAT, 0);
	class_addmethod(rewrap_class, (t_method)rewrap_b, gensym("b"), A_FLOAT, 0);
    class_sethelpsymbol(rewrap_class, gensym("maxlib/help-rewrap.pd"));
}
#endif

--- NEW FILE: speedlim.c ---
/* ------------------------- speedlim ----------------------------------------- */
/*                                                                              */
/* Lets information through only every N milliseconds.                          */
/* Written by Krzysztof Czaja for his cyclone library.                          */
/* Modified to fit into maxlib by Olaf Matthes <olaf.matthes at gmx.de>.           */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* You should have received a copy of the GNU Lesser General Public             */
/* License along with this library; if not, write to the                        */
/* Free Software Foundation, Inc., 59 Temple Place - Suite 330,                 */
/* Boston, MA  02111-1307, USA.                                                 */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

/* this is the original copyright notice: */

/* Copyright (c) 1997-2002 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.  */


#include <string.h>
#include "m_pd.h"

#define SPEEDLIM_INISIZE   32  /* LATER rethink */
#define SPEEDLIM_MAXSIZE  256  /* not used */

typedef struct _speedlim
{
    t_object     x_ob;
    int          x_open;
    t_float      x_delta;
    t_symbol    *x_selector;
    t_float      x_float;
    t_symbol    *x_symbol;
    t_gpointer  *x_pointer;
    int          x_size;    /* as allocated */
    int          x_natoms;  /* as used */
    t_atom      *x_message;
    t_atom       x_messini[SPEEDLIM_INISIZE];
    int          x_entered;
    t_clock     *x_clock;
} t_speedlim;

static t_class *speedlim_class;

/* a caller must check for nrequested > *sizep */
/* returns actual number of atoms: requested (success)
   or a default value of initial size (failure) */
/* the result is guaranteed to be >= min(nrequested, inisize) */
static int speedlim_grow(int nrequested, int *sizep, t_atom **bufp,
		int inisize, t_atom *bufini)
{
    int newsize = *sizep * 2;
    while (newsize < nrequested) newsize *= 2;
    if (*bufp == bufini)
	*bufp = (t_atom *)getbytes(newsize * sizeof(**bufp));
    else
	*bufp = (t_atom *)resizebytes(*bufp, *sizep * sizeof(**bufp),
				      newsize * sizeof(**bufp));
    if (*bufp)
	*sizep = newsize;
    else
    {
	*bufp = bufini;
	nrequested = *sizep = inisize;
    }
    return (nrequested);
}

static void speedlim_dooutput(t_speedlim *x, t_symbol *s, int ac, t_atom *av)
{
    x->x_open = 0;     /* so there will be no reentrant calls of dooutput */
    x->x_entered = 1;  /* this prevents a message from being overridden */
    clock_unset(x->x_clock);
    if (s == &s_bang)
	outlet_bang(((t_object *)x)->ob_outlet);
    else if (s == &s_float)
	outlet_float(((t_object *)x)->ob_outlet, x->x_float);
    else if (s == &s_symbol && x->x_symbol)
    {
	/* if x_symbol is null, then symbol &s_ is passed
	   by outlet_anything() -> typedmess() */
	outlet_symbol(((t_object *)x)->ob_outlet, x->x_symbol);
	x->x_symbol = 0;
    }
    else if (s == &s_pointer && x->x_pointer)
    {
	/* LATER */
	x->x_pointer = 0;
    }
    else if (s == &s_list)
	outlet_list(((t_object *)x)->ob_outlet, &s_list, ac, av);
    else if (s)
	outlet_anything(((t_object *)x)->ob_outlet, s, ac, av);
    x->x_selector = 0;
    x->x_natoms = 0;
    if (x->x_delta > 0)
	clock_delay(x->x_clock, x->x_delta);
    else
	x->x_open = 1;
    x->x_entered = 0;
}

static void speedlim_tick(t_speedlim *x)
{
    if (x->x_selector)
	speedlim_dooutput(x, x->x_selector, x->x_natoms, x->x_message);
    else
	x->x_open = 1;
}

static void speedlim_anything(t_speedlim *x, t_symbol *s, int ac, t_atom *av)
{
    if (x->x_open)
	speedlim_dooutput(x, s, ac, av);
    else if (s && s != &s_ && !x->x_entered)
    {
	if (ac > x->x_size)
	    /* MAXSIZE not used, not even a warning...
	       LATER consider clipping */
	    ac = speedlim_grow(ac, &x->x_size, &x->x_message,
			     SPEEDLIM_INISIZE, x->x_messini);
	x->x_selector = s;
	x->x_natoms = ac;
	if (ac)
	    memcpy(x->x_message, av, ac * sizeof(*x->x_message));
    }
}

static void speedlim_bang(t_speedlim *x)
{
    x->x_selector = &s_bang;
    speedlim_anything(x, x->x_selector, 0, 0);
}

static void speedlim_float(t_speedlim *x, t_float f)
{
    x->x_selector = &s_float;
    x->x_float = f;
    speedlim_anything(x, x->x_selector, 0, 0);
}

static void speedlim_symbol(t_speedlim *x, t_symbol *s)
{
    x->x_selector = &s_symbol;
    x->x_symbol = s;
    speedlim_anything(x, x->x_selector, 0, 0);
}

/* LATER gpointer */

static void speedlim_list(t_speedlim *x, t_symbol *s, int ac, t_atom *av)
{
    x->x_selector = &s_list;
    speedlim_anything(x, x->x_selector, ac, av);
}

static void speedlim_ft1(t_speedlim *x, t_floatarg f)
{
    if (f < 0)
	f = 0;  /* redundant (and CHECKED) */
    x->x_delta = f;
    /* CHECKED: no rearming --
       if clock is set, then new delta value is not used until next tick */
}

static void speedlim_free(t_speedlim *x)
{
    if (x->x_message != x->x_messini)
	freebytes(x->x_message, x->x_size * sizeof(*x->x_message));
    if (x->x_clock)
	clock_free(x->x_clock);
}

static void *speedlim_new(t_floatarg f)
{
    t_speedlim *x = (t_speedlim *)pd_new(speedlim_class);
    x->x_open = 1;  /* CHECKED */
    x->x_delta = 0;
    x->x_selector = 0;
    x->x_float = 0;
    x->x_symbol = 0;
    x->x_pointer = 0;
    x->x_size = SPEEDLIM_INISIZE;
    x->x_natoms = 0;
    x->x_message = x->x_messini;
    x->x_entered = 0;
    inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft1"));
    outlet_new((t_object *)x, &s_anything);
    x->x_clock = clock_new(x, (t_method)speedlim_tick);
    speedlim_ft1(x, f);
    return (x);
}

#ifndef MAXLIB
void speedlim_setup(void)
{
    speedlim_class = class_new(gensym("speedlim"), (t_newmethod)speedlim_new,
		(t_method)speedlim_free, sizeof(t_speedlim), 0, A_DEFFLOAT, 0);
#else
void maxlib_speedlim_setup(void)
{
    speedlim_class = class_new(gensym("maxlib_speedlim"), (t_newmethod)speedlim_new,
		(t_method)speedlim_free, sizeof(t_speedlim), 0, A_DEFFLOAT, 0);
	class_addcreator((t_newmethod)speedlim_new, gensym("speedlim"), A_DEFFLOAT, 0);
#endif
    class_addbang(speedlim_class, speedlim_bang);
    class_addfloat(speedlim_class, speedlim_float);
    class_addsymbol(speedlim_class, speedlim_symbol);
    class_addlist(speedlim_class, speedlim_list);
    class_addanything(speedlim_class, speedlim_anything);
    class_addmethod(speedlim_class, (t_method)speedlim_ft1, gensym("ft1"), A_FLOAT, 0);
#ifndef MAXLIB
    class_sethelpsymbol(speedlim_class, gensym("help-speedlim.pd"));
#else
    class_sethelpsymbol(speedlim_class, gensym("maxlib/help-speedlim.pd"));
#endif
}

--- NEW FILE: average.c ---
/* -------------------------- average ----------------------------------------- */
/*                                                                              */
/* Calculates the average value of the last N elements.                         */
/* Written by Olaf Matthes (olaf.matthes at gmx.de)                                */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

#include "m_pd.h"
#include <math.h>

#define MAX_ARG  128                /* maximum number of items to average */

static char *version = "average v0.1, written by Olaf Matthes <olaf.matthes at gmx.de>";
 
typedef struct average
{
  t_object x_ob;
  t_clock  *x_clock;
  t_inlet  *x_inindex;
  t_outlet *x_outfloat;             /* output the average */
  t_outlet *x_outtendency;          /* outputs the tendency of the average */
  t_int    x_limit;                 /* indicates if input is 'blocked' (1) */
  t_int    x_index;                 /* the number of elements to average */
  t_float  x_input[MAX_ARG];        /* stores the input values we need for averaging */
  t_int    x_inpointer;             /* actual position in above array */
  t_float  x_average;               /* what do you guess ? */
  t_float  x_lastaverage;
  t_int    x_mode;                  /* how to average: linear or geometric */

} t_average;

	/* there must be a function for this in math.h but how is the 
	   german 'Fakultät' called in english ????  */
static int normalise(int i)
{
	int ret = i;
	while(i--)
	{
		if(i == 0)break;
		ret += i;
	}
	return (ret);
}

static void average_float(t_average *x, t_floatarg f)
{
	int i, j = 0;
	t_float tendency;
	t_float geo = 1.0;

	x->x_average = 0;
		/* put value into array */
	x->x_input[x->x_inpointer] = f;
		/* calulate average */
	for(i = 0; i < x->x_index; i++)
	{
		if(x->x_mode == 0)	/* linear */
		{
			x->x_average += x->x_input[i] * (1.0 / (float)x->x_index);
		}
		else if(x->x_mode == 1)	/* geometric */
		{
			if(x->x_input[i] == 0)x->x_input[i] = 0.001;	/* need to cheat a bit... */
			geo *= x->x_input[i];
			if(i == x->x_index - 1)
				x->x_average = pow(geo, (1.0/(float)x->x_index));
		}
		else if(x->x_mode == 2)	/* weighted */
		{
			x->x_average += x->x_input[(j + x->x_inpointer + x->x_index) % x->x_index] * (float)(x->x_index - (i + 1));
			j--;	/* go back in array */
				/* normalise output */
			if(i == x->x_index - 1)
				x->x_average = x->x_average / (float)normalise(x->x_index - 1);
		} else post("average: internal error!");
	}
	if(++x->x_inpointer > x->x_index)
	{
		x->x_inpointer = 0;
		if(x->x_lastaverage < x->x_average)
		{
			tendency = 1;	/* getting more */
		}
		else if(x->x_lastaverage > x->x_average)
		{
			tendency = -1;	/* getting less */
		}
		else tendency = 0;	/* nothing has changed */
		outlet_float(x->x_outtendency, tendency);
		x->x_lastaverage = x->x_average;
	}
	outlet_float(x->x_outfloat, x->x_average);
}

static void average_index(t_average *x, t_floatarg f)
{
	x->x_index = (t_int)f;
	if(x->x_index > MAX_ARG)x->x_index = MAX_ARG;
}

static void average_reset(t_average *x)
{
	int i;
		/* zeroe out the array */
	for(i = 0; i < MAX_ARG; i++)x->x_input[i] = 0.0;
	x->x_inpointer = 0;
	x->x_average = 0;
	x->x_lastaverage = 0;
    post("average: reset");
}

static void average_linear(t_average *x)
{
	x->x_mode = 0;
    post("average: linear");
}

static void average_geometric(t_average *x)
{
	x->x_mode = 1;
    post("average: geometric");
}

static void average_weight(t_average *x)
{
	x->x_mode = 2;
    post("average: weighted");
}

static void average_free(t_average *x)
{
	/* nothing to do */
}

static t_class *average_class;

static void *average_new(t_floatarg f)
{
	int i;

    t_average *x = (t_average *)pd_new(average_class);
	x->x_inindex = inlet_new(&x->x_ob, &x->x_ob.ob_pd, gensym("float"), gensym("index"));
	x->x_outfloat = outlet_new(&x->x_ob, gensym("float"));
	x->x_outtendency = outlet_new(&x->x_ob, gensym("float"));

		/* zeroe out the array */
	for(i = 0; i < MAX_ARG; i++)x->x_input[i] = 0.0;
	x->x_index = (t_int)f;
	if(x->x_index > MAX_ARG)
	{
		x->x_index = MAX_ARG;
		post("average: set number of items to %d", x->x_index);
	}
	x->x_inpointer = 0;
	x->x_average = 0;
	x->x_mode = 0;
    return (void *)x;
}

#ifndef MAXLIB
void average_setup(void)
{
    average_class = class_new(gensym("average"), (t_newmethod)average_new,
    	(t_method)average_free, sizeof(t_average), 0, A_DEFFLOAT, 0);
#else
void maxlib_average_setup(void)
{
    average_class = class_new(gensym("maxlib_average"), (t_newmethod)average_new,
    	(t_method)average_free, sizeof(t_average), 0, A_DEFFLOAT, 0);
#endif
    class_addmethod(average_class, (t_method)average_reset, gensym("reset"), 0);
    class_addmethod(average_class, (t_method)average_linear, gensym("linear"), 0);
    class_addmethod(average_class, (t_method)average_geometric, gensym("geometric"), 0);
    class_addmethod(average_class, (t_method)average_weight, gensym("weight"), 0);
    class_addfloat(average_class, average_float);
	class_addmethod(average_class, (t_method)average_index, gensym("index"), A_FLOAT, 0);
#ifndef MAXLIB
    post(version);
    class_sethelpsymbol(average_class, gensym("help-average.pd"));
#else
	class_addcreator((t_newmethod)average_new, gensym("average"), A_DEFFLOAT, 0);
    class_sethelpsymbol(average_class, gensym("maxlib/help-average.pd"));
#endif
}


--- NEW FILE: arraycopy.c ---
/* ------------------------- arraycopy  --------------------------------------- */
/*                                                                              */
/* Copy data from one array to another .                                        */
/* Written by Olaf Matthes <olaf.matthes at gmx.de>                                */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

#include "m_pd.h"
#include <stdlib.h>

static char *version = "arraycopy v0.2, written by Olaf Matthes <olaf.matthes at gmx.de>";

typedef struct arraycopy
{
	t_object x_obj;		
	t_symbol *x_destarray;
	t_symbol *x_sourcearray;
	t_garray *x_destbuf;
	t_garray *x_sourcebuf;
	t_int    x_start;
	t_int    x_end;
	t_int    x_pos;
	short    x_print;
} t_arraycopy;

	/* choose the destination array to copy to */
static void arraycopy_setdestarray(t_arraycopy *x, t_symbol *s)
{
	t_garray *b;
	
	if ((b = (t_garray *)pd_findbyclass(s, garray_class)))
	{
		// post("arraycopy: destination array set to \"%s\"", s->s_name);
		x->x_destbuf = b;
	} else {
		post("arraycopy: no array \"%s\" (error %d)", s->s_name, b);
		x->x_destbuf = 0;
	}
}

static void arraycopy_setdest(t_arraycopy *x, t_symbol *s)
{
		x->x_destarray = s;
		arraycopy_setdestarray(x, x->x_destarray);
}

	/* choose the source array to copy from */
static void arraycopy_setsourcearray(t_arraycopy *x, t_symbol *s)
{
	t_garray *b;
	
	if ((b = (t_garray *)pd_findbyclass(s, garray_class)))
	{
		// post("arraycopy: source array set to \"%s\"", s->s_name);
		x->x_sourcebuf = b;
	} else {
		post("arraycopy: no array \"%s\" (error %d)", s->s_name, b);
		x->x_sourcebuf = 0;
	}
}

	/* this is the routine that actually does the copying */
	/* get's called directly when we get a 'bang' */
static void arraycopy_docopy(t_arraycopy *x)
{
	t_garray *b;		/* make local copy of array */
	t_float *tab;                 /* the content itselfe */
	t_int items, i;
	t_garray *A;
	int npoints;
	t_float *vec;

	if(!x->x_destarray)
	{
		post("arraycopy: no destination array specified");
		return;
	}
	if(!x->x_sourcearray)
	{
		post("arraycopy: no source array specified");
		return;
	}

	A = x->x_destbuf;

	if ((b = (t_garray *)pd_findbyclass(x->x_sourcearray, garray_class)))
	{
		// post("arraycopy: source array set to \"%s\"", x->x_sourcearray->s_name);
	} else {
		post("arraycopy: no array \"%s\" (error %d)", x->x_sourcearray->s_name, b);
		return;
	}

		// read from our array
	if (!garray_getfloatarray(b, &items, &tab))
	{
		post("arraycopy: couldn't read from source array!");
		return;
	}

	if (!(A = (t_garray *)pd_findbyclass(x->x_destarray, garray_class)))
		error("arraycopy: %s: no such array", x->x_destarray->s_name);
	else if (!garray_getfloatarray(A, &npoints, &vec))
		error("arraycopy: %s: bad template ", x->x_destarray->s_name);
	else
	{
		if(x->x_start > items)	// check start point
		{
			post("arraycopy: source start point out of range for the array given");
			return;
		}
		if(x->x_end)	// end point is specified
		{
			if(x->x_end > items)	// check start point
			{
				post("arraycopy: source end point out of range for the array given");
				x->x_end = items;
			}
		}
		else x->x_end = items;

		if(x->x_pos)
			vec += x->x_pos;

		for(i = x->x_start; i < x->x_end; i++)
		{
			*vec++ = tab[i];
		}
		garray_redraw(A);
		if(x->x_print)post("arraycopy: copied %d values from array \"%s\" to array \"%s\"", 
					        x->x_end-x->x_start, x->x_sourcearray->s_name, x->x_destarray->s_name);
	}
}

static void arraycopy_list(t_arraycopy *x, t_symbol *s, int argc, t_atom *argv)
{
	if(argc > 1) {
		x->x_sourcearray = atom_getsymbolarg(0, argc, argv);
		x->x_destarray   = atom_getsymbolarg(1, argc, argv);
	}
}

static void arraycopy_source(t_arraycopy *x, t_symbol *s)
{
	x->x_sourcearray = s;
	x->x_start = x->x_end = x->x_pos = 0;
	arraycopy_docopy(x);
}

static void arraycopy_print(t_arraycopy *x, t_floatarg f)
{
	if(f)
		x->x_print = 1;
	else
		x->x_print = 0;
}

static void arraycopy_copy(t_arraycopy *x, t_symbol *s, int argc, t_atom *argv)
{
	if(argc == 1)		// source array name supplied
	{
		x->x_sourcearray = atom_getsymbolarg(0, argc, argv);
		x->x_start = x->x_end = x->x_pos = 0;
	}
	else if(argc == 2)	// array name and start point supplied
	{
		x->x_sourcearray = atom_getsymbolarg(0, argc, argv);
		x->x_start = atom_getfloatarg(1, argc, argv);
		x->x_end = x->x_pos = 0;
	}
	else if(argc == 3)	// arrayname and start & end point supplied
	{
		x->x_sourcearray = atom_getsymbolarg(0, argc, argv);
		x->x_start = atom_getfloatarg(1, argc, argv);
		if(argv[2].a_type == A_FLOAT)	// real position
		{
			x->x_end = atom_getfloatarg(2, argc, argv);
		}
		else	// offset given
		{
			t_symbol *offset = atom_getsymbolarg(2, argc, argv);
			x->x_end = (t_int)atoi(offset->s_name) + x->x_start;
		}
		x->x_pos = 0;
	}
	else if(argc == 4)	// as above & dest. array
	{
		x->x_sourcearray = atom_getsymbolarg(0, argc, argv);
		x->x_start = atom_getfloatarg(1, argc, argv);
		if(argv[2].a_type == A_FLOAT)	// real position
		{
			x->x_end = atom_getfloatarg(2, argc, argv);
		}
		else	// offset given
		{
			t_symbol *offset = atom_getsymbolarg(2, argc, argv);
			x->x_end = (t_int)atoi(offset->s_name) + x->x_start;
		}
		x->x_destarray = atom_getsymbolarg(3, argc, argv);
		arraycopy_setdestarray(x, x->x_destarray);
		x->x_pos = 0;
	}
	else if(argc == 5)	// as above & dest. array & pos. in dest.
	{
		x->x_sourcearray = atom_getsymbolarg(0, argc, argv);
		x->x_start = atom_getfloatarg(1, argc, argv);
		if(argv[2].a_type == A_FLOAT)	// real position
		{
			x->x_end = atom_getfloatarg(2, argc, argv);
		}
		else	// offset given
		{
			t_symbol *offset = atom_getsymbolarg(2, argc, argv);
			x->x_end = (t_int)atoi(offset->s_name) + x->x_start;
		}
		x->x_destarray = atom_getsymbolarg(3, argc, argv);
		arraycopy_setdestarray(x, x->x_destarray);
		x->x_pos = atom_getfloatarg(4, argc, argv);
	}
	else post("arraycopy: copy: wrong number of arguments");
	
	arraycopy_docopy(x);
}

static t_class *arraycopy_class;

static void *arraycopy_new(t_symbol *s, int argc, t_atom *argv)
{
    t_arraycopy *x = (t_arraycopy *)pd_new(arraycopy_class);

	if (argc > 0) {
		x->x_destarray = atom_getsymbolarg(0, argc, argv);
		arraycopy_setdestarray(x, x->x_destarray);
	}
	inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("symbol"), gensym("dest"));
	x->x_start = x->x_end = x->x_pos = x->x_print = 0;
	return (x);
}

#ifndef MAXLIB
void arraycopy_setup(void)
{
	/* the object's class: */
    arraycopy_class = class_new(gensym("arraycopy"), (t_newmethod)arraycopy_new,
    	0, sizeof(t_arraycopy), 0, A_GIMME, 0);
#else
void maxlib_arraycopy_setup(void)
{
	/* the object's class: */
    arraycopy_class = class_new(gensym("maxlib_arraycopy"), (t_newmethod)arraycopy_new,
    	0, sizeof(t_arraycopy), 0, A_GIMME, 0);
	class_addcreator((t_newmethod)arraycopy_new, gensym("arraycopy"), A_GIMME, 0);
#endif
	class_addmethod(arraycopy_class, (t_method)arraycopy_copy, gensym("copy"), A_GIMME, 0);
	class_addmethod(arraycopy_class, (t_method)arraycopy_print, gensym("print"), A_FLOAT, 0);
	class_addmethod(arraycopy_class, (t_method)arraycopy_setdest, gensym("dest"), A_SYMBOL, 0);
    class_addsymbol(arraycopy_class, arraycopy_source);
	class_addbang(arraycopy_class, arraycopy_docopy);
	// class_addlist(arraycopy_class, arraycopy_list);
#ifndef MAXLIB
    class_sethelpsymbol(arraycopy_class, gensym("help-arraycopy.pd"));
    post(version);
#else
    class_sethelpsymbol(arraycopy_class, gensym("maxlib/help-arraycopy.pd"));
#endif
}

--- NEW FILE: delta.c ---
/* ------------------------- delta   ------------------------------------------ */
/*                                                                              */
/* Claculate 1st or 2nd order difference.                                       */
/* Written by Olaf Matthes (olaf.matthes at gmx.de)                                */
/* Inspired by code written by Trond Lossius.                                   */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

#include "m_pd.h"
#include <stdio.h>

#define MAXSIZE 32

static char *version = "delta v0.1, written by Olaf Matthes <olaf.matthes at gmx.de>";
 
typedef struct delta
{
  t_object x_ob;
  t_outlet *x_out;                  /* result */
  t_int    x_order;                 /* 1st or second order */
  t_int    x_clearflag;
  t_float  x_delta;                 /* the result */

  t_float  x_prev;                  /* previous value */
  t_float  x_prev2;                 /* value previous to previous value */
} t_delta;

static void delta_clear(t_delta *x)
{
	if(x->x_order == 2)
		x->x_clearflag = 2;
	else
		x->x_clearflag = 1;
	x->x_delta = 0;
}

static void delta_bang(t_delta *x)
{
	outlet_float(x->x_out, x->x_delta);
}

static void delta_float(t_delta *x, t_floatarg f)
{
	if(x->x_order != 2)	/* first order */
	{
		if(x->x_clearflag)
		{
			x->x_prev = f;
			x->x_delta = 0;
			x->x_clearflag = 0;
		}
		else
		{
			x->x_delta = f - x->x_prev;
			x->x_prev = f;
		}
	}
	else
	{
		switch(x->x_clearflag)
		{
			case 0:
				x->x_delta = f - 2*x->x_prev + x->x_prev2;
				x->x_prev2 = x->x_prev;
				x->x_prev = f;
				break;
			case 1:
				x->x_prev = f;
				x->x_clearflag--;
				break;
			case 2:
				x->x_prev2 = f;
				x->x_clearflag--;
				break;
		}
	}
	delta_bang(x);
}

static t_class *delta_class;

static void *delta_new(t_floatarg f)
{
	int i;

    t_delta *x = (t_delta *)pd_new(delta_class);
	x->x_out = outlet_new(&x->x_ob, gensym("float"));

	x->x_order = (int)f;
	if(x->x_order == 2)
		x->x_clearflag = 2;
	else
		x->x_clearflag = 1;
	x->x_delta = 0;

    return (void *)x;
}

#ifndef MAXLIB
void delta_setup(void)
{
    delta_class = class_new(gensym("delta"), (t_newmethod)delta_new,
    	0, sizeof(t_delta), 0, A_DEFFLOAT, 0);
#else
void maxlib_delta_setup(void)
{
    delta_class = class_new(gensym("maxlib_delta"), (t_newmethod)delta_new,
    	0, sizeof(t_delta), 0, A_DEFFLOAT, 0);
#endif
    class_addfloat(delta_class, delta_float);
	class_addbang(delta_class, (t_method)delta_bang);
	class_addmethod(delta_class, (t_method)delta_clear, gensym("clear"), 0);
    class_sethelpsymbol(delta_class, gensym("maxlib/help-delta.pd"));
#ifndef MAXLIB
    class_sethelpsymbol(delta_class, gensym("help-delta.pd"));
    post(version);
#else
	class_addcreator((t_newmethod)delta_new, gensym("delta"), A_DEFFLOAT, 0);
    class_sethelpsymbol(delta_class, gensym("maxlib/help-delta.pd"));
#endif
}


--- NEW FILE: dist.c ---
/* --------------------------  dist  ------------------------------------------ */
/*                                                                              */
/* Distributes incoming data to a changeable list of receive objects.           */
/* Written by Olaf Matthes (olaf.matthes at gmx.de)                                */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */
/*
   connect <symbol list>: store receive objects in list of receivers
   disconnect <symbol list>: remove objects from list of receivers
   clear: clear list of receivers
   send <anything>: send anything to all receives named in the list of receivers  */

#include "m_pd.h"

#include <string.h>
#include <stdio.h>

#define MAX_REC 64		            /* maximum number of receive objects */
#define MAX_ARG 32		            /* maximum number of arguments to pass on */

static char *version = "dist v0.1, written by Olaf Matthes <olaf.matthes at gmx.de>";

static t_class *dist_class;

typedef struct _dist
{
    t_object x_obj;
    t_symbol *x_sym[MAX_REC];       /* names of receiving objects */
	t_int    x_rec;                 /* current number of receiving objects */
	t_int    x_verbose;             /* set to 0 to turn off detailed output in Pd window */
} t_dist;

static void dist_bang(t_dist *x)
{
	int i;

	for(i = 0; i <= x->x_rec; i++)
	{
		if (x->x_sym[i]->s_thing) pd_bang(x->x_sym[i]->s_thing);
	}
}

static void dist_float(t_dist *x, t_float f)
{
	int i;

	for(i = 0; i <= x->x_rec; i++)
	{
		if (x->x_sym[i]->s_thing) pd_float(x->x_sym[i]->s_thing, f);
	}
}

static void dist_symbol(t_dist *x, t_symbol *s)
{
	int i;

	for(i = 0; i <= x->x_rec; i++)
	{
		if (x->x_sym[i]->s_thing) pd_symbol(x->x_sym[i]->s_thing, s);
	}
}

static void dist_pointer(t_dist *x, t_gpointer *gp)
{
	int i;

	for(i = 0; i <= x->x_rec; i++)
	{
		if (x->x_sym[i]->s_thing) pd_pointer(x->x_sym[i]->s_thing, gp);
	}
}

static void dist_list(t_dist *x, t_symbol *s, int argc, t_atom *argv)
{
	int i;

	for(i = 0; i <= x->x_rec; i++)
	{
		if (x->x_sym[i]->s_thing) pd_list(x->x_sym[i]->s_thing, s, argc, argv);
	}
}

static void dist_anything(t_dist *x, t_symbol *s, int argc, t_atom *argv)
{
	int i;

	for(i = 0; i <= x->x_rec; i++)
	{
		if (x->x_sym[i]->s_thing) typedmess(x->x_sym[i]->s_thing, s, argc, argv);
	}
}

	/* send 'anything' to receiver */
static void dist_send(t_dist *x, t_symbol *s, int argc, t_atom *argv)
{
	int i;
	t_atom av[MAX_ARG];		/* the 'new' t_atom without first element */
	t_int ac = argc - 1;    /* the 'new' number of arguments */

	if(ac > MAX_ARG)
	{
		post("dist: too many arguments!");
		return;
	}

	for(i = 1; i < argc; i++)
	{
		av[i - 1] = argv[i];	/* just copy, don't care about types */
	}
		/* send only argument-part to receivers */
	for(i = 0; i <= x->x_rec; i++)
	{
		if (x->x_sym[i]->s_thing) pd_forwardmess(x->x_sym[i]->s_thing, argc, argv);
	}
}

static void dist_connect(t_dist *x, t_symbol *s, int argc, t_atom *argv)
{
	int i, j;
	int exist;
	t_symbol *name;
		/* just append every new receive-name to end of list */
	for(i = 0; i < argc; i++)
	{
		exist = 0;
		if(x->x_rec == MAX_REC - 1)
		{
			post("dist: too many connections in use!");
			return;
		}
		name = atom_getsymbolarg(i, argc, argv);
		for(j = 0; j <= x->x_rec; j++)
		{	
				/* check if the name already exists */
			if(x->x_sym[j] == name)
			{
				post("dist: \"%s\" already exists in list of receivers", name->s_name);
				exist = 1;	/* indicate that it _does_ exist */
			}
		}	
			/* add it in case it's a new one */
		if(!exist)
		{
			x->x_rec++;
			x->x_sym[x->x_rec] = name;
			if(x->x_verbose)post("dist: \"%s\" added to list of receivers", x->x_sym[x->x_rec]->s_name);
		}
	}
}

static void dist_disconnect(t_dist *x, t_symbol *s, int argc, t_atom *argv)
{
		/* need to rearrange list in order to get rid of empty entries */
	int i, j, k;
	int done;
	t_symbol *name;

	for(i = 0; i < argc; i++)
	{
		name = atom_getsymbolarg(i, argc, argv);	/* the one we're going to remove */
		done = 0;                                   /* not yet removed */
		for(j = 0; j <= x->x_rec; j++)              /* search for it... */
		{
			if(x->x_sym[j] == name)
			{
				x->x_rec--;
				if(x->x_verbose)post("dist: \"%s\" removed from list of receivers", x->x_sym[j]->s_name);
				x->x_sym[j] = NULL;	/* delete entry */
					/* rearrange list now: move entries to close the gap */
				for(k = j; k <= x->x_rec; k++)
				{
					x->x_sym[k] = x->x_sym[k + 1];
				}
				done = 1;							/* removed successfully */
			}
		}
		if(!done)post("dist: \"%s\" not in list of receivers, ignored", name->s_name);
	}
}

static void dist_clear(t_dist *x)
{
	int i;

	for(i = 0; i < MAX_REC; i++)
	{
		x->x_sym[i] = NULL;
	}
	x->x_rec = -1;
}

static void dist_print(t_dist *x)
{
	int i;

	if(x->x_rec == 0)
	{
		post("dist: there is one object in receiver list:");
	} 
	else if(x->x_rec > 0)
	{
		post("dist: there are %d objects in receiver list:", x->x_rec + 1);
	} 
	else
	{
		post("dist: there are no objects in receiver list");
		return;
	}

	for(i = 0; i <= x->x_rec; i++)
	{
		post("      \"%s\"", x->x_sym[i]->s_name);
	}
}

static void *dist_new(t_symbol *s, int argc, t_atom *argv)
{
	int i;

    t_dist *x = (t_dist *)pd_new(dist_class);

	x->x_rec = -1;
	x->x_verbose = 1;	/* display info on connect/disconnect */
	for(i = 0; i < argc; i++)
	{
		x->x_sym[i] = atom_getsymbolarg(i, argc, argv);
		x->x_rec++;
	}
    return (x);
}

#ifndef MAXLIB
void dist_setup(void)
{
    dist_class = class_new(gensym("dist"), (t_newmethod)dist_new, 0,
    	sizeof(t_dist), 0, A_GIMME, 0);
#else
void maxlib_dist_setup(void)
{
    dist_class = class_new(gensym("maxlib_dist"), (t_newmethod)dist_new, 0,
    	sizeof(t_dist), 0, A_GIMME, 0);
#endif
    class_addcreator((t_newmethod)dist_new, gensym("d"), A_GIMME, 0);
    class_addbang(dist_class, dist_bang);
    class_addfloat(dist_class, dist_float);
    class_addsymbol(dist_class, dist_symbol);
    class_addpointer(dist_class, dist_pointer);
    class_addlist(dist_class, dist_list);
	class_addmethod(dist_class, (t_method)dist_connect, gensym("connect"), A_GIMME, 0);
	class_addmethod(dist_class, (t_method)dist_disconnect, gensym("disconnect"), A_GIMME, 0);
	class_addmethod(dist_class, (t_method)dist_clear, gensym("clear"), 0);
	class_addmethod(dist_class, (t_method)dist_print, gensym("print"), 0);
	class_addmethod(dist_class, (t_method)dist_send, gensym("send"), A_GIMME, 0);
    class_addanything(dist_class, dist_anything);
#ifndef MAXLIB
	class_sethelpsymbol(dist_class, gensym("help-dist.pd"));
    post(version);
#else
	class_addcreator((t_newmethod)dist_new, gensym("dist"), A_GIMME, 0);
	class_sethelpsymbol(dist_class, gensym("maxlib/help-dist.pd"));
#endif
}

--- NEW FILE: scale.c ---
/* -------------------------  scale  ------------------------------------------ */
/*                                                                              */
/* Scales input to lie within an output range.                                  */
/* Written by Olaf Matthes <olaf.matthes at gmx.de>                                */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

#include "m_pd.h"
#include <stdio.h>
#include <math.h>

static char *version = "scale v0.2, written by Olaf Matthes <olaf.matthes at gmx.de>";
 
typedef struct scale
{
  t_object x_ob;
  t_float  x_f;                    /* current input value */
  t_float  x_il;                   /* low border of input range */
  t_float  x_ih;                   /* high border of input range */
  t_float  x_ol;                   /* low border of output range */
  t_float  x_oh;                   /* high border of output range */
  t_float  x_logcoeff;             /* log-coefficient */
  t_outlet *x_outlet1;             /* result */
} t_scale;

static void scale_float(t_scale *x, t_floatarg f)
{
	t_float ir = x->x_ih - x->x_il;
	t_float or = x->x_oh - x->x_ol;
	double oq;
	double result;
	double k;
	if(ir == 0)
	{
		post("scale: input range must not be 0");
		return;
	}
	/* we accept an output range of 0 in case someone really wants this */
	if(!x->x_logcoeff)	/* linear */
	{
		k = (or / ir);
		result = ((f - x->x_il) * k) + x->x_ol;
	}
	else	/* logarythmical scale */
	{
		oq = x->x_oh / x->x_ol;
	//	k = (log((double)oq)/log(x->x_logcoeff))/((double)ir);
		k = log((double)oq)/((double)ir);

		if(x->x_ol)
		{
		//	result = (double)x->x_ol*exp(k*(double)(f - x->x_il)*log(x->x_logcoeff));
			result = (double)x->x_ol*exp(k*(double)(f - x->x_il));
		}
		else
		{
				/* in case the low output is 0 we have to cheat... */
				/* okay, here's the chating: we calculate for a lower out limit  
				   of 1 and remove this shift after the calculation */
			result = ((double)(x->x_ol+1)*exp(k*(double)(f - x->x_il)))-1.0;
		}
	}

	x->x_f = f;         /* save current input value */

	outlet_float(x->x_outlet1, result);
}

static void scale_bang(t_scale *x)
{
	scale_float(x, x->x_f);	/* recalculate result */
}

static t_class *scale_class;

static void *scale_new(t_floatarg fil, t_floatarg fih, t_floatarg fol, t_floatarg foh, t_floatarg flc)
{
    t_scale *x = (t_scale *)pd_new(scale_class);

	floatinlet_new(&x->x_ob, &x->x_il);
	floatinlet_new(&x->x_ob, &x->x_ih);
	floatinlet_new(&x->x_ob, &x->x_ol);
	floatinlet_new(&x->x_ob, &x->x_oh);
	floatinlet_new(&x->x_ob, &x->x_logcoeff);

	x->x_outlet1 = outlet_new(&x->x_ob, gensym("float"));

		/* default values taken from Max's scale */
	x->x_il = fil;
	x->x_ih = fih;
	if(!x->x_ih)x->x_ih = 127.0;
	x->x_ol = fol;
	x->x_oh = foh;
	if(!x->x_oh)x->x_oh = 1.0;
	x->x_logcoeff = flc;
	x->x_f = 0;

    return (void *)x;
}

#ifndef MAXLIB
void scale_setup(void)
{
    scale_class = class_new(gensym("scale"), (t_newmethod)scale_new,
    	0, sizeof(t_scale), 0, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0);
    class_addfloat(scale_class, scale_float);
    class_addbang(scale_class, scale_bang);
    class_sethelpsymbol(scale_class, gensym("help-scale.pd"));
    post(version);
#else
void maxlib_scale_setup(void)
{
    scale_class = class_new(gensym("maxlib_scale"), (t_newmethod)scale_new,
    	0, sizeof(t_scale), 0, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0);
	class_addcreator((t_newmethod)scale_new, gensym("scale"), A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0);
    class_addfloat(scale_class, scale_float);
    class_addbang(scale_class, scale_bang);
    class_sethelpsymbol(scale_class, gensym("maxlib/help-scale.pd"));
#endif
}


--- NEW FILE: remote.c ---
/* ------------------------  remote  ------------------------------------------ */
/*                                                                              */
/* Send data to receive obejct <name>.                                          */
/* Written by Olaf Matthes (olaf.matthes at gmx.de)                                */
/* Get source at http://www.akustische-kunst.de/puredata/                       */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

#include "m_pd.h"

#include <string.h>
#include <stdio.h>

#define MAX_REC 64		            /* maximum number of receive objects */
#define MAX_ARG 64		            /* maximum number of arguments to pass on */

static char *version = "remote v0.2, written by Olaf Matthes <olaf.matthes at gmx.de>";

static t_class *remote_class;

typedef struct _remote
{
    t_object x_obj;
	t_symbol *x_prefix;
	t_int    x_prepend;
} t_remote;

	/* send 'anything' to receiver */
static void remote_anything(t_remote *x, t_symbol *s, int argc, t_atom *argv)
{
	int i;
	t_atom av[MAX_ARG];		/* the 'new' t_atom without first element */
	t_int ac = argc - 1;    /* the 'new' number of arguments */
	char mysym[MAXPDSTRING];
	t_symbol *target;

	if(argc < 1)			/* need <name> <data> */
	{
		post("remote: too few arguments!");
		return;
	}
	if(ac > MAX_ARG)
	{
		post("remote: too many arguments!");
		return;
	}

	for(i = 1; i < argc; i++)
	{
		av[i - 1] = argv[i];	/* just copy, don't care about types */
	}
		/* send only argument-part to receivers */
	if(x->x_prepend)
	{
		sprintf(mysym,"%s%s", x->x_prefix->s_name, s->s_name);
		target = gensym(mysym);
		if (target->s_thing) pd_forwardmess(target->s_thing, argc, argv);
	}
	else
		if (s->s_thing) pd_forwardmess(s->s_thing, argc, argv);
}

static void *remote_new(t_symbol *s)
{
    t_remote *x = (t_remote *)pd_new(remote_class);

	x->x_prefix = s;
	if(x->x_prefix) x->x_prepend = 1;
	else x->x_prepend = 0;

    return (x);
}

#ifndef MAXLIB
void remote_setup(void)
{
    remote_class = class_new(gensym("remote"), (t_newmethod)remote_new, 0,
    	sizeof(t_remote), 0, A_DEFSYM, 0);
    class_addanything(remote_class, remote_anything);
	class_sethelpsymbol(remote_class, gensym("help-remote.pd"));
    post(version);
}
#else
void maxlib_remote_setup(void)
{
    remote_class = class_new(gensym("maxlib_remote"), (t_newmethod)remote_new, 0,
    	sizeof(t_remote), 0, A_DEFSYM, 0);
	class_addcreator((t_newmethod)remote_new, gensym("remote"), A_DEFSYM, 0);
    class_addanything(remote_class, remote_anything);
	class_sethelpsymbol(remote_class, gensym("maxlib/help-remote.pd"));
}
#endif

--- NEW FILE: fifo.c ---
/* ---------------------------- fifo ------------------------------------------ */
/*                                                                              */
/* Fifo buffer of floats, empties itselfe on every bang (in order of coming in) */
/* Written by Olaf Matthes (olaf.matthes at gmx.de)                                */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* Fifi-code based St. Rainstick fifi.c for Max,                                */
/* copyright St. Rainstick, Amsterdam 1995                                      */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

#include "m_pd.h"

static char *version = "fifo v0.1, written by Olaf Matthes <olaf.matthes at gmx.de>";

typedef struct fifo
{
	t_object d_ob;
	t_float *getal;
	t_int count, end, size;
	t_outlet *out;

}t_fifo;

static t_class *fifo_class;

static void fifo_int(t_fifo *x, t_floatarg n)
{
	x->getal[x->count] = n;
	x->count = (x->count + 1) % x->size;
}

static void fifo_bang(t_fifo *x)
{
	if (x->end != x->count){
		outlet_float(x->out,x->getal[x->end]);
		x->end = (x->end + 1) % x->size;
	}
}

static void fifo_free(t_fifo *x)
{
	freebytes(x->getal, x->size * sizeof(t_float));
}

static void *fifo_new(t_floatarg n)
{

	t_fifo *x = (t_fifo *)pd_new(fifo_class);
	if (n<10) n = 10;
	x->size = (t_int)n;
	x->end = 0;
	x->count = 0;
	x->getal = (t_float *)getbytes(x->size * sizeof(t_float));
	x->out = outlet_new(&x->d_ob, gensym("float"));
		
	return (x);
}

#ifndef MAXLIB
void fifo_setup(void)
{
    fifo_class = class_new(gensym("fifo"), (t_newmethod)fifo_new,
    	(t_method)fifo_free, sizeof(t_fifo), 0, A_DEFFLOAT, 0);
    class_addfloat(fifo_class, fifo_int);
	class_addbang(fifo_class, fifo_bang);
    class_sethelpsymbol(fifo_class, gensym("help-fifo.pd"));
    post(version);
}
#else
void maxlib_fifo_setup(void)
{
    fifo_class = class_new(gensym("maxlib_fifo"), (t_newmethod)fifo_new,
    	(t_method)fifo_free, sizeof(t_fifo), 0, A_DEFFLOAT, 0);
	class_addcreator((t_newmethod)fifo_new, gensym("fifo"), A_DEFFLOAT, 0);
    class_addfloat(fifo_class, fifo_int);
	class_addbang(fifo_class, fifo_bang);
    class_sethelpsymbol(fifo_class, gensym("maxlib/help-fifo.pd"));
}
#endif

--- NEW FILE: cauchy.c ---
/* ---------------------------- rand_cauchy ----------------------------------- */
/*                                                                              */
/* rand_cauchy generates a Cauchy distributed random variable.                  */
/* Written by Olaf Matthes (olaf.matthes at gmx.de)                                */
/* Based on code found in Dodge/Jerse "Computer Music"                          */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

#include "m_pd.h"
#include <stdlib.h>
#include <time.h>
#include <math.h>

#define fran()         (t_float)rand()/(t_float)RAND_MAX
#ifndef M_PI
#define M_PI           3.1415927
#endif

static char *version = "cauchy v0.1, generates a Cauchy distributed random variable\n"
                       "             with a spread governed by to parameter 'aplha',\n"
                       "             written by Olaf Matthes <olaf.matthes at gmx.de>";

/* -------------------------- rand_cauchy ------------------------------ */

static t_class *rand_cauchy_class;

typedef struct _rand_cauchy
{
    t_object x_obj;
	t_float  x_alpha;
} t_rand_cauchy;

static void *rand_cauchy_new(t_floatarg f)
{
    t_rand_cauchy *x = (t_rand_cauchy *)pd_new(rand_cauchy_class);
    srand( (unsigned)time( NULL ) );
    floatinlet_new(&x->x_obj, &x->x_alpha);
    outlet_new(&x->x_obj, &s_float);
	x->x_alpha = f;
    return (x);
}

static void rand_cauchy_bang(t_rand_cauchy *x)
{
	t_float u;
	do
	{
		u = fran();
	}
	while(u == 0.5);
	u *= M_PI;
    outlet_float(x->x_obj.ob_outlet, x->x_alpha*tan(u));
}

#ifndef MAXLIB
void cauchy_setup(void)
{
    rand_cauchy_class = class_new(gensym("cauchy"), (t_newmethod)rand_cauchy_new, 0,
    	sizeof(t_rand_cauchy), 0, A_DEFFLOAT, 0);
    class_addbang(rand_cauchy_class, rand_cauchy_bang);
	class_sethelpsymbol(rand_cauchy_class, gensym("help-cauchy.pd"));
    post(version);
#else
void maxlib_cauchy_setup(void)
{
    rand_cauchy_class = class_new(gensym("maxlib_cauchy"), (t_newmethod)rand_cauchy_new, 0,
    	sizeof(t_rand_cauchy), 0, A_DEFFLOAT, 0);
    class_addbang(rand_cauchy_class, rand_cauchy_bang);
	class_addcreator((t_newmethod)rand_cauchy_new, gensym("cauchy"), A_DEFFLOAT, 0);
	class_sethelpsymbol(rand_cauchy_class, gensym("maxlib/help-cauchy.pd"));
#endif
}

--- NEW FILE: sync.c ---
/* -------------------------  sync  ------------------------------------------- */
/*                                                                              */
/* syncronises outputs depending on inputs.                                     */
/* Written by Olaf Matthes <olaf.matthes at gmx.de>                                */
/* Based on 'sync' from jMax.                                                   */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

#include "m_pd.h"
#include <stdio.h>
#include <math.h>

#define SYNC_MAX_SIZE (int)(sizeof(unsigned int) * 8)

static char *version = "sync v0.1, written by Olaf Matthes <olaf.matthes at gmx.de>\n"
                       "           based on sync from jMax";

typedef struct sync
{
  t_object x_ob;
  t_float  x_min;                  /* low border of input range */
  t_float  x_max;                  /* high border of input range */
  t_outlet *x_outlet[SYNC_MAX_SIZE];

  t_int        x_n;
  unsigned int x_trigger; /* control bits: trigger on input at given inlets */
  unsigned int x_require; /* control bits: require input on given inlets */
  unsigned int x_reset; /* control bits: reset memory of given inputs after on each input */
  unsigned int x_wait; /* status bits: wait for input at given inlet before output */
  t_atom       x_a[SYNC_MAX_SIZE];
  enum {mode_all, mode_select} mode;
} t_sync;

typedef struct proxy
{
	t_object obj;
	t_int index;		/* number of proxy inlet(s) */
	t_sync *x;		/* we'll put the other struct in here */
} t_proxy;

static void sync_output(t_sync *x)
{
	int i;

	for(i=x->x_n-1; i>=0; i--)
		if(x->x_a[i].a_type != A_SEMI)
			outlet_list(x->x_outlet[i], NULL, 1, x->x_a + i);
}

static void sync_input(t_proxy *p, t_symbol *s, int ac, t_atom *at)
{
	t_sync *x = (t_sync *)(p->x);
	int winlet = p->index;

	if(ac)
	{
		unsigned int bit = 1 << winlet;

		x->x_a[winlet] = at[0];

		x->x_wait &= ~bit;

		if(!x->x_wait && (x->x_trigger & bit))
		{
			sync_output(x);
			x->x_wait |= x->x_reset & x->x_require;
		}
	}
}

static void sync_float_input(t_proxy *p, t_floatarg f)
{
	t_sync *x = (t_sync *)(p->x);
	int winlet = p->index;

	{
		unsigned int bit = 1 << winlet;

		SETFLOAT(x->x_a + winlet, f);

		x->x_wait &= ~bit;

		if(!x->x_wait && (x->x_trigger & bit))
		{
			sync_output(x);
			x->x_wait |= x->x_reset & x->x_require;
		}
	}
}

static void sync_set_bits(unsigned int *bits, int n, t_atom *at, int sign)
{
	if(at->a_type == A_SYMBOL)
	{
		t_symbol *mode = atom_getsymbol(at);

		if(mode == gensym("all"))
			*bits = (1 << n) - 1;
		else if(mode == gensym("none"))
			*bits = 0;
	}
	else if(at->a_type == A_FLOAT)
	{
		int in = (int)atom_getfloat(at) * sign;

		if(in >= 0 && in < n)
			*bits = 1 << in;
	}
	else if(at->a_type == A_GIMME)
	{
		int size = n;
		int i;

		*bits = 0;

		for(i=0; i<size; i++)
		{
			if(at[i].a_type == A_FLOAT)
			{
				int in = atom_getfloatarg(i, size, at) * sign;

				if(in >= 0 && in < n)
				*bits |= 1 << in;
			}  
		}
	}
}

static void sync_set_trigger(t_sync *x, t_symbol *s, int ac, t_atom *at)
{
	sync_set_bits(&x->x_trigger, x->x_n, at, 1);
}

static void sync_set_require(t_sync *x, t_symbol *s, int ac, t_atom *at)
{
  unsigned int once = 0;

  sync_set_bits(&x->x_require, x->x_n, at, 1);
  sync_set_bits(&once, x->x_n, at, -1);

  x->x_reset = ~once;
  x->x_wait = x->x_require | once;
}

static void sync_set_mode(t_sync *x, t_symbol *mode)
{
	if(mode == gensym("any"))
	{
		x->x_trigger = (1 << x->x_n) - 1;
		x->x_reset = 0;
		x->x_require = 0;
	}
	else if(mode == gensym("all"))
		x->x_trigger = x->x_require = x->x_reset = x->x_wait = (1 << x->x_n) - 1;
	else if(mode == gensym("left"))
	{
		x->x_trigger = 1;
		x->x_reset = 0;
		x->x_require = 0;
	}
	else if(mode == gensym("right"))
	{
		x->x_trigger = (1 << (x->x_n - 1));
		x->x_reset = 0;
		x->x_require = 0;
	}

	x->x_wait = x->x_require;
}

static void sync_float(t_sync *x, t_floatarg f)
{
	unsigned int bit = 1 << 0;

	SETFLOAT(x->x_a, f);

	x->x_wait &= ~bit;

	if(!x->x_wait && (x->x_trigger & bit))
	{
		sync_output(x);
		x->x_wait |= x->x_reset & x->x_require;
	}
}

static t_class *sync_class;
static t_class *proxy_class;

static void *sync_new(t_symbol *s, int ac, t_atom *at)
{
	int n = 0;
	int i;
    t_sync *x = (t_sync *)pd_new(sync_class);
	t_proxy *inlet[SYNC_MAX_SIZE];

		/* void state - we fill with SEMI and treat this as 'void' */
	for(i=0; i<SYNC_MAX_SIZE; i++)
		SETSEMI(x->x_a + i);

	if(ac == 1)
	{
		if(at->a_type == A_FLOAT)
		{
			n = atom_getfloat(at);

			if(n < 2) 
				n = 2;
			else if(n > SYNC_MAX_SIZE)
				n = SYNC_MAX_SIZE;
		}
		else
		{
			post("sync: wrong argument");
			return (0);
		}
	}
	else if(ac > 1)
	{
		if(ac > SYNC_MAX_SIZE)
			ac = SYNC_MAX_SIZE;

		n = ac;

		for(i=0; i<n; i++)
			x->x_a[i] = at[i];
	}

	x->x_n = n;
	x->x_trigger = x->x_require = x->x_reset = x->x_wait = (1 << n) - 1;

	x->x_outlet[0] = outlet_new(&x->x_ob, gensym("list"));

	for(i=1; i<n; i++)
	{
		inlet[i] = (t_proxy *)pd_new(proxy_class);	/* create the proxy inlet */
		inlet[i]->x = x;		/* make t_sync *x visible to the proxy inlets */
		inlet[i]->index = i;	/* remember it's number */
			/* it belongs to the object t_sync but the destination is t_proxy */
		inlet_new(&x->x_ob, &inlet[i]->obj.ob_pd, 0,0);

		x->x_outlet[i] = outlet_new(&x->x_ob, gensym("list"));
	}

    return (void *)x;
}

#ifndef MAXLIB
void sync_setup(void)
{
    sync_class = class_new(gensym("sync"), (t_newmethod)sync_new,
    	0, sizeof(t_sync), 0, A_GIMME, 0);
#else
void maxlib_sync_setup(void)
{
    sync_class = class_new(gensym("maxlib_sync"), (t_newmethod)sync_new,
    	0, sizeof(t_sync), 0, A_GIMME, 0);
#endif
		/* a class for the proxy inlet: */
	proxy_class = class_new(gensym("maxlib_sync_proxy"), NULL, NULL, sizeof(t_proxy),
		CLASS_PD|CLASS_NOINLET, A_NULL);

	class_addfloat(proxy_class, sync_float_input);
	class_addanything(proxy_class, sync_input);

    class_addfloat(sync_class, sync_float);
	class_addmethod(sync_class, (t_method)sync_set_trigger, gensym("trigger"), A_GIMME, 0);
	class_addmethod(sync_class, (t_method)sync_set_require, gensym("require"), A_GIMME, 0);
	class_addmethod(sync_class, (t_method)sync_set_mode, gensym("mode"), A_SYMBOL, 0);
#ifndef MAXLIB
    class_sethelpsymbol(sync_class, gensym("help-sync.pd"));
    post(version);
#else
	class_addcreator((t_newmethod)sync_new, gensym("sync"), A_GIMME, 0);
    class_sethelpsymbol(sync_class, gensym("maxlib/help-sync.pd"));
#endif
}


--- NEW FILE: listfifo.c ---
/* ---------------------------- listfifo -------------------------------------- */
/*                                                                              */
/* Fifo buffer of lists, empties itselfe on every bang (in order of coming in)  */
/* Written by Olaf Matthes (olaf.matthes at gmx.de)                                */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

#include "m_pd.h"

#define MAX_ELEM  256           /* maximum number of list elements to pass on */

static char *version = "listfifo v0.1, written by Olaf Matthes <olaf.matthes at gmx.de>";

typedef struct listfifo
{
	t_object d_ob;
	t_atom *getal;				/* stores the list values */
	t_int  *getsize;			/* stores the number of elements in list */
	t_int count, end, size;
	t_outlet *out;

}t_listfifo;

static t_class *listfifo_class;

static void listfifo_list(t_listfifo *x, t_symbol *s, int argc, t_atom *argv)
{
	int i;
	if(argc > MAX_ELEM)
	{
		post("listfifo: to many arguments in list, ignored");
		return;
	}
	for(i = 0; i < argc; i++)
		x->getal[(x->count * MAX_ELEM) + i] = argv[i];
	x->getsize[x->count] = argc;
	x->count = (x->count + 1) % x->size;
	// post("got %d elements", argc);
}

static void listfifo_bang(t_listfifo *x)
{
	// post("count = %d, end = %d", x->count, x->end);
	if (x->end != x->count){
		outlet_list(x->out, NULL, x->getsize[x->end], x->getal+(x->end * MAX_ELEM));
		x->end = (x->end + 1) % x->size;
	}
}

static void listfifo_free(t_listfifo *x)
{
	freebytes(x->getsize, x->size * sizeof(t_int));
	freebytes(x->getal, x->size * sizeof(t_float) * MAX_ELEM);
}

static void *listfifo_new(t_floatarg n)
{
	int i;

	t_listfifo *x = (t_listfifo *)pd_new(listfifo_class);
	if (n<10) n = 10;
	x->size = (t_int)n;
	x->end = 0;
	x->count = 0;
	x->getsize = (t_int *)getbytes(x->size * sizeof(t_int));
	x->getal = (t_atom *)getbytes(x->size * sizeof(t_atom) * MAX_ELEM);
	x->out = outlet_new(&x->d_ob, gensym("list"));
		
	return (x);
}

#ifndef MAXLIB
void listfifo_setup(void)
{
    listfifo_class = class_new(gensym("listfifo"), (t_newmethod)listfifo_new,
    	(t_method)listfifo_free, sizeof(t_listfifo), 0, A_DEFFLOAT, 0);
	class_addbang(listfifo_class, listfifo_bang);
    class_addlist(listfifo_class, listfifo_list);
    class_sethelpsymbol(listfifo_class, gensym("help-listfifo.pd"));
    post(version);
}
#else
void maxlib_listfifo_setup(void)
{
    listfifo_class = class_new(gensym("maxlib_listfifo"), (t_newmethod)listfifo_new,
    	(t_method)listfifo_free, sizeof(t_listfifo), 0, A_DEFFLOAT, 0);
	class_addcreator((t_newmethod)listfifo_new, gensym("listfifo"), A_DEFFLOAT, 0);
	class_addbang(listfifo_class, listfifo_bang);
    class_addlist(listfifo_class, listfifo_list);
    class_sethelpsymbol(listfifo_class, gensym("maxlib/help-listfifo.pd"));
}
#endif

--- NEW FILE: netclient.c ---
/* --------------------------  netclient  ------------------------------------- */
/*                                                                              */
/* Extended 'netsend', connects to 'netserver'.                                 */
/* Uses child thread to connect to server. Thus needs pd0.35-test17 or later.   */
/* Written by Olaf Matthes (olaf.matthes at gmx.de)                                */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* 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.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */
/* Changes: use circular message buffer for receive */
/*          using pollfunction instead of clock (suggested by HCS) */

#ifdef PD_0_37
#include "m_pd.h"
#include "s_stuff.h"
#endif
#include "m_imp.h"

#include <sys/types.h>
#include <string.h>
#include <pthread.h>
#ifdef UNIX
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/errno.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <unistd.h>
#define SOCKET_ERROR -1
#else
#include <winsock.h>
#endif

#define INBUFSIZE 4096	/* maximum numbers of characters to read */

static char *version = "netclient v0.3, written by Olaf Matthes <olaf.matthes at gmx.de>";

static t_class *netclient_class;
static t_binbuf *inbinbuf;

typedef struct _netclient
{
    t_object x_obj;
	t_clock *x_clock;
	t_outlet *x_outdata;
	t_outlet *x_outconnect;
    int x_fd;
	char *x_hostname;
	int x_connectstate;
	int x_port;
    int x_protocol;
	char x_inbuf[INBUFSIZE];	/* circular message buffer for received data */
	int x_intail;
	int x_inhead;
		/* multithread stuff */
	pthread_t x_threadid;            /* id of child thread */
	pthread_attr_t x_threadattr;     /* attributes of child thread */
} t_netclient;

#ifdef USE_CIRCULAR
static t_binbuf *inbinbuf;
#endif

	/* one lonlely prototype */
static void netclient_rcv(t_netclient *x);


	/* get's called when connection has been made */
static void netclient_tick(t_netclient *x)
{
    outlet_float(x->x_outconnect, 1);
		/* add pollfunction for checking for input */
	sys_addpollfn(x->x_fd, (t_fdpollfn)netclient_rcv, x);
}

static void *netclient_child_connect(void *w)
{
	t_netclient *x = (t_netclient*) w;
    struct sockaddr_in server;
    struct hostent *hp;
    int sockfd;
    int portno = x->x_port;
    if (x->x_fd >= 0)
    {
    	error("netclient_connect: already connected");
    	return (x);
    }

    	/* create a socket */
    sockfd = socket(AF_INET, x->x_protocol, 0);
#if 0
    fprintf(stderr, "send socket %d\n", sockfd);
#endif
    if (sockfd < 0)
    {
    	sys_sockerror("socket");
    	return (x);
    }
		/* connect socket using hostname provided in command line */
    server.sin_family = AF_INET;
    hp = gethostbyname(x->x_hostname);
    if (hp == 0)
    {
		post("bad host?\n");
		return (x);
    }
    memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length);

		/* assign client port number */
    server.sin_port = htons((u_short)portno);

    post("connecting to port %d", portno);
		/* try to connect */
    if (connect(sockfd, (struct sockaddr *) &server, sizeof (server)) < 0)
    {
    	sys_sockerror("connecting stream socket");
    	sys_closesocket(sockfd);
    	return (x);
    }
    x->x_fd = sockfd;
		/* outlet_float is not threadsafe ! */
    // outlet_float(x->x_obj.ob_outlet, 1);
	x->x_connectstate = 1;
		/* use callback instead to set outlet */
	clock_delay(x->x_clock, 0);
	return (x);
}

static void netclient_connect(t_netclient *x, t_symbol *hostname,
    t_floatarg fportno)
{
		/* we get hostname and port and pass them on
		to the child thread that establishes the connection */
	x->x_hostname = hostname->s_name;
	x->x_port = fportno;
	x->x_connectstate = 0;
		/* start child thread */
	if(pthread_create( &x->x_threadid, &x->x_threadattr, netclient_child_connect, x) < 0)
		post("netclient: could not create new thread");
}

static void netclient_disconnect(t_netclient *x)
{
    if (x->x_fd >= 0)
    {
		sys_rmpollfn(x->x_fd);
    	sys_closesocket(x->x_fd);
    	x->x_fd = -1;
		x->x_connectstate = 0;
    	outlet_float(x->x_outconnect, 0);
    }
}

static void netclient_send(t_netclient *x, t_symbol *s, int argc, t_atom *argv)
{
    if (x->x_fd >= 0)
    {
	t_binbuf *b = binbuf_new();
	char *buf, *bp;
	int length, sent;
	t_atom at;
	binbuf_add(b, argc, argv);
	SETSEMI(&at);
	binbuf_add(b, 1, &at);
	binbuf_gettext(b, &buf, &length);
	for (bp = buf, sent = 0; sent < length;)
	{
	    static double lastwarntime;
	    static double pleasewarn;
	    double timebefore = sys_getrealtime();
    	    int res = send(x->x_fd, buf, length-sent, 0);
    	    double timeafter = sys_getrealtime();
    	    int late = (timeafter - timebefore > 0.005);
    	    if (late || pleasewarn)
    	    {
    	    	if (timeafter > lastwarntime + 2)
    	    	{
    	    	     post("netclient blocked %d msec",
    	    	     	(int)(1000 * ((timeafter - timebefore) + pleasewarn)));
    	    	     pleasewarn = 0;
    	    	     lastwarntime = timeafter;
    	    	}
    	    	else if (late) pleasewarn += timeafter - timebefore;
    	    }
    	    if (res <= 0)
    	    {
    		sys_sockerror("netclient");
    		netclient_disconnect(x);
    		break;
    	    }
    	    else
    	    {
    		sent += res;
    		bp += res;
    	    }
	}
	t_freebytes(buf, length);
	binbuf_free(b);
    }
    else error("netclient: not connected");
}

    /* this is in a separately called subroutine so that the buffer isn't
    sitting on the stack while the messages are getting passed. */
static int netclient_doread(t_netclient *x)
{
    char messbuf[INBUFSIZE], *bp = messbuf;
    int indx;
    int inhead = x->x_inhead;
    int intail = x->x_intail;
    char *inbuf = x->x_inbuf;
    if (intail == inhead) return (0);
    for (indx = intail; indx != inhead; indx = (indx+1)&(INBUFSIZE-1))
    {
    	char c = *bp++ = inbuf[indx];
    	if (c == ';' && (!indx || inbuf[indx-1] != '\\'))
    	{
    	    intail = (indx+1)&(INBUFSIZE-1);
    	    binbuf_text(inbinbuf, messbuf, bp - messbuf);
    	    x->x_inhead = inhead;
    	    x->x_intail = intail;
    	    return (1);
    	}
    }
    return (0);
}

static void netclient_rcv(t_netclient *x)
{
	int fd = x->x_fd;
	int ret;
    char resp[INBUFSIZE];
	fd_set readset;
	fd_set exceptset;
    struct timeval ztout;
		/* output data */
	t_binbuf *binbuf;
    t_atom messbuf[1024];
    int msg, natom;
    t_atom *at;
	int i;
	
	if(x->x_connectstate)
	{
			/* check if we can read/write from/to the socket */
		FD_ZERO(&readset);
		FD_ZERO(&exceptset);
		FD_SET(fd, &readset );
		FD_SET(fd, &exceptset );

		ztout.tv_sec = 0;
		ztout.tv_usec = 0;
		ret = select(fd+1, &readset, NULL, &exceptset, &ztout);
		if(ret < 0)
		{
			error("netclient: can not read from socket");
			sys_closesocket(fd);
			return;
		}
		if(FD_ISSET(fd, &readset) || FD_ISSET(fd, &exceptset))
		{
			int readto = (x->x_inhead >= x->x_intail ? INBUFSIZE : x->x_intail-1);

			ret = recv(fd, x->x_inbuf + x->x_inhead, readto - x->x_inhead, 0);
			if (ret < 0)
			{
				sys_sockerror("recv");
				sys_rmpollfn(fd);
	    		sys_closesocket(fd);
			}
			else if (ret == 0)
			{
	    		post("netclient: connection closed on socket %d", fd);
				sys_rmpollfn(fd);
	    		sys_closesocket(fd);
			}
			else
			{
    			x->x_inhead += ret;
    			if (x->x_inhead >= INBUFSIZE) x->x_inhead = 0;
    			while (netclient_doread(x))
				{
					/* output binbuf */
					natom = binbuf_getnatom(inbinbuf);	/* get number of atoms */
					at = binbuf_getvec(inbinbuf);	/* get the atoms */
						/* now split it into several parts at every A_SEMI because
						   we probably received more than one message at a time     */
					for (msg = 0; msg < natom;)
					{
    					int emsg;
						for (emsg = msg; emsg < natom && at[emsg].a_type != A_COMMA
							&& at[emsg].a_type != A_SEMI; emsg++);

						if (emsg > msg)
						{
							int ii;
							for (ii = msg; ii < emsg; ii++)
	    						if (at[ii].a_type == A_DOLLAR || at[ii].a_type == A_DOLLSYM)
								{
	    							pd_error(x, "netserver: -- got dollar sign in message");
									goto nodice;
								}
							if (at[msg].a_type == A_FLOAT)
							{
	    						if (emsg > msg + 1)
									outlet_list(x->x_outdata, 0, emsg-msg, at + msg);
								else outlet_float(x->x_outdata, at[msg].a_w.w_float);
							}
							else if (at[msg].a_type == A_SYMBOL)
	    						outlet_anything(x->x_outdata, at[msg].a_w.w_symbol,
								emsg-msg-1, at + msg + 1);
						}
						nodice:
    						msg = emsg + 1;
					}
 	    		}
			}
		}
	}
	else post("netclient: not connected");
}

static void *netclient_new(t_floatarg udpflag)
{
    t_netclient *x = (t_netclient *)pd_new(netclient_class);
    x->x_outdata = outlet_new(&x->x_obj, &s_anything);	/* received data */
    x->x_outconnect = outlet_new(&x->x_obj, &s_float);	/* connection state */
    x->x_clock = clock_new(x, (t_method)netclient_tick);
	inbinbuf = binbuf_new();
    x->x_fd = -1;
    x->x_protocol = (udpflag != 0 ? SOCK_DGRAM : SOCK_STREAM);
		/* prepare child thread */
    if(pthread_attr_init(&x->x_threadattr) < 0)
       post("netclient: warning: could not prepare child thread" );
    if(pthread_attr_setdetachstate(&x->x_threadattr, PTHREAD_CREATE_DETACHED) < 0)
       post("netclient: warning: could not prepare child thread" );
    return (x);
}

static void netclient_free(t_netclient *x)
{
    netclient_disconnect(x);
    clock_free(x->x_clock);
	binbuf_free(inbinbuf);
}

#ifndef MAXLIB
void netclient_setup(void)
{
    netclient_class = class_new(gensym("netclient"), (t_newmethod)netclient_new,
    	(t_method)netclient_free,
    	sizeof(t_netclient), 0, A_DEFFLOAT, 0);
    class_addmethod(netclient_class, (t_method)netclient_connect, gensym("connect"), A_SYMBOL, A_FLOAT, 0);
    class_addmethod(netclient_class, (t_method)netclient_disconnect, gensym("disconnect"), 0);
    class_addmethod(netclient_class, (t_method)netclient_send, gensym("send"), A_GIMME, 0);
	class_addmethod(netclient_class, (t_method)netclient_rcv, gensym("receive"), 0);
	class_addmethod(netclient_class, (t_method)netclient_rcv, gensym("rcv"), 0);
    class_sethelpsymbol(netclient_class, gensym("help-netclient.pd"));
	post(version);
}
#else
void maxlib_netclient_setup(void)
{
    netclient_class = class_new(gensym("maxlib_netclient"), (t_newmethod)netclient_new,
    	(t_method)netclient_free,
    	sizeof(t_netclient), 0, A_DEFFLOAT, 0);
	class_addcreator((t_newmethod)netclient_new, gensym("netclient"), A_DEFFLOAT, 0);
    class_addmethod(netclient_class, (t_method)netclient_connect, gensym("connect"), A_SYMBOL, A_FLOAT, 0);
    class_addmethod(netclient_class, (t_method)netclient_disconnect, gensym("disconnect"), 0);
    class_addmethod(netclient_class, (t_method)netclient_send, gensym("send"), A_GIMME, 0);
	class_addmethod(netclient_class, (t_method)netclient_rcv, gensym("receive"), 0);
	class_addmethod(netclient_class, (t_method)netclient_rcv, gensym("rcv"), 0);
    class_sethelpsymbol(netclient_class, gensym("maxlib/help-netclient.pd"));
}
#endif





More information about the Pd-cvs mailing list