annotate midiFileReader/MIDIEvent.h @ 35:6cd3e0075adf

now writing out alignment data - correct beat positions for the MIDI file so alignment can be done via iostream over RWV database
author Andrew N Robertson <andrew.robertson@eecs.qmul.ac.uk>
date Wed, 14 Dec 2011 17:28:17 +0000
parents b299a65a3ad0
children
rev   line source
andrew@0 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
andrew@0 2
andrew@0 3 /*
andrew@0 4 This is a modified version of a source file from the
andrew@0 5 Rosegarden MIDI and audio sequencer and notation editor.
andrew@0 6 This file copyright 2000-2010 Richard Bown and Chris Cannam.
andrew@0 7
andrew@0 8 Permission is hereby granted, free of charge, to any person
andrew@0 9 obtaining a copy of this software and associated documentation
andrew@0 10 files (the "Software"), to deal in the Software without
andrew@0 11 restriction, including without limitation the rights to use, copy,
andrew@0 12 modify, merge, publish, distribute, sublicense, and/or sell copies
andrew@0 13 of the Software, and to permit persons to whom the Software is
andrew@0 14 furnished to do so, subject to the following conditions:
andrew@0 15
andrew@0 16 The above copyright notice and this permission notice shall be
andrew@0 17 included in all copies or substantial portions of the Software.
andrew@0 18
andrew@0 19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
andrew@0 20 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
andrew@0 21 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
andrew@0 22 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
andrew@0 23 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
andrew@0 24 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
andrew@0 25 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
andrew@0 26
andrew@0 27 Except as contained in this notice, the names of the authors
andrew@0 28 shall not be used in advertising or otherwise to promote the sale,
andrew@0 29 use or other dealings in this Software without prior written
andrew@0 30 authorization.
andrew@0 31 */
andrew@0 32
andrew@0 33 #ifndef _MIDI_EVENT_H_
andrew@0 34 #define _MIDI_EVENT_H_
andrew@0 35
andrew@0 36 #include <string>
andrew@0 37 #include <iostream>
andrew@0 38
andrew@0 39 typedef unsigned char MIDIByte;
andrew@0 40
andrew@0 41 namespace MIDIConstants
andrew@0 42 {
andrew@0 43 static const char *const MIDI_FILE_HEADER = "MThd";
andrew@0 44 static const char *const MIDI_TRACK_HEADER = "MTrk";
andrew@0 45
andrew@0 46 static const MIDIByte MIDI_STATUS_BYTE_MASK = 0x80;
andrew@0 47 static const MIDIByte MIDI_MESSAGE_TYPE_MASK = 0xF0;
andrew@0 48 static const MIDIByte MIDI_CHANNEL_NUM_MASK = 0x0F;
andrew@0 49
andrew@0 50 static const MIDIByte MIDI_NOTE_OFF = 0x80;
andrew@0 51 static const MIDIByte MIDI_NOTE_ON = 0x90;
andrew@0 52 static const MIDIByte MIDI_POLY_AFTERTOUCH = 0xA0;
andrew@0 53 static const MIDIByte MIDI_CTRL_CHANGE = 0xB0;
andrew@0 54 static const MIDIByte MIDI_PROG_CHANGE = 0xC0;
andrew@0 55 static const MIDIByte MIDI_CHNL_AFTERTOUCH = 0xD0;
andrew@0 56 static const MIDIByte MIDI_PITCH_BEND = 0xE0;
andrew@0 57 static const MIDIByte MIDI_SELECT_CHNL_MODE = 0xB0;
andrew@0 58 static const MIDIByte MIDI_SYSTEM_EXCLUSIVE = 0xF0;
andrew@0 59 static const MIDIByte MIDI_TC_QUARTER_FRAME = 0xF1;
andrew@0 60 static const MIDIByte MIDI_SONG_POSITION_PTR = 0xF2;
andrew@0 61 static const MIDIByte MIDI_SONG_SELECT = 0xF3;
andrew@0 62 static const MIDIByte MIDI_TUNE_REQUEST = 0xF6;
andrew@0 63 static const MIDIByte MIDI_END_OF_EXCLUSIVE = 0xF7;
andrew@0 64 static const MIDIByte MIDI_TIMING_CLOCK = 0xF8;
andrew@0 65 static const MIDIByte MIDI_START = 0xFA;
andrew@0 66 static const MIDIByte MIDI_CONTINUE = 0xFB;
andrew@0 67 static const MIDIByte MIDI_STOP = 0xFC;
andrew@0 68 static const MIDIByte MIDI_ACTIVE_SENSING = 0xFE;
andrew@0 69 static const MIDIByte MIDI_SYSTEM_RESET = 0xFF;
andrew@0 70 static const MIDIByte MIDI_SYSEX_NONCOMMERCIAL = 0x7D;
andrew@0 71 static const MIDIByte MIDI_SYSEX_NON_RT = 0x7E;
andrew@0 72 static const MIDIByte MIDI_SYSEX_RT = 0x7F;
andrew@0 73 static const MIDIByte MIDI_SYSEX_RT_COMMAND = 0x06;
andrew@0 74 static const MIDIByte MIDI_SYSEX_RT_RESPONSE = 0x07;
andrew@0 75 static const MIDIByte MIDI_MMC_STOP = 0x01;
andrew@0 76 static const MIDIByte MIDI_MMC_PLAY = 0x02;
andrew@0 77 static const MIDIByte MIDI_MMC_DEFERRED_PLAY = 0x03;
andrew@0 78 static const MIDIByte MIDI_MMC_FAST_FORWARD = 0x04;
andrew@0 79 static const MIDIByte MIDI_MMC_REWIND = 0x05;
andrew@0 80 static const MIDIByte MIDI_MMC_RECORD_STROBE = 0x06;
andrew@0 81 static const MIDIByte MIDI_MMC_RECORD_EXIT = 0x07;
andrew@0 82 static const MIDIByte MIDI_MMC_RECORD_PAUSE = 0x08;
andrew@0 83 static const MIDIByte MIDI_MMC_PAUSE = 0x08;
andrew@0 84 static const MIDIByte MIDI_MMC_EJECT = 0x0A;
andrew@0 85 static const MIDIByte MIDI_MMC_LOCATE = 0x44;
andrew@0 86 static const MIDIByte MIDI_FILE_META_EVENT = 0xFF;
andrew@0 87 static const MIDIByte MIDI_SEQUENCE_NUMBER = 0x00;
andrew@0 88 static const MIDIByte MIDI_TEXT_EVENT = 0x01;
andrew@0 89 static const MIDIByte MIDI_COPYRIGHT_NOTICE = 0x02;
andrew@0 90 static const MIDIByte MIDI_TRACK_NAME = 0x03;
andrew@0 91 static const MIDIByte MIDI_INSTRUMENT_NAME = 0x04;
andrew@0 92 static const MIDIByte MIDI_LYRIC = 0x05;
andrew@0 93 static const MIDIByte MIDI_TEXT_MARKER = 0x06;
andrew@0 94 static const MIDIByte MIDI_CUE_POINT = 0x07;
andrew@0 95 static const MIDIByte MIDI_CHANNEL_PREFIX = 0x20;
andrew@0 96 static const MIDIByte MIDI_CHANNEL_PREFIX_OR_PORT = 0x21;
andrew@0 97 static const MIDIByte MIDI_END_OF_TRACK = 0x2F;
andrew@0 98 static const MIDIByte MIDI_SET_TEMPO = 0x51;
andrew@0 99 static const MIDIByte MIDI_SMPTE_OFFSET = 0x54;
andrew@0 100 static const MIDIByte MIDI_TIME_SIGNATURE = 0x58;
andrew@0 101 static const MIDIByte MIDI_KEY_SIGNATURE = 0x59;
andrew@0 102 static const MIDIByte MIDI_SEQUENCER_SPECIFIC = 0x7F;
andrew@0 103 static const MIDIByte MIDI_CONTROLLER_BANK_MSB = 0x00;
andrew@0 104 static const MIDIByte MIDI_CONTROLLER_VOLUME = 0x07;
andrew@0 105 static const MIDIByte MIDI_CONTROLLER_BANK_LSB = 0x20;
andrew@0 106 static const MIDIByte MIDI_CONTROLLER_MODULATION = 0x01;
andrew@0 107 static const MIDIByte MIDI_CONTROLLER_PAN = 0x0A;
andrew@0 108 static const MIDIByte MIDI_CONTROLLER_SUSTAIN = 0x40;
andrew@0 109 static const MIDIByte MIDI_CONTROLLER_RESONANCE = 0x47;
andrew@0 110 static const MIDIByte MIDI_CONTROLLER_RELEASE = 0x48;
andrew@0 111 static const MIDIByte MIDI_CONTROLLER_ATTACK = 0x49;
andrew@0 112 static const MIDIByte MIDI_CONTROLLER_FILTER = 0x4A;
andrew@0 113 static const MIDIByte MIDI_CONTROLLER_REVERB = 0x5B;
andrew@0 114 static const MIDIByte MIDI_CONTROLLER_CHORUS = 0x5D;
andrew@0 115 static const MIDIByte MIDI_CONTROLLER_NRPN_1 = 0x62;
andrew@0 116 static const MIDIByte MIDI_CONTROLLER_NRPN_2 = 0x63;
andrew@0 117 static const MIDIByte MIDI_CONTROLLER_RPN_1 = 0x64;
andrew@0 118 static const MIDIByte MIDI_CONTROLLER_RPN_2 = 0x65;
andrew@0 119 static const MIDIByte MIDI_CONTROLLER_SOUNDS_OFF = 0x78;
andrew@0 120 static const MIDIByte MIDI_CONTROLLER_RESET = 0x79;
andrew@0 121 static const MIDIByte MIDI_CONTROLLER_LOCAL = 0x7A;
andrew@0 122 static const MIDIByte MIDI_CONTROLLER_ALL_NOTES_OFF = 0x7B;
andrew@0 123 static const MIDIByte MIDI_PERCUSSION_CHANNEL = 9;
andrew@0 124
andrew@0 125 typedef enum {
andrew@0 126 MIDI_SINGLE_TRACK_FILE = 0x00,
andrew@0 127 MIDI_SIMULTANEOUS_TRACK_FILE = 0x01,
andrew@0 128 MIDI_SEQUENTIAL_TRACK_FILE = 0x02,
andrew@0 129 MIDI_FILE_BAD_FORMAT = 0xFF
andrew@0 130 } MIDIFileFormatType;
andrew@0 131 }
andrew@0 132
andrew@0 133 class MIDIEvent
andrew@0 134 {
andrew@0 135 public:
andrew@0 136 MIDIEvent(unsigned long deltaTime,
andrew@0 137 MIDIByte eventCode,
andrew@0 138 MIDIByte data1 = 0,
andrew@0 139 MIDIByte data2 = 0) :
andrew@0 140 m_deltaTime(deltaTime),
andrew@0 141 m_duration(0),
andrew@0 142 m_eventCode(eventCode),
andrew@0 143 m_data1(data1),
andrew@0 144 m_data2(data2),
andrew@0 145 m_metaEventCode(0)
andrew@0 146 { }
andrew@0 147
andrew@0 148 MIDIEvent(unsigned long deltaTime,
andrew@0 149 MIDIByte eventCode,
andrew@0 150 MIDIByte metaEventCode,
andrew@0 151 const std::string &metaMessage) :
andrew@0 152 m_deltaTime(deltaTime),
andrew@0 153 m_duration(0),
andrew@0 154 m_eventCode(eventCode),
andrew@0 155 m_data1(0),
andrew@0 156 m_data2(0),
andrew@0 157 m_metaEventCode(metaEventCode),
andrew@0 158 m_metaMessage(metaMessage)
andrew@0 159 { }
andrew@0 160
andrew@0 161 MIDIEvent(unsigned long deltaTime,
andrew@0 162 MIDIByte eventCode,
andrew@0 163 const std::string &sysEx) :
andrew@0 164 m_deltaTime(deltaTime),
andrew@0 165 m_duration(0),
andrew@0 166 m_eventCode(eventCode),
andrew@0 167 m_data1(0),
andrew@0 168 m_data2(0),
andrew@0 169 m_metaEventCode(0),
andrew@0 170 m_metaMessage(sysEx)
andrew@0 171 { }
andrew@0 172
andrew@0 173 ~MIDIEvent() { }
andrew@0 174
andrew@0 175 void setTime(const unsigned long &time) { m_deltaTime = time; }
andrew@0 176 void setDuration(const unsigned long& duration) { m_duration = duration;}
andrew@0 177 unsigned long addTime(const unsigned long &time) {
andrew@0 178 m_deltaTime += time;
andrew@0 179 return m_deltaTime;
andrew@0 180 }
andrew@0 181
andrew@0 182 int getMessageType() const
andrew@0 183 { return (m_eventCode & MIDIConstants::MIDI_MESSAGE_TYPE_MASK); }
andrew@0 184
andrew@0 185 int getChannelNumber() const
andrew@0 186 { return (m_eventCode & MIDIConstants::MIDI_CHANNEL_NUM_MASK); }
andrew@0 187
andrew@0 188 unsigned long getTime() const { return m_deltaTime; }
andrew@0 189 unsigned long getDuration() const { return m_duration; }
andrew@0 190
andrew@0 191 int getPitch() const { return m_data1; }
andrew@0 192 int getVelocity() const { return m_data2; }
andrew@0 193 int getData1() const { return m_data1; }
andrew@0 194 int getData2() const { return m_data2; }
andrew@0 195 int getEventCode() const { return m_eventCode; }
andrew@0 196
andrew@0 197 bool isMeta() const { return (m_eventCode == MIDIConstants::MIDI_FILE_META_EVENT); }
andrew@0 198
andrew@0 199 int getMetaEventCode() const { return m_metaEventCode; }
andrew@0 200 std::string getMetaMessage() const { return m_metaMessage; }
andrew@0 201 void setMetaMessage(const std::string &meta) { m_metaMessage = meta; }
andrew@0 202
andrew@0 203 friend bool operator<(const MIDIEvent &a, const MIDIEvent &b);
andrew@0 204
andrew@0 205 private:
andrew@0 206 unsigned long m_deltaTime;
andrew@0 207 unsigned long m_duration;
andrew@0 208 MIDIByte m_eventCode;
andrew@0 209 MIDIByte m_data1; // or Note
andrew@0 210 MIDIByte m_data2; // or Velocity
andrew@0 211 MIDIByte m_metaEventCode;
andrew@0 212 std::string m_metaMessage;
andrew@0 213 };
andrew@0 214
andrew@0 215 // Comparator for sorting
andrew@0 216 //
andrew@0 217 struct MIDIEventCmp
andrew@0 218 {
andrew@0 219 bool operator()(const MIDIEvent &mE1, const MIDIEvent &mE2) const
andrew@0 220 { return mE1.getTime() < mE2.getTime(); }
andrew@0 221
andrew@0 222 bool operator()(const MIDIEvent *mE1, const MIDIEvent *mE2) const
andrew@0 223 { return mE1->getTime() < mE2->getTime(); }
andrew@0 224 };
andrew@0 225
andrew@0 226 class MIDIException : virtual public std::exception
andrew@0 227 {
andrew@0 228 public:
andrew@0 229 MIDIException(std::string message) throw() : m_message(message) {
andrew@0 230 std::cerr << "WARNING: MIDI exception: " << message.c_str() << std::endl;
andrew@0 231 }
andrew@0 232 virtual ~MIDIException() throw() { }
andrew@0 233
andrew@0 234 virtual const char *what() const throw() {
andrew@0 235 return m_message.c_str();
andrew@0 236 }
andrew@0 237
andrew@0 238 protected:
andrew@0 239 std::string m_message;
andrew@0 240 };
andrew@0 241
andrew@0 242 #endif