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.

577 lines
18KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2013 - Raw Material Software 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. SynthesiserSound::SynthesiserSound() {}
  18. SynthesiserSound::~SynthesiserSound() {}
  19. //==============================================================================
  20. SynthesiserVoice::SynthesiserVoice()
  21. : currentSampleRate (44100.0),
  22. currentlyPlayingNote (-1),
  23. currentPlayingMidiChannel (0),
  24. noteOnTime (0),
  25. keyIsDown (false),
  26. sostenutoPedalDown (false)
  27. {
  28. }
  29. SynthesiserVoice::~SynthesiserVoice()
  30. {
  31. }
  32. bool SynthesiserVoice::isPlayingChannel (const int midiChannel) const
  33. {
  34. return currentPlayingMidiChannel == midiChannel;
  35. }
  36. void SynthesiserVoice::setCurrentPlaybackSampleRate (const double newRate)
  37. {
  38. currentSampleRate = newRate;
  39. }
  40. bool SynthesiserVoice::isVoiceActive() const
  41. {
  42. return getCurrentlyPlayingNote() >= 0;
  43. }
  44. void SynthesiserVoice::clearCurrentNote()
  45. {
  46. currentlyPlayingNote = -1;
  47. currentlyPlayingSound = nullptr;
  48. currentPlayingMidiChannel = 0;
  49. }
  50. void SynthesiserVoice::aftertouchChanged (int) {}
  51. void SynthesiserVoice::channelPressureChanged (int) {}
  52. bool SynthesiserVoice::wasStartedBefore (const SynthesiserVoice& other) const noexcept
  53. {
  54. return noteOnTime < other.noteOnTime;
  55. }
  56. //==============================================================================
  57. Synthesiser::Synthesiser()
  58. : sampleRate (0),
  59. lastNoteOnCounter (0),
  60. minimumSubBlockSize (32),
  61. shouldStealNotes (true)
  62. {
  63. for (int i = 0; i < numElementsInArray (lastPitchWheelValues); ++i)
  64. lastPitchWheelValues[i] = 0x2000;
  65. }
  66. Synthesiser::~Synthesiser()
  67. {
  68. }
  69. //==============================================================================
  70. SynthesiserVoice* Synthesiser::getVoice (const int index) const
  71. {
  72. const ScopedLock sl (lock);
  73. return voices [index];
  74. }
  75. void Synthesiser::clearVoices()
  76. {
  77. const ScopedLock sl (lock);
  78. voices.clear();
  79. }
  80. SynthesiserVoice* Synthesiser::addVoice (SynthesiserVoice* const newVoice)
  81. {
  82. const ScopedLock sl (lock);
  83. return voices.add (newVoice);
  84. }
  85. void Synthesiser::removeVoice (const int index)
  86. {
  87. const ScopedLock sl (lock);
  88. voices.remove (index);
  89. }
  90. void Synthesiser::clearSounds()
  91. {
  92. const ScopedLock sl (lock);
  93. sounds.clear();
  94. }
  95. SynthesiserSound* Synthesiser::addSound (const SynthesiserSound::Ptr& newSound)
  96. {
  97. const ScopedLock sl (lock);
  98. return sounds.add (newSound);
  99. }
  100. void Synthesiser::removeSound (const int index)
  101. {
  102. const ScopedLock sl (lock);
  103. sounds.remove (index);
  104. }
  105. void Synthesiser::setNoteStealingEnabled (const bool shouldSteal)
  106. {
  107. shouldStealNotes = shouldSteal;
  108. }
  109. void Synthesiser::setMinimumRenderingSubdivisionSize (int numSamples) noexcept
  110. {
  111. jassert (numSamples > 0); // it wouldn't make much sense for this to be less than 1
  112. minimumSubBlockSize = numSamples;
  113. }
  114. //==============================================================================
  115. void Synthesiser::setCurrentPlaybackSampleRate (const double newRate)
  116. {
  117. if (sampleRate != newRate)
  118. {
  119. const ScopedLock sl (lock);
  120. allNotesOff (0, false);
  121. sampleRate = newRate;
  122. for (int i = voices.size(); --i >= 0;)
  123. voices.getUnchecked (i)->setCurrentPlaybackSampleRate (newRate);
  124. }
  125. }
  126. void Synthesiser::renderNextBlock (AudioSampleBuffer& outputBuffer, const MidiBuffer& midiData,
  127. int startSample, int numSamples)
  128. {
  129. // must set the sample rate before using this!
  130. jassert (sampleRate != 0);
  131. MidiBuffer::Iterator midiIterator (midiData);
  132. midiIterator.setNextSamplePosition (startSample);
  133. int midiEventPos;
  134. MidiMessage m;
  135. const ScopedLock sl (lock);
  136. while (numSamples > 0)
  137. {
  138. if (! midiIterator.getNextEvent (m, midiEventPos))
  139. {
  140. renderVoices (outputBuffer, startSample, numSamples);
  141. return;
  142. }
  143. const int samplesToNextMidiMessage = midiEventPos - startSample;
  144. if (samplesToNextMidiMessage >= numSamples)
  145. {
  146. renderVoices (outputBuffer, startSample, numSamples);
  147. handleMidiEvent (m);
  148. break;
  149. }
  150. if (samplesToNextMidiMessage < minimumSubBlockSize)
  151. {
  152. handleMidiEvent (m);
  153. continue;
  154. }
  155. renderVoices (outputBuffer, startSample, samplesToNextMidiMessage);
  156. handleMidiEvent (m);
  157. startSample += samplesToNextMidiMessage;
  158. numSamples -= samplesToNextMidiMessage;
  159. }
  160. while (midiIterator.getNextEvent (m, midiEventPos))
  161. handleMidiEvent (m);
  162. }
  163. void Synthesiser::renderVoices (AudioSampleBuffer& buffer, int startSample, int numSamples)
  164. {
  165. for (int i = voices.size(); --i >= 0;)
  166. voices.getUnchecked (i)->renderNextBlock (buffer, startSample, numSamples);
  167. }
  168. void Synthesiser::handleMidiEvent (const MidiMessage& m)
  169. {
  170. const int channel = m.getChannel();
  171. if (m.isNoteOn())
  172. {
  173. noteOn (channel, m.getNoteNumber(), m.getFloatVelocity());
  174. }
  175. else if (m.isNoteOff())
  176. {
  177. noteOff (channel, m.getNoteNumber(), m.getFloatVelocity(), true);
  178. }
  179. else if (m.isAllNotesOff() || m.isAllSoundOff())
  180. {
  181. allNotesOff (channel, true);
  182. }
  183. else if (m.isPitchWheel())
  184. {
  185. const int wheelPos = m.getPitchWheelValue();
  186. lastPitchWheelValues [channel - 1] = wheelPos;
  187. handlePitchWheel (channel, wheelPos);
  188. }
  189. else if (m.isAftertouch())
  190. {
  191. handleAftertouch (channel, m.getNoteNumber(), m.getAfterTouchValue());
  192. }
  193. else if (m.isChannelPressure())
  194. {
  195. handleChannelPressure (channel, m.getChannelPressureValue());
  196. }
  197. else if (m.isController())
  198. {
  199. handleController (channel, m.getControllerNumber(), m.getControllerValue());
  200. }
  201. else if (m.isProgramChange())
  202. {
  203. handleProgramChange (channel, m.getProgramChangeNumber());
  204. }
  205. }
  206. //==============================================================================
  207. void Synthesiser::noteOn (const int midiChannel,
  208. const int midiNoteNumber,
  209. const float velocity)
  210. {
  211. const ScopedLock sl (lock);
  212. for (int i = sounds.size(); --i >= 0;)
  213. {
  214. SynthesiserSound* const sound = sounds.getUnchecked(i);
  215. if (sound->appliesToNote (midiNoteNumber)
  216. && sound->appliesToChannel (midiChannel))
  217. {
  218. // If hitting a note that's still ringing, stop it first (it could be
  219. // still playing because of the sustain or sostenuto pedal).
  220. for (int j = voices.size(); --j >= 0;)
  221. {
  222. SynthesiserVoice* const voice = voices.getUnchecked (j);
  223. if (voice->getCurrentlyPlayingNote() == midiNoteNumber
  224. && voice->isPlayingChannel (midiChannel))
  225. stopVoice (voice, 1.0f, true);
  226. }
  227. startVoice (findFreeVoice (sound, midiChannel, midiNoteNumber, shouldStealNotes),
  228. sound, midiChannel, midiNoteNumber, velocity);
  229. }
  230. }
  231. }
  232. void Synthesiser::startVoice (SynthesiserVoice* const voice,
  233. SynthesiserSound* const sound,
  234. const int midiChannel,
  235. const int midiNoteNumber,
  236. const float velocity)
  237. {
  238. if (voice != nullptr && sound != nullptr)
  239. {
  240. if (voice->currentlyPlayingSound != nullptr)
  241. voice->stopNote (0.0f, false);
  242. voice->currentlyPlayingNote = midiNoteNumber;
  243. voice->currentPlayingMidiChannel = midiChannel;
  244. voice->noteOnTime = ++lastNoteOnCounter;
  245. voice->currentlyPlayingSound = sound;
  246. voice->keyIsDown = true;
  247. voice->sostenutoPedalDown = false;
  248. voice->startNote (midiNoteNumber, velocity, sound,
  249. lastPitchWheelValues [midiChannel - 1]);
  250. }
  251. }
  252. void Synthesiser::stopVoice (SynthesiserVoice* voice, float velocity, const bool allowTailOff)
  253. {
  254. jassert (voice != nullptr);
  255. voice->stopNote (velocity, allowTailOff);
  256. // the subclass MUST call clearCurrentNote() if it's not tailing off! RTFM for stopNote()!
  257. jassert (allowTailOff || (voice->getCurrentlyPlayingNote() < 0 && voice->getCurrentlyPlayingSound() == 0));
  258. }
  259. void Synthesiser::noteOff (const int midiChannel,
  260. const int midiNoteNumber,
  261. const float velocity,
  262. const bool allowTailOff)
  263. {
  264. const ScopedLock sl (lock);
  265. for (int i = voices.size(); --i >= 0;)
  266. {
  267. SynthesiserVoice* const voice = voices.getUnchecked (i);
  268. if (voice->getCurrentlyPlayingNote() == midiNoteNumber
  269. && voice->isPlayingChannel (midiChannel))
  270. {
  271. if (SynthesiserSound* const sound = voice->getCurrentlyPlayingSound())
  272. {
  273. if (sound->appliesToNote (midiNoteNumber)
  274. && sound->appliesToChannel (midiChannel))
  275. {
  276. voice->keyIsDown = false;
  277. if (! (sustainPedalsDown [midiChannel] || voice->sostenutoPedalDown))
  278. stopVoice (voice, velocity, allowTailOff);
  279. }
  280. }
  281. }
  282. }
  283. }
  284. void Synthesiser::allNotesOff (const int midiChannel, const bool allowTailOff)
  285. {
  286. const ScopedLock sl (lock);
  287. for (int i = voices.size(); --i >= 0;)
  288. {
  289. SynthesiserVoice* const voice = voices.getUnchecked (i);
  290. if (midiChannel <= 0 || voice->isPlayingChannel (midiChannel))
  291. voice->stopNote (1.0f, allowTailOff);
  292. }
  293. sustainPedalsDown.clear();
  294. }
  295. void Synthesiser::handlePitchWheel (const int midiChannel, const int wheelValue)
  296. {
  297. const ScopedLock sl (lock);
  298. for (int i = voices.size(); --i >= 0;)
  299. {
  300. SynthesiserVoice* const voice = voices.getUnchecked (i);
  301. if (midiChannel <= 0 || voice->isPlayingChannel (midiChannel))
  302. voice->pitchWheelMoved (wheelValue);
  303. }
  304. }
  305. void Synthesiser::handleController (const int midiChannel,
  306. const int controllerNumber,
  307. const int controllerValue)
  308. {
  309. switch (controllerNumber)
  310. {
  311. case 0x40: handleSustainPedal (midiChannel, controllerValue >= 64); break;
  312. case 0x42: handleSostenutoPedal (midiChannel, controllerValue >= 64); break;
  313. case 0x43: handleSoftPedal (midiChannel, controllerValue >= 64); break;
  314. default: break;
  315. }
  316. const ScopedLock sl (lock);
  317. for (int i = voices.size(); --i >= 0;)
  318. {
  319. SynthesiserVoice* const voice = voices.getUnchecked (i);
  320. if (midiChannel <= 0 || voice->isPlayingChannel (midiChannel))
  321. voice->controllerMoved (controllerNumber, controllerValue);
  322. }
  323. }
  324. void Synthesiser::handleAftertouch (int midiChannel, int midiNoteNumber, int aftertouchValue)
  325. {
  326. const ScopedLock sl (lock);
  327. for (int i = voices.size(); --i >= 0;)
  328. {
  329. SynthesiserVoice* const voice = voices.getUnchecked (i);
  330. if (voice->getCurrentlyPlayingNote() == midiNoteNumber
  331. && (midiChannel <= 0 || voice->isPlayingChannel (midiChannel)))
  332. voice->aftertouchChanged (aftertouchValue);
  333. }
  334. }
  335. void Synthesiser::handleChannelPressure (int midiChannel, int channelPressureValue)
  336. {
  337. const ScopedLock sl (lock);
  338. for (int i = voices.size(); --i >= 0;)
  339. {
  340. SynthesiserVoice* const voice = voices.getUnchecked (i);
  341. if (midiChannel <= 0 || voice->isPlayingChannel (midiChannel))
  342. voice->channelPressureChanged (channelPressureValue);
  343. }
  344. }
  345. void Synthesiser::handleSustainPedal (int midiChannel, bool isDown)
  346. {
  347. jassert (midiChannel > 0 && midiChannel <= 16);
  348. const ScopedLock sl (lock);
  349. if (isDown)
  350. {
  351. sustainPedalsDown.setBit (midiChannel);
  352. }
  353. else
  354. {
  355. for (int i = voices.size(); --i >= 0;)
  356. {
  357. SynthesiserVoice* const voice = voices.getUnchecked (i);
  358. if (voice->isPlayingChannel (midiChannel) && ! voice->keyIsDown)
  359. stopVoice (voice, 1.0f, true);
  360. }
  361. sustainPedalsDown.clearBit (midiChannel);
  362. }
  363. }
  364. void Synthesiser::handleSostenutoPedal (int midiChannel, bool isDown)
  365. {
  366. jassert (midiChannel > 0 && midiChannel <= 16);
  367. const ScopedLock sl (lock);
  368. for (int i = voices.size(); --i >= 0;)
  369. {
  370. SynthesiserVoice* const voice = voices.getUnchecked (i);
  371. if (voice->isPlayingChannel (midiChannel))
  372. {
  373. if (isDown)
  374. voice->sostenutoPedalDown = true;
  375. else if (voice->sostenutoPedalDown)
  376. stopVoice (voice, 1.0f, true);
  377. }
  378. }
  379. }
  380. void Synthesiser::handleSoftPedal (int midiChannel, bool /*isDown*/)
  381. {
  382. (void) midiChannel;
  383. jassert (midiChannel > 0 && midiChannel <= 16);
  384. }
  385. void Synthesiser::handleProgramChange (int midiChannel, int programNumber)
  386. {
  387. (void) midiChannel; (void) programNumber;
  388. jassert (midiChannel > 0 && midiChannel <= 16);
  389. }
  390. //==============================================================================
  391. SynthesiserVoice* Synthesiser::findFreeVoice (SynthesiserSound* soundToPlay,
  392. int midiChannel, int midiNoteNumber,
  393. const bool stealIfNoneAvailable) const
  394. {
  395. const ScopedLock sl (lock);
  396. for (int i = 0; i < voices.size(); ++i)
  397. {
  398. SynthesiserVoice* const voice = voices.getUnchecked (i);
  399. if ((! voice->isVoiceActive()) && voice->canPlaySound (soundToPlay))
  400. return voice;
  401. }
  402. if (stealIfNoneAvailable)
  403. return findVoiceToSteal (soundToPlay, midiChannel, midiNoteNumber);
  404. return nullptr;
  405. }
  406. struct VoiceAgeSorter
  407. {
  408. static int compareElements (SynthesiserVoice* v1, SynthesiserVoice* v2) noexcept
  409. {
  410. return v1->wasStartedBefore (*v2) ? -1 : (v2->wasStartedBefore (*v1) ? 1 : 0);
  411. }
  412. };
  413. SynthesiserVoice* Synthesiser::findVoiceToSteal (SynthesiserSound* soundToPlay,
  414. int /*midiChannel*/, int midiNoteNumber) const
  415. {
  416. SynthesiserVoice* bottom = nullptr;
  417. SynthesiserVoice* top = nullptr;
  418. // this is a list of voices we can steal, sorted by how long they've been running
  419. Array<SynthesiserVoice*> usableVoices;
  420. usableVoices.ensureStorageAllocated (voices.size());
  421. for (int i = 0; i < voices.size(); ++i)
  422. {
  423. SynthesiserVoice* const voice = voices.getUnchecked (i);
  424. if (voice->canPlaySound (soundToPlay))
  425. {
  426. VoiceAgeSorter sorter;
  427. usableVoices.addSorted (sorter, voice);
  428. const int note = voice->getCurrentlyPlayingNote();
  429. if (bottom == nullptr || note < bottom->getCurrentlyPlayingNote())
  430. bottom = voice;
  431. if (top == nullptr || note > top->getCurrentlyPlayingNote())
  432. top = voice;
  433. }
  434. }
  435. const int numUsableVoices = usableVoices.size();
  436. // The oldest note that's playing with the target pitch playing is ideal..
  437. for (int i = 0; i < numUsableVoices; ++i)
  438. {
  439. SynthesiserVoice* const voice = usableVoices.getUnchecked (i);
  440. if (voice->getCurrentlyPlayingNote() == midiNoteNumber)
  441. return voice;
  442. }
  443. // Oldest voice that has been released (no finger on it and not held by sustain pedal)
  444. for (int i = 0; i < numUsableVoices; ++i)
  445. {
  446. SynthesiserVoice* const voice = usableVoices.getUnchecked (i);
  447. if (voice != bottom && voice != top && ! voice->isKeyDown() && ! voice->isSostenutoPedalDown())
  448. return voice;
  449. }
  450. // Oldest voice that doesn't have a finger on it:
  451. for (int i = 0; i < numUsableVoices; ++i)
  452. {
  453. SynthesiserVoice* const voice = usableVoices.getUnchecked (i);
  454. if (voice != bottom && voice != top && ! voice->isKeyDown())
  455. return voice;
  456. }
  457. // At this point, all notes have fingers on them, so look for the oldest note
  458. // that isn't the top or bottom note..
  459. for (int i = 0; i < numUsableVoices; ++i)
  460. {
  461. SynthesiserVoice* const voice = usableVoices.getUnchecked (i);
  462. if (voice != bottom && voice != top)
  463. return voice;
  464. }
  465. // ..otherwise, there's only one or two voices to choose from - prefer to steal the highest one:
  466. jassert (top != nullptr || bottom != nullptr);
  467. return (top == nullptr ? bottom : top);
  468. }