Hi Toby, This CSD has a basic system for voice allocation removing old notes first. There's a gilimit variable for how many notes to have on at the same time. Now, this example doesn't take into account if a note naturally ends to remove it's note number from the active list, but that won't matter in the context of a MIDI based system, as you'll likely handle the note on and note off in the controller instrument, and the notes for the sounding instrument will be set to be held indefinitely until signaled by the controller. You can do that signalling simply be removing from the active list, as instrument 2 checks if it's id is still in the active list, at which time, instead of immediately using turnoff, you could do some kind of enveloping to avoid clicks and then use turnoff. So the logic in the controller instruments would work for the MIDI note on's, but you'd have to add a little more for the MIDI note off's, maybe adding another UDO for removing a note by ID. Well, hope that helps at least get the ball rolling. There probalby a bug or two in there somewhere, but that's pretty much all the time I'm going to spend on it. Good luck! steven ; ; "Voice Allocation Test" ; by steven yi ; ; ; ; Generated by blue 0.105.1 (http://csounds.com/stevenyi/blue/index.html) ; sr=44100 ksmps=1 nchnls=2 gilimit = 5 opcode findPowerOfTwo,i,i inum xin ipowtwosamples = 2 loop: ipowtwosamples = ipowtwosamples * 2 if ipowtwosamples < inum igoto loop xout ipowtwosamples endop opcode compressTable,0,i itabnum xin ilen = ftlen(itabnum) itemptable ftgentmp 0, 0, ilen, 10, 0 icount = 0 icount2 = 0 loopStart: ival tablei icount, itabnum if (ival != 0) then tableiw ival, icount2, itemptable icount2 = icount2 + 1 endif loop_lt icount, 1, ilen, loopStart tableicopy itabnum, itemptable endop opcode numActiveNotes,i,i itabnum xin ilen = ftlen(itabnum) icount = 0 icount2 = 0 loopStart: ival tablei icount, itabnum if (ival != 0) then icount2 = icount2 + 1 endif loop_lt icount, 1, ilen, loopStart xout icount2 endop opcode getNoteNum,i,0 ival chnget "noteNumber" if (ival == 0) then ival = 1 endif chnset ival + 1, "noteNumber" xout ival endop opcode removeNotes,0,ii inumnotes, itabnum xin if (inumnotes > 0) ithen icount = 0 loopStart: iNoteNum tablei icount, itabnum prints "Removing Note Number: %f\n", iNoteNum tableiw 0, icount, itabnum loop_lt icount, 1, inumnotes, loopStart endif endop opcode addNote,0,ii inotenum, itabnum xin icount = 0 ilen = ftlen(itabnum) loopStart: ival tablei icount, itabnum if (ival == 0) then ;print icount tableiw inotenum, icount, itabnum icount = icount + ilen endif loop_lt icount, 1, ilen, loopStart endop opcode noteIsActive,k,ii inotenum, itabnum xin ilen = gilimit kcount init 0 kcount = 0 k_noteActive init 1 k_noteActive = 0 loopStart: kval table kcount, itabnum if (kval == inotenum) then k_noteActive = 1 kgoto end endif kcount = kcount + 1 if kcount < ilen kgoto loopStart ;loop_lt kcount, 1, ilen, loopStart end: xout k_noteActive endop instr 1 ;Controller Instrument ipch = cpspch(p4) iamp = ampdb(p5) itabsize findPowerOfTwo gilimit itabnum chnget "instrumentController" if (itabnum == 0) ithen itabnum ftgen 0, 0, itabsize, 10, 0 chnset itabnum, "instrumentController" endif compressTable itabnum iNumNotes numActiveNotes itabnum if (iNumNotes + 1 > gilimit) then removeNotes (iNumNotes + 1 - gilimit), itabnum compressTable itabnum endif iNoteNum getNoteNum addNote iNoteNum, itabnum iNumNotes numActiveNotes itabnum event_i "i", 2, 0, p3, p4, p5, iNoteNum endin instr 2 ;VCO2 Instrument ipch = cpspch(p4) iamp = ampdb(p5) i_id = p6 itabsize findPowerOfTwo gilimit itabnum chnget "instrumentController" if (itabnum == 0) ithen itabnum ftgen 0, 0, itabsize, 10, 0 chnset itabnum, "instrumentController" endif kactive noteIsActive i_id, itabnum ;printks "Instr %f: %f\n", .1, i_id, kactive if (kactive == 0) then itime times ;printks "turning off: %f %f %f\n", itime, i_id, i(kactive) turnoff endif kenv adsr .01, 1, .9, .2 aout vco2 1, ipch aout moogvcf aout, ipch + (kenv * ipch * 4), .1 aout = kenv * iamp * aout outs aout, aout endin i1 0.0 10 7.0 70 i1 0.2 10 7.01 70 i1 0.4 10 7.02 70 i1 0.6 10 7.03 70 i1 0.8 10 7.04 70 i1 1.0 10 7.05 70 i1 1.2 10 7.06 70 i1 1.4 10 7.07 70 i1 1.6 10 7.08 70 i1 1.8 10 7.09 70 i1 2.0 10 7.1 70 i1 2.2 10 7.11 70 i1 2.4 10 8.0 70 i1 2.6 10 8.01 70 i1 2.8 10 8.02 70 i1 3.0 10 8.03 70 i1 3.2 10 8.04 70 i1 3.4 10 8.05 70 i1 3.6 10 8.06 70 i1 3.8 10 8.07 70 i1 4.0 10 8.08 70 i1 4.2 10 8.09 70 i1 4.4 10 8.1 70 i1 4.6 10 8.11 70 i1 4.8 10 9.0 70 i1 5.0 10 9.01 70 i1 5.2 10 9.02 70 i1 5.4 10 9.03 70 i1 5.6 10 9.04 70 i1 5.8 10 9.05 70 i1 6.0 10 9.06 70 i1 6.2 10 9.07 70 i1 6.4 10 9.08 70 i1 6.6 10 9.09 70 i1 6.8 10 9.1 70 i1 7.0 10 9.11 70 i1 7.2 10 10.0 70 i1 7.4 10 10.01 70 i1 7.6 10 10.02 70 i1 7.8 10 10.03 70 i1 8.0 10 10.04 70 i1 8.2 10 10.05 70 i1 8.4 10 10.06 70 i1 8.6 10 10.07 70 i1 8.8 10 10.08 70 i1 9.0 10 10.09 70 i1 9.2 10 10.1 70 i1 9.4 10 10.11 70 e