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.

217 lines
7.3KB

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