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.

650 lines
20KB

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