diff --git a/src/sfizz/FilePool.cpp b/src/sfizz/FilePool.cpp index 44bb446f..f08ea3be 100644 --- a/src/sfizz/FilePool.cpp +++ b/src/sfizz/FilePool.cpp @@ -60,18 +60,19 @@ std::unique_ptr> upsample4x(const sfz::AudioBuffer& buffe template std::unique_ptr> upsample8x(const sfz::AudioBuffer& buffer) { - auto tempBuffer = std::make_unique>(buffer.getNumFrames() * 4); + auto tempBuffer2x = std::make_unique>(buffer.getNumFrames() * 2); + auto tempBuffer4x = std::make_unique>(buffer.getNumFrames() * 4); auto outputBuffer = std::make_unique>(buffer.getNumChannels(), buffer.getNumFrames() * 8); for (int channelIdx = 0; channelIdx < buffer.getNumChannels(); channelIdx++) { - sfz::upsample2xStage(buffer.getConstSpan(channelIdx), absl::MakeSpan(*tempBuffer).first(buffer.getNumFrames() * 2)); - sfz::upsample4xStage(absl::MakeConstSpan(*tempBuffer).first(buffer.getNumFrames() * 2), absl::MakeSpan(*tempBuffer)); - sfz::upsample8xStage(absl::MakeConstSpan(*tempBuffer), outputBuffer->getSpan(channelIdx)); + sfz::upsample2xStage(buffer.getConstSpan(channelIdx), absl::MakeSpan(*tempBuffer2x)); + sfz::upsample4xStage(absl::MakeConstSpan(*tempBuffer2x), absl::MakeSpan(*tempBuffer4x)); + sfz::upsample8xStage(absl::MakeConstSpan(*tempBuffer4x), outputBuffer->getSpan(channelIdx)); } return outputBuffer; } template -std::unique_ptr> readFromFile(SndfileHandle& sndFile, uint32_t numFrames, sfz::Oversampling factor = sfz::Oversampling::x1) +std::unique_ptr> readFromFile(SndfileHandle& sndFile, uint32_t numFrames, sfz::Oversampling factor) { auto baseBuffer = std::make_unique>(sndFile.channels(), numFrames); if (sndFile.channels() == 1) { @@ -83,13 +84,17 @@ std::unique_ptr> readFromFile(SndfileHandle& sndFile, uint32 sfz::readInterleaved(tempReadBuffer->getSpan(0), baseBuffer->getSpan(0), baseBuffer->getSpan(1)); } - switch (factor) - { - case sfz::Oversampling::x1: return baseBuffer; - case sfz::Oversampling::x2: return upsample2x(*baseBuffer); - case sfz::Oversampling::x4: return upsample4x(*baseBuffer); - case sfz::Oversampling::x8: return upsample8x(*baseBuffer); - default: return {}; + switch (factor) { + case sfz::Oversampling::x1: + return baseBuffer; + case sfz::Oversampling::x2: + return upsample2x(*baseBuffer); + case sfz::Oversampling::x4: + return upsample4x(*baseBuffer); + case sfz::Oversampling::x8: + return upsample8x(*baseBuffer); + default: + return {}; } } @@ -159,7 +164,7 @@ sfz::FilePromisePtr sfz::FilePool::getFilePromise(const std::string& filename) n promise->preloadedData = preloaded->second.preloadedData; promise->sampleRate = preloaded->second.sampleRate; promise->oversamplingFactor = oversamplingFactor; - temporaryFilePromises.push_back(promise); + promiseQueue.enqueue(promise); } return promise; } @@ -172,30 +177,32 @@ void sfz::FilePool::setPreloadSize(uint32_t preloadSize) noexcept const uint32_t maxOffset = numFrames > this->preloadSize ? numFrames - this->preloadSize : 0; fs::path file { rootDirectory / std::string(preloadedFile.first) }; SndfileHandle sndFile(reinterpret_cast(file.c_str())); - preloadedFile.second.preloadedData = readFromFile(sndFile, preloadSize + maxOffset); + preloadedFile.second.preloadedData = readFromFile(sndFile, preloadSize + maxOffset, oversamplingFactor); } this->preloadSize = preloadSize; } void sfz::FilePool::loadingThread() noexcept { + FilePromisePtr promise; while (!quitThread) { - std::this_thread::sleep_for(1ms); - for (auto& promise : temporaryFilePromises) { - if (!promise->dataReady) { - fs::path file { rootDirectory / std::string(promise->filename) }; - SndfileHandle sndFile(reinterpret_cast(file.c_str())); - if (sndFile.error() != 0) - continue; - - DBG("Loading file for " << promise->filename << " in the background"); - const uint32_t frames = sndFile.frames(); - promise->fileData = readFromFile(sndFile, frames); - promise->dataReady = true; - } + promisesToClean.clear(); + if (!promiseQueue.try_dequeue(promise)) { + std::this_thread::sleep_for(0.1ms); + continue; } - promisesToClean.clear(); + fs::path file { rootDirectory / std::string(promise->filename) }; + SndfileHandle sndFile(reinterpret_cast(file.c_str())); + if (sndFile.error() != 0) + continue; + + DBG("Loading file for " << promise->filename << " in the background"); + const uint32_t frames = sndFile.frames(); + promise->fileData = readFromFile(sndFile, frames, oversamplingFactor); + promise->dataReady = true; + temporaryFilePromises.push_back(promise); + promise.reset(); } } @@ -233,7 +240,7 @@ void sfz::FilePool::setOversamplingFactor(sfz::Oversampling factor) noexcept const uint32_t maxOffset = numFrames > this->preloadSize ? numFrames - this->preloadSize : 0; fs::path file { rootDirectory / std::string(preloadedFile.first) }; SndfileHandle sndFile(reinterpret_cast(file.c_str())); - preloadedFile.second.preloadedData = readFromFile(sndFile, preloadSize + maxOffset); + preloadedFile.second.preloadedData = readFromFile(sndFile, preloadSize + maxOffset, factor); preloadedFile.second.sampleRate *= samplerateChange; } diff --git a/src/sfizz/FilePool.h b/src/sfizz/FilePool.h index 1bb9e557..48c3bdac 100644 --- a/src/sfizz/FilePool.h +++ b/src/sfizz/FilePool.h @@ -31,6 +31,7 @@ #include #include #include "absl/strings/string_view.h" +#include "moodycamel/readerwriterqueue.h" #include #include @@ -139,9 +140,9 @@ private: fs::path rootDirectory; void loadingThread() noexcept; + moodycamel::ReaderWriterQueue promiseQueue; uint32_t preloadSize { config::preloadSize }; Oversampling oversamplingFactor { config::defaultOversamplingFactor }; - // Signals bool quitThread { false }; bool emptyQueue { false }; diff --git a/src/sfizz/Voice.cpp b/src/sfizz/Voice.cpp index da2189ac..62c79437 100644 --- a/src/sfizz/Voice.cpp +++ b/src/sfizz/Voice.cpp @@ -60,9 +60,11 @@ void sfz::Voice::startVoice(Region* region, int delay, int channel, int number, return; } speedRatio = static_cast(currentPromise->sampleRate / this->sampleRate); + DBG("[Voice] Sample rate for " << region->sample << " is " << currentPromise->sampleRate); + DBG("[Voice] Speed ratio set to " << speedRatio); } - pitchRatio = region->getBasePitchVariation(number, value); + DBG("[Voice] Pitch ratio set to " << pitchRatio); baseVolumedB = region->getBaseVolumedB(number); @@ -373,7 +375,10 @@ void sfz::Voice::fillWithData(AudioSpan buffer) noexcept add(sourcePosition, indices); //FIXME : all this casting is driving me crazy - const auto sampleEnd = min(static_cast(region->trueSampleEnd(currentPromise->oversamplingFactor)), source.getNumFrames()) - 1; + const auto sampleEnd = min( + static_cast(region->trueSampleEnd(currentPromise->oversamplingFactor)), + static_cast(source.getNumFrames()) + ) - 1; if (region->shouldLoop() && region->loopEnd(currentPromise->oversamplingFactor) <= source.getNumFrames()) { const auto offset = sampleEnd - static_cast(region->loopStart(currentPromise->oversamplingFactor)); for (auto* index = indices.begin(); index < indices.end(); ++index) {