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.

167 lines
5.4KB

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