MIDI IN, Note On Vel =0, help

I have a sound circuit that has worked fine with the code I had "thrown" together.
Now I have a new MIDI sequencer, that sends Note On, Velocity = 0, in stead of Note Off messages.

Here's the code I have used until now

byte incomingByte;
byte note;
int action=2; //0 =note off ; 1=note on ; 2= nada

  
 Serial.begin(31250);
}

//loop: wait for serial data, and interpret the message
void loop () {
  if (Serial.available() > 0) {
    // read the incoming byte:
    incomingByte = Serial.read();
    //Serial.print(incomingByte, BYTE); //debugging over midi out

    // wait for a status-byte, channel 1, note on or off
    if (incomingByte== 144){ // note on message starting starting
      action=1;
    }else if (incomingByte== 128){ // note off message starting
      action=0;
    }else if ( (action==0)&&(note==0) ){ // if we received a "note off", we wait for which note (databyte)
      note=incomingByte;
      playAl(0); //play allophone number 0, a pause to make it shut up :)
      note=0;
      action=2;
    }else if ( (action==1)&&(note==0) ){ // if we received a "note on", we wait for the note (databyte)
      note=incomingByte;
      playAl(note);
      note=0;
      action=0;
    }else{
      //nada      
   }
   
       // deal with cc data
    if((incomingByte >= 0xb0) && (incomingByte < 0xc0) && (flag_previous == 0)) {
      channel = incomingByte & B00001111;
      flag_previous = 3;
    }
    else if((incomingByte < 0x80) && (flag_previous == 3)) {
      ccnumber = incomingByte;
      flag_previous = 4;
    }
    else if((incomingByte < 0x80) && (flag_previous == 4)) {
      ccvalue = incomingByte;
      doCC(channel, ccnumber, ccvalue);
      flag_previous = 0;
    }
    // done with cc data
  }
}

void playAl(byte note)
{
  digitalWrite(ALD, LOW);
  delayMicroseconds(2);
  digitalWrite(ALD, HIGH);
  PORTB = note; //PORTB is digital pins 8-13,6&7 not in use
  while (digitalRead(SBY) == 0);
}

The MIDI code is copied from somewhere, and I have seen it with the Velocity part as well.
My question is how to implement the Velocity in my code.

The sound circuit can not make use of the velocity, but the code needs to work for both Note Off and Note On with velocity = 0.

So Note On velocity >0 will start playAl (note) and Note On velocity ==0 will start playAl (0) which is a pause or mute command.

The code works now with other sequencers, and I don't want to mess up what works, but the different approaches I have tried has not worked, so I wonder if I need to look at the whole MIDI IN code with new eyes.

There's a lot of "else if" there. Maybe a "cleaner" approach

I tried this:

byte incomingByte;
byte note;
byte velocity;
int action=2; //0 =note off ; 1=note on ; 2= nada



void loop () {
  if (Serial.available() > 0) {
    // read the incoming byte:
    incomingByte = Serial.read();
    //Serial.print(incomingByte, BYTE); //debugging over midi out

    // wait for a status-byte, channel 1, note on or off
    if (incomingByte== 144){ // note on message starting starting
      action=1;
    }else if (incomingByte== 128){ // note off message starting
      action=0;
    }else if ( (action==0)&&(note==0) ){ // if we received a "note off", we wait for which note (databyte)
      note=incomingByte;
      playAl(0); //play allophone number 0, a pause to make it shut up :)
      note=0;
      velocity=0;
      action=2;
    }else if ( (action==1)&&(note==0) ){ // if we received a "note on", we wait for the note (databyte)
      note=incomingByte;
    }else if ( (action==1)&&(note!=0) ){ // ...and then the velocity
     velocity=incomingByte;
    }else if ( (action==1)&&(note!=0)&&(velocity==0) ){
     playAl(0);
     note=0;
     velocity=0;
     action=2;
    }else if ( (action==1)&&(note!=0)&&(velocity!=0) ){
      playAl(note);
      note=0;
      velocity=0;
      action=0;
    }else{
      //nada      
   }

This did not work

Any suggestions?

That code is just rubbish. Basically it does not input the three parameters, message, note & velocity and seems to play a note before velocity is received.

What is your sound circuit? Does it use velocity at all when playing a note. That playAl function looks well strange putting out a 6 bit value when the note value is going to be a 7 bit value.

If your code was half way decent it could be easily modified, I suspect you only think it works because you have not tested it enough.

Hi

The sound circuit is based on a SP0256-AL2 Speech chip.

No, it does not use velocity when playing a note, or allophone.

The playAl function may look strange, but works fine.

But that is not where I need help.

It's the MIDI part.

Could you please direct me to a working MIDI code where I can listen to the 3 parameters, and execute the playAl (note) function when velocity is >0 and playAl (0) when it's = 0

The code I use is the Arduino MIDI code that comes up most places I find on the web.
Do you have another code to suggest, or should I use a library maybe?

Cheers

But that is not where I need help.

Yes it is but please yourself.

Could you please direct me to a working MIDI code where I can listen to the 3 parameters, and execute the playAl (note) function when velocity is >0 and playAl (0) when it's = 0

You will have to put your own crazy playAl function in it in place of the play note

/* Midi Shield - Mike Cook May 2009
 * ----------------- 
 * listen for MIDI serial data, 
 * sends MIDI note on with push button on Pin 2
 
#####################################################################################################################################################

HARDWARE NOTE:
The MIDI Socket is connected to arduino RX through an opto-isolator to invert the MIDI signal 
and separate the circuits of individual instruments.

####################################################################################################################################################
*/

//variables setup

  byte incomingByte;
  byte note;
  byte button;
  int noteDown = LOW;
  int state=0;        // state machine variable 0 = command waiting : 1 = note waitin : 2 = velocity waiting
  byte channel = 1;  // MIDI channel to respond to (in this case channel 2) change this to change the channel number
                    // MIDI channel = the value in 'channel' + 1

//setup: declaring inputs and outputs and begin serial 
void setup() { 

  pinMode(13,OUTPUT);       // LED to light up
  pinMode(2,INPUT);         // push button to read
  digitalWrite(2,HIGH);     // enable internal pull up resistors
  button = digitalRead(2);  // initialise push button state
  state = 0;  // initialise state machine variable
  //start serial with MIDI baud rate 31250 or another standard speed for debugging
  Serial.begin(31250);        
  digitalWrite(13,LOW);     // Turn LED off
}

//loop: wait for serial data, and interpret the message 
void loop () {
  checkIn(); // see if anything has arrived at the input
  checkButton();
  }
  
void checkButton(){
  if(button != digitalRead(2)) {  // only do stuff on a change
    button = digitalRead(2);     // get new state of button
    if(button == HIGH) noteSend(0x80, 65, 0); else noteSend(0x90, 65, 127);
  }
}  

//  plays a MIDI note
void noteSend(byte cmd, byte data1, byte data2) {
  cmd = cmd | channel;        // merge channel number
  Serial.write((byte)cmd);    // command
  Serial.write((byte)data1);  // note number
  Serial.write((byte)data2);  // velocity
}
  
void checkIn(){
  if (Serial.available() > 0) {
    // read the incoming byte:
    incomingByte = Serial.read();

   switch (state){
      case 0:
    // look for as status-byte, our channel, note on
    // if (incomingByte== (144 | channel)){  // un comment and comment the line below - to read only one channel
      if ((incomingByte & 0xf0) == 0x90){    // this reads all channels
         noteDown = HIGH;
         state=1;
        }
    // look for as status-byte, our channel, note off
   // if (incomingByte== (128 | channel)){   // un comment and comment the line below - to read only one channel 
        if ((incomingByte & 0xf0) == 0x80){  // this reads all channels
         noteDown = LOW;
         state=1;
        }
        
       case 1:
       // get the note to play or stop
       if(incomingByte < 128) {
          note=incomingByte;
          state=2;
       }
       else{
       state = 0;  // reset state machine as this should be a note number
       }
       break;
       
       case 2:
       // get the velocity
       if(incomingByte < 128) {
         doNote(note, incomingByte, noteDown); // do something withh the note on message
       }
         state = 0;  // reset state machine to start            
     }
  }
}

void doNote(byte note, byte velocity, int down){
  // if velocity = 0 on a 'Note ON' command, treat it as a note off
  if ((down == HIGH) && (velocity == 0)){
      down = LOW; 
  }
  // do something with the note message 
  // this just toggles Pin 13 and ignores the note value and velocity
 if(down == LOW) digitalWrite(13, LOW); else  digitalWrite(13, HIGH);

}

thank you for the MIDI code

do you think the problem with the code is the playAl function, and not the MIDI part?

I am not married to it, so if you have some suggestions on what it should look like, I am interested.

I don't see how that play function can possibly work over the full range of notes. As I said it only outputs 6 bits, that covers only half the range of notes.

the playAl function controls the sound chip, SP0256-AL2 is a speech chip that can produce 59 allophones that put together can "speak" English.
I only need the 6 bits to play the 59 sounds

I only need the 6 bits to play the 59 sounds

indeed you do. :wink:

SP0256-AL2 is a speech chip ......

Well I haven't seen one of those since the 80s, I did have a play with one then. Not too impressed though.