29 : lowerZone (other.lowerZone),
30 upperZone (other.upperZone)
36 lowerZone = other.lowerZone;
37 upperZone = other.upperZone;
39 sendLayoutChangeMessage();
44 void MPEZoneLayout::sendLayoutChangeMessage()
46 listeners.call ([
this] (Listener& l) { l.zoneLayoutChanged (*
this); });
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)
124 if (rpn.channel == 1)
126 else if (rpn.channel == 16)
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)
153 if (rpn.channel == 1)
155 updateMasterPitchbend (lowerZone, rpn.value);
157 else if (rpn.channel == 16)
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);
212 class MPEZoneLayoutTests :
public UnitTest
215 MPEZoneLayoutTests() : UnitTest (
"MPEZoneLayout class",
"MIDI/MPE") {}
217 void runTest()
override
219 beginTest (
"initialisation");
221 MPEZoneLayout layout;
222 expect (! layout.getLowerZone().isActive());
223 expect (! layout.getUpperZone().isActive());
226 beginTest (
"adding zones");
228 MPEZoneLayout layout;
230 layout.setLowerZone (7);
232 expect (layout.getLowerZone().isActive());
233 expect (! layout.getUpperZone().isActive());
234 expectEquals (layout.getLowerZone().getMasterChannel(), 1);
235 expectEquals (layout.getLowerZone().numMemberChannels, 7);
237 layout.setUpperZone (7);
239 expect (layout.getLowerZone().isActive());
240 expect (layout.getUpperZone().isActive());
241 expectEquals (layout.getLowerZone().getMasterChannel(), 1);
242 expectEquals (layout.getLowerZone().numMemberChannels, 7);
243 expectEquals (layout.getUpperZone().getMasterChannel(), 16);
244 expectEquals (layout.getUpperZone().numMemberChannels, 7);
246 layout.setLowerZone (3);
248 expect (layout.getLowerZone().isActive());
249 expect (layout.getUpperZone().isActive());
250 expectEquals (layout.getLowerZone().getMasterChannel(), 1);
251 expectEquals (layout.getLowerZone().numMemberChannels, 3);
252 expectEquals (layout.getUpperZone().getMasterChannel(), 16);
253 expectEquals (layout.getUpperZone().numMemberChannels, 7);
255 layout.setUpperZone (3);
257 expect (layout.getLowerZone().isActive());
258 expect (layout.getUpperZone().isActive());
259 expectEquals (layout.getLowerZone().getMasterChannel(), 1);
260 expectEquals (layout.getLowerZone().numMemberChannels, 3);
261 expectEquals (layout.getUpperZone().getMasterChannel(), 16);
262 expectEquals (layout.getUpperZone().numMemberChannels, 3);
264 layout.setLowerZone (15);
266 expect (layout.getLowerZone().isActive());
267 expect (! layout.getUpperZone().isActive());
268 expectEquals (layout.getLowerZone().getMasterChannel(), 1);
269 expectEquals (layout.getLowerZone().numMemberChannels, 15);
272 beginTest (
"clear all zones");
274 MPEZoneLayout layout;
276 expect (! layout.getLowerZone().isActive());
277 expect (! layout.getUpperZone().isActive());
279 layout.setLowerZone (7);
280 layout.setUpperZone (2);
282 expect (layout.getLowerZone().isActive());
283 expect (layout.getUpperZone().isActive());
285 layout.clearAllZones();
287 expect (! layout.getLowerZone().isActive());
288 expect (! layout.getUpperZone().isActive());
291 beginTest (
"process MIDI buffers");
293 MPEZoneLayout layout;
297 layout.processNextMidiBuffer (buffer);
299 expect (layout.getLowerZone().isActive());
300 expect (! layout.getUpperZone().isActive());
301 expectEquals (layout.getLowerZone().getMasterChannel(), 1);
302 expectEquals (layout.getLowerZone().numMemberChannels, 7);
305 layout.processNextMidiBuffer (buffer);
307 expect (layout.getLowerZone().isActive());
308 expect (layout.getUpperZone().isActive());
309 expectEquals (layout.getLowerZone().getMasterChannel(), 1);
310 expectEquals (layout.getLowerZone().numMemberChannels, 7);
311 expectEquals (layout.getUpperZone().getMasterChannel(), 16);
312 expectEquals (layout.getUpperZone().numMemberChannels, 7);
316 layout.processNextMidiBuffer (buffer);
318 expect (layout.getLowerZone().isActive());
319 expect (layout.getUpperZone().isActive());
320 expectEquals (layout.getLowerZone().getMasterChannel(), 1);
321 expectEquals (layout.getLowerZone().numMemberChannels, 10);
322 expectEquals (layout.getUpperZone().getMasterChannel(), 16);
323 expectEquals (layout.getUpperZone().numMemberChannels, 4);
327 layout.processNextMidiBuffer (buffer);
329 expectEquals (layout.getLowerZone().numMemberChannels, 10);
330 expectEquals (layout.getLowerZone().perNotePitchbendRange, 33);
331 expectEquals (layout.getLowerZone().masterPitchbendRange, 44);
336 layout.processNextMidiBuffer (buffer);
338 expect (layout.getLowerZone().isActive());
339 expect (layout.getUpperZone().isActive());
340 expectEquals (layout.getLowerZone().getMasterChannel(), 1);
341 expectEquals (layout.getLowerZone().numMemberChannels, 4);
342 expectEquals (layout.getUpperZone().getMasterChannel(), 16);
343 expectEquals (layout.getUpperZone().numMemberChannels, 10);
347 layout.processNextMidiBuffer (buffer);
349 expectEquals (layout.getUpperZone().numMemberChannels, 10);
350 expectEquals (layout.getUpperZone().perNotePitchbendRange, 33);
351 expectEquals (layout.getUpperZone().masterPitchbendRange, 44);
355 layout.processNextMidiBuffer (buffer);
357 expect (! layout.getLowerZone().isActive());
358 expect (! layout.getUpperZone().isActive());
361 beginTest (
"process individual MIDI messages");
363 MPEZoneLayout layout;
365 layout.processNextMidiEvent ({ 0x80, 0x59, 0xd0 });
366 layout.processNextMidiEvent ({ 0xb0, 0x64, 0x06 });
367 layout.processNextMidiEvent ({ 0xb0, 0x65, 0x00 });
368 layout.processNextMidiEvent ({ 0xb8, 0x0b, 0x66 });
369 layout.processNextMidiEvent ({ 0xb0, 0x06, 0x03 });
370 layout.processNextMidiEvent ({ 0x90, 0x60, 0x00 });
372 expect (layout.getLowerZone().isActive());
373 expect (! layout.getUpperZone().isActive());
374 expectEquals (layout.getLowerZone().getMasterChannel(), 1);
375 expectEquals (layout.getLowerZone().numMemberChannels, 3);
376 expectEquals (layout.getLowerZone().perNotePitchbendRange, 48);
377 expectEquals (layout.getLowerZone().masterPitchbendRange, 2);
382 static MPEZoneLayoutTests MPEZoneLayoutUnitTests;
385 #endif // JUCE_UNIT_TESTS