29 : lowerZone (other.lowerZone),
30 upperZone (other.upperZone)
36 lowerZone = other.lowerZone;
37 upperZone = other.upperZone;
39 sendLayoutChangeMessage();
44 void MPEZoneLayout::sendLayoutChangeMessage()
50 void MPEZoneLayout::setZone (
bool isLower,
int numMemberChannels,
int perNotePitchbendRange,
int masterPitchbendRange) noexcept
52 checkAndLimitZoneParameters (0, 15, numMemberChannels);
53 checkAndLimitZoneParameters (0, 96, perNotePitchbendRange);
54 checkAndLimitZoneParameters (0, 96, masterPitchbendRange);
57 lowerZone = {
true, numMemberChannels, perNotePitchbendRange, masterPitchbendRange };
59 upperZone = {
false, numMemberChannels, perNotePitchbendRange, masterPitchbendRange };
61 if (numMemberChannels > 0)
63 auto totalChannels = lowerZone.numMemberChannels + upperZone.numMemberChannels;
65 if (totalChannels >= 15)
68 upperZone.numMemberChannels = 14 - numMemberChannels;
70 lowerZone.numMemberChannels = 14 - numMemberChannels;
74 sendLayoutChangeMessage();
79 setZone (
true, numMemberChannels, perNotePitchbendRange, masterPitchbendRange);
84 setZone (
false, numMemberChannels, perNotePitchbendRange, masterPitchbendRange);
89 lowerZone = {
true, 0 };
90 upperZone = {
false, 0 };
92 sendLayoutChangeMessage();
108 processRpnMessage (rpn);
115 processZoneLayoutRpnMessage (rpn);
117 processPitchbendRangeRpnMessage (rpn);
120 void MPEZoneLayout::processZoneLayoutRpnMessage (
MidiRPNMessage rpn)
131 void MPEZoneLayout::updateMasterPitchbend (
Zone& zone,
int value)
133 if (zone.masterPitchbendRange != value)
135 checkAndLimitZoneParameters (0, 96, zone.masterPitchbendRange);
136 zone.masterPitchbendRange = value;
137 sendLayoutChangeMessage();
141 void MPEZoneLayout::updatePerNotePitchbendRange (
Zone& zone,
int value)
143 if (zone.perNotePitchbendRange != value)
145 checkAndLimitZoneParameters (0, 96, zone.perNotePitchbendRange);
146 zone.perNotePitchbendRange = value;
147 sendLayoutChangeMessage();
151 void MPEZoneLayout::processPitchbendRangeRpnMessage (
MidiRPNMessage rpn)
155 updateMasterPitchbend (lowerZone, rpn.
value);
159 updateMasterPitchbend (upperZone, rpn.
value);
163 if (lowerZone.isUsingChannelAsMemberChannel (rpn.
channel))
164 updatePerNotePitchbendRange (lowerZone, rpn.
value);
165 else if (upperZone.isUsingChannelAsMemberChannel (rpn.
channel))
166 updatePerNotePitchbendRange (upperZone, rpn.
value);
183 listeners.add (listenerToAdd);
188 listeners.remove (listenerToRemove);
192 void MPEZoneLayout::checkAndLimitZoneParameters (
int minValue,
int maxValue,
193 int& valueToCheckAndLimit) noexcept
195 if (valueToCheckAndLimit < minValue || valueToCheckAndLimit > maxValue)
204 valueToCheckAndLimit = jlimit (minValue, maxValue, valueToCheckAndLimit);
213 class MPEZoneLayoutTests :
public UnitTest 217 :
UnitTest (
"MPEZoneLayout class", UnitTestCategories::midi)
220 void runTest()
override 222 beginTest (
"initialisation");
229 beginTest (
"adding zones");
237 expectEquals (layout.
getLowerZone().getMasterChannel(), 1);
238 expectEquals (layout.
getLowerZone().numMemberChannels, 7);
244 expectEquals (layout.
getLowerZone().getMasterChannel(), 1);
245 expectEquals (layout.
getLowerZone().numMemberChannels, 7);
246 expectEquals (layout.
getUpperZone().getMasterChannel(), 16);
247 expectEquals (layout.
getUpperZone().numMemberChannels, 7);
253 expectEquals (layout.
getLowerZone().getMasterChannel(), 1);
254 expectEquals (layout.
getLowerZone().numMemberChannels, 3);
255 expectEquals (layout.
getUpperZone().getMasterChannel(), 16);
256 expectEquals (layout.
getUpperZone().numMemberChannels, 7);
262 expectEquals (layout.
getLowerZone().getMasterChannel(), 1);
263 expectEquals (layout.
getLowerZone().numMemberChannels, 3);
264 expectEquals (layout.
getUpperZone().getMasterChannel(), 16);
265 expectEquals (layout.
getUpperZone().numMemberChannels, 3);
271 expectEquals (layout.
getLowerZone().getMasterChannel(), 1);
272 expectEquals (layout.
getLowerZone().numMemberChannels, 15);
275 beginTest (
"clear all zones");
294 beginTest (
"process MIDI buffers");
304 expectEquals (layout.
getLowerZone().getMasterChannel(), 1);
305 expectEquals (layout.
getLowerZone().numMemberChannels, 7);
312 expectEquals (layout.
getLowerZone().getMasterChannel(), 1);
313 expectEquals (layout.
getLowerZone().numMemberChannels, 7);
314 expectEquals (layout.
getUpperZone().getMasterChannel(), 16);
315 expectEquals (layout.
getUpperZone().numMemberChannels, 7);
323 expectEquals (layout.
getLowerZone().getMasterChannel(), 1);
324 expectEquals (layout.
getLowerZone().numMemberChannels, 10);
325 expectEquals (layout.
getUpperZone().getMasterChannel(), 16);
326 expectEquals (layout.
getUpperZone().numMemberChannels, 4);
332 expectEquals (layout.
getLowerZone().numMemberChannels, 10);
333 expectEquals (layout.
getLowerZone().perNotePitchbendRange, 33);
334 expectEquals (layout.
getLowerZone().masterPitchbendRange, 44);
343 expectEquals (layout.
getLowerZone().getMasterChannel(), 1);
344 expectEquals (layout.
getLowerZone().numMemberChannels, 4);
345 expectEquals (layout.
getUpperZone().getMasterChannel(), 16);
346 expectEquals (layout.
getUpperZone().numMemberChannels, 10);
352 expectEquals (layout.
getUpperZone().numMemberChannels, 10);
353 expectEquals (layout.
getUpperZone().perNotePitchbendRange, 33);
354 expectEquals (layout.
getUpperZone().masterPitchbendRange, 44);
364 beginTest (
"process individual MIDI messages");
377 expectEquals (layout.
getLowerZone().getMasterChannel(), 1);
378 expectEquals (layout.
getLowerZone().numMemberChannels, 3);
379 expectEquals (layout.
getLowerZone().perNotePitchbendRange, 48);
380 expectEquals (layout.
getLowerZone().masterPitchbendRange, 2);
385 static MPEZoneLayoutTests MPEZoneLayoutUnitTests;
void processNextMidiBuffer(const MidiBuffer &buffer)
bool getNextEvent(MidiMessage &result, int &samplePosition) noexcept
void processNextMidiEvent(const MidiMessage &message)
virtual void zoneLayoutChanged(const MPEZoneLayout &layout)=0
void setUpperZone(int numMemberChannels=0, int perNotePitchbendRange=48, int masterPitchbendRange=2) noexcept
static MidiBuffer setUpperZone(int numMemberChannels=0, int perNotePitchbendRange=48, int masterPitchbendRange=2)
static MidiBuffer setLowerZone(int numMemberChannels=0, int perNotePitchbendRange=48, int masterPitchbendRange=2)
const Zone getUpperZone() const noexcept
static MidiBuffer clearAllZones()
void addListener(Listener *const listenerToAdd) noexcept
int getControllerNumber() const noexcept
int getChannel() const noexcept
bool isController() const noexcept
const Zone getLowerZone() const noexcept
int getControllerValue() const noexcept
MPEZoneLayout & operator=(const MPEZoneLayout &other)
static const int zoneLayoutMessagesRpnNumber
bool parseControllerMessage(int midiChannel, int controllerNumber, int controllerValue, MidiRPNMessage &result) noexcept
void removeListener(Listener *const listenerToRemove) noexcept
void setLowerZone(int numMemberChannels=0, int perNotePitchbendRange=48, int masterPitchbendRange=2) noexcept