What confused me is that you’re putting things into the ~notes array, but never using what you put in there.
x
can hold only one synth. So when you do x.set
, this cannot be polyphonic. So it turns out that x
is the thing to delete, then.
For polyphony, each note-on needs to create an all new Synth instance. You cannot reuse an old synth instance with x.set
there – x.set is changing the frequency of an old note, which is what you’d do in a mono synth.
~on = MIDIFunc.noteOn({
arg veloc, num, chan, src;
~notes[num] = Synth(\plucked,
[\freq, num.midicps,
... full arg list including control bus mappings...]
);
}, chan: 0);
Your example follows ccnum 9. Your code logic then retrieves a synth with note number 9 and sets its parameter. Thus ccnum 9 will control notes with frequency 13.75 only, and ignore all other notes.
That is, it isn’t about order of parameters – it’s about their semantics. A ccnum does not mean the same thing as a note num. Your notes array is indexed in terms of note numbers so it is invalid to access synths from it based on cc numbers.
IMO in a polyphonic context, the easiest way to handle MIDI CCs is with control buses.
// MIDI CC Func #1 for undefined CC channel #20
~cc1Bus = Bus.control(s, 1);
~cc1 = MIDIFunc.cc({
arg veloc, num, chan, src;
~cc1Bus.set(
veloc.linlin(0, 127, 0.0, 1.0),
);
}, ccNum: 20, chan: 0);
// MIDI CC Func #2 for undefined CC channel #21
~cc2Bus = Bus.control(s, 1);
// btw you wrote cc1 for this one too
// fixing that... the variable name collision means that your .free doesn't free everything
~cc2 = MIDIFunc.cc({
arg veloc, num, chan, src;
~cc2Bus.set(
veloc.linlin(0, 127, 0.0, 1.0),
);
}, ccNum: 21, chan: 0);
Then the note on func should do ~notes[num] = Synth(\plucked, [freq: num.midicps, \pan, ~cc1Bus.asMap, \synthesisParameter1, ~cc2Bus.asMap]);
.
hjh