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