drumstick
1.0.2
|
00001 /* 00002 Drumstick MIDI realtime input-output 00003 Copyright (C) 2009-2015 Pedro Lopez-Cabanillas <plcl@users.sf.net> 00004 00005 This program is free software; you can redistribute it and/or modify 00006 it under the terms of the GNU General Public License as published by 00007 the Free Software Foundation; either version 2 of the License, or 00008 (at your option) any later version. 00009 00010 This program is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 GNU General Public License for more details. 00014 00015 You should have received a copy of the GNU General Public License along 00016 with this program; if not, write to the Free Software Foundation, Inc., 00017 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00018 */ 00019 00020 #include <QDebug> 00021 #include "midiparser.h" 00022 #include "rtmidioutput.h" 00023 00024 namespace drumstick { 00025 namespace rt { 00026 00027 class MIDIParser::MIDIParserPrivate { 00028 public: 00029 MIDIParserPrivate(): m_in(0), m_out(0), m_running_status(0) { } 00030 MIDIInput *m_in; 00031 MIDIOutput *m_out; 00032 unsigned char m_running_status; 00033 QByteArray m_buffer; 00034 00035 void processNoteOff(const int chan, const int note, const int vel) 00036 { 00037 //qDebug() << "NoteOff(" << hex << chan << "," << note << "," << vel << ")"; 00038 if (m_in != 0 && m_in->isEnabledMIDIThru() && m_out != 0) { 00039 m_out->sendNoteOff(chan, note, vel); 00040 } 00041 if (m_in != 0) { 00042 m_in->emit midiNoteOff(chan, note, vel); 00043 } 00044 } 00045 00046 void processNoteOn(const int chan, const int note, const int vel) 00047 { 00048 //qDebug() << "NoteOn(" << hex << chan << "," << note << "," << vel << ")"; 00049 if (m_in != 0 && m_in->isEnabledMIDIThru() && m_out != 0) { 00050 m_out->sendNoteOn(chan, note, vel); 00051 } 00052 if (m_in != 0) { 00053 m_in->emit midiNoteOn(chan, note, vel); 00054 } 00055 } 00056 00057 void processKeyPressure(const int chan, const int note, const int value) 00058 { 00059 //qDebug() << "KeyPressure(" << hex << chan << "," << note << "," << value << ")"; 00060 if (m_in != 0 && m_in->isEnabledMIDIThru() && m_out != 0) { 00061 m_out->sendKeyPressure(chan, note, value); 00062 } 00063 if (m_in != 0) { 00064 m_in->emit midiKeyPressure(chan, note, value); 00065 } 00066 } 00067 00068 void processController(const int chan, const int control, const int value) 00069 { 00070 //qDebug() << "Controller(" << chan << "," << control << "," << value << ")"; 00071 if (m_in != 0 && m_in->isEnabledMIDIThru() && m_out != 0) { 00072 m_out->sendController(chan, control, value); 00073 } 00074 if (m_in != 0) { 00075 m_in->emit midiController(chan, control, value); 00076 } 00077 } 00078 00079 void processProgram(const int chan, const int program) 00080 { 00081 //qDebug() << "Program(" << hex << chan << "," << program << ")"; 00082 if (m_in != 0 && m_in->isEnabledMIDIThru() && m_out != 0) { 00083 m_out->sendProgram(chan, program); 00084 } 00085 if (m_in != 0) { 00086 m_in->emit midiProgram(chan, program); 00087 } 00088 } 00089 00090 void processChannelPressure(const int chan, const int value) 00091 { 00092 //qDebug() << "ChannelPressure(" << chan << "," << value << ")"; 00093 if (m_in != 0 && m_in->isEnabledMIDIThru() && m_out != 0) { 00094 m_out->sendChannelPressure(chan, value); 00095 } 00096 if (m_in != 0) { 00097 m_in->emit midiChannelPressure(chan, value); 00098 } 00099 } 00100 00101 void processPitchBend(const int chan, const int value) 00102 { 00103 //qDebug() << "PitchBend(" << chan << "," << value << ")"; 00104 if (m_in != 0 && m_in->isEnabledMIDIThru() && m_out != 0) { 00105 m_out->sendPitchBend(chan, value); 00106 } 00107 if (m_in != 0) { 00108 m_in->emit midiPitchBend(chan, value); 00109 } 00110 } 00111 00112 void processSysex(const QByteArray &data) 00113 { 00114 //qDebug() << "Sysex(" << data.toHex() << ")"; 00115 if (m_in != 0 && m_in->isEnabledMIDIThru() && m_out != 0) { 00116 m_out->sendSysex(data); 00117 } 00118 if (m_in != 0) { 00119 m_in->emit midiSysex(data); 00120 } 00121 } 00122 00123 void processSystemCommon(const int status) 00124 { 00125 //qDebug() << "common SystemMsg(" << hex << status << ")"; 00126 if (m_in != 0 && m_in->isEnabledMIDIThru() && m_out != 0) { 00127 m_out->sendSystemMsg(status); 00128 } 00129 if (m_in != 0) { 00130 m_in->emit midiSystemCommon(status); 00131 00132 } 00133 } 00134 00135 void processSystemRealtime(unsigned char byte) 00136 { 00137 //qDebug() << "realtime SystemMsg(" << hex << byte << ")"; 00138 if (m_in != 0 && m_in->isEnabledMIDIThru() && m_out != 0) { 00139 m_out->sendSystemMsg(byte); 00140 } 00141 if (m_in != 0) { 00142 m_in->emit midiSystemRealtime(byte); 00143 } 00144 } 00145 00146 }; 00147 00148 MIDIParser::MIDIParser(MIDIInput *in, QObject *parent) : 00149 QObject(parent), 00150 d(new MIDIParser::MIDIParserPrivate) 00151 { 00152 d->m_buffer.clear(); 00153 d->m_in = in; 00154 } 00155 00156 MIDIParser::~MIDIParser() 00157 { 00158 delete d; 00159 } 00160 00161 void MIDIParser::setMIDIThruDevice(MIDIOutput *device) 00162 { 00163 d->m_out = device; 00164 } 00165 00166 void MIDIParser::parse(unsigned char byte) 00167 { 00168 unsigned char status; 00169 int chan, m1, m2, v; 00170 00171 if (byte >= MIDI_STATUS_REALTIME) { // system realtime 00172 d->processSystemRealtime(byte); 00173 return; 00174 } else 00175 d->m_buffer.append(byte); 00176 00177 while(d->m_buffer.length() > 0) { 00178 status = static_cast<unsigned>(d->m_buffer.at(0)); 00179 if (status == MIDI_STATUS_SYSEX) { // system exclusive 00180 if (byte == MIDI_STATUS_ENDSYSEX) { 00181 d->processSysex(d->m_buffer); 00182 d->m_buffer.clear(); 00183 } else 00184 return; 00185 } else 00186 if (status > MIDI_STATUS_SYSEX && 00187 status < MIDI_STATUS_ENDSYSEX) { // system common 00188 d->processSystemCommon(status); 00189 d->m_buffer.clear(); 00190 } else 00191 if (status < MIDI_STATUS_SYSEX && 00192 status >= MIDI_STATUS_NOTEOFF) { // channel message 00193 d->m_running_status = status; 00194 chan = status & MIDI_CHANNEL_MASK; 00195 status = status & MIDI_STATUS_MASK; 00196 switch(status) { 00197 case MIDI_STATUS_NOTEOFF: 00198 if (d->m_buffer.length() < 3) 00199 return; 00200 m1 = static_cast<unsigned>(d->m_buffer.at(1)); 00201 m2 = static_cast<unsigned>(d->m_buffer.at(2)); 00202 d->processNoteOff(chan, m1, m2); 00203 break; 00204 case MIDI_STATUS_NOTEON: 00205 if (d->m_buffer.length() < 3) 00206 return; 00207 m1 = static_cast<unsigned>(d->m_buffer.at(1)); 00208 m2 = static_cast<unsigned>(d->m_buffer.at(2)); 00209 d->processNoteOn(chan, m1, m2); 00210 break; 00211 case MIDI_STATUS_KEYPRESURE: 00212 if (d->m_buffer.length() < 3) 00213 return; 00214 m1 = static_cast<unsigned>(d->m_buffer.at(1)); 00215 m2 = static_cast<unsigned>(d->m_buffer.at(2)); 00216 d->processKeyPressure(chan, m1, m2); 00217 break; 00218 case MIDI_STATUS_CONTROLCHANGE: 00219 if (d->m_buffer.length() < 3) 00220 return; 00221 m1 = static_cast<unsigned>(d->m_buffer.at(1)); 00222 m2 = static_cast<unsigned>(d->m_buffer.at(2)); 00223 d->processController(chan, m1, m2); 00224 break; 00225 case MIDI_STATUS_PROGRAMCHANGE: 00226 if (d->m_buffer.length() < 2) 00227 return; 00228 m1 = static_cast<unsigned>(d->m_buffer.at(1)); 00229 d->processProgram(chan, m1); 00230 break; 00231 case MIDI_STATUS_CHANNELPRESSURE: 00232 if (d->m_buffer.length() < 2) 00233 return; 00234 m1 = static_cast<unsigned>(d->m_buffer.at(1)); 00235 d->processChannelPressure(chan, m1); 00236 break; 00237 case MIDI_STATUS_PITCHBEND: 00238 if (d->m_buffer.length() < 3) 00239 return; 00240 m1 = static_cast<unsigned>(d->m_buffer.at(1)); 00241 m2 = static_cast<unsigned>(d->m_buffer.at(2)); 00242 v = m1 + m2 * 0x80 - 0x2000; 00243 d->processPitchBend(chan, v); 00244 break; 00245 } 00246 d->m_buffer.clear(); 00247 } else { // running status 00248 d->m_buffer.insert(0, d->m_running_status); 00249 } 00250 } 00251 } 00252 00253 void MIDIParser::parse(QByteArray bytes) 00254 { 00255 foreach(unsigned char byte, bytes) { 00256 parse(byte); 00257 } 00258 } 00259 00260 }} 00261