MidiIn.cpp (4658B)
1 /* 2 ZynAddSubFX - a software synthesizer 3 4 MidiIn.C - This class is inherited by all the Midi input classes 5 Copyright (C) 2002-2005 Nasca Octavian Paul 6 Author: Nasca Octavian Paul 7 8 This program is free software; you can redistribute it and/or 9 modify it under the terms of the GNU General Public License 10 as published by the Free Software Foundation; either version 2 11 of the License, or (at your option) any later version. 12 */ 13 14 #include "MidiIn.h" 15 #include "../globals.h" 16 #include "InMgr.h" 17 #include <string.h> 18 19 namespace zyn { 20 21 MidiIn::MidiIn() 22 { 23 sysex_offset = 0; 24 memset(sysex_data, 0, sizeof(sysex_data)); 25 } 26 27 uint8_t MidiIn::midiSysEx(unsigned char data) 28 { 29 if (data & 0x80) { 30 if (data == 0xF0) { 31 sysex_offset = 0; /* begin */ 32 } else if (data == 0xF7) { 33 return (2); /* end */ 34 } else { 35 return (1); /* error */ 36 } 37 } else if (sysex_offset >= sizeof(sysex_data)) { 38 return (1); /* error */ 39 } 40 sysex_data[sysex_offset++] = data; 41 return (0); 42 } 43 44 void MidiIn::midiProcess(unsigned char head, 45 unsigned char num, 46 unsigned char value) 47 { 48 MidiEvent ev; 49 unsigned char chan = head & 0x0f; 50 51 /* SYSEX handling */ 52 if (head == 0xF0 || sysex_offset != 0) { 53 uint8_t status = 0; 54 55 status |= midiSysEx(head); 56 status |= midiSysEx(num); 57 status |= midiSysEx(value); 58 59 if (status & 1) { 60 /* error parsing SYSEX */ 61 sysex_offset = 0; 62 } else if (status & 2) { 63 /* message complete */ 64 65 if (sysex_offset >= 10 && 66 sysex_data[1] == 0x0A && 67 sysex_data[2] == 0x55) { 68 ev.channel = sysex_data[3] & 0x0F; 69 ev.log2_freq = sysex_data[6] + 70 (sysex_data[7] / (128.0f)) + 71 (sysex_data[8] / (128.0f * 128.0f)) + 72 (sysex_data[9] / (128.0f * 128.0f * 128.0f)); 73 74 switch (sysex_data[3] >> 4) { 75 case 0: /* Note ON */ 76 ev.type = M_FLOAT_NOTE; 77 ev.num = sysex_data[4]; 78 ev.value = sysex_data[5]; 79 ev.log2_freq /= 12.0f; 80 break; 81 case 1: /* Pressure, Aftertouch */ 82 ev.type = M_FLOAT_CTRL; 83 ev.num = C_aftertouch; 84 ev.value = sysex_data[4]; 85 break; 86 case 2: /* Controller */ 87 ev.type = M_FLOAT_CTRL; 88 ev.num = sysex_data[5]; 89 ev.value = sysex_data[4]; 90 break; 91 case 3: /* Absolute pitch */ 92 ev.type = M_FLOAT_CTRL; 93 ev.num = C_pitch; 94 ev.value = sysex_data[4]; 95 ev.log2_freq /= 12.0f; 96 break; 97 default: 98 return; 99 } 100 InMgr::getInstance().putEvent(ev); 101 } 102 return; /* message complete */ 103 } else { 104 return; /* wait for more data */ 105 } 106 } 107 switch(head & 0xf0) { 108 case 0x80: //Note Off 109 ev.type = M_NOTE; 110 ev.channel = chan; 111 ev.num = num; 112 ev.value = 0; 113 InMgr::getInstance().putEvent(ev); 114 break; 115 case 0x90: //Note On 116 ev.type = M_NOTE; 117 ev.channel = chan; 118 ev.num = num; 119 ev.value = value; 120 InMgr::getInstance().putEvent(ev); 121 break; 122 case 0xA0: /* pressure, aftertouch */ 123 ev.type = M_PRESSURE; 124 ev.channel = chan; 125 ev.num = num; 126 ev.value = value; 127 InMgr::getInstance().putEvent(ev); 128 break; 129 case 0xb0: //Controller 130 ev.type = M_CONTROLLER; 131 ev.channel = chan; 132 ev.num = num; 133 ev.value = value; 134 InMgr::getInstance().putEvent(ev); 135 break; 136 case 0xc0: //Program Change 137 ev.type = M_PGMCHANGE; 138 ev.channel = chan; 139 ev.num = num; 140 ev.value = 0; 141 InMgr::getInstance().putEvent(ev); 142 break; 143 case 0xe0: //Pitch Wheel 144 ev.type = M_CONTROLLER; 145 ev.channel = chan; 146 ev.num = C_pitchwheel; 147 ev.value = (num + value * (int) 128) - 8192; 148 InMgr::getInstance().putEvent(ev); 149 break; 150 } 151 } 152 153 }