comparison data/fileio/MIDIEvent.h @ 301:73537d900d4b

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