Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

juce_MPESynthesiser.h 15KB

8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2016 - ROLI Ltd.
  5. Permission is granted to use this software under the terms of the ISC license
  6. http://www.isc.org/downloads/software-support-policy/isc-license/
  7. Permission to use, copy, modify, and/or distribute this software for any
  8. purpose with or without fee is hereby granted, provided that the above
  9. copyright notice and this permission notice appear in all copies.
  10. THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD
  11. TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  12. FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT,
  13. OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
  14. USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  15. TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
  16. OF THIS SOFTWARE.
  17. -----------------------------------------------------------------------------
  18. To release a closed-source product which uses other parts of JUCE not
  19. licensed under the ISC terms, commercial licenses are available: visit
  20. www.juce.com for more information.
  21. ==============================================================================
  22. */
  23. #ifndef JUCE_MPESynthesiser_H_INCLUDED
  24. #define JUCE_MPESynthesiser_H_INCLUDED
  25. //==============================================================================
  26. /**
  27. Base class for an MPE-compatible musical device that can play sounds.
  28. This class extends MPESynthesiserBase by adding the concept of voices,
  29. each of which can play a sound triggered by a MPENote that can be modulated
  30. by MPE dimensions like pressure, pitchbend, and timbre, while the note is
  31. sounding.
  32. To create a synthesiser, you'll need to create a subclass of MPESynthesiserVoice
  33. which can play back one of these sounds at a time.
  34. Then you can use the addVoice() methods to give the synthesiser a set of voices
  35. it can use to play notes. If you only give it one voice it will be monophonic -
  36. the more voices it has, the more polyphony it'll have available.
  37. Then repeatedly call the renderNextBlock() method to produce the audio (inherited
  38. from MPESynthesiserBase). The voices will be started, stopped, and modulated
  39. automatically, based on the MPE/MIDI messages that the synthesiser receives.
  40. Before rendering, be sure to call the setCurrentPlaybackSampleRate() to tell it
  41. what the target playback rate is. This value is passed on to the voices so that
  42. they can pitch their output correctly.
  43. @see MPESynthesiserBase, MPESythesiserVoice, MPENote, MPEInstrument
  44. */
  45. class JUCE_API MPESynthesiser : public MPESynthesiserBase
  46. {
  47. public:
  48. //==============================================================================
  49. /** Constructor.
  50. You'll need to add some voices before it'll make any sound.
  51. @see addVoice
  52. */
  53. MPESynthesiser();
  54. /** Constructor to pass to the synthesiser a custom MPEInstrument object
  55. to handle the MPE note state, MIDI channel assignment etc.
  56. (in case you need custom logic for this that goes beyond MIDI and MPE).
  57. The synthesiser will take ownership of this object.
  58. @see MPESynthesiserBase, MPEInstrument
  59. */
  60. MPESynthesiser (MPEInstrument* instrument);
  61. /** Destructor. */
  62. ~MPESynthesiser();
  63. //==============================================================================
  64. /** Deletes all voices. */
  65. void clearVoices();
  66. /** Returns the number of voices that have been added. */
  67. int getNumVoices() const noexcept { return voices.size(); }
  68. /** Returns one of the voices that have been added. */
  69. MPESynthesiserVoice* getVoice (int index) const;
  70. /** Adds a new voice to the synth.
  71. All the voices should be the same class of object and are treated equally.
  72. The object passed in will be managed by the synthesiser, which will delete
  73. it later on when no longer needed. The caller should not retain a pointer to the
  74. voice.
  75. */
  76. void addVoice (MPESynthesiserVoice* newVoice);
  77. /** Deletes one of the voices. */
  78. void removeVoice (int index);
  79. /** Reduces the number of voices to newNumVoices.
  80. This will repeatedly call findVoiceToSteal() and remove that voice, until
  81. the total number of voices equals newNumVoices. If newNumVoices is greater than
  82. or equal to the current number of voices, this method does nothing.
  83. */
  84. void reduceNumVoices (int newNumVoices);
  85. /** Release all MPE notes and turn off all voices.
  86. If allowTailOff is true, the voices will be allowed to fade out the notes gracefully
  87. (if they can do). If this is false, the notes will all be cut off immediately.
  88. This method is meant to be called by the user, for example to implement
  89. a MIDI panic button in a synth.
  90. */
  91. virtual void turnOffAllVoices (bool allowTailOff);
  92. //==============================================================================
  93. /** If set to true, then the synth will try to take over an existing voice if
  94. it runs out and needs to play another note.
  95. The value of this boolean is passed into findFreeVoice(), so the result will
  96. depend on the implementation of this method.
  97. */
  98. void setVoiceStealingEnabled (bool shouldSteal) noexcept { shouldStealVoices = shouldSteal; }
  99. /** Returns true if note-stealing is enabled. */
  100. bool isVoiceStealingEnabled() const noexcept { return shouldStealVoices; }
  101. //==============================================================================
  102. /** Tells the synthesiser what the sample rate is for the audio it's being used to render.
  103. This overrides the implementation in MPESynthesiserBase, to additionally
  104. propagate the new value to the voices so that they can use it to render the correct
  105. pitches.
  106. */
  107. void setCurrentPlaybackSampleRate (double newRate) override;
  108. //==============================================================================
  109. /** Handle incoming MIDI events.
  110. This method will be called automatically according to the MIDI data passed
  111. into renderNextBlock(), but you can also call it yourself to manually
  112. inject MIDI events.
  113. This implementation forwards program change messages and non-MPE-related
  114. controller messages to handleProgramChange and handleController, respectively,
  115. and then simply calls through to MPESynthesiserBase::handleMidiEvent to deal
  116. with MPE-related MIDI messages used for MPE notes, zones etc.
  117. This method can be overridden further if you need to do custom MIDI
  118. handling on top of what is provided here.
  119. */
  120. void handleMidiEvent (const MidiMessage&) override;
  121. /** Callback for MIDI controller messages. The default implementation
  122. provided here does nothing; override this method if you need custom
  123. MIDI controller handling on top of MPE.
  124. This method will be called automatically according to the midi data passed into
  125. renderNextBlock().
  126. */
  127. virtual void handleController (int /*midiChannel*/,
  128. int /*controllerNumber*/,
  129. int /*controllerValue*/) {}
  130. /** Callback for MIDI program change messages. The default implementation
  131. provided here does nothing; override this method if you need to handle
  132. those messages.
  133. This method will be called automatically according to the midi data passed into
  134. renderNextBlock().
  135. */
  136. virtual void handleProgramChange (int /*midiChannel*/,
  137. int /*programNumber*/) {}
  138. protected:
  139. //==============================================================================
  140. /** Attempts to start playing a new note.
  141. The default method here will find a free voice that is appropriate for
  142. playing the given MPENote, and use that voice to start playing the sound.
  143. If isNoteStealingEnabled returns true (set this by calling setNoteStealingEnabled),
  144. the synthesiser will use the voice stealing algorithm to find a free voice for
  145. the note (if no voices are free otherwise).
  146. This method will be called automatically according to the midi data passed into
  147. renderNextBlock(). Do not call it yourself, otherwise the internal MPE note state
  148. will become inconsistent.
  149. */
  150. virtual void noteAdded (MPENote newNote) override;
  151. /** Stops playing a note.
  152. This will be called whenever an MPE note is released (either by a note-off message,
  153. or by a sustain/sostenuto pedal release for a note that already received a note-off),
  154. and should therefore stop playing.
  155. This will find any voice that is currently playing finishedNote,
  156. turn its currently playing note off, and call its noteStopped callback.
  157. This method will be called automatically according to the midi data passed into
  158. renderNextBlock(). Do not call it yourself, otherwise the internal MPE note state
  159. will become inconsistent.
  160. */
  161. virtual void noteReleased (MPENote finishedNote) override;
  162. /** Will find any voice that is currently playing changedNote, update its
  163. currently playing note, and call its notePressureChanged method.
  164. This method will be called automatically according to the midi data passed into
  165. renderNextBlock(). Do not call it yourself.
  166. */
  167. virtual void notePressureChanged (MPENote changedNote) override;
  168. /** Will find any voice that is currently playing changedNote, update its
  169. currently playing note, and call its notePitchbendChanged method.
  170. This method will be called automatically according to the midi data passed into
  171. renderNextBlock(). Do not call it yourself.
  172. */
  173. virtual void notePitchbendChanged (MPENote changedNote) override;
  174. /** Will find any voice that is currently playing changedNote, update its
  175. currently playing note, and call its noteTimbreChanged method.
  176. This method will be called automatically according to the midi data passed into
  177. renderNextBlock(). Do not call it yourself.
  178. */
  179. virtual void noteTimbreChanged (MPENote changedNote) override;
  180. /** Will find any voice that is currently playing changedNote, update its
  181. currently playing note, and call its noteKeyStateChanged method.
  182. This method will be called automatically according to the midi data passed into
  183. renderNextBlock(). Do not call it yourself.
  184. */
  185. virtual void noteKeyStateChanged (MPENote changedNote) override;
  186. //==============================================================================
  187. /** This will simply call renderNextBlock for each currently active
  188. voice and fill the buffer with the sum.
  189. Override this method if you need to do more work to render your audio.
  190. */
  191. virtual void renderNextSubBlock (AudioBuffer<float>& outputAudio,
  192. int startSample,
  193. int numSamples) override;
  194. /** This will simply call renderNextBlock for each currently active
  195. voice and fill the buffer with the sum. (souble-precision version)
  196. Override this method if you need to do more work to render your audio.
  197. */
  198. virtual void renderNextSubBlock (AudioBuffer<double>& outputAudio,
  199. int startSample,
  200. int numSamples) override;
  201. //==============================================================================
  202. /** Searches through the voices to find one that's not currently playing, and
  203. which can play the given MPE note.
  204. If all voices are active and stealIfNoneAvailable is false, this returns
  205. a nullptr. If all voices are active and stealIfNoneAvailable is true,
  206. this will call findVoiceToSteal() to find a voice.
  207. If you need to find a free voice for something else than playing a note
  208. (e.g. for deleting it), you can pass an invalid (default-constructed) MPENote.
  209. */
  210. virtual MPESynthesiserVoice* findFreeVoice (MPENote noteToFindVoiceFor,
  211. bool stealIfNoneAvailable) const;
  212. /** Chooses a voice that is most suitable for being re-used to play a new
  213. note, or for being deleted by reduceNumVoices.
  214. The default method will attempt to find the oldest voice that isn't the
  215. bottom or top note being played. If that's not suitable for your synth,
  216. you can override this method and do something more cunning instead.
  217. If you pass a valid MPENote for the optional argument, then the note number
  218. of that note will be taken into account for finding the ideal voice to steal.
  219. If you pass an invalid (default-constructed) MPENote instead, this part of
  220. the algorithm will be ignored.
  221. */
  222. virtual MPESynthesiserVoice* findVoiceToSteal (MPENote noteToStealVoiceFor = MPENote()) const;
  223. /** Starts a specified voice and tells it to play a particular MPENote.
  224. You should never need to call this, it's called internally by
  225. MPESynthesiserBase::instrument via the noteStarted callback,
  226. but is protected in case it's useful for some custom subclasses.
  227. */
  228. void startVoice (MPESynthesiserVoice* voice, MPENote noteToStart);
  229. /** Stops a given voice and tells it to stop playing a particular MPENote
  230. (which should be the same note it is actually playing).
  231. You should never need to call this, it's called internally by
  232. MPESynthesiserBase::instrument via the noteReleased callback,
  233. but is protected in case it's useful for some custom subclasses.
  234. */
  235. void stopVoice (MPESynthesiserVoice* voice, MPENote noteToStop, bool allowTailOff);
  236. //==============================================================================
  237. OwnedArray<MPESynthesiserVoice> voices;
  238. private:
  239. //==============================================================================
  240. bool shouldStealVoices;
  241. CriticalSection voicesLock;
  242. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MPESynthesiser)
  243. };
  244. #endif // JUCE_MPESynthesiser_H_INCLUDED