/* ============================================================================== SampleLoader.h Created: 14 Jun 2024 5:37:01pm Author: binya ============================================================================== */ #pragma once #include #include "BufferUtils.h" /** A utility thread for asynchronously loading samples */ class LoaderThread final : public juce::Thread { public: LoaderThread(std::unique_ptr formatReader, int threadID) : Thread("Loader_Thread_" + juce::String(threadID)), reader{std::move(formatReader)} { } ~LoaderThread() override { stopThread(-1); } void cancel() { canceled = true; } juce::AudioBuffer* releaseSample() { return newSample.release(); } juce::AudioFormatReader* releaseReader() { return reader.release(); } const juce::String& getLoadedSampleHash() const { return sampleHash; } private: void run() override { newSample = std::make_unique>(int(reader->numChannels), int(reader->lengthInSamples)); reader->read(&*newSample, 0, int(reader->lengthInSamples), 0, true, true); sampleHash = getSampleHash(*newSample); if (canceled) newSample = nullptr; signalThreadShouldExit(); } std::unique_ptr reader; std::unique_ptr> newSample; juce::String sampleHash; bool canceled{ false }; }; /** Asynchronously loads a sample */ class SampleLoader final : public juce::Thread::Listener { public: void loadSample(std::unique_ptr formatReader, const std::function>& loadedSample, const juce::String& sampleHash, const std::unique_ptr& reader)>& onCompletion) { loading = true; completionCallback = onCompletion; for (const auto& thread : threads) { thread->cancel(); thread->removeListener(this); } auto newThread = std::make_unique(std::move(formatReader), ++ids); newThread->addListener(this); newThread->startThread(); threads.emplace_back(std::move(newThread)); } bool isLoading() const { return loading; } private: void exitSignalSent() override { juce::MessageManager::callAsync([this]() -> void { auto& lastThread = threads[threads.size() - 1]; completionCallback(std::unique_ptr>(lastThread->releaseSample()), lastThread->getLoadedSampleHash(), std::unique_ptr(lastThread->releaseReader())); loading = false; }); } //============================================================================== int ids{ 0 }; std::vector> threads; std::function>, const juce::String&, std::unique_ptr)> completionCallback; bool loading{ false }; };