26MidiMessageSequence::MidiEventHolder::MidiEventHolder (
const MidiMessage& mm) : message (mm) {}
27MidiMessageSequence::MidiEventHolder::MidiEventHolder (MidiMessage&& mm) : message (std::move (mm)) {}
28MidiMessageSequence::MidiEventHolder::~MidiEventHolder() {}
31MidiMessageSequence::MidiMessageSequence()
37 list.addCopiesOf (
other.list);
39 for (
int i = 0; i < list.size(); ++i)
56 : list (std::move (
other.list))
62 list = std::move (
other.list);
66MidiMessageSequence::~MidiMessageSequence()
72 list.swapWith (
other.list);
75void MidiMessageSequence::clear()
95double MidiMessageSequence::getTimeOfMatchingKeyUp (
int index)
const noexcept
97 if (
auto*
meh = list[index])
98 if (
auto* noteOff =
meh->noteOffObject)
99 return noteOff->message.getTimeStamp();
104int MidiMessageSequence::getIndexOfMatchingKeyUp (
int index)
const noexcept
106 if (
auto*
meh = list[index])
108 if (
auto* noteOff =
meh->noteOffObject)
110 for (
int i = index; i < list.size(); ++i)
111 if (list.getUnchecked(i) == noteOff)
123 return list.indexOf (
event);
126int MidiMessageSequence::getNextIndexAtTime (
double timeStamp)
const noexcept
132 if (list.getUnchecked(i)->message.getTimeStamp() >= timeStamp)
141 return getEventTime (0);
146 return getEventTime (list.size() - 1);
149double MidiMessageSequence::getEventTime (
const int index)
const noexcept
151 if (
auto*
meh = list[index])
152 return meh->message.getTimeStamp();
161 auto time =
newEvent->message.getTimeStamp();
164 for (i = list.size(); --i >= 0;)
165 if (list.getUnchecked(i)->message.getTimeStamp() <= time)
184 if (isPositiveAndBelow (index, list.
size()))
187 deleteEvent (getIndexOfMatchingKeyUp (index),
false);
195 for (
auto* m :
other)
210 for (
auto* m :
other)
217 newOne->message.setTimeStamp (
t);
227 std::stable_sort (list.begin(), list.end(),
231void MidiMessageSequence::updateMatchedPairs()
noexcept
233 for (
int i = 0; i < list.
size(); ++i)
236 auto&
m1 =
meh->message;
240 meh->noteOffObject =
nullptr;
241 auto note =
m1.getNoteNumber();
242 auto chan =
m1.getChannel();
245 for (
int j = i + 1;
j <
len; ++
j)
248 auto& m =
meh2->message;
250 if (m.getNoteNumber() ==
note && m.getChannel() ==
chan)
262 newEvent->message.setTimeStamp (m.getTimeStamp());
272void MidiMessageSequence::addTimeToMessages (
double delta)
noexcept
276 m->message.addToTimeStamp (
delta);
284 for (
auto*
meh : list)
292 for (
auto*
meh : list)
293 if (
meh->message.isSysEx())
299 for (
int i = list.
size(); --i >= 0;)
304void MidiMessageSequence::deleteSysExMessages()
306 for (
int i = list.
size(); --i >= 0;)
307 if (list.getUnchecked(i)->message.isSysEx())
318 for (
int i = list.
size(); --i >= 0;)
334 else if (
mm.isController())
357 :
UnitTest (
"MidiMessageSequence", UnitTestCategories::midi)
360 void runTest()
override
362 MidiMessageSequence s;
364 s.addEvent (MidiMessage::noteOn (1, 60, 0.5f).withTimeStamp (0.0));
365 s.addEvent (MidiMessage::noteOff (1, 60, 0.5f).withTimeStamp (4.0));
366 s.addEvent (MidiMessage::noteOn (1, 30, 0.5f).withTimeStamp (2.0));
367 s.addEvent (MidiMessage::noteOff (1, 30, 0.5f).withTimeStamp (8.0));
369 beginTest (
"Start & end time");
370 expectEquals (s.getStartTime(), 0.0);
371 expectEquals (s.getEndTime(), 8.0);
372 expectEquals (s.getEventTime (1), 2.0);
374 beginTest (
"Matching note off & ons");
375 s.updateMatchedPairs();
376 expectEquals (s.getTimeOfMatchingKeyUp (0), 4.0);
377 expectEquals (s.getTimeOfMatchingKeyUp (1), 8.0);
378 expectEquals (s.getIndexOfMatchingKeyUp (0), 2);
379 expectEquals (s.getIndexOfMatchingKeyUp (1), 3);
381 beginTest (
"Time & indices");
382 expectEquals (s.getNextIndexAtTime (0.5), 1);
383 expectEquals (s.getNextIndexAtTime (2.5), 2);
384 expectEquals (s.getNextIndexAtTime (9.0), 4);
386 beginTest (
"Deleting events");
387 s.deleteEvent (0,
true);
388 expectEquals (s.getNumEvents(), 2);
390 beginTest (
"Merging sequences");
391 MidiMessageSequence s2;
392 s2.addEvent (MidiMessage::noteOn (2, 25, 0.5f).withTimeStamp (0.0));
393 s2.addEvent (MidiMessage::noteOn (2, 40, 0.5f).withTimeStamp (1.0));
394 s2.addEvent (MidiMessage::noteOff (2, 40, 0.5f).withTimeStamp (5.0));
395 s2.addEvent (MidiMessage::noteOn (2, 80, 0.5f).withTimeStamp (3.0));
396 s2.addEvent (MidiMessage::noteOff (2, 80, 0.5f).withTimeStamp (7.0));
397 s2.addEvent (MidiMessage::noteOff (2, 25, 0.5f).withTimeStamp (9.0));
399 s.addSequence (s2, 0.0, 0.0, 8.0);
400 s.updateMatchedPairs();
402 expectEquals (s.getNumEvents(), 7);
403 expectEquals (s.getIndexOfMatchingKeyUp (0), -1);
404 expectEquals (s.getTimeOfMatchingKeyUp (1), 5.0);
408static MidiMessageSequenceTest midiMessageSequenceTests;
ElementType getUnchecked(int index) const
int size() const noexcept
void remove(int indexToRemove)
void insert(int indexToInsertAt, ParameterType newElement)
ElementType * begin() noexcept
ElementType * end() noexcept
void add(const ElementType &newElement)