The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
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.

352 lines
11KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2015 - ROLI Ltd.
  5. Permission is granted to use this software under the terms of either:
  6. a) the GPL v2 (or any later version)
  7. b) the Affero GPL v3
  8. Details of these licenses can be found at: www.gnu.org/licenses
  9. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  10. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  11. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  12. ------------------------------------------------------------------------------
  13. To release a closed-source product which uses JUCE, commercial licenses are
  14. available: visit www.juce.com for more information.
  15. ==============================================================================
  16. */
  17. MPESynthesiser::MPESynthesiser()
  18. {
  19. }
  20. MPESynthesiser::MPESynthesiser (MPEInstrument* instrument) : MPESynthesiserBase (instrument)
  21. {
  22. }
  23. MPESynthesiser::~MPESynthesiser()
  24. {
  25. }
  26. //==============================================================================
  27. void MPESynthesiser::startVoice (MPESynthesiserVoice* voice, MPENote noteToStart)
  28. {
  29. jassert (voice != nullptr);
  30. voice->currentlyPlayingNote = noteToStart;
  31. voice->noteStarted();
  32. }
  33. void MPESynthesiser::stopVoice (MPESynthesiserVoice* voice, MPENote noteToStop, bool allowTailOff)
  34. {
  35. jassert (voice != nullptr);
  36. voice->currentlyPlayingNote = noteToStop;
  37. voice->noteStopped (allowTailOff);
  38. }
  39. //==============================================================================
  40. void MPESynthesiser::noteAdded (MPENote newNote)
  41. {
  42. const ScopedLock sl (voicesLock);
  43. if (MPESynthesiserVoice* voice = findFreeVoice (newNote, shouldStealVoices))
  44. startVoice (voice, newNote);
  45. }
  46. void MPESynthesiser::notePressureChanged (MPENote changedNote)
  47. {
  48. const ScopedLock sl (voicesLock);
  49. for (int i = 0; i < voices.size(); ++i)
  50. {
  51. MPESynthesiserVoice* voice = voices.getUnchecked (i);
  52. if (voice->isCurrentlyPlayingNote (changedNote))
  53. {
  54. voice->currentlyPlayingNote = changedNote;
  55. voice->notePressureChanged();
  56. }
  57. }
  58. }
  59. void MPESynthesiser::notePitchbendChanged (MPENote changedNote)
  60. {
  61. const ScopedLock sl (voicesLock);
  62. for (int i = 0; i < voices.size(); ++i)
  63. {
  64. MPESynthesiserVoice* voice = voices.getUnchecked (i);
  65. if (voice->isCurrentlyPlayingNote (changedNote))
  66. {
  67. voice->currentlyPlayingNote = changedNote;
  68. voice->notePitchbendChanged();
  69. }
  70. }
  71. }
  72. void MPESynthesiser::noteTimbreChanged (MPENote changedNote)
  73. {
  74. const ScopedLock sl (voicesLock);
  75. for (int i = 0; i < voices.size(); ++i)
  76. {
  77. MPESynthesiserVoice* voice = voices.getUnchecked (i);
  78. if (voice->isCurrentlyPlayingNote (changedNote))
  79. {
  80. voice->currentlyPlayingNote = changedNote;
  81. voice->noteTimbreChanged();
  82. }
  83. }
  84. }
  85. void MPESynthesiser::noteKeyStateChanged (MPENote changedNote)
  86. {
  87. const ScopedLock sl (voicesLock);
  88. for (int i = 0; i < voices.size(); ++i)
  89. {
  90. MPESynthesiserVoice* voice = voices.getUnchecked (i);
  91. if (voice->isCurrentlyPlayingNote (changedNote))
  92. {
  93. voice->currentlyPlayingNote = changedNote;
  94. voice->noteKeyStateChanged();
  95. }
  96. }
  97. }
  98. void MPESynthesiser::noteReleased (MPENote finishedNote)
  99. {
  100. const ScopedLock sl (voicesLock);
  101. for (int i = voices.size(); --i >= 0;)
  102. {
  103. MPESynthesiserVoice* const voice = voices.getUnchecked (i);
  104. if (voice->isCurrentlyPlayingNote(finishedNote))
  105. stopVoice (voice, finishedNote, true);
  106. }
  107. }
  108. void MPESynthesiser::setCurrentPlaybackSampleRate (const double newRate)
  109. {
  110. MPESynthesiserBase::setCurrentPlaybackSampleRate (newRate);
  111. const ScopedLock sl (voicesLock);
  112. turnOffAllVoices (false);
  113. for (int i = voices.size(); --i >= 0;)
  114. voices.getUnchecked (i)->setCurrentSampleRate (newRate);
  115. }
  116. void MPESynthesiser::handleMidiEvent (const MidiMessage& m)
  117. {
  118. if (m.isController())
  119. handleController (m.getChannel(), m.getControllerNumber(), m.getControllerValue());
  120. else if (m.isProgramChange())
  121. handleProgramChange (m.getChannel(), m.getProgramChangeNumber());
  122. MPESynthesiserBase::handleMidiEvent (m);
  123. }
  124. MPESynthesiserVoice* MPESynthesiser::findFreeVoice (MPENote noteToFindVoiceFor, bool stealIfNoneAvailable) const
  125. {
  126. const ScopedLock sl (voicesLock);
  127. for (int i = 0; i < voices.size(); ++i)
  128. {
  129. MPESynthesiserVoice* const voice = voices.getUnchecked (i);
  130. if (! voice->isActive())
  131. return voice;
  132. }
  133. if (stealIfNoneAvailable)
  134. return findVoiceToSteal (noteToFindVoiceFor);
  135. return nullptr;
  136. }
  137. struct MPEVoiceAgeSorter
  138. {
  139. static int compareElements (MPESynthesiserVoice* v1, MPESynthesiserVoice* v2) noexcept
  140. {
  141. return v1->wasStartedBefore (*v2) ? -1 : (v2->wasStartedBefore (*v1) ? 1 : 0);
  142. }
  143. };
  144. MPESynthesiserVoice* MPESynthesiser::findVoiceToSteal (MPENote noteToStealVoiceFor) const
  145. {
  146. // This voice-stealing algorithm applies the following heuristics:
  147. // - Re-use the oldest notes first
  148. // - Protect the lowest & topmost notes, even if sustained, but not if they've been released.
  149. // These are the voices we want to protect (ie: only steal if unavoidable)
  150. MPESynthesiserVoice* low = nullptr; // Lowest sounding note, might be sustained, but NOT in release phase
  151. MPESynthesiserVoice* top = nullptr; // Highest sounding note, might be sustained, but NOT in release phase
  152. // this is a list of voices we can steal, sorted by how long they've been running
  153. Array<MPESynthesiserVoice*> usableVoices;
  154. usableVoices.ensureStorageAllocated (voices.size());
  155. for (int i = 0; i < voices.size(); ++i)
  156. {
  157. MPESynthesiserVoice* const voice = voices.getUnchecked (i);
  158. jassert (voice->isActive()); // We wouldn't be here otherwise
  159. MPEVoiceAgeSorter sorter;
  160. usableVoices.addSorted (sorter, voice);
  161. if (! voice->isPlayingButReleased()) // Don't protect released notes
  162. {
  163. const int noteNumber = voice->getCurrentlyPlayingNote().initialNote;
  164. if (low == nullptr || noteNumber < low->getCurrentlyPlayingNote().initialNote)
  165. low = voice;
  166. if (top == nullptr || noteNumber > top->getCurrentlyPlayingNote().initialNote)
  167. top = voice;
  168. }
  169. }
  170. // Eliminate pathological cases (ie: only 1 note playing): we always give precedence to the lowest note(s)
  171. if (top == low)
  172. top = nullptr;
  173. const int numUsableVoices = usableVoices.size();
  174. // If we want to re-use the voice to trigger a new note,
  175. // then The oldest note that's playing the same note number is ideal.
  176. if (noteToStealVoiceFor.isValid())
  177. {
  178. for (int i = 0; i < numUsableVoices; ++i)
  179. {
  180. MPESynthesiserVoice* const voice = usableVoices.getUnchecked (i);
  181. if (voice->getCurrentlyPlayingNote().initialNote == noteToStealVoiceFor.initialNote)
  182. return voice;
  183. }
  184. }
  185. // Oldest voice that has been released (no finger on it and not held by sustain pedal)
  186. for (int i = 0; i < numUsableVoices; ++i)
  187. {
  188. MPESynthesiserVoice* const voice = usableVoices.getUnchecked (i);
  189. if (voice != low && voice != top && voice->isPlayingButReleased())
  190. return voice;
  191. }
  192. // Oldest voice that doesn't have a finger on it:
  193. for (int i = 0; i < numUsableVoices; ++i)
  194. {
  195. MPESynthesiserVoice* const voice = usableVoices.getUnchecked (i);
  196. if (voice != low && voice != top
  197. && voice->getCurrentlyPlayingNote().keyState != MPENote::keyDown
  198. && voice->getCurrentlyPlayingNote().keyState != MPENote::keyDownAndSustained)
  199. return voice;
  200. }
  201. // Oldest voice that isn't protected
  202. for (int i = 0; i < numUsableVoices; ++i)
  203. {
  204. MPESynthesiserVoice* const voice = usableVoices.getUnchecked (i);
  205. if (voice != low && voice != top)
  206. return voice;
  207. }
  208. // We've only got "protected" voices now: lowest note takes priority
  209. jassert (low != nullptr);
  210. // Duophonic synth: give priority to the bass note:
  211. if (top != nullptr)
  212. return top;
  213. return low;
  214. }
  215. //==============================================================================
  216. void MPESynthesiser::addVoice (MPESynthesiserVoice* const newVoice)
  217. {
  218. const ScopedLock sl (voicesLock);
  219. voices.add (newVoice);
  220. }
  221. void MPESynthesiser::clearVoices()
  222. {
  223. const ScopedLock sl (voicesLock);
  224. voices.clear();
  225. }
  226. MPESynthesiserVoice* MPESynthesiser::getVoice (const int index) const
  227. {
  228. const ScopedLock sl (voicesLock);
  229. return voices [index];
  230. }
  231. void MPESynthesiser::removeVoice (const int index)
  232. {
  233. const ScopedLock sl (voicesLock);
  234. voices.remove (index);
  235. }
  236. void MPESynthesiser::reduceNumVoices (const int newNumVoices)
  237. {
  238. // we can't possibly get to a negative number of voices...
  239. jassert (newNumVoices >= 0);
  240. const ScopedLock sl (voicesLock);
  241. while (voices.size() > newNumVoices)
  242. {
  243. if (MPESynthesiserVoice* voice = findVoiceToSteal())
  244. voices.removeObject (voice);
  245. else
  246. voices.remove (0); // if there's no voice to steal, kill the oldest voice
  247. }
  248. }
  249. void MPESynthesiser::turnOffAllVoices (bool allowTailOff)
  250. {
  251. // first turn off all voices (it's more efficient to do this immediately
  252. // rather than to go through the MPEInstrument for this).
  253. for (int i = voices.size(); --i >= 0;)
  254. voices.getUnchecked (i)->noteStopped (allowTailOff);
  255. // finally make sure the MPE Instrument also doesn't have any notes anymore.
  256. instrument->releaseAllNotes();
  257. }
  258. //==============================================================================
  259. void MPESynthesiser::renderNextSubBlock (AudioBuffer<float>& buffer, int startSample, int numSamples)
  260. {
  261. for (int i = voices.size(); --i >= 0;)
  262. {
  263. MPESynthesiserVoice* voice = voices.getUnchecked (i);
  264. if (voice->isActive())
  265. voice->renderNextBlock (buffer, startSample, numSamples);
  266. }
  267. }
  268. void MPESynthesiser::renderNextSubBlock (AudioBuffer<double>& buffer, int startSample, int numSamples)
  269. {
  270. for (int i = voices.size(); --i >= 0;)
  271. {
  272. MPESynthesiserVoice* voice = voices.getUnchecked (i);
  273. if (voice->isActive())
  274. voice->renderNextBlock (buffer, startSample, numSamples);
  275. }
  276. }