43 inline int8 getMinValue()
const noexcept {
return values[0]; }
44 inline int8 getMaxValue()
const noexcept {
return values[1]; }
59 if (values[0] == values[1])
68 inline bool isNonZero()
const noexcept
70 return values[1] > values[0];
73 inline int getPeak()
const noexcept
75 return jmax (std::abs ((
int) values[0]),
76 std::abs ((
int) values[1]));
106 int numSamples)
override
126 dest.clearSamples (numSamples);
134 using SourceNumericalType =
165 enum { timeBeforeDeletingReader = 3000 };
175 if (reader !=
nullptr)
177 lengthInSamples = reader->lengthInSamples;
178 numChannels = reader->numChannels;
179 sampleRate = reader->sampleRate;
181 if (lengthInSamples <= 0 || isFullyLoaded())
192 if (reader ==
nullptr)
196 if (reader !=
nullptr)
203 if (reader !=
nullptr)
205 if (levels.size() < (
int) reader->numChannels)
206 levels.insertMultiple (0, {}, (
int) reader->numChannels - levels.size());
208 reader->readMaxLevels (startSample, numSamples, levels.getRawDataPointer(), (
int) reader->numChannels);
214 void releaseResources()
224 if (reader !=
nullptr && source !=
nullptr)
241 if (reader !=
nullptr)
243 if (! readNextBlock())
256 bool isFullyLoaded()
const noexcept
258 return numSamplesFinished >= lengthInSamples;
266 int64 lengthInSamples = 0, numSamplesFinished = 0;
267 double sampleRate = 0;
268 unsigned int numChannels = 0;
272 AudioThumbnail& owner;
275 CriticalSection readerLock;
280 if (reader ==
nullptr && source !=
nullptr)
289 if (! isFullyLoaded())
291 auto numToDo = (
int)
jmin (256 * (
int64) owner.samplesPerThumbSample, lengthInSamples - numSamplesFinished);
295 auto startSample = numSamplesFinished;
304 for (
int i = 0; i < (
int) numChannels; ++i)
311 reader->readMaxLevels ((
firstThumbIndex + i) * owner.samplesPerThumbSample,
312 owner.samplesPerThumbSample,
levelsRead, (
int) numChannels);
314 for (
int j = 0;
j < (
int) numChannels; ++
j)
328 return isFullyLoaded();
347 int getSize()
const noexcept
354 if (startSample >= 0)
363 auto& v = data.getReference (startSample);
365 if (v.getMinValue() <
mn)
mn = v.getMinValue();
366 if (v.getMaxValue() >
mx)
mx = v.getMaxValue();
385 if (startIndex +
numValues > data.size())
388 auto* dest = getData (startIndex);
394 void resetPeak()
noexcept
399 int getPeak()
noexcept
405 auto peak = s.getPeak();
407 if (peak > peakLevel)
436 cacheNeedsRefilling =
true;
440 const double startTime,
const double endTime,
445 if (refillCache (area.
getWidth(), startTime, endTime, rate,
451 if (! clip.isEmpty())
463 auto x = (
float) clip.getX();
465 for (
int w = clip.getWidth(); --w >= 0;)
486 double cachedStart = 0, cachedTimePerPixel = 0;
487 int numChannelsCached = 0, numSamplesCached = 0;
488 bool cacheNeedsRefilling =
true;
490 bool refillCache (
int numSamples,
double startTime,
double endTime,
496 if (numSamples <= 0 ||
timePerPixel <= 0.0 || rate <= 0)
502 if (numSamples == numSamplesCached
506 && ! cacheNeedsRefilling)
508 return ! cacheNeedsRefilling;
511 numSamplesCached = numSamples;
513 cachedStart = startTime;
515 cacheNeedsRefilling =
false;
517 ensureSize (numSamples);
525 for (i = 0; i < numSamples; ++i)
531 if (sample >=
levelData->lengthInSamples)
538 levelData->getLevels (sample,
jmax (1, nextSample - sample), levels);
551 numSamplesCached = i;
564 startTime = cachedStart;
567 for (
int i = numSamples; --i >= 0;)
587 return data.getRawDataPointer() +
channelNum * numSamplesCached
591 void ensureSize (
const int numSamples)
604 : formatManagerToUse (formatManager),
623void AudioThumbnail::clearChannelData()
625 window->invalidate();
627 totalSamples = numSamplesFinished = 0;
646void AudioThumbnail::createChannels (
const int length)
648 while (channels.size() < numChannels)
649 channels.add (
new ThumbData (length));
663 samplesPerThumbSample = input.
readInt();
675 channels.getUnchecked (
chan)->getData (i)->read (input);
684 const int numThumbnailSamples = channels.size() == 0 ? 0 : channels.getUnchecked (0)->getSize();
686 output.
write (
"jatm", 4);
687 output.
writeInt (samplesPerThumbSample);
698 channels.getUnchecked (
chan)->getData (i)->write (output);
702bool AudioThumbnail::setDataSource (LevelDataSource*
newSource)
706 numSamplesFinished = 0;
707 auto wasSuccessful = [&] {
return sampleRate > 0 && totalSamples > 0; };
713 source->lengthInSamples = totalSamples;
714 source->sampleRate = sampleRate;
715 source->numChannels = (
unsigned int) numChannels;
716 source->numSamplesFinished = numSamplesFinished;
724 source->initialise (numSamplesFinished);
726 totalSamples = source->lengthInSamples;
727 sampleRate = source->sampleRate;
728 numChannels = (
int32) source->numChannels;
730 createChannels (1 + (
int) (totalSamples / samplesPerThumbSample));
762 return source ==
nullptr ? 0 : source->hashCode;
773 auto lastThumbIndex = (
int) ((startSample + numSamples + (samplesPerThumbSample - 1)) / samplesPerThumbSample);
789 for (
int i = 0; i <
numToDo; ++i)
791 auto start = i * samplesPerThumbSample;
792 dest[i].setFloat (FloatVectorOperations::findMinAndMax (
sourceData + start,
jmin (samplesPerThumbSample, numSamples - start)));
804 for (
int i =
jmin (
numChans, channels.size()); --i >= 0;)
810 if (numSamplesFinished >= start &&
end > numSamplesFinished)
811 numSamplesFinished =
end;
813 totalSamples =
jmax (numSamplesFinished, totalSamples);
814 window->invalidate();
828 return sampleRate > 0 ? ((
double) totalSamples / sampleRate) : 0.0;
834 return numSamplesFinished >= totalSamples - samplesPerThumbSample;
840 return jlimit (0.0, 1.0, (
double) numSamplesFinished / (
double)
jmax ((
int64) 1, totalSamples));
846 return numSamplesFinished;
854 for (
auto* c : channels)
855 peak =
jmax (peak, c->getPeak());
857 return (
float)
jlimit (0, 127, peak) / 127.0f;
861 float& minValue,
float& maxValue)
const noexcept
865 auto* data = channels [channelIndex];
867 if (data !=
nullptr && sampleRate > 0)
870 auto lastThumbIndex = (
int) (((endTime * sampleRate) + samplesPerThumbSample - 1) / samplesPerThumbSample);
875 minValue = result.getMinValue() / 128.0f;
876 maxValue = result.getMaxValue() / 128.0f;
885 sampleRate, numChannels, samplesPerThumbSample, source.
get(), channels);
891 for (
int i = 0; i < numChannels; ++i)
Holds a resizable array of primitive or copy-by-value objects.
int size() const noexcept
Returns the current number of elements in the array.
ElementType & getReference(int index) noexcept
Returns a direct reference to one of the elements in the array, without checking the index passed in.
bool readSamples(int *const *destChannels, int numDestChannels, int startOffsetInDestBuffer, int64 startSampleInFile, int numSamples) override
Subclasses must implement this method to perform the low-level read operation.
A multi-channel buffer containing floating point audio samples.
int getNumChannels() const noexcept
Returns the number of channels of audio data that this buffer contains.
int getNumSamples() const noexcept
Returns the number of samples allocated in each of the buffer's channels.
const Type * getReadPointer(int channelNumber) const noexcept
Returns a pointer to an array of read-only samples in one of the buffer's channels.
Used as a template parameter for AudioData::Pointer.
void convertSamples(Pointer source, int numSamples) const noexcept
Writes a stream of samples into this pointer from another pointer.
An instance of this class is used to manage multiple AudioThumbnail objects.
TimeSliceThread & getTimeSliceThread() noexcept
Returns the thread that client thumbnails can use.
void storeThumb(const AudioThumbnailBase &thumb, int64 hashCode)
Stores the cacheable data from the specified thumb in this cache.
bool loadThumb(AudioThumbnailBase &thumb, int64 hashCode)
Reloads the specified thumb if this cache contains the appropriate stored data.
int useTimeSlice() override
Called back by a TimeSliceThread.
Makes it easy to quickly draw scaled views of the waveform shape of an audio file.
void drawChannels(Graphics &g, const Rectangle< int > &area, double startTimeSeconds, double endTimeSeconds, float verticalZoomFactor) override
Draws the waveforms for all channels in the thumbnail.
~AudioThumbnail() override
Destructor.
void getApproximateMinMax(double startTime, double endTime, int channelIndex, float &minValue, float &maxValue) const noexcept override
Reads the approximate min and max levels from a section of the thumbnail.
double getTotalLength() const noexcept override
Returns the length of the audio file, in seconds.
float getApproximatePeak() const override
Returns the highest level in the thumbnail.
int64 getNumSamplesFinished() const noexcept override
Returns the number of samples that have been set in the thumbnail.
void clear() override
Clears and resets the thumbnail.
AudioThumbnail(int sourceSamplesPerThumbnailSample, AudioFormatManager &formatManagerToUse, AudioThumbnailCache &cacheToUse)
Creates an audio thumbnail.
double getProportionComplete() const noexcept
Returns a value between 0 and 1 to indicate the progress towards loading the entire file.
void saveTo(OutputStream &output) const override
Saves the low res thumbnail data to an output stream.
bool loadFrom(InputStream &input) override
Reloads the low res thumbnail data from an input stream.
int64 getHashCode() const override
Returns the hash code that was set by setSource() or setReader().
void reset(int numChannels, double sampleRate, int64 totalSamplesInSource=0) override
Resets the thumbnail, ready for adding data with the specified format.
int getNumChannels() const noexcept override
Returns the number of channels in the file.
void drawChannel(Graphics &g, const Rectangle< int > &area, double startTimeSeconds, double endTimeSeconds, int channelNum, float verticalZoomFactor) override
Draws the waveform for a channel.
void addBlock(int64 sampleNumberInSource, const AudioBuffer< float > &newData, int startOffsetInBuffer, int numSamples) override
Adds a block of level data to the thumbnail.
void setReader(AudioFormatReader *newReader, int64 hashCode) override
Gives the thumbnail an AudioFormatReader to use directly.
bool setSource(InputSource *newSource) override
Specifies the file or stream that contains the audio file.
bool isFullyLoaded() const noexcept override
Returns true if the low res preview is fully generated.
void sendChangeMessage()
Causes an asynchronous change message to be sent to all the registered listeners.
Automatically locks and unlocks a mutex object.
A graphics context, used for drawing a component or image.
void fillRectList(const RectangleList< float > &rectangles) const
Fills a set of rectangles using the current colour or brush.
Rectangle< int > getClipBounds() const
Returns the position of the bounding box for the current clipping region.
Very simple container class to hold a pointer to some data on the heap.
The base class for streams that write data to some kind of destination.
virtual bool write(const void *dataToWrite, size_t numberOfBytes)=0
Writes a block of data to the stream.
virtual bool writeInt64(int64 value)
Writes a 64-bit integer to the stream in a little-endian byte order.
virtual bool writeInt(int value)
Writes a 32-bit integer to the stream in a little-endian byte order.
An array designed for holding objects.
A general-purpose range object, that simply represents any linear range with a start and end point.
Maintains a set of rectangles as a complex region.
void ensureStorageAllocated(int minNumRectangles)
Increases the internal storage to hold a minimum number of rectangles.
Manages a rectangle and allows geometric operations to be performed on it.
ValueType getX() const noexcept
Returns the x coordinate of the rectangle's left-hand-side.
Rectangle getIntersection(Rectangle other) const noexcept
Returns the region that is the overlap between this and another rectangle.
ValueType getBottom() const noexcept
Returns the y coordinate of the rectangle's bottom edge.
ValueType getWidth() const noexcept
Returns the width of the rectangle.
ValueType getY() const noexcept
Returns the y coordinate of the rectangle's top edge.
Rectangle withWidth(ValueType newWidth) const noexcept
Returns a rectangle which has the same position and height as this one, but with a different width.
ValueType getHeight() const noexcept
Returns the height of the rectangle.
Used by the TimeSliceThread class.
void removeTimeSliceClient(TimeSliceClient *clientToRemove)
Removes a client from the list.
void addTimeSliceClient(TimeSliceClient *clientToAdd, int millisecondsBeforeStarting=0)
Adds a client to the list.
static uint32 getMillisecondCounter() noexcept
Returns the number of millisecs since a fixed event (usually system startup).
#define JUCE_ASSERT_MESSAGE_MANAGER_IS_LOCKED
This macro is used to catch unsafe use of functions which expect to only be called on the message thr...
CriticalSection::ScopedLockType ScopedLock
Automatically locks and unlocks a CriticalSection object.
constexpr bool approximatelyEqual(Type a, Type b, Tolerance< Type > tolerance=Tolerance< Type >{} .withAbsolute(std::numeric_limits< Type >::min()) .withRelative(std::numeric_limits< Type >::epsilon()))
Returns true if the two floating-point numbers are approximately equal.
constexpr Type jmin(Type a, Type b)
Returns the smaller of two values.
constexpr Type jmax(Type a, Type b)
Returns the larger of two values.
RangedDirectoryIterator end(const RangedDirectoryIterator &)
Returns a default-constructed sentinel value.
Type jlimit(Type lowerLimit, Type upperLimit, Type valueToConstrain) noexcept
Constrains a value to keep it within a given range.
signed int int32
A platform-independent 32-bit signed integer type.
signed char int8
A platform-independent 8-bit signed integer type.
Type unalignedPointerCast(void *ptr) noexcept
Casts a pointer to another type via void*, which suppresses the cast-align warning which sometimes ar...
bool isPositiveAndBelow(Type1 valueToTest, Type2 upperLimit) noexcept
Returns true if a value is at least zero, and also below a specified upper limit.
CriticalSection::ScopedUnlockType ScopedUnlock
Automatically unlocks and re-locks a CriticalSection object.
int roundToInt(const FloatType value) noexcept
Fast floating-point-to-integer conversion.
long long int64
A platform-independent 64-bit integer type.