Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to divide a decimal MIDI pitch-bend value into 2 separated 7 bit values correctly?

Tags:

c

int

midi

7-bit

I'm trying to make a sort of custom midi player, to do so I'm using an array that already has memorized correctly the midi messages data like this:

int array[3000][4]={{time,status,data1,data2},{...},...}

when I want my program to send the midi message (so that it can be played) I call this array and do the needed distinctions between noteon/off, pitch-bend and such. The pitch-bend value (ranging from 0 to 16383, but usually is around 8192 which means no pitch shifting) is all memorized in data1 (array[i][2]). For the conversion from int to the two 7 bits values to pass to midiOutShortMsg() I've used some of the code I found here. Here is the code I'm actually using:

union { unsigned long word; unsigned char data[4]; } message;
int main(int argc, char** argv) {
    int midiport; // select which MIDI output port to open
    uint16_t bend;
    int flag,u;    // monitor the status of returning functions
    uint16_t mask = 0x007F;
    HMIDIOUT device;    // MIDI device interface for sending MIDI output
    message.data[0] = 0x90;  
    message.data[1] = 60;    
    message.data[2] = 100;   
    message.data[3] = 0;     // Unused parameter


// Assign the MIDI output port number (from input or default to 0)
if (!midiOutGetNumDevs()){
    printf("non ci sono devices");
}
if (argc < 2) {
    midiport = 0;
}
else {
    midiport = 0;
}
printf("MIDI output port set to %d.\n", midiport);

// Open the MIDI output port
flag = midiOutOpen(&device, midiport, 0, 0, CALLBACK_NULL);
if (flag != MMSYSERR_NOERROR) {
    printf("Error opening MIDI Output.\n");
    return 1;
}i = 0;
message.data[0] = 0xC0;
message.data[1] = 25;
message.data[2] = 0;
flag = midiOutShortMsg(device, message.word); //program change to steel guitar
if (flag != MMSYSERR_NOERROR) {
    printf("Warning: MIDI Output is not open.\n");
}
while (1){
    if (array[i][1] == 1) { //note on 
        this_works();i++;
    }
    else if (array[i][1] == 0){//note off
        this_also_works();i++;
    }
    else if (array[i][1] == 2){//pitch bend
        while (array[i][1] == 2){
            Sleep(10);
            message.data[0] = 0xE0;
            bend = (uint16_t) array[i][2];
            message.data[1] = bend & mask;
            message.data[2] = (bend & (mask << 7)) >> 7;
            printf("bending %d, %d\n", message.data[1],message.data[2]); 
            flag = midiOutShortMsg(device, message.word);
            if (flag != MMSYSERR_NOERROR) {
                printf("Warning: MIDI Output is not open.\n");
            }i++;
        }
    }
}}

The printf("bending %d,%d") function always prints the first %d as a 0, no matter what. It's the first time I program in midi and I never had to deal with 7 bits values before, so I'm getting quite confused, any help will be appreciated.

like image 535
Febio Mosca Avatar asked May 19 '15 17:05

Febio Mosca


1 Answers

For a pitch bend message data1 (your message.data[1]) is the LSB, and data2 (message.data[2]) is MSB. I'm not a C developer, but here's how I do it in some pseudo-code:

(byte) data2 = pitchbend >> 7
(byte) data1 = pitchbend & 0x7F

In English:

  • MSB is: pitchbend bit shift right 7
  • LSB is: pitchbend bitwise AND with a mask of 127

For reference, doing the reverse (combining the two values to calculate pitch bend, if you had received them in a message, for instance) is a simple matter of:

pitchbend = (data2 * 128) + data1

Edit: I read your code more closely, and it looks like you're already doing what I described. IE:

uint16_t mask = 0x007F;
bend = (uint16_t) array[i][2];

message.data[1] = bend & mask;
message.data[2] = (bend & (mask << 7)) >> 7;

What values for array[i][2] are you trying to send? Anything that is an even multiple of 128 will result in an LSB (message.data[1]) of zero. It is not uncommon for devices to ignore, or not use the added resolution provided by the low byte, so your sample MIDI data may fall under this condition.

like image 167
Justin Ryan Avatar answered Sep 18 '22 11:09

Justin Ryan