I need to hand assemble 14bit MIDI Pitch Bend values from raw UInt16 values in iOS. I'm wondering if anybody out there has had a chance to come up with an elegant solution? Here's where I'm at - I'll get a chance to test this probably later today, but if I hear back before then, great:
First, some MIDI preliminaries for anybody curious.
MIDI Pitch Bend is broken up into one Status Byte followed by two Data Bytes (it's a 14bit controller), these two Data Bytes are associated with their Status Byte by both leading with a Zero status bit, MIDI Spec has them appearing in the order of MSB -> LSB
(Edit: Update, it's actually Status -> LSB -> MSB )
( ie 1110 0000, 0111 1111, 0111 1111 )
The challenge is how to break up an ARM/Intel 16bit UInt16 into two 7 bit segments on iOS, and have it make sense for MIDI?
Please keep in mind that, because we're dealing with an unsigned integer, a 0 value is NOT neutral pitch bend, but rather full pitch down - where as neutral pitch bend is defined as 8192 - and 16,383 is full pitch up.
So here's my best guess as to how to do this:
UInt16 msbAnd = base10ValueUInt16 & 16256; //clearing out LSB
UInt16 msbAndShift = msbAnd << 1; //shift into leading Byte, with 0 status bit
UInt16 lsbAnd = base10ValueUInt16 & 127; //isolating LSB
UInt16 finalTwoBytePitchWord = msbFinalAndShift | lsbAnd; //make UInt16 word
UInt16 finalTwoBytePitchWordFlipped = CFSwapInt16HostToBig(finalTwoBytePitchWord); //Endian tweak
This code runs fine and seems to create the two Data Bytes with the required zero status bits and flips them around from little endian Intel/ARM which seems to be necessary for MIDI (MIDI is STATUS -> MSB -> LSB ): I can slap on the leading Status Byte with the appropriate MIDI channel later.
So, does this make sense? Has anybody come up with a more elegant solution? ( is there a Library I'm overlooking? ) ... I'll check back in later and also let folks know if this actually worked on the sampler I have to target it at.
Thanks