hi,
after rereading my discussion with pix, I think there are few
points I must clear up.
1. My `notsocute' example, patched up in haste, was meant to
illustrate my general doubts, and not to be used as a nqpoly~
replacement. On the other hand, any Pd-instrument designer
would welcome a simple access to poly~'s functionality.
2. I was wrong, arguing that an addition of a request to return
a single voice to the free voices pool of PureData's poly would
cause an incompatibility with max. Even if we seriously cared
for such compatibility, `clear' message to poly is PureData's
extra addition to max-poly, which has only `stop' message.
But anyway I was right about simplicity of such addition. The
proof is in x_midi.c.diff attachment, which adds a float argument
to `clear' message. If this argument's value $n$ is in the range
[1..<number-of-voices>] then voice$_n$ is returned to the pool.
In this version an argumentless `clear' works as it used to.
The question remains, if this simple addition does not introduce
unnecessary ambiguity to the meaning of poly. Currently stopping
a voice means stopping the oldest voice playing a note of
a specified pitch, if there is any such voice. Stopping a voice
number n is something conceptually different. Maybe it is better
to add a separate object class `pool'? OK, there could be an
extern...
#if 0 // this is hackery
3. ... or, if none of the above is available, the remaining
technique would be to cheat existing poly, forcing it to store
noteons with pitch always equal to voice number -- as I did in
notsocute.pd, and which is a very inefficient way of doing
something pretty simple. This trickery is factored out into the
attached abstraction `pooly.pd'. The interface of poly remains
in pooly (with quite the same functionality), and there are two
extensions for handling the voice pool: a `bang' message to choose
a voice (in stealing mode or not), and a `clear <n>' message to
return voice n to the pool. But beware, this abstraction plays
nasty tricks...
#endif
4. Of course the `pitch' input to poly may have any meaning, not
necessarily directly interpreted as a single parameter of a note,
but instead, for example, mapped to a parameter vector, or to any
other mechanism of generating parameter values. A user of poly
should think rather of playing/stopping a note of some arbitrarily
choosen cathegory, which can be pitch or anything else.
5. One thing that is really troublesome in designing poly~-alike
abstraction is a dispatching scheme, since there is no `forward'
object class in Pd. We need to feed the choosen voice with
parameters. This voice's number is a variable. Since, of course,
it is impossible to [route] into as many destinations as we wish,
the only way is to use global send/receive. But if we wanted to
choose send's destination dynamically, we are stuck with a message
box, and the number of parameters must be kept constant -- we
cannot dispatch anything. If, on the other hand, we need variable
number of parameters, then they will have to be sent to all voices,
preceded by another message opening a spigot in the voice being
current destination (one can make variations of this theme, like
passing a message through a chain of destinations, until it is
spigoted into the proper one). This is clumsy, unreliable and
highly inefficient.
Whoever knows of any other way (using max/forward excluded),
please give me a clue.
Krzysztof
--- x_midi.c~ Sun May 20 05:50:52 2001
+++ x_midi.c Mon Oct 1 16:04:05 2001
@@ -1173,11 +1173,18 @@
}
}
-static void poly_clear(t_poly *x)
+static void poly_clear(t_poly *x, t_floatarg ndx)
{
- int i;
+ int i = ndx;
t_voice *v;
- for (v = x->x_vec, i = x->x_n; i--; v++) v->v_used = v->v_serial = 0;
+ if (i--) {
+ if (i >= 0 && i < x->x_n) {
+ x->x_vec[i].v_used = 0;
+ x->x_vec[i].v_serial = x->x_serial++;
+ }
+ }
+ else
+ 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)
@@ -1192,7 +1199,7 @@
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);
+ class_addmethod(poly_class, (t_method)poly_clear, gensym("clear"), A_DEFFLOAT, 0);
}
/* -------------------------- bag -------------------------- */
#N canvas 323 9 349 397 12;
#X obj 123 28 inlet;
#X obj 249 27 inlet;
#X obj 148 249 outlet;
#X obj 199 333 outlet;
#X obj 173 292 outlet;
#X obj 123 157 poly \$1 \$2;
#N canvas 0 0 376 304 routing 0;
#X obj 35 25 inlet;
#X obj 35 227 outlet;
#X obj 222 227 outlet;
#X obj 104 108 route float;
#X msg 133 189 \$1 0;
#X obj 104 146 t b 0 b;
#X msg 279 189 0;
#X msg 222 189 1;
#X obj 133 227 outlet;
#X obj 35 69 route bang clear;
#X msg 198 146 clear;
#X obj 279 109 t a b;
#X connect 0 0 9 0;
#X connect 3 0 5 0;
#X connect 3 1 10 0;
#X connect 4 0 8 0;
#X connect 5 0 7 0;
#X connect 5 1 4 0;
#X connect 5 2 6 0;
#X connect 6 0 2 0;
#X connect 7 0 2 0;
#X connect 9 0 1 0;
#X connect 9 1 3 0;
#X connect 9 2 11 0;
#X connect 10 0 8 0;
#X connect 11 0 8 0;
#X connect 11 1 7 0;
#X restore 123 71 pd routing;
#N canvas 0 0 296 388 cheating 0;
#X msg 103 234 \$1 1;
#X msg 164 234 0 0;
#X obj 103 155 spigot;
#X msg 152 111 1;
#X msg 198 194 0;
#X obj 103 194 t 0 b b;
#X obj 103 34 inlet;
#X obj 103 278 outlet;
#X obj 164 318 outlet;
#X obj 103 71 t b b;
#X msg 103 111 0 1;
#X obj 29 34 inlet;
#X connect 0 0 7 0;
#X connect 1 0 8 0;
#X connect 2 0 5 0;
#X connect 3 0 2 1;
#X connect 4 0 2 1;
#X connect 5 0 0 0;
#X connect 5 1 1 0;
#X connect 5 2 4 0;
#X connect 6 0 9 0;
#X connect 9 0 10 0;
#X connect 9 1 3 0;
#X connect 10 0 8 0;
#X connect 11 0 2 0;
#X restore 29 116 pd cheating;
#N canvas 104 80 379 374 output 0;
#X obj 88 251 outlet;
#X obj 191 334 outlet;
#X obj 139 293 outlet;
#X obj 88 174 spigot;
#X obj 55 121 pack 0 0 0;
#X obj 88 213 unpack 0 0 0;
#X obj 15 22 inlet;
#X obj 97 22 inlet;
#X obj 184 22 inlet;
#X obj 15 213 outlet;
#X obj 15 58 t 0 0;
#X obj 15 174 spigot;
#X obj 284 22 inlet;
#X obj 97 58 t 0 0;
#X obj 275 121 spigot;
#X obj 284 58 t 0 0;
#X obj 184 58 t 0 0;
#X connect 3 0 5 0;
#X connect 4 0 3 0;
#X connect 5 0 0 0;
#X connect 5 1 2 0;
#X connect 5 2 1 0;
#X connect 6 0 10 0;
#X connect 7 0 13 0;
#X connect 8 0 16 0;
#X connect 10 0 11 0;
#X connect 10 1 4 0;
#X connect 11 0 9 0;
#X connect 12 0 15 0;
#X connect 13 0 4 1;
#X connect 13 1 14 0;
#X connect 14 0 3 1;
#X connect 15 0 3 1;
#X connect 15 1 14 1;
#X connect 16 0 11 1;
#X connect 16 1 4 2;
#X restore 123 201 pd output;
#X connect 0 0 6 0;
#X connect 1 0 5 1;
#X connect 5 0 8 0;
#X connect 5 1 8 1;
#X connect 5 2 8 2;
#X connect 6 0 7 1;
#X connect 6 1 5 0;
#X connect 6 2 8 3;
#X connect 7 0 6 0;
#X connect 7 1 5 0;
#X connect 8 0 7 0;
#X connect 8 1 2 0;
#X connect 8 2 4 0;
#X connect 8 3 3 0;