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.

612 lines
19KB

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