From 0f12c96d992570360af4676b90d1cb2f40cf6fa8 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Mon, 21 Mar 2011 21:01:26 +0000 Subject: refactored x_midi.c into individual objects, and split out inmidi_* functions to e_midi.c in pd-extended.git svn path=/trunk/; revision=15037 --- externals/vanilla/poly.c | 139 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 externals/vanilla/poly.c (limited to 'externals/vanilla/poly.c') diff --git a/externals/vanilla/poly.c b/externals/vanilla/poly.c new file mode 100644 index 00000000..cc20b855 --- /dev/null +++ b/externals/vanilla/poly.c @@ -0,0 +1,139 @@ +/* Copyright (c) 1997-2001 Miller Puckette and others. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* MIDI. */ + +#include "m_pd.h" + +static t_class *poly_class; + +typedef struct voice +{ + t_float v_pitch; + int v_used; + unsigned long v_serial; +} t_voice; + +typedef struct poly +{ + t_object x_obj; + int x_n; + t_voice *x_vec; + t_float x_vel; + t_outlet *x_pitchout; + t_outlet *x_velout; + unsigned long x_serial; + int x_steal; +} t_poly; + +static void *poly_new(t_float fnvoice, t_float fsteal) +{ + int i, n = fnvoice; + t_poly *x = (t_poly *)pd_new(poly_class); + t_voice *v; + if (n < 1) n = 1; + x->x_n = n; + x->x_vec = (t_voice *)getbytes(n * sizeof(*x->x_vec)); + for (v = x->x_vec, i = n; i--; v++) + v->v_pitch = v->v_used = v->v_serial = 0; + x->x_vel = 0; + x->x_steal = (fsteal != 0); + floatinlet_new(&x->x_obj, &x->x_vel); + outlet_new(&x->x_obj, &s_float); + x->x_pitchout = outlet_new(&x->x_obj, &s_float); + x->x_velout = outlet_new(&x->x_obj, &s_float); + x->x_serial = 0; + return (x); +} + +static void poly_float(t_poly *x, t_float f) +{ + int i; + t_voice *v; + t_voice *firston, *firstoff; + unsigned int serialon, serialoff, onindex = 0, offindex = 0; + if (x->x_vel > 0) + { + /* note on. Look for a vacant voice */ + for (v = x->x_vec, i = 0, firston = firstoff = 0, + serialon = serialoff = 0xffffffff; i < x->x_n; v++, i++) + { + if (v->v_used && v->v_serial < serialon) + firston = v, serialon = v->v_serial, onindex = i; + else if (!v->v_used && v->v_serial < serialoff) + firstoff = v, serialoff = v->v_serial, offindex = i; + } + if (firstoff) + { + outlet_float(x->x_velout, x->x_vel); + outlet_float(x->x_pitchout, firstoff->v_pitch = f); + outlet_float(x->x_obj.ob_outlet, offindex+1); + firstoff->v_used = 1; + firstoff->v_serial = x->x_serial++; + } + /* if none, steal one */ + else if (firston && x->x_steal) + { + outlet_float(x->x_velout, 0); + outlet_float(x->x_pitchout, firston->v_pitch); + outlet_float(x->x_obj.ob_outlet, onindex+1); + outlet_float(x->x_velout, x->x_vel); + outlet_float(x->x_pitchout, firston->v_pitch = f); + outlet_float(x->x_obj.ob_outlet, onindex+1); + firston->v_serial = x->x_serial++; + } + } + else /* note off. Turn off oldest match */ + { + for (v = x->x_vec, i = 0, firston = 0, serialon = 0xffffffff; + i < x->x_n; v++, i++) + if (v->v_used && v->v_pitch == f && v->v_serial < serialon) + firston = v, serialon = v->v_serial, onindex = i; + if (firston) + { + firston->v_used = 0; + firston->v_serial = x->x_serial++; + outlet_float(x->x_velout, 0); + outlet_float(x->x_pitchout, firston->v_pitch); + outlet_float(x->x_obj.ob_outlet, onindex+1); + } + } +} + +static void poly_stop(t_poly *x) +{ + int i; + t_voice *v; + for (i = 0, v = x->x_vec; i < x->x_n; i++, v++) + if (v->v_used) + { + outlet_float(x->x_velout, 0L); + outlet_float(x->x_pitchout, v->v_pitch); + outlet_float(x->x_obj.ob_outlet, i+1); + v->v_used = 0; + v->v_serial = x->x_serial++; + } +} + +static void poly_clear(t_poly *x) +{ + int i; + t_voice *v; + for (v = x->x_vec, i = x->x_n; i--; v++) v->v_used = v->v_serial = 0; +} + +static void poly_free(t_poly *x) +{ + freebytes(x->x_vec, x->x_n * sizeof (*x->x_vec)); +} + +void poly_setup(void) +{ + poly_class = class_new(gensym("poly"), + (t_newmethod)poly_new, (t_method)poly_free, + sizeof(t_poly), 0, A_DEFFLOAT, A_DEFFLOAT, 0); + class_addfloat(poly_class, poly_float); + class_addmethod(poly_class, (t_method)poly_stop, gensym("stop"), 0); + class_addmethod(poly_class, (t_method)poly_clear, gensym("clear"), 0); +} -- cgit v1.2.1