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@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@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@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@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@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@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@gmx.de) */ /* Based on iso for Max by Charlie Baker (baker@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@foxtrot.ccmrc.ucsb.edu\n" " ported to Pd by Olaf Matthes olaf.matthes@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@koncon.nl */ /* Written by Olaf Matthes (olaf.matthes@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@clyde.as.utexas.edu\n" " ported to Pd by Olaf Matthes olaf.matthes@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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