Dependencies:   mbed

Committer:
Midimetric
Date:
Tue Jun 07 13:32:20 2011 +0000
Revision:
0:71d791204057
Version 1.0

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Midimetric 0:71d791204057 1 #include <vector>
Midimetric 0:71d791204057 2 #include "midi.h"
Midimetric 0:71d791204057 3 #include "stack.h"
Midimetric 0:71d791204057 4 #include "memory.h"
Midimetric 0:71d791204057 5
Midimetric 0:71d791204057 6 #define TO_OUT1 1
Midimetric 0:71d791204057 7 #define TO_OUT2 2
Midimetric 0:71d791204057 8 #define TO_OUT3 4
Midimetric 0:71d791204057 9
Midimetric 0:71d791204057 10 #define BitSet( flag, bit ) ( ( flag >> bit ) & 1 )
Midimetric 0:71d791204057 11 #define BitPut( flag, bit ) ( flag | ( 1 << bit ) )
Midimetric 0:71d791204057 12 #define BitDel( flag, bit ) ( flag & ~( 1 << bit ) )
Midimetric 0:71d791204057 13
Midimetric 0:71d791204057 14 // literals are either 8 bits ( 0 to 255 ) or 14 bits ( 0 to 16383 / -8192 to 8191 )
Midimetric 0:71d791204057 15 // commands are coded with bit 14 set (above 16383 ) but not with bit 15 to leave negative down to -8192 to literals and to avoid ambiguity
Midimetric 0:71d791204057 16
Midimetric 0:71d791204057 17 #define ISCOMMAND(x) ( (x & 0xF000) == 0x4000 )
Midimetric 0:71d791204057 18
Midimetric 0:71d791204057 19 // sequence delimiter
Midimetric 0:71d791204057 20 #define SEQ 0x4000 // escape; introducing a sequence in a Chain:
Midimetric 0:71d791204057 21 #define E7_ 0x4001 // return 7 bits byte from computation
Midimetric 0:71d791204057 22 #define E8_ 0x4002 // return 8 bits byte from computation
Midimetric 0:71d791204057 23 #define E14 0x4003 // return 14 bits word from computation (msb then lsb)
Midimetric 0:71d791204057 24 #define NOP 0x4004 // nul terminator in sequence array
Midimetric 0:71d791204057 25 #define RAW 0x4005 // output is raw input (no change)
Midimetric 0:71d791204057 26 // VALUES
Midimetric 0:71d791204057 27 #define VMC 0x4010 // =%mc Full midi command (base command + channel), can be used in sequence or alone
Midimetric 0:71d791204057 28 #define VM_ 0x4011 // =%m Base midi command (4 msb of VMC ), can be used in sequence or alone
Midimetric 0:71d791204057 29 #define VC_ 0x4012 // =%c Value of Channel (4 lsb of VMC )
Midimetric 0:71d791204057 30 #define VA_ 0x4013 // Value A, can be used in sequence or alone
Midimetric 0:71d791204057 31 #define VB_ 0x4014 // Value B
Midimetric 0:71d791204057 32 #define VN_ 0x4015 // RPN or NRPN 14bits number
Midimetric 0:71d791204057 33 #define VD_ 0x4016 // RPN or NRPN 14bits data
Midimetric 0:71d791204057 34 #define VK_ 0x4017 // Bank 14bits data
Midimetric 0:71d791204057 35
Midimetric 0:71d791204057 36 // FUNCTIONS
Midimetric 0:71d791204057 37 #define ADD 0x4020
Midimetric 0:71d791204057 38 #define SUB 0x4021 // Add 14 bits value as signed integer, bound to 0 - 0xFFFF
Midimetric 0:71d791204057 39 #define MUL 0x4022
Midimetric 0:71d791204057 40 #define DIV 0x4023
Midimetric 0:71d791204057 41 #define MOD 0x4024
Midimetric 0:71d791204057 42 #define BIT 0x4125 // folowing int is index value then bit shift then bits count
Midimetric 0:71d791204057 43 #define BOR 0x4026 // bynary OR
Midimetric 0:71d791204057 44 #define BAN 0x4027 // bynary AND
Midimetric 0:71d791204057 45 #define BNO 0x4028 // bynary NOT
Midimetric 0:71d791204057 46 #define BSL 0x4029 // bynary shift left (<<)
Midimetric 0:71d791204057 47 #define BSR 0x402A // bynary shift right (>>)
Midimetric 0:71d791204057 48 #define MAP 0x402B // discrete value mapping
Midimetric 0:71d791204057 49 #define RPN 0x402C // RPN type formated output
Midimetric 0:71d791204057 50 #define NPN 0x402D // NRPN type formated output
Midimetric 0:71d791204057 51 #define BNK 0x402E // Bank type formated output
Midimetric 0:71d791204057 52 #define MSB 0x402F // msb part of value
Midimetric 0:71d791204057 53 #define LSB 0x4030 // lsb part of value
Midimetric 0:71d791204057 54 #define NP8 0x4031 // 8 bit value NRPN (sends only CC6 not CC38)
Midimetric 0:71d791204057 55
Midimetric 0:71d791204057 56 // checkSUm
Midimetric 0:71d791204057 57 // - compute checksum from value after 'SUB' to value before 'SUE'
Midimetric 0:71d791204057 58 #define CSB 0x4040 // checkSUm Begin
Midimetric 0:71d791204057 59 #define CSE 0x4041 // checkSUm End
Midimetric 0:71d791204057 60 #define CS1 0x4042 // insert 8 bit checksum at position (careful:may appear before SUB-SUE range)
Midimetric 0:71d791204057 61 #define CS2 0x4043 // 32 bits checksum
Midimetric 0:71d791204057 62 // Checksum Type1 (Roland) : -( sum( SUB -> SUE ) & 127 ) & 127
Midimetric 0:71d791204057 63 // Checksum Type2 (Alesis) : -( sum( SUB -> SUE ) & 0xFFFF ) & 0xFFFF
Midimetric 0:71d791204057 64
Midimetric 0:71d791204057 65 // custom identifiers
Midimetric 0:71d791204057 66 #define CID 0x4100 // end of Custom IDentifier
Midimetric 0:71d791204057 67 // 0x41cc // cc = ascii char index
Midimetric 0:71d791204057 68 #define CUL 0x4200 // Custom identifier character set Upper Limit
Midimetric 0:71d791204057 69
Midimetric 0:71d791204057 70 #if _DEBUGFILTER
Midimetric 0:71d791204057 71 #include "filter_debug.h"
Midimetric 0:71d791204057 72 #endif
Midimetric 0:71d791204057 73
Midimetric 0:71d791204057 74 // error codes returned by Compute
Midimetric 0:71d791204057 75 #define CHAIN_SKIPROUTE -1
Midimetric 0:71d791204057 76 #define CHAIN_NOERROR 0
Midimetric 0:71d791204057 77 #define CHAIN_STACK_FAILURE 1
Midimetric 0:71d791204057 78 #define CHAIN_MISSING_SUB 2
Midimetric 0:71d791204057 79 #define CHAIN_MISSING_SUE 3
Midimetric 0:71d791204057 80 #define CHAIN_SUB_AFTER_SUE 4
Midimetric 0:71d791204057 81 #define CHAIN_NOT_A_BYTE 5
Midimetric 0:71d791204057 82 #define CHAIN_UNKNOWN_OP 6
Midimetric 0:71d791204057 83 #define CHAIN_SYNTAXE_ERROR 7
Midimetric 0:71d791204057 84 #define CHAIN_DIVIDE_BY_ZERO 8
Midimetric 0:71d791204057 85
Midimetric 0:71d791204057 86 #define NEXT i++; break;
Midimetric 0:71d791204057 87 #define PUSH(x) Out.push_back(x)
Midimetric 0:71d791204057 88
Midimetric 0:71d791204057 89 short bitmasking[] = {0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383};
Midimetric 0:71d791204057 90
Midimetric 0:71d791204057 91 //_____________________________________________________________________________
Midimetric 0:71d791204057 92 class Chain
Midimetric 0:71d791204057 93 {//""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
Midimetric 0:71d791204057 94 // a chain defines for each port a message composed of fixed bytes or symbols
Midimetric 0:71d791204057 95 public:
Midimetric 0:71d791204057 96 vector<short> Msg[3];
Midimetric 0:71d791204057 97 vector<byte> Out;
Midimetric 0:71d791204057 98
Midimetric 0:71d791204057 99 Chain() { }
Midimetric 0:71d791204057 100 Chain( vector<short> &msg1, vector<short> &msg2, vector<short> &msg3 ) { Msg[0] = msg1; Msg[1] = msg2; Msg[2] = msg3; }
Midimetric 0:71d791204057 101 ~Chain() { }
Midimetric 0:71d791204057 102
Midimetric 0:71d791204057 103 void Done() // clear output vector until next compute to avoid keeping computation for all filters in memory
Midimetric 0:71d791204057 104 {
Midimetric 0:71d791204057 105 Out.clear();
Midimetric 0:71d791204057 106 }
Midimetric 0:71d791204057 107 short Compute( byte port, MidiM &cur, MidiM &prev ) // 0=ok, else return error code
Midimetric 0:71d791204057 108 {
Midimetric 0:71d791204057 109 short max = Msg[port].size();
Midimetric 0:71d791204057 110 if( max == 0 ) return -1;
Midimetric 0:71d791204057 111
Midimetric 0:71d791204057 112 Stack<long> k;
Midimetric 0:71d791204057 113 long a,b,c,d; // temp
Midimetric 0:71d791204057 114 short i = 0; // next position in Msg
Midimetric 0:71d791204057 115 bool s = false; // true when "in sequence"
Midimetric 0:71d791204057 116 short csb = -1; // position of check sum begin
Midimetric 0:71d791204057 117 short cse = -1; // position of check sum end
Midimetric 0:71d791204057 118 short csu = 0; // position where to insert check sum
Midimetric 0:71d791204057 119 short cst = 0; // check sum type
Midimetric 0:71d791204057 120
Midimetric 0:71d791204057 121 Out.clear();
Midimetric 0:71d791204057 122
Midimetric 0:71d791204057 123 while( i < max )
Midimetric 0:71d791204057 124 {
Midimetric 0:71d791204057 125 short n = Msg[port][i];
Midimetric 0:71d791204057 126 if( ! s ) // out of sequence, expect a byte value or a custom identifier or SEQ
Midimetric 0:71d791204057 127 {
Midimetric 0:71d791204057 128 if( n < 256 ) { PUSH( (byte)n ); i++; } // just copy fixed message byte
Midimetric 0:71d791204057 129 else if( ! ISCOMMAND( n ) ) return CHAIN_NOT_A_BYTE; // short values are not allowed outside of sequence
Midimetric 0:71d791204057 130 else switch( n ) {
Midimetric 0:71d791204057 131 case SEQ : s = true; NEXT
Midimetric 0:71d791204057 132 case VMC : PUSH( cur.Command | ( cur.Channel == NAKN ? 0 : cur.Channel ) ); NEXT
Midimetric 0:71d791204057 133 case VM_ : PUSH( cur.Command ); NEXT
Midimetric 0:71d791204057 134 case VC_ : PUSH( cur.Channel == NAKN ? 0 : cur.Channel ); NEXT
Midimetric 0:71d791204057 135 case VA_ : PUSH( cur.ValA ); NEXT
Midimetric 0:71d791204057 136 case VB_ : PUSH( cur.ValB ); NEXT
Midimetric 0:71d791204057 137 case VN_ : PUSH( prev.ValA ); PUSH( prev.ValB ); NEXT
Midimetric 0:71d791204057 138 case VD_ : PUSH( cur.ValA ); PUSH( cur.ValB ); NEXT
Midimetric 0:71d791204057 139 case VK_ : PUSH( cur.ValA ); PUSH( cur.ValB ); NEXT
Midimetric 0:71d791204057 140
Midimetric 0:71d791204057 141 case RAW : if( ( cur.Type == DATA || cur.Type == INCR || cur.Type == DECR )
Midimetric 0:71d791204057 142 && ( prev.Type == NRPN || prev.Type == RPN_ ) )
Midimetric 0:71d791204057 143 {
Midimetric 0:71d791204057 144 Out = prev.Raw; Out.insert( Out.end(), cur.Raw.begin(), cur.Raw.end() );
Midimetric 0:71d791204057 145 }
Midimetric 0:71d791204057 146 else Out = cur.Raw;
Midimetric 0:71d791204057 147 return 0;
Midimetric 0:71d791204057 148
Midimetric 0:71d791204057 149 default : {char id[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; short idi = 0;
Midimetric 0:71d791204057 150 while( n > CID && n < CUL ) { id[idi++] = (char)(n - CID); n = Msg[port][++i]; }
Midimetric 0:71d791204057 151 PUSH( (byte)ML.Get( id ) ); } NEXT
Midimetric 0:71d791204057 152 }
Midimetric 0:71d791204057 153 }
Midimetric 0:71d791204057 154 else if( ! ISCOMMAND( n ) ) // 14 bit literal inside a sequence, push on stack
Midimetric 0:71d791204057 155 {
Midimetric 0:71d791204057 156 k.Push( n ); i++;
Midimetric 0:71d791204057 157 }
Midimetric 0:71d791204057 158 else switch( n )
Midimetric 0:71d791204057 159 {
Midimetric 0:71d791204057 160 case NOP : NEXT
Midimetric 0:71d791204057 161 case E7_ : k.Pull(a); if(a < 0) a=0; else if(a > 127) a=127; PUSH(a); s = false; NEXT
Midimetric 0:71d791204057 162 case E8_ : k.Pull(a); if(a < 0) a=0; else if(a > 255) a=255; PUSH(a); s = false; NEXT
Midimetric 0:71d791204057 163 case E14 : k.Pull(a); PUSH( (byte)(a >> 7) & 127 ); PUSH(a & 127); s = false; NEXT
Midimetric 0:71d791204057 164 case VMC : k.Push( cur.Command|( cur.Channel == NAKN ? 0 : cur.Channel ) ); NEXT
Midimetric 0:71d791204057 165 case VM_ : k.Push( cur.Command ); NEXT
Midimetric 0:71d791204057 166 case VC_ : k.Push( ( cur.Channel == NAKN ? 0 : cur.Channel ) ); NEXT
Midimetric 0:71d791204057 167 case VA_ : k.Push( cur.ValA ); NEXT
Midimetric 0:71d791204057 168 case VB_ : k.Push( cur.ValB ); NEXT
Midimetric 0:71d791204057 169 case VN_ : k.Push( prev.Get14() ); NEXT
Midimetric 0:71d791204057 170 case VD_ : k.Push( cur.Get14() ); NEXT
Midimetric 0:71d791204057 171 case VK_ : k.Push( cur.Get14() ); NEXT
Midimetric 0:71d791204057 172 case ADD : k.Pull( b, a ); k.Push( a + b ); NEXT
Midimetric 0:71d791204057 173 case SUB : k.Pull( b, a ); k.Push( a - b ); NEXT
Midimetric 0:71d791204057 174 case MUL : k.Pull( b, a ); k.Push( a * b ); NEXT
Midimetric 0:71d791204057 175 case DIV : k.Pull( b, a ); if(b==0) return CHAIN_DIVIDE_BY_ZERO; k.Push( a / b ); NEXT
Midimetric 0:71d791204057 176 case MOD : k.Pull( b, a ); if(b==0) return CHAIN_DIVIDE_BY_ZERO; k.Push( a % b ); NEXT
Midimetric 0:71d791204057 177 case BIT : k.Pull( c,b,a); k.Push(cur.Raw[a] >> b & bitmasking[c]); NEXT
Midimetric 0:71d791204057 178 case BOR : k.Pull( b, a ); k.Push( a | b ); NEXT
Midimetric 0:71d791204057 179 case BAN : k.Pull( b, a ); k.Push( a & b ); NEXT
Midimetric 0:71d791204057 180 case BNO : k.Pull( a ); k.Push( ~a ); NEXT
Midimetric 0:71d791204057 181 case BSL : k.Pull( b, a ); k.Push( a << b ); NEXT
Midimetric 0:71d791204057 182 case BSR : k.Pull( b, a ); k.Push( a >> b ); NEXT
Midimetric 0:71d791204057 183 case MSB : k.Pull( a ); k.Push( a >> 7 ); NEXT
Midimetric 0:71d791204057 184 case LSB : k.Pull( a ); k.Push( a & 127 ); NEXT
Midimetric 0:71d791204057 185 case CSB : csb=Out.size(); s = false; /*quit sequence not waiting for END*/ NEXT
Midimetric 0:71d791204057 186 case CSE : cse=Out.size(); s = false; NEXT
Midimetric 0:71d791204057 187 case CS1 : csu=Out.size(); cst=1; PUSH(0); NEXT
Midimetric 0:71d791204057 188 case CS2 : csu=Out.size(); cst=2; PUSH(0); PUSH(0); PUSH(0); PUSH(0); NEXT
Midimetric 0:71d791204057 189 case MAP : k.Pull( d, a, c, b ); d--;
Midimetric 0:71d791204057 190 while( a != b )
Midimetric 0:71d791204057 191 if( ( d -= 2 ) == 0 ) return CHAIN_SKIPROUTE;
Midimetric 0:71d791204057 192 else k.Pull( c, b );
Midimetric 0:71d791204057 193 while( d -= 2 ) k.Pull(a,b); /* unstack unused values */ k.Push( c ); NEXT
Midimetric 0:71d791204057 194 case NPN : k.Pull( c,b,a); a &= 15;
Midimetric 0:71d791204057 195 if( b > 127 ) { PUSH( 0xB0 + a ); PUSH( 99 ); PUSH( ( b >> 7 ) & 127 ); }
Midimetric 0:71d791204057 196 PUSH( 0xB0 + a ); PUSH( 98 ); PUSH( b & 127 );
Midimetric 0:71d791204057 197 PUSH( 0xB0 + a ); PUSH( 6 ); PUSH( ( c >> 7 ) & 127 );
Midimetric 0:71d791204057 198 PUSH( 0xB0 + a ); PUSH( 38 ); PUSH( c & 127 ); NEXT
Midimetric 0:71d791204057 199
Midimetric 0:71d791204057 200 case NP8 : k.Pull( c,b,a); a &= 15;
Midimetric 0:71d791204057 201 if( b > 127 ) { PUSH( 0xB0 + a ); PUSH( 99 ); PUSH( ( b >> 7 ) & 127 ); }
Midimetric 0:71d791204057 202 PUSH( 0xB0 + a ); PUSH( 98 ); PUSH( b & 127 );
Midimetric 0:71d791204057 203 PUSH( 0xB0 + a ); PUSH( 6 ); PUSH( c & 127 ); NEXT
Midimetric 0:71d791204057 204
Midimetric 0:71d791204057 205 case RPN : k.Pull( c,b,a); a &= 15;
Midimetric 0:71d791204057 206 if( b > 127 ) { PUSH( 0xB0 + a ); PUSH(101 ); PUSH( ( b >> 7 ) & 127 ); }
Midimetric 0:71d791204057 207 PUSH( 0xB0 + a ); PUSH(100 ); PUSH( b & 127 );
Midimetric 0:71d791204057 208 PUSH( 0xB0 + a ); PUSH( 6 ); PUSH( ( c >> 7 ) & 127 );
Midimetric 0:71d791204057 209 PUSH( 0xB0 + a ); PUSH( 38 ); PUSH( c & 127 ); NEXT
Midimetric 0:71d791204057 210
Midimetric 0:71d791204057 211 case BNK : k.Pull( b, a ); a &= 15;
Midimetric 0:71d791204057 212 if( b > 127 ) { PUSH( 0xB0 + a ); PUSH( 0 ); PUSH( ( b >> 7 ) & 127 ); }
Midimetric 0:71d791204057 213 PUSH( 0xB0 + a ); PUSH( 32 ); PUSH( b & 127 ); NEXT
Midimetric 0:71d791204057 214 default:
Midimetric 0:71d791204057 215 if( n <= CID && n > CID + 0xFF )return CHAIN_UNKNOWN_OP;
Midimetric 0:71d791204057 216 {char id[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; short idi = 0;
Midimetric 0:71d791204057 217 while( n > CID && n < CUL ) { id[idi++] = (char)(n - CID);
Midimetric 0:71d791204057 218 n = Msg[port][++i]; } k.Push( (byte)ML.Get( id ) ); } NEXT
Midimetric 0:71d791204057 219 }
Midimetric 0:71d791204057 220 }
Midimetric 0:71d791204057 221 c = 0;
Midimetric 0:71d791204057 222 if( cst )
Midimetric 0:71d791204057 223 {
Midimetric 0:71d791204057 224 if( csb == -1 ) return CHAIN_MISSING_SUB;
Midimetric 0:71d791204057 225 if( cse == -1 ) return CHAIN_MISSING_SUE;
Midimetric 0:71d791204057 226 if( csb >= cse ) return CHAIN_SUB_AFTER_SUE;
Midimetric 0:71d791204057 227 }
Midimetric 0:71d791204057 228 if( cst == 1 )
Midimetric 0:71d791204057 229 {
Midimetric 0:71d791204057 230 for( i = csb ; i < cse ; i++ )
Midimetric 0:71d791204057 231 c -= Out[i];
Midimetric 0:71d791204057 232 Out[csu]= (byte)( c & 127 );
Midimetric 0:71d791204057 233 }
Midimetric 0:71d791204057 234 if( cst == 2 )
Midimetric 0:71d791204057 235 {
Midimetric 0:71d791204057 236 for( i = csb ; i < cse ; i += 4 )
Midimetric 0:71d791204057 237 c -= Out[i] + ( Out[i+1] << 8 ) + ( Out[i+2] << 16 ) + ( Out[i+3] << 24 );
Midimetric 0:71d791204057 238 Out[csu++]= (byte)( c );
Midimetric 0:71d791204057 239 Out[csu++]= (byte)( c >> 8 );
Midimetric 0:71d791204057 240 Out[csu++]= (byte)( c >> 16 );
Midimetric 0:71d791204057 241 Out[csu ]= (byte)( c >> 24 );
Midimetric 0:71d791204057 242 }
Midimetric 0:71d791204057 243
Midimetric 0:71d791204057 244 return 0;
Midimetric 0:71d791204057 245 }
Midimetric 0:71d791204057 246 };
Midimetric 0:71d791204057 247 //_____________________________________________________________________________
Midimetric 0:71d791204057 248 class Assignment
Midimetric 0:71d791204057 249 {//""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
Midimetric 0:71d791204057 250 public:
Midimetric 0:71d791204057 251 char Name[17];
Midimetric 0:71d791204057 252 vector<short> Msg;
Midimetric 0:71d791204057 253 short Value;
Midimetric 0:71d791204057 254
Midimetric 0:71d791204057 255 Assignment() { Name[0] = 0; Value = NOP; }
Midimetric 0:71d791204057 256 Assignment( char* name, vector<short> &msg ) { strncpy( Name, name, 17 ); Msg = msg; Value = NOP; }
Midimetric 0:71d791204057 257 ~Assignment() { }
Midimetric 0:71d791204057 258
Midimetric 0:71d791204057 259 short Compute( MidiM &cur, MidiM &prev ) // 0=ok, else return error code
Midimetric 0:71d791204057 260 {
Midimetric 0:71d791204057 261 Stack<long> k;
Midimetric 0:71d791204057 262 long a,b,c,d; // temp
Midimetric 0:71d791204057 263 short i = 0; // next position in Msg
Midimetric 0:71d791204057 264 bool s = false; // true when "in sequence"
Midimetric 0:71d791204057 265
Midimetric 0:71d791204057 266 while( i < Msg.size() )
Midimetric 0:71d791204057 267 {
Midimetric 0:71d791204057 268 short n = Msg[i];
Midimetric 0:71d791204057 269 if( ! s ) // out of sequence, expect a byte value or a custom identifier or SEQ
Midimetric 0:71d791204057 270 {
Midimetric 0:71d791204057 271 if( n < 256 ) { Value = n; return 0; } // just copy fixed message byte
Midimetric 0:71d791204057 272 else if( ! ISCOMMAND( n ) ) return CHAIN_NOT_A_BYTE; // short values are not allowed outside of sequence
Midimetric 0:71d791204057 273 else switch( n ) {
Midimetric 0:71d791204057 274 case SEQ : s = true; NEXT
Midimetric 0:71d791204057 275 case VMC : Value = cur.Command | ( cur.Channel == NAKN ? 0 : cur.Channel ); return 0;
Midimetric 0:71d791204057 276 case VM_ : Value = cur.Command; return 0;
Midimetric 0:71d791204057 277 case VC_ : Value = ( cur.Channel == NAKN ? 0 : cur.Channel ); return 0;
Midimetric 0:71d791204057 278 case VA_ : Value = cur.ValA; return 0;
Midimetric 0:71d791204057 279 case VN_ : Value = prev.Get14(); return 0;
Midimetric 0:71d791204057 280 case VB_ : Value = cur.ValB; return 0;
Midimetric 0:71d791204057 281 case VD_ :
Midimetric 0:71d791204057 282 case VK_ : Value = cur.Get14(); return 0;
Midimetric 0:71d791204057 283 default : char id[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; short idi = 0;
Midimetric 0:71d791204057 284 while( n > CID && n < CUL ) { id[idi++] = (char)(n - CID);
Midimetric 0:71d791204057 285 n = Msg[i++]; } Value = ML.Get( id ); return 0;
Midimetric 0:71d791204057 286 }
Midimetric 0:71d791204057 287 }
Midimetric 0:71d791204057 288 else if( ! ISCOMMAND( n ) ) // 14 bit literal inside a sequence, push on stack
Midimetric 0:71d791204057 289 {
Midimetric 0:71d791204057 290 k.Push( n ); i++;
Midimetric 0:71d791204057 291 }
Midimetric 0:71d791204057 292 else switch( n )
Midimetric 0:71d791204057 293 {
Midimetric 0:71d791204057 294 case E7_ :
Midimetric 0:71d791204057 295 case E8_ :
Midimetric 0:71d791204057 296 case E14 : Value = (short)k.Pull(); return 0;
Midimetric 0:71d791204057 297
Midimetric 0:71d791204057 298 case VMC : k.Push( cur.Command|( cur.Channel == NAKN ? 0 : cur.Channel ) ); NEXT
Midimetric 0:71d791204057 299 case VM_ : k.Push( cur.Command ); NEXT
Midimetric 0:71d791204057 300 case VC_ : k.Push( ( cur.Channel == NAKN ? 0 : cur.Channel ) ); NEXT
Midimetric 0:71d791204057 301 case VA_ : k.Push( cur.ValA ); NEXT
Midimetric 0:71d791204057 302 case VB_ : k.Push( cur.ValB ); NEXT
Midimetric 0:71d791204057 303 case VN_ : k.Push( prev.Get14() ); NEXT
Midimetric 0:71d791204057 304 case VD_ :
Midimetric 0:71d791204057 305 case VK_ : k.Push( cur.Get14() ); NEXT
Midimetric 0:71d791204057 306 case ADD : k.Pull( b, a ); k.Push( a + b ); NEXT
Midimetric 0:71d791204057 307 case SUB : k.Pull( b, a ); k.Push( a - b ); NEXT
Midimetric 0:71d791204057 308 case MUL : k.Pull( b, a ); k.Push( a * b ); NEXT
Midimetric 0:71d791204057 309 case DIV : k.Pull( b, a ); k.Push( a / b ); NEXT
Midimetric 0:71d791204057 310 case MOD : k.Pull( b, a ); k.Push( a % b ); NEXT
Midimetric 0:71d791204057 311 case BIT : k.Pull( c,b,a); k.Push( cur.Raw[a] >> b & bitmasking[c] ); NEXT
Midimetric 0:71d791204057 312 case BOR : k.Pull( b, a ); k.Push( a | b ); NEXT
Midimetric 0:71d791204057 313 case BAN : k.Pull( b, a ); k.Push( a & b ); NEXT
Midimetric 0:71d791204057 314 case BNO : k.Pull( a ); k.Push( ~a ); NEXT
Midimetric 0:71d791204057 315 case BSL : k.Pull( b, a ); k.Push( a << b ); NEXT
Midimetric 0:71d791204057 316 case BSR : k.Pull( b, a ); k.Push( a >> b ); NEXT
Midimetric 0:71d791204057 317 case MSB : k.Pull( a ); k.Push( a >> 7 ); NEXT
Midimetric 0:71d791204057 318 case LSB : k.Pull( a ); k.Push( a & 127 ); NEXT
Midimetric 0:71d791204057 319 case MAP : k.Pull( d, a, c, b ); d--;
Midimetric 0:71d791204057 320 while( a != b )
Midimetric 0:71d791204057 321 if( ( d -= 2 ) == 0 ) { k.Push( NAKN ); NEXT }
Midimetric 0:71d791204057 322 else k.Pull( c, b );
Midimetric 0:71d791204057 323 while( d -= 2 ) k.Pull(a,b); /* unstack unused values */ k.Push( c ); NEXT
Midimetric 0:71d791204057 324 default:
Midimetric 0:71d791204057 325 if( n <= CID && n > CID + 0xFF )return CHAIN_UNKNOWN_OP;
Midimetric 0:71d791204057 326 {char id[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; short idi = 0;
Midimetric 0:71d791204057 327 while( n > CID && n < CUL ) { id[idi++] = (char)(n - CID);
Midimetric 0:71d791204057 328 n = Msg[++i]; } k.Push( (byte)ML.Get( id ) ); } NEXT
Midimetric 0:71d791204057 329 }
Midimetric 0:71d791204057 330 }
Midimetric 0:71d791204057 331 return CHAIN_SYNTAXE_ERROR;
Midimetric 0:71d791204057 332 }
Midimetric 0:71d791204057 333 };
Midimetric 0:71d791204057 334 //_____________________________________________________________________________
Midimetric 0:71d791204057 335 class Filter
Midimetric 0:71d791204057 336 {//""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
Midimetric 0:71d791204057 337 public:
Midimetric 0:71d791204057 338 byte Port; // use constants TO_OUT1...3
Midimetric 0:71d791204057 339 byte Type; // use constants NOTE, POLA, ... from midi.h
Midimetric 0:71d791204057 340 short Channel;
Midimetric 0:71d791204057 341 short Amin; // may be a 14 bits value for RPN, NRPN identifier
Midimetric 0:71d791204057 342 short Amax;
Midimetric 0:71d791204057 343 short Bmin; // may be a 14 bits value for RPN, NRPN value
Midimetric 0:71d791204057 344 short Bmax;
Midimetric 0:71d791204057 345 vector<byte> Head;
Midimetric 0:71d791204057 346 Chain Out;
Midimetric 0:71d791204057 347 vector<Assignment*> Assigns;
Midimetric 0:71d791204057 348
Midimetric 0:71d791204057 349 Filter() : Port(0), Type(0), Channel(NAKW), Amin(NAKN), Amax(NAKN), Bmin(NAKN), Bmax(NAKN), Head( 1, (short)0xF0 ) { }
Midimetric 0:71d791204057 350 ~Filter() { }
Midimetric 0:71d791204057 351
Midimetric 0:71d791204057 352 Filter( Filter & f )
Midimetric 0:71d791204057 353 : Port(f.Port),Type(f.Type),Channel(f.Channel),Amin(f.Amin),Amax(f.Amax),Bmin(f.Bmin),Bmax(f.Bmax)
Midimetric 0:71d791204057 354 {
Midimetric 0:71d791204057 355 Head = f.Head; Out.Msg[0] = f.Out.Msg[0]; Out.Msg[1] = f.Out.Msg[1]; Out.Msg[2] = f.Out.Msg[2]; Assigns = f.Assigns;
Midimetric 0:71d791204057 356 }
Midimetric 0:71d791204057 357
Midimetric 0:71d791204057 358 Filter( byte p, byte t, short c, short ai, short ax, short bi, short bx, vector<byte> &head, vector<short> &o1, vector<short> &o2, vector<short> &o3, vector<Assignment*> &assigns )
Midimetric 0:71d791204057 359 : Port(p), Type(t), Channel(c), Amin(ai), Amax(ax), Bmin(bi), Bmax(bx)
Midimetric 0:71d791204057 360 {
Midimetric 0:71d791204057 361 Head = head; Out.Msg[0] = o1; Out.Msg[1] = o2; Out.Msg[2] = o3; Assigns = assigns;
Midimetric 0:71d791204057 362 }
Midimetric 0:71d791204057 363 };
Midimetric 0:71d791204057 364
Midimetric 0:71d791204057 365 //_____________________________________________________________________________
Midimetric 0:71d791204057 366 class FilterList
Midimetric 0:71d791204057 367 {//""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
Midimetric 0:71d791204057 368 public:
Midimetric 0:71d791204057 369 vector<Filter*> List;
Midimetric 0:71d791204057 370
Midimetric 0:71d791204057 371 void Add( byte inport, byte message, short channels, short mina, short maxa, short minb, short maxb, vector<byte> &head, vector<short> &sequence1, vector<short> &sequence2, vector<short> &sequence3, vector<Assignment*> &assigns )
Midimetric 0:71d791204057 372 {
Midimetric 0:71d791204057 373 List.push_back( new Filter( inport, message, channels, mina, maxa, minb, maxb, head, sequence1, sequence2, sequence3, assigns ) );
Midimetric 0:71d791204057 374 HasBank |= message == BANK;
Midimetric 0:71d791204057 375 HasData |= ( message >= DATA ) && ( message <= NRPN );
Midimetric 0:71d791204057 376 HasSysx |= message == SYSX;
Midimetric 0:71d791204057 377 }
Midimetric 0:71d791204057 378 Filter* operator[] ( short index )
Midimetric 0:71d791204057 379 {
Midimetric 0:71d791204057 380 return List[index];
Midimetric 0:71d791204057 381 }
Midimetric 0:71d791204057 382 void Route( byte from, MidiM &cur, MidiM &prev )
Midimetric 0:71d791204057 383 {
Midimetric 0:71d791204057 384 for( short i = 0 ; i < List.size() ; i++ )
Midimetric 0:71d791204057 385 {
Midimetric 0:71d791204057 386 Filter* f = List[i];
Midimetric 0:71d791204057 387 if( f->Port != from ) continue;
Midimetric 0:71d791204057 388
Midimetric 0:71d791204057 389 if( HasSysx && ( f->Type == SYSX ) && ( cur.Type == SYSX ) )
Midimetric 0:71d791204057 390 {
Midimetric 0:71d791204057 391 bool ok = f->Head.size() > 0;
Midimetric 0:71d791204057 392 if( ok )
Midimetric 0:71d791204057 393 if( f->Head[0] != RAW )
Midimetric 0:71d791204057 394 for( int j = 0 ; j < f->Head.size() ; j++ )
Midimetric 0:71d791204057 395 if( j == cur.Raw.size() || f->Head[j] != cur.Raw[j] )
Midimetric 0:71d791204057 396 ok=false;
Midimetric 0:71d791204057 397 if( ok )
Midimetric 0:71d791204057 398 {
Midimetric 0:71d791204057 399 for( int assign = 0 ; assign < f->Assigns.size() ; assign++ )
Midimetric 0:71d791204057 400 if( f->Assigns[assign]->Compute( cur, prev ) == 0 )
Midimetric 0:71d791204057 401 ML.Add( f->Assigns[assign]->Name, f->Assigns[assign]->Value );
Midimetric 0:71d791204057 402
Midimetric 0:71d791204057 403 for( int port = 0 ; port < 3 ; port++ )
Midimetric 0:71d791204057 404 if( f->Out.Compute( port, cur, prev ) == 0 )
Midimetric 0:71d791204057 405 {
Midimetric 0:71d791204057 406 led[3] = 1;
Midimetric 0:71d791204057 407 for( short j = 0 ; j < f->Out.Out.size() ; j++ )
Midimetric 0:71d791204057 408 SL[port].putc( f->Out.Out[j] );
Midimetric 0:71d791204057 409 led[3] = 0;
Midimetric 0:71d791204057 410 }
Midimetric 0:71d791204057 411 f->Out.Done();
Midimetric 0:71d791204057 412 return;
Midimetric 0:71d791204057 413 }
Midimetric 0:71d791204057 414 }
Midimetric 0:71d791204057 415 else if( HasData && ( f->Type == DATA || f->Type == INCR || f->Type == DECR ) && ( cur.Type == f->Type ) && ( prev.Type == NRPN || prev.Type == RPN_ ) )
Midimetric 0:71d791204057 416 {
Midimetric 0:71d791204057 417 short number = prev.Get14(), data = cur.Get14();
Midimetric 0:71d791204057 418 if( f->Channel == NAKW || ( f->Channel & ( 1 << cur.Channel ) & ( 1 << prev.Channel ) ) )
Midimetric 0:71d791204057 419 if( f->Amin==NAKW || ( f->Amax==NAKW && number==f->Amin ) || ( f->Amax!=NAKW && number>=f->Amin && number<=f->Amax ) )
Midimetric 0:71d791204057 420 if( f->Bmin==NAKW || ( f->Bmax==NAKW && data==f->Bmin ) || ( f->Bmax!=NAKW && data>=f->Bmin && data<=f->Bmax ) )
Midimetric 0:71d791204057 421 {
Midimetric 0:71d791204057 422 for( int assign = 0 ; assign < f->Assigns.size() ; assign++ )
Midimetric 0:71d791204057 423 if( f->Assigns[assign]->Compute( cur, prev ) == 0 )
Midimetric 0:71d791204057 424 ML.Add( f->Assigns[assign]->Name, f->Assigns[assign]->Value );
Midimetric 0:71d791204057 425 for( int port = 0 ; port < 3 ; port++ )
Midimetric 0:71d791204057 426 if( f->Out.Compute( port, cur, prev ) == 0 )
Midimetric 0:71d791204057 427 {
Midimetric 0:71d791204057 428 for( short j = 0 ; j < f->Out.Out.size() ; j++ ) // check for unrountable message
Midimetric 0:71d791204057 429 {
Midimetric 0:71d791204057 430 short n = f->Out.Out[j];
Midimetric 0:71d791204057 431 if( f->Out.Out[j] == NAKN ) return;
Midimetric 0:71d791204057 432 }
Midimetric 0:71d791204057 433 led[3] = 1;
Midimetric 0:71d791204057 434 for( short j = 0 ; j < f->Out.Out.size() ; j++ )
Midimetric 0:71d791204057 435 SL[port].putc( f->Out.Out[j] );
Midimetric 0:71d791204057 436 led[3] = 0;
Midimetric 0:71d791204057 437 }
Midimetric 0:71d791204057 438 f->Out.Done();
Midimetric 0:71d791204057 439 return;
Midimetric 0:71d791204057 440 }
Midimetric 0:71d791204057 441 }
Midimetric 0:71d791204057 442 else if( f->Type == cur.Type )
Midimetric 0:71d791204057 443 if( ( f->Channel == NAKW ) || ( f->Channel & ( 1 << cur.Channel ) ) )
Midimetric 0:71d791204057 444 if( cur.ValCount()==0 || f->Amin==NAKN || ( f->Amax==NAKN && cur.ValA==f->Amin ) || ( f->Amax!=NAKN && cur.ValA>=f->Amin && cur.ValA<=f->Amax ) )
Midimetric 0:71d791204057 445 if( cur.ValCount()==1 || f->Bmin==NAKN || ( f->Bmax==NAKN && cur.ValB==f->Bmin ) || ( f->Bmax!=NAKN && cur.ValB>=f->Bmin && cur.ValB<=f->Bmax ) )
Midimetric 0:71d791204057 446 {
Midimetric 0:71d791204057 447 for( int assign = 0 ; assign < f->Assigns.size() ; assign++ )
Midimetric 0:71d791204057 448 if( f->Assigns[assign]->Compute( cur, prev ) == 0 )
Midimetric 0:71d791204057 449 ML.Add( f->Assigns[assign]->Name, f->Assigns[assign]->Value );
Midimetric 0:71d791204057 450
Midimetric 0:71d791204057 451 for( int port = 0 ; port < 3 ; port++ )
Midimetric 0:71d791204057 452 if( f->Out.Compute( port, cur, prev ) == 0 )
Midimetric 0:71d791204057 453 {
Midimetric 0:71d791204057 454 for( short j = 0 ; j < f->Out.Out.size() ; j++ ) // check for unrountable message
Midimetric 0:71d791204057 455 if( f->Out.Out[j] == NAKN ) return;
Midimetric 0:71d791204057 456 led[3] = 1;
Midimetric 0:71d791204057 457 for( short j = 0 ; j < f->Out.Out.size() ; j++ )
Midimetric 0:71d791204057 458 SL[port].putc( f->Out.Out[j] );
Midimetric 0:71d791204057 459 led[3] = 0;
Midimetric 0:71d791204057 460 }
Midimetric 0:71d791204057 461 f->Out.Done();
Midimetric 0:71d791204057 462 return;
Midimetric 0:71d791204057 463 }
Midimetric 0:71d791204057 464
Midimetric 0:71d791204057 465 }
Midimetric 0:71d791204057 466 }
Midimetric 0:71d791204057 467 };
Midimetric 0:71d791204057 468
Midimetric 0:71d791204057 469 #undef NEXT
Midimetric 0:71d791204057 470 #undef PUSH
Midimetric 0:71d791204057 471