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.

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