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