Cabbage Logo
Back to Cabbage Site

Seperating notes from polyphonic midi into seperate midi channels

HI!

Is this possible? What opcodes would I need to look at for this?

My intention is to make my own polyphonic pitch shifter. I want to be able to have three instances of a pitch shifter and one instance of polyphonic midi, and have the separate midi notes automatically allocated to separate midi channels.

If each voice is already assigned a unieq channel, then you can parse the MIDI notes depending on the channel. You’ll probably want to use the low level midiin opcode and then parse the tracks according to their MIDI channel number. If you are hoping to parse polyphonic MIDI on a single channel (for example a fugue), then there is no easy way to do it as far as I know.

If I’m holding down a chord, is there no way to access the midi values for each note?

Yes of course, if you don’t care about which ‘voice’ each note belongs to. You can easily split up all notes. Maybe I was overcomplicating it :rofl:

Yes, that bit doesn’t matter. The pitch shifters will all have the exact same scaling, so it doesn’t matter which one gets which note. How would one go about this?

You’ll need to write each MIDI note to an array based on note on messages, then you can read through the array/table and pass each note to a different output channel. You will also need to listen for note off messages, so you can remove the values from the array table. It might be a little tricky to implement, but it should work :thinking:

Sorry I should’ve explained myself better, the bit I don’t understand is how to actually read the midi events, like what opcode to use. Midi in csound is still a bit of a mystery to me, but I just came across midiin. I must have read past it in my initial searches, sorry! Thank you for your time.

You can use an always on instrument, and then midiin to read the incoming MIDI messages. Don’t use the --midi-key-cps=4 --midi-velocity-amp=5 command line flags as they operate differently. Although :thinking:

Maybe there is an easier way to do this. If instr 1 is triggered with each note then you can simple output each successive note to a new channel? Use a global variable to keep count of the channel, and when it gets to 16, simply start again at 1? you know what I mean? Something like this:

<Cabbage>
form caption("Untitled") size(400, 110), guiMode("queue") pluginId("def1")
keyboard bounds(0, 2, 400, 100) channel("keyboard10000")
</Cabbage>
<CsoundSynthesizer>
<CsOptions>
-n -d -+rtmidi=NULL -M0 -m0d --midi-key-cps=4 --midi-velocity-amp=5
</CsOptions>
<CsInstruments>
; Initialize the global variables. 
ksmps = 32
nchnls = 2
0dbfs = 1

giMidiChannel init 1

instr 1
    prints "This note goes to channel %d\n", giMidiChannel
    giMidiChannel = (giMidiChannel < 15 ? giMidiChannel+1 : 1)
endin

</CsInstruments>
<CsScore>
;causes Csound to run for about 7000 years...
f0 z
</CsScore>
</CsoundSynthesizer>