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.

222 lines
7.4KB

  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. //==============================================================================
  70. void AudioProcessorPlayer::audioDeviceIOCallback (const float** const inputChannelData,
  71. const int numInputChannels,
  72. float** const outputChannelData,
  73. const int numOutputChannels,
  74. const int numSamples)
  75. {
  76. // these should have been prepared by audioDeviceAboutToStart()...
  77. jassert (sampleRate > 0 && blockSize > 0);
  78. incomingMidi.clear();
  79. messageCollector.removeNextBlockOfMessages (incomingMidi, numSamples);
  80. int totalNumChans = 0;
  81. if (numInputChannels > numOutputChannels)
  82. {
  83. // if there aren't enough output channels for the number of
  84. // inputs, we need to create some temporary extra ones (can't
  85. // use the input data in case it gets written to)
  86. tempBuffer.setSize (numInputChannels - numOutputChannels, numSamples,
  87. false, false, true);
  88. for (int i = 0; i < numOutputChannels; ++i)
  89. {
  90. channels[totalNumChans] = outputChannelData[i];
  91. memcpy (channels[totalNumChans], inputChannelData[i], sizeof (float) * (size_t) numSamples);
  92. ++totalNumChans;
  93. }
  94. for (int i = numOutputChannels; i < numInputChannels; ++i)
  95. {
  96. channels[totalNumChans] = tempBuffer.getWritePointer (i - numOutputChannels);
  97. memcpy (channels[totalNumChans], inputChannelData[i], sizeof (float) * (size_t) numSamples);
  98. ++totalNumChans;
  99. }
  100. }
  101. else
  102. {
  103. for (int i = 0; i < numInputChannels; ++i)
  104. {
  105. channels[totalNumChans] = outputChannelData[i];
  106. memcpy (channels[totalNumChans], inputChannelData[i], sizeof (float) * (size_t) numSamples);
  107. ++totalNumChans;
  108. }
  109. for (int i = numInputChannels; i < numOutputChannels; ++i)
  110. {
  111. channels[totalNumChans] = outputChannelData[i];
  112. zeromem (channels[totalNumChans], sizeof (float) * (size_t) numSamples);
  113. ++totalNumChans;
  114. }
  115. }
  116. AudioBuffer<float> buffer (channels, totalNumChans, numSamples);
  117. {
  118. const ScopedLock sl (lock);
  119. if (processor != nullptr)
  120. {
  121. const ScopedLock sl2 (processor->getCallbackLock());
  122. if (! processor->isSuspended())
  123. {
  124. if (processor->isUsingDoublePrecision())
  125. {
  126. conversionBuffer.makeCopyOf (buffer, true);
  127. processor->processBlock (conversionBuffer, incomingMidi);
  128. buffer.makeCopyOf (conversionBuffer, true);
  129. }
  130. else
  131. {
  132. processor->processBlock (buffer, incomingMidi);
  133. }
  134. return;
  135. }
  136. }
  137. }
  138. for (int i = 0; i < numOutputChannels; ++i)
  139. FloatVectorOperations::clear (outputChannelData[i], numSamples);
  140. }
  141. void AudioProcessorPlayer::audioDeviceAboutToStart (AudioIODevice* const device)
  142. {
  143. auto newSampleRate = device->getCurrentSampleRate();
  144. auto newBlockSize = device->getCurrentBufferSizeSamples();
  145. auto numChansIn = device->getActiveInputChannels().countNumberOfSetBits();
  146. auto numChansOut = device->getActiveOutputChannels().countNumberOfSetBits();
  147. const ScopedLock sl (lock);
  148. sampleRate = newSampleRate;
  149. blockSize = newBlockSize;
  150. numInputChans = numChansIn;
  151. numOutputChans = numChansOut;
  152. messageCollector.reset (sampleRate);
  153. channels.calloc (jmax (numChansIn, numChansOut) + 2);
  154. if (processor != nullptr)
  155. {
  156. if (isPrepared)
  157. processor->releaseResources();
  158. auto* oldProcessor = processor;
  159. setProcessor (nullptr);
  160. setProcessor (oldProcessor);
  161. }
  162. }
  163. void AudioProcessorPlayer::audioDeviceStopped()
  164. {
  165. const ScopedLock sl (lock);
  166. if (processor != nullptr && isPrepared)
  167. processor->releaseResources();
  168. sampleRate = 0.0;
  169. blockSize = 0;
  170. isPrepared = false;
  171. tempBuffer.setSize (1, 1);
  172. }
  173. void AudioProcessorPlayer::handleIncomingMidiMessage (MidiInput*, const MidiMessage& message)
  174. {
  175. messageCollector.addMessageToQueue (message);
  176. }
  177. } // namespace juce