#!/usr/bin/python # (c) Steve Gutteridge 26 January 2013 # RaspberryPi@SallyAndSteve.com # http://SteveGutteridge.com # # Simple Midi Analyser # # For Midi interface and other config requirements, try this website: # http://www.siliconstuff.com/2012/08/serial-port-midi-on-raspberry-pi.html import serial import time controllers=('undefined','Modulation Wheel','Breath Controller','undefined','Foot Controller',\ 'Portamento Time','Data Entry Slider','Main Volume','Balance','undefined',\ 'Pan','Expression Controller','undefined','undefined','undefined',\ 'undefined','Gen Purpose Controller 1','Gen Purpose Controller 2','Gen Purpose Controller 3','Gen Purpose Controller 4',\ 'undefined','undefined','undefined','undefined','undefined',\ 'undefined','undefined','undefined','undefined','undefined',\ 'undefined','undefined','LSB for controller 0','LSB for controller 1','LSB for controller 2',\ 'LSB for controller 3','LSB for controller 4','LSB for controller 5','LSB for controller 6','LSB for controller 7',\ 'LSB for controller 8','LSB for controller 9','LSB for controller 10','LSB for controller 11','LSB for controller 12',\ 'LSB for controller 13','LSB for controller 14','LSB for controller 15','LSB for controller 16','LSB for controller 17',\ 'LSB for controller 18','LSB for controller 19','LSB for controller 20','LSB for controller 21','LSB for controller 22',\ 'LSB for controller 23','LSB for controller 24','LSB for controller 25','LSB for controller 26','LSB for controller 27',\ 'LSB for controller 28','LSB for controller 29','LSB for controller 30','LSB for controller 31','Damper Pedal',\ 'Portamento','Sostenuto','Soft Pedal','undefined','Hold 2',\ 'undefined','undefined','undefined','undefined','undefined',\ 'undefined','undefined','undefined','undefined','undefined',\ 'Gen Purpose Controller 5','Gen Purpose Controller 6','Gen Purpose Controller 7','Gen Purpose Controller 8','undefined',\ 'undefined','undefined','undefined','undefined','undefined',\ 'undefined','undefined','Tremelo Depth','Chorus Depth','Celeste (Detune) Depth',\ 'Phaser Depth','Data Increment','Data Decrement','Non Registered Parameter Number LSB','Non Registered Parameter Number MSB',\ 'Registered Parameter Number LSB','Registered Parameter Number MSB','undefined','undefined','undefined',\ 'undefined','undefined','undefined','undefined','undefined',\ 'undefined','undefined','undefined','undefined','undefined',\ 'undefined','undefined','undefined','undefined','undefined',\ 'undefined','undefined','Channel Mode Messages','Channel Mode Messages','Channel Mode Messages',\ 'Channel Mode Messages','Channel Mode Messages','Channel Mode Messages') serialport = serial.Serial("/dev/ttyAMA0", baudrate=38400, bytesize=8, parity='N', stopbits=1, xonxoff=0, rtscts=0, dsrdtr=0, timeout=0) print 'Awaiting MIDI input:' runningstatus='0x0' thisparam=1 params=1 while 1: c=serialport.read(1000) if c<>'': for x in c: v=ord(x) h=hex(v) if h=='0xf7': print 'System Exclusive End' continue else: if h=='0xf8': continue #Timing Tick. Ignore if h=='0xfe': continue #Active sensing. Ignore if v>127: #New Command midichannel=v%16 runningstatus=h[:3] thisparam=1 #Next byte will be parameter no.1 if runningstatus=='0x8': params=2 #Note Off has 2 parameters elif runningstatus=='0x9': params=2 elif runningstatus=='0xa': params=2 elif runningstatus=='0xb': params=2 elif runningstatus=='0xc': params=1 elif runningstatus=='0xd': params=1 elif runningstatus=='0xe': params=2 elif runningstatus=='0xf': runningstatus=h if runningstatus=='0xf2': params=2 elif runningstatus=='0xf0': params=1 #System Exclusive show params one at a time elif runningstatus=='0xf3': params=1 elif runningstatus=='0xf5': params=1 elif runningstatus=='0xf6': print 'Sysex Tune Request' elif runningstatus=='0xfa': print 'Sysex Start Song' elif runningstatus=='0xfb': print 'Sysex Continue Song' elif runningstatus=='0xfc': print 'Sysex Stop Song' elif runningstatus=='0xff': print 'Sysex System Reset' continue if thisparam==1: param1=v #First parameter else: param2=v #Second parameter if thisparam==params: #All Parameters are in so process the message if runningstatus=='0x9': #Note On if param2==0: print 'ch',midichannel,': Note',param1,'Off' else: print 'ch',midichannel,': Note On',param1,'Velocity',param2 elif runningstatus=='0x8': #Note Off print 'ch',midichannel,': Note Off',param1,'Release Velocity',param2 elif runningstatus=='0xa': #Key Pressure print 'ch',midichannel,': Key Pressure Note',param1,'Pressure',param2 elif runningstatus=='0xb': #Controller Change print 'ch',midichannel,': Controller',param1,controllers[param1],'Value',param2 elif runningstatus=='0xc': #Program Change print 'ch',midichannel,': Program Change',param1 elif runningstatus=='0xd': #Channel Pressure print 'ch',midichannel,': Channel Pressure',param1 elif runningstatus=='0xe': #Pitch Bend print 'ch',midichannel,': Pitch Bend LSB',param1,'MSB',param2 elif runningstatus=='0xf0': #System Exclusive print 'System Exclusive Data Byte',param1 elif runningstatus=='0xf2': #Song Position print 'Sysex Song Position LSB',param1,'MSB',param2 elif runningstatus=='0xf3': #Song Select print'Sysex Song Select',param1 elif runningstatus=='0xf5': #Unofficial Bus Select print'Sysex Unofficial Bus Select',param1 thisparam=1 # For Running Status might get another message of same type else: thisparam=thisparam+1