annotate data/midi/MIDIEvent.h @ 1773:fadd9f8aaa27

This output is too annoying, in the perfectly innocuous case of reading from an aggregate model whose components are different lengths
author Chris Cannam
date Wed, 14 Aug 2019 13:54:23 +0100
parents c3b5564cfb78
children 98339fac0faf
rev   line source
Chris@301 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@301 2
Chris@301 3 /*
Chris@301 4 Sonic Visualiser
Chris@301 5 An audio file viewer and annotation editor.
Chris@301 6 Centre for Digital Music, Queen Mary, University of London.
Chris@301 7
Chris@301 8 This program is free software; you can redistribute it and/or
Chris@301 9 modify it under the terms of the GNU General Public License as
Chris@301 10 published by the Free Software Foundation; either version 2 of the
Chris@301 11 License, or (at your option) any later version. See the file
Chris@301 12 COPYING included with this distribution for more information.
Chris@301 13 */
Chris@301 14
Chris@301 15
Chris@301 16 /*
Chris@301 17 This is a modified version of a source file from the
Chris@301 18 Rosegarden MIDI and audio sequencer and notation editor.
Chris@301 19 This file copyright 2000-2006 Richard Bown and Chris Cannam.
Chris@301 20 */
Chris@301 21
Chris@1581 22 #ifndef SV_MIDI_EVENT_H
Chris@1581 23 #define SV_MIDI_EVENT_H
Chris@301 24
Chris@301 25 #include <QString>
Chris@301 26 #include <string>
Chris@301 27 #include <iostream>
Chris@1038 28 #include <stdexcept>
Chris@1038 29
Chris@687 30 #include "base/Debug.h"
Chris@301 31
Chris@301 32 typedef unsigned char MIDIByte;
Chris@301 33
Chris@301 34 namespace MIDIConstants
Chris@301 35 {
Chris@301 36 static const char *const MIDI_FILE_HEADER = "MThd";
Chris@301 37 static const char *const MIDI_TRACK_HEADER = "MTrk";
Chris@301 38
Chris@301 39 static const MIDIByte MIDI_STATUS_BYTE_MASK = 0x80;
Chris@301 40 static const MIDIByte MIDI_MESSAGE_TYPE_MASK = 0xF0;
Chris@301 41 static const MIDIByte MIDI_CHANNEL_NUM_MASK = 0x0F;
Chris@301 42
Chris@301 43 static const MIDIByte MIDI_NOTE_OFF = 0x80;
Chris@301 44 static const MIDIByte MIDI_NOTE_ON = 0x90;
Chris@301 45 static const MIDIByte MIDI_POLY_AFTERTOUCH = 0xA0;
Chris@301 46 static const MIDIByte MIDI_CTRL_CHANGE = 0xB0;
Chris@301 47 static const MIDIByte MIDI_PROG_CHANGE = 0xC0;
Chris@301 48 static const MIDIByte MIDI_CHNL_AFTERTOUCH = 0xD0;
Chris@301 49 static const MIDIByte MIDI_PITCH_BEND = 0xE0;
Chris@301 50 static const MIDIByte MIDI_SELECT_CHNL_MODE = 0xB0;
Chris@301 51 static const MIDIByte MIDI_SYSTEM_EXCLUSIVE = 0xF0;
Chris@301 52 static const MIDIByte MIDI_TC_QUARTER_FRAME = 0xF1;
Chris@301 53 static const MIDIByte MIDI_SONG_POSITION_PTR = 0xF2;
Chris@301 54 static const MIDIByte MIDI_SONG_SELECT = 0xF3;
Chris@301 55 static const MIDIByte MIDI_TUNE_REQUEST = 0xF6;
Chris@301 56 static const MIDIByte MIDI_END_OF_EXCLUSIVE = 0xF7;
Chris@301 57 static const MIDIByte MIDI_TIMING_CLOCK = 0xF8;
Chris@301 58 static const MIDIByte MIDI_START = 0xFA;
Chris@301 59 static const MIDIByte MIDI_CONTINUE = 0xFB;
Chris@301 60 static const MIDIByte MIDI_STOP = 0xFC;
Chris@301 61 static const MIDIByte MIDI_ACTIVE_SENSING = 0xFE;
Chris@301 62 static const MIDIByte MIDI_SYSTEM_RESET = 0xFF;
Chris@301 63 static const MIDIByte MIDI_SYSEX_NONCOMMERCIAL = 0x7D;
Chris@301 64 static const MIDIByte MIDI_SYSEX_NON_RT = 0x7E;
Chris@301 65 static const MIDIByte MIDI_SYSEX_RT = 0x7F;
Chris@301 66 static const MIDIByte MIDI_SYSEX_RT_COMMAND = 0x06;
Chris@301 67 static const MIDIByte MIDI_SYSEX_RT_RESPONSE = 0x07;
Chris@301 68 static const MIDIByte MIDI_MMC_STOP = 0x01;
Chris@301 69 static const MIDIByte MIDI_MMC_PLAY = 0x02;
Chris@301 70 static const MIDIByte MIDI_MMC_DEFERRED_PLAY = 0x03;
Chris@301 71 static const MIDIByte MIDI_MMC_FAST_FORWARD = 0x04;
Chris@301 72 static const MIDIByte MIDI_MMC_REWIND = 0x05;
Chris@301 73 static const MIDIByte MIDI_MMC_RECORD_STROBE = 0x06;
Chris@301 74 static const MIDIByte MIDI_MMC_RECORD_EXIT = 0x07;
Chris@301 75 static const MIDIByte MIDI_MMC_RECORD_PAUSE = 0x08;
Chris@301 76 static const MIDIByte MIDI_MMC_PAUSE = 0x08;
Chris@301 77 static const MIDIByte MIDI_MMC_EJECT = 0x0A;
Chris@301 78 static const MIDIByte MIDI_MMC_LOCATE = 0x44;
Chris@301 79 static const MIDIByte MIDI_FILE_META_EVENT = 0xFF;
Chris@301 80 static const MIDIByte MIDI_SEQUENCE_NUMBER = 0x00;
Chris@301 81 static const MIDIByte MIDI_TEXT_EVENT = 0x01;
Chris@301 82 static const MIDIByte MIDI_COPYRIGHT_NOTICE = 0x02;
Chris@301 83 static const MIDIByte MIDI_TRACK_NAME = 0x03;
Chris@301 84 static const MIDIByte MIDI_INSTRUMENT_NAME = 0x04;
Chris@301 85 static const MIDIByte MIDI_LYRIC = 0x05;
Chris@301 86 static const MIDIByte MIDI_TEXT_MARKER = 0x06;
Chris@301 87 static const MIDIByte MIDI_CUE_POINT = 0x07;
Chris@301 88 static const MIDIByte MIDI_CHANNEL_PREFIX = 0x20;
Chris@301 89 static const MIDIByte MIDI_CHANNEL_PREFIX_OR_PORT = 0x21;
Chris@301 90 static const MIDIByte MIDI_END_OF_TRACK = 0x2F;
Chris@301 91 static const MIDIByte MIDI_SET_TEMPO = 0x51;
Chris@301 92 static const MIDIByte MIDI_SMPTE_OFFSET = 0x54;
Chris@301 93 static const MIDIByte MIDI_TIME_SIGNATURE = 0x58;
Chris@301 94 static const MIDIByte MIDI_KEY_SIGNATURE = 0x59;
Chris@301 95 static const MIDIByte MIDI_SEQUENCER_SPECIFIC = 0x7F;
Chris@301 96 static const MIDIByte MIDI_CONTROLLER_BANK_MSB = 0x00;
Chris@301 97 static const MIDIByte MIDI_CONTROLLER_VOLUME = 0x07;
Chris@301 98 static const MIDIByte MIDI_CONTROLLER_BANK_LSB = 0x20;
Chris@301 99 static const MIDIByte MIDI_CONTROLLER_MODULATION = 0x01;
Chris@301 100 static const MIDIByte MIDI_CONTROLLER_PAN = 0x0A;
Chris@301 101 static const MIDIByte MIDI_CONTROLLER_SUSTAIN = 0x40;
Chris@301 102 static const MIDIByte MIDI_CONTROLLER_RESONANCE = 0x47;
Chris@301 103 static const MIDIByte MIDI_CONTROLLER_RELEASE = 0x48;
Chris@301 104 static const MIDIByte MIDI_CONTROLLER_ATTACK = 0x49;
Chris@301 105 static const MIDIByte MIDI_CONTROLLER_FILTER = 0x4A;
Chris@301 106 static const MIDIByte MIDI_CONTROLLER_REVERB = 0x5B;
Chris@301 107 static const MIDIByte MIDI_CONTROLLER_CHORUS = 0x5D;
Chris@301 108 static const MIDIByte MIDI_CONTROLLER_NRPN_1 = 0x62;
Chris@301 109 static const MIDIByte MIDI_CONTROLLER_NRPN_2 = 0x63;
Chris@301 110 static const MIDIByte MIDI_CONTROLLER_RPN_1 = 0x64;
Chris@301 111 static const MIDIByte MIDI_CONTROLLER_RPN_2 = 0x65;
Chris@301 112 static const MIDIByte MIDI_CONTROLLER_SOUNDS_OFF = 0x78;
Chris@301 113 static const MIDIByte MIDI_CONTROLLER_RESET = 0x79;
Chris@301 114 static const MIDIByte MIDI_CONTROLLER_LOCAL = 0x7A;
Chris@301 115 static const MIDIByte MIDI_CONTROLLER_ALL_NOTES_OFF = 0x7B;
Chris@301 116 static const MIDIByte MIDI_PERCUSSION_CHANNEL = 9;
Chris@301 117 }
Chris@301 118
Chris@301 119 class MIDIEvent
Chris@301 120 {
Chris@301 121 public:
Chris@301 122 MIDIEvent(unsigned long deltaTime,
Chris@1038 123 int eventCode,
Chris@1038 124 int data1 = 0,
Chris@1038 125 int data2 = 0) :
Chris@1429 126 m_deltaTime(deltaTime),
Chris@1429 127 m_duration(0),
Chris@1429 128 m_metaEventCode(0)
Chris@1038 129 {
Chris@1038 130 if (eventCode < 0 || eventCode > 0xff ||
Chris@1038 131 data1 < 0 || data1 > 0xff ||
Chris@1038 132 data2 < 0 || data2 > 0xff) {
Chris@1038 133 throw std::domain_error("not all args within byte range");
Chris@1038 134 }
Chris@1038 135 m_eventCode = MIDIByte(eventCode);
Chris@1038 136 m_data1 = MIDIByte(data1);
Chris@1038 137 m_data2 = MIDIByte(data2);
Chris@1038 138 }
Chris@301 139
Chris@301 140 MIDIEvent(unsigned long deltaTime,
Chris@301 141 MIDIByte eventCode,
Chris@301 142 MIDIByte metaEventCode,
Chris@301 143 const std::string &metaMessage) :
Chris@1429 144 m_deltaTime(deltaTime),
Chris@1429 145 m_duration(0),
Chris@1429 146 m_eventCode(eventCode),
Chris@1429 147 m_data1(0),
Chris@1429 148 m_data2(0),
Chris@1429 149 m_metaEventCode(metaEventCode),
Chris@1429 150 m_metaMessage(metaMessage)
Chris@301 151 { }
Chris@301 152
Chris@301 153 MIDIEvent(unsigned long deltaTime,
Chris@301 154 MIDIByte eventCode,
Chris@301 155 const std::string &sysEx) :
Chris@1429 156 m_deltaTime(deltaTime),
Chris@1429 157 m_duration(0),
Chris@1429 158 m_eventCode(eventCode),
Chris@1429 159 m_data1(0),
Chris@1429 160 m_data2(0),
Chris@1429 161 m_metaEventCode(0),
Chris@1429 162 m_metaMessage(sysEx)
Chris@301 163 { }
Chris@301 164
Chris@1733 165 MIDIEvent(const MIDIEvent &) =default;
Chris@1733 166 MIDIEvent& operator=(const MIDIEvent &) =default;
Chris@1733 167
Chris@301 168 ~MIDIEvent() { }
Chris@301 169
Chris@301 170 void setTime(const unsigned long &time) { m_deltaTime = time; }
Chris@301 171 void setDuration(const unsigned long& duration) { m_duration = duration;}
Chris@301 172 unsigned long addTime(const unsigned long &time) {
Chris@1429 173 m_deltaTime += time;
Chris@1429 174 return m_deltaTime;
Chris@301 175 }
Chris@301 176
Chris@301 177 MIDIByte getMessageType() const
Chris@301 178 { return (m_eventCode & MIDIConstants::MIDI_MESSAGE_TYPE_MASK); }
Chris@301 179
Chris@301 180 MIDIByte getChannelNumber() const
Chris@301 181 { return (m_eventCode & MIDIConstants::MIDI_CHANNEL_NUM_MASK); }
Chris@301 182
Chris@301 183 unsigned long getTime() const { return m_deltaTime; }
Chris@301 184 unsigned long getDuration() const { return m_duration; }
Chris@301 185
Chris@301 186 MIDIByte getPitch() const { return m_data1; }
Chris@301 187 MIDIByte getVelocity() const { return m_data2; }
Chris@301 188 MIDIByte getData1() const { return m_data1; }
Chris@301 189 MIDIByte getData2() const { return m_data2; }
Chris@301 190 MIDIByte getEventCode() const { return m_eventCode; }
Chris@301 191
Chris@301 192 bool isMeta() const { return (m_eventCode == MIDIConstants::MIDI_FILE_META_EVENT); }
Chris@301 193
Chris@301 194 MIDIByte getMetaEventCode() const { return m_metaEventCode; }
Chris@301 195 std::string getMetaMessage() const { return m_metaMessage; }
Chris@301 196 void setMetaMessage(const std::string &meta) { m_metaMessage = meta; }
Chris@301 197
Chris@301 198 friend bool operator<(const MIDIEvent &a, const MIDIEvent &b);
Chris@301 199
Chris@301 200 private:
Chris@301 201 unsigned long m_deltaTime;
Chris@301 202 unsigned long m_duration;
Chris@301 203 MIDIByte m_eventCode;
Chris@301 204 MIDIByte m_data1; // or Note
Chris@301 205 MIDIByte m_data2; // or Velocity
Chris@301 206 MIDIByte m_metaEventCode;
Chris@301 207 std::string m_metaMessage;
Chris@301 208 };
Chris@301 209
Chris@301 210 // Comparator for sorting
Chris@301 211 //
Chris@301 212 struct MIDIEventCmp
Chris@301 213 {
Chris@301 214 bool operator()(const MIDIEvent &mE1, const MIDIEvent &mE2) const
Chris@301 215 { return mE1.getTime() < mE2.getTime(); }
Chris@301 216
Chris@301 217 bool operator()(const MIDIEvent *mE1, const MIDIEvent *mE2) const
Chris@301 218 { return mE1->getTime() < mE2->getTime(); }
Chris@301 219 };
Chris@301 220
Chris@301 221 class MIDIException : virtual public std::exception
Chris@301 222 {
Chris@301 223 public:
Chris@301 224 MIDIException(QString message) throw() : m_message(message) {
Chris@301 225 std::cerr << "WARNING: MIDI exception: "
Chris@1429 226 << message.toLocal8Bit().data() << std::endl;
Chris@301 227 }
Chris@301 228 virtual ~MIDIException() throw() { }
Chris@301 229
Chris@1580 230 const char *what() const throw() override {
Chris@1429 231 return m_message.toLocal8Bit().data();
Chris@301 232 }
Chris@301 233
Chris@301 234 protected:
Chris@301 235 QString m_message;
Chris@301 236 };
Chris@301 237
Chris@301 238 #endif