Dependencies:   mbed

Revision:
0:71d791204057
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/midi.h	Tue Jun 07 13:32:20 2011 +0000
@@ -0,0 +1,435 @@
+#ifndef MIDI_H
+#define MIDI_H
+
+#include <vector>
+
+#ifndef BYTE
+    #define BYTE
+    typedef unsigned char byte;
+#endif
+
+#ifndef WORD
+    #define WORD
+    typedef unsigned short word;
+#endif
+
+ // unused midi code serves as defining 'Not A Known Value':
+#define NAKN  253
+
+// out of 14bit range value serves as defining 'Not A Known Word':
+#define NAKW  0x5000
+
+// generic:
+#define NONE    0
+
+// values for member 'next':
+#define VALA    1
+#define VALB    2
+#define MSB     3
+#define LSB     4
+#define PAIR    5
+#define ITEM    6
+#define MSB2    7
+#define LSB2    8
+
+// values for member 'type':
+// channel message:
+#define NOTE    1
+#define POLA    2
+#define CTRL    3
+#define PROG    4
+#define BANK    5
+#define DATA    6
+#define INCR    7
+#define DECR    8
+#define RPN_    9
+#define NRPN   10
+#define MONA   11
+#define BEND   12
+// no channel message:
+#define SYSX   13
+#define TCOD   14
+#define SPOS   15
+#define SSEL   16
+#define TUNE   17
+#define CLOK   18
+#define STAR   19
+#define CONT   20
+#define STOP   21
+#define SENS   22
+#define RSET   23
+
+///////////////////////////////////////////////////////////////////////////////
+ // base class for all Messages
+//_____________________________________________________________________________
+class MidiM
+{//""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+public:
+    byte Command;
+    byte Type;
+    byte Channel;
+    byte Next; // expected type of next inconming byte
+    byte ValA; // data
+    byte ValB; // data
+    vector<byte> Raw;
+
+    MidiM( byte type )                  : Command(0), Type( type ), Channel( NAKN ), Next(NONE), ValA(NAKN), ValB(NAKN) {}
+    MidiM( byte type, byte ch )         : Command(0), Type( type ), Channel( ch ), Next(NONE), ValA(NAKN), ValB(NAKN) {}
+    virtual ~MidiM(){}
+
+    virtual bool Append( byte b) { Raw.push_back(b); return true; }
+
+    virtual byte ValCount() { return 0; }
+
+    short  Get14()
+    { 
+        return ( ValA == NAKN ? 0 : ValA << 7 ) + ( ValB == NAKN ? 0 : ValB ); 
+    }
+    void Set14( short v )
+    { 
+        ValA = ( v >> 7 ) & 127; 
+        ValB = v & 127; 
+        Next = NONE;
+    }
+};
+//_____________________________________________________________________________
+class MidiTune     : public MidiM 
+{//""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+public:
+    MidiTune()     : MidiM( TUNE )      { Raw.push_back( Command = 0xF6 ); } 
+    virtual ~MidiTune(){}
+//    virtual void Send( Serial &s )      { s.putc( 0xF6 ); } 
+};
+//_____________________________________________________________________________
+class MidiClock    : public MidiM 
+{//""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+public:
+    MidiClock()    : MidiM( CLOK )      { Raw.push_back( Command = 0xF8 ); } 
+    virtual ~MidiClock(){}
+//   virtual void Send( Serial &s )      { s.putc( 0xF8 ); } 
+};
+//_____________________________________________________________________________
+class MidiStart    : public MidiM 
+{//""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+public:
+    MidiStart()    : MidiM( STAR )      { Raw.push_back( Command = 0xFA ); }
+    virtual ~MidiStart(){}
+//    virtual void Send( Serial &s )      { s.putc( 0xFA ); }
+};
+//_____________________________________________________________________________
+class MidiContinue : public MidiM
+{//""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+public:
+    MidiContinue() : MidiM( CONT )      { Raw.push_back( Command = 0xFB ); }
+    virtual ~MidiContinue(){}
+//    virtual void Send( Serial &s )      { s.putc( 0xFB ); }
+};
+//_____________________________________________________________________________
+class MidiStop     : public MidiM
+{//""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+public:
+    MidiStop()     : MidiM( STOP )      { Raw.push_back( Command = 0xFC ); }
+    virtual ~MidiStop(){}
+//    virtual void Send( Serial &s )      { s.putc( 0xFC ); }
+};
+//_____________________________________________________________________________
+class MidiSensing  : public MidiM
+{//""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+public:
+    MidiSensing()  : MidiM( SENS )      { Raw.push_back( Command = 0xFE ); }
+    virtual ~MidiSensing(){}
+//    virtual void Send( Serial &s )      { s.putc( 0xFE ); }
+};
+//_____________________________________________________________________________
+class MidiReset    : public MidiM
+{//""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+public:
+    MidiReset()    : MidiM( RSET )      { Raw.push_back( Command = 0xFF ); }
+    virtual ~MidiReset(){}
+//    virtual void Send( Serial &s )      { s.putc( 0xFF ); }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// base class & derived classes for all Messages having 1 byte of data
+//_____________________________________________________________________________
+class MidiM1 : public MidiM 
+{//""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+public:
+    MidiM1( byte type, byte ch )         : MidiM( type, ch ) { Next = VALA; }
+    MidiM1( byte type, byte ch, byte v ) : MidiM( type, ch ) { Next = NONE; ValA = v; }
+    virtual ~MidiM1(){}
+    virtual bool Append( byte b )
+    { 
+        Raw.push_back(b);
+        if( b > 127 || Next == NONE  ) return false; 
+        Next = NONE; ValA = b; return true; 
+     }
+    virtual byte ValCount() { return 1; }
+};
+//_____________________________________________________________________________
+class MidiSelect   : public MidiM1
+{//""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+public: 
+    MidiSelect()                : MidiM1( SSEL, NAKN )      { Raw.push_back( Command = 0xF3 ); } 
+    MidiSelect( byte v )        : MidiM1( SSEL, NAKN, v )   { Raw.push_back( Command = 0xF3 ); } 
+    virtual ~MidiSelect(){}
+//    virtual void Send( Serial &s )          { s.putc( 0xF3 ); s.putc( ValA ); } 
+};
+//_____________________________________________________________________________
+class MidiTimeCode : public MidiM1 
+{//""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+public:
+    MidiTimeCode()              : MidiM1( TCOD, NAKN )      { Raw.push_back( Command = 0xF1 ); }
+    MidiTimeCode( byte v )      : MidiM1( TCOD, NAKN, v )   { Raw.push_back( Command = 0xF1 ); }
+    virtual ~MidiTimeCode(){}
+//    virtual void Send( Serial &s )          { s.putc( 0xF1 ); s.putc( ValA ); } 
+};
+//_____________________________________________________________________________
+class MidiProgram  : public MidiM1 
+{//""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+public:
+    MidiProgram( byte ch )           : MidiM1( PROG, ch )   { Raw.push_back( ( Command = 0xC0 ) + ch ); }
+    MidiProgram( byte ch, byte v )   : MidiM1( PROG, ch, v ){ Raw.push_back( ( Command = 0xC0 ) + ch ); }
+    virtual ~MidiProgram(){}
+//    virtual void Send( Serial &s ){ s.putc( 0xC0 + Channel ); s.putc( ValA ); }
+};
+//_____________________________________________________________________________                            
+class MidiMonoAft  : public MidiM1 
+{//""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+public:
+    MidiMonoAft( byte ch )           : MidiM1( MONA, ch )   { Raw.push_back( ( Command = 0xD0 ) + ch ); }
+    MidiMonoAft( byte ch, byte v )   : MidiM1( MONA, ch, v ){ Raw.push_back( ( Command = 0xD0 ) + ch ); }
+    virtual ~MidiMonoAft(){}
+//    virtual void Send( Serial &s ){ s.putc( 0xD0 + Channel ); s.putc( ValA ); }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// base class & derived classes for all Messages having 2 byte of data
+//_____________________________________________________________________________                            
+class MidiM2 : public MidiM 
+{//""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+public:
+    MidiM2(byte type,byte ch)              : MidiM(type,ch){ Next = VALA; }
+    MidiM2(byte type,byte ch,byte v)       : MidiM(type,ch){Next=VALB;ValA=v;}
+    MidiM2(byte type,byte ch,byte v,byte w): MidiM(type,ch){Next=NONE;ValA=v;ValB=w;}
+    virtual ~MidiM2(){}
+    virtual byte ValCount() { return 2; }
+
+    virtual bool Append( byte b )
+    {
+        Raw.push_back(b);
+        if( b > 127 || Next == NONE ) return false;
+        if( Next == VALA ) { ValA = b; Next = VALB; }
+        else               { ValB = b; Next = NONE; }
+        return true;
+    }
+};
+//_____________________________________________________________________________                            
+class MidiPosition : public MidiM2 
+{//""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+public:
+    MidiPosition()             : MidiM2( SPOS, NAKN )       { Raw.push_back( Command = 0xF3 ); } 
+    MidiPosition( byte v )     : MidiM2( SPOS, NAKN, v )    { Raw.push_back( Command = 0xF3 ); } 
+    MidiPosition( byte v, byte w ) : MidiM2( SPOS, NAKN, v, w ) { Command = 0xF3; } 
+    virtual ~MidiPosition(){}
+//    virtual void Send( Serial &s ){ s.putc(0xF3); s.putc(ValA); s.putc(ValB); }
+};
+//_____________________________________________________________________________                            
+class MidiNoteOn   : public MidiM2 
+{//""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+public:
+    MidiNoteOn( byte ch )        : MidiM2( NOTE, ch )       { Raw.push_back( ( Command = 0x90 ) + ch ); }
+    MidiNoteOn( byte ch, byte v ): MidiM2( NOTE, ch, v )    { Raw.push_back( ( Command = 0x90 ) + ch ); }
+    MidiNoteOn( byte ch, byte v, byte w ) : MidiM2( NOTE, ch, v, w ) { Command = 0x90; }
+    virtual ~MidiNoteOn(){}
+/*    virtual void Send( Serial &s )
+    {
+        s.putc( 0x90 + Channel ); s.putc( ValA ); s.putc( ValB );
+    }*/
+};
+//_____________________________________________________________________________                            
+class MidiNoteOff  : public MidiM2 
+{//""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+public:
+    MidiNoteOff( byte ch )       : MidiM2( NOTE, ch )       { Raw.push_back( ( Command = 0x80 ) + ch ); }
+    MidiNoteOff( byte ch, byte v ): MidiM2( NOTE, ch, v )    { Raw.push_back( ( Command = 0x80 ) + ch ); }
+    MidiNoteOff( byte ch, byte v, byte w ): MidiM2( NOTE, ch, v, w ) { Command = 0x80; }
+    virtual ~MidiNoteOff(){}
+/*    virtual void Send( Serial &s )
+    {
+        s.putc( 0x80 + Channel ); s.putc( ValA ); s.putc( ValB );
+    }*/
+};
+//_____________________________________________________________________________                            
+class MidiPolyAft  : public MidiM2 
+{//""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+public:
+    MidiPolyAft( byte ch )       : MidiM2( POLA, ch )       { Raw.push_back( ( Command = 0xA0 ) + ch ); }
+    MidiPolyAft( byte ch, byte v ): MidiM2( POLA, ch, v )    { Raw.push_back( ( Command = 0xA0 ) + ch ); }
+    MidiPolyAft( byte ch, byte v, byte w ): MidiM2( POLA, ch, v, w ) { Command = 0xA0; }
+    virtual ~MidiPolyAft(){}
+/*    virtual void Send( Serial &s )
+    {
+        s.putc( 0xA0 + Channel ); s.putc( ValA ); s.putc( ValB );
+    }*/
+};
+//_____________________________________________________________________________                            
+class MidiBend     : public MidiM2 
+{//""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+public:
+    MidiBend( byte ch )          : MidiM2( BEND, ch )       { Raw.push_back( ( Command = 0xE0 ) + ch ); }
+    MidiBend( byte ch, byte v )  : MidiM2( BEND, ch, v )    { Raw.push_back( ( Command = 0xE0 ) + ch ); }
+    MidiBend( byte ch, byte v, byte w ): MidiM2( BEND, ch, v, w ) { Command = 0xE0; }
+    virtual ~MidiBend(){}
+/*    virtual void Send( Serial &s )
+    {
+        s.putc( 0xE0 + Channel ); s.putc( ValA ); s.putc( ValB );
+    }*/
+};
+//_____________________________________________________________________________                            
+class MidiControl  : public MidiM2 
+{//""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+public:
+    MidiControl( byte ch )       : MidiM2( CTRL, ch )       { Raw.push_back( ( Command = 0xB0 ) + ch ); }
+    MidiControl( byte ch, byte v ): MidiM2( CTRL, ch, v )   { Raw.push_back( ( Command = 0xB0 ) + ch ); }
+    MidiControl( byte ch, byte v, byte w ): MidiM2( CTRL, ch, v, w ) { Command = 0xB0; }
+    virtual ~MidiControl(){}
+/*    virtual void Send( Serial &s )           
+    {
+        byte c = 0xB0 + Channel;
+        switch( Type ) {
+            case CTRL :                    s.putc( c ); s.putc(ValA ); s.putc( ValB ); break;
+            case BANK : if( ValA != NAKN ) s.putc( c ); s.putc(   0 ); s.putc( ValA );
+                        if( ValB != NAKN ) s.putc( c ); s.putc(  32 ); s.putc( ValB ); break;
+            case DATA : if( ValA != NAKN ) s.putc( c ); s.putc(   6 ); s.putc( ValA );
+                        if( ValB != NAKN ) s.putc( c ); s.putc(  38 ); s.putc( ValB ); break;
+            case INCR :                    s.putc( c ); s.putc(  96 );                 break;
+            case DECR :                    s.putc( c ); s.putc(  97 );                 break;
+            case NRPN : if( ValA != NAKN ) s.putc( c ); s.putc(  99 ); s.putc( ValA );
+                        if( ValB != NAKN ) s.putc( c ); s.putc(  98 ); s.putc( ValB ); break;
+            case RPN_ : if( ValA != NAKN ) s.putc( c ); s.putc( 101 ); s.putc( ValA );
+                        if( ValB != NAKN ) s.putc( c ); s.putc( 100 ); s.putc( ValB ); break;
+        }        
+    }*/
+    virtual bool Append( byte b )
+    {
+        Raw.push_back(b);
+        switch( Next ) {
+            case VALA: 
+                if( HasBank || HasData )
+                        switch( b ) {
+                        case   0:   if( HasBank ) { Next=MSB;  Type=BANK; }
+                                    else          { Next=VALB; ValA=b;    } return true;
+
+                        case  32:   if( HasBank ) { Next=LSB;  Type=BANK; }
+                                    else          { Next=VALB; ValA=b;    } return true;
+
+                        case   6:   if( HasData ) { Next=MSB;  Type=DATA; }
+                                    else          { Next=VALB; ValA=b;    } return true;
+                       
+                        case  38:   if( HasData ) { Next=LSB;  Type=DATA; }
+                                    else          { Next=VALB; ValA=b;    } return true;
+                       
+                        case  96:   if( HasData ) { Next=NONE;  Type=INCR; }
+                                    else          { Next=VALB; ValA=b;    } return true;
+
+                        case  97:   if( HasData ) { Next=NONE;  Type=DECR; }
+                                    else          { Next=VALB; ValA=b;    } return true;
+                       
+                        case  98:   if( HasData ) { Next=LSB;  Type=NRPN; }
+                                    else          { Next=VALB; ValA=b;    } return true;
+                       
+                        case  99:   if( HasData ) { Next=MSB;  Type=NRPN; }
+                                    else          { Next=VALB; ValA=b;    } return true;
+
+                        case 100:   if( HasData ) { Next=LSB;  Type=NRPN; }
+                                    else          { Next=VALB; ValA=b;    } return true;
+                       
+                        case 101:   if( HasData ) { Next=MSB;  Type=NRPN; }
+                                    else          { Next=VALB; ValA=b;    } return true;
+
+                        default:    Next = VALB;    ValA = b;               return true;
+                       }
+                else{
+                                    Next = VALB;
+                                    ValA = b;
+                                    return true;
+                }                                    
+            case VALB:              Next = NONE;    ValB = b;       return true;
+            case MSB:               Next = PAIR;    ValA = b;       return true; // wait for 0xB*
+            case LSB:               Next = PAIR;    ValB = b;       return true; // wait for 0xB*
+            case MSB2:              Next = NONE;    ValA = b;       return true;
+            case LSB2:              Next = NONE;    ValB = b;       return true;
+            case PAIR:              Next = ITEM;                    return true; // 0xB*
+            case ITEM: 
+                switch( Type ) {
+                    case BANK: if( b!=  0 && b!= 32 ){ Next = NONE; return false; }
+                                    Next = b ==  0 ? MSB2 : LSB2;   return true;
+                    case DATA: if( b!=  6 && b!= 38 ){ Next = NONE; return false; }
+                                    Next = b ==  6  ? MSB2 : LSB2;   return true;
+                    case NRPN: if( b!= 98 && b!= 99 ){ Next = NONE; return false; }
+                                    Next = b == 99 ? MSB2 : LSB2;   return true;
+                    case RPN_: if( b!=100 && b!=101 ){ Next = NONE; return false; }
+                                    Next = b ==101 ? MSB2 : LSB2;   return true;
+                }    
+        }
+        return false;
+    }
+
+};
+
+//_____________________________________________________________________________                            
+class MidiX : public MidiM2 // class for SysEx message
+{//""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+public:
+    MidiX() : MidiM2( SYSX, NAKN ){ Raw.push_back( Command = 0xF0 ); }
+    virtual ~MidiX(){}
+    virtual bool Append( byte b )
+    {
+        Raw.push_back(b);
+        if( b==0xF7 ) 
+            Next = NONE; 
+        return true;
+    }
+};
+
+//_____________________________________________________________________________                            
+MidiM* MidiCreateMessage( byte command )
+{//""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+    if( command >= 0xF0 )
+        switch( command ) {
+            case 0xF0: return new MidiX();
+            case 0xF1: return new MidiTimeCode();
+            case 0xF2: return new MidiPosition();
+            case 0xF3: return new MidiSelect();
+            case 0xF6: return new MidiTune();
+            case 0xF8: return new MidiClock();
+            case 0xFA: return new MidiStart();
+            case 0xFB: return new MidiContinue();
+            case 0xFC: return new MidiStop();
+            case 0xFE: return new MidiSensing();
+            case 0xFF: return new MidiReset();
+        }
+    else switch( command >> 4 ) {
+            case 0x8: return new MidiNoteOff( command & 15 );
+            case 0x9: return new MidiNoteOn ( command & 15 );
+            case 0xA: return new MidiPolyAft( command & 15 );
+            case 0xB: return new MidiControl( command & 15 );
+            case 0xC: return new MidiProgram( command & 15 );
+            case 0xD: return new MidiMonoAft( command & 15 );
+            case 0xE: return new MidiBend   ( command & 15 );
+    
+        }
+    return new MidiM( NONE );
+}
+
+#undef VALA
+#undef VALB
+#undef MSB
+#undef LSB
+#undef PAIR
+#undef ITEM
+#undef MSB2
+#undef LSB2
+
+#endif
\ No newline at end of file