1 /************************************************************************ 2 FAUST Architecture File 3 Copyright (C) 2003-2011 GRAME, Centre National de Creation Musicale 4 --------------------------------------------------------------------- 5 This Architecture section is free software; you can redistribute it 6 and/or modify it under the terms of the GNU General Public License 7 as published by the Free Software Foundation; either version 3 of 8 the License, or (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program; If not, see <http://www.gnu.org/licenses/>. 17 18 EXCEPTION : As a special exception, you may create a larger work 19 that contains this FAUST architecture section and distribute 20 that work under terms of your choice, so long as this FAUST 21 architecture section is not modified. 22 23 ************************************************************************ 24 ************************************************************************/ 25 26 #ifndef __midi__ 27 #define __midi__ 28 29 #include <vector> 30 #include <string> 31 #include <algorithm> 32 33 class MapUI; 34 35 //---------------------------------------------------------------- 36 // MIDI processor definition 37 //---------------------------------------------------------------- 38 39 class midi { 40 41 public: 42 midi()43 midi() {} ~midi()44 virtual ~midi() {} 45 46 // Additional time-stamped API for MIDI input keyOn(double,int channel,int pitch,int velocity)47 virtual MapUI* keyOn(double, int channel, int pitch, int velocity) 48 { 49 return keyOn(channel, pitch, velocity); 50 } 51 52 virtual void keyOff(double, int channel, int pitch, int velocity = 127) 53 { 54 keyOff(channel, pitch, velocity); 55 } 56 pitchWheel(double,int channel,int wheel)57 virtual void pitchWheel(double, int channel, int wheel) 58 { 59 pitchWheel(channel, wheel); 60 } 61 ctrlChange(double,int channel,int ctrl,int value)62 virtual void ctrlChange(double, int channel, int ctrl, int value) 63 { 64 ctrlChange(channel, ctrl, value); 65 } 66 progChange(double,int channel,int pgm)67 virtual void progChange(double, int channel, int pgm) 68 { 69 progChange(channel, pgm); 70 } 71 keyPress(double,int channel,int pitch,int press)72 virtual void keyPress(double, int channel, int pitch, int press) 73 { 74 keyPress(channel, pitch, press); 75 } 76 chanPress(double date,int channel,int press)77 virtual void chanPress(double date, int channel, int press) 78 { 79 chanPress(channel, press); 80 } 81 ctrlChange14bits(double,int channel,int ctrl,int value)82 virtual void ctrlChange14bits(double, int channel, int ctrl, int value) 83 { 84 ctrlChange14bits(channel, ctrl, value); 85 } 86 87 // MIDI sync start_sync(double date)88 virtual void start_sync(double date) {} stop_sync(double date)89 virtual void stop_sync(double date) {} clock(double date)90 virtual void clock(double date) {} 91 92 // Standard MIDI API keyOn(int channel,int pitch,int velocity)93 virtual MapUI* keyOn(int channel, int pitch, int velocity) { return 0; } keyOff(int channel,int pitch,int velocity)94 virtual void keyOff(int channel, int pitch, int velocity) {} keyPress(int channel,int pitch,int press)95 virtual void keyPress(int channel, int pitch, int press) {} chanPress(int channel,int press)96 virtual void chanPress(int channel, int press) {} ctrlChange(int channel,int ctrl,int value)97 virtual void ctrlChange(int channel, int ctrl, int value) {} ctrlChange14bits(int channel,int ctrl,int value)98 virtual void ctrlChange14bits(int channel, int ctrl, int value) {} pitchWheel(int channel,int wheel)99 virtual void pitchWheel(int channel, int wheel) {} progChange(int channel,int pgm)100 virtual void progChange(int channel, int pgm) {} 101 102 enum MidiStatus { 103 104 // channel voice messages 105 MIDI_NOTE_OFF = 0x80, 106 MIDI_NOTE_ON = 0x90, 107 MIDI_CONTROL_CHANGE = 0xB0, 108 MIDI_PROGRAM_CHANGE = 0xC0, 109 MIDI_PITCH_BEND = 0xE0, 110 MIDI_AFTERTOUCH = 0xD0, // aka channel pressure 111 MIDI_POLY_AFTERTOUCH = 0xA0, // aka key pressure 112 MIDI_CLOCK = 0xF8, 113 MIDI_START = 0xFA, 114 MIDI_STOP = 0xFC 115 116 }; 117 118 enum MidiCtrl { 119 120 ALL_NOTES_OFF = 123, 121 ALL_SOUND_OFF = 120 122 123 }; 124 }; 125 126 //---------------------------------------------------------------- 127 // Base class for MIDI API handling 128 //---------------------------------------------------------------- 129 130 class midi_handler : public midi { 131 132 protected: 133 134 std::vector<midi*> fMidiInputs; 135 std::string fName; 136 137 public: 138 fName(name)139 midi_handler(const std::string& name = "MIDIHandler"):fName(name) {} ~midi_handler()140 virtual ~midi_handler() {} 141 addMidiIn(midi * midi_dsp)142 virtual void addMidiIn(midi* midi_dsp) { if (midi_dsp) fMidiInputs.push_back(midi_dsp); } removeMidiIn(midi * midi_dsp)143 virtual void removeMidiIn(midi* midi_dsp) 144 { 145 std::vector<midi*>::iterator it = std::find(fMidiInputs.begin(), fMidiInputs.end(), midi_dsp); 146 if (it != fMidiInputs.end()) { 147 fMidiInputs.erase(it); 148 } 149 } 150 start_midi()151 virtual bool start_midi() { return true; } stop_midi()152 virtual void stop_midi() {} 153 handleSync(double time,int type)154 void handleSync(double time, int type) 155 { 156 if (type == MIDI_CLOCK) { 157 for (unsigned int i = 0; i < fMidiInputs.size(); i++) { 158 fMidiInputs[i]->clock(time); 159 } 160 } else if (type == MIDI_START) { 161 for (unsigned int i = 0; i < fMidiInputs.size(); i++) { 162 fMidiInputs[i]->start_sync(time); 163 } 164 } else if (type == MIDI_STOP) { 165 for (unsigned int i = 0; i < fMidiInputs.size(); i++) { 166 fMidiInputs[i]->stop_sync(time); 167 } 168 } 169 } 170 handleData1(double time,int type,int channel,int data1)171 void handleData1(double time, int type, int channel, int data1) 172 { 173 if (type == MIDI_PROGRAM_CHANGE) { 174 for (unsigned int i = 0; i < fMidiInputs.size(); i++) { 175 fMidiInputs[i]->progChange(time, channel, data1); 176 } 177 } else if (type == MIDI_AFTERTOUCH) { 178 for (unsigned int i = 0; i < fMidiInputs.size(); i++) { 179 fMidiInputs[i]->chanPress(time, channel, data1); 180 } 181 } 182 } 183 handleData2(double time,int type,int channel,int data1,int data2)184 void handleData2(double time, int type, int channel, int data1, int data2) 185 { 186 if (type == MIDI_NOTE_OFF || ((type == MIDI_NOTE_ON) && (data2 == 0))) { 187 for (unsigned int i = 0; i < fMidiInputs.size(); i++) { 188 fMidiInputs[i]->keyOff(time, channel, data1, data2); 189 } 190 } else if (type == MIDI_NOTE_ON) { 191 for (unsigned int i = 0; i < fMidiInputs.size(); i++) { 192 fMidiInputs[i]->keyOn(time, channel, data1, data2); 193 } 194 } else if (type == MIDI_CONTROL_CHANGE) { 195 for (unsigned int i = 0; i < fMidiInputs.size(); i++) { 196 fMidiInputs[i]->ctrlChange(time, channel, data1, data2); 197 } 198 } else if (type == MIDI_PITCH_BEND) { 199 for (unsigned int i = 0; i < fMidiInputs.size(); i++) { 200 fMidiInputs[i]->pitchWheel(time, channel, (data2 * 128.0) + data1); 201 } 202 } else if (type == MIDI_POLY_AFTERTOUCH) { 203 for (unsigned int i = 0; i < fMidiInputs.size(); i++) { 204 fMidiInputs[i]->keyPress(time, channel, data1, data2); 205 } 206 } 207 } 208 209 210 }; 211 212 #endif // __midi__ 213