From 99140593c4591c3156f88b7bb09f7c64d92698ef Mon Sep 17 00:00:00 2001 From: Paul Date: Sat, 24 Aug 2024 13:09:00 -0400 Subject: [PATCH] Group Processor Ringout support (#1176) This adds support for a processor to implement tailLength and then keep a group alie through its tail. it also adds a reasonable tailLength implementation to ShortDelay (but no other processor). Addresses #852. Once we do the same with EG12 release that issue will be mostly wrapped, but we do need to visit all the procs for a tail. --- libs/sst/sst-effects | 2 +- src/dsp/processor/processor.h | 6 ++- src/engine/group.cpp | 74 ++++++++++++++++++++++++++++++++++- src/engine/group.h | 6 ++- 4 files changed, 82 insertions(+), 6 deletions(-) diff --git a/libs/sst/sst-effects b/libs/sst/sst-effects index 1da6ef6f..812bcaaf 160000 --- a/libs/sst/sst-effects +++ b/libs/sst/sst-effects @@ -1 +1 @@ -Subproject commit 1da6ef6ff6fff8a4b2ceb95af6492f49209af86a +Subproject commit 812bcaafa69faba81e8ec8d9e942ad88f6c00333 diff --git a/src/dsp/processor/processor.h b/src/dsp/processor/processor.h index 30c66b80..84c8c9eb 100644 --- a/src/dsp/processor/processor.h +++ b/src/dsp/processor/processor.h @@ -294,9 +294,11 @@ struct Processor : MoveableOnly, SampleRateSupport assert(false); } - // processors are required to be able to process stereo blocks if stereo is true in the - // constructor virtual void suspend() {} + + /* + * Tail length in samples + */ virtual int tail_length() { return 0; } float modulation_output; // processors can use this to output modulation data to the matrix diff --git a/src/engine/group.cpp b/src/engine/group.cpp index 4cffa134..fa64dd9a 100644 --- a/src/engine/group.cpp +++ b/src/engine/group.cpp @@ -260,6 +260,16 @@ template void Group::processWithOS(scxt::engine::Engine &e) { osDownFilter.process_block_D2(lOut, rOut, blockSize << 1); } + if (activeZones == 0) + { + ringoutTime += blockSize; + updateRingout(); + if (ringoutTime >= ringoutMax) + { + mUILag.instantlySnap(); + parentPart->removeActiveGroup(); + } + } } void Group::addActiveZone() @@ -269,7 +279,40 @@ void Group::addActiveZone() parentPart->addActiveGroup(); attack(); } + // Important we do this *after* the attack since it allows + // isActive to be accurate with processor ringout activeZones++; + ringoutTime = 0; +} + +bool Group::updateRingout() +{ + auto res{false}; + int32_t mx{0}; + for (auto &p : processors) + { + if (!p) + continue; + auto tl = p->tail_length(); + if (tl != 0) + { + if (tl == -1) + { + /* + * Someone is infinite. So set ringout time to 0 + * then if someone drops away from infinite we start + * counting at their max + */ + mx = std::numeric_limits::max(); + ringoutTime = 0; + } + else + mx = std::max(mx, tl); + res = true; + } + } + ringoutMax = mx; + return res; } void Group::removeActiveZone() @@ -278,8 +321,14 @@ void Group::removeActiveZone() activeZones--; if (activeZones == 0) { - mUILag.instantlySnap(); - parentPart->removeActiveGroup(); + ringoutMax = 0; + ringoutTime = 0; + auto hasRingout = updateRingout(); + if (!hasRingout) + { + mUILag.instantlySnap(); + parentPart->removeActiveGroup(); + } } } @@ -365,6 +414,13 @@ void Group::onProcessorTypeChanged(int w, dsp::processor::ProcessorType t) void Group::attack() { + if (isActive()) + { + // I *thin* we need to do this + rePrepareAndBindGroupMatrix(); + return; + } + for (int i = 0; i < processorsPerZoneAndGroup; ++i) { const auto &ps = processorStorage[i]; @@ -380,6 +436,10 @@ void Group::attack() osDownFilter.reset(); resetLFOs(); rePrepareAndBindGroupMatrix(); + + for (auto p : processors) + if (p) + p->init(); } void Group::resetLFOs(int whichLFO) @@ -417,5 +477,15 @@ void Group::resetLFOs(int whichLFO) } } +bool Group::isActive() const +{ + const auto az = activeZones != 0; + const auto procRO = ringoutTime < ringoutMax; + + // structuring it so we can do AEG and env LFO shortly also + + return az || procRO; +} + template struct HasGroupZoneProcessors; } // namespace scxt::engine diff --git a/src/engine/group.h b/src/engine/group.h index a37cbf36..d49e4be5 100644 --- a/src/engine/group.h +++ b/src/engine/group.h @@ -152,7 +152,7 @@ struct Group : MoveableOnly, return res; } - bool isActive() { return activeZones != 0; } + bool isActive() const; void addActiveZone(); void removeActiveZone(); @@ -204,6 +204,10 @@ struct Group : MoveableOnly, void onProcessorTypeChanged(int w, dsp::processor::ProcessorType t); uint32_t activeZones{0}; + int32_t ringoutTime{0}; + int32_t ringoutMax{0}; + + bool updateRingout(); typedef std::vector> zoneContainer_t;