Skip to content

Commit

Permalink
Group Processor Ringout support (surge-synthesizer#1176)
Browse files Browse the repository at this point in the history
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 surge-synthesizer#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.
  • Loading branch information
baconpaul authored Aug 24, 2024
1 parent a5a2652 commit 9914059
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 6 deletions.
6 changes: 4 additions & 2 deletions src/dsp/processor/processor.h
Original file line number Diff line number Diff line change
Expand Up @@ -294,9 +294,11 @@ struct Processor : MoveableOnly<Processor>, 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
Expand Down
74 changes: 72 additions & 2 deletions src/engine/group.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,16 @@ template <bool OS> 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()
Expand All @@ -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<int32_t>::max();
ringoutTime = 0;
}
else
mx = std::max(mx, tl);
res = true;
}
}
ringoutMax = mx;
return res;
}

void Group::removeActiveZone()
Expand All @@ -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();
}
}
}

Expand Down Expand Up @@ -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];
Expand All @@ -380,6 +436,10 @@ void Group::attack()
osDownFilter.reset();
resetLFOs();
rePrepareAndBindGroupMatrix();

for (auto p : processors)
if (p)
p->init();
}

void Group::resetLFOs(int whichLFO)
Expand Down Expand Up @@ -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<Group>;
} // namespace scxt::engine
6 changes: 5 additions & 1 deletion src/engine/group.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ struct Group : MoveableOnly<Group>,
return res;
}

bool isActive() { return activeZones != 0; }
bool isActive() const;
void addActiveZone();
void removeActiveZone();

Expand Down Expand Up @@ -204,6 +204,10 @@ struct Group : MoveableOnly<Group>,
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<std::unique_ptr<Zone>> zoneContainer_t;

Expand Down

0 comments on commit 9914059

Please sign in to comment.