91 return std::find (ch.notes.begin(), ch.notes.end(), noteNumber) != ch.notes.end();
99 const auto removeNote = [] (
MidiChannel& ch,
int noteNum)
110 if (midiChannel >= 0 && midiChannel <= 16)
112 removeNote (
midiChannels[(
size_t) midiChannel], noteNumber);
118 if (removeNote (ch, noteNumber))
127 if (ch.notes.size() > 0)
128 ch.lastNotePlayed = ch.notes.getLast();
137 int closestNoteDistance = 127;
143 auto noteDistance = std::abs (note - noteNumber);
145 if (noteDistance > 0 && noteDistance < closestNoteDistance)
147 closestNoteDistance = noteDistance;
148 channelWithClosestNote = ch;
153 return channelWithClosestNote;
158 :
zone (zoneToRemap),
170 auto channel =
message.getChannel();
172 if (!
zone.isUsingChannelAsMemberChannel (channel))
175 if (channel ==
zone.getMasterChannel() && (
message.isResetAllControllers() ||
message.isAllNotesOff()))
181 auto sourceAndChannelID = (((
uint32) mpeSourceID << 5) | (
uint32) (channel));
228 if (
uint32 (
s >> 5) == mpeSourceID)
245 m.setChannel (channel);
275 for (
int i = 0;
i < 17; ++
i)
287struct MPEUtilsUnitTests :
public UnitTest
293 void runTest()
override
295 beginTest (
"MPEChannelAssigner");
297 MPEZoneLayout layout;
301 layout.setLowerZone (15);
304 MPEChannelAssigner channelAssigner (layout.getLowerZone());
308 for (
int ch = 2; ch <= 16; ++ch)
310 expectEquals (channelAssigner.findMidiChannelForNewNote (noteNum), ch);
311 expectEquals (channelAssigner.findMidiChannelForExistingNote (noteNum), ch);
317 channelAssigner.noteOff (60);
318 expectEquals (channelAssigner.findMidiChannelForNewNote (60), 2);
319 expectEquals (channelAssigner.findMidiChannelForExistingNote (60), 2);
321 channelAssigner.noteOff (61);
322 expectEquals (channelAssigner.findMidiChannelForNewNote (61), 3);
323 expectEquals (channelAssigner.findMidiChannelForExistingNote (61), 3);
326 channelAssigner.noteOff (65);
327 channelAssigner.noteOff (66);
328 expectEquals (channelAssigner.findMidiChannelForNewNote (66), 8);
329 expectEquals (channelAssigner.findMidiChannelForNewNote (65), 7);
330 expectEquals (channelAssigner.findMidiChannelForExistingNote (66), 8);
331 expectEquals (channelAssigner.findMidiChannelForExistingNote (65), 7);
334 expectEquals (channelAssigner.findMidiChannelForNewNote (80), 16);
335 expectEquals (channelAssigner.findMidiChannelForNewNote (55), 2);
336 expectEquals (channelAssigner.findMidiChannelForExistingNote (80), 16);
337 expectEquals (channelAssigner.findMidiChannelForExistingNote (55), 2);
340 channelAssigner.allNotesOff();
343 expectEquals (channelAssigner.findMidiChannelForNewNote (66), 8);
344 expectEquals (channelAssigner.findMidiChannelForNewNote (65), 7);
345 expectEquals (channelAssigner.findMidiChannelForNewNote (80), 16);
346 expectEquals (channelAssigner.findMidiChannelForNewNote (55), 2);
347 expectEquals (channelAssigner.findMidiChannelForExistingNote (66), 8);
348 expectEquals (channelAssigner.findMidiChannelForExistingNote (65), 7);
349 expectEquals (channelAssigner.findMidiChannelForExistingNote (80), 16);
350 expectEquals (channelAssigner.findMidiChannelForExistingNote (55), 2);
353 expectEquals (channelAssigner.findMidiChannelForNewNote (101), 3);
354 expectEquals (channelAssigner.findMidiChannelForNewNote (20), 4);
355 expectEquals (channelAssigner.findMidiChannelForExistingNote (101), 3);
356 expectEquals (channelAssigner.findMidiChannelForExistingNote (20), 4);
361 layout.setUpperZone (15);
364 MPEChannelAssigner channelAssigner (layout.getUpperZone());
368 for (
int ch = 15; ch >= 1; --ch)
370 expectEquals (channelAssigner.findMidiChannelForNewNote (noteNum), ch);
371 expectEquals (channelAssigner.findMidiChannelForExistingNote (noteNum), ch);
377 channelAssigner.noteOff (60);
378 expectEquals (channelAssigner.findMidiChannelForNewNote (60), 15);
379 expectEquals (channelAssigner.findMidiChannelForExistingNote (60), 15);
381 channelAssigner.noteOff (61);
382 expectEquals (channelAssigner.findMidiChannelForNewNote (61), 14);
383 expectEquals (channelAssigner.findMidiChannelForExistingNote (61), 14);
386 channelAssigner.noteOff (65);
387 channelAssigner.noteOff (66);
388 expectEquals (channelAssigner.findMidiChannelForNewNote (66), 9);
389 expectEquals (channelAssigner.findMidiChannelForNewNote (65), 10);
390 expectEquals (channelAssigner.findMidiChannelForExistingNote (66), 9);
391 expectEquals (channelAssigner.findMidiChannelForExistingNote (65), 10);
394 expectEquals (channelAssigner.findMidiChannelForNewNote (80), 1);
395 expectEquals (channelAssigner.findMidiChannelForNewNote (55), 15);
396 expectEquals (channelAssigner.findMidiChannelForExistingNote (80), 1);
397 expectEquals (channelAssigner.findMidiChannelForExistingNote (55), 15);
400 channelAssigner.allNotesOff();
403 expectEquals (channelAssigner.findMidiChannelForNewNote (66), 9);
404 expectEquals (channelAssigner.findMidiChannelForNewNote (65), 10);
405 expectEquals (channelAssigner.findMidiChannelForNewNote (80), 1);
406 expectEquals (channelAssigner.findMidiChannelForNewNote (55), 15);
407 expectEquals (channelAssigner.findMidiChannelForExistingNote (66), 9);
408 expectEquals (channelAssigner.findMidiChannelForExistingNote (65), 10);
409 expectEquals (channelAssigner.findMidiChannelForExistingNote (80), 1);
410 expectEquals (channelAssigner.findMidiChannelForExistingNote (55), 15);
413 expectEquals (channelAssigner.findMidiChannelForNewNote (101), 14);
414 expectEquals (channelAssigner.findMidiChannelForNewNote (20), 13);
415 expectEquals (channelAssigner.findMidiChannelForExistingNote (101), 14);
416 expectEquals (channelAssigner.findMidiChannelForExistingNote (20), 13);
421 MPEChannelAssigner channelAssigner;
425 for (
int ch = 1; ch <= 16; ++ch)
427 expectEquals (channelAssigner.findMidiChannelForNewNote (noteNum), ch);
428 expectEquals (channelAssigner.findMidiChannelForExistingNote (noteNum), ch);
434 channelAssigner.noteOff (60);
435 expectEquals (channelAssigner.findMidiChannelForNewNote (60), 1);
436 expectEquals (channelAssigner.findMidiChannelForExistingNote (60), 1);
438 channelAssigner.noteOff (61);
439 expectEquals (channelAssigner.findMidiChannelForNewNote (61), 2);
440 expectEquals (channelAssigner.findMidiChannelForExistingNote (61), 2);
443 channelAssigner.noteOff (65);
444 channelAssigner.noteOff (66);
445 expectEquals (channelAssigner.findMidiChannelForNewNote (66), 7);
446 expectEquals (channelAssigner.findMidiChannelForNewNote (65), 6);
447 expectEquals (channelAssigner.findMidiChannelForExistingNote (66), 7);
448 expectEquals (channelAssigner.findMidiChannelForExistingNote (65), 6);
451 expectEquals (channelAssigner.findMidiChannelForNewNote (80), 16);
452 expectEquals (channelAssigner.findMidiChannelForNewNote (55), 1);
453 expectEquals (channelAssigner.findMidiChannelForExistingNote (80), 16);
454 expectEquals (channelAssigner.findMidiChannelForExistingNote (55), 1);
457 channelAssigner.allNotesOff();
460 expectEquals (channelAssigner.findMidiChannelForNewNote (66), 7);
461 expectEquals (channelAssigner.findMidiChannelForNewNote (65), 6);
462 expectEquals (channelAssigner.findMidiChannelForNewNote (80), 16);
463 expectEquals (channelAssigner.findMidiChannelForNewNote (55), 1);
464 expectEquals (channelAssigner.findMidiChannelForExistingNote (66), 7);
465 expectEquals (channelAssigner.findMidiChannelForExistingNote (65), 6);
466 expectEquals (channelAssigner.findMidiChannelForExistingNote (80), 16);
467 expectEquals (channelAssigner.findMidiChannelForExistingNote (55), 1);
470 expectEquals (channelAssigner.findMidiChannelForNewNote (101), 2);
471 expectEquals (channelAssigner.findMidiChannelForNewNote (20), 3);
472 expectEquals (channelAssigner.findMidiChannelForExistingNote (101), 2);
473 expectEquals (channelAssigner.findMidiChannelForExistingNote (20), 3);
477 beginTest (
"MPEChannelRemapper");
480 const int sourceID1 = 0;
481 const int sourceID2 = 1;
482 const int sourceID3 = 2;
484 MPEZoneLayout layout;
487 layout.setLowerZone (15);
490 MPEChannelRemapper channelRemapper (layout.getLowerZone());
493 for (
int ch = 2; ch <= 16; ++ch)
497 channelRemapper.remapMidiChannelIfNeeded (noteOn, sourceID1);
498 expectEquals (noteOn.getChannel(), ch);
504 channelRemapper.remapMidiChannelIfNeeded (noteOn, sourceID2);
505 expectEquals (noteOn.getChannel(), 2);
508 channelRemapper.remapMidiChannelIfNeeded (noteOn, sourceID3);
509 expectEquals (noteOn.getChannel(), 3);
513 channelRemapper.remapMidiChannelIfNeeded (noteOff, sourceID3);
514 expectEquals (noteOff.getChannel(), 3);
518 layout.setUpperZone (15);
521 MPEChannelRemapper channelRemapper (layout.getUpperZone());
524 for (
int ch = 15; ch >= 1; --ch)
528 channelRemapper.remapMidiChannelIfNeeded (noteOn, sourceID1);
529 expectEquals (noteOn.getChannel(), ch);
535 channelRemapper.remapMidiChannelIfNeeded (noteOn, sourceID2);
536 expectEquals (noteOn.getChannel(), 15);
539 channelRemapper.remapMidiChannelIfNeeded (noteOn, sourceID3);
540 expectEquals (noteOn.getChannel(), 14);
544 channelRemapper.remapMidiChannelIfNeeded (noteOff, sourceID3);
545 expectEquals (noteOff.getChannel(), 14);
551static MPEUtilsUnitTests MPEUtilsUnitTests;
#define noexcept
Definition DistrhoDefines.h:72
static void message(int level, const char *fmt,...)
Definition adplugdb.cpp:120
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
int removeAllInstancesOf(ParameterType valueToRemove)
Definition juce_Array.h:861
int numChannels
Definition juce_MPEUtils.h:85
int midiChannelLastAssigned
Definition juce_MPEUtils.h:85
bool isLegacy
Definition juce_MPEUtils.h:83
int firstChannel
Definition juce_MPEUtils.h:85
int findMidiChannelPlayingClosestNonequalNote(int noteNumber) noexcept
Definition juce_MPEUtils.cpp:134
int lastChannel
Definition juce_MPEUtils.h:85
std::unique_ptr< MPEZoneLayout::Zone > zone
Definition juce_MPEUtils.h:84
int findMidiChannelForExistingNote(int initialNoteOnNumber) noexcept
Definition juce_MPEUtils.cpp:87
MPEChannelAssigner(MPEZoneLayout::Zone zoneToUse)
Definition juce_MPEUtils.cpp:26
std::array< MidiChannel, 17 > midiChannels
Definition juce_MPEUtils.h:94
int findMidiChannelForNewNote(int noteNumber) noexcept
Definition juce_MPEUtils.cpp:50
int channelIncrement
Definition juce_MPEUtils.h:85
void noteOff(int noteNumber, int midiChannel=-1)
Definition juce_MPEUtils.cpp:97
void allNotesOff()
Definition juce_MPEUtils.cpp:123
int firstChannel
Definition juce_MPEUtils.h:142
int lastChannel
Definition juce_MPEUtils.h:142
void reset() noexcept
Definition juce_MPEUtils.cpp:213
void zeroArrays()
Definition juce_MPEUtils.cpp:273
void remapMidiChannelIfNeeded(MidiMessage &message, uint32 mpeSourceID) noexcept
Definition juce_MPEUtils.cpp:168
bool messageIsNoteData(const MidiMessage &m)
Definition juce_MPEUtils.h:155
MPEZoneLayout::Zone zone
Definition juce_MPEUtils.h:139
bool applyRemapIfExisting(int channel, uint32 sourceAndChannelID, MidiMessage &m) noexcept
Definition juce_MPEUtils.cpp:236
static const uint32 notMPE
Definition juce_MPEUtils.h:111
int getBestChanToReuse() const noexcept
Definition juce_MPEUtils.cpp:252
uint32 counter
Definition juce_MPEUtils.h:146
void clearChannel(int channel) noexcept
Definition juce_MPEUtils.cpp:219
void clearSource(uint32 mpeSourceID)
Definition juce_MPEUtils.cpp:224
uint32 sourceAndChannel[17]
Definition juce_MPEUtils.h:144
int channelIncrement
Definition juce_MPEUtils.h:141
uint32 lastUsed[17]
Definition juce_MPEUtils.h:145
MPEChannelRemapper(MPEZoneLayout::Zone zoneToRemap)
Definition juce_MPEUtils.cpp:157
Definition juce_MPEZoneLayout.h:121
MPEZone Zone
Definition juce_MPEZoneLayout.h:216
Definition juce_MidiMessage.h:35
Definition juce_Range.h:40
constexpr bool isEmpty() const noexcept
Definition juce_Range.h:89
Definition juce_UnitTest.h:70
unsigned * m
Definition inflate.c:1559
register unsigned i
Definition inflate.c:1575
unsigned s
Definition inflate.c:1555
Definition juce_UnitTestCategories.h:27
Definition carla_juce.cpp:31
unsigned int uint32
Definition juce_MathsFunctions.h:45
#define true
Definition ordinals.h:82
Definition juce_MPEUtils.h:89
int lastNotePlayed
Definition juce_MPEUtils.h:91
Array< int > notes
Definition juce_MPEUtils.h:90
typedef int(UZ_EXP MsgFn)()
#define const
Definition zconf.h:137