From da942c9244ef1ae8038e92f0a89a99609076d7f8 Mon Sep 17 00:00:00 2001 From: Paul Fd Date: Mon, 28 Jun 2021 10:27:24 +0200 Subject: [PATCH 1/2] Store files to load and their offset and defer loading Better behavior when using a file multiple times with different offsets. --- src/sfizz/Synth.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/sfizz/Synth.cpp b/src/sfizz/Synth.cpp index 1e200b58..d02271c5 100644 --- a/src/sfizz/Synth.cpp +++ b/src/sfizz/Synth.cpp @@ -581,6 +581,8 @@ void Synth::Impl::finalizeSfzLoad() size_t currentRegionIndex = 0; size_t currentRegionCount = layers_.size(); + absl::flat_hash_map filesToLoad; + auto removeCurrentRegion = [this, ¤tRegionIndex, ¤tRegionCount]() { const Region& region = layers_[currentRegionIndex]->getRegion(); DBG("Removing the region with sample " << *region.sampleId); @@ -679,10 +681,8 @@ void Synth::Impl::finalizeSfzLoad() return Default::offsetMod.bounds.clamp(sumOffsetCC); }(); - if (!filePool.preloadFile(*region.sampleId, maxOffset)) { - removeCurrentRegion(); - continue; - } + auto& toLoad = filesToLoad[*region.sampleId]; + toLoad = max(toLoad, maxOffset); } else if (!region.isGenerator()) { if (!wavePool.createFileWave(filePool, std::string(region.sampleId->filename()))) { @@ -763,6 +763,11 @@ void Synth::Impl::finalizeSfzLoad() ++currentRegionIndex; } + + for (const auto& toLoad: filesToLoad) { + filePool.preloadFile(toLoad.first, toLoad.second); + } + if (currentRegionCount < layers_.size()) { DBG("Removing " << (layers_.size() - currentRegionCount) << " out of " << layers_.size() << " regions"); From 559464684a6a8125ad84717dc64163c824046cec Mon Sep 17 00:00:00 2001 From: Paul Fd Date: Mon, 5 Jul 2021 11:31:24 +0200 Subject: [PATCH 2/2] CC Triggers also considers sequences --- src/sfizz/Layer.cpp | 14 ++++++++------ src/sfizz/Layer.h | 2 +- src/sfizz/Synth.cpp | 4 ++-- tests/SynthT.cpp | 26 ++++++++++++++++++++++++++ 4 files changed, 37 insertions(+), 9 deletions(-) diff --git a/src/sfizz/Layer.cpp b/src/sfizz/Layer.cpp index 146d2181..a90261da 100644 --- a/src/sfizz/Layer.cpp +++ b/src/sfizz/Layer.cpp @@ -129,7 +129,7 @@ bool Layer::registerNoteOff(int noteNumber, float velocity, float randValue) noe return false; } -bool Layer::registerCC(int ccNumber, float ccValue) noexcept +bool Layer::registerCC(int ccNumber, float ccValue, bool dontTrigger) noexcept { const Region& region = region_; @@ -152,14 +152,16 @@ bool Layer::registerCC(int ccNumber, float ccValue) noexcept else ccSwitched_.set(ccNumber, false); - if (!isSwitchedOn()) - return false; - - if (!region.triggerOnCC) + if (dontTrigger || !region.triggerOnCC) return false; if (auto triggerRange = region.ccTriggers.get(ccNumber)) { - if (triggerRange->containsWithEnd(ccValue)) + if (!triggerRange->containsWithEnd(ccValue)) + return false; + + sequenceSwitched_ = + ((sequenceCounter_++ % region.sequenceLength) == region.sequencePosition - 1); + if (isSwitchedOn()) return true; } diff --git a/src/sfizz/Layer.h b/src/sfizz/Layer.h index ede1490a..ec7a7806 100644 --- a/src/sfizz/Layer.h +++ b/src/sfizz/Layer.h @@ -88,7 +88,7 @@ public: * @return true if the region should trigger on this event * @return false */ - bool registerCC(int ccNumber, float ccValue) noexcept; + bool registerCC(int ccNumber, float ccValue, bool dontTrigger = false) noexcept; /** * @brief Register a new pitch wheel event. * diff --git a/src/sfizz/Synth.cpp b/src/sfizz/Synth.cpp index d02271c5..7a993090 100644 --- a/src/sfizz/Synth.cpp +++ b/src/sfizz/Synth.cpp @@ -726,7 +726,7 @@ void Synth::Impl::finalizeSfzLoad() // Defaults MidiState& midiState = resources_.getMidiState(); for (int cc = 0; cc < config::numCCs; cc++) { - layer.registerCC(cc, midiState.getCCValue(cc)); + layer.registerCC(cc, midiState.getCCValue(cc), true); } @@ -1951,7 +1951,7 @@ void Synth::Impl::resetAllControllers(int delay) noexcept for (const LayerPtr& layerPtr : layers_) { Layer& layer = *layerPtr; for (int cc = 0; cc < config::numCCs; ++cc) - layer.registerCC(cc, defaultCCValues_[cc]); + layer.registerCC(cc, defaultCCValues_[cc], true); } } diff --git a/tests/SynthT.cpp b/tests/SynthT.cpp index 639acefa..0905ae0b 100644 --- a/tests/SynthT.cpp +++ b/tests/SynthT.cpp @@ -1960,3 +1960,29 @@ TEST_CASE("[Synth] Resets all controllers to default values") REQUIRE( synth.getHdcc(56) == 64_norm ); REQUIRE( synth.getHdcc(78) == 0.0f ); } + +TEST_CASE("[Synth] Sequences also work on cc triggers") +{ + sfz::Synth synth; + std::vector messageList; + sfz::Client client(&messageList); + client.setReceiveCallback(&simpleMessageReceiver); + sfz::AudioBuffer buffer { 2, static_cast(synth.getSamplesPerBlock()) }; + synth.loadSfzString(fs::current_path() / "tests/TestFiles/sequence_cc_triggers.sfz", R"( + seq_length=3 + sample=*sine hikey=-1 start_locc61=0 start_hicc61=64 seq_position=1 + sample=*saw hikey=-1 start_locc61=0 start_hicc61=64 seq_position=2 + )"); + synth.cc(0, 61, 10); + synth.renderBlock(buffer); + REQUIRE( playingSamples(synth) == std::vector { "*sine" } ); + synth.cc(0, 61, 20); + synth.renderBlock(buffer); + REQUIRE( playingSamples(synth) == std::vector { "*sine", "*saw" } ); + synth.cc(0, 61, 20); + synth.renderBlock(buffer); + REQUIRE( playingSamples(synth) == std::vector { "*sine", "*saw" } ); + synth.cc(0, 61, 20); + synth.renderBlock(buffer); + REQUIRE( playingSamples(synth) == std::vector { "*sine", "*saw", "*sine" } ); +}