Thursday, February 2, 2012

MSB and LSB with MIDI (NRPN)

If you know nothing about programming yet find yourself programming for a living (as I do), you might have to deal with some of this bit-shifting bullshit that you should've learned in University. I was drinking coffee and reading Foucault, so I did not learn any of this stuff. My skills as a PUA are probably better, however. But I digress...

I'm about to implement NRPN in MIDI Designer, which led me to this wonderful article. It's pretty easy. Kind of.

Normal MIDI Messages

In the normal case (not NRPNs), MIDI messages typically have a channel, command, data1 (the cc number or the "note") and data2 (the value). The first two are combined into status. So the whole thing looks like this:

   int status = ((command & 0xF0) | (channel & 0x0F));
   Byte theBytes[3] = {status & 0xFF, data1 & 0xFF, data2 & 0xFF};

NRPNs - How to Get MSB and LSB?

NRPNs are like this, but the data2 is being used in two different 3-length byte arrays to get more values in there. So instead of going from 0-127, they go from 0-16129 (127 squared).

Now this creates a problem where you need to get the MSB and the LSB. After talking to my father on the phone today, I realized that what's so messed up about this is that they're not 8-bit bytes. They're "7-bit bytes" (they go from 0-127). So anyway, you have a value and you want to get the MSB and LSB. 

static int msb(int value) {
    return (value) >> 7; 
}

static int lsb(int value) {
    return value & 0x7f; 
}

static int makeValue(int msb, int lsb) {
    return ((msb << 7)) + lsb;
}

Now, you could do this the normal way, too, like this:

int msb = (float)value / 128.0f;
int lsb = value - msb * 128.0f;

which also works, but people will laugh at you.

Conclusion

By now most of you still have no idea what I'm talking about, and this article hasn't helped you. But if you were about to implement NRPNs in a MIDI program, this article might help. 

No comments: