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.

226 lines
7.4KB

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