OpenShot Library | OpenShotAudio 0.2.2
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
27namespace 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{
50public:
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 isUsing (int channel) const noexcept
106 {
107 return isUsingChannelAsMemberChannel (channel) || channel == getMasterChannel();
108 }
109
110 bool operator== (const Zone& other) const noexcept { return lowerZone == other.lowerZone
111 && numMemberChannels == other.numMemberChannels
112 && perNotePitchbendRange == other.perNotePitchbendRange
113 && masterPitchbendRange == other.masterPitchbendRange; }
114
115 bool operator!= (const Zone& other) const noexcept { return ! operator== (other); }
116
117 int numMemberChannels;
118 int perNotePitchbendRange;
119 int masterPitchbendRange;
120
121 private:
122 friend class MPEZoneLayout;
123
124 Zone (bool lower, int memberChans = 0, int perNotePb = 48, int masterPb = 2) noexcept
125 : numMemberChannels (memberChans),
126 perNotePitchbendRange (perNotePb),
127 masterPitchbendRange (masterPb),
128 lowerZone (lower)
129 {
130 }
131
132 bool lowerZone;
133 };
134
135 /** Sets the lower zone of this layout. */
136 void setLowerZone (int numMemberChannels = 0,
137 int perNotePitchbendRange = 48,
138 int masterPitchbendRange = 2) noexcept;
139
140 /** Sets the upper zone of this layout. */
141 void setUpperZone (int numMemberChannels = 0,
142 int perNotePitchbendRange = 48,
143 int masterPitchbendRange = 2) noexcept;
144
145 /** Returns a struct representing the lower MPE zone. */
146 const Zone getLowerZone() const noexcept { return lowerZone; }
147
148 /** Returns a struct representing the upper MPE zone. */
149 const Zone getUpperZone() const noexcept { return upperZone; }
150
151 /** Clears the lower and upper zones of this layout, making them both inactive
152 and disabling MPE mode.
153 */
154 void clearAllZones();
155
156 //==============================================================================
157 /** Pass incoming MIDI messages to an object of this class if you want the
158 zone layout to properly react to MPE RPN messages like an
159 MPE device.
160
161 MPEMessages::rpnNumber will add or remove zones; RPN 0 will
162 set the per-note or master pitchbend ranges.
163
164 Any other MIDI messages will be ignored by this class.
165
166 @see MPEMessages
167 */
168 void processNextMidiEvent (const MidiMessage& message);
169
170 /** Pass incoming MIDI buffers to an object of this class if you want the
171 zone layout to properly react to MPE RPN messages like an
172 MPE device.
173
174 MPEMessages::rpnNumber will add or remove zones; RPN 0 will
175 set the per-note or master pitchbend ranges.
176
177 Any other MIDI messages will be ignored by this class.
178
179 @see MPEMessages
180 */
181 void processNextMidiBuffer (const MidiBuffer& buffer);
182
183 //==============================================================================
184 /** Listener class. Derive from this class to allow your class to be
185 notified about changes to the zone layout.
186 */
188 {
189 public:
190 /** Destructor. */
191 virtual ~Listener() = default;
192
193 /** Implement this callback to be notified about any changes to this
194 MPEZoneLayout. Will be called whenever a zone is added, zones are
195 removed, or any zone's master or note pitchbend ranges change.
196 */
197 virtual void zoneLayoutChanged (const MPEZoneLayout& layout) = 0;
198 };
199
200 //==============================================================================
201 /** Adds a listener. */
202 void addListener (Listener* const listenerToAdd) noexcept;
203
204 /** Removes a listener. */
205 void removeListener (Listener* const listenerToRemove) noexcept;
206
207private:
208 //==============================================================================
209 Zone lowerZone { true, 0 };
210 Zone upperZone { false, 0 };
211
212 MidiRPNDetector rpnDetector;
213 ListenerList<Listener> listeners;
214
215 //==============================================================================
216 void setZone (bool, int, int, int) noexcept;
217
218 void processRpnMessage (MidiRPNMessage);
219 void processZoneLayoutRpnMessage (MidiRPNMessage);
220 void processPitchbendRangeRpnMessage (MidiRPNMessage);
221
222 void updateMasterPitchbend (Zone&, int);
223 void updatePerNotePitchbendRange (Zone&, int);
224
225 void sendLayoutChangeMessage();
226 void checkAndLimitZoneParameters (int, int, int&) noexcept;
227};
228
229} // namespace juce
230
231/** @}*/
virtual void zoneLayoutChanged(const MPEZoneLayout &layout)=0
Implement this callback to be notified about any changes to this MPEZoneLayout.
virtual ~Listener()=default
Destructor.
This class represents the current MPE zone layout of a device capable of handling MPE.
const Zone getUpperZone() const noexcept
Returns a struct representing the upper MPE zone.
Holds a sequence of time-stamped midi events.
Encapsulates a MIDI message.
#define JUCE_API
This macro is added to all JUCE public class declarations.
This struct represents an MPE zone.