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.

244 lines
8.1KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2020 - Raw Material Software Limited
  5. JUCE is an open source library subject to commercial or open-source
  6. licensing.
  7. By using JUCE, you agree to the terms of both the JUCE 6 End-User License
  8. Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
  9. End User License Agreement: www.juce.com/juce-6-licence
  10. Privacy Policy: www.juce.com/juce-privacy-policy
  11. Or: You may also use this code under the terms of the GPL v3 (see
  12. www.gnu.org/licenses).
  13. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  14. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  15. DISCLAIMED.
  16. ==============================================================================
  17. */
  18. namespace juce
  19. {
  20. AudioProcessorPlayer::AudioProcessorPlayer (bool doDoublePrecisionProcessing)
  21. : isDoublePrecision (doDoublePrecisionProcessing)
  22. {
  23. }
  24. AudioProcessorPlayer::~AudioProcessorPlayer()
  25. {
  26. setProcessor (nullptr);
  27. }
  28. //==============================================================================
  29. void AudioProcessorPlayer::setProcessor (AudioProcessor* const processorToPlay)
  30. {
  31. if (processor != processorToPlay)
  32. {
  33. if (processorToPlay != nullptr && sampleRate > 0 && blockSize > 0)
  34. {
  35. processorToPlay->setPlayConfigDetails (numInputChans, numOutputChans, sampleRate, blockSize);
  36. bool supportsDouble = processorToPlay->supportsDoublePrecisionProcessing() && isDoublePrecision;
  37. processorToPlay->setProcessingPrecision (supportsDouble ? AudioProcessor::doublePrecision
  38. : AudioProcessor::singlePrecision);
  39. processorToPlay->prepareToPlay (sampleRate, blockSize);
  40. }
  41. AudioProcessor* oldOne;
  42. {
  43. const ScopedLock sl (lock);
  44. oldOne = isPrepared ? processor : nullptr;
  45. processor = processorToPlay;
  46. isPrepared = true;
  47. }
  48. if (oldOne != nullptr)
  49. oldOne->releaseResources();
  50. }
  51. }
  52. void AudioProcessorPlayer::setDoublePrecisionProcessing (bool doublePrecision)
  53. {
  54. if (doublePrecision != isDoublePrecision)
  55. {
  56. const ScopedLock sl (lock);
  57. if (processor != nullptr)
  58. {
  59. processor->releaseResources();
  60. bool supportsDouble = processor->supportsDoublePrecisionProcessing() && doublePrecision;
  61. processor->setProcessingPrecision (supportsDouble ? AudioProcessor::doublePrecision
  62. : AudioProcessor::singlePrecision);
  63. processor->prepareToPlay (sampleRate, blockSize);
  64. }
  65. isDoublePrecision = doublePrecision;
  66. }
  67. }
  68. void AudioProcessorPlayer::setMidiOutput (MidiOutput* midiOutputToUse)
  69. {
  70. if (midiOutput != midiOutputToUse)
  71. {
  72. const ScopedLock sl (lock);
  73. midiOutput = midiOutputToUse;
  74. }
  75. }
  76. //==============================================================================
  77. void AudioProcessorPlayer::audioDeviceIOCallback (const float** const inputChannelData,
  78. const int numInputChannels,
  79. float** const outputChannelData,
  80. const int numOutputChannels,
  81. const int numSamples)
  82. {
  83. // these should have been prepared by audioDeviceAboutToStart()...
  84. jassert (sampleRate > 0 && blockSize > 0);
  85. incomingMidi.clear();
  86. messageCollector.removeNextBlockOfMessages (incomingMidi, numSamples);
  87. int totalNumChans = 0;
  88. if (numInputChannels > numOutputChannels)
  89. {
  90. // if there aren't enough output channels for the number of
  91. // inputs, we need to create some temporary extra ones (can't
  92. // use the input data in case it gets written to)
  93. tempBuffer.setSize (numInputChannels - numOutputChannels, numSamples,
  94. false, false, true);
  95. for (int i = 0; i < numOutputChannels; ++i)
  96. {
  97. channels[totalNumChans] = outputChannelData[i];
  98. memcpy (channels[totalNumChans], inputChannelData[i], (size_t) numSamples * sizeof (float));
  99. ++totalNumChans;
  100. }
  101. for (int i = numOutputChannels; i < numInputChannels; ++i)
  102. {
  103. channels[totalNumChans] = tempBuffer.getWritePointer (i - numOutputChannels);
  104. memcpy (channels[totalNumChans], inputChannelData[i], (size_t) numSamples * sizeof (float));
  105. ++totalNumChans;
  106. }
  107. }
  108. else
  109. {
  110. for (int i = 0; i < numInputChannels; ++i)
  111. {
  112. channels[totalNumChans] = outputChannelData[i];
  113. memcpy (channels[totalNumChans], inputChannelData[i], (size_t) numSamples * sizeof (float));
  114. ++totalNumChans;
  115. }
  116. for (int i = numInputChannels; i < numOutputChannels; ++i)
  117. {
  118. channels[totalNumChans] = outputChannelData[i];
  119. zeromem (channels[totalNumChans], (size_t) numSamples * sizeof (float));
  120. ++totalNumChans;
  121. }
  122. }
  123. AudioBuffer<float> buffer (channels, totalNumChans, numSamples);
  124. {
  125. const ScopedLock sl (lock);
  126. if (processor != nullptr)
  127. {
  128. const ScopedLock sl2 (processor->getCallbackLock());
  129. if (! processor->isSuspended())
  130. {
  131. if (processor->isUsingDoublePrecision())
  132. {
  133. conversionBuffer.makeCopyOf (buffer, true);
  134. processor->processBlock (conversionBuffer, incomingMidi);
  135. buffer.makeCopyOf (conversionBuffer, true);
  136. }
  137. else
  138. {
  139. processor->processBlock (buffer, incomingMidi);
  140. }
  141. if (midiOutput != nullptr)
  142. {
  143. if (midiOutput->isBackgroundThreadRunning())
  144. {
  145. midiOutput->sendBlockOfMessages (incomingMidi,
  146. Time::getMillisecondCounterHiRes(),
  147. sampleRate);
  148. }
  149. else
  150. {
  151. midiOutput->sendBlockOfMessagesNow (incomingMidi);
  152. }
  153. }
  154. return;
  155. }
  156. }
  157. }
  158. for (int i = 0; i < numOutputChannels; ++i)
  159. FloatVectorOperations::clear (outputChannelData[i], numSamples);
  160. }
  161. void AudioProcessorPlayer::audioDeviceAboutToStart (AudioIODevice* const device)
  162. {
  163. auto newSampleRate = device->getCurrentSampleRate();
  164. auto newBlockSize = device->getCurrentBufferSizeSamples();
  165. auto numChansIn = device->getActiveInputChannels().countNumberOfSetBits();
  166. auto numChansOut = device->getActiveOutputChannels().countNumberOfSetBits();
  167. const ScopedLock sl (lock);
  168. sampleRate = newSampleRate;
  169. blockSize = newBlockSize;
  170. numInputChans = numChansIn;
  171. numOutputChans = numChansOut;
  172. messageCollector.reset (sampleRate);
  173. channels.calloc (jmax (numChansIn, numChansOut) + 2);
  174. if (processor != nullptr)
  175. {
  176. if (isPrepared)
  177. processor->releaseResources();
  178. auto* oldProcessor = processor;
  179. setProcessor (nullptr);
  180. setProcessor (oldProcessor);
  181. }
  182. }
  183. void AudioProcessorPlayer::audioDeviceStopped()
  184. {
  185. const ScopedLock sl (lock);
  186. if (processor != nullptr && isPrepared)
  187. processor->releaseResources();
  188. sampleRate = 0.0;
  189. blockSize = 0;
  190. isPrepared = false;
  191. tempBuffer.setSize (1, 1);
  192. }
  193. void AudioProcessorPlayer::handleIncomingMidiMessage (MidiInput*, const MidiMessage& message)
  194. {
  195. messageCollector.addMessageToQueue (message);
  196. }
  197. } // namespace juce