Sending Midi pitch bend data to VST plugin

Topics: Host Processing, Midi, VST.NET Framework
Mar 21, 2014 at 3:31 AM
Edited Mar 21, 2014 at 3:38 AM
Documentation on sending pitch bend to VST plugins is misleading. I suppose it's because people keep suggesting workarounds instead of directly sending a midi message because some VST plugins don't support midi pitch bend message, amirite (am I right?)

Or should I proceed differently to send midi pitch bend values to a VST plugin using VST.NET?

Midi message is built according to this spec source:
http://www.midikits.net23.net/midi_analyser/pitch_bend.htm

Implementation is a delicate exercise in striking a balance between verbose versus convoluted code. If there's some bit lovers lurking around, comments for improvements are welcome.
// Convert 14 bits pitch bend to 16 bits packed midi message (midi byte 2 and 3)
BitArray pitchBendBits = new BitArray(new int[] { pitchBend }),
                                    midiByte2 = new BitArray(8),
                                    midiByte3 = new BitArray(8);

// Pack pitch bend value, lower 7 bits in midi byte 2, bit 8 is always 0
for (int i = 0; i < 7 && i < pitchBendBits.Length && i < pitchBendBits.Length; i++)
     midiByte2[i] = pitchBendBits[i];

// Pack pitch bend value, higher 7 bits in midi byte 3, bit 16 is always 0
for (int i = 0, j = 7; j < 14 && j < pitchBendBits.Length; i++, j++)
     midiByte3[i] = pitchBendBits[j];

// Midi message
// Byte 1, pack higher 4 bits pitch bend flag 1110 + lower 4 bits channel value
// Byte 2, pitch bend value, lower 7 bits
// Byte 3, pitch bend value, higher 7 bits
byte[] midiData = new byte[4];
midiData[0] = (byte)(224 + channel);
midiByte2.CopyTo(midiData, 1);
midiByte3.CopyTo(midiData, 2);

VstMidiEvent ve= new VstMidiEvent(0, // DeltaFrames
                                                     0, // NoteLength
                                                     0, // NoteOffset
                                                     midiData,
                                                     0, // Detune
                                                     0, // NoteOffVelocity
                                                     true); // IsRealTime
Hope this helps other VST.Net library users.

Edit: what happened to the Code tag in codeplex discussion? Formatting is all screwed up now :(
If using chrome browser, & #43 ; is the escape sequence character for the plus sign
Coordinator
Mar 21, 2014 at 6:15 AM
Edited Mar 21, 2014 at 6:20 AM
After the Pitch wheel (bend) status byte the value is specified in little endian mode - that means the first data byte represents the LSB(yte) (data1) and the second data byte represents the MSB(yte) (data2).

I think you can do something like:
int bendData = data1 | (data2 << 7);

// or the other way around

byte data1 = bendData & 0x7F;
byte data2 = (bendData >> 7) & 0x7F;
disclaimer: you probably have to cast some of it to int or byte in order for the code to compile.

BTW: This is also a nice resource for Midi specs:
http://home.roadrunner.com/~jgglatt/tech/midispec.htm
Mar 21, 2014 at 2:50 PM
Edited Mar 21, 2014 at 2:51 PM
Yeah makes sense, I needed sleep yesterday....
This is somewhat more cryptic but the tradeoff is OK.

My bend data is already in range so I think the mask on the second byte isn't necessary.

byte data1 = (byte)(bendData & 127);
byte data2 = (byte)(bendData >> 7);

Thank you