OpenShot Library | libopenshot-audio  0.2.0
juce_MPEZoneLayout.h
1 
2 /** @weakgroup juce_audio_basics-mpe
3  * @{
4  */
5 /*
6  ==============================================================================
7 
8  This file is part of the JUCE library.
9  Copyright (c) 2017 - ROLI Ltd.
10 
11  JUCE is an open source library subject to commercial or open-source
12  licensing.
13 
14  The code included in this file is provided under the terms of the ISC license
15  http://www.isc.org/downloads/software-support-policy/isc-license. Permission
16  To use, copy, modify, and/or distribute this software for any purpose with or
17  without fee is hereby granted provided that the above copyright notice and
18  this permission notice appear in all copies.
19 
20  JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
21  EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
22  DISCLAIMED.
23 
24  ==============================================================================
25 */
26 
27 namespace juce
28 {
29 
30 //==============================================================================
31 /**
32  This class represents the current MPE zone layout of a device capable of handling MPE.
33 
34  An MPE device can have up to two zones: a lower zone with master channel 1 and
35  allocated MIDI channels increasing from channel 2, and an upper zone with master
36  channel 16 and allocated MIDI channels decreasing from channel 15. MPE mode is
37  enabled on a device when one of these zones is active and disabled when both
38  are inactive.
39 
40  Use the MPEMessages helper class to convert the zone layout represented
41  by this object to MIDI message sequences that you can send to an Expressive
42  MIDI device to set its zone layout, add zones etc.
43 
44  @see MPEInstrument
45 
46  @tags{Audio}
47 */
49 {
50 public:
51  /** Default constructor.
52 
53  This will create a layout with inactive lower and upper zones, representing
54  a device with MPE mode disabled.
55 
56  You can set the lower or upper MPE zones using the setZone() method.
57 
58  @see setZone
59  */
60  MPEZoneLayout() noexcept;
61 
62  /** Copy constuctor.
63  This will not copy the listeners registered to the MPEZoneLayout.
64  */
65  MPEZoneLayout (const MPEZoneLayout& other);
66 
67  /** Copy assignment operator.
68  This will not copy the listeners registered to the MPEZoneLayout.
69  */
70  MPEZoneLayout& operator= (const MPEZoneLayout& other);
71 
72  //==============================================================================
73  /**
74  This struct represents an MPE zone.
75 
76  It can either be a lower or an upper zone, where:
77  - A lower zone encompasses master channel 1 and an arbitrary number of ascending
78  MIDI channels, increasing from channel 2.
79  - An upper zone encompasses master channel 16 and an arbitrary number of descending
80  MIDI channels, decreasing from channel 15.
81 
82  It also defines a pitchbend range (in semitones) to be applied for per-note pitchbends and
83  master pitchbends, respectively.
84  */
85  struct Zone
86  {
87  Zone (const Zone& other) = default;
88 
89  bool isLowerZone() const noexcept { return lowerZone; }
90  bool isUpperZone() const noexcept { return ! lowerZone; }
91 
92  bool isActive() const noexcept { return numMemberChannels > 0; }
93 
94  int getMasterChannel() const noexcept { return lowerZone ? 1 : 16; }
95  int getFirstMemberChannel() const noexcept { return lowerZone ? 2 : 15; }
96  int getLastMemberChannel() const noexcept { return lowerZone ? (1 + numMemberChannels)
97  : (16 - numMemberChannels); }
98 
99  bool isUsingChannelAsMemberChannel (int channel) const noexcept
100  {
101  return lowerZone ? (channel > 1 && channel <= 1 + numMemberChannels)
102  : (channel < 16 && channel >= 16 - numMemberChannels);
103  }
104 
105  bool operator== (const Zone& other) const noexcept { return lowerZone == other.lowerZone
106  && numMemberChannels == other.numMemberChannels
107  && perNotePitchbendRange == other.perNotePitchbendRange
108  && masterPitchbendRange == other.masterPitchbendRange; }
109 
110  bool operator!= (const Zone& other) const noexcept { return ! operator== (other); }
111 
112  int numMemberChannels;
113  int perNotePitchbendRange;
114  int masterPitchbendRange;
115 
116  private:
117  friend class MPEZoneLayout;
118 
119  Zone (bool lower, int memberChans = 0, int perNotePb = 48, int masterPb = 2) noexcept
120  : numMemberChannels (memberChans),
121  perNotePitchbendRange (perNotePb),
122  masterPitchbendRange (masterPb),
123  lowerZone (lower)
124  {
125  }
126 
127  bool lowerZone;
128  };
129 
130  /** Sets the lower zone of this layout. */
131  void setLowerZone (int numMemberChannels = 0,
132  int perNotePitchbendRange = 48,
133  int masterPitchbendRange = 2) noexcept;
134 
135  /** Sets the upper zone of this layout. */
136  void setUpperZone (int numMemberChannels = 0,
137  int perNotePitchbendRange = 48,
138  int masterPitchbendRange = 2) noexcept;
139 
140  /** Returns a struct representing the lower MPE zone. */
141  const Zone getLowerZone() const noexcept { return lowerZone; }
142 
143  /** Returns a struct representing the upper MPE zone. */
144  const Zone getUpperZone() const noexcept { return upperZone; }
145 
146  /** Clears the lower and upper zones of this layout, making them both inactive
147  and disabling MPE mode.
148  */
149  void clearAllZones();
150 
151  //==============================================================================
152  /** Pass incoming MIDI messages to an object of this class if you want the
153  zone layout to properly react to MPE RPN messages like an
154  MPE device.
155 
156  MPEMessages::rpnNumber will add or remove zones; RPN 0 will
157  set the per-note or master pitchbend ranges.
158 
159  Any other MIDI messages will be ignored by this class.
160 
161  @see MPEMessages
162  */
163  void processNextMidiEvent (const MidiMessage& message);
164 
165  /** Pass incoming MIDI buffers to an object of this class if you want the
166  zone layout to properly react to MPE RPN messages like an
167  MPE device.
168 
169  MPEMessages::rpnNumber will add or remove zones; RPN 0 will
170  set the per-note or master pitchbend ranges.
171 
172  Any other MIDI messages will be ignored by this class.
173 
174  @see MPEMessages
175  */
176  void processNextMidiBuffer (const MidiBuffer& buffer);
177 
178  //==============================================================================
179  /** Listener class. Derive from this class to allow your class to be
180  notified about changes to the zone layout.
181  */
182  class Listener
183  {
184  public:
185  /** Destructor. */
186  virtual ~Listener() = default;
187 
188  /** Implement this callback to be notified about any changes to this
189  MPEZoneLayout. Will be called whenever a zone is added, zones are
190  removed, or any zone's master or note pitchbend ranges change.
191  */
192  virtual void zoneLayoutChanged (const MPEZoneLayout& layout) = 0;
193  };
194 
195  //==============================================================================
196  /** Adds a listener. */
197  void addListener (Listener* const listenerToAdd) noexcept;
198 
199  /** Removes a listener. */
200  void removeListener (Listener* const listenerToRemove) noexcept;
201 
202 private:
203  //==============================================================================
204  Zone lowerZone { true, 0 };
205  Zone upperZone { false, 0 };
206 
207  MidiRPNDetector rpnDetector;
208  ListenerList<Listener> listeners;
209 
210  //==============================================================================
211  void setZone (bool, int, int, int) noexcept;
212 
213  void processRpnMessage (MidiRPNMessage);
214  void processZoneLayoutRpnMessage (MidiRPNMessage);
215  void processPitchbendRangeRpnMessage (MidiRPNMessage);
216 
217  void updateMasterPitchbend (Zone&, int);
218  void updatePerNotePitchbendRange (Zone&, int);
219 
220  void sendLayoutChangeMessage();
221  void checkAndLimitZoneParameters (int, int, int&) noexcept;
222 };
223 
224 } // namespace juce
225 
226 /** @}*/
JUCE_API
#define JUCE_API
This macro is added to all JUCE public class declarations.
Definition: juce_StandardHeader.h:143
juce::MidiBuffer
Holds a sequence of time-stamped midi events.
Definition: juce_MidiBuffer.h:46
juce::MPEZoneLayout
This class represents the current MPE zone layout of a device capable of handling MPE.
Definition: juce_MPEZoneLayout.h:48
juce::MidiMessage
Encapsulates a MIDI message.
Definition: juce_MidiMessage.h:38
juce::MPEZoneLayout::Listener
Listener class.
Definition: juce_MPEZoneLayout.h:182
juce::MPEZoneLayout::getUpperZone
const Zone getUpperZone() const noexcept
Returns a struct representing the upper MPE zone.
Definition: juce_MPEZoneLayout.h:144
juce::MPEZoneLayout::Zone
This struct represents an MPE zone.
Definition: juce_MPEZoneLayout.h:85