| 
							- /*
 -   ==============================================================================
 - 
 -    This file is part of the JUCE library.
 -    Copyright (c) 2020 - Raw Material Software Limited
 - 
 -    JUCE is an open source library subject to commercial or open-source
 -    licensing.
 - 
 -    The code included in this file is provided under the terms of the ISC license
 -    http://www.isc.org/downloads/software-support-policy/isc-license. Permission
 -    To use, copy, modify, and/or distribute this software for any purpose with or
 -    without fee is hereby granted provided that the above copyright notice and
 -    this permission notice appear in all copies.
 - 
 -    JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
 -    EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
 -    DISCLAIMED.
 - 
 -   ==============================================================================
 - */
 - 
 - namespace juce
 - {
 - 
 - MPEZoneLayout::MPEZoneLayout() noexcept {}
 - 
 - MPEZoneLayout::MPEZoneLayout (const MPEZoneLayout& other)
 -     : lowerZone (other.lowerZone),
 -       upperZone (other.upperZone)
 - {
 - }
 - 
 - MPEZoneLayout& MPEZoneLayout::operator= (const MPEZoneLayout& other)
 - {
 -     lowerZone = other.lowerZone;
 -     upperZone = other.upperZone;
 - 
 -     sendLayoutChangeMessage();
 - 
 -     return *this;
 - }
 - 
 - void MPEZoneLayout::sendLayoutChangeMessage()
 - {
 -     listeners.call ([this] (Listener& l) { l.zoneLayoutChanged (*this); });
 - }
 - 
 - //==============================================================================
 - void MPEZoneLayout::setZone (bool isLower, int numMemberChannels, int perNotePitchbendRange, int masterPitchbendRange) noexcept
 - {
 -     checkAndLimitZoneParameters (0, 15,  numMemberChannels);
 -     checkAndLimitZoneParameters (0, 96,  perNotePitchbendRange);
 -     checkAndLimitZoneParameters (0, 96,  masterPitchbendRange);
 - 
 -     if (isLower)
 -         lowerZone = { true, numMemberChannels, perNotePitchbendRange, masterPitchbendRange };
 -     else
 -         upperZone = { false, numMemberChannels, perNotePitchbendRange, masterPitchbendRange };
 - 
 -     if (numMemberChannels > 0)
 -     {
 -         auto totalChannels = lowerZone.numMemberChannels + upperZone.numMemberChannels;
 - 
 -         if (totalChannels >= 15)
 -         {
 -             if (isLower)
 -                 upperZone.numMemberChannels = 14 - numMemberChannels;
 -             else
 -                 lowerZone.numMemberChannels = 14 - numMemberChannels;
 -         }
 -     }
 - 
 -     sendLayoutChangeMessage();
 - }
 - 
 - void MPEZoneLayout::setLowerZone (int numMemberChannels, int perNotePitchbendRange, int masterPitchbendRange) noexcept
 - {
 -     setZone (true, numMemberChannels, perNotePitchbendRange, masterPitchbendRange);
 - }
 - 
 - void MPEZoneLayout::setUpperZone (int numMemberChannels, int perNotePitchbendRange, int masterPitchbendRange) noexcept
 - {
 -     setZone (false, numMemberChannels, perNotePitchbendRange, masterPitchbendRange);
 - }
 - 
 - void MPEZoneLayout::clearAllZones()
 - {
 -     lowerZone = { true, 0 };
 -     upperZone = { false, 0 };
 - 
 -     sendLayoutChangeMessage();
 - }
 - 
 - //==============================================================================
 - void MPEZoneLayout::processNextMidiEvent (const MidiMessage& message)
 - {
 -     if (! message.isController())
 -         return;
 - 
 -     MidiRPNMessage rpn;
 - 
 -     if (rpnDetector.parseControllerMessage (message.getChannel(),
 -                                             message.getControllerNumber(),
 -                                             message.getControllerValue(),
 -                                             rpn))
 -     {
 -         processRpnMessage (rpn);
 -     }
 - }
 - 
 - void MPEZoneLayout::processRpnMessage (MidiRPNMessage rpn)
 - {
 -     if (rpn.parameterNumber == MPEMessages::zoneLayoutMessagesRpnNumber)
 -         processZoneLayoutRpnMessage (rpn);
 -     else if (rpn.parameterNumber == 0)
 -         processPitchbendRangeRpnMessage (rpn);
 - }
 - 
 - void MPEZoneLayout::processZoneLayoutRpnMessage (MidiRPNMessage rpn)
 - {
 -     if (rpn.value < 16)
 -     {
 -         if (rpn.channel == 1)
 -             setLowerZone (rpn.value);
 -         else if (rpn.channel == 16)
 -             setUpperZone (rpn.value);
 -     }
 - }
 - 
 - void MPEZoneLayout::updateMasterPitchbend (Zone& zone, int value)
 - {
 -     if (zone.masterPitchbendRange != value)
 -     {
 -         checkAndLimitZoneParameters (0, 96, zone.masterPitchbendRange);
 -         zone.masterPitchbendRange = value;
 -         sendLayoutChangeMessage();
 -     }
 - }
 - 
 - void MPEZoneLayout::updatePerNotePitchbendRange (Zone& zone, int value)
 - {
 -     if (zone.perNotePitchbendRange != value)
 -     {
 -         checkAndLimitZoneParameters (0, 96, zone.perNotePitchbendRange);
 -         zone.perNotePitchbendRange = value;
 -         sendLayoutChangeMessage();
 -     }
 - }
 - 
 - void MPEZoneLayout::processPitchbendRangeRpnMessage (MidiRPNMessage rpn)
 - {
 -     if (rpn.channel == 1)
 -     {
 -         updateMasterPitchbend (lowerZone, rpn.value);
 -     }
 -     else if (rpn.channel == 16)
 -     {
 -         updateMasterPitchbend (upperZone, rpn.value);
 -     }
 -     else
 -     {
 -         if (lowerZone.isUsingChannelAsMemberChannel (rpn.channel))
 -             updatePerNotePitchbendRange (lowerZone, rpn.value);
 -         else if (upperZone.isUsingChannelAsMemberChannel (rpn.channel))
 -             updatePerNotePitchbendRange (upperZone, rpn.value);
 -     }
 - }
 - 
 - void MPEZoneLayout::processNextMidiBuffer (const MidiBuffer& buffer)
 - {
 -     MidiBuffer::Iterator iter (buffer);
 -     MidiMessage message;
 -     int samplePosition; // not actually used, so no need to initialise.
 - 
 -     while (iter.getNextEvent (message, samplePosition))
 -         processNextMidiEvent (message);
 - }
 - 
 - //==============================================================================
 - void MPEZoneLayout::addListener (Listener* const listenerToAdd) noexcept
 - {
 -     listeners.add (listenerToAdd);
 - }
 - 
 - void MPEZoneLayout::removeListener (Listener* const listenerToRemove) noexcept
 - {
 -     listeners.remove (listenerToRemove);
 - }
 - 
 - //==============================================================================
 - void MPEZoneLayout::checkAndLimitZoneParameters (int minValue, int maxValue,
 -                                                  int& valueToCheckAndLimit) noexcept
 - {
 -     if (valueToCheckAndLimit < minValue || valueToCheckAndLimit > maxValue)
 -     {
 -         // if you hit this, one of the parameters you supplied for this zone
 -         // was not within the allowed range!
 -         // we fit this back into the allowed range here to maintain a valid
 -         // state for the zone, but probably the resulting zone is not what you
 -         // wanted it to be!
 -         jassertfalse;
 - 
 -         valueToCheckAndLimit = jlimit (minValue, maxValue, valueToCheckAndLimit);
 -     }
 - }
 - 
 - 
 - //==============================================================================
 - //==============================================================================
 - #if JUCE_UNIT_TESTS
 - 
 - class MPEZoneLayoutTests  : public UnitTest
 - {
 - public:
 -     MPEZoneLayoutTests()
 -         : UnitTest ("MPEZoneLayout class", UnitTestCategories::midi)
 -     {}
 - 
 -     void runTest() override
 -     {
 -         beginTest ("initialisation");
 -         {
 -             MPEZoneLayout layout;
 -             expect (! layout.getLowerZone().isActive());
 -             expect (! layout.getUpperZone().isActive());
 -         }
 - 
 -         beginTest ("adding zones");
 -         {
 -             MPEZoneLayout layout;
 - 
 -             layout.setLowerZone (7);
 - 
 -             expect (layout.getLowerZone().isActive());
 -             expect (! layout.getUpperZone().isActive());
 -             expectEquals (layout.getLowerZone().getMasterChannel(), 1);
 -             expectEquals (layout.getLowerZone().numMemberChannels, 7);
 - 
 -             layout.setUpperZone (7);
 - 
 -             expect (layout.getLowerZone().isActive());
 -             expect (layout.getUpperZone().isActive());
 -             expectEquals (layout.getLowerZone().getMasterChannel(), 1);
 -             expectEquals (layout.getLowerZone().numMemberChannels, 7);
 -             expectEquals (layout.getUpperZone().getMasterChannel(), 16);
 -             expectEquals (layout.getUpperZone().numMemberChannels, 7);
 - 
 -             layout.setLowerZone (3);
 - 
 -             expect (layout.getLowerZone().isActive());
 -             expect (layout.getUpperZone().isActive());
 -             expectEquals (layout.getLowerZone().getMasterChannel(), 1);
 -             expectEquals (layout.getLowerZone().numMemberChannels, 3);
 -             expectEquals (layout.getUpperZone().getMasterChannel(), 16);
 -             expectEquals (layout.getUpperZone().numMemberChannels, 7);
 - 
 -             layout.setUpperZone (3);
 - 
 -             expect (layout.getLowerZone().isActive());
 -             expect (layout.getUpperZone().isActive());
 -             expectEquals (layout.getLowerZone().getMasterChannel(), 1);
 -             expectEquals (layout.getLowerZone().numMemberChannels, 3);
 -             expectEquals (layout.getUpperZone().getMasterChannel(), 16);
 -             expectEquals (layout.getUpperZone().numMemberChannels, 3);
 - 
 -             layout.setLowerZone (15);
 - 
 -             expect (layout.getLowerZone().isActive());
 -             expect (! layout.getUpperZone().isActive());
 -             expectEquals (layout.getLowerZone().getMasterChannel(), 1);
 -             expectEquals (layout.getLowerZone().numMemberChannels, 15);
 -         }
 - 
 -         beginTest ("clear all zones");
 -         {
 -             MPEZoneLayout layout;
 - 
 -             expect (! layout.getLowerZone().isActive());
 -             expect (! layout.getUpperZone().isActive());
 - 
 -             layout.setLowerZone (7);
 -             layout.setUpperZone (2);
 - 
 -             expect (layout.getLowerZone().isActive());
 -             expect (layout.getUpperZone().isActive());
 - 
 -             layout.clearAllZones();
 - 
 -             expect (! layout.getLowerZone().isActive());
 -             expect (! layout.getUpperZone().isActive());
 -         }
 - 
 -         beginTest ("process MIDI buffers");
 -         {
 -             MPEZoneLayout layout;
 -             MidiBuffer buffer;
 - 
 -             buffer = MPEMessages::setLowerZone (7);
 -             layout.processNextMidiBuffer (buffer);
 - 
 -             expect (layout.getLowerZone().isActive());
 -             expect (! layout.getUpperZone().isActive());
 -             expectEquals (layout.getLowerZone().getMasterChannel(), 1);
 -             expectEquals (layout.getLowerZone().numMemberChannels, 7);
 - 
 -             buffer = MPEMessages::setUpperZone (7);
 -             layout.processNextMidiBuffer (buffer);
 - 
 -             expect (layout.getLowerZone().isActive());
 -             expect (layout.getUpperZone().isActive());
 -             expectEquals (layout.getLowerZone().getMasterChannel(), 1);
 -             expectEquals (layout.getLowerZone().numMemberChannels, 7);
 -             expectEquals (layout.getUpperZone().getMasterChannel(), 16);
 -             expectEquals (layout.getUpperZone().numMemberChannels, 7);
 - 
 -             {
 -                 buffer = MPEMessages::setLowerZone (10);
 -                 layout.processNextMidiBuffer (buffer);
 - 
 -                 expect (layout.getLowerZone().isActive());
 -                 expect (layout.getUpperZone().isActive());
 -                 expectEquals (layout.getLowerZone().getMasterChannel(), 1);
 -                 expectEquals (layout.getLowerZone().numMemberChannels, 10);
 -                 expectEquals (layout.getUpperZone().getMasterChannel(), 16);
 -                 expectEquals (layout.getUpperZone().numMemberChannels, 4);
 - 
 - 
 -                 buffer = MPEMessages::setLowerZone (10, 33, 44);
 -                 layout.processNextMidiBuffer (buffer);
 - 
 -                 expectEquals (layout.getLowerZone().numMemberChannels, 10);
 -                 expectEquals (layout.getLowerZone().perNotePitchbendRange, 33);
 -                 expectEquals (layout.getLowerZone().masterPitchbendRange, 44);
 -             }
 - 
 -             {
 -                 buffer = MPEMessages::setUpperZone (10);
 -                 layout.processNextMidiBuffer (buffer);
 - 
 -                 expect (layout.getLowerZone().isActive());
 -                 expect (layout.getUpperZone().isActive());
 -                 expectEquals (layout.getLowerZone().getMasterChannel(), 1);
 -                 expectEquals (layout.getLowerZone().numMemberChannels, 4);
 -                 expectEquals (layout.getUpperZone().getMasterChannel(), 16);
 -                 expectEquals (layout.getUpperZone().numMemberChannels, 10);
 - 
 -                 buffer = MPEMessages::setUpperZone (10, 33, 44);
 - 
 -                 layout.processNextMidiBuffer (buffer);
 - 
 -                 expectEquals (layout.getUpperZone().numMemberChannels, 10);
 -                 expectEquals (layout.getUpperZone().perNotePitchbendRange, 33);
 -                 expectEquals (layout.getUpperZone().masterPitchbendRange, 44);
 -             }
 - 
 -             buffer = MPEMessages::clearAllZones();
 -             layout.processNextMidiBuffer (buffer);
 - 
 -             expect (! layout.getLowerZone().isActive());
 -             expect (! layout.getUpperZone().isActive());
 -         }
 - 
 -         beginTest ("process individual MIDI messages");
 -         {
 -             MPEZoneLayout layout;
 - 
 -             layout.processNextMidiEvent ({ 0x80, 0x59, 0xd0 });  // unrelated note-off msg
 -             layout.processNextMidiEvent ({ 0xb0, 0x64, 0x06 });  // RPN part 1
 -             layout.processNextMidiEvent ({ 0xb0, 0x65, 0x00 });  // RPN part 2
 -             layout.processNextMidiEvent ({ 0xb8, 0x0b, 0x66 });  // unrelated CC msg
 -             layout.processNextMidiEvent ({ 0xb0, 0x06, 0x03 });  // RPN part 3
 -             layout.processNextMidiEvent ({ 0x90, 0x60, 0x00 });  // unrelated note-on msg
 - 
 -             expect (layout.getLowerZone().isActive());
 -             expect (! layout.getUpperZone().isActive());
 -             expectEquals (layout.getLowerZone().getMasterChannel(), 1);
 -             expectEquals (layout.getLowerZone().numMemberChannels, 3);
 -             expectEquals (layout.getLowerZone().perNotePitchbendRange, 48);
 -             expectEquals (layout.getLowerZone().masterPitchbendRange, 2);
 -         }
 -     }
 - };
 - 
 - static MPEZoneLayoutTests MPEZoneLayoutUnitTests;
 - 
 - 
 - #endif
 - 
 - } // namespace juce
 
 
  |