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.

224 lines
7.7KB

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