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.

165 lines
5.3KB

  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. //==============================================================================
  42. void MPESynthesiserBase::enableLegacyMode (int pitchbendRange, Range<int> channelRange)
  43. {
  44. instrument->enableLegacyMode (pitchbendRange, channelRange);
  45. }
  46. bool MPESynthesiserBase::isLegacyModeEnabled() const noexcept
  47. {
  48. return instrument->isLegacyModeEnabled();
  49. }
  50. Range<int> MPESynthesiserBase::getLegacyModeChannelRange() const noexcept
  51. {
  52. return instrument->getLegacyModeChannelRange();
  53. }
  54. void MPESynthesiserBase::setLegacyModeChannelRange (Range<int> channelRange)
  55. {
  56. instrument->setLegacyModeChannelRange (channelRange);
  57. }
  58. int MPESynthesiserBase::getLegacyModePitchbendRange() const noexcept
  59. {
  60. return instrument->getLegacyModePitchbendRange();
  61. }
  62. void MPESynthesiserBase::setLegacyModePitchbendRange (int pitchbendRange)
  63. {
  64. instrument->setLegacyModePitchbendRange (pitchbendRange);
  65. }
  66. //==============================================================================
  67. void MPESynthesiserBase::handleMidiEvent (const MidiMessage& m)
  68. {
  69. instrument->processNextMidiEvent (m);
  70. }
  71. //==============================================================================
  72. template <typename floatType>
  73. void MPESynthesiserBase::renderNextBlock (AudioBuffer<floatType>& outputAudio,
  74. const MidiBuffer& inputMidi,
  75. int startSample,
  76. int numSamples)
  77. {
  78. // you must set the sample rate before using this!
  79. jassert (sampleRate != 0);
  80. MidiBuffer::Iterator midiIterator (inputMidi);
  81. midiIterator.setNextSamplePosition (startSample);
  82. bool firstEvent = true;
  83. int midiEventPos;
  84. MidiMessage m;
  85. const ScopedLock sl (noteStateLock);
  86. while (numSamples > 0)
  87. {
  88. if (! midiIterator.getNextEvent (m, midiEventPos))
  89. {
  90. renderNextSubBlock (outputAudio, startSample, numSamples);
  91. return;
  92. }
  93. const int samplesToNextMidiMessage = midiEventPos - startSample;
  94. if (samplesToNextMidiMessage >= numSamples)
  95. {
  96. renderNextSubBlock (outputAudio, startSample, numSamples);
  97. handleMidiEvent (m);
  98. break;
  99. }
  100. if (samplesToNextMidiMessage < (firstEvent ? 1 : minimumSubBlockSize))
  101. {
  102. handleMidiEvent (m);
  103. continue;
  104. }
  105. firstEvent = false;
  106. renderNextSubBlock (outputAudio, startSample, samplesToNextMidiMessage);
  107. handleMidiEvent (m);
  108. startSample += samplesToNextMidiMessage;
  109. numSamples -= samplesToNextMidiMessage;
  110. }
  111. while (midiIterator.getNextEvent (m, midiEventPos))
  112. handleMidiEvent (m);
  113. }
  114. // explicit instantiation for supported float types:
  115. template void MPESynthesiserBase::renderNextBlock<float> (AudioBuffer<float>&, const MidiBuffer&, int, int);
  116. template void MPESynthesiserBase::renderNextBlock<double> (AudioBuffer<double>&, const MidiBuffer&, int, int);
  117. //==============================================================================
  118. void MPESynthesiserBase::setCurrentPlaybackSampleRate (const double newRate)
  119. {
  120. if (sampleRate != newRate)
  121. {
  122. const ScopedLock sl (noteStateLock);
  123. instrument->releaseAllNotes();
  124. sampleRate = newRate;
  125. }
  126. }
  127. //==============================================================================
  128. void MPESynthesiserBase::setMinimumRenderingSubdivisionSize (int numSamples) noexcept
  129. {
  130. jassert (numSamples > 0); // it wouldn't make much sense for this to be less than 1
  131. minimumSubBlockSize = numSamples;
  132. }