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_Synthesiser.cpp 20KB

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