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.

141 lines
4.5KB

  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. MPESynthesiserBase::MPESynthesiserBase()
  18. : instrument (new MPEInstrument),
  19. sampleRate (0),
  20. minimumSubBlockSize (32)
  21. {
  22. instrument->addListener (this);
  23. }
  24. MPESynthesiserBase::MPESynthesiserBase (MPEInstrument* inst)
  25. : instrument (inst),
  26. sampleRate (0),
  27. minimumSubBlockSize (32)
  28. {
  29. jassert (instrument != nullptr);
  30. instrument->addListener (this);
  31. }
  32. //==============================================================================
  33. MPEZoneLayout MPESynthesiserBase::getZoneLayout() const noexcept
  34. {
  35. return instrument->getZoneLayout();
  36. }
  37. void MPESynthesiserBase::setZoneLayout (MPEZoneLayout newLayout)
  38. {
  39. instrument->setZoneLayout (newLayout);
  40. }
  41. void MPESynthesiserBase::enableOmniMode (int pitchbendRange)
  42. {
  43. instrument->enableOmniMode (pitchbendRange);
  44. }
  45. bool MPESynthesiserBase::isOmniModeEnabled() const noexcept
  46. {
  47. return instrument->isOmniModeEnabled();
  48. }
  49. //==============================================================================
  50. void MPESynthesiserBase::handleMidiEvent (const MidiMessage& m)
  51. {
  52. instrument->processNextMidiEvent (m);
  53. }
  54. //==============================================================================
  55. template <typename floatType>
  56. void MPESynthesiserBase::renderNextBlock (AudioBuffer<floatType>& outputAudio,
  57. const MidiBuffer& inputMidi,
  58. int startSample,
  59. int numSamples)
  60. {
  61. // you must set the sample rate before using this!
  62. jassert (sampleRate != 0);
  63. MidiBuffer::Iterator midiIterator (inputMidi);
  64. midiIterator.setNextSamplePosition (startSample);
  65. int midiEventPos;
  66. MidiMessage m;
  67. const ScopedLock sl (renderAudioLock);
  68. while (numSamples > 0)
  69. {
  70. if (! midiIterator.getNextEvent (m, midiEventPos))
  71. {
  72. renderNextSubBlock (outputAudio, startSample, numSamples);
  73. return;
  74. }
  75. const int samplesToNextMidiMessage = midiEventPos - startSample;
  76. if (samplesToNextMidiMessage >= numSamples)
  77. {
  78. renderNextSubBlock (outputAudio, startSample, numSamples);
  79. handleMidiEvent (m);
  80. break;
  81. }
  82. if (samplesToNextMidiMessage < minimumSubBlockSize)
  83. {
  84. handleMidiEvent (m);
  85. continue;
  86. }
  87. renderNextSubBlock (outputAudio, startSample, samplesToNextMidiMessage);
  88. handleMidiEvent (m);
  89. startSample += samplesToNextMidiMessage;
  90. numSamples -= samplesToNextMidiMessage;
  91. }
  92. while (midiIterator.getNextEvent (m, midiEventPos))
  93. handleMidiEvent (m);
  94. }
  95. // explicit instantiation for supported float types:
  96. template void MPESynthesiserBase::renderNextBlock<float> (AudioBuffer<float>&, const MidiBuffer&, int, int);
  97. template void MPESynthesiserBase::renderNextBlock<double> (AudioBuffer<double>&, const MidiBuffer&, int, int);
  98. //==============================================================================
  99. void MPESynthesiserBase::setCurrentPlaybackSampleRate (const double newRate)
  100. {
  101. if (sampleRate != newRate)
  102. {
  103. const ScopedLock sl (renderAudioLock);
  104. instrument->releaseAllNotes();
  105. sampleRate = newRate;
  106. }
  107. }
  108. //==============================================================================
  109. void MPESynthesiserBase::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. }