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.

311 lines
12KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2022 - Raw Material Software Limited
  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 7 End-User License
  8. Agreement and JUCE Privacy Policy.
  9. End User License Agreement: www.juce.com/juce-7-licence
  10. Privacy Policy: www.juce.com/juce-privacy-policy
  11. Or: You may also use this code under the terms of the GPL v3 (see
  12. www.gnu.org/licenses).
  13. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  14. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  15. DISCLAIMED.
  16. ==============================================================================
  17. */
  18. namespace juce
  19. {
  20. ARAAudioSourceReader::ARAAudioSourceReader (ARAAudioSource* audioSource)
  21. : AudioFormatReader (nullptr, "ARAAudioSourceReader"),
  22. audioSourceBeingRead (audioSource)
  23. {
  24. jassert (audioSourceBeingRead != nullptr);
  25. bitsPerSample = 32;
  26. usesFloatingPointData = true;
  27. sampleRate = audioSourceBeingRead->getSampleRate();
  28. numChannels = (unsigned int) audioSourceBeingRead->getChannelCount();
  29. lengthInSamples = audioSourceBeingRead->getSampleCount();
  30. tmpPtrs.resize (numChannels);
  31. audioSourceBeingRead->addListener (this);
  32. if (audioSourceBeingRead->isSampleAccessEnabled())
  33. hostReader.reset (new ARA::PlugIn::HostAudioReader (audioSourceBeingRead));
  34. }
  35. ARAAudioSourceReader::~ARAAudioSourceReader()
  36. {
  37. invalidate();
  38. }
  39. void ARAAudioSourceReader::invalidate()
  40. {
  41. ScopedWriteLock scopedLock (lock);
  42. if (! isValid())
  43. return;
  44. hostReader.reset();
  45. audioSourceBeingRead->removeListener (this);
  46. audioSourceBeingRead = nullptr;
  47. }
  48. void ARAAudioSourceReader::willUpdateAudioSourceProperties (ARAAudioSource* audioSource,
  49. ARAAudioSource::PropertiesPtr newProperties)
  50. {
  51. if (audioSource->getSampleCount() != newProperties->sampleCount
  52. || audioSource->getSampleRate() != newProperties->sampleRate
  53. || audioSource->getChannelCount() != newProperties->channelCount)
  54. {
  55. invalidate();
  56. }
  57. }
  58. void ARAAudioSourceReader::doUpdateAudioSourceContent (ARAAudioSource* audioSource,
  59. ARAContentUpdateScopes scopeFlags)
  60. {
  61. jassertquiet (audioSourceBeingRead == audioSource);
  62. // Don't invalidate if the audio signal is unchanged
  63. if (scopeFlags.affectSamples())
  64. invalidate();
  65. }
  66. void ARAAudioSourceReader::willEnableAudioSourceSamplesAccess (ARAAudioSource* audioSource, bool enable)
  67. {
  68. jassertquiet (audioSourceBeingRead == audioSource);
  69. // Invalidate our reader if sample access is disabled
  70. if (! enable)
  71. {
  72. ScopedWriteLock scopedLock (lock);
  73. hostReader.reset();
  74. }
  75. }
  76. void ARAAudioSourceReader::didEnableAudioSourceSamplesAccess (ARAAudioSource* audioSource, bool enable)
  77. {
  78. jassertquiet (audioSourceBeingRead == audioSource);
  79. // Recreate our reader if sample access is enabled
  80. if (enable && isValid())
  81. {
  82. ScopedWriteLock scopedLock (lock);
  83. hostReader.reset (new ARA::PlugIn::HostAudioReader (audioSourceBeingRead));
  84. }
  85. }
  86. void ARAAudioSourceReader::willDestroyAudioSource (ARAAudioSource* audioSource)
  87. {
  88. jassertquiet (audioSourceBeingRead == audioSource);
  89. invalidate();
  90. }
  91. bool ARAAudioSourceReader::readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,
  92. int64 startSampleInFile, int numSamples)
  93. {
  94. const auto destSize = (bitsPerSample / 8) * (size_t) numSamples;
  95. const auto bufferOffset = (int) (bitsPerSample / 8) * startOffsetInDestBuffer;
  96. if (isValid() && hostReader != nullptr)
  97. {
  98. const ScopedTryReadLock readLock (lock);
  99. if (readLock.isLocked())
  100. {
  101. for (size_t i = 0; i < tmpPtrs.size(); ++i)
  102. {
  103. if ((i < (size_t) numDestChannels) && (destSamples[i] != nullptr))
  104. {
  105. tmpPtrs[i] = ((uint8_t*) destSamples[i]) + bufferOffset;
  106. }
  107. else
  108. {
  109. // We need to provide destination pointers for all channels in the ARA read call, even if
  110. // readSamples is not reading all of them. Hence we use this dummy buffer to pad the read
  111. // destination area.
  112. static thread_local std::vector<uint8_t> dummyBuffer;
  113. if (destSize > dummyBuffer.size())
  114. dummyBuffer.resize (destSize);
  115. tmpPtrs[i] = dummyBuffer.data();
  116. }
  117. }
  118. return hostReader->readAudioSamples (startSampleInFile, numSamples, tmpPtrs.data());
  119. }
  120. }
  121. for (int i = 0; i < numDestChannels; ++i)
  122. if (destSamples[i] != nullptr)
  123. zeromem (((uint8_t*) destSamples[i]) + bufferOffset, destSize);
  124. return false;
  125. }
  126. //==============================================================================
  127. ARAPlaybackRegionReader::ARAPlaybackRegionReader (ARAPlaybackRegion* playbackRegion)
  128. : ARAPlaybackRegionReader (playbackRegion->getAudioModification()->getAudioSource()->getSampleRate(),
  129. playbackRegion->getAudioModification()->getAudioSource()->getChannelCount(),
  130. { playbackRegion })
  131. {}
  132. ARAPlaybackRegionReader::ARAPlaybackRegionReader (double rate, int numChans,
  133. const std::vector<ARAPlaybackRegion*>& playbackRegions)
  134. : AudioFormatReader (nullptr, "ARAPlaybackRegionReader")
  135. {
  136. // We're only providing the minimal set of meaningful values, since the ARA renderer should only
  137. // look at the time position and the playing state, and read any related tempo or bar signature
  138. // information from the ARA model directly (MusicalContext).
  139. positionInfo.resetToDefault();
  140. positionInfo.isPlaying = true;
  141. sampleRate = rate;
  142. numChannels = (unsigned int) numChans;
  143. bitsPerSample = 32;
  144. usesFloatingPointData = true;
  145. auto* documentController = (! playbackRegions.empty())
  146. ? playbackRegions.front()->getDocumentController<ARADocumentController>()
  147. : nullptr;
  148. playbackRenderer.reset (documentController ? static_cast<ARAPlaybackRenderer*> (documentController->doCreatePlaybackRenderer())
  149. : nullptr);
  150. if (playbackRenderer != nullptr)
  151. {
  152. double regionsStartTime = std::numeric_limits<double>::max();
  153. double regionsEndTime = std::numeric_limits<double>::lowest();
  154. for (const auto& playbackRegion : playbackRegions)
  155. {
  156. jassert (playbackRegion->getDocumentController() == documentController);
  157. auto playbackRegionTimeRange = playbackRegion->getTimeRange (ARAPlaybackRegion::IncludeHeadAndTail::yes);
  158. regionsStartTime = jmin (regionsStartTime, playbackRegionTimeRange.getStart());
  159. regionsEndTime = jmax (regionsEndTime, playbackRegionTimeRange.getEnd());
  160. playbackRenderer->addPlaybackRegion (ARA::PlugIn::toRef (playbackRegion));
  161. playbackRegion->addListener (this);
  162. }
  163. startInSamples = (int64) (regionsStartTime * sampleRate + 0.5);
  164. lengthInSamples = (int64) ((regionsEndTime - regionsStartTime) * sampleRate + 0.5);
  165. playbackRenderer->prepareToPlay (rate,
  166. maximumBlockSize,
  167. numChans,
  168. AudioProcessor::ProcessingPrecision::singlePrecision,
  169. ARARenderer::AlwaysNonRealtime::yes);
  170. }
  171. else
  172. {
  173. startInSamples = 0;
  174. lengthInSamples = 0;
  175. }
  176. }
  177. ARAPlaybackRegionReader::~ARAPlaybackRegionReader()
  178. {
  179. invalidate();
  180. }
  181. void ARAPlaybackRegionReader::invalidate()
  182. {
  183. ScopedWriteLock scopedWrite (lock);
  184. if (! isValid())
  185. return;
  186. for (auto& playbackRegion : playbackRenderer->getPlaybackRegions())
  187. playbackRegion->removeListener (this);
  188. playbackRenderer->releaseResources();
  189. playbackRenderer.reset();
  190. }
  191. bool ARAPlaybackRegionReader::readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,
  192. int64 startSampleInFile, int numSamples)
  193. {
  194. bool success = false;
  195. bool needClearSamples = true;
  196. const ScopedTryReadLock readLock (lock);
  197. if (readLock.isLocked())
  198. {
  199. if (isValid())
  200. {
  201. success = true;
  202. needClearSamples = false;
  203. positionInfo.timeInSamples = startSampleInFile + startInSamples;
  204. while (numSamples > 0)
  205. {
  206. const int numSliceSamples = jmin (numSamples, maximumBlockSize);
  207. AudioBuffer<float> buffer ((float **) destSamples, numDestChannels, startOffsetInDestBuffer, numSliceSamples);
  208. positionInfo.timeInSeconds = static_cast<double> (positionInfo.timeInSamples) / sampleRate;
  209. success &= playbackRenderer->processBlock (buffer, AudioProcessor::Realtime::no, positionInfo);
  210. numSamples -= numSliceSamples;
  211. startOffsetInDestBuffer += numSliceSamples;
  212. positionInfo.timeInSamples += numSliceSamples;
  213. }
  214. }
  215. }
  216. if (needClearSamples)
  217. for (int chan_i = 0; chan_i < numDestChannels; ++chan_i)
  218. FloatVectorOperations::clear ((float *) destSamples[chan_i], numSamples);
  219. return success;
  220. }
  221. void ARAPlaybackRegionReader::willUpdatePlaybackRegionProperties (ARAPlaybackRegion* playbackRegion, ARAPlaybackRegion::PropertiesPtr newProperties)
  222. {
  223. jassert (ARA::contains (playbackRenderer->getPlaybackRegions(), playbackRegion));
  224. if ((playbackRegion->getStartInAudioModificationTime() != newProperties->startInModificationTime)
  225. || (playbackRegion->getDurationInAudioModificationTime() != newProperties->durationInModificationTime)
  226. || (playbackRegion->getStartInPlaybackTime() != newProperties->startInPlaybackTime)
  227. || (playbackRegion->getDurationInPlaybackTime() != newProperties->durationInPlaybackTime)
  228. || (playbackRegion->isTimestretchEnabled() != ((newProperties->transformationFlags & ARA::kARAPlaybackTransformationTimestretch) != 0))
  229. || (playbackRegion->isTimeStretchReflectingTempo() != ((newProperties->transformationFlags & ARA::kARAPlaybackTransformationTimestretchReflectingTempo) != 0))
  230. || (playbackRegion->hasContentBasedFadeAtHead() != ((newProperties->transformationFlags & ARA::kARAPlaybackTransformationContentBasedFadeAtHead) != 0))
  231. || (playbackRegion->hasContentBasedFadeAtTail() != ((newProperties->transformationFlags & ARA::kARAPlaybackTransformationContentBasedFadeAtTail) != 0)))
  232. {
  233. invalidate();
  234. }
  235. }
  236. void ARAPlaybackRegionReader::didUpdatePlaybackRegionContent (ARAPlaybackRegion* playbackRegion,
  237. ARAContentUpdateScopes scopeFlags)
  238. {
  239. jassertquiet (ARA::contains (playbackRenderer->getPlaybackRegions(), playbackRegion));
  240. // Invalidate if the audio signal is changed
  241. if (scopeFlags.affectSamples())
  242. invalidate();
  243. }
  244. void ARAPlaybackRegionReader::willDestroyPlaybackRegion (ARAPlaybackRegion* playbackRegion)
  245. {
  246. jassertquiet (ARA::contains (playbackRenderer->getPlaybackRegions(), playbackRegion));
  247. invalidate();
  248. }
  249. } // namespace juce