OpenShot Library | libopenshot-audio  0.1.9
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 
27 namespace 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 {
60 public:
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* instrument);
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 
181 protected:
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. (souble-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 
308 private:
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 /** @}*/
#define JUCE_API
This macro is added to all JUCE public class declarations.
Base class for an MPE-compatible musical device that can play sounds.
Encapsulates a MIDI message.
int getNumVoices() const noexcept
Returns the number of voices that have been added.
bool isVoiceStealingEnabled() const noexcept
Returns true if note-stealing is enabled.
Represents an MPE voice that an MPESynthesiser can use to play a sound.
A re-entrant mutex.
Derive from this class to create a basic audio generator capable of MPE.
This struct represents a playing MPE note.
Definition: juce_MPENote.h:43
virtual void handleController(int, int, int)
Callback for MIDI controller messages.
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.
An array designed for holding objects.
This class represents an instrument handling MPE.