OpenShot Audio Library | OpenShotAudio  0.6.0
juce_MPEZoneLayout.h
1 /*
2  ==============================================================================
3 
4  This file is part of the JUCE library.
5  Copyright (c) 2022 - Raw Material Software Limited
6 
7  JUCE is an open source library subject to commercial or open-source
8  licensing.
9 
10  The code included in this file is provided under the terms of the ISC license
11  http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12  To use, copy, modify, and/or distribute this software for any purpose with or
13  without fee is hereby granted provided that the above copyright notice and
14  this permission notice appear in all copies.
15 
16  JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17  EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18  DISCLAIMED.
19 
20  ==============================================================================
21 */
22 
23 namespace juce
24 {
25 
26 //==============================================================================
41 struct MPEZone
42 {
43  enum class Type { lower, upper };
44 
45  MPEZone() = default;
46 
47  MPEZone (Type type, int memberChannels = 0, int perNotePitchbend = 48, int masterPitchbend = 2)
48  : zoneType (type),
49  numMemberChannels (memberChannels),
50  perNotePitchbendRange (perNotePitchbend),
51  masterPitchbendRange (masterPitchbend)
52  {}
53 
54  bool isLowerZone() const noexcept { return zoneType == Type::lower; }
55  bool isUpperZone() const noexcept { return zoneType == Type::upper; }
56 
57  bool isActive() const noexcept { return numMemberChannels > 0; }
58 
59  int getMasterChannel() const noexcept { return isLowerZone() ? lowerZoneMasterChannel : upperZoneMasterChannel; }
60  int getFirstMemberChannel() const noexcept { return isLowerZone() ? lowerZoneMasterChannel + 1 : upperZoneMasterChannel - 1; }
61  int getLastMemberChannel() const noexcept { return isLowerZone() ? (lowerZoneMasterChannel + numMemberChannels)
62  : (upperZoneMasterChannel - numMemberChannels); }
63 
64  bool isUsingChannelAsMemberChannel (int channel) const noexcept
65  {
66  return isLowerZone() ? (lowerZoneMasterChannel < channel && channel <= getLastMemberChannel())
67  : (channel < upperZoneMasterChannel && getLastMemberChannel() <= channel);
68  }
69 
70  bool isUsing (int channel) const noexcept
71  {
72  return isUsingChannelAsMemberChannel (channel) || channel == getMasterChannel();
73  }
74 
75  static auto tie (const MPEZone& z)
76  {
77  return std::tie (z.zoneType,
78  z.numMemberChannels,
79  z.perNotePitchbendRange,
80  z.masterPitchbendRange);
81  }
82 
83  bool operator== (const MPEZone& other) const
84  {
85  return tie (*this) == tie (other);
86  }
87 
88  bool operator!= (const MPEZone& other) const
89  {
90  return tie (*this) != tie (other);
91  }
92 
93  //==============================================================================
94  static constexpr int lowerZoneMasterChannel = 1,
95  upperZoneMasterChannel = 16;
96 
97  Type zoneType = Type::lower;
98 
99  int numMemberChannels = 0;
100  int perNotePitchbendRange = 48;
101  int masterPitchbendRange = 2;
102 };
103 
104 //==============================================================================
122 class JUCE_API MPEZoneLayout
123 {
124 public:
125  //==============================================================================
127  MPEZoneLayout() = default;
128 
130  MPEZoneLayout (MPEZone lower, MPEZone upper);
131 
133  MPEZoneLayout (MPEZone singleZone);
134 
135  MPEZoneLayout (const MPEZoneLayout& other);
136  MPEZoneLayout& operator= (const MPEZoneLayout& other);
137 
138  bool operator== (const MPEZoneLayout& other) const { return lowerZone == other.lowerZone && upperZone == other.upperZone; }
139  bool operator!= (const MPEZoneLayout& other) const { return ! operator== (other); }
140 
141  //==============================================================================
143  MPEZone getLowerZone() const noexcept { return lowerZone; }
144 
146  MPEZone getUpperZone() const noexcept { return upperZone; }
147 
149  void setLowerZone (int numMemberChannels = 0,
150  int perNotePitchbendRange = 48,
151  int masterPitchbendRange = 2) noexcept;
152 
154  void setUpperZone (int numMemberChannels = 0,
155  int perNotePitchbendRange = 48,
156  int masterPitchbendRange = 2) noexcept;
157 
161  void clearAllZones();
162 
164  bool isActive() const { return lowerZone.isActive() || upperZone.isActive(); }
165 
166  //==============================================================================
178  void processNextMidiEvent (const MidiMessage& message);
179 
191  void processNextMidiBuffer (const MidiBuffer& buffer);
192 
193  //==============================================================================
197  class Listener
198  {
199  public:
201  virtual ~Listener() = default;
202 
207  virtual void zoneLayoutChanged (const MPEZoneLayout& layout) = 0;
208  };
209 
210  //==============================================================================
212  void addListener (Listener* const listenerToAdd) noexcept;
213 
215  void removeListener (Listener* const listenerToRemove) noexcept;
216 
217  #ifndef DOXYGEN
218  using Zone = MPEZone;
219  #endif
220 
221 private:
222  //==============================================================================
223  MPEZone lowerZone { MPEZone::Type::lower, 0 };
224  MPEZone upperZone { MPEZone::Type::upper, 0 };
225 
226  MidiRPNDetector rpnDetector;
227  ListenerList<Listener> listeners;
228 
229  //==============================================================================
230  void setZone (bool, int, int, int) noexcept;
231 
232  void processRpnMessage (MidiRPNMessage);
233  void processZoneLayoutRpnMessage (MidiRPNMessage);
234  void processPitchbendRangeRpnMessage (MidiRPNMessage);
235 
236  void updateMasterPitchbend (MPEZone&, int);
237  void updatePerNotePitchbendRange (MPEZone&, int);
238 
239  void sendLayoutChangeMessage();
240  void checkAndLimitZoneParameters (int, int, int&) noexcept;
241 };
242 
243 } // namespace juce
virtual void zoneLayoutChanged(const MPEZoneLayout &layout)=0
virtual ~Listener()=default
MPEZone getUpperZone() const noexcept
MPEZoneLayout()=default
MPEZone getLowerZone() const noexcept