OpenShot Library | OpenShotAudio 0.2.2
juce_MPESynthesiser.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 Base class for an MPE-compatible musical device that can play sounds.
33
34 This class extends MPESynthesiserBase by adding the concept of voices,
35 each of which can play a sound triggered by a MPENote that can be modulated
36 by MPE dimensions like pressure, pitchbend, and timbre, while the note is
37 sounding.
38
39 To create a synthesiser, you'll need to create a subclass of MPESynthesiserVoice
40 which can play back one of these sounds at a time.
41
42 Then you can use the addVoice() methods to give the synthesiser a set of voices
43 it can use to play notes. If you only give it one voice it will be monophonic -
44 the more voices it has, the more polyphony it'll have available.
45
46 Then repeatedly call the renderNextBlock() method to produce the audio (inherited
47 from MPESynthesiserBase). The voices will be started, stopped, and modulated
48 automatically, based on the MPE/MIDI messages that the synthesiser receives.
49
50 Before rendering, be sure to call the setCurrentPlaybackSampleRate() to tell it
51 what the target playback rate is. This value is passed on to the voices so that
52 they can pitch their output correctly.
53
54 @see MPESynthesiserBase, MPESynthesiserVoice, MPENote, MPEInstrument
55
56 @tags{Audio}
57*/
59{
60public:
61 //==============================================================================
62 /** Constructor.
63 You'll need to add some voices before it'll make any sound.
64
65 @see addVoice
66 */
68
69 /** Constructor to pass to the synthesiser a custom MPEInstrument object
70 to handle the MPE note state, MIDI channel assignment etc.
71 (in case you need custom logic for this that goes beyond MIDI and MPE).
72 The synthesiser will take ownership of this object.
73
74 @see MPESynthesiserBase, MPEInstrument
75 */
76 MPESynthesiser (MPEInstrument* instrumentToUse);
77
78 /** Destructor. */
79 ~MPESynthesiser() override;
80
81 //==============================================================================
82 /** Deletes all voices. */
83 void clearVoices();
84
85 /** Returns the number of voices that have been added. */
86 int getNumVoices() const noexcept { return voices.size(); }
87
88 /** Returns one of the voices that have been added. */
89 MPESynthesiserVoice* getVoice (int index) const;
90
91 /** Adds a new voice to the synth.
92
93 All the voices should be the same class of object and are treated equally.
94
95 The object passed in will be managed by the synthesiser, which will delete
96 it later on when no longer needed. The caller should not retain a pointer to the
97 voice.
98 */
99 void addVoice (MPESynthesiserVoice* newVoice);
100
101 /** Deletes one of the voices. */
102 void removeVoice (int index);
103
104 /** Reduces the number of voices to newNumVoices.
105
106 This will repeatedly call findVoiceToSteal() and remove that voice, until
107 the total number of voices equals newNumVoices. If newNumVoices is greater than
108 or equal to the current number of voices, this method does nothing.
109 */
110 void reduceNumVoices (int newNumVoices);
111
112 /** Release all MPE notes and turn off all voices.
113
114 If allowTailOff is true, the voices will be allowed to fade out the notes gracefully
115 (if they can do). If this is false, the notes will all be cut off immediately.
116
117 This method is meant to be called by the user, for example to implement
118 a MIDI panic button in a synth.
119 */
120 virtual void turnOffAllVoices (bool allowTailOff);
121
122 //==============================================================================
123 /** If set to true, then the synth will try to take over an existing voice if
124 it runs out and needs to play another note.
125
126 The value of this boolean is passed into findFreeVoice(), so the result will
127 depend on the implementation of this method.
128 */
129 void setVoiceStealingEnabled (bool shouldSteal) noexcept { shouldStealVoices = shouldSteal; }
130
131 /** Returns true if note-stealing is enabled. */
132 bool isVoiceStealingEnabled() const noexcept { return shouldStealVoices; }
133
134 //==============================================================================
135 /** Tells the synthesiser what the sample rate is for the audio it's being used to render.
136
137 This overrides the implementation in MPESynthesiserBase, to additionally
138 propagate the new value to the voices so that they can use it to render the correct
139 pitches.
140 */
141 void setCurrentPlaybackSampleRate (double newRate) override;
142
143 //==============================================================================
144 /** Handle incoming MIDI events.
145
146 This method will be called automatically according to the MIDI data passed
147 into renderNextBlock(), but you can also call it yourself to manually
148 inject MIDI events.
149
150 This implementation forwards program change messages and non-MPE-related
151 controller messages to handleProgramChange and handleController, respectively,
152 and then simply calls through to MPESynthesiserBase::handleMidiEvent to deal
153 with MPE-related MIDI messages used for MPE notes, zones etc.
154
155 This method can be overridden further if you need to do custom MIDI
156 handling on top of what is provided here.
157 */
158 void handleMidiEvent (const MidiMessage&) override;
159
160 /** Callback for MIDI controller messages. The default implementation
161 provided here does nothing; override this method if you need custom
162 MIDI controller handling on top of MPE.
163
164 This method will be called automatically according to the midi data passed into
165 renderNextBlock().
166 */
167 virtual void handleController (int /*midiChannel*/,
168 int /*controllerNumber*/,
169 int /*controllerValue*/) {}
170
171 /** Callback for MIDI program change messages. The default implementation
172 provided here does nothing; override this method if you need to handle
173 those messages.
174
175 This method will be called automatically according to the midi data passed into
176 renderNextBlock().
177 */
178 virtual void handleProgramChange (int /*midiChannel*/,
179 int /*programNumber*/) {}
180
181protected:
182 //==============================================================================
183 /** Attempts to start playing a new note.
184
185 The default method here will find a free voice that is appropriate for
186 playing the given MPENote, and use that voice to start playing the sound.
187 If isNoteStealingEnabled returns true (set this by calling setNoteStealingEnabled),
188 the synthesiser will use the voice stealing algorithm to find a free voice for
189 the note (if no voices are free otherwise).
190
191 This method will be called automatically according to the midi data passed into
192 renderNextBlock(). Do not call it yourself, otherwise the internal MPE note state
193 will become inconsistent.
194 */
195 void noteAdded (MPENote newNote) override;
196
197 /** Stops playing a note.
198
199 This will be called whenever an MPE note is released (either by a note-off message,
200 or by a sustain/sostenuto pedal release for a note that already received a note-off),
201 and should therefore stop playing.
202
203 This will find any voice that is currently playing finishedNote,
204 turn its currently playing note off, and call its noteStopped callback.
205
206 This method will be called automatically according to the midi data passed into
207 renderNextBlock(). Do not call it yourself, otherwise the internal MPE note state
208 will become inconsistent.
209 */
210 void noteReleased (MPENote finishedNote) override;
211
212 /** Will find any voice that is currently playing changedNote, update its
213 currently playing note, and call its notePressureChanged method.
214
215 This method will be called automatically according to the midi data passed into
216 renderNextBlock(). Do not call it yourself.
217 */
218 void notePressureChanged (MPENote changedNote) override;
219
220 /** Will find any voice that is currently playing changedNote, update its
221 currently playing note, and call its notePitchbendChanged method.
222
223 This method will be called automatically according to the midi data passed into
224 renderNextBlock(). Do not call it yourself.
225 */
226 void notePitchbendChanged (MPENote changedNote) override;
227
228 /** Will find any voice that is currently playing changedNote, update its
229 currently playing note, and call its noteTimbreChanged method.
230
231 This method will be called automatically according to the midi data passed into
232 renderNextBlock(). Do not call it yourself.
233 */
234 void noteTimbreChanged (MPENote changedNote) override;
235
236 /** Will find any voice that is currently playing changedNote, update its
237 currently playing note, and call its noteKeyStateChanged method.
238
239 This method will be called automatically according to the midi data passed into
240 renderNextBlock(). Do not call it yourself.
241 */
242 void noteKeyStateChanged (MPENote changedNote) override;
243
244 //==============================================================================
245 /** This will simply call renderNextBlock for each currently active
246 voice and fill the buffer with the sum.
247 Override this method if you need to do more work to render your audio.
248 */
249 void renderNextSubBlock (AudioBuffer<float>& outputAudio,
250 int startSample,
251 int numSamples) override;
252
253 /** This will simply call renderNextBlock for each currently active
254 voice and fill the buffer with the sum. (double-precision version)
255 Override this method if you need to do more work to render your audio.
256 */
257 void renderNextSubBlock (AudioBuffer<double>& outputAudio,
258 int startSample,
259 int numSamples) override;
260
261 //==============================================================================
262 /** Searches through the voices to find one that's not currently playing, and
263 which can play the given MPE note.
264
265 If all voices are active and stealIfNoneAvailable is false, this returns
266 a nullptr. If all voices are active and stealIfNoneAvailable is true,
267 this will call findVoiceToSteal() to find a voice.
268
269 If you need to find a free voice for something else than playing a note
270 (e.g. for deleting it), you can pass an invalid (default-constructed) MPENote.
271 */
272 virtual MPESynthesiserVoice* findFreeVoice (MPENote noteToFindVoiceFor,
273 bool stealIfNoneAvailable) const;
274
275 /** Chooses a voice that is most suitable for being re-used to play a new
276 note, or for being deleted by reduceNumVoices.
277
278 The default method will attempt to find the oldest voice that isn't the
279 bottom or top note being played. If that's not suitable for your synth,
280 you can override this method and do something more cunning instead.
281
282 If you pass a valid MPENote for the optional argument, then the note number
283 of that note will be taken into account for finding the ideal voice to steal.
284 If you pass an invalid (default-constructed) MPENote instead, this part of
285 the algorithm will be ignored.
286 */
287 virtual MPESynthesiserVoice* findVoiceToSteal (MPENote noteToStealVoiceFor = MPENote()) const;
288
289 /** Starts a specified voice and tells it to play a particular MPENote.
290 You should never need to call this, it's called internally by
291 MPESynthesiserBase::instrument via the noteStarted callback,
292 but is protected in case it's useful for some custom subclasses.
293 */
294 void startVoice (MPESynthesiserVoice* voice, MPENote noteToStart);
295
296 /** Stops a given voice and tells it to stop playing a particular MPENote
297 (which should be the same note it is actually playing).
298 You should never need to call this, it's called internally by
299 MPESynthesiserBase::instrument via the noteReleased callback,
300 but is protected in case it's useful for some custom subclasses.
301 */
302 void stopVoice (MPESynthesiserVoice* voice, MPENote noteToStop, bool allowTailOff);
303
304 //==============================================================================
306 CriticalSection voicesLock;
307
308private:
309 //==============================================================================
310 bool shouldStealVoices = false;
311 uint32 lastNoteOnCounter = 0;
312
313 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MPESynthesiser)
314};
315
316} // namespace juce
317
318/** @}*/
A re-entrant mutex.
This class represents an instrument handling MPE.
Represents an MPE voice that an MPESynthesiser can use to play a sound.
Base class for an MPE-compatible musical device that can play sounds.
bool isVoiceStealingEnabled() const noexcept
Returns true if note-stealing is enabled.
int getNumVoices() const noexcept
Returns the number of voices that have been added.
void setVoiceStealingEnabled(bool shouldSteal) noexcept
If set to true, then the synth will try to take over an existing voice if it runs out and needs to pl...
virtual void handleProgramChange(int, int)
Callback for MIDI program change messages.
virtual void handleController(int, int, int)
Callback for MIDI controller messages.
Encapsulates a MIDI message.
An array designed for holding objects.
#define JUCE_API
This macro is added to all JUCE public class declarations.
This struct represents a playing MPE note.
Definition: juce_MPENote.h:44
Derive from this class to create a basic audio generator capable of MPE.