hi there,
i've just finished making a kind-of poly~ (ala max4) for pd... without any externals at all :) ... it make gratuitous use of the much-discussed self-modifying-code tricks.
it can do ~100 note polyphony (with a veeery simple instrument) on my machine... so it's fit to do some reasonable granular synthesis too.
i'll just post the abstractions here for the moment, i'll probably put them on my site somewhere soon(ish)..
for now, read the readme.txt... look at the examples... scream in horror...
please let me know what you get up to with this...
seeya, pix.
hi,
cute indeed, but why not to do (almost) the same the simple way, using PureData's poly, and global connections (both control and audio)?
Krzysztof
pix wrote: ...
i've just finished making a kind-of poly~ (ala max4) for pd... without any externals at all :) ... it make gratuitous use of the much-discussed self-modifying-code tricks.
...
#N canvas 96 78 450 300 12; #X msg 24 24 440 0.5; #X msg 37 56 440 0; #X obj 24 94 poly 10 1; #X obj 24 132 pack 0 0 0; #X obj 56 170 print; #X msg 24 206 ; $1-voice $2 $3; #X obj 217 94 catch~ bus; #X obj 217 136 dac~; #N canvas 0 0 600 400 put-your-voices-here 0; #X obj 31 22 voice 1; #X obj 31 54 voice 2; #X obj 31 86 voice 3; #X obj 31 118 voice 4; #X obj 31 150 voice 5; #X obj 126 22 voice 6; #X obj 126 54 voice 7; #X obj 126 86 voice 8; #X obj 126 118 voice 9; #X obj 126 150 voice 10; #X restore 190 24 pd put-your-voices-here; #X connect 0 0 2 0; #X connect 1 0 2 0; #X connect 2 0 3 0; #X connect 2 1 3 1; #X connect 2 2 3 2; #X connect 3 0 4 0; #X connect 3 0 5 0; #X connect 6 0 7 0; #X connect 6 0 7 1;
#N canvas 268 117 450 300 12; #X obj 164 58 r $1-voice; #X obj 164 95 unpack; #X obj 164 134 osc~; #X obj 164 175 *~ 0; #X obj 164 217 throw~ bus; #X connect 0 0 1 0; #X connect 1 0 2 0; #X connect 1 1 3 1; #X connect 2 0 3 0; #X connect 3 0 4 0;
On Fri, 28 Sep 2001 12:02:18 +0200 Krzysztof Czaja czaja@chopin.edu.pl wrote:
hi,
cute indeed, but why not to do (almost) the same the simple way, using PureData's poly, and global connections (both control and audio)?
mainly because poly only lets you send through two parameters...
and also how does it recycle the voices in the pool? it doesn't know when they have finished.
to do stuff like grainsynth, you need to be able to recycle free voices straight away (without having to stop all notes, which i think it what you have to do with poly).
poly could probably be fiddled with to make it more useful (or should i just say, general) - for example, taking a message that will kill a given voice number (that the voice can send when it is finished).
and you could even squeeze some self-mod patch in there for making the building of the voice-pool less painful (i'd rather not make 100 voices by hand - especially with extra wrapper-logic for signalling back to poly).
pix.
Krzysztof
pix wrote: ...
i've just finished making a kind-of poly~ (ala max4) for pd... without
any
externals at all :) ... it make gratuitous use of the much-discussed self-modifying-code tricks.
...
hi,
I like your cute-poly~, it is fun. Any doubts I have are of more general
nature. And I would be happy to sort out these things for the future, to
give more stability in time' (shell I say:
more permanent status'?) to
the work composers are patching in Pd.
Take a look, if you wish, to the attached new version of notsocute.pd (untested), which deal with some of the difficulties you pointed out. Finally, allow me to add few remarks to your explanation:
pix wrote: ...
mainly because poly only lets you send through two parameters...
As in my notsocute.pd example, one can always send more parameters separately to the voice that currently awaits them.
and also how does it recycle the voices in the pool? it doesn't know when they have finished.
to do stuff like grainsynth, you need to be able to recycle free voices straight away (without having to stop all notes, which i think it what you have to do with poly).
You are right, poly works the MIDI-way, so one has to cheat it somehow. There is such cheating in my example, the `extended-poly' subpatch (it is ugly).
poly could probably be fiddled with to make it more useful (or should i just say, general) - for example, taking a message that will kill a given voice number (that the voice can send when it is finished).
That would make PureData's poly incompatible with max, but indeed, making such an extended poly-alike would save much trouble (and is very easy btw).
and you could even squeeze some self-mod patch in there for making the building of the voice-pool less painful (i'd rather not make 100 voices by hand - especially with extra wrapper-logic for signalling back to poly).
Since with global callback (killme' s/r in my example) you do not need to make any local connections, creating 100 voices is not a pain. You can automate this through some sort of self-mod mechanism, as in
create-your-voices' subpatch in my example, but anyway it is safer to
do this only once, and not each time your patch is loading.
Krzysztof
ps. I will be out of reach (and away from Pd) for the next few days. Then I will start adding midifile interface to qlist, if nobody stops me :)
#N canvas 251 16 464 430 12; #X obj 289 249 catch~ bus; #X obj 289 291 dac~; #N canvas 0 0 600 400 your-voices-go-here 0; #X restore 254 204 pd your-voices-go-here; #N canvas 0 0 555 383 create-your-voices 0; #X obj 70 125 until; #X obj 164 187 + 1; #X obj 70 259 pack 0 0 0; #X obj 70 189 t 0 0 0; #X obj 70 88 unpack; #X obj 70 157 f 1; #X obj 99 221 * 10; #X obj 70 19 inlet; #X obj 70 54 pack 0 1; #X msg 70 299 ; pd-your-voices-go-here obj $2 $3 voice $1; #X connect 0 0 5 0; #X connect 1 0 5 1; #X connect 2 0 9 0; #X connect 3 0 2 0; #X connect 3 1 6 0; #X connect 3 2 1 0; #X connect 4 0 0 0; #X connect 4 1 5 1; #X connect 5 0 3 0; #X connect 6 0 2 1; #X connect 6 0 2 2; #X connect 7 0 8 0; #X connect 8 0 4 0; #X restore 253 166 pd create-your-voices; #X msg 253 130 100; #N canvas 0 0 374 304 choose-parameters 0; #X obj 76 52 inlet; #X obj 76 244 outlet; #X obj 76 85 t b b; #X obj 76 211 pack 0 0; #X obj 76 148 + 3; #X obj 76 179 * 10; #X obj 76 117 random 300; #X obj 185 149 random 1000; #X obj 185 180 + 10; #X connect 0 0 2 0; #X connect 2 0 6 0; #X connect 2 1 7 0; #X connect 3 0 1 0; #X connect 4 0 5 0; #X connect 5 0 3 0; #X connect 6 0 4 0; #X connect 7 0 8 0; #X connect 8 0 3 1; #X restore 46 252 pd choose-parameters; #X msg 86 189 ; $1-voice 1; #X obj 185 49 r killme; #X obj 46 288 s parameters; #X msg 46 52 0 1; #N canvas 0 0 456 375 extended-poly 0; #X msg 288 259 0 0; #X obj 145 184 spigot; #X msg 170 301 $1 1; #X obj 145 214 spigot; #X obj 145 65 t a 0; #X msg 185 98 1; #X msg 266 222 0; #X obj 145 28 inlet; #X obj 288 31 inlet; #X msg 288 68 $1 0; #X obj 145 334 outlet; #X obj 145 253 t 0 0 0 b; #X obj 145 141 poly 100 1; #X obj 18 254 print start; #X obj 316 119 print end; #X connect 0 0 12 0; #X connect 1 0 3 0; #X connect 2 0 12 0; #X connect 3 0 11 0; #X connect 3 0 13 0; #X connect 4 0 12 0; #X connect 4 1 5 0; #X connect 5 0 3 1; #X connect 6 0 3 1; #X connect 7 0 4 0; #X connect 8 0 9 0; #X connect 8 0 14 0; #X connect 9 0 12 0; #X connect 11 0 10 0; #X connect 11 1 2 0; #X connect 11 2 6 0; #X connect 11 3 0 0; #X connect 12 0 1 0; #X connect 12 2 1 1; #X restore 46 96 pd extended-poly; #X obj 46 139 t 0 0; #X connect 0 0 1 0; #X connect 0 0 1 1; #X connect 4 0 3 0; #X connect 5 0 8 0; #X connect 7 0 10 1; #X connect 9 0 10 0; #X connect 10 0 11 0; #X connect 11 0 5 0; #X connect 11 1 6 0;
#N canvas 268 117 450 300 12; #X obj 184 21 r $1-voice; #X obj 41 132 unpack; #X obj 41 165 osc~; #X obj 41 205 *~ 0; #X obj 41 240 throw~ bus; #X obj 41 21 r parameters; #X obj 212 131 delay; #X obj 41 60 spigot; #X obj 41 93 t a 0; #X obj 212 240 s killme; #X obj 212 164 t b 0; #X obj 212 205 f $1; #X msg 120 60 0; #X connect 0 0 7 1; #X connect 1 0 2 0; #X connect 1 1 6 0; #X connect 2 0 3 0; #X connect 3 0 4 0; #X connect 5 0 7 0; #X connect 6 0 10 0; #X connect 7 0 8 0; #X connect 8 0 1 0; #X connect 8 1 12 0; #X connect 10 0 11 0; #X connect 10 1 3 1; #X connect 11 0 9 0; #X connect 12 0 7 1;
On Fri, 28 Sep 2001 15:32:47 +0200 Krzysztof Czaja czaja@chopin.edu.pl wrote:
hi,
I like your cute-poly~, it is fun. Any doubts I have are of more general nature. And I would be happy to sort out these things for the future, to give more
stability in time' (shell I say:
more permanent status'?) to the work composers are patching in Pd.
yeah, the comments are interesting and making me think... i hadn't really considered trying to use poly to do this, but i can see many reasons why it's probably good that i didn't... most of these revolve around how midi-dependant poly is. i would really like to think that we are well beyond the simplicity if midi-like specifications of sound events. i'm not sure what the 10 parameters might be that someone could use to trigger a note in nqpoly~, but i like making it more general.
Take a look, if you wish, to the attached new version of notsocute.pd (untested), which deal with some of the difficulties you pointed out. Finally, allow me to add few remarks to your explanation:
pix wrote: ...
mainly because poly only lets you send through two parameters...
As in my notsocute.pd example, one can always send more parameters separately to the voice that currently awaits them.
but there is a lot of trickery to change the parameters before every event...
and also how does it recycle the voices in the pool? it doesn't know
when
they have finished.
to do stuff like grainsynth, you need to be able to recycle free
voices
straight away (without having to stop all notes, which i think it what
you
have to do with poly).
You are right, poly works the MIDI-way, so one has to cheat it somehow. There is such cheating in my example, the `extended-poly' subpatch (it is ugly).
yeah this is very very midi - assuming that you won't want two events with the same frequency.. but there is a lot more to sound than frequency.
poly could probably be fiddled with to make it more useful (or should
i
just say, general) - for example, taking a message that will kill a
given
voice number (that the voice can send when it is finished).
That would make PureData's poly incompatible with max, but indeed, making such an extended poly-alike would save much trouble (and is very easy btw).
yeah i imagine it would be easy... at it really just involves is an efficient array for remembering which voices are doing what. theoretically this could probably just be done with a table anyhow... *thinks thinks.. hmm, evil gleam*.. i have this perverse obsession with doing as much as possible in abstractions without resorting to externals (which feel like a kind of cheating - because everything is theoretically possible in code, i'm more interested in finding out what is possible in pd).
and you could even squeeze some self-mod patch in there for making the building of the voice-pool less painful (i'd rather not make 100
voices by
hand - especially with extra wrapper-logic for signalling back to
poly).
Since with global callback (
killme' s/r in my example) you do not need to make any local connections, creating 100 voices is not a pain. You can automate this through some sort of self-mod mechanism, as in
create-your-voices' subpatch in my example, but anyway it is safer to do this only once, and not each time your patch is loading.
i don't know about safer.. but it's certainly easier to code. as you can imagine, making changes to nqpoly~ is a nightmare :)
Krzysztof
ps. I will be out of reach (and away from Pd) for the next few days. Then I will start adding midifile interface to qlist, if nobody stops me :)
pix.
hmm, i just had another look at my nqpoly~.pd thing, and noticed that it had been broken by an edit that i did just before i posted it.
nqpoly~-test stil openened, and would make some noise, but would spit out some errors about broken connections... but i'm not quite sure what the symptoms of the bad wiring would be...
anyhow, this one should work (objects had shifted around in the .pd file, and so the self-references were pointing in the wrong places).
pix.