diff --git a/src/sfizz/Config.h b/src/sfizz/Config.h index b99eb5e2..52d26a31 100644 --- a/src/sfizz/Config.h +++ b/src/sfizz/Config.h @@ -24,8 +24,7 @@ #pragma once namespace sfz { -enum class Oversampling: int -{ +enum Oversampling { x1 = 1, x2 = 2, x4 = 4, diff --git a/src/sfizz/FilePool.cpp b/src/sfizz/FilePool.cpp index 17e34f89..b6a5e46c 100644 --- a/src/sfizz/FilePool.cpp +++ b/src/sfizz/FilePool.cpp @@ -142,7 +142,7 @@ void sfz::FilePool::loadingThread() noexcept if (sndFile.error() != 0) continue; - DBG("Loading file for " << *promise->filename << " in the background"); + DBG("Loading file for " << promise->filename << " in the background"); const uint32_t frames = sndFile.frames(); promise->fileData = readFromFile(sndFile, frames); promise->dataReady = true; @@ -179,3 +179,19 @@ void sfz::FilePool::cleanupPromises() noexcept } } } + + +void sfz::FilePool::setOversamplingFactor(sfz::Oversampling factor) noexcept +{ + this->oversamplingFactor = factor; +} + +sfz::Oversampling sfz::FilePool::getOversamplingFactor() const noexcept +{ + return oversamplingFactor; +} + +uint32_t sfz::FilePool::getPreloadSize() const noexcept +{ + return preloadSize; +} diff --git a/src/sfizz/FilePool.h b/src/sfizz/FilePool.h index f5bd445c..08bae48a 100644 --- a/src/sfizz/FilePool.h +++ b/src/sfizz/FilePool.h @@ -133,6 +133,9 @@ public: void cleanupPromises() noexcept; FilePromisePtr getFilePromise(const std::string& filename) noexcept; void setPreloadSize(uint32_t preloadSize) noexcept; + uint32_t getPreloadSize() const noexcept; + void setOversamplingFactor(Oversampling factor) noexcept; + Oversampling getOversamplingFactor() const noexcept; private: fs::path rootDirectory; diff --git a/src/sfizz/Region.cpp b/src/sfizz/Region.cpp index 1e7a7758..2531ba81 100644 --- a/src/sfizz/Region.cpp +++ b/src/sfizz/Region.cpp @@ -644,9 +644,9 @@ float sfz::Region::getBaseGain() noexcept return normalizePercents(amplitude); } -uint32_t sfz::Region::getOffset() noexcept +uint32_t sfz::Region::getOffset(Oversampling factor) noexcept { - return offset + offsetDistribution(Random::randomGenerator); + return (offset + offsetDistribution(Random::randomGenerator)) * factor; } float sfz::Region::getDelay() noexcept @@ -654,9 +654,19 @@ float sfz::Region::getDelay() noexcept return delay + delayDistribution(Random::randomGenerator); } -uint32_t sfz::Region::trueSampleEnd() const noexcept +uint32_t sfz::Region::trueSampleEnd(Oversampling factor) const noexcept { - return min(sampleEnd, loopRange.getEnd()); + return min(sampleEnd, loopRange.getEnd()) * factor; +} + +uint32_t sfz::Region::loopStart(Oversampling factor) const noexcept +{ + return loopRange.getStart() * factor; +} + +uint32_t sfz::Region::loopEnd(Oversampling factor) const noexcept +{ + return loopRange.getEnd() * factor; } template @@ -757,13 +767,3 @@ float sfz::Region::velocityCurve(uint8_t velocity) const noexcept return gain; } - -void sfz::Region::setOversamplingFactor(sfz::Oversampling factor) noexcept -{ - oversamplingFactor = factor; -} - -sfz::Oversampling sfz::Region::getOversamplingFactor() const noexcept -{ - return oversamplingFactor; -} diff --git a/src/sfizz/Region.h b/src/sfizz/Region.h index 77c2a701..3692631b 100644 --- a/src/sfizz/Region.h +++ b/src/sfizz/Region.h @@ -201,7 +201,7 @@ struct Region { * * @return uint32_t */ - uint32_t getOffset() noexcept; + uint32_t getOffset(Oversampling factor = x1) noexcept; /** * @brief Get the region delay in seconds * @@ -214,14 +214,7 @@ struct Region { * * @return uint32_t */ - uint32_t trueSampleEnd() const noexcept; - /** - * @brief Can the region use the preloaded data only to play its full range? - * - * @return true - * @return false - */ - bool canUsePreloadedData() const noexcept; + uint32_t trueSampleEnd(Oversampling factor = x1) const noexcept; /** * @brief Parse a new opcode into the region to fill in the proper parameters. * This must be called multiple times for each opcode applying to this region. @@ -232,21 +225,8 @@ struct Region { */ bool parseOpcode(const Opcode& opcode); - /** - * @brief Set the oversampling factor to a new value. This will trigger updates of - * all the relevant values (sample ends, loop points, etc). It will also trigger - * preloading the file data again. - * - * @param factor - */ - void setOversamplingFactor(Oversampling factor) noexcept; - - /** - * @brief get the current oversampling factor - * - * @return Oversampling - */ - Oversampling getOversamplingFactor() const noexcept; + uint32_t loopStart(Oversampling factor = x1) const noexcept; + uint32_t loopEnd(Oversampling factor = x1) const noexcept; // Sound source: sample playback std::string sample {}; // Sample diff --git a/src/sfizz/Synth.cpp b/src/sfizz/Synth.cpp index 8c06283e..a6fea684 100644 --- a/src/sfizz/Synth.cpp +++ b/src/sfizz/Synth.cpp @@ -550,10 +550,7 @@ void sfz::Synth::setOversamplingFactor(sfz::Oversampling factor) noexcept for (auto& voice: voices) voice->reset(); - for (auto& region: regions) { - region->setOversamplingFactor(factor); - } - + resources.filePool.setOversamplingFactor(factor); oversamplingFactor = factor; } @@ -561,3 +558,18 @@ sfz::Oversampling sfz::Synth::getOversamplingFactor() const noexcept { return oversamplingFactor; } + +void sfz::Synth::setPreloadSize(uint32_t preloadSize) noexcept +{ + AtomicDisabler callbackDisabler{ canEnterCallback }; + while (inCallback) { + std::this_thread::sleep_for(1ms); + } + + resources.filePool.setPreloadSize(preloadSize); +} + +uint32_t sfz::Synth::getPreloadSize() const noexcept +{ + return resources.filePool.getPreloadSize(); +} diff --git a/src/sfizz/Synth.h b/src/sfizz/Synth.h index 775963c7..410c14f4 100644 --- a/src/sfizz/Synth.h +++ b/src/sfizz/Synth.h @@ -296,6 +296,20 @@ public: * @return Oversampling */ Oversampling getOversamplingFactor() const noexcept; + + /** + * @brief Set the preloaded file size. This will disable the callback. + * + * @param factor + */ + void setPreloadSize(uint32_t preloadSize) noexcept; + + /** + * @brief get the current preloaded file size + * + * @return Oversampling + */ + uint32_t getPreloadSize() const noexcept; protected: /** * @brief The parser callback; this is called by the parent object each time diff --git a/src/sfizz/Voice.cpp b/src/sfizz/Voice.cpp index 58a5700e..da2189ac 100644 --- a/src/sfizz/Voice.cpp +++ b/src/sfizz/Voice.cpp @@ -373,9 +373,9 @@ 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()), static_cast(source.getNumFrames())) - 1; - if (region->shouldLoop() && region->loopRange.getEnd() <= source.getNumFrames()) { - const auto offset = sampleEnd - static_cast(region->loopRange.getStart()); + const auto sampleEnd = min(static_cast(region->trueSampleEnd(currentPromise->oversamplingFactor)), 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) { if (*index > sampleEnd) { const auto remainingElements = static_cast(std::distance(index, indices.end()));