Pages: [1]   Go Down
Author Topic: MIDI library inconsistent performance -resolved  (Read 364 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Jr. Member
**
Karma: 0
Posts: 98
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I have what I think is a relatively simple project:  to control a few things on my KORG electribe via MIDI commands.  I have a Ruggeduino + MIDI shield  and I recently finished some code to 'mute' certain parts and added a start/stop toggle and send program changes.  All of this is handled by the MIDI library, specifically the HandleNoteOn callback.  The issue, is that both functions (start/stop & 'mute & program change') do not work nicely together for some reason.  

It seems like which ever one is sent first, is the one that works.  For example, if I trigger a note to start the sequencer, none of the program changes work.  If I reset and trigger a program change, it works, but then 'start' does not.  ???


here's some info from KORG on the recognized MIDI commands:

2.RECOGNIZED RECEIVE DATA
2-1 CHANNEL MESSAGES
+--------+---------+-------+--------------------------------------+
| Status | Second | Third | Description |
| [Hex] | [H] [D] | [H] | |
+--------+---------+-------+--------------------------------------+
| 8n | kk (kk) | vv | Note Off vv=0~127 |
| 9n | kk (kk) | 00 | Note Off |
| 9n | kk (kk) | vv | Note On vv=1~127 |
| Bn | 06 (06) | dd | Data Entry(MSB) [TABLE1]|
| Bn | 62 (98) | nl | NRPN LSB [TABLE1]|
| Bn | 63 (99) | nm | NRPN MSB [TABLE1]|
| Bn | 79(121) | 00 | Reset All Controllers |
| Bn | 7B(123) | 00 | All Note Off * |
| Cn | pp (pp) | -- | Program Change [NOTE1]|
+--------+---------+-------+--------------------------------------+
n : MIDI Channel No.(0~15)

NOTE1 : Pattern number
pp = 00~3F : A01~64
40~7F : B01~64





Code:
byte P = 0;  //program or patch number
byte M1 = 0;  //mute for part 1 off
byte M2 = 0;  //mute for part 2 off
byte M3 = 0;  //mute for part 3 off
byte M4 = 0;  //mute for part 4 off
byte M5 = 0;  //mute for part 5 off
byte M6a = 0;  //mute for part 6a off
byte M6b = 0;  //mute for part 6b off
byte M7a = 0;  //mute for part 7a off
byte M7b = 0;  //mute for part 7b off
byte S = 0;   //stop/start bit


Code:
void HandleNoteOn (byte channel, byte note, byte velocity){
  //if note X is sent, send program change control to go up
  //todo:

  if (velocity>0){
    switch (note) {
    case 58: //note value of A#3 or 0x3a
      if (S == 0){
        S++;
        MIDI.sendRealTime(Start);
      }
      else
      {
        S--;
        MIDI.sendRealTime(Stop);
      }
      break;
    case 60: //note value of C4  or 0x3C, handles program change 'up'
      if (P == 127){    //this notes that the program is at the highest of 127 and needs reset to 0
        P=0;
        MIDI.sendProgramChange(P,10);
      }
      else
      {
        P++;
        MIDI.sendProgramChange(P,10);
      }
      break;
    case 62: // note value of D4  or 0x3E, handles program change 'down'.
      if (P== 0){
        P=127;
        MIDI.sendProgramChange(P,10);
      }
      else
      {
        P--;
        MIDI.sendProgramChange(P,10);
      }
      break;
    case 64: //part 1 mute, M variable tells us if it's muted already
      if (M1==0) {
        MIDI.sendControlChange(99,5,10);
        MIDI.sendControlChange(98,1,10);
        MIDI.sendControlChange(06,0,10);  //sets level to zero, for part 1
        //need to toggle it
        M1=1;
      }
      else {
        MIDI.sendControlChange(99,5,10);
        MIDI.sendControlChange(98,1,10);
        MIDI.sendControlChange(06,120,10);
        M1=0;
      }

break;
    case 66:
      if (M2==0) {
        MIDI.sendControlChange(99,5,10);
        MIDI.sendControlChange(98,9,10);
        MIDI.sendControlChange(06,0,10);  //sets level to zero, for part 2
        //need to toggle it
        M2=1;
      }
      else {
        MIDI.sendControlChange(99,5,10);
        MIDI.sendControlChange(98,9,10);
        MIDI.sendControlChange(06,120,10);
        M2=0;
      }
break;
    case 68:   //mute for part 3
      if (M3==0) {
        MIDI.sendControlChange(99,5,10);
        MIDI.sendControlChange(98,17,10);
        MIDI.sendControlChange(06,0,10);  //sets level to zero, for part 3
        //need to toggle it
        M3=1;
      }
      else {
        MIDI.sendControlChange(99,5,10);
        MIDI.sendControlChange(98,17,10);
        MIDI.sendControlChange(06,120,10);
        M3=0;
      }
      break;
    case 70:
      if (M4==0) {
        MIDI.sendControlChange(99,5,10);
        MIDI.sendControlChange(98,25,10);
        MIDI.sendControlChange(06,0,10);  //sets level to zero, for part 1
        //need to toggle it
        M4=1;
      }
      else {
        MIDI.sendControlChange(99,5,10);
        MIDI.sendControlChange(98,25,10);
        MIDI.sendControlChange(06,120,10);
        M4=0;
      }
      break;
    case 72:
      if (M5==0) {
        MIDI.sendControlChange(99,5,10);
        MIDI.sendControlChange(98,33,10);
        MIDI.sendControlChange(06,0,10);  //sets level to zero, for part 1
        //need to toggle it
        M5=1;
      }
      else {
        MIDI.sendControlChange(99,5,10);
        MIDI.sendControlChange(98,33,10);
        MIDI.sendControlChange(06,120,10);
        M5=0;
      }
      break;
    case 74:
      if (M6a==0) {
        MIDI.sendControlChange(99,5,10);
        MIDI.sendControlChange(98,41,10);
        MIDI.sendControlChange(06,0,10);  //sets level to zero, for part 1
        //need to toggle it
        M6a=1;
      }
      else {
        MIDI.sendControlChange(99,5,10);
        MIDI.sendControlChange(98,41,10);
        MIDI.sendControlChange(06,120,10);
        M6a=0;
      }
      break;
    case 76:
      if (M6b==0) {
        MIDI.sendControlChange(99,5,10);
        MIDI.sendControlChange(98,49,10);
        MIDI.sendControlChange(06,0,10);  //sets level to zero, for part 1
        //need to toggle it
        M6b=1;
      }
      else {
        MIDI.sendControlChange(99,5,10);
        MIDI.sendControlChange(98,49,10);
        MIDI.sendControlChange(06,120,10);
        M6b=0;
      }
break;
    case 78:
      if (M7a==0) {
        MIDI.sendControlChange(99,5,10);
        MIDI.sendControlChange(98,57,10);
        MIDI.sendControlChange(06,0,10);  //sets level to zero, for part 1
        //need to toggle it
        M7a=1;
      }
      else {
        MIDI.sendControlChange(99,5,10);
        MIDI.sendControlChange(98,57,10);
        MIDI.sendControlChange(06,120,10);
        M7a=0;
      }
      break;
    case 80:
      if (M7b==0) {
        MIDI.sendControlChange(99,5,10);
        MIDI.sendControlChange(98,65,10);
        MIDI.sendControlChange(06,0,10);  //sets level to zero, for part 1
        //need to toggle it
        M7b=1;
      }
      else {
        MIDI.sendControlChange(99,5,10);
        MIDI.sendControlChange(98,65,10);
        MIDI.sendControlChange(06,120,10);
        M7b=0;
      }
      break;


    } //end of switch (note)  



  }

}

and I can see (Via MIDI OX) that the correct MIDI command is being sent (I patched into the sequencer's MIDI THRU port), but the device doesn't change programs.  It's like both things (send start, then send program change) can't be accomplished.  



Here's the rest of the code, if it's relevant

Code:
void setup() {

  MIDI.begin(MIDI_CHANNEL_OMNI);
  MIDI.turnThruOff();
  MIDI.setHandleNoteOn(HandleNoteOn);
  MIDI.sendProgramChange(P,10);
  //   MIDI.setHandleClock ( HandleClock );

}

void loop () {

  MIDI.read(); //is there incoming MIDI?


}
« Last Edit: September 05, 2013, 10:56:24 am by deseipel » Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 98
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

HI guys!  I'm happy to report I figured out the issue.  Apparently, many program change messages must be super sized to work.  Basically, you have to add CC's for them to work correctly. 

oh, and here's a demo of what I've created




Code:

#include <MIDI.h>
/*
8/9/13:
 
 Things this sketch does:
 ------------------------------------
 1. Program change up/down
 a.  note 60 is up, note 62 is down
 
 2. "Mute"  parts 1-7b (sets the volume to zero)
 a.  note 64 is part 1
 b.  note 66 is part 2
 c.  note 68 is part 3
 d.  note 70 is part 4
 e.  note 72 is part 5
 f.  note 74 is part 6
 g.  note 76 is part 6a
 h.  note 78 is part 6b
 i.  note 79 is part 7a
 j.  note 80 is part 7b
 
 
 TO DO:
 ----------------------------
 1.  Start/stop via trigger pad
 
 if note X is received
 sendRealTime (Start/Stop)?
 
 2.  MIDI file reader/send out, get sync...
 
 */

byte P = 0;  //program or patch number
byte M1 = 0;  //mute for part 1 off
byte M2 = 0;  //mute for part 2 off
byte M3 = 0;  //mute for part 3 off
byte M4 = 0;  //mute for part 4 off
byte M5 = 0;  //mute for part 5 off
byte M6a = 0;  //mute for part 6a off
byte M6b = 0;  //mute for part 6b off
byte M7a = 0;  //mute for part 7a off
byte M7b = 0;  //mute for part 7b off
byte S = 0;   //stop/start bit


/*void HandleClock() {
 
 //do stuff ?
 
 }
 */


void HandleNoteOn (byte channel, byte note, byte velocity){
  //if note X is sent, send program change control to go up
  //todo:

  if (velocity>0){ //needs to be greater than zero, not equal to,
    switch (note) {
    case 58: //note value of A#3 or 0x3a
      if (S == 0){
        S++;
        MIDI.sendRealTime(Start);
      }
      else
      {
        S--;
        MIDI.sendRealTime(Stop);
//        MIDI.sendSongPosition(0);
      }
      break;
    case 60: //note value of C4  or 0x3C, handles program change 'up'
      if (P == 127){    //this notes that the program is at the highest of 127 and needs reset to 0
        P=0;
        MIDI.sendControlChange(99,05,10);
        MIDI.sendControlChange(98,107,10);
        MIDI.sendControlChange(06,0,10);
        MIDI.sendControlChange(99,05,10);
        MIDI.sendControlChange(98,108,10);
        MIDI.sendControlChange(06,0,10);
        MIDI.sendProgramChange(P,10);
      }
      else
      {
        P++;
             MIDI.sendControlChange(99,05,10);
        MIDI.sendControlChange(98,107,10);
        MIDI.sendControlChange(06,0,10);
        MIDI.sendControlChange(99,05,10);
        MIDI.sendControlChange(98,108,10);
        MIDI.sendControlChange(06,0,10);
        MIDI.sendProgramChange(P,10);

      }
      break;
    case 62: // note value of D4  or 0x3E, handles program change 'down'.
      if (P== 0){
        P=127;
             MIDI.sendControlChange(99,05,10);
        MIDI.sendControlChange(98,107,10);
        MIDI.sendControlChange(06,0,10);
        MIDI.sendControlChange(99,05,10);
        MIDI.sendControlChange(98,108,10);
        MIDI.sendControlChange(06,0,10);
        MIDI.sendProgramChange(P,10);
      }
      else
      {
        P--;
             MIDI.sendControlChange(99,05,10);
        MIDI.sendControlChange(98,107,10);
        MIDI.sendControlChange(06,0,10);
        MIDI.sendControlChange(99,05,10);
        MIDI.sendControlChange(98,108,10);
        MIDI.sendControlChange(06,0,10);
        MIDI.sendProgramChange(P,10);
           
      }
      break;
    case 64: //part 1 mute, M variable tells us if it's muted already;  all these mutes actually set the volume to zero, uses the volume NRPNs!
      if (M1==0) {
        MIDI.sendControlChange(99,5,10);
        MIDI.sendControlChange(98,1,10);
        MIDI.sendControlChange(06,0,10);  //sets level to zero, for part 1
        //need to toggle it
        M1=1;
      }
      else {
        MIDI.sendControlChange(99,5,10);
        MIDI.sendControlChange(98,1,10);
        MIDI.sendControlChange(06,120,10);
        M1=0;
      }

break;
    case 66:
      if (M2==0) {
        MIDI.sendControlChange(99,5,10);
        MIDI.sendControlChange(98,9,10);
        MIDI.sendControlChange(06,0,10);  //sets level to zero, for part 2
        //need to toggle it
        M2=1;
      }
      else {
        MIDI.sendControlChange(99,5,10);
        MIDI.sendControlChange(98,9,10);
        MIDI.sendControlChange(06,120,10);
        M2=0;
      }
break;
    case 68:   //mute for part 3
      if (M3==0) {
        MIDI.sendControlChange(99,5,10);
        MIDI.sendControlChange(98,17,10);
        MIDI.sendControlChange(06,0,10);  //sets level to zero, for part 3
        //need to toggle it
        M3=1;
      }
      else {
        MIDI.sendControlChange(99,5,10);
        MIDI.sendControlChange(98,17,10);
        MIDI.sendControlChange(06,120,10);
        M3=0;
      }
      break;
    case 70:
      if (M4==0) {
        MIDI.sendControlChange(99,5,10);
        MIDI.sendControlChange(98,25,10);
        MIDI.sendControlChange(06,0,10);  //sets level to zero, for part 1
        //need to toggle it
        M4=1;
      }
      else {
        MIDI.sendControlChange(99,5,10);
        MIDI.sendControlChange(98,25,10);
        MIDI.sendControlChange(06,120,10);
        M4=0;
      }
      break;
    case 72:
      if (M5==0) {
        MIDI.sendControlChange(99,5,10);
        MIDI.sendControlChange(98,33,10);
        MIDI.sendControlChange(06,0,10);  //sets level to zero, for part 1
        //need to toggle it
        M5=1;
      }
      else {
        MIDI.sendControlChange(99,5,10);
        MIDI.sendControlChange(98,33,10);
        MIDI.sendControlChange(06,120,10);
        M5=0;
      }
      break;
    case 74:
      if (M6a==0) {
        MIDI.sendControlChange(99,5,10);
        MIDI.sendControlChange(98,41,10);
        MIDI.sendControlChange(06,0,10);  //sets level to zero, for part 1
        //need to toggle it
        M6a=1;
      }
      else {
        MIDI.sendControlChange(99,5,10);
        MIDI.sendControlChange(98,41,10);
        MIDI.sendControlChange(06,120,10);
        M6a=0;
      }
      break;
    case 76:
      if (M6b==0) {
        MIDI.sendControlChange(99,5,10);
        MIDI.sendControlChange(98,49,10);
        MIDI.sendControlChange(06,0,10);  //sets level to zero, for part 1
        //need to toggle it
        M6b=1;
      }
      else {
        MIDI.sendControlChange(99,5,10);
        MIDI.sendControlChange(98,49,10);
        MIDI.sendControlChange(06,120,10);
        M6b=0;
      }
break;
    case 78:
      if (M7a==0) {
        MIDI.sendControlChange(99,5,10);
        MIDI.sendControlChange(98,57,10);
        MIDI.sendControlChange(06,0,10);  //sets level to zero, for part 1
        //need to toggle it
        M7a=1;
      }
      else {
        MIDI.sendControlChange(99,5,10);
        MIDI.sendControlChange(98,57,10);
        MIDI.sendControlChange(06,120,10);
        M7a=0;
      }
      break;
    case 80:
      if (M7b==0) {
        MIDI.sendControlChange(99,5,10);
        MIDI.sendControlChange(98,65,10);
        MIDI.sendControlChange(06,0,10);  //sets level to zero, for part 1
        //need to toggle it
        M7b=1;
      }
      else {
        MIDI.sendControlChange(99,5,10);
        MIDI.sendControlChange(98,65,10);
        MIDI.sendControlChange(06,120,10);
        M7b=0;
      }
      break;


    } //end of switch (note) 



  }
 
  else{
    switch(note){
      case 58:
        MIDI.sendNoteOff(58,0,10);
        break;
      case 60:
        MIDI.sendNoteOff(60,0,10);
      break;
      case 62:
        MIDI.sendNoteOff(62,0, 10);
      break;   
 case 64:
        MIDI.sendNoteOff(64,0, 10);
      break;     
 case 66:
        MIDI.sendNoteOff(66,0, 10);
      break;     
 case 68:
        MIDI.sendNoteOff(68,0, 10);
      break;     
 case 70:
        MIDI.sendNoteOff(70,0, 10);
      break;     
 case 72:
        MIDI.sendNoteOff(72,0, 10);
      break;     
 case 74:
        MIDI.sendNoteOff(74,0, 10);
      break;   
case 76:
        MIDI.sendNoteOff(76,0, 10);
      break;     
case 78:
        MIDI.sendNoteOff(78,0, 10);
      break;     
case 80:
        MIDI.sendNoteOff(80,0, 10);
      break;           
   
    }
  }

}


void setup() {

  MIDI.begin(MIDI_CHANNEL_OMNI);
  MIDI.turnThruOff();
  MIDI.setHandleNoteOn(HandleNoteOn);
  MIDI.sendProgramChange(P,10);
  //   MIDI.setHandleClock ( HandleClock );
 
}

void loop () {

  MIDI.read(); //is there incoming MIDI?


}

Logged

Pages: [1]   Go Up
Jump to: