aboutsummaryrefslogtreecommitdiff
path: root/externals/vanilla/poly.c
diff options
context:
space:
mode:
authorHans-Christoph Steiner <eighthave@users.sourceforge.net>2011-03-21 21:01:26 +0000
committerHans-Christoph Steiner <eighthave@users.sourceforge.net>2011-03-21 21:01:26 +0000
commit0f12c96d992570360af4676b90d1cb2f40cf6fa8 (patch)
treede217ab398ef18b7618001d084ed9f445196f2b2 /externals/vanilla/poly.c
parent70fa5194a370320732db2d7048316c8e09b07a88 (diff)
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
Diffstat (limited to 'externals/vanilla/poly.c')
-rw-r--r--externals/vanilla/poly.c139
1 files changed, 139 insertions, 0 deletions
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);
+}