38 for (
int i = 0;
i <
list.size(); ++
i)
42 if (noteOffIndex >= 0)
43 list.getUnchecked(
i)->noteOffObject =
list.getUnchecked (noteOffIndex);
55 :
list (std::move (other.list))
61 list = std::move (other.list);
67 list.swapWith (other.list);
92 if (
auto* meh =
list[index])
93 if (
auto* noteOff = meh->noteOffObject)
94 return noteOff->message.getTimeStamp();
101 if (
auto* meh =
list[index])
103 if (
auto* noteOff = meh->noteOffObject)
105 for (
int i = index;
i <
list.size(); ++
i)
106 if (
list.getUnchecked(
i) == noteOff)
118 return list.indexOf (event);
123 auto numEvents =
list.size();
126 for (
i = 0;
i < numEvents; ++
i)
127 if (
list.getUnchecked(
i)->message.getTimeStamp() >= timeStamp)
146 if (
auto* meh =
list[index])
147 return meh->message.getTimeStamp();
159 for (
i =
list.size(); --
i >= 0;)
160 if (
list.getUnchecked(
i)->message.getTimeStamp() <= time)
163 list.insert (
i + 1, newEvent);
181 if (deleteMatchingNoteUp)
190 for (
auto*
m : other)
193 newOne->message.addToTimeStamp (timeAdjustment);
201 double timeAdjustment,
202 double firstAllowableTime,
203 double endOfAllowableDestTimes)
205 for (
auto*
m : other)
207 auto t =
m->message.getTimeStamp() + timeAdjustment;
209 if (
t >= firstAllowableTime &&
t < endOfAllowableDestTimes)
212 newOne->message.setTimeStamp (
t);
222 std::stable_sort (
list.begin(),
list.end(),
228 for (
int i = 0;
i <
list.size(); ++
i)
230 auto* meh =
list.getUnchecked(
i);
231 auto& m1 = meh->message;
235 meh->noteOffObject =
nullptr;
236 auto note = m1.getNoteNumber();
237 auto chan = m1.getChannel();
238 auto len =
list.size();
240 for (
int j =
i + 1;
j < len; ++
j)
242 auto* meh2 =
list.getUnchecked(
j);
243 auto&
m = meh2->message;
245 if (
m.getNoteNumber() == note &&
m.getChannel() == chan)
249 meh->noteOffObject = meh2;
256 list.insert (
j, newEvent);
257 newEvent->message.setTimeStamp (
m.getTimeStamp());
258 meh->noteOffObject = newEvent;
271 m->message.addToTimeStamp (delta);
277 const bool alsoIncludeMetaEvents)
const
279 for (
auto* meh :
list)
280 if (meh->message.isForChannel (channelNumberToExtract)
281 || (alsoIncludeMetaEvents && meh->message.isMetaEvent()))
282 destSequence.
addEvent (meh->message);
287 for (
auto* meh :
list)
288 if (meh->message.isSysEx())
289 destSequence.
addEvent (meh->message);
294 for (
int i =
list.size(); --
i >= 0;)
295 if (
list.getUnchecked(
i)->message.isForChannel (channelNumberToRemove))
301 for (
int i =
list.size(); --
i >= 0;)
302 if (
list.getUnchecked(
i)->message.isSysEx())
314 if (
value.hasValue())
331 for (
auto it = std::begin (
values); it != std::end (
values); ++it)
349 if (!
value.hasValue())
366 case 0x00:
bankMSB = (char)
v;
return true;
367 case 0x20:
bankLSB = (char)
v;
return true;
394 const auto newest = std::tie (
newestKind, newestMsb, newestLsb);
396 if (lastSent == newest || ! newestMsb.hasValue() || ! newestLsb.hasValue())
427 for (
const auto& item :
list)
429 const auto&
mm = item->message;
431 if (! (
mm.isForChannel (channel) &&
mm.getTimeStamp() <= time))
434 if (
mm.isController())
436 const auto num =
mm.getControllerNumber();
441 if (programChange.
trySetBank (num,
mm.getControllerValue()))
444 constexpr int passthroughs[] { 0x06, 0x26, 0x60, 0x61 };
446 if (std::find (std::begin (passthroughs), std::end (passthroughs), num) != std::end (passthroughs))
453 controllers.
set (num,
mm.getControllerValue());
456 else if (
mm.isProgramChange())
460 else if (
mm.isPitchWheel())
462 pitchWheel.
set (
mm.getPitchWheelValue());
466 pitchWheel.
emit (channel, dest);
467 controllers.
emit (channel, dest);
470 programChange.
emit (channel, time, dest);
480struct MidiMessageSequenceTest :
public UnitTest
482 MidiMessageSequenceTest()
486 void runTest()
override
488 MidiMessageSequence
s;
495 beginTest (
"Start & end time");
496 expectEquals (
s.getStartTime(), 0.0);
497 expectEquals (
s.getEndTime(), 8.0);
498 expectEquals (
s.getEventTime (1), 2.0);
500 beginTest (
"Matching note off & ons");
501 s.updateMatchedPairs();
502 expectEquals (
s.getTimeOfMatchingKeyUp (0), 4.0);
503 expectEquals (
s.getTimeOfMatchingKeyUp (1), 8.0);
504 expectEquals (
s.getIndexOfMatchingKeyUp (0), 2);
505 expectEquals (
s.getIndexOfMatchingKeyUp (1), 3);
507 beginTest (
"Time & indices");
508 expectEquals (
s.getNextIndexAtTime (0.5), 1);
509 expectEquals (
s.getNextIndexAtTime (2.5), 2);
510 expectEquals (
s.getNextIndexAtTime (9.0), 4);
512 beginTest (
"Deleting events");
513 s.deleteEvent (0,
true);
514 expectEquals (
s.getNumEvents(), 2);
516 beginTest (
"Merging sequences");
517 MidiMessageSequence s2;
525 s.addSequence (s2, 0.0, 0.0, 8.0);
526 s.updateMatchedPairs();
528 expectEquals (
s.getNumEvents(), 7);
529 expectEquals (
s.getIndexOfMatchingKeyUp (0), -1);
530 expectEquals (
s.getTimeOfMatchingKeyUp (1), 5.0);
536 int controllerBase, channel, parameter,
value;
539 std::array<ControlValue, 4> getControlValues()
const
541 return { { { controllerBase + 1, (parameter >> 7) & 0x7f },
542 { controllerBase + 0, (parameter >> 0) & 0x7f },
543 { 0x06, (
value >> 7) & 0x7f },
544 { 0x26, (
value >> 0) & 0x7f } } };
547 void addToSequence (MidiMessageSequence&
s)
const
549 for (
const auto& pair : getControlValues())
553 bool matches (
const MidiMessage* begin,
const MidiMessage* end)
const
555 const auto isEqual = [
this] (
const ControlValue& cv,
const MidiMessage&
msg)
557 return msg.getTimeStamp() ==
time
558 &&
msg.isController()
559 &&
msg.getChannel() == channel
560 &&
msg.getControllerNumber() == cv.control
561 &&
msg.getControllerValue() == cv.value;
564 const auto pairs = getControlValues();
565 return std::equal (pairs.begin(), pairs.end(), begin, end, isEqual);
569 const auto addNrpn = [&] (MidiMessageSequence& seq,
int channel,
int parameter,
int value,
double time = 0.0)
571 DataEntry { 0x62, channel, parameter,
value,
time }.addToSequence (seq);
574 const auto addRpn = [&] (MidiMessageSequence& seq,
int channel,
int parameter,
int value,
double time = 0.0)
576 DataEntry { 0x64, channel, parameter,
value,
time }.addToSequence (seq);
579 const auto checkNrpn = [&] (
const MidiMessage*
begin,
const MidiMessage*
end,
int channel,
int parameter,
int value,
double time = 0.0)
581 expect (DataEntry { 0x62, channel, parameter,
value,
time }.matches (begin, end));
584 const auto checkRpn = [&] (
const MidiMessage*
begin,
const MidiMessage*
end,
int channel,
int parameter,
int value,
double time = 0.0)
586 expect (DataEntry { 0x64, channel, parameter,
value,
time }.matches (begin, end));
589 beginTest (
"createControllerUpdatesForTime should emit (N)RPN components in the correct order");
591 const auto channel = 1;
592 const auto number = 200;
593 const auto value = 300;
595 MidiMessageSequence sequence;
596 addNrpn (sequence, channel, number,
value);
598 Array<MidiMessage>
m;
599 sequence.createControllerUpdatesForTime (channel, 1.0,
m);
601 checkNrpn (
m.begin(),
m.end(), channel, number,
value);
604 beginTest (
"createControllerUpdatesForTime ignores (N)RPNs after the final requested time");
606 const auto channel = 2;
607 const auto number = 123;
608 const auto value = 456;
610 MidiMessageSequence sequence;
611 addRpn (sequence, channel, number,
value, 0.5);
612 addRpn (sequence, channel, 111, 222, 1.5);
613 addRpn (sequence, channel, 333, 444, 2.5);
615 Array<MidiMessage>
m;
616 sequence.createControllerUpdatesForTime (channel, 1.0,
m);
618 checkRpn (
m.begin(), std::next (
m.begin(), 4), channel, number,
value, 0.5);
621 beginTest (
"createControllerUpdatesForTime should emit separate (N)RPN messages when appropriate");
623 const auto channel = 2;
624 const auto numberA = 1111;
625 const auto valueA = 9999;
627 const auto numberB = 8888;
628 const auto valueB = 2222;
630 const auto numberC = 7777;
631 const auto valueC = 3333;
633 const auto numberD = 6666;
634 const auto valueD = 4444;
636 const auto time = 0.5;
638 MidiMessageSequence sequence;
639 addRpn (sequence, channel, numberA, valueA, time);
640 addRpn (sequence, channel, numberB, valueB, time);
641 addNrpn (sequence, channel, numberC, valueC, time);
642 addNrpn (sequence, channel, numberD, valueD, time);
644 Array<MidiMessage>
m;
645 sequence.createControllerUpdatesForTime (channel, time * 2,
m);
647 checkRpn (std::next (
m.begin(), 0), std::next (
m.begin(), 4), channel, numberA, valueA, time);
648 checkRpn (std::next (
m.begin(), 4), std::next (
m.begin(), 8), channel, numberB, valueB, time);
649 checkNrpn (std::next (
m.begin(), 8), std::next (
m.begin(), 12), channel, numberC, valueC, time);
650 checkNrpn (std::next (
m.begin(), 12), std::next (
m.begin(), 16), channel, numberD, valueD, time);
653 beginTest (
"createControllerUpdatesForTime correctly emits (N)RPN messages on multiple channels");
655 struct Info {
int channel, number,
value; };
657 const Info infos[] { { 2, 1111, 9999 },
662 const auto time = 0.5;
664 MidiMessageSequence sequence;
666 for (
const auto&
info : infos)
667 addRpn (sequence,
info.channel,
info.number,
info.value, time);
669 for (
const auto&
info : infos)
671 Array<MidiMessage>
m;
672 sequence.createControllerUpdatesForTime (
info.channel, time * 2,
m);
673 checkRpn (std::next (
m.begin(), 0), std::next (
m.begin(), 4),
info.channel,
info.number,
info.value, time);
677 const auto messagesAreEqual = [] (
const MidiMessage&
a,
const MidiMessage&
b)
679 return std::equal (
a.getRawData(),
a.getRawData() +
a.getRawDataSize(),
680 b.getRawData(),
b.getRawData() +
b.getRawDataSize());
683 beginTest (
"createControllerUpdatesForTime sends bank select messages when the next program is in a new bank");
685 MidiMessageSequence sequence;
687 const auto time = 0.0;
688 const auto channel = 1;
700 for (
const auto&
e : finalEvents)
701 sequence.addEvent (
e);
703 Array<MidiMessage>
m;
704 sequence.createControllerUpdatesForTime (channel, 1.0,
m);
706 expect (std::equal (
m.begin(),
m.end(), finalEvents.begin(), finalEvents.end(), messagesAreEqual));
709 beginTest (
"createControllerUpdatesForTime preserves all Data Increment and Data Decrement messages");
711 MidiMessageSequence sequence;
713 const auto time = 0.0;
714 const auto channel = 1;
726 for (
const auto&
m : messages)
727 sequence.addEvent (
m, time);
729 Array<MidiMessage>
m;
730 sequence.createControllerUpdatesForTime (channel, 1.0,
m);
732 expect (std::equal (
m.begin(),
m.end(), messages.begin(), messages.end(), messagesAreEqual));
735 beginTest (
"createControllerUpdatesForTime does not emit redundant parameter number changes");
737 MidiMessageSequence sequence;
739 const auto time = 0.0;
740 const auto channel = 1;
748 for (
const auto&
m : messages)
749 sequence.addEvent (
m, time);
751 Array<MidiMessage>
m;
752 sequence.createControllerUpdatesForTime (channel, 1.0,
m);
758 expect (std::equal (
m.begin(),
m.end(), expected.
begin(), expected.
end(), messagesAreEqual));
761 beginTest (
"createControllerUpdatesForTime sets parameter number correctly at end of sequence");
763 MidiMessageSequence sequence;
765 const auto time = 0.0;
766 const auto channel = 1;
775 for (
const auto&
m : messages)
776 sequence.addEvent (
m, time);
778 const auto finalTime = 1.0;
780 Array<MidiMessage>
m;
781 sequence.createControllerUpdatesForTime (channel, finalTime,
m);
790 expect (std::equal (
m.begin(),
m.end(), expected.
begin(), expected.
end(), messagesAreEqual));
793 beginTest (
"createControllerUpdatesForTime does not emit duplicate parameter number change messages");
795 MidiMessageSequence sequence;
797 const auto time = 0.0;
798 const auto channel = 1;
812 for (
const auto&
m : messages)
813 sequence.addEvent (
m, time);
815 const auto finalTime = 1.0;
817 Array<MidiMessage>
m;
818 sequence.createControllerUpdatesForTime (channel, finalTime,
m);
830 expect (std::equal (
m.begin(),
m.end(), expected.
begin(), expected.
end(), messagesAreEqual));
833 beginTest (
"createControllerUpdatesForTime emits bank change messages immediately before program change");
835 MidiMessageSequence sequence;
837 const auto time = 0.0;
838 const auto channel = 1;
846 for (
const auto&
m : messages)
847 sequence.addEvent (
m, time);
849 const auto finalTime = 1.0;
851 Array<MidiMessage>
m;
852 sequence.createControllerUpdatesForTime (channel, finalTime,
m);
861 expect (std::equal (
m.begin(),
m.end(), expected.
begin(), expected.
end(), messagesAreEqual));
866static MidiMessageSequenceTest midiMessageSequenceTests;
Controller controller
Definition main.C:5
#define noexcept
Definition DistrhoDefines.h:72
uint8_t a
Definition Spc_Cpu.h:141
ElementType * begin() const noexcept
Definition Array.h:292
ElementType * end() const noexcept
Definition Array.h:300
static MidiMessage noteOn(int channel, int noteNumber, float velocity) noexcept
Definition MidiMessage.cpp:534
static MidiMessage noteOff(int channel, int noteNumber, float velocity) noexcept
Definition MidiMessage.cpp:548
static MidiMessage controllerEvent(int channel, int controllerType, int value) noexcept
Definition MidiMessage.cpp:516
static MidiMessage programChange(int channel, int programNumber) noexcept
Definition MidiMessage.cpp:465
Definition juce_Array.h:56
void add(const ElementType &newElement)
Definition juce_Array.h:418
Definition juce_MidiMessage.h:35
static MidiMessage pitchWheel(int channel, int position) noexcept
Definition juce_MidiMessage.cpp:554
double getTimeStamp() const noexcept
Definition juce_MidiMessage.h:164
static MidiMessage controllerEvent(int channel, int controllerType, int value) noexcept
Definition juce_MidiMessage.cpp:586
static MidiMessage noteOff(int channel, int noteNumber, float velocity) noexcept
Definition juce_MidiMessage.cpp:618
void addToTimeStamp(double delta) noexcept
Definition juce_MidiMessage.h:175
static MidiMessage programChange(int channel, int programNumber) noexcept
Definition juce_MidiMessage.cpp:535
Definition juce_MidiMessageSequence.h:65
MidiMessage message
Definition juce_MidiMessageSequence.h:69
MidiEventHolder(const MidiMessage &)
Definition juce_MidiMessageSequence.cpp:26
void extractMidiChannelMessages(int channelNumberToExtract, MidiMessageSequence &destSequence, bool alsoIncludeMetaEvents) const
Definition juce_MidiMessageSequence.cpp:275
double getEventTime(int index) const noexcept
Definition juce_MidiMessageSequence.cpp:144
void deleteSysExMessages()
Definition juce_MidiMessageSequence.cpp:299
void clear()
Definition juce_MidiMessageSequence.cpp:70
MidiMessageSequence()
Definition juce_MidiMessageSequence.cpp:30
void createControllerUpdatesForTime(int channelNumber, double time, Array< MidiMessage > &resultMessages)
Definition juce_MidiMessageSequence.cpp:420
double getTimeOfMatchingKeyUp(int index) const noexcept
Definition juce_MidiMessageSequence.cpp:90
MidiEventHolder * addEvent(const MidiMessage &newMessage, double timeAdjustment=0)
Definition juce_MidiMessageSequence.cpp:167
int getIndexOf(const MidiEventHolder *event) const noexcept
Definition juce_MidiMessageSequence.cpp:116
void updateMatchedPairs() noexcept
Definition juce_MidiMessageSequence.cpp:226
int getIndexOfMatchingKeyUp(int index) const noexcept
Definition juce_MidiMessageSequence.cpp:99
void addTimeToMessages(double deltaTime) noexcept
Definition juce_MidiMessageSequence.cpp:267
void swapWith(MidiMessageSequence &) noexcept
Definition juce_MidiMessageSequence.cpp:65
void deleteMidiChannelMessages(int channelNumberToRemove)
Definition juce_MidiMessageSequence.cpp:292
void sort() noexcept
Definition juce_MidiMessageSequence.cpp:220
double getStartTime() const noexcept
Definition juce_MidiMessageSequence.cpp:134
void deleteEvent(int index, bool deleteMatchingNoteUp)
Definition juce_MidiMessageSequence.cpp:177
double getEndTime() const noexcept
Definition juce_MidiMessageSequence.cpp:139
MidiEventHolder ** end() noexcept
Definition juce_MidiMessageSequence.cpp:87
int getNextIndexAtTime(double timeStamp) const noexcept
Definition juce_MidiMessageSequence.cpp:121
MidiEventHolder * getEventPointer(int index) const noexcept
Definition juce_MidiMessageSequence.cpp:80
OwnedArray< MidiEventHolder > list
Definition juce_MidiMessageSequence.h:308
MidiEventHolder ** begin() noexcept
Definition juce_MidiMessageSequence.cpp:85
int getNumEvents() const noexcept
Definition juce_MidiMessageSequence.cpp:75
void addSequence(const MidiMessageSequence &other, double timeAdjustmentDelta, double firstAllowableDestTime, double endOfAllowableDestTimes)
Definition juce_MidiMessageSequence.cpp:200
void extractSysExMessages(MidiMessageSequence &destSequence) const
Definition juce_MidiMessageSequence.cpp:285
Definition juce_MidiMessageSequence.cpp:325
Optional< char > values[128]
Definition juce_MidiMessageSequence.cpp:326
void set(int controller, int value)
Definition juce_MidiMessageSequence.cpp:336
void emit(int channel, Array< MidiMessage > &out) const
Definition juce_MidiMessageSequence.cpp:329
Definition juce_Optional.h:74
Definition juce_MidiMessageSequence.cpp:308
void set(int v)
Definition juce_MidiMessageSequence.cpp:318
void emit(int channel, Array< MidiMessage > &out) const
Definition juce_MidiMessageSequence.cpp:312
Optional< int > value
Definition juce_MidiMessageSequence.cpp:309
Definition juce_MidiMessageSequence.cpp:343
Optional< char > value
Definition juce_MidiMessageSequence.cpp:344
Optional< char > bankMSB
Definition juce_MidiMessageSequence.cpp:344
void setProgram(int v)
Definition juce_MidiMessageSequence.cpp:373
Optional< char > bankLSB
Definition juce_MidiMessageSequence.cpp:344
void emit(int channel, double time, Array< MidiMessage > &out) const
Definition juce_MidiMessageSequence.cpp:347
bool trySetBank(int controller, int v)
Definition juce_MidiMessageSequence.cpp:362
Definition juce_MidiMessageSequence.cpp:377
void sendIfNecessary(int channel, double time, Array< MidiMessage > &out)
Definition juce_MidiMessageSequence.cpp:388
Kind newestKind
Definition juce_MidiMessageSequence.cpp:381
Kind
Definition juce_MidiMessageSequence.cpp:378
@ nrpn
Definition juce_MidiMessageSequence.cpp:378
@ rpn
Definition juce_MidiMessageSequence.cpp:378
Optional< char > lastSentMsb
Definition juce_MidiMessageSequence.cpp:380
bool trySetProgramNumber(int controller, int value)
Definition juce_MidiMessageSequence.cpp:406
Optional< char > newestNrpnMsb
Definition juce_MidiMessageSequence.cpp:380
Optional< char > newestNrpnLsb
Definition juce_MidiMessageSequence.cpp:380
Optional< char > newestRpnLsb
Definition juce_MidiMessageSequence.cpp:380
Optional< char > lastSentLsb
Definition juce_MidiMessageSequence.cpp:380
Optional< char > newestRpnMsb
Definition juce_MidiMessageSequence.cpp:380
Kind lastSentKind
Definition juce_MidiMessageSequence.cpp:381
Definition juce_UnitTest.h:70
* e
Definition inflate.c:1404
unsigned * m
Definition inflate.c:1559
struct huft * t
Definition inflate.c:943
register unsigned j
Definition inflate.c:1576
unsigned v[N_MAX]
Definition inflate.c:1584
register unsigned i
Definition inflate.c:1575
unsigned s
Definition inflate.c:1555
static PuglViewHint int value
Definition pugl.h:1708
struct backing_store_struct * info
Definition jmemsys.h:183
float control
Definition lilv_test.c:1462
float out
Definition lilv_test.c:1461
const char * msg
Definition missing_descriptor.c:20
Definition juce_UnitTestCategories.h:27
Definition carla_juce.cpp:31
RangedDirectoryIterator end(const RangedDirectoryIterator &)
Definition juce_RangedDirectoryIterator.h:184
bool isPositiveAndBelow(Type1 valueToTest, Type2 upperLimit) noexcept
Definition juce_MathsFunctions.h:279
RangedDirectoryIterator begin(const RangedDirectoryIterator &it)
Definition juce_RangedDirectoryIterator.h:179
Definition juce_Uuid.h:141
const AbsTime * time
Definition PADnoteParameters.h:189
#define Info(...)
Definition unzpriv.h:2701
mm
Definition zipinfo.c:2291
#define const
Definition zconf.h:137