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.

195 lines
8.9KB

  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. #pragma once
  19. namespace juce
  20. {
  21. class AudioProcessor;
  22. /* All these readers follow a common pattern of "invalidation":
  23. Whenever the samples they are reading are altered, the readers become invalid and will stop
  24. accessing the model graph. These alterations are model edits such as property changes, content
  25. changes (if affecting sample scope), or the deletion of some model object involved in the read
  26. process. Since these edits are performed on the document controller thread, reader validity can
  27. immediately be checked after the edit has been concluded, and any reader that has become invalid
  28. can be recreated.
  29. Note that encountering a failure in any individual read call does not invalidate the reader, so
  30. that the entity using the reader can decide whether to retry or to back out. This includes trying
  31. to read an audio source for which the host has currently disabled access: the failure will be
  32. immediately visible, but the reader will remain valid. This ensures that for example a realtime
  33. renderer can just keep reading and will be seeing proper samples again once sample access is
  34. re-enabled.
  35. If desired, the code calling readSamples() can also implement proper signaling of any read error
  36. to the document controller thread to trigger rebuilding the reader as needed. This will typically
  37. be done when implementing audio source analysis: if there is an error upon reading the samples
  38. that cannot be resolved within a reasonable timeout, then the analysis would be aborted. The
  39. document controller code that monitors the analysis tasks can evaluate this and re-launch a new
  40. analysis when appropriate (e.g. when access is re-enabled).
  41. When reading playback regions (directly or through a region sequence reader), the reader will
  42. represent the regions as a single source object that covers the union of all affected regions.
  43. The first sample produced by the reader thus will be the first sample of the earliest region.
  44. This means that the location of this region has to be taken into account by the calling code if
  45. it wants to relate the samples to the model or any other reader output.
  46. */
  47. //==============================================================================
  48. /**
  49. Subclass of AudioFormatReader that reads samples from a single ARA audio source.
  50. Plug-Ins typically use this from their rendering code, wrapped in a BufferingAudioReader
  51. to bridge between realtime rendering and non-realtime audio reading.
  52. The reader becomes invalidated if
  53. - the audio source content is updated in a way that affects its samples,
  54. - the audio source sample access is disabled, or
  55. - the audio source being read is destroyed.
  56. @tags{ARA}
  57. */
  58. class JUCE_API ARAAudioSourceReader : public AudioFormatReader,
  59. private ARAAudioSource::Listener
  60. {
  61. public:
  62. /** Use an ARAAudioSource to construct an audio source reader for the given \p audioSource. */
  63. explicit ARAAudioSourceReader (ARAAudioSource* audioSource);
  64. ~ARAAudioSourceReader() override;
  65. bool readSamples (int* const* destSamples,
  66. int numDestChannels,
  67. int startOffsetInDestBuffer,
  68. int64 startSampleInFile,
  69. int numSamples) override;
  70. /** Returns true as long as the reader's underlying ARAAudioSource remains accessible and its
  71. sample content is not changed.
  72. */
  73. bool isValid() const { return audioSourceBeingRead != nullptr; }
  74. /** Invalidate the reader - the reader will call this internally if needed, but can also be
  75. invalidated from the outside (from message thread only!).
  76. */
  77. void invalidate();
  78. void willUpdateAudioSourceProperties (ARAAudioSource* audioSource,
  79. ARAAudioSource::PropertiesPtr newProperties) override;
  80. void doUpdateAudioSourceContent (ARAAudioSource* audioSource,
  81. ARAContentUpdateScopes scopeFlags) override;
  82. void willEnableAudioSourceSamplesAccess (ARAAudioSource* audioSource, bool enable) override;
  83. void didEnableAudioSourceSamplesAccess (ARAAudioSource* audioSource, bool enable) override;
  84. void willDestroyAudioSource (ARAAudioSource* audioSource) override;
  85. private:
  86. ARAAudioSource* audioSourceBeingRead;
  87. std::unique_ptr<ARA::PlugIn::HostAudioReader> hostReader;
  88. ReadWriteLock lock;
  89. std::vector<void*> tmpPtrs;
  90. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ARAAudioSourceReader)
  91. };
  92. //==============================================================================
  93. /**
  94. Subclass of AudioFormatReader that reads samples from a group of playback regions.
  95. Plug-Ins typically use this to draw the output of a playback region in their UI.
  96. In order to read from playback regions, the reader requires an audio processor that acts as ARA
  97. playback renderer. Configuring the audio processor for real-time operation results in the reader
  98. being real-time capable too, unlike most other AudioFormatReaders. The reader instance will take
  99. care of adding all regions being read to the renderer and invoke its processBlock function in
  100. order to read the region samples.
  101. The reader becomes invalid if
  102. - any region properties are updated in a way that would affect its samples,
  103. - any region content is updated in a way that would affect its samples, or
  104. - any of its regions are destroyed.
  105. @tags{ARA}
  106. */
  107. class JUCE_API ARAPlaybackRegionReader : public AudioFormatReader,
  108. private ARAPlaybackRegion::Listener
  109. {
  110. public:
  111. /** Create an ARAPlaybackRegionReader instance to read the given \p playbackRegion, using the
  112. sample rate and channel count of the underlying ARAAudioSource.
  113. @param playbackRegion The playback region that should be read - must not be nullptr!
  114. */
  115. explicit ARAPlaybackRegionReader (ARAPlaybackRegion* playbackRegion);
  116. /** Create an ARAPlaybackRegionReader instance to read the given \p playbackRegions
  117. @param sampleRate The sample rate that should be used for reading.
  118. @param numChannels The channel count that should be used for reading.
  119. @param playbackRegions The vector of playback regions that should be read - must not be empty!
  120. All regions must be part of the same ARADocument.
  121. */
  122. ARAPlaybackRegionReader (double sampleRate, int numChannels,
  123. const std::vector<ARAPlaybackRegion*>& playbackRegions);
  124. ~ARAPlaybackRegionReader() override;
  125. /** Returns true as long as any of the reader's underlying playback region's haven't changed. */
  126. bool isValid() const { return (playbackRenderer != nullptr); }
  127. /** Invalidate the reader - this should be called if the sample content of any of the reader's
  128. ARAPlaybackRegions changes.
  129. */
  130. void invalidate();
  131. bool readSamples (int* const* destSamples,
  132. int numDestChannels,
  133. int startOffsetInDestBuffer,
  134. int64 startSampleInFile,
  135. int numSamples) override;
  136. void willUpdatePlaybackRegionProperties (ARAPlaybackRegion* playbackRegion,
  137. ARAPlaybackRegion::PropertiesPtr newProperties) override;
  138. void didUpdatePlaybackRegionContent (ARAPlaybackRegion* playbackRegion,
  139. ARAContentUpdateScopes scopeFlags) override;
  140. void willDestroyPlaybackRegion (ARAPlaybackRegion* playbackRegion) override;
  141. /** The starting point of the reader in playback samples */
  142. int64 startInSamples = 0;
  143. private:
  144. std::unique_ptr<ARAPlaybackRenderer> playbackRenderer;
  145. AudioPlayHead::PositionInfo positionInfo;
  146. ReadWriteLock lock;
  147. static constexpr int maximumBlockSize = 4 * 1024;
  148. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ARAPlaybackRegionReader)
  149. };
  150. } // namespace juce