1 //
2 // Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
3 // Creation Date: Sat Feb 14 21:40:14 PST 2015
4 // Last Modified: Sat Apr 21 10:52:19 PDT 2018 Removed using namespace std;
5 // Filename: midifile/src/MidiEvent.cpp
6 // Website: http://midifile.sapp.org
7 // Syntax: C++11
8 // vim: ts=3 noexpandtab
9 //
10 // Description: A class which stores a MidiMessage and a timestamp
11 // for the MidiFile class.
12 //
13
14 #include "MidiEvent.h"
15
16 #include <stdlib.h>
17
18
19 namespace smf {
20
21 //////////////////////////////
22 //
23 // MidiEvent::MidiEvent -- Constructor classes
24 //
25
MidiEvent(void)26 MidiEvent::MidiEvent(void) : MidiMessage() {
27 clearVariables();
28 }
29
30
MidiEvent(int command)31 MidiEvent::MidiEvent(int command) : MidiMessage(command) {
32 clearVariables();
33 }
34
35
MidiEvent(int command,int p1)36 MidiEvent::MidiEvent(int command, int p1) : MidiMessage(command, p1) {
37 clearVariables();
38 }
39
40
MidiEvent(int command,int p1,int p2)41 MidiEvent::MidiEvent(int command, int p1, int p2)
42 : MidiMessage(command, p1, p2) {
43 clearVariables();
44 }
45
46
MidiEvent(int aTime,int aTrack,vector<uchar> & message)47 MidiEvent::MidiEvent(int aTime, int aTrack, vector<uchar>& message)
48 : MidiMessage(message) {
49 track = aTrack;
50 tick = aTime;
51 seconds = 0.0;
52 seq = 0;
53 m_eventlink = NULL;
54 }
55
56
MidiEvent(const MidiEvent & mfevent)57 MidiEvent::MidiEvent(const MidiEvent& mfevent) : MidiMessage() {
58 track = mfevent.track;
59 tick = mfevent.tick;
60 seconds = mfevent.seconds;
61 seq = mfevent.seq;
62 m_eventlink = NULL;
63
64 this->resize(mfevent.size());
65 for (int i=0; i<(int)this->size(); i++) {
66 (*this)[i] = mfevent[i];
67 }
68 }
69
70
71
72 //////////////////////////////
73 //
74 // MidiEvent::~MidiEvent -- MidiFile Event destructor
75 //
76
~MidiEvent()77 MidiEvent::~MidiEvent() {
78 track = -1;
79 tick = -1;
80 seconds = -1.0;
81 seq = -1;
82 this->resize(0);
83 m_eventlink = NULL;
84 }
85
86
87 //////////////////////////////
88 //
89 // MidiEvent::clearVariables -- Clear everything except MidiMessage data.
90 //
91
clearVariables(void)92 void MidiEvent::clearVariables(void) {
93 track = 0;
94 tick = 0;
95 seconds = 0.0;
96 seq = 0;
97 m_eventlink = NULL;
98 }
99
100
101 //////////////////////////////
102 //
103 // MidiEvent::operator= -- Copy the contents of another MidiEvent.
104 //
105
operator =(const MidiEvent & mfevent)106 MidiEvent& MidiEvent::operator=(const MidiEvent& mfevent) {
107 if (this == &mfevent) {
108 return *this;
109 }
110 tick = mfevent.tick;
111 track = mfevent.track;
112 seconds = mfevent.seconds;
113 seq = mfevent.seq;
114 m_eventlink = NULL;
115 this->resize(mfevent.size());
116 for (int i=0; i<(int)this->size(); i++) {
117 (*this)[i] = mfevent[i];
118 }
119 return *this;
120 }
121
122
operator =(const MidiMessage & message)123 MidiEvent& MidiEvent::operator=(const MidiMessage& message) {
124 if (this == &message) {
125 return *this;
126 }
127 clearVariables();
128 this->resize(message.size());
129 for (int i=0; i<(int)this->size(); i++) {
130 (*this)[i] = message[i];
131 }
132 return *this;
133 }
134
135
operator =(const vector<uchar> & bytes)136 MidiEvent& MidiEvent::operator=(const vector<uchar>& bytes) {
137 clearVariables();
138 this->resize(bytes.size());
139 for (int i=0; i<(int)this->size(); i++) {
140 (*this)[i] = bytes[i];
141 }
142 return *this;
143 }
144
145
operator =(const vector<char> & bytes)146 MidiEvent& MidiEvent::operator=(const vector<char>& bytes) {
147 clearVariables();
148 setMessage(bytes);
149 return *this;
150 }
151
152
operator =(const vector<int> & bytes)153 MidiEvent& MidiEvent::operator=(const vector<int>& bytes) {
154 clearVariables();
155 setMessage(bytes);
156 return *this;
157 }
158
159
160
161 //////////////////////////////
162 //
163 // MidiEvent::unlinkEvent -- Disassociate this event with another.
164 // Also tell the other event to disassociate from this event.
165 //
166
unlinkEvent(void)167 void MidiEvent::unlinkEvent(void) {
168 if (m_eventlink == NULL) {
169 return;
170 }
171 MidiEvent* mev = m_eventlink;
172 m_eventlink = NULL;
173 mev->unlinkEvent();
174 }
175
176
177
178 //////////////////////////////
179 //
180 // MidiEvent::linkEvent -- Make a link between two messages.
181 // Unlinking
182 //
183
linkEvent(MidiEvent * mev)184 void MidiEvent::linkEvent(MidiEvent* mev) {
185 if (mev->m_eventlink != NULL) {
186 // unlink other event if it is linked to something else;
187 mev->unlinkEvent();
188 }
189 // if this is already linked to something else, then unlink:
190 if (m_eventlink != NULL) {
191 m_eventlink->unlinkEvent();
192 }
193 unlinkEvent();
194
195 mev->m_eventlink = this;
196 m_eventlink = mev;
197 }
198
199
linkEvent(MidiEvent & mev)200 void MidiEvent::linkEvent(MidiEvent& mev) {
201 linkEvent(&mev);
202 }
203
204
205
206 //////////////////////////////
207 //
208 // MidiEvent::getLinkedEvent -- Returns a linked event. Usually
209 // this is the note-off message for a note-on message and vice-versa.
210 // Returns null if there are no links.
211 //
212
getLinkedEvent(void)213 MidiEvent* MidiEvent::getLinkedEvent(void) {
214 return m_eventlink;
215 }
216
217
getLinkedEvent(void) const218 const MidiEvent* MidiEvent::getLinkedEvent(void) const {
219 return m_eventlink;
220 }
221
222
223
224 //////////////////////////////
225 //
226 // MidiEvent::isLinked -- Returns true if there is an event which is not
227 // NULL. This function is similar to getLinkedEvent().
228 //
229
isLinked(void) const230 int MidiEvent::isLinked(void) const {
231 return m_eventlink == NULL ? 0 : 1;
232 }
233
234
235
236 //////////////////////////////
237 //
238 // MidiEvent::getTickDuration -- For linked events (note-ons and note-offs),
239 // return the absolute tick time difference between the two events.
240 // The tick values are presumed to be in absolute tick mode rather than
241 // delta tick mode. Returns 0 if not linked.
242 //
243
getTickDuration(void) const244 int MidiEvent::getTickDuration(void) const {
245 const MidiEvent* mev = getLinkedEvent();
246 if (mev == NULL) {
247 return 0;
248 }
249 int tick2 = mev->tick;
250 if (tick2 > tick) {
251 return tick2 - tick;
252 } else {
253 return tick - tick2;
254 }
255 }
256
257
258
259 //////////////////////////////
260 //
261 // MidiEvent::getDurationInSeconds -- For linked events (note-ons and
262 // note-offs), return the duration of the note in seconds. The
263 // seconds analysis must be done first; otherwise the duration will be
264 // reported as zero.
265 //
266
getDurationInSeconds(void) const267 double MidiEvent::getDurationInSeconds(void) const {
268 const MidiEvent* mev = getLinkedEvent();
269 if (mev == NULL) {
270 return 0;
271 }
272 double seconds2 = mev->seconds;
273 if (seconds2 > seconds) {
274 return seconds2 - seconds;
275 } else {
276 return seconds - seconds2;
277 }
278 }
279
280
281 } // end namespace smf
282
283
284
285