29 : lowerZone (
other.lowerZone),
30 upperZone (
other.upperZone)
36 lowerZone =
other.lowerZone;
37 upperZone =
other.upperZone;
39 sendLayoutChangeMessage();
44void MPEZoneLayout::sendLayoutChangeMessage()
46 listeners.call ([
this] (Listener&
l) {
l.zoneLayoutChanged (*
this); });
50void 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);
116 else if (
rpn.parameterNumber == 0)
117 processPitchbendRangeRpnMessage (
rpn);
120void MPEZoneLayout::processZoneLayoutRpnMessage (MidiRPNMessage rpn)
124 if (rpn.channel == 1)
126 else if (rpn.channel == 16)
131void MPEZoneLayout::updateMasterPitchbend (Zone& zone,
int value)
133 if (zone.masterPitchbendRange != value)
135 checkAndLimitZoneParameters (0, 96, zone.masterPitchbendRange);
136 zone.masterPitchbendRange = value;
137 sendLayoutChangeMessage();
141void MPEZoneLayout::updatePerNotePitchbendRange (Zone& zone,
int value)
143 if (zone.perNotePitchbendRange != value)
145 checkAndLimitZoneParameters (0, 96, zone.perNotePitchbendRange);
146 zone.perNotePitchbendRange = value;
147 sendLayoutChangeMessage();
151void 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);
192void MPEZoneLayout::checkAndLimitZoneParameters (
int minValue,
int maxValue,
213class MPEZoneLayoutTests :
public UnitTest
217 : UnitTest (
"MPEZoneLayout class", UnitTestCategories::midi)
220 void runTest()
override
222 beginTest (
"initialisation");
225 expect (!
layout.getLowerZone().isActive());
226 expect (!
layout.getUpperZone().isActive());
229 beginTest (
"adding zones");
235 expect (
layout.getLowerZone().isActive());
236 expect (!
layout.getUpperZone().isActive());
237 expectEquals (
layout.getLowerZone().getMasterChannel(), 1);
238 expectEquals (
layout.getLowerZone().numMemberChannels, 7);
242 expect (
layout.getLowerZone().isActive());
243 expect (
layout.getUpperZone().isActive());
244 expectEquals (
layout.getLowerZone().getMasterChannel(), 1);
245 expectEquals (
layout.getLowerZone().numMemberChannels, 7);
246 expectEquals (
layout.getUpperZone().getMasterChannel(), 16);
247 expectEquals (
layout.getUpperZone().numMemberChannels, 7);
251 expect (
layout.getLowerZone().isActive());
252 expect (
layout.getUpperZone().isActive());
253 expectEquals (
layout.getLowerZone().getMasterChannel(), 1);
254 expectEquals (
layout.getLowerZone().numMemberChannels, 3);
255 expectEquals (
layout.getUpperZone().getMasterChannel(), 16);
256 expectEquals (
layout.getUpperZone().numMemberChannels, 7);
260 expect (
layout.getLowerZone().isActive());
261 expect (
layout.getUpperZone().isActive());
262 expectEquals (
layout.getLowerZone().getMasterChannel(), 1);
263 expectEquals (
layout.getLowerZone().numMemberChannels, 3);
264 expectEquals (
layout.getUpperZone().getMasterChannel(), 16);
265 expectEquals (
layout.getUpperZone().numMemberChannels, 3);
269 expect (
layout.getLowerZone().isActive());
270 expect (!
layout.getUpperZone().isActive());
271 expectEquals (
layout.getLowerZone().getMasterChannel(), 1);
272 expectEquals (
layout.getLowerZone().numMemberChannels, 15);
275 beginTest (
"clear all zones");
279 expect (!
layout.getLowerZone().isActive());
280 expect (!
layout.getUpperZone().isActive());
285 expect (
layout.getLowerZone().isActive());
286 expect (
layout.getUpperZone().isActive());
290 expect (!
layout.getLowerZone().isActive());
291 expect (!
layout.getUpperZone().isActive());
294 beginTest (
"process MIDI buffers");
300 layout.processNextMidiBuffer (buffer);
302 expect (
layout.getLowerZone().isActive());
303 expect (!
layout.getUpperZone().isActive());
304 expectEquals (
layout.getLowerZone().getMasterChannel(), 1);
305 expectEquals (
layout.getLowerZone().numMemberChannels, 7);
308 layout.processNextMidiBuffer (buffer);
310 expect (
layout.getLowerZone().isActive());
311 expect (
layout.getUpperZone().isActive());
312 expectEquals (
layout.getLowerZone().getMasterChannel(), 1);
313 expectEquals (
layout.getLowerZone().numMemberChannels, 7);
314 expectEquals (
layout.getUpperZone().getMasterChannel(), 16);
315 expectEquals (
layout.getUpperZone().numMemberChannels, 7);
319 layout.processNextMidiBuffer (buffer);
321 expect (
layout.getLowerZone().isActive());
322 expect (
layout.getUpperZone().isActive());
323 expectEquals (
layout.getLowerZone().getMasterChannel(), 1);
324 expectEquals (
layout.getLowerZone().numMemberChannels, 10);
325 expectEquals (
layout.getUpperZone().getMasterChannel(), 16);
326 expectEquals (
layout.getUpperZone().numMemberChannels, 4);
330 layout.processNextMidiBuffer (buffer);
332 expectEquals (
layout.getLowerZone().numMemberChannels, 10);
333 expectEquals (
layout.getLowerZone().perNotePitchbendRange, 33);
334 expectEquals (
layout.getLowerZone().masterPitchbendRange, 44);
339 layout.processNextMidiBuffer (buffer);
341 expect (
layout.getLowerZone().isActive());
342 expect (
layout.getUpperZone().isActive());
343 expectEquals (
layout.getLowerZone().getMasterChannel(), 1);
344 expectEquals (
layout.getLowerZone().numMemberChannels, 4);
345 expectEquals (
layout.getUpperZone().getMasterChannel(), 16);
346 expectEquals (
layout.getUpperZone().numMemberChannels, 10);
350 layout.processNextMidiBuffer (buffer);
352 expectEquals (
layout.getUpperZone().numMemberChannels, 10);
353 expectEquals (
layout.getUpperZone().perNotePitchbendRange, 33);
354 expectEquals (
layout.getUpperZone().masterPitchbendRange, 44);
358 layout.processNextMidiBuffer (buffer);
360 expect (!
layout.getLowerZone().isActive());
361 expect (!
layout.getUpperZone().isActive());
364 beginTest (
"process individual MIDI messages");
368 layout.processNextMidiEvent ({ 0x80, 0x59, 0xd0 });
369 layout.processNextMidiEvent ({ 0xb0, 0x64, 0x06 });
370 layout.processNextMidiEvent ({ 0xb0, 0x65, 0x00 });
371 layout.processNextMidiEvent ({ 0xb8, 0x0b, 0x66 });
372 layout.processNextMidiEvent ({ 0xb0, 0x06, 0x03 });
373 layout.processNextMidiEvent ({ 0x90, 0x60, 0x00 });
375 expect (
layout.getLowerZone().isActive());
376 expect (!
layout.getUpperZone().isActive());
377 expectEquals (
layout.getLowerZone().getMasterChannel(), 1);
378 expectEquals (
layout.getLowerZone().numMemberChannels, 3);
379 expectEquals (
layout.getLowerZone().perNotePitchbendRange, 48);
380 expectEquals (
layout.getLowerZone().masterPitchbendRange, 2);
385static MPEZoneLayoutTests MPEZoneLayoutUnitTests;
void remove(int indexToRemove)
void add(const ElementType &newElement)
static MidiBuffer setUpperZone(int numMemberChannels=0, int perNotePitchbendRange=48, int masterPitchbendRange=2)
static MidiBuffer clearAllZones()
static MidiBuffer setLowerZone(int numMemberChannels=0, int perNotePitchbendRange=48, int masterPitchbendRange=2)
static const int zoneLayoutMessagesRpnNumber
void processNextMidiBuffer(const MidiBuffer &buffer)
void setUpperZone(int numMemberChannels=0, int perNotePitchbendRange=48, int masterPitchbendRange=2) noexcept
void removeListener(Listener *const listenerToRemove) noexcept
void addListener(Listener *const listenerToAdd) noexcept
MPEZoneLayout & operator=(const MPEZoneLayout &other)
void setLowerZone(int numMemberChannels=0, int perNotePitchbendRange=48, int masterPitchbendRange=2) noexcept
void processNextMidiEvent(const MidiMessage &message)
int getChannel() const noexcept
bool isController() const noexcept
int getControllerNumber() const noexcept
int getControllerValue() const noexcept
bool parseControllerMessage(int midiChannel, int controllerNumber, int controllerValue, MidiRPNMessage &result) noexcept