annotate data/midi/MIDIEvent.h @ 1848:98339fac0faf

Avoid returning expired pointers
author Chris Cannam
date Thu, 23 Apr 2020 15:39:08 +0100
parents c3b5564cfb78
children
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@1848 231 static QByteArray msg;
Chris@1848 232 msg = m_message.toLocal8Bit();
Chris@1848 233 return msg.data();
Chris@301 234 }
Chris@301 235
Chris@301 236 protected:
Chris@301 237 QString m_message;
Chris@301 238 };
Chris@301 239
Chris@301 240 #endif