28 const uint8 noLSBValueReceived = 0xff;
29 const Range<int> allChannels { 1, 17 };
35 std::fill_n (lastPressureLowerBitReceivedOnChannel, 16, noLSBValueReceived);
36 std::fill_n (lastTimbreLowerBitReceivedOnChannel, 16, noLSBValueReceived);
37 std::fill_n (isMemberChannelSustained, 16,
false);
46 legacyMode.isEnabled =
false;
47 legacyMode.pitchbendRange = 2;
48 legacyMode.channelRange = allChannels;
66 legacyMode.isEnabled =
false;
67 zoneLayout = newLayout;
76 legacyMode.isEnabled =
true;
77 legacyMode.pitchbendRange = pitchbendRange;
78 legacyMode.channelRange = channelRange;
84 return legacyMode.isEnabled;
89 return legacyMode.channelRange;
94 jassert (allChannels.contains (channelRange));
98 legacyMode.channelRange = channelRange;
103 return legacyMode.pitchbendRange;
108 jassert (pitchbendRange >= 0 && pitchbendRange <= 96);
112 legacyMode.pitchbendRange = pitchbendRange;
118 pressureDimension.trackingMode = modeToUse;
123 pitchbendDimension.trackingMode = modeToUse;
128 timbreDimension.trackingMode = modeToUse;
134 listeners.add (listenerToAdd);
139 listeners.remove (listenerToRemove);
147 if (message.
isNoteOn (
true)) processMidiNoteOnMessage (message);
148 else if (message.
isNoteOff (
false)) processMidiNoteOffMessage (message);
150 || message.
isAllNotesOff()) processMidiResetAllControllersMessage (message);
151 else if (message.
isPitchWheel()) processMidiPitchWheelMessage (message);
152 else if (message.
isChannelPressure()) processMidiChannelPressureMessage (message);
153 else if (message.
isController()) processMidiControllerMessage (message);
157void MPEInstrument::processMidiNoteOnMessage (
const MidiMessage& message)
178void MPEInstrument::processMidiNoteOffMessage (
const MidiMessage& message)
181 message.getNoteNumber(),
186void MPEInstrument::processMidiPitchWheelMessage (
const MidiMessage& message)
193void MPEInstrument::processMidiChannelPressureMessage (
const MidiMessage& message)
200void MPEInstrument::processMidiControllerMessage (
const MidiMessage& message)
202 switch (message.getControllerNumber())
204 case 64:
sustainPedal (message.getChannel(), message.isSustainPedalOn());
break;
205 case 66:
sostenutoPedal (message.getChannel(), message.isSostenutoPedalOn());
break;
206 case 70: handlePressureMSB (message.getChannel(), message.getControllerValue());
break;
207 case 74: handleTimbreMSB (message.getChannel(), message.getControllerValue());
break;
208 case 102: handlePressureLSB (message.getChannel(), message.getControllerValue());
break;
209 case 106: handleTimbreLSB (message.getChannel(), message.getControllerValue());
break;
215void MPEInstrument::processMidiResetAllControllersMessage (
const MidiMessage& message)
220 if (legacyMode.isEnabled && legacyMode.channelRange.contains (message.getChannel()))
222 for (
auto i = notes.size(); --i >= 0;)
224 auto& note = notes.getReference (i);
226 if (note.midiChannel == message.getChannel())
230 listeners.call ([&] (Listener& l) { l.noteReleased (note); });
237 auto zone = (message.getChannel() == 1 ? zoneLayout.
getLowerZone()
240 for (
auto i = notes.size(); --i >= 0;)
242 auto& note = notes.getReference (i);
244 if (zone.isUsingChannelAsMemberChannel (note.midiChannel))
248 listeners.call ([&] (Listener& l) { l.noteReleased (note); });
256void MPEInstrument::handlePressureMSB (
int midiChannel,
int value)
noexcept
258 auto lsb = lastPressureLowerBitReceivedOnChannel[midiChannel - 1];
261 : MPEValue::from14BitInt (lsb + (value << 7)));
264void MPEInstrument::handlePressureLSB (
int midiChannel,
int value)
noexcept
266 lastPressureLowerBitReceivedOnChannel[midiChannel - 1] = uint8 (value);
269void MPEInstrument::handleTimbreMSB (
int midiChannel,
int value)
noexcept
271 auto lsb = lastTimbreLowerBitReceivedOnChannel[midiChannel - 1];
274 : MPEValue::from14BitInt (lsb + (value << 7)));
277void MPEInstrument::handleTimbreLSB (
int midiChannel,
int value)
noexcept
279 lastTimbreLowerBitReceivedOnChannel[midiChannel - 1] = uint8 (value);
293 getInitialValueForNewNote (midiChannel, pitchbendDimension),
294 getInitialValueForNewNote (midiChannel, pressureDimension),
295 getInitialValueForNewNote (midiChannel, timbreDimension),
299 updateNoteTotalPitchbend (newNote);
301 if (
auto* alreadyPlayingNote = getNotePtr (midiChannel, midiNoteNumber))
307 notes.remove (alreadyPlayingNote);
324 if (
auto* note = getNotePtr (midiChannel, midiNoteNumber))
327 note->noteOffVelocity = midiNoteOffVelocity;
351 updateDimension (midiChannel, pitchbendDimension, value);
357 updateDimension (midiChannel, pressureDimension, value);
363 updateDimension (midiChannel, timbreDimension, value);
366MPEValue MPEInstrument::getInitialValueForNewNote (
int midiChannel, MPEDimension& dimension)
const
368 if (getLastNotePlayedPtr (midiChannel) !=
nullptr)
371 return dimension.lastValueReceivedOnChannel[midiChannel - 1];
375void MPEInstrument::updateDimension (
int midiChannel, MPEDimension& dimension, MPEValue value)
377 dimension.lastValueReceivedOnChannel[midiChannel - 1] = value;
386 for (
auto i = notes.size(); --i >= 0;)
388 auto& note = notes.getReference (i);
390 if (note.midiChannel == midiChannel)
391 updateDimensionForNote (note, dimension, value);
396 if (
auto* note = getNotePtr (midiChannel, dimension.trackingMode))
397 updateDimensionForNote (*note, dimension, value);
402 updateDimensionMaster (midiChannel == 1, dimension, value);
407void MPEInstrument::updateDimensionMaster (
bool isLowerZone, MPEDimension& dimension, MPEValue value)
412 if (! zone.isActive())
415 for (
auto i = notes.size(); --i >= 0;)
417 auto& note = notes.getReference (i);
419 if (! zone.isUsingChannelAsMemberChannel (note.midiChannel))
422 if (&dimension == &pitchbendDimension)
426 updateNoteTotalPitchbend (note);
427 listeners.call ([&] (Listener& l) { l.notePitchbendChanged (note); });
429 else if (dimension.getValue (note) != value)
431 dimension.getValue (note) = value;
432 callListenersDimensionChanged (note, dimension);
438void MPEInstrument::updateDimensionForNote (MPENote& note, MPEDimension& dimension, MPEValue value)
440 if (dimension.getValue (note) != value)
442 dimension.getValue (note) = value;
444 if (&dimension == &pitchbendDimension)
445 updateNoteTotalPitchbend (note);
447 callListenersDimensionChanged (note, dimension);
452void MPEInstrument::callListenersDimensionChanged (
const MPENote& note,
const MPEDimension& dimension)
454 if (&dimension == &pressureDimension) { listeners.call ([&] (Listener& l) { l.notePressureChanged (note); });
return; }
455 if (&dimension == &timbreDimension) { listeners.call ([&] (Listener& l) { l.noteTimbreChanged (note); });
return; }
456 if (&dimension == &pitchbendDimension) { listeners.call ([&] (Listener& l) { l.notePitchbendChanged (note); });
return; }
460void MPEInstrument::updateNoteTotalPitchbend (MPENote& note)
462 if (legacyMode.isEnabled)
464 note.totalPitchbendInSemitones = note.pitchbend.asSignedFloat() * legacyMode.pitchbendRange;
470 if (! zone.isUsingChannelAsMemberChannel (note.midiChannel))
472 if (zoneLayout.
getUpperZone().isUsingChannelAsMemberChannel (note.midiChannel))
484 auto notePitchbendInSemitones = note.pitchbend.asSignedFloat() * zone.perNotePitchbendRange;
486 auto masterPitchbendInSemitones = pitchbendDimension.lastValueReceivedOnChannel[zone.getMasterChannel() - 1]
488 * zone.masterPitchbendRange;
490 note.totalPitchbendInSemitones = notePitchbendInSemitones + masterPitchbendInSemitones;
498 handleSustainOrSostenuto (midiChannel, isDown,
false);
504 handleSustainOrSostenuto (midiChannel, isDown,
true);
508void MPEInstrument::handleSustainOrSostenuto (
int midiChannel,
bool isDown,
bool isSostenuto)
513 if (legacyMode.isEnabled ? (! legacyMode.channelRange.contains (midiChannel)) : (!
isMasterChannel (midiChannel)))
516 auto zone = (midiChannel == 1 ? zoneLayout.
getLowerZone()
519 for (
auto i = notes.size(); --i >= 0;)
521 auto& note = notes.getReference (i);
523 if (legacyMode.isEnabled ? (note.midiChannel == midiChannel) : zone.isUsingChannelAsMemberChannel (note.midiChannel))
534 listeners.call ([&] (Listener& l) { l.noteReleased (note); });
539 listeners.call ([&] (Listener& l) { l.noteKeyStateChanged (note); });
546 if (legacyMode.isEnabled)
548 isMemberChannelSustained[midiChannel - 1] = isDown;
552 if (zone.isLowerZone())
553 for (
auto i = zone.getFirstMemberChannel(); i <= zone.getLastMemberChannel(); ++i)
554 isMemberChannelSustained[i - 1] = isDown;
556 for (
auto i = zone.getFirstMemberChannel(); i >= zone.getLastMemberChannel(); --i)
557 isMemberChannelSustained[i - 1] = isDown;
565 if (legacyMode.isEnabled)
566 return legacyMode.channelRange.contains (midiChannel);
568 return zoneLayout.getLowerZone().isUsingChannelAsMemberChannel (midiChannel)
569 || zoneLayout.getUpperZone().isUsingChannelAsMemberChannel (midiChannel);
574 if (legacyMode.isEnabled)
577 return (midiChannel == 1 || midiChannel == 16);
587 if (
auto* note = getNotePtr (midiChannel, midiNoteNumber))
601 if (
auto* note = getLastNotePlayedPtr (midiChannel))
609 for (
auto i = notes.size(); --i >= 0;)
611 auto& note = notes.getReference (i);
613 if (note != otherThanThisNote)
621const MPENote* MPEInstrument::getNotePtr (
int midiChannel,
int midiNoteNumber)
const noexcept
623 for (
int i = 0; i < notes.size(); ++i)
625 auto& note = notes.getReference (i);
627 if (note.midiChannel == midiChannel && note.initialNote == midiNoteNumber)
634MPENote* MPEInstrument::getNotePtr (
int midiChannel,
int midiNoteNumber)
noexcept
636 return const_cast<MPENote*
> (
static_cast<const MPEInstrument&
> (*this).getNotePtr (midiChannel, midiNoteNumber));
640const MPENote* MPEInstrument::getNotePtr (
int midiChannel, TrackingMode mode)
const noexcept
644 jassert (mode != allNotesOnChannel);
646 if (mode == lastNotePlayedOnChannel)
return getLastNotePlayedPtr (midiChannel);
647 if (mode == lowestNoteOnChannel)
return getLowestNotePtr (midiChannel);
648 if (mode == highestNoteOnChannel)
return getHighestNotePtr (midiChannel);
653MPENote* MPEInstrument::getNotePtr (
int midiChannel, TrackingMode mode)
noexcept
655 return const_cast<MPENote*
> (
static_cast<const MPEInstrument&
> (*this).getNotePtr (midiChannel, mode));
659const MPENote* MPEInstrument::getLastNotePlayedPtr (
int midiChannel)
const noexcept
661 for (
auto i = notes.size(); --i >= 0;)
663 auto& note = notes.getReference (i);
665 if (note.midiChannel == midiChannel
673MPENote* MPEInstrument::getLastNotePlayedPtr (
int midiChannel)
noexcept
675 return const_cast<MPENote*
> (
static_cast<const MPEInstrument&
> (*this).getLastNotePlayedPtr (midiChannel));
679const MPENote* MPEInstrument::getHighestNotePtr (
int midiChannel)
const noexcept
681 int initialNoteMax = -1;
682 MPENote* result =
nullptr;
684 for (
auto i = notes.size(); --i >= 0;)
686 auto& note = notes.getReference (i);
688 if (note.midiChannel == midiChannel
690 && note.initialNote > initialNoteMax)
693 initialNoteMax = note.initialNote;
700MPENote* MPEInstrument::getHighestNotePtr (
int midiChannel)
noexcept
702 return const_cast<MPENote*
> (
static_cast<const MPEInstrument&
> (*this).getHighestNotePtr (midiChannel));
705const MPENote* MPEInstrument::getLowestNotePtr (
int midiChannel)
const noexcept
707 int initialNoteMin = 128;
708 MPENote* result =
nullptr;
710 for (
auto i = notes.size(); --i >= 0;)
712 auto& note = notes.getReference (i);
714 if (note.midiChannel == midiChannel
716 && note.initialNote < initialNoteMin)
719 initialNoteMin = note.initialNote;
726MPENote* MPEInstrument::getLowestNotePtr (
int midiChannel)
noexcept
728 return const_cast<MPENote*
> (
static_cast<const MPEInstrument&
> (*this).getLowestNotePtr (midiChannel));
736 for (
auto i = notes.size(); --i >= 0;)
738 auto& note = notes.getReference (i);
751class MPEInstrumentTests :
public UnitTest
755 :
UnitTest (
"MPEInstrument class",
"MIDI/MPE")
762 testLayout.setLowerZone (5);
763 testLayout.setUpperZone (6);
766 void runTest()
override
768 beginTest (
"initial zone layout");
771 expect (! test.getZoneLayout().getLowerZone().isActive());
772 expect (! test.getZoneLayout().getUpperZone().isActive());
775 beginTest (
"get/setZoneLayout");
778 test.setZoneLayout (testLayout);
780 auto newLayout = test.getZoneLayout();
782 expect (test.getZoneLayout().getLowerZone().isActive());
783 expect (test.getZoneLayout().getUpperZone().isActive());
784 expectEquals (newLayout.getLowerZone().getMasterChannel(), 1);
785 expectEquals (newLayout.getLowerZone().numMemberChannels, 5);
786 expectEquals (newLayout.getUpperZone().getMasterChannel(), 16);
787 expectEquals (newLayout.getUpperZone().numMemberChannels, 6);
790 beginTest (
"noteOn / noteOff");
794 test.setZoneLayout (testLayout);
795 expectEquals (test.getNumPlayingNotes(), 0);
798 UnitTestInstrument test;
799 test.setZoneLayout (testLayout);
802 test.noteOn (1, 60, MPEValue::from7BitInt (100));
803 expectEquals (test.getNumPlayingNotes(), 0);
804 expectEquals (test.noteAddedCallCounter, 0);
807 test.noteOn (7, 60, MPEValue::from7BitInt (100));
808 expectEquals (test.getNumPlayingNotes(), 0);
809 expectEquals (test.noteAddedCallCounter, 0);
812 test.noteOn (3, 60, MPEValue::from7BitInt (100));
813 expectEquals (test.getNumPlayingNotes(), 1);
814 expectEquals (test.noteAddedCallCounter, 1);
815 expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown);
818 test.noteOff (3, 60, MPEValue::from7BitInt (33));
819 expectEquals (test.getNumPlayingNotes(), 0);
820 expectEquals (test.noteReleasedCallCounter, 1);
821 expectHasFinishedNote (test, 3, 60, 33);
824 UnitTestInstrument test;
825 test.setZoneLayout (testLayout);
826 test.noteOn (3, 60, MPEValue::from7BitInt (100));
829 test.noteOff (3, 61, MPEValue::from7BitInt (33));
830 expectEquals (test.getNumPlayingNotes(), 1);
831 expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown);
832 expectEquals (test.noteReleasedCallCounter, 0);
835 test.noteOff (2, 60, MPEValue::from7BitInt (33));
836 expectEquals (test.getNumPlayingNotes(), 1);
837 expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown);
838 expectEquals (test.noteReleasedCallCounter, 0);
842 UnitTestInstrument test;
843 test.setZoneLayout (testLayout);
844 test.noteOn (3, 0, MPEValue::from7BitInt (100));
845 test.noteOn (3, 1, MPEValue::from7BitInt (100));
846 test.noteOn (3, 2, MPEValue::from7BitInt (100));
847 expectEquals (test.getNumPlayingNotes(), 3);
848 expectNote (test.getNote (3, 0), 100, 0, 8192, 64, MPENote::keyDown);
849 expectNote (test.getNote (3, 1), 100, 0, 8192, 64, MPENote::keyDown);
850 expectNote (test.getNote (3, 2), 100, 0, 8192, 64, MPENote::keyDown);
854 UnitTestInstrument test;
855 test.setZoneLayout (testLayout);
856 test.noteOn (3, 0, MPEValue::from7BitInt (100));
857 test.noteOn (3, 0, MPEValue::from7BitInt (60));
858 expectEquals (test.getNumPlayingNotes(), 1);
859 expectNote (test.getNote (3, 0), 60, 0, 8192, 64, MPENote::keyDown);
863 beginTest (
"noteReleased after setZoneLayout");
865 UnitTestInstrument test;
866 test.setZoneLayout (testLayout);
868 test.noteOn (3, 60, MPEValue::from7BitInt (100));
869 test.noteOn (3, 61, MPEValue::from7BitInt (100));
870 test.noteOn (4, 61, MPEValue::from7BitInt (100));
871 expectEquals (test.getNumPlayingNotes(), 3);
872 expectEquals (test.noteReleasedCallCounter, 0);
874 test.setZoneLayout (testLayout);
875 expectEquals (test.getNumPlayingNotes(), 0);
876 expectEquals (test.noteReleasedCallCounter, 3);
879 beginTest (
"releaseAllNotes");
881 UnitTestInstrument test;
882 test.setZoneLayout (testLayout);
883 test.noteOn (3, 60, MPEValue::from7BitInt (100));
884 test.noteOn (4, 61, MPEValue::from7BitInt (100));
885 test.noteOn (15, 62, MPEValue::from7BitInt (100));
886 expectEquals (test.getNumPlayingNotes(), 3);
888 test.releaseAllNotes();
889 expectEquals (test.getNumPlayingNotes(), 0);
892 beginTest (
"sustainPedal");
894 UnitTestInstrument test;
895 test.setZoneLayout (testLayout);
896 test.noteOn (3, 60, MPEValue::from7BitInt (100));
897 test.noteOn (10, 60, MPEValue::from7BitInt (100));
900 test.sustainPedal (3,
true);
901 expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown);
903 expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown);
904 expectNote (test.getNote (10, 60), 100, 0, 8192, 64, MPENote::keyDown);
905 expectEquals (test.noteKeyStateChangedCallCounter, 0);
908 test.sustainPedal (7,
true);
909 expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown);
910 expectNote (test.getNote (10, 60), 100, 0, 8192, 64, MPENote::keyDown);
911 expectEquals (test.noteKeyStateChangedCallCounter, 0);
914 test.sustainPedal (1,
true);
915 expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDownAndSustained);
916 expectNote (test.getNote (10, 60), 100, 0, 8192, 64, MPENote::keyDown);
917 expectEquals (test.noteKeyStateChangedCallCounter, 1);
920 test.sustainPedal (1,
false);
921 expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown);
922 expectNote (test.getNote (10, 60), 100, 0, 8192, 64, MPENote::keyDown);
923 expectEquals (test.noteKeyStateChangedCallCounter, 2);
926 test.sustainPedal (1,
true);
927 expectEquals (test.noteKeyStateChangedCallCounter, 3);
928 test.noteOn (4, 51, MPEValue::from7BitInt (100));
929 expectNote (test.getNote (4, 51), 100, 0, 8192, 64, MPENote::keyDownAndSustained);
930 expectEquals (test.noteKeyStateChangedCallCounter, 3);
933 test.sustainPedal (11,
true);
934 test.noteOn (11, 52, MPEValue::from7BitInt (100));
935 expectNote (test.getNote (11, 52), 100, 0, 8192, 64, MPENote::keyDown);
936 test.noteOff (11, 52, MPEValue::from7BitInt (100));
937 expectEquals (test.noteReleasedCallCounter, 1);
940 test.noteOff (3, 60, MPEValue::from7BitInt (100));
941 test.noteOff (4, 51, MPEValue::from7BitInt (100));
942 test.noteOff (10, 60, MPEValue::from7BitInt (100));
943 expectEquals (test.getNumPlayingNotes(), 2);
944 expectEquals (test.noteReleasedCallCounter, 2);
945 expectEquals (test.noteKeyStateChangedCallCounter, 5);
946 expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::sustained);
947 expectNote (test.getNote (4, 51), 100, 0, 8192, 64, MPENote::sustained);
950 test.sustainPedal (1,
false);
951 expectEquals (test.getNumPlayingNotes(), 0);
952 expectEquals (test.noteReleasedCallCounter, 4);
955 beginTest (
"sostenutoPedal");
957 UnitTestInstrument test;
958 test.setZoneLayout (testLayout);
959 test.noteOn (3, 60, MPEValue::from7BitInt (100));
960 test.noteOn (10, 60, MPEValue::from7BitInt (100));
963 test.sostenutoPedal (3,
true);
964 expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown);
965 expectNote (test.getNote (10, 60), 100, 0, 8192, 64, MPENote::keyDown);
966 expectEquals (test.noteKeyStateChangedCallCounter, 0);
969 test.sostenutoPedal (9,
true);
970 expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown);
971 expectNote (test.getNote (10, 60), 100, 0, 8192, 64, MPENote::keyDown);
972 expectEquals (test.noteKeyStateChangedCallCounter, 0);
975 test.sostenutoPedal (1,
true);
976 expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDownAndSustained);
977 expectNote (test.getNote (10, 60), 100, 0, 8192, 64, MPENote::keyDown);
978 expectEquals (test.noteKeyStateChangedCallCounter, 1);
981 test.sostenutoPedal (1,
false);
982 expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown);
983 expectNote (test.getNote (10, 60), 100, 0, 8192, 64, MPENote::keyDown);
984 expectEquals (test.noteKeyStateChangedCallCounter, 2);
987 test.sostenutoPedal (1,
true);
988 expectEquals (test.noteKeyStateChangedCallCounter, 3);
989 test.noteOn (4, 51, MPEValue::from7BitInt (100));
990 expectEquals (test.getNumPlayingNotes(), 3);
991 expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDownAndSustained);
992 expectNote (test.getNote (4, 51), 100, 0, 8192, 64, MPENote::keyDown);
993 expectNote (test.getNote (10, 60), 100, 0, 8192, 64, MPENote::keyDown);
994 expectEquals (test.noteKeyStateChangedCallCounter, 3);
998 test.noteOff (3, 60, MPEValue::from7BitInt (100));
999 test.noteOff (4, 51, MPEValue::from7BitInt (100));
1000 test.noteOff (10, 60, MPEValue::from7BitInt (100));
1001 expectEquals (test.getNumPlayingNotes(), 1);
1002 expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::sustained);
1003 expectEquals (test.noteReleasedCallCounter, 2);
1004 expectEquals (test.noteKeyStateChangedCallCounter, 4);
1007 test.sustainPedal (1,
false);
1008 expectEquals (test.getNumPlayingNotes(), 0);
1009 expectEquals (test.noteReleasedCallCounter, 3);
1012 beginTest (
"getMostRecentNote");
1015 test.setZoneLayout (testLayout);
1017 test.noteOn (3, 60, MPEValue::from7BitInt (100));
1018 test.noteOn (3, 61, MPEValue::from7BitInt (100));
1021 auto note = test.getMostRecentNote (2);
1022 expect (! note.isValid());
1025 auto note = test.getMostRecentNote (3);
1026 expect (note.isValid());
1027 expectEquals (
int (note.midiChannel), 3);
1028 expectEquals (
int (note.initialNote), 61);
1031 test.sustainPedal (1,
true);
1032 test.noteOff (3, 61, MPEValue::from7BitInt (100));
1035 auto note = test.getMostRecentNote (3);
1036 expect (note.isValid());
1037 expectEquals (
int (note.midiChannel), 3);
1038 expectEquals (
int (note.initialNote), 60);
1041 test.sustainPedal (1,
false);
1042 test.noteOff (3, 60, MPEValue::from7BitInt (100));
1045 auto note = test.getMostRecentNote (3);
1046 expect (! note.isValid());
1050 beginTest (
"getMostRecentNoteOtherThan");
1052 MPENote testNote (3, 60,
1053 MPEValue::centreValue(), MPEValue::centreValue(),
1054 MPEValue::centreValue(), MPEValue::centreValue());
1060 test.setZoneLayout (testLayout);
1061 expect (! test.getMostRecentNoteOtherThan (testNote).isValid());
1063 test.noteOn (3, 60, MPEValue::from7BitInt (100));
1064 expect (! test.getMostRecentNoteOtherThan (testNote).isValid());
1066 test.noteOn (4, 61, MPEValue::from7BitInt (100));
1067 expect (test.getMostRecentNoteOtherThan (testNote).isValid());
1068 expect (test.getMostRecentNoteOtherThan (testNote).midiChannel == 4);
1069 expect (test.getMostRecentNoteOtherThan (testNote).initialNote == 61);
1075 test.setZoneLayout (testLayout);
1076 expect (! test.getMostRecentNoteOtherThan (testNote).isValid());
1078 test.noteOn (4, 61, MPEValue::from7BitInt (100));
1079 expect (test.getMostRecentNoteOtherThan (testNote).isValid());
1080 expect (test.getMostRecentNoteOtherThan (testNote).midiChannel == 4);
1081 expect (test.getMostRecentNoteOtherThan (testNote).initialNote == 61);
1083 test.noteOn (3, 60, MPEValue::from7BitInt (100));
1084 expect (test.getMostRecentNoteOtherThan (testNote).isValid());
1085 expect (test.getMostRecentNoteOtherThan (testNote).midiChannel == 4);
1086 expect (test.getMostRecentNoteOtherThan (testNote).initialNote == 61);
1090 beginTest (
"pressure");
1093 UnitTestInstrument test;
1094 test.setZoneLayout (testLayout);
1096 test.noteOn (3, 60, MPEValue::from7BitInt (100));
1097 test.noteOn (4, 60, MPEValue::from7BitInt (100));
1098 test.noteOn (10, 60, MPEValue::from7BitInt (100));
1101 test.pressure (3, MPEValue::from7BitInt (33));
1102 expectNote (test.getNote (3, 60), 100, 33, 8192, 64, MPENote::keyDown);
1103 expectNote (test.getNote (4, 60), 100, 0, 8192, 64, MPENote::keyDown);
1104 expectNote (test.getNote (10, 60), 100, 0, 8192, 64, MPENote::keyDown);
1105 expectEquals (test.notePressureChangedCallCounter, 1);
1108 test.pressure (1, MPEValue::from7BitInt (44));
1109 expectNote (test.getNote (3, 60), 100, 44, 8192, 64, MPENote::keyDown);
1110 expectNote (test.getNote (4, 60), 100, 44, 8192, 64, MPENote::keyDown);
1111 expectNote (test.getNote (10, 60), 100, 0, 8192, 64, MPENote::keyDown);
1112 expectEquals (test.notePressureChangedCallCounter, 3);
1115 test.pressure (8, MPEValue::from7BitInt (55));
1116 expectNote (test.getNote (3, 60), 100, 44, 8192, 64, MPENote::keyDown);
1117 expectNote (test.getNote (4, 60), 100, 44, 8192, 64, MPENote::keyDown);
1118 expectNote (test.getNote (10, 60), 100, 0, 8192, 64, MPENote::keyDown);
1119 expectEquals (test.notePressureChangedCallCounter, 3);
1122 UnitTestInstrument test;
1123 test.setZoneLayout (testLayout);
1126 test.noteOn (3, 60, MPEValue::from7BitInt (100));
1127 test.noteOn (3, 61, MPEValue::from7BitInt (100));
1128 test.pressure (3, MPEValue::from7BitInt (66));
1129 expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown);
1130 expectNote (test.getNote (3, 61), 100, 66, 8192, 64, MPENote::keyDown);
1131 expectEquals (test.notePressureChangedCallCounter, 1);
1134 UnitTestInstrument test;
1135 test.setZoneLayout (testLayout);
1139 test.noteOn (3, 60, MPEValue::from7BitInt (100));
1140 test.noteOn (3, 61, MPEValue::from7BitInt (100));
1141 test.noteOff (3, 61, MPEValue::from7BitInt (100));
1142 test.pressure (3, MPEValue::from7BitInt (77));
1143 expectEquals (test.getNumPlayingNotes(), 1);
1144 expectNote (test.getNote (3, 60), 100, 77, 8192, 64, MPENote::keyDown);
1145 expectEquals (test.notePressureChangedCallCounter, 1);
1148 UnitTestInstrument test;
1149 test.setZoneLayout (testLayout);
1152 test.noteOn (3, 60, MPEValue::from7BitInt (100));
1153 expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown);
1156 UnitTestInstrument test;
1157 test.setZoneLayout (testLayout);
1160 test.pressure (3, MPEValue::from7BitInt (77));
1161 test.noteOn (3, 60, MPEValue::from7BitInt (100));
1162 expectNote (test.getNote (3, 60), 100, 77, 8192, 64, MPENote::keyDown);
1165 UnitTestInstrument test;
1166 test.setZoneLayout (testLayout);
1170 test.noteOn (3, 61, MPEValue::from7BitInt (100));
1171 test.pressure (3, MPEValue::from7BitInt (77));
1172 test.noteOff (3, 61, MPEValue::from7BitInt (100));
1173 test.noteOn (3, 60, MPEValue::from7BitInt (100));
1174 expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown);
1177 UnitTestInstrument test;
1178 test.setZoneLayout (testLayout);
1182 test.noteOn (3, 61, MPEValue::from7BitInt (100));
1183 test.pressure (3, MPEValue::from7BitInt (77));
1184 test.noteOn (3, 60, MPEValue::from7BitInt (100));
1185 expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown);
1186 test.pressure (3, MPEValue::from7BitInt (78));
1187 expectNote (test.getNote (3, 60), 100, 78, 8192, 64, MPENote::keyDown);
1188 expectNote (test.getNote (3, 61), 100, 77, 8192, 64, MPENote::keyDown);
1192 beginTest (
"pitchbend");
1195 UnitTestInstrument test;
1196 test.setZoneLayout (testLayout);
1198 test.noteOn (3, 60, MPEValue::from7BitInt (100));
1199 test.noteOn (4, 60, MPEValue::from7BitInt (100));
1200 test.noteOn (10, 60, MPEValue::from7BitInt (100));
1203 test.pitchbend (3, MPEValue::from14BitInt (1111));
1204 expectNote (test.getNote (3, 60), 100, 0, 1111, 64, MPENote::keyDown);
1205 expectNote (test.getNote (4, 60), 100, 0, 8192, 64, MPENote::keyDown);
1206 expectNote (test.getNote (10, 60), 100, 0, 8192, 64, MPENote::keyDown);
1207 expectEquals (test.notePitchbendChangedCallCounter, 1);
1213 test.pitchbend (1, MPEValue::from14BitInt (2222));
1214 expectNote (test.getNote (3, 60), 100, 0, 1111, 64, MPENote::keyDown);
1215 expectNote (test.getNote (4, 60), 100, 0, 8192, 64, MPENote::keyDown);
1216 expectNote (test.getNote (10, 60), 100, 0, 8192, 64, MPENote::keyDown);
1217 expectEquals (test.notePitchbendChangedCallCounter, 3);
1220 test.pitchbend (8, MPEValue::from14BitInt (3333));
1221 expectNote (test.getNote (3, 60), 100, 0, 1111, 64, MPENote::keyDown);
1222 expectNote (test.getNote (4, 60), 100, 0, 8192, 64, MPENote::keyDown);
1223 expectNote (test.getNote (10, 60), 100, 0, 8192, 64, MPENote::keyDown);
1224 expectEquals (test.notePitchbendChangedCallCounter, 3);
1227 UnitTestInstrument test;
1228 test.setZoneLayout (testLayout);
1231 test.noteOn (3, 60, MPEValue::from7BitInt (100));
1232 test.noteOn (3, 61, MPEValue::from7BitInt (100));
1233 test.pitchbend (3, MPEValue::from14BitInt (4444));
1234 expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown);
1235 expectNote (test.getNote (3, 61), 100, 0, 4444, 64, MPENote::keyDown);
1236 expectEquals (test.notePitchbendChangedCallCounter, 1);
1239 UnitTestInstrument test;
1240 test.setZoneLayout (testLayout);
1244 test.noteOn (3, 60, MPEValue::from7BitInt (100));
1245 test.noteOn (3, 61, MPEValue::from7BitInt (100));
1246 test.noteOff (3, 61, MPEValue::from7BitInt (100));
1247 test.pitchbend (3, MPEValue::from14BitInt (5555));
1248 expectEquals (test.getNumPlayingNotes(), 1);
1249 expectNote (test.getNote (3, 60), 100, 0, 5555, 64, MPENote::keyDown);
1250 expectEquals (test.notePitchbendChangedCallCounter, 1);
1253 UnitTestInstrument test;
1254 test.setZoneLayout (testLayout);
1264 test.noteOn (3, 60, MPEValue::from7BitInt (100));
1265 test.sustainPedal (1,
true);
1266 test.noteOff (3, 60, MPEValue::from7BitInt (64));
1267 expectEquals (test.getNumPlayingNotes(), 1);
1268 expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::sustained);
1269 expectEquals (test.noteKeyStateChangedCallCounter, 2);
1271 test.noteOn (3, 61, MPEValue::from7BitInt (100));
1272 test.pitchbend (3, MPEValue::from14BitInt (6666));
1273 expectEquals (test.getNumPlayingNotes(), 2);
1274 expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::sustained);
1275 expectNote (test.getNote (3, 61), 100, 0, 6666, 64, MPENote::keyDownAndSustained);
1276 expectEquals (test.notePitchbendChangedCallCounter, 1);
1279 UnitTestInstrument test;
1280 test.setZoneLayout (testLayout);
1290 test.noteOn (3, 60, MPEValue::from7BitInt (100));
1291 test.pitchbend (3, MPEValue::from14BitInt (5555));
1292 expectNote (test.getNote (3, 60), 100, 0, 5555, 64, MPENote::keyDown);
1294 test.noteOff (3, 60, MPEValue::from7BitInt (100));
1295 test.noteOn (3, 60, MPEValue::from7BitInt (100));
1296 expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown);
1301 UnitTestInstrument test;
1303 MPEZoneLayout layout = testLayout;
1304 test.setZoneLayout (layout);
1305 test.noteOn (3, 60, MPEValue::from7BitInt (100));
1306 test.pitchbend (3, MPEValue::from14BitInt (4096));
1307 expectDoubleWithinRelativeError (test.getMostRecentNote (3).totalPitchbendInSemitones, -24.0, 0.01);
1309 layout.setLowerZone (5, 96);
1310 test.setZoneLayout (layout);
1311 test.noteOn (3, 60, MPEValue::from7BitInt (100));
1312 test.pitchbend (3, MPEValue::from14BitInt (0));
1313 expectDoubleWithinRelativeError (test.getMostRecentNote (3).totalPitchbendInSemitones, -96.0, 0.01);
1315 layout.setLowerZone (5, 1);
1316 test.setZoneLayout (layout);
1317 test.noteOn (3, 60, MPEValue::from7BitInt (100));
1318 test.pitchbend (3, MPEValue::from14BitInt (16383));
1319 expectDoubleWithinRelativeError (test.getMostRecentNote (3).totalPitchbendInSemitones, 1.0, 0.01);
1321 layout.setLowerZone (5, 0);
1322 test.setZoneLayout (layout);
1323 test.noteOn (3, 60, MPEValue::from7BitInt (100));
1324 test.pitchbend (3, MPEValue::from14BitInt (12345));
1325 expectDoubleWithinRelativeError (test.getMostRecentNote (3).totalPitchbendInSemitones, 0.0, 0.01);
1330 UnitTestInstrument test;
1332 MPEZoneLayout layout = testLayout;
1333 test.setZoneLayout (layout);
1334 test.noteOn (3, 60, MPEValue::from7BitInt (100));
1335 test.pitchbend (1, MPEValue::from14BitInt (4096));
1336 expectDoubleWithinRelativeError (test.getMostRecentNote (3).totalPitchbendInSemitones, -1.0, 0.01);
1338 layout.setLowerZone (5, 48, 96);
1339 test.setZoneLayout (layout);
1340 test.noteOn (3, 60, MPEValue::from7BitInt (100));
1341 test.pitchbend (1, MPEValue::from14BitInt (0));
1342 expectDoubleWithinRelativeError (test.getMostRecentNote (3).totalPitchbendInSemitones, -96.0, 0.01);
1344 layout.setLowerZone (5, 48, 1);
1345 test.setZoneLayout (layout);
1346 test.noteOn (3, 60, MPEValue::from7BitInt (100));
1347 test.pitchbend (1, MPEValue::from14BitInt (16383));
1348 expectDoubleWithinRelativeError (test.getMostRecentNote (3).totalPitchbendInSemitones, 1.0, 0.01);
1350 layout.setLowerZone (5, 48, 0);
1351 test.setZoneLayout (layout);
1352 test.noteOn (3, 60, MPEValue::from7BitInt (100));
1353 test.pitchbend (1, MPEValue::from14BitInt (12345));
1354 expectDoubleWithinRelativeError (test.getMostRecentNote (3).totalPitchbendInSemitones, 0.0, 0.01);
1360 UnitTestInstrument test;
1362 MPEZoneLayout layout = testLayout;
1363 layout.setLowerZone (5, 12, 1);
1364 test.setZoneLayout (layout);
1366 test.pitchbend (1, MPEValue::from14BitInt (4096));
1367 test.pitchbend (3, MPEValue::from14BitInt (0));
1370 test.noteOn (3, 60, MPEValue::from7BitInt (100));
1371 expectDoubleWithinRelativeError (test.getMostRecentNote (3).totalPitchbendInSemitones, -12.5, 0.01);
1375 beginTest (
"timbre");
1378 UnitTestInstrument test;
1379 test.setZoneLayout (testLayout);
1381 test.noteOn (3, 60, MPEValue::from7BitInt (100));
1382 test.noteOn (4, 60, MPEValue::from7BitInt (100));
1383 test.noteOn (10, 60, MPEValue::from7BitInt (100));
1386 test.timbre (3, MPEValue::from7BitInt (33));
1387 expectNote (test.getNote (3, 60), 100, 0, 8192, 33, MPENote::keyDown);
1388 expectNote (test.getNote (4, 60), 100, 0, 8192, 64, MPENote::keyDown);
1389 expectNote (test.getNote (10, 60), 100, 0, 8192, 64, MPENote::keyDown);
1390 expectEquals (test.noteTimbreChangedCallCounter, 1);
1393 test.timbre (1, MPEValue::from7BitInt (44));
1394 expectNote (test.getNote (3, 60), 100, 0, 8192, 44, MPENote::keyDown);
1395 expectNote (test.getNote (4, 60), 100, 0, 8192, 44, MPENote::keyDown);
1396 expectNote (test.getNote (10, 60), 100, 0, 8192, 64, MPENote::keyDown);
1397 expectEquals (test.noteTimbreChangedCallCounter, 3);
1400 test.timbre (9, MPEValue::from7BitInt (55));
1401 expectNote (test.getNote (3, 60), 100, 0, 8192, 44, MPENote::keyDown);
1402 expectNote (test.getNote (4, 60), 100, 0, 8192, 44, MPENote::keyDown);
1403 expectNote (test.getNote (10, 60), 100, 0, 8192, 64, MPENote::keyDown);
1404 expectEquals (test.noteTimbreChangedCallCounter, 3);
1407 UnitTestInstrument test;
1408 test.setZoneLayout (testLayout);
1411 test.noteOn (3, 60, MPEValue::from7BitInt (100));
1412 test.noteOn (3, 61, MPEValue::from7BitInt (100));
1413 test.timbre (3, MPEValue::from7BitInt (66));
1414 expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown);
1415 expectNote (test.getNote (3, 61), 100, 0, 8192, 66, MPENote::keyDown);
1416 expectEquals (test.noteTimbreChangedCallCounter, 1);
1419 UnitTestInstrument test;
1420 test.setZoneLayout (testLayout);
1424 test.noteOn (3, 60, MPEValue::from7BitInt (100));
1425 test.noteOn (3, 61, MPEValue::from7BitInt (100));
1426 test.noteOff (3, 61, MPEValue::from7BitInt (100));
1427 test.timbre (3, MPEValue::from7BitInt (77));
1428 expectEquals (test.getNumPlayingNotes(), 1);
1429 expectNote (test.getNote (3, 60), 100, 0, 8192, 77, MPENote::keyDown);
1430 expectEquals (test.noteTimbreChangedCallCounter, 1);
1433 UnitTestInstrument test;
1434 test.setZoneLayout (testLayout);
1437 test.noteOn (3, 60, MPEValue::from7BitInt (100));
1438 test.timbre (3, MPEValue::from7BitInt (42));
1439 expectNote (test.getNote (3, 60), 100, 0, 8192, 42, MPENote::keyDown);
1441 test.noteOff (3, 60, MPEValue::from7BitInt (100));
1442 test.noteOn (3, 60, MPEValue::from7BitInt (100));
1443 expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown);
1447 beginTest (
"setPressureTrackingMode");
1451 UnitTestInstrument test;
1452 test.setZoneLayout (testLayout);
1454 test.setPressureTrackingMode (MPEInstrument::lastNotePlayedOnChannel);
1455 test.noteOn (3, 60, MPEValue::from7BitInt (100));
1456 test.noteOn (3, 62, MPEValue::from7BitInt (100));
1457 test.noteOn (3, 61, MPEValue::from7BitInt (100));
1458 test.pressure (3, MPEValue::from7BitInt (99));
1459 expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown);
1460 expectNote (test.getNote (3, 62), 100, 0, 8192, 64, MPENote::keyDown);
1461 expectNote (test.getNote (3, 61), 100, 99, 8192, 64, MPENote::keyDown);
1462 expectEquals (test.notePressureChangedCallCounter, 1);
1466 UnitTestInstrument test;
1467 test.setZoneLayout (testLayout);
1469 test.setPressureTrackingMode (MPEInstrument::lowestNoteOnChannel);
1470 test.noteOn (3, 60, MPEValue::from7BitInt (100));
1471 test.noteOn (3, 62, MPEValue::from7BitInt (100));
1472 test.noteOn (3, 61, MPEValue::from7BitInt (100));
1473 test.pressure (3, MPEValue::from7BitInt (99));
1474 expectNote (test.getNote (3, 60), 100, 99, 8192, 64, MPENote::keyDown);
1475 expectNote (test.getNote (3, 62), 100, 0, 8192, 64, MPENote::keyDown);
1476 expectNote (test.getNote (3, 61), 100, 0, 8192, 64, MPENote::keyDown);
1477 expectEquals (test.notePressureChangedCallCounter, 1);
1481 UnitTestInstrument test;
1482 test.setZoneLayout (testLayout);
1484 test.setPressureTrackingMode (MPEInstrument::highestNoteOnChannel);
1485 test.noteOn (3, 60, MPEValue::from7BitInt (100));
1486 test.noteOn (3, 62, MPEValue::from7BitInt (100));
1487 test.noteOn (3, 61, MPEValue::from7BitInt (100));
1488 test.pressure (3, MPEValue::from7BitInt (99));
1489 expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown);
1490 expectNote (test.getNote (3, 62), 100, 99, 8192, 64, MPENote::keyDown);
1491 expectNote (test.getNote (3, 61), 100, 0, 8192, 64, MPENote::keyDown);
1492 expectEquals (test.notePressureChangedCallCounter, 1);
1496 UnitTestInstrument test;
1497 test.setZoneLayout (testLayout);
1499 test.setPressureTrackingMode (MPEInstrument::allNotesOnChannel);
1500 test.noteOn (3, 60, MPEValue::from7BitInt (100));
1501 test.noteOn (3, 62, MPEValue::from7BitInt (100));
1502 test.noteOn (3, 61, MPEValue::from7BitInt (100));
1503 test.pressure (3, MPEValue::from7BitInt (99));
1504 expectNote (test.getNote (3, 60), 100, 99, 8192, 64, MPENote::keyDown);
1505 expectNote (test.getNote (3, 62), 100, 99, 8192, 64, MPENote::keyDown);
1506 expectNote (test.getNote (3, 61), 100, 99, 8192, 64, MPENote::keyDown);
1507 expectEquals (test.notePressureChangedCallCounter, 3);
1511 beginTest (
"setPitchbendTrackingMode");
1515 UnitTestInstrument test;
1516 test.setZoneLayout (testLayout);
1518 test.setPitchbendTrackingMode (MPEInstrument::lastNotePlayedOnChannel);
1519 test.noteOn (3, 60, MPEValue::from7BitInt (100));
1520 test.noteOn (3, 62, MPEValue::from7BitInt (100));
1521 test.noteOn (3, 61, MPEValue::from7BitInt (100));
1522 test.pitchbend (3, MPEValue::from14BitInt (9999));
1523 expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown);
1524 expectNote (test.getNote (3, 62), 100, 0, 8192, 64, MPENote::keyDown);
1525 expectNote (test.getNote (3, 61), 100, 0, 9999, 64, MPENote::keyDown);
1526 expectEquals (test.notePitchbendChangedCallCounter, 1);
1530 UnitTestInstrument test;
1531 test.setZoneLayout (testLayout);
1533 test.setPitchbendTrackingMode (MPEInstrument::lowestNoteOnChannel);
1534 test.noteOn (3, 60, MPEValue::from7BitInt (100));
1535 test.noteOn (3, 62, MPEValue::from7BitInt (100));
1536 test.noteOn (3, 61, MPEValue::from7BitInt (100));
1537 test.pitchbend (3, MPEValue::from14BitInt (9999));
1538 expectNote (test.getNote (3, 60), 100, 0, 9999, 64, MPENote::keyDown);
1539 expectNote (test.getNote (3, 62), 100, 0, 8192, 64, MPENote::keyDown);
1540 expectNote (test.getNote (3, 61), 100, 0, 8192, 64, MPENote::keyDown);
1541 expectEquals (test.notePitchbendChangedCallCounter, 1);
1545 UnitTestInstrument test;
1546 test.setZoneLayout (testLayout);
1548 test.setPitchbendTrackingMode (MPEInstrument::highestNoteOnChannel);
1549 test.noteOn (3, 60, MPEValue::from7BitInt (100));
1550 test.noteOn (3, 62, MPEValue::from7BitInt (100));
1551 test.noteOn (3, 61, MPEValue::from7BitInt (100));
1552 test.pitchbend (3, MPEValue::from14BitInt (9999));
1553 expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown);
1554 expectNote (test.getNote (3, 62), 100, 0, 9999, 64, MPENote::keyDown);
1555 expectNote (test.getNote (3, 61), 100, 0, 8192, 64, MPENote::keyDown);
1556 expectEquals (test.notePitchbendChangedCallCounter, 1);
1560 UnitTestInstrument test;
1561 test.setZoneLayout (testLayout);
1563 test.setPitchbendTrackingMode (MPEInstrument::allNotesOnChannel);
1564 test.noteOn (3, 60, MPEValue::from7BitInt (100));
1565 test.noteOn (3, 62, MPEValue::from7BitInt (100));
1566 test.noteOn (3, 61, MPEValue::from7BitInt (100));
1567 test.pitchbend (3, MPEValue::from14BitInt (9999));
1568 expectNote (test.getNote (3, 60), 100, 0, 9999, 64, MPENote::keyDown);
1569 expectNote (test.getNote (3, 62), 100, 0, 9999, 64, MPENote::keyDown);
1570 expectNote (test.getNote (3, 61), 100, 0, 9999, 64, MPENote::keyDown);
1571 expectEquals (test.notePitchbendChangedCallCounter, 3);
1575 beginTest (
"setTimbreTrackingMode");
1579 UnitTestInstrument test;
1580 test.setZoneLayout (testLayout);
1582 test.setTimbreTrackingMode (MPEInstrument::lastNotePlayedOnChannel);
1583 test.noteOn (3, 60, MPEValue::from7BitInt (100));
1584 test.noteOn (3, 62, MPEValue::from7BitInt (100));
1585 test.noteOn (3, 61, MPEValue::from7BitInt (100));
1586 test.timbre (3, MPEValue::from7BitInt (99));
1587 expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown);
1588 expectNote (test.getNote (3, 62), 100, 0, 8192, 64, MPENote::keyDown);
1589 expectNote (test.getNote (3, 61), 100, 0, 8192, 99, MPENote::keyDown);
1590 expectEquals (test.noteTimbreChangedCallCounter, 1);
1594 UnitTestInstrument test;
1595 test.setZoneLayout (testLayout);
1597 test.setTimbreTrackingMode (MPEInstrument::lowestNoteOnChannel);
1598 test.noteOn (3, 60, MPEValue::from7BitInt (100));
1599 test.noteOn (3, 62, MPEValue::from7BitInt (100));
1600 test.noteOn (3, 61, MPEValue::from7BitInt (100));
1601 test.timbre (3, MPEValue::from7BitInt (99));
1602 expectNote (test.getNote (3, 60), 100, 0, 8192, 99, MPENote::keyDown);
1603 expectNote (test.getNote (3, 62), 100, 0, 8192, 64, MPENote::keyDown);
1604 expectNote (test.getNote (3, 61), 100, 0, 8192, 64, MPENote::keyDown);
1605 expectEquals (test.noteTimbreChangedCallCounter, 1);
1609 UnitTestInstrument test;
1610 test.setZoneLayout (testLayout);
1612 test.setTimbreTrackingMode (MPEInstrument::highestNoteOnChannel);
1613 test.noteOn (3, 60, MPEValue::from7BitInt (100));
1614 test.noteOn (3, 62, MPEValue::from7BitInt (100));
1615 test.noteOn (3, 61, MPEValue::from7BitInt (100));
1616 test.timbre (3, MPEValue::from7BitInt (99));
1617 expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown);
1618 expectNote (test.getNote (3, 62), 100, 0, 8192, 99, MPENote::keyDown);
1619 expectNote (test.getNote (3, 61), 100, 0, 8192, 64, MPENote::keyDown);
1620 expectEquals (test.noteTimbreChangedCallCounter, 1);
1624 UnitTestInstrument test;
1625 test.setZoneLayout (testLayout);
1627 test.setTimbreTrackingMode (MPEInstrument::allNotesOnChannel);
1628 test.noteOn (3, 60, MPEValue::from7BitInt (100));
1629 test.noteOn (3, 62, MPEValue::from7BitInt (100));
1630 test.noteOn (3, 61, MPEValue::from7BitInt (100));
1631 test.timbre (3, MPEValue::from7BitInt (99));
1632 expectNote (test.getNote (3, 60), 100, 0, 8192, 99, MPENote::keyDown);
1633 expectNote (test.getNote (3, 62), 100, 0, 8192, 99, MPENote::keyDown);
1634 expectNote (test.getNote (3, 61), 100, 0, 8192, 99, MPENote::keyDown);
1635 expectEquals (test.noteTimbreChangedCallCounter, 3);
1639 beginTest (
"processNextMidiEvent");
1641 UnitTestInstrument test;
1645 test.processNextMidiEvent (MidiMessage::noteOn (3, 42, uint8 (92)));
1646 expectEquals (test.noteOnCallCounter, 1);
1647 expectEquals (test.lastMidiChannelReceived, 3);
1648 expectEquals (test.lastMidiNoteNumberReceived, 42);
1649 expectEquals (test.lastMPEValueReceived.as7BitInt(), 92);
1653 test.processNextMidiEvent (MidiMessage::noteOff (4, 12, uint8 (33)));
1654 expectEquals (test.noteOffCallCounter, 1);
1655 expectEquals (test.lastMidiChannelReceived, 4);
1656 expectEquals (test.lastMidiNoteNumberReceived, 12);
1657 expectEquals (test.lastMPEValueReceived.as7BitInt(), 33);
1662 test.processNextMidiEvent (MidiMessage::noteOn (5, 11, uint8 (0)));
1663 expectEquals (test.noteOffCallCounter, 2);
1664 expectEquals (test.lastMidiChannelReceived, 5);
1665 expectEquals (test.lastMidiNoteNumberReceived, 11);
1666 expectEquals (test.lastMPEValueReceived.as7BitInt(), 64);
1670 test.processNextMidiEvent (MidiMessage::pitchWheel (1, 3333));
1671 expectEquals (test.pitchbendCallCounter, 1);
1672 expectEquals (test.lastMidiChannelReceived, 1);
1673 expectEquals (test.lastMPEValueReceived.as14BitInt(), 3333);
1678 test.processNextMidiEvent (MidiMessage::channelPressureChange (10, 35));
1679 expectEquals (test.pressureCallCounter, 1);
1680 expectEquals (test.lastMidiChannelReceived, 10);
1681 expectEquals (test.lastMPEValueReceived.as7BitInt(), 35);
1687 test.processNextMidiEvent (MidiMessage::controllerEvent (3, 70, 120));
1688 expectEquals (test.pressureCallCounter, 2);
1689 expectEquals (test.lastMidiChannelReceived, 3);
1690 expectEquals (test.lastMPEValueReceived.as7BitInt(), 120);
1693 test.processNextMidiEvent (MidiMessage::controllerEvent (4, 102, 121));
1694 expectEquals (test.pressureCallCounter, 2);
1695 test.processNextMidiEvent (MidiMessage::controllerEvent (5, 102, 122));
1696 expectEquals (test.pressureCallCounter, 2);
1697 test.processNextMidiEvent (MidiMessage::controllerEvent (4, 70, 123));
1698 expectEquals (test.pressureCallCounter, 3);
1699 expectEquals (test.lastMidiChannelReceived, 4);
1700 expectEquals (test.lastMPEValueReceived.as14BitInt(), 121 + (123 << 7));
1701 test.processNextMidiEvent (MidiMessage::controllerEvent (5, 70, 124));
1702 expectEquals (test.pressureCallCounter, 4);
1703 expectEquals (test.lastMidiChannelReceived, 5);
1704 expectEquals (test.lastMPEValueReceived.as14BitInt(), 122 + (124 << 7));
1705 test.processNextMidiEvent (MidiMessage::controllerEvent (5, 70, 64));
1706 expectEquals (test.pressureCallCounter, 5);
1707 expectEquals (test.lastMidiChannelReceived, 5);
1708 expectEquals (test.lastMPEValueReceived.as7BitInt(), 64);
1711 test.processNextMidiEvent (MidiMessage::controllerEvent (3, 74, 120));
1712 expectEquals (test.timbreCallCounter, 1);
1713 expectEquals (test.lastMidiChannelReceived, 3);
1714 expectEquals (test.lastMPEValueReceived.as7BitInt(), 120);
1715 test.processNextMidiEvent (MidiMessage::controllerEvent (4, 106, 121));
1716 expectEquals (test.timbreCallCounter, 1);
1717 test.processNextMidiEvent (MidiMessage::controllerEvent (5, 106, 122));
1718 expectEquals (test.timbreCallCounter, 1);
1719 test.processNextMidiEvent (MidiMessage::controllerEvent (4, 74, 123));
1720 expectEquals (test.timbreCallCounter, 2);
1721 expectEquals (test.lastMidiChannelReceived, 4);
1722 expectEquals (test.lastMPEValueReceived.as14BitInt(), 121 + (123 << 7));
1723 test.processNextMidiEvent (MidiMessage::controllerEvent (5, 74, 124));
1724 expectEquals (test.timbreCallCounter, 3);
1725 expectEquals (test.lastMidiChannelReceived, 5);
1726 expectEquals (test.lastMPEValueReceived.as14BitInt(), 122 + (124 << 7));
1727 test.processNextMidiEvent (MidiMessage::controllerEvent (5, 74, 64));
1728 expectEquals (test.timbreCallCounter, 4);
1729 expectEquals (test.lastMidiChannelReceived, 5);
1730 expectEquals (test.lastMPEValueReceived.as7BitInt(), 64);
1733 test.processNextMidiEvent (MidiMessage::controllerEvent (1, 64, 127));
1734 expectEquals (test.sustainPedalCallCounter, 1);
1735 expectEquals (test.lastMidiChannelReceived, 1);
1736 expect (test.lastSustainPedalValueReceived);
1737 test.processNextMidiEvent (MidiMessage::controllerEvent (16, 64, 0));
1738 expectEquals (test.sustainPedalCallCounter, 2);
1739 expectEquals (test.lastMidiChannelReceived, 16);
1740 expect (! test.lastSustainPedalValueReceived);
1743 test.processNextMidiEvent (MidiMessage::controllerEvent (1, 66, 127));
1744 expectEquals (test.sostenutoPedalCallCounter, 1);
1745 expectEquals (test.lastMidiChannelReceived, 1);
1746 expect (test.lastSostenutoPedalValueReceived);
1747 test.processNextMidiEvent (MidiMessage::controllerEvent (16, 66, 0));
1748 expectEquals (test.sostenutoPedalCallCounter, 2);
1749 expectEquals (test.lastMidiChannelReceived, 16);
1750 expect (! test.lastSostenutoPedalValueReceived);
1760 buffer.addEvents (MPEMessages::setLowerZone (5), 0, -1, 0);
1761 buffer.addEvents (MPEMessages::setUpperZone (6), 0, -1, 0);
1763 MidiBuffer::Iterator iter (buffer);
1764 MidiMessage message;
1767 while (iter.getNextEvent (message, samplePosition))
1768 test.processNextMidiEvent (message);
1770 expect (test.getZoneLayout().getLowerZone().isActive());
1771 expect (test.getZoneLayout().getUpperZone().isActive());
1772 expectEquals (test.getZoneLayout().getLowerZone().getMasterChannel(), 1);
1773 expectEquals (test.getZoneLayout().getLowerZone().numMemberChannels, 5);
1774 expectEquals (test.getZoneLayout().getUpperZone().getMasterChannel(), 16);
1775 expectEquals (test.getZoneLayout().getUpperZone().numMemberChannels, 6);
1778 beginTest (
"MIDI all notes off");
1780 UnitTestInstrument test;
1781 test.setZoneLayout (testLayout);
1782 test.noteOn (3, 60, MPEValue::from7BitInt (100));
1783 test.noteOn (4, 61, MPEValue::from7BitInt (100));
1784 test.noteOn (15, 62, MPEValue::from7BitInt (100));
1785 test.noteOn (15, 63, MPEValue::from7BitInt (100));
1786 expectEquals (test.getNumPlayingNotes(), 4);
1789 test.processNextMidiEvent (MidiMessage::allControllersOff (3));
1790 expectEquals (test.getNumPlayingNotes(), 4);
1793 test.processNextMidiEvent (MidiMessage::allControllersOff (9));
1794 expectEquals (test.getNumPlayingNotes(), 4);
1797 test.processNextMidiEvent (MidiMessage::allControllersOff (1));
1798 expectEquals (test.getNumPlayingNotes(), 2);
1799 test.processNextMidiEvent (MidiMessage::allControllersOff (16));
1800 expectEquals (test.getNumPlayingNotes(), 0);
1803 beginTest (
"MIDI all notes off (legacy mode)");
1805 UnitTestInstrument test;
1806 test.enableLegacyMode();
1807 test.noteOn (3, 60, MPEValue::from7BitInt (100));
1808 test.noteOn (4, 61, MPEValue::from7BitInt (100));
1809 test.noteOn (15, 62, MPEValue::from7BitInt (100));
1810 test.noteOn (15, 63, MPEValue::from7BitInt (100));
1811 expectEquals (test.getNumPlayingNotes(), 4);
1813 test.processNextMidiEvent (MidiMessage::allControllersOff (3));
1814 expectEquals (test.getNumPlayingNotes(), 3);
1816 test.processNextMidiEvent (MidiMessage::allControllersOff (15));
1817 expectEquals (test.getNumPlayingNotes(), 1);
1819 test.processNextMidiEvent (MidiMessage::allControllersOff (4));
1820 expectEquals (test.getNumPlayingNotes(), 0);
1823 beginTest (
"default initial values for pitchbend and timbre");
1826 test.setZoneLayout (testLayout);
1828 test.pitchbend (3, MPEValue::from14BitInt (3333));
1829 test.pitchbend (2, MPEValue::from14BitInt (4444));
1830 test.pitchbend (2, MPEValue::from14BitInt (5555));
1832 test.timbre (3, MPEValue::from7BitInt (66));
1833 test.timbre (2, MPEValue::from7BitInt (77));
1834 test.timbre (2, MPEValue::from7BitInt (88));
1836 test.noteOn (3, 60, MPEValue::from7BitInt (100));
1838 expectNote (test.getMostRecentNote (3), 100, 0, 3333, 66, MPENote::keyDown);
1841 beginTest (
"Legacy mode");
1846 expect (! test.isLegacyModeEnabled());
1848 test.setZoneLayout (testLayout);
1849 expect (! test.isLegacyModeEnabled());
1851 test.enableLegacyMode();
1852 expect (test.isLegacyModeEnabled());
1854 test.setZoneLayout (testLayout);
1855 expect (! test.isLegacyModeEnabled());
1860 test.enableLegacyMode (0, Range<int> (1, 11));
1861 expectEquals (test.getLegacyModePitchbendRange(), 0);
1862 expect (test.getLegacyModeChannelRange() == Range<int> (1, 11));
1867 test.enableLegacyMode();
1869 expectEquals (test.getLegacyModePitchbendRange(), 2);
1870 expect (test.getLegacyModeChannelRange() == Range<int> (1, 17));
1872 test.setLegacyModePitchbendRange (96);
1873 expectEquals (test.getLegacyModePitchbendRange(), 96);
1875 test.setLegacyModeChannelRange (Range<int> (10, 12));
1876 expect (test.getLegacyModeChannelRange() == Range<int> (10, 12));
1881 UnitTestInstrument test;
1882 test.enableLegacyMode();
1884 test.noteOn (1, 60, MPEValue::from7BitInt (100));
1885 test.noteOn (2, 60, MPEValue::from7BitInt (100));
1886 test.noteOn (15, 60, MPEValue::from7BitInt (100));
1887 test.noteOn (16, 60, MPEValue::from7BitInt (100));
1888 expectEquals (test.getNumPlayingNotes(), 4);
1892 test.pitchbend (1, MPEValue::from14BitInt (9999));
1893 test.pressure (2, MPEValue::from7BitInt (88));
1894 test.timbre (15, MPEValue::from7BitInt (77));
1896 expectNote (test.getNote (1, 60), 100, 0, 9999, 64, MPENote::keyDown);
1897 expectNote (test.getNote (2, 60), 100, 88, 8192, 64, MPENote::keyDown);
1898 expectNote (test.getNote (15, 60), 100, 0, 8192, 77, MPENote::keyDown);
1899 expectNote (test.getNote (16, 60), 100, 0, 8192, 64, MPENote::keyDown);
1903 test.noteOff (15, 60, MPEValue::from7BitInt (0));
1904 test.noteOff (1, 60, MPEValue::from7BitInt (0));
1905 test.noteOff (2, 60, MPEValue::from7BitInt (0));
1906 test.noteOff (16, 60, MPEValue::from7BitInt (0));
1907 expectEquals (test.getNumPlayingNotes(), 0);
1912 UnitTestInstrument test;
1913 test.enableLegacyMode (2, Range<int> (3, 8));
1915 test.noteOn (1, 60, MPEValue::from7BitInt (100));
1916 test.noteOn (2, 60, MPEValue::from7BitInt (100));
1917 test.noteOn (3, 60, MPEValue::from7BitInt (100));
1918 test.noteOn (4, 60, MPEValue::from7BitInt (100));
1919 test.noteOn (6, 60, MPEValue::from7BitInt (100));
1920 test.noteOn (7, 60, MPEValue::from7BitInt (100));
1921 test.noteOn (8, 60, MPEValue::from7BitInt (100));
1922 test.noteOn (16, 60, MPEValue::from7BitInt (100));
1924 expectEquals (test.getNumPlayingNotes(), 4);
1925 expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown);
1926 expectNote (test.getNote (4, 60), 100, 0, 8192, 64, MPENote::keyDown);
1927 expectNote (test.getNote (6, 60), 100, 0, 8192, 64, MPENote::keyDown);
1928 expectNote (test.getNote (7, 60), 100, 0, 8192, 64, MPENote::keyDown);
1933 UnitTestInstrument test;
1934 test.enableLegacyMode();
1936 test.setPitchbendTrackingMode (MPEInstrument::lastNotePlayedOnChannel);
1937 test.noteOn (1, 60, MPEValue::from7BitInt (100));
1938 test.noteOn (1, 62, MPEValue::from7BitInt (100));
1939 test.noteOn (1, 61, MPEValue::from7BitInt (100));
1940 test.pitchbend (1, MPEValue::from14BitInt (9999));
1941 expectNote (test.getNote (1, 60), 100, 0, 8192, 64, MPENote::keyDown);
1942 expectNote (test.getNote (1, 61), 100, 0, 9999, 64, MPENote::keyDown);
1943 expectNote (test.getNote (1, 62), 100, 0, 8192, 64, MPENote::keyDown);
1946 UnitTestInstrument test;
1947 test.enableLegacyMode();
1949 test.setPitchbendTrackingMode (MPEInstrument::lowestNoteOnChannel);
1950 test.noteOn (1, 60, MPEValue::from7BitInt (100));
1951 test.noteOn (1, 62, MPEValue::from7BitInt (100));
1952 test.noteOn (1, 61, MPEValue::from7BitInt (100));
1953 test.pitchbend (1, MPEValue::from14BitInt (9999));
1954 expectNote (test.getNote (1, 60), 100, 0, 9999, 64, MPENote::keyDown);
1955 expectNote (test.getNote (1, 61), 100, 0, 8192, 64, MPENote::keyDown);
1956 expectNote (test.getNote (1, 62), 100, 0, 8192, 64, MPENote::keyDown);
1959 UnitTestInstrument test;
1960 test.enableLegacyMode();
1962 test.setPitchbendTrackingMode (MPEInstrument::highestNoteOnChannel);
1963 test.noteOn (1, 60, MPEValue::from7BitInt (100));
1964 test.noteOn (1, 62, MPEValue::from7BitInt (100));
1965 test.noteOn (1, 61, MPEValue::from7BitInt (100));
1966 test.pitchbend (1, MPEValue::from14BitInt (9999));
1967 expectNote (test.getNote (1, 60), 100, 0, 8192, 64, MPENote::keyDown);
1968 expectNote (test.getNote (1, 61), 100, 0, 8192, 64, MPENote::keyDown);
1969 expectNote (test.getNote (1, 62), 100, 0, 9999, 64, MPENote::keyDown);
1972 UnitTestInstrument test;
1973 test.enableLegacyMode();
1975 test.setPitchbendTrackingMode (MPEInstrument::allNotesOnChannel);
1976 test.noteOn (1, 60, MPEValue::from7BitInt (100));
1977 test.noteOn (1, 62, MPEValue::from7BitInt (100));
1978 test.noteOn (1, 61, MPEValue::from7BitInt (100));
1979 test.pitchbend (1, MPEValue::from14BitInt (9999));
1980 expectNote (test.getNote (1, 60), 100, 0, 9999, 64, MPENote::keyDown);
1981 expectNote (test.getNote (1, 61), 100, 0, 9999, 64, MPENote::keyDown);
1982 expectNote (test.getNote (1, 62), 100, 0, 9999, 64, MPENote::keyDown);
1987 UnitTestInstrument test;
1988 test.enableLegacyMode (11);
1990 test.pitchbend (1, MPEValue::from14BitInt (4096));
1991 test.noteOn (1, 60, MPEValue::from7BitInt (100));
1992 expectDoubleWithinRelativeError (test.getMostRecentNote (1).totalPitchbendInSemitones, -5.5, 0.01);
1996 UnitTestInstrument test;
1997 test.enableLegacyMode();
1999 test.sustainPedal (1,
true);
2000 test.noteOn (2, 61, MPEValue::from7BitInt (100));
2001 test.noteOff (2, 61, MPEValue::from7BitInt (100));
2002 test.noteOn (1, 60, MPEValue::from7BitInt (100));
2003 test.noteOff (1, 60, MPEValue::from7BitInt (100));
2005 expectEquals (test.getNumPlayingNotes(), 1);
2006 expectNote (test.getNote (1, 60), 100, 0, 8192, 64, MPENote::sustained);
2008 test.sustainPedal (1,
false);
2009 expectEquals (test.getNumPlayingNotes(), 0);
2011 test.noteOn (2, 61, MPEValue::from7BitInt (100));
2012 test.sustainPedal (1,
true);
2013 test.noteOff (2, 61, MPEValue::from7BitInt (100));
2014 expectEquals (test.getNumPlayingNotes(), 0);
2019 UnitTestInstrument test;
2020 test.enableLegacyMode();
2022 test.noteOn (1, 60, MPEValue::from7BitInt (100));
2023 test.sostenutoPedal (1,
true);
2024 test.noteOff (1, 60, MPEValue::from7BitInt (100));
2025 test.noteOn (2, 61, MPEValue::from7BitInt (100));
2026 test.noteOff (2, 61, MPEValue::from7BitInt (100));
2028 expectEquals (test.getNumPlayingNotes(), 1);
2029 expectNote (test.getNote (1, 60), 100, 0, 8192, 64, MPENote::sustained);
2031 test.sostenutoPedal (1,
false);
2032 expectEquals (test.getNumPlayingNotes(), 0);
2034 test.noteOn (2, 61, MPEValue::from7BitInt (100));
2035 test.sostenutoPedal (1,
true);
2036 test.noteOff (2, 61, MPEValue::from7BitInt (100));
2037 expectEquals (test.getNumPlayingNotes(), 0);
2041 UnitTestInstrument test;
2042 test.setZoneLayout (testLayout);
2043 test.noteOn (3, 60, MPEValue::from7BitInt (100));
2044 expectEquals (test.getNumPlayingNotes(), 1);
2046 test.enableLegacyMode();
2047 expectEquals (test.getNumPlayingNotes(), 0);
2048 test.noteOn (3, 60, MPEValue::from7BitInt (100));
2049 expectEquals (test.getNumPlayingNotes(), 1);
2051 test.setZoneLayout (testLayout);
2052 expectEquals (test.getNumPlayingNotes(), 0);
2062 class UnitTestInstrument :
public MPEInstrument,
2063 private MPEInstrument::Listener
2065 using Base = MPEInstrument;
2068 UnitTestInstrument()
2069 : noteOnCallCounter (0), noteOffCallCounter (0), pitchbendCallCounter (0),
2070 pressureCallCounter (0), timbreCallCounter (0), sustainPedalCallCounter (0),
2071 sostenutoPedalCallCounter (0), noteAddedCallCounter (0), notePressureChangedCallCounter (0),
2072 notePitchbendChangedCallCounter (0), noteTimbreChangedCallCounter (0),
2073 noteKeyStateChangedCallCounter (0), noteReleasedCallCounter (0),
2074 lastMidiChannelReceived (-1), lastMidiNoteNumberReceived (-1),
2075 lastSustainPedalValueReceived (false), lastSostenutoPedalValueReceived (false)
2080 void noteOn (
int midiChannel,
int midiNoteNumber, MPEValue midiNoteOnVelocity)
override
2082 Base::noteOn (midiChannel, midiNoteNumber, midiNoteOnVelocity);
2084 noteOnCallCounter++;
2085 lastMidiChannelReceived = midiChannel;
2086 lastMidiNoteNumberReceived = midiNoteNumber;
2087 lastMPEValueReceived = midiNoteOnVelocity;
2090 void noteOff (
int midiChannel,
int midiNoteNumber, MPEValue midiNoteOffVelocity)
override
2092 Base::noteOff (midiChannel, midiNoteNumber, midiNoteOffVelocity);
2094 noteOffCallCounter++;
2095 lastMidiChannelReceived = midiChannel;
2096 lastMidiNoteNumberReceived = midiNoteNumber;
2097 lastMPEValueReceived = midiNoteOffVelocity;
2100 void pitchbend (
int midiChannel, MPEValue value)
override
2102 Base::pitchbend (midiChannel, value);
2104 pitchbendCallCounter++;
2105 lastMidiChannelReceived = midiChannel;
2106 lastMPEValueReceived = value;
2109 void pressure (
int midiChannel, MPEValue value)
override
2111 Base::pressure (midiChannel, value);
2113 pressureCallCounter++;
2114 lastMidiChannelReceived = midiChannel;
2115 lastMPEValueReceived = value;
2118 void timbre (
int midiChannel, MPEValue value)
override
2120 Base::timbre (midiChannel, value);
2122 timbreCallCounter++;
2123 lastMidiChannelReceived = midiChannel;
2124 lastMPEValueReceived = value;
2127 void sustainPedal (
int midiChannel,
bool value)
override
2129 Base::sustainPedal (midiChannel, value);
2131 sustainPedalCallCounter++;
2132 lastMidiChannelReceived = midiChannel;
2133 lastSustainPedalValueReceived = value;
2136 void sostenutoPedal (
int midiChannel,
bool value)
override
2138 Base::sostenutoPedal (midiChannel, value);
2140 sostenutoPedalCallCounter++;
2141 lastMidiChannelReceived = midiChannel;
2142 lastSostenutoPedalValueReceived = value;
2145 int noteOnCallCounter, noteOffCallCounter, pitchbendCallCounter,
2146 pressureCallCounter, timbreCallCounter, sustainPedalCallCounter,
2147 sostenutoPedalCallCounter, noteAddedCallCounter,
2148 notePressureChangedCallCounter, notePitchbendChangedCallCounter,
2149 noteTimbreChangedCallCounter, noteKeyStateChangedCallCounter,
2150 noteReleasedCallCounter, lastMidiChannelReceived, lastMidiNoteNumberReceived;
2152 bool lastSustainPedalValueReceived, lastSostenutoPedalValueReceived;
2153 MPEValue lastMPEValueReceived;
2154 std::unique_ptr<MPENote> lastNoteFinished;
2158 void noteAdded (MPENote)
override { noteAddedCallCounter++; }
2160 void notePressureChanged (MPENote)
override { notePressureChangedCallCounter++; }
2161 void notePitchbendChanged (MPENote)
override { notePitchbendChangedCallCounter++; }
2162 void noteTimbreChanged (MPENote)
override { noteTimbreChangedCallCounter++; }
2163 void noteKeyStateChanged (MPENote)
override { noteKeyStateChangedCallCounter++; }
2165 void noteReleased (MPENote finishedNote)
override
2167 noteReleasedCallCounter++;
2168 lastNoteFinished.reset (
new MPENote (finishedNote));
2173 void expectNote (MPENote noteToTest,
2174 int noteOnVelocity7Bit,
2178 MPENote::KeyState keyState)
2180 expect (noteToTest.isValid());
2181 expectEquals (noteToTest.noteOnVelocity.as7BitInt(), noteOnVelocity7Bit);
2182 expectEquals (noteToTest.pressure.as7BitInt(), pressure7Bit);
2183 expectEquals (noteToTest.pitchbend.as14BitInt(), pitchbend14Bit);
2184 expectEquals (noteToTest.timbre.as7BitInt(),timbre7Bit);
2185 expect (noteToTest.keyState == keyState);
2188 void expectHasFinishedNote (
const UnitTestInstrument& test,
2189 int channel,
int noteNumber,
int noteOffVelocity7Bit)
2191 expect (test.lastNoteFinished !=
nullptr);
2192 expectEquals (
int (test.lastNoteFinished->midiChannel), channel);
2193 expectEquals (
int (test.lastNoteFinished->initialNote), noteNumber);
2194 expectEquals (test.lastNoteFinished->noteOffVelocity.as7BitInt(), noteOffVelocity7Bit);
2195 expect (test.lastNoteFinished->keyState == MPENote::off);
2198 void expectDoubleWithinRelativeError (
double actual,
double expected,
double maxRelativeError)
2200 const double maxAbsoluteError = jmax (1.0, std::abs (expected)) * maxRelativeError;
2201 expect (std::abs (expected - actual) < maxAbsoluteError);
2205 MPEZoneLayout testLayout;
2208static MPEInstrumentTests MPEInstrumentUnitTests;
Automatically locks and unlocks a mutex object.
Derive from this class to be informed about any changes in the expressive MIDI notes played by this i...
virtual void noteKeyStateChanged(MPENote changedNote)=0
Implement this callback to be informed whether a currently playing MPE note's key state (whether the ...
virtual void noteReleased(MPENote finishedNote)=0
Implement this callback to be informed whenever an MPE note is released (either by a note-off message...
virtual void noteAdded(MPENote newNote)=0
Implement this callback to be informed whenever a new expressive MIDI note is triggered.
void setPitchbendTrackingMode(TrackingMode modeToUse)
Set the MPE tracking mode for the pitchbend dimension.
void setLegacyModeChannelRange(Range< int > channelRange)
Re-sets the range of MIDI channels (1-16) to be used for notes when in legacy mode.
MPENote getMostRecentNoteOtherThan(MPENote otherThanThisNote) const noexcept
Returns the most recent note that is not the note passed in.
MPEZoneLayout getZoneLayout() const noexcept
Returns the current zone layout of the instrument.
virtual void sostenutoPedal(int midiChannel, bool isDown)
Request a sostenuto pedal press or release.
virtual void pitchbend(int midiChannel, MPEValue pitchbend)
Request a pitchbend on the given channel with the given value (in units of MIDI pitchwheel position).
virtual ~MPEInstrument()
Destructor.
void enableLegacyMode(int pitchbendRange=2, Range< int > channelRange=Range< int >(1, 17))
Puts the instrument into legacy mode.
MPENote getNote(int index) const noexcept
Returns the note at the given index.
TrackingMode
The MPE note tracking mode.
@ allNotesOnChannel
All notes on the channel (key down and/or sustained).
MPEInstrument() noexcept
Constructor.
void setZoneLayout(MPEZoneLayout newLayout)
Re-sets the zone layout of the instrument to the one passed in.
virtual void processNextMidiEvent(const MidiMessage &message)
Process a MIDI message and trigger the appropriate method calls (noteOn, noteOff etc....
void setLegacyModePitchbendRange(int pitchbendRange)
Re-sets the pitchbend range in semitones (0-96) to be used for notes when in legacy mode.
bool isLegacyModeEnabled() const noexcept
Returns true if the instrument is in legacy mode, false otherwise.
void setPressureTrackingMode(TrackingMode modeToUse)
Set the MPE tracking mode for the pressure dimension.
void addListener(Listener *listenerToAdd)
Adds a listener.
void removeListener(Listener *listenerToRemove)
Removes a listener.
virtual void sustainPedal(int midiChannel, bool isDown)
Request a sustain pedal press or release.
void setTimbreTrackingMode(TrackingMode modeToUse)
Set the MPE tracking mode for the timbre dimension.
int getNumPlayingNotes() const noexcept
Returns the number of MPE notes currently played by the instrument.
void releaseAllNotes()
Discard all currently playing notes.
virtual void timbre(int midiChannel, MPEValue value)
Request a third dimension (timbre) change on the given channel with the given value.
MPENote getMostRecentNote(int midiChannel) const noexcept
Returns the most recent note that is playing on the given midiChannel (this will be the note which ha...
Range< int > getLegacyModeChannelRange() const noexcept
Returns the range of MIDI channels (1-16) to be used for notes when in legacy mode.
virtual void noteOn(int midiChannel, int midiNoteNumber, MPEValue midiNoteOnVelocity)
Request a note-on on the given channel, with the given initial note number and velocity.
int getLegacyModePitchbendRange() const noexcept
Returns the pitchbend range in semitones (0-96) to be used for notes when in legacy mode.
virtual void noteOff(int midiChannel, int midiNoteNumber, MPEValue midiNoteOffVelocity)
Request a note-off.
virtual void pressure(int midiChannel, MPEValue value)
Request a pressure change on the given channel with the given value.
bool isMasterChannel(int midiChannel) const noexcept
Returns true if the given MIDI channel (1-16) is a master channel (channel 1 or 16).
bool isMemberChannel(int midiChannel) noexcept
Returns true if the given MIDI channel (1-16) is a note channel in any of the MPEInstrument's MPE zon...
This class represents a single value for any of the MPE dimensions of control.
static MPEValue centreValue() noexcept
Constructs an MPEValue corresponding to the centre value.
static MPEValue from14BitInt(int value) noexcept
Constructs an MPEValue from an integer between 0 and 16383 (using 14-bit precision).
static MPEValue minValue() noexcept
Constructs an MPEValue corresponding to the minimum value.
static MPEValue from7BitInt(int value) noexcept
Constructs an MPEValue from an integer between 0 and 127 (using 7-bit precision).
This class represents the current MPE zone layout of a device capable of handling MPE.
void clearAllZones()
Clears the lower and upper zones of this layout, making them both inactive and disabling MPE mode.
const Zone getUpperZone() const noexcept
Returns a struct representing the upper MPE zone.
const Zone getLowerZone() const noexcept
Returns a struct representing the lower MPE zone.
void processNextMidiEvent(const MidiMessage &message)
Pass incoming MIDI messages to an object of this class if you want the zone layout to properly react ...
Encapsulates a MIDI message.
bool isNoteOn(bool returnTrueForVelocity0=false) const noexcept
Returns true if this message is a 'key-down' event.
int getChannel() const noexcept
Returns the midi channel associated with the message.
bool isController() const noexcept
Returns true if this is a midi controller message.
bool isNoteOff(bool returnTrueForNoteOnVelocity0=true) const noexcept
Returns true if this message is a 'key-up' event.
bool isPitchWheel() const noexcept
Returns true if the message is a pitch-wheel move.
int getNoteNumber() const noexcept
Returns the midi note number for note-on and note-off messages.
bool isResetAllControllers() const noexcept
Checks whether this message is a reset all controllers message.
bool isAllNotesOff() const noexcept
Checks whether this message is an all-notes-off message.
uint8 getVelocity() const noexcept
Returns the velocity of a note-on or note-off message.
bool isChannelPressure() const noexcept
Returns true if the message is a channel-pressure change event.
A general-purpose range object, that simply represents any linear range with a start and end point.
This is a base class for classes that perform a unit test.
This struct represents a playing MPE note.
@ keyDown
The note key is currently down (pressed).
@ off
The key is up (off).
@ keyDownAndSustained
The note key is down and sustained (by a sustain or sostenuto pedal).
@ sustained
The note is sustained (by a sustain or sostenuto pedal).
MPEValue timbre
Current value of the note's third expressive dimension, typically encoding some kind of timbre parame...
MPEValue pitchbend
Current per-note pitchbend of the note (in units of MIDI pitchwheel position).
MPEValue pressure
Current pressure with which the note is held down.