Cabbage Logo
Back to Cabbage Site

Any way to force pchbend channel?

I am working on a cabbage instrument where the synthesis occurs in instrument 1 as usual, but an always on instrument 2 handles gui elements of the synth, effects processing, etc. I would like to have this gui instrument capture the pchbend and mod wheel (via ctrl7) and put them into global variables rather than have each instance of the polyphonic synth 1 read and process the same data.

How might I go about doing this? ctrl7 has an argument to choose a channel, but pchbend does not… it defaults to the channel assigned by csound at init time, in this case “2”. I don’t think massign is the right answer, because that would cause new instances of the gui handling instrument when the keyboard is played.

I don’t see anything wrong with having each instance overwrite the previous global pitch bend variable. The pitch bend wheel can only be one value at a time right?

It’s more of an issue of everything else that the gui instrument is doing that can’t/shouldn’t be overwritten, such as handling effects such as reverb/delay… plus it’s just a lot of overhead I’d rather avoid if possible. :wink:

If this helps make the idea I was going for more clear… long term I wanted to make a UDO that calculates a cps multiplier and amp multiplier based on the pitch wheel and an lfo linked to the mod wheel (and associated cabbage widgets). The idea is to encapsulate the processing of that into one call, rather than having each instance pull the data, do the math, and come up with the same answer… with an added side benefit of a synced LFO across note instances.

You can always read the pitchbend data using midiin. Set one up in an instrument that is always listening for MIDI input and that should work or?

Hrm, I don’t know… I’ll have to give it a shot. It looks to be rather clunky, but I suspect it will be able to get what I need. I’m guessing once I check for status to the the right type, then kdata1 and kdata2 are each 7bits and will need to be combined to make the 14 for pitch bend data? I’m familiar with the concept in theory, but haven’t done it in practice with midi/csound… I’m guessing it will be something like:
kBend = (kdata1 << 7) & kdata2

Perhaps I should have mentioned, I’m pretty new to using midi in conjunction with csound/cabbage other than past the most basic level. I wouldn’t be surprised if there are a few other ways to get the data that I’ve never heard of. Maybe this would be better suited for the noobs section? :wink:

I"m not sure this is a newbie topic :slight_smile: Might this be of any use to you?

That was a great help, thanks Rory. This method definitely isn’t as complicated as it looked at first last night… tho I still feel like the pchbend opcode probably deserves channel selection built in, similar to ctrl7/14 etc, and was a little surprised to learn it didn’t have that already.

But I digress… after reading Iain’s example and some more experimenting, it appears I had the least/most significant bits confused, data2 is MSB… additionally I bitwise ANDed when I should have ORd (you’re gonna have a bad time!). But other than that it seems to be working like a charm so far this way:
kBend = (kData2 << 7) | kData1

By just using kdata2, a-la Iain’s example, you end up with 128 scaled steps for pitch bend, before port. By bitshifting over 7 places and combining the two values with OR, you gain back the full 16384 steps. I’m hoping this will negate the need for port/portk? But I guess if you allow bending across more than one or two octaves, perhaps it’s better to have it there anyway. Hrm… :thinking:

That said, Iain’s example raised an unrelated question for me… why is his pitch bend’s portk using a linseg to change the port times? I’m sure there’s a good reason to do that, but it’s new technique to me so I’m curious what the benefit is there over a static port time.

Yes, that example of mine looks a bit old and I think I was using very poor hardware that was only outputting meaningful data using the MSB. midiin is definitely the way to go as pchbend depends on a MIDI note trigger and only uses the channel on which the instrument was triggered - useful for MPE but less useful here.
That thing with the linseg controlling the portamento time is a trick I use all the time to ensure that kbend doesn’t slide up slowly from zero each time a note is played but instead jumps instantly to the initial value (as portamento time is initially zero according to the linseg). You can also specify an initial value for portk but I find this method preferable.

Hey Iain, thanks for jumping in with the explanation! I’m pretty sure I’ve got it all figured out now…

So that sounds like since I’m using a global variable to store the bend value instead of having it calculated each note, that linseg isn’t really needed and I can use a static port time (assuming I decide to use port at all)?

Nice work!
If your hardware is outputting full 14 bit resolution then portamento may indeed not be necessary - it’s often just a necessary evil. Cheaper hardware often uses AD converters of lower bit depth so that the 14 bit value is jumping in large steps. Cheap M-Audio pitch bend controllers jump in steps of 127 so are effectively 7-bit controls.