Midi Running Status

K
Kees posted May 10, 23:13:

With two of my keyboards (Yamaha KX25 and a Oxygen8 v2), I ran into the problem of Midi Running status (serial midi), where the note-on, note-off and CC/PC byte is omitted.

So I wrote a (crude) alternative for the MidiSerialCallback()function and I thought: why not share it, so others can use and test it.

<code>
def MidiSerialCallback():
message = [0,0,0]
i = 0
status = 0 # 0:Ignore; 1:Note Off; 2:Note On;3:Program Change
laststatusByte = 0

  while True:
    data = ord(ser.read(1)) # read a byte
    if data >> 7 == 0 and status in (1,2): # note-on or note-off
      if i == 3: # midi rolling status
        message[0] = laststatusByte
        message[1] = data
        i = 2
      else:
        message[i] = data
        i += 1

    elif data >> 7 == 0 and status == 3: #program change
      if i == 2: #midi rolling status
        message[0] = laststatusByte
        message[1] = data
        message[2] = 0
      else:  
        message[1] = data
        message[2] = 0
        i += 1

    elif data >> 4 in (8, 9, 12):
      message[0] = data
      laststatusByte = data
      if data >> 4 == 8: status = 1
      elif data >> 4 == 9: status = 2
      else: status = 3
      i = 1

    else: # Ignore al other messages
      status = 0
      i = 0

    if i == 3:
      MidiCallback(message, None)

</code>

K
Kees posted May 12, 17:07:

First error found, programm change did not work correctly..
Here is the fix.

def MidiSerialCallback():
  message = [0, 0, 0] 
  i = 0
  status = 0 # 0:Ignore; 1:Note Off; 2:Note On;3:Program Change
  laststatusByte = 0

  while True:
    data = ord(ser.read(1)) # read a byte
    print data
    if data >> 7 == 0 and status in (1,2):
      if i == 3: # midi rolling status
        message[0] = laststatusByte
        message[1] = data
        i = 2
      else:
        message[i] = data
        i += 1

    elif data >> 7 == 0 and status == 3:
      if i == 2: #midi rolling status
        message[0] = laststatusByte
        message[1] = data
        message[2] = 0
        i += 1
      else:  
        message[1] = data
        message[2] = 0
        i = 3

    elif data >> 4 in (8, 9, 12):
      message[0] = data
      laststatusByte = data
      if data >> 4 == 8: status = 1
      elif data >> 4 == 9: status = 2
      else: status = 3
      i = 1

    else: # Ignore al othe messages
      print "Ignore"
      status = 0
      i = 0

    if i == 3:
      MidiCallback(message, None)
J
jpg posted Jun 4, 21:03:

Thank you very much Kees for sharing!
I tried your code today but I face to the same problem: If I quickly play several notes, some of them are played again by themselves. My keyboard is plugged on the USB port of the raspberry.
Is your code solve this problem for you?

K
Kees posted Jun 6, 19:48:

Both USB and serial midi and both at the same time never gave me errors anymore. Doesn't matter how much notes I play at the same time, they are all played (and stopped) fine...

Which setup are you using?

J
jpg posted Jun 10, 22:54:

I used a Microkorg XL plugged by usb into the microsample.
I have no problem when I plug it into another midi device.

K
Kees posted Jun 11, 01:04:

Did you check the output using an program like Midi-ox or as I did, a saleae like logic analyzer?

J
jpg posted Jun 26, 11:14:

Everything seems to be normal.
When I play some chords and some notes, at the same time or not, slowly or quickly, I see all the note on/off midi messages.
I have also many clock messages.

Is there a way to debug something in the raspeberry to see how it manages the midi messages?

J
jpg posted Jun 26, 11:56:

Sorry, I forgot to answer to another question you asked in http://www.samplerbox.org/forum/147
I've got a Raspberry Pi 2 and the image is read only.

J
jpg posted Jun 26, 19:40:

Ouch! Modifying the code and trying to debug it with print messages
Sorry, I haven't seen the difference between MidiSerialCallback and MidiCallback... :-/

...

  (not published)
  I want to post as guest
 

Post