Search code examples
cwinapimidipitch

How to send midi pitch bend messages correctly in c?


I'm trying to make a custom midi player, to do so I'm using an array that has already 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. At first I thought I was doing the division in two 7 bits variables wrong, because I never worked with this procedure and I just copied the code from another question on stackoverflow, I posted my own question about it (here) and as it turns out the copied code works just fine. And yet the sound output isn't the right one, it barely has any change in pitch and when it has, it is so small I'm not even sure I'm hearing it (it should sound like a half tone bend with a vibrato in the end). So here's the code:

 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++;
         }
     }
 }}

here's the pitch-bend array[][] values for a half tone bend with vibrato:

{ 6560, 2, 8192 },
{ 6576, 2, 8320 },
{ 6592, 2, 8448 },
{ 6608, 2, 8704 },
{ 6624, 2, 8832 },
{ 6720, 2, 8832 },
{ 6729, 2, 8832 },
{ 6739, 2, 8832 },
{ 6748, 2, 8832 },
{ 6757, 2, 8832 },
{ 6766, 2, 8832 },
{ 6776, 2, 8704 },
{ 6785, 2, 8704 },
{ 6794, 2, 8704 },
{ 6804, 2, 8704 },
{ 6813, 2, 8704 },
{ 6822, 2, 8832 },
{ 6831, 2, 8832 },
{ 6841, 2, 8832 },
{ 6850, 2, 8832 },
{ 6859, 2, 8832 },
{ 6868, 2, 8832 },
{ 6878, 2, 8832 },
{ 6887, 2, 8832 },
{ 6896, 2, 8832 },
{ 6906, 2, 8832 },
{ 6915, 2, 8832 },
{ 6924, 2, 8960 },
{ 6933, 2, 8960 },
{ 6943, 2, 8960 },
{ 6952, 2, 8960 },
{ 6961, 2, 8960 },
{ 6971, 2, 8832 },
{ 6980, 2, 8832 },
{ 6989, 2, 8832 },
{ 6998, 2, 8832 },
{ 7008, 2, 8832 },
{ 7017, 2, 8832 },
{ 7026, 2, 8832 },
{ 7036, 2, 8960 },
{ 7045, 2, 8960 },
{ 7054, 2, 8960 },
{ 7063, 2, 8960 },
{ 7073, 2, 8960 },
{ 7082, 2, 8960 },
{ 7091, 2, 8960 },
{ 7101, 2, 8960 },
{ 7110, 2, 8960 },
{ 7119, 2, 8960 },
{ 7128, 2, 8960 },
{ 7138, 2, 8960 },
{ 7147, 2, 8960 },
{ 7156, 2, 8832 },
{ 7165, 2, 8832 },
{ 7175, 2, 8832 },
{ 7184, 2, 8704 },
{ 7193, 2, 8704 },
{ 7203, 2, 8704 },
{ 7212, 2, 8704 },
{ 7221, 2, 8704 },
{ 7230, 2, 8704 },
{ 7240, 2, 8704 },
{ 7249, 2, 8704 },
{ 7258, 2, 8704 },
{ 7268, 2, 8704 },
{ 7277, 2, 8704 },
{ 7286, 2, 8704 },
{ 7295, 2, 8704 },
{ 7305, 2, 8832 },
{ 7314, 2, 8832 },
{ 7323, 2, 8832 },
{ 7333, 2, 8960 },
{ 7342, 2, 8960 },
{ 7351, 2, 9088 },
{ 7360, 2, 9088 },
{ 7370, 2, 9088 },
{ 7379, 2, 9088 },
{ 7388, 2, 9088 },
{ 7398, 2, 9088 },
{ 7407, 2, 9088 },
{ 7416, 2, 9088 },
{ 7425, 2, 9088 },
{ 7435, 2, 8960 },
{ 7444, 2, 8960 },
{ 7453, 2, 8832 },
{ 7462, 2, 8832 },
{ 7472, 2, 8832 },
{ 7481, 2, 8704 },
{ 7490, 2, 8704 },
{ 7500, 2, 8576 },
{ 7509, 2, 8576 },
{ 7518, 2, 8576 },
{ 7527, 2, 8576 },
{ 7537, 2, 8576 },
{ 7546, 2, 8576 },
{ 7555, 2, 8576 },
{ 7565, 2, 8576 },
{ 7574, 2, 8576 },
{ 7583, 2, 8704 },
{ 7592, 2, 8704 },
{ 7602, 2, 8832 },
{ 7611, 2, 8832 },
{ 7620, 2, 8832 },
{ 7630, 2, 8832 },
{ 7639, 2, 8832 },
{ 7648, 2, 8832 },
{ 7657, 2, 8832 },
{ 7667, 2, 8832 },
{ 7676, 2, 8832 },

and here's the printf output: printf output as requested

I really don't know what I'm doing wrong, any help will be appreciated.


Solution

  • The message.data[] values are correctly computed; the code does nothing wrong.

    The problem is that the bend values do not correspond to a half tone. The default pitch bend range maps the 0..16383 control values to ±2 halftones; to get a half tone up, the values would have to go up to 12288.