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.

255 lines
9.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. AudioProcessorPlayer::AudioProcessorPlayer(bool doDoublePrecisionProcessing)
  18. : processor (nullptr),
  19. sampleRate (0),
  20. blockSize (0),
  21. isPrepared (false),
  22. isDoublePrecision (doDoublePrecisionProcessing),
  23. numInputChans (0),
  24. numOutputChans (0)
  25. {
  26. }
  27. AudioProcessorPlayer::~AudioProcessorPlayer()
  28. {
  29. setProcessor (nullptr);
  30. }
  31. //==============================================================================
  32. void AudioProcessorPlayer::setProcessor (AudioProcessor* const processorToPlay)
  33. {
  34. if (processor != processorToPlay)
  35. {
  36. if (processorToPlay != nullptr && sampleRate > 0 && blockSize > 0)
  37. {
  38. const int numInBuses = processorToPlay->busArrangement.inputBuses. size();
  39. const int numOutBuses = processorToPlay->busArrangement.outputBuses.size();
  40. for (int i = 1; i < numInBuses; ++i)
  41. {
  42. bool success = processorToPlay->setPreferredBusArrangement (true, i, AudioChannelSet::disabled());
  43. // if using in audio processor player, it must be possible to disable sidechains
  44. jassert (success);
  45. ignoreUnused (success);
  46. }
  47. for (int i = 1; i < numOutBuses; ++i)
  48. {
  49. bool success = processorToPlay->setPreferredBusArrangement (false, i, AudioChannelSet::disabled());
  50. // if using in audio processor player, it must be possible to disable aux outputs
  51. jassert (success);
  52. ignoreUnused(success);
  53. }
  54. if (numInBuses > 0 && processorToPlay->busArrangement.inputBuses.getReference(0).channels.size() != numInputChans)
  55. processorToPlay->setPreferredBusArrangement (true, 0, AudioChannelSet::canonicalChannelSet(numInputChans));
  56. if (numOutBuses > 0 && processorToPlay->busArrangement.outputBuses.getReference(0).channels.size() != numOutputChans)
  57. processorToPlay->setPreferredBusArrangement (false, 0, AudioChannelSet::canonicalChannelSet(numOutputChans));
  58. jassert (processorToPlay->getTotalNumInputChannels() == numInputChans);
  59. jassert (processorToPlay->getTotalNumOutputChannels() == numOutputChans);
  60. processorToPlay->setRateAndBufferSizeDetails (sampleRate, blockSize);
  61. const bool supportsDouble = processorToPlay->supportsDoublePrecisionProcessing() && isDoublePrecision;
  62. AudioProcessor::ProcessingPrecision precision = supportsDouble ? AudioProcessor::doublePrecision
  63. : AudioProcessor::singlePrecision;
  64. processorToPlay->setProcessingPrecision (precision);
  65. processorToPlay->prepareToPlay (sampleRate, blockSize);
  66. }
  67. AudioProcessor* oldOne;
  68. {
  69. const ScopedLock sl (lock);
  70. oldOne = isPrepared ? processor : nullptr;
  71. processor = processorToPlay;
  72. isPrepared = true;
  73. }
  74. if (oldOne != nullptr)
  75. oldOne->releaseResources();
  76. }
  77. }
  78. void AudioProcessorPlayer::setDoublePrecisionProcessing (bool doublePrecision)
  79. {
  80. if (doublePrecision != isDoublePrecision)
  81. {
  82. const ScopedLock sl (lock);
  83. if (processor != nullptr)
  84. {
  85. processor->releaseResources();
  86. const bool supportsDouble = processor->supportsDoublePrecisionProcessing() && doublePrecision;
  87. AudioProcessor::ProcessingPrecision precision = supportsDouble ? AudioProcessor::doublePrecision
  88. : AudioProcessor::singlePrecision;
  89. processor->setProcessingPrecision (precision);
  90. processor->prepareToPlay (sampleRate, blockSize);
  91. }
  92. isDoublePrecision = doublePrecision;
  93. }
  94. }
  95. //==============================================================================
  96. void AudioProcessorPlayer::audioDeviceIOCallback (const float** const inputChannelData,
  97. const int numInputChannels,
  98. float** const outputChannelData,
  99. const int numOutputChannels,
  100. const int numSamples)
  101. {
  102. // these should have been prepared by audioDeviceAboutToStart()...
  103. jassert (sampleRate > 0 && blockSize > 0);
  104. incomingMidi.clear();
  105. messageCollector.removeNextBlockOfMessages (incomingMidi, numSamples);
  106. int totalNumChans = 0;
  107. if (numInputChannels > numOutputChannels)
  108. {
  109. // if there aren't enough output channels for the number of
  110. // inputs, we need to create some temporary extra ones (can't
  111. // use the input data in case it gets written to)
  112. tempBuffer.setSize (numInputChannels - numOutputChannels, numSamples,
  113. false, false, true);
  114. for (int i = 0; i < numOutputChannels; ++i)
  115. {
  116. channels[totalNumChans] = outputChannelData[i];
  117. memcpy (channels[totalNumChans], inputChannelData[i], sizeof (float) * (size_t) numSamples);
  118. ++totalNumChans;
  119. }
  120. for (int i = numOutputChannels; i < numInputChannels; ++i)
  121. {
  122. channels[totalNumChans] = tempBuffer.getWritePointer (i - numOutputChannels);
  123. memcpy (channels[totalNumChans], inputChannelData[i], sizeof (float) * (size_t) numSamples);
  124. ++totalNumChans;
  125. }
  126. }
  127. else
  128. {
  129. for (int i = 0; i < numInputChannels; ++i)
  130. {
  131. channels[totalNumChans] = outputChannelData[i];
  132. memcpy (channels[totalNumChans], inputChannelData[i], sizeof (float) * (size_t) numSamples);
  133. ++totalNumChans;
  134. }
  135. for (int i = numInputChannels; i < numOutputChannels; ++i)
  136. {
  137. channels[totalNumChans] = outputChannelData[i];
  138. zeromem (channels[totalNumChans], sizeof (float) * (size_t) numSamples);
  139. ++totalNumChans;
  140. }
  141. }
  142. AudioSampleBuffer buffer (channels, totalNumChans, numSamples);
  143. {
  144. const ScopedLock sl (lock);
  145. if (processor != nullptr)
  146. {
  147. const ScopedLock sl2 (processor->getCallbackLock());
  148. if (! processor->isSuspended())
  149. {
  150. if (processor->isUsingDoublePrecision())
  151. {
  152. conversionBuffer.makeCopyOf (buffer);
  153. processor->processBlock (conversionBuffer, incomingMidi);
  154. buffer.makeCopyOf (conversionBuffer);
  155. }
  156. else
  157. {
  158. processor->processBlock (buffer, incomingMidi);
  159. }
  160. return;
  161. }
  162. }
  163. }
  164. for (int i = 0; i < numOutputChannels; ++i)
  165. FloatVectorOperations::clear (outputChannelData[i], numSamples);
  166. }
  167. void AudioProcessorPlayer::audioDeviceAboutToStart (AudioIODevice* const device)
  168. {
  169. const double newSampleRate = device->getCurrentSampleRate();
  170. const int newBlockSize = device->getCurrentBufferSizeSamples();
  171. const int numChansIn = device->getActiveInputChannels().countNumberOfSetBits();
  172. const int numChansOut = device->getActiveOutputChannels().countNumberOfSetBits();
  173. const ScopedLock sl (lock);
  174. sampleRate = newSampleRate;
  175. blockSize = newBlockSize;
  176. numInputChans = numChansIn;
  177. numOutputChans = numChansOut;
  178. messageCollector.reset (sampleRate);
  179. channels.calloc ((size_t) jmax (numChansIn, numChansOut) + 2);
  180. if (processor != nullptr)
  181. {
  182. if (isPrepared)
  183. processor->releaseResources();
  184. AudioProcessor* const oldProcessor = processor;
  185. setProcessor (nullptr);
  186. setProcessor (oldProcessor);
  187. }
  188. }
  189. void AudioProcessorPlayer::audioDeviceStopped()
  190. {
  191. const ScopedLock sl (lock);
  192. if (processor != nullptr && isPrepared)
  193. processor->releaseResources();
  194. sampleRate = 0.0;
  195. blockSize = 0;
  196. isPrepared = false;
  197. tempBuffer.setSize (1, 1);
  198. }
  199. void AudioProcessorPlayer::handleIncomingMidiMessage (MidiInput*, const MidiMessage& message)
  200. {
  201. messageCollector.addMessageToQueue (message);
  202. }