// SPDX-License-Identifier: GPLv3-or-later WITH Appstore-exception // Copyright (C) 2017 Xenakios // Copyright (C) 2020 Jesse Chappell #pragma once #include "../JuceLibraryCode/JuceHeader.h" class JUCE_API MyBufferingAudioSource : public PositionableAudioSource, private TimeSliceClient { public: //============================================================================== /** Creates a BufferingAudioSource. @param source the input source to read from @param backgroundThread a background thread that will be used for the background read-ahead. This object must not be deleted until after any BufferingAudioSources that are using it have been deleted! @param deleteSourceWhenDeleted if true, then the input source object will be deleted when this object is deleted @param numberOfSamplesToBuffer the size of buffer to use for reading ahead @param numberOfChannels the number of channels that will be played @param prefillBufferOnPrepareToPlay if true, then calling prepareToPlay on this object will block until the buffer has been filled */ MyBufferingAudioSource(PositionableAudioSource* source, TimeSliceThread& backgroundThread, bool deleteSourceWhenDeleted, int numberOfSamplesToBuffer, int numberOfChannels = 2, bool prefillBufferOnPrepareToPlay = true); ~MyBufferingAudioSource(); void prepareToPlay (int samplesPerBlockExpected, double sampleRate) override; void releaseResources() override; void getNextAudioBlock (const AudioSourceChannelInfo&) override; void setNextReadPosition (int64 newPosition) override; int64 getNextReadPosition() const override; int64 getTotalLength() const override { return source->getTotalLength(); } bool isLooping() const override { return source->isLooping(); } bool waitForNextAudioBlockReady (const AudioSourceChannelInfo& info, const uint32 timeout); [[nodiscard]] double getPercentReady() const; int getNumberOfChannels() { return numberOfChannels; } private: //============================================================================== OptionalScopedPointer source; TimeSliceThread& backgroundThread; int numberOfSamplesToBuffer, numberOfChannels; AudioBuffer buffer; CriticalSection bufferStartPosLock; WaitableEvent bufferReadyEvent; std::atomic bufferValidStart { 0 }, bufferValidEnd { 0 }, nextPlayPos { 0 }; double sampleRate = 0; bool wasSourceLooping = false, isPrepared = false, prefillBuffer; bool readNextBufferChunk(); void readBufferSection (int64 start, int length, int bufferOffset); int useTimeSlice() override; JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MyBufferingAudioSource) };