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.

183 lines
5.9KB

  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::setPressureTrackingMode (TrackingMode modeToUse)
  69. {
  70. instrument->setPressureTrackingMode (modeToUse);
  71. }
  72. void MPESynthesiserBase::setPitchbendTrackingMode (TrackingMode modeToUse)
  73. {
  74. instrument->setPitchbendTrackingMode (modeToUse);
  75. }
  76. void MPESynthesiserBase::setTimbreTrackingMode (TrackingMode modeToUse)
  77. {
  78. instrument->setTimbreTrackingMode (modeToUse);
  79. }
  80. //==============================================================================
  81. void MPESynthesiserBase::handleMidiEvent (const MidiMessage& m)
  82. {
  83. instrument->processNextMidiEvent (m);
  84. }
  85. //==============================================================================
  86. template <typename floatType>
  87. void MPESynthesiserBase::renderNextBlock (AudioBuffer<floatType>& outputAudio,
  88. const MidiBuffer& inputMidi,
  89. int startSample,
  90. int numSamples)
  91. {
  92. // you must set the sample rate before using this!
  93. jassert (sampleRate != 0);
  94. MidiBuffer::Iterator midiIterator (inputMidi);
  95. midiIterator.setNextSamplePosition (startSample);
  96. bool firstEvent = true;
  97. int midiEventPos;
  98. MidiMessage m;
  99. const ScopedLock sl (noteStateLock);
  100. while (numSamples > 0)
  101. {
  102. if (! midiIterator.getNextEvent (m, midiEventPos))
  103. {
  104. renderNextSubBlock (outputAudio, startSample, numSamples);
  105. return;
  106. }
  107. const int samplesToNextMidiMessage = midiEventPos - startSample;
  108. if (samplesToNextMidiMessage >= numSamples)
  109. {
  110. renderNextSubBlock (outputAudio, startSample, numSamples);
  111. handleMidiEvent (m);
  112. break;
  113. }
  114. if (samplesToNextMidiMessage < ((firstEvent && ! subBlockSubdivisionIsStrict) ? 1 : minimumSubBlockSize))
  115. {
  116. handleMidiEvent (m);
  117. continue;
  118. }
  119. firstEvent = false;
  120. renderNextSubBlock (outputAudio, startSample, samplesToNextMidiMessage);
  121. handleMidiEvent (m);
  122. startSample += samplesToNextMidiMessage;
  123. numSamples -= samplesToNextMidiMessage;
  124. }
  125. while (midiIterator.getNextEvent (m, midiEventPos))
  126. handleMidiEvent (m);
  127. }
  128. // explicit instantiation for supported float types:
  129. template void MPESynthesiserBase::renderNextBlock<float> (AudioBuffer<float>&, const MidiBuffer&, int, int);
  130. template void MPESynthesiserBase::renderNextBlock<double> (AudioBuffer<double>&, const MidiBuffer&, int, int);
  131. //==============================================================================
  132. void MPESynthesiserBase::setCurrentPlaybackSampleRate (const double newRate)
  133. {
  134. if (sampleRate != newRate)
  135. {
  136. const ScopedLock sl (noteStateLock);
  137. instrument->releaseAllNotes();
  138. sampleRate = newRate;
  139. }
  140. }
  141. //==============================================================================
  142. void MPESynthesiserBase::setMinimumRenderingSubdivisionSize (int numSamples, bool shouldBeStrict) noexcept
  143. {
  144. jassert (numSamples > 0); // it wouldn't make much sense for this to be less than 1
  145. minimumSubBlockSize = numSamples;
  146. subBlockSubdivisionIsStrict = shouldBeStrict;
  147. }