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
9.5KB

  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. #pragma once
  20. //==============================================================================
  21. /**
  22. Makes it easy to quickly draw scaled views of the waveform shape of an
  23. audio file.
  24. To use this class, just create an AudioThumbNail class for the file you want
  25. to draw, call setSource to tell it which file or resource to use, then call
  26. drawChannel() to draw it.
  27. The class will asynchronously scan the wavefile to create its scaled-down view,
  28. so you should make your UI repaint itself as this data comes in. To do this, the
  29. AudioThumbnail is a ChangeBroadcaster, and will broadcast a message when its
  30. listeners should repaint themselves.
  31. The thumbnail stores an internal low-res version of the wave data, and this can
  32. be loaded and saved to avoid having to scan the file again.
  33. @see AudioThumbnailCache, AudioThumbnailBase
  34. */
  35. class JUCE_API AudioThumbnail : public AudioThumbnailBase
  36. {
  37. public:
  38. //==============================================================================
  39. /** Creates an audio thumbnail.
  40. @param sourceSamplesPerThumbnailSample when creating a stored, low-res version
  41. of the audio data, this is the scale at which it should be done. (This
  42. number is the number of original samples that will be averaged for each
  43. low-res sample)
  44. @param formatManagerToUse the audio format manager that is used to open the file
  45. @param cacheToUse an instance of an AudioThumbnailCache - this provides a background
  46. thread and storage that is used to by the thumbnail, and the cache
  47. object can be shared between multiple thumbnails
  48. */
  49. AudioThumbnail (int sourceSamplesPerThumbnailSample,
  50. AudioFormatManager& formatManagerToUse,
  51. AudioThumbnailCache& cacheToUse);
  52. /** Destructor. */
  53. ~AudioThumbnail();
  54. //==============================================================================
  55. /** Clears and resets the thumbnail. */
  56. void clear() override;
  57. /** Specifies the file or stream that contains the audio file.
  58. For a file, just call
  59. @code
  60. setSource (new FileInputSource (file))
  61. @endcode
  62. You can pass a nullptr in here to clear the thumbnail.
  63. The source that is passed in will be deleted by this object when it is no longer needed.
  64. @returns true if the source could be opened as a valid audio file, false if this failed for
  65. some reason.
  66. */
  67. bool setSource (InputSource* newSource) override;
  68. /** Gives the thumbnail an AudioFormatReader to use directly.
  69. This will start parsing the audio in a background thread (unless the hash code
  70. can be looked-up successfully in the thumbnail cache). Note that the reader
  71. object will be held by the thumbnail and deleted later when no longer needed.
  72. The thumbnail will actually keep hold of this reader until you clear the thumbnail
  73. or change the input source, so the file will be held open for all this time. If
  74. you don't want the thumbnail to keep a file handle open continuously, you
  75. should use the setSource() method instead, which will only open the file when
  76. it needs to.
  77. */
  78. void setReader (AudioFormatReader* newReader, int64 hashCode) override;
  79. /** Resets the thumbnail, ready for adding data with the specified format.
  80. If you're going to generate a thumbnail yourself, call this before using addBlock()
  81. to add the data.
  82. */
  83. void reset (int numChannels, double sampleRate, int64 totalSamplesInSource = 0) override;
  84. /** Adds a block of level data to the thumbnail.
  85. Call reset() before using this, to tell the thumbnail about the data format.
  86. */
  87. void addBlock (int64 sampleNumberInSource, const AudioSampleBuffer& newData,
  88. int startOffsetInBuffer, int numSamples) override;
  89. //==============================================================================
  90. /** Reloads the low res thumbnail data from an input stream.
  91. This is not an audio file stream! It takes a stream of thumbnail data that would
  92. previously have been created by the saveTo() method.
  93. @see saveTo
  94. */
  95. bool loadFrom (InputStream& input) override;
  96. /** Saves the low res thumbnail data to an output stream.
  97. The data that is written can later be reloaded using loadFrom().
  98. @see loadFrom
  99. */
  100. void saveTo (OutputStream& output) const override;
  101. //==============================================================================
  102. /** Returns the number of channels in the file. */
  103. int getNumChannels() const noexcept override;
  104. /** Returns the length of the audio file, in seconds. */
  105. double getTotalLength() const noexcept override;
  106. /** Draws the waveform for a channel.
  107. The waveform will be drawn within the specified rectangle, where startTime
  108. and endTime specify the times within the audio file that should be positioned
  109. at the left and right edges of the rectangle.
  110. The waveform will be scaled vertically so that a full-volume sample will fill
  111. the rectangle vertically, but you can also specify an extra vertical scale factor
  112. with the verticalZoomFactor parameter.
  113. */
  114. void drawChannel (Graphics& g,
  115. const Rectangle<int>& area,
  116. double startTimeSeconds,
  117. double endTimeSeconds,
  118. int channelNum,
  119. float verticalZoomFactor) override;
  120. /** Draws the waveforms for all channels in the thumbnail.
  121. This will call drawChannel() to render each of the thumbnail's channels, stacked
  122. above each other within the specified area.
  123. @see drawChannel
  124. */
  125. void drawChannels (Graphics& g,
  126. const Rectangle<int>& area,
  127. double startTimeSeconds,
  128. double endTimeSeconds,
  129. float verticalZoomFactor) override;
  130. /** Returns true if the low res preview is fully generated. */
  131. bool isFullyLoaded() const noexcept override;
  132. /** Returns a value between 0 and 1 to indicate the progress towards loading the entire file. */
  133. double getProportionComplete() const noexcept;
  134. /** Returns the number of samples that have been set in the thumbnail. */
  135. int64 getNumSamplesFinished() const noexcept override;
  136. /** Returns the highest level in the thumbnail.
  137. Note that because the thumb only stores low-resolution data, this isn't
  138. an accurate representation of the highest value, it's only a rough approximation.
  139. */
  140. float getApproximatePeak() const override;
  141. /** Reads the approximate min and max levels from a section of the thumbnail.
  142. The lowest and highest samples are returned in minValue and maxValue, but obviously
  143. because the thumb only stores low-resolution data, these numbers will only be a rough
  144. approximation of the true values.
  145. */
  146. void getApproximateMinMax (double startTime, double endTime, int channelIndex,
  147. float& minValue, float& maxValue) const noexcept override;
  148. /** Returns the hash code that was set by setSource() or setReader(). */
  149. int64 getHashCode() const override;
  150. private:
  151. //==============================================================================
  152. AudioFormatManager& formatManagerToUse;
  153. AudioThumbnailCache& cache;
  154. class LevelDataSource;
  155. struct MinMaxValue;
  156. class ThumbData;
  157. class CachedWindow;
  158. friend class LevelDataSource;
  159. friend class ThumbData;
  160. friend class CachedWindow;
  161. friend struct ContainerDeletePolicy<LevelDataSource>;
  162. friend struct ContainerDeletePolicy<ThumbData>;
  163. friend struct ContainerDeletePolicy<CachedWindow>;
  164. ScopedPointer<LevelDataSource> source;
  165. ScopedPointer<CachedWindow> window;
  166. OwnedArray<ThumbData> channels;
  167. int32 samplesPerThumbSample;
  168. int64 totalSamples, numSamplesFinished;
  169. int32 numChannels;
  170. double sampleRate;
  171. CriticalSection lock;
  172. void clearChannelData();
  173. bool setDataSource (LevelDataSource* newSource);
  174. void setLevels (const MinMaxValue* const* values, int thumbIndex, int numChans, int numValues);
  175. void createChannels (int length);
  176. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioThumbnail)
  177. };