Skip to content

Commit

Permalink
Unused LFO/EG Optimization - Voice
Browse files Browse the repository at this point in the history
This commit means the voice only runs and inits the LFOs and
EGs used in the routing table. Still have group to go.

Addresses #1041
  • Loading branch information
baconpaul committed Aug 25, 2024
1 parent 4e53c7a commit 915cf4a
Show file tree
Hide file tree
Showing 12 changed files with 154 additions and 68 deletions.
2 changes: 1 addition & 1 deletion src-ui/app/edit-screen/EditScreen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ EditScreen::ZoneOrGroupElements<ZGTrait>::ZoneOrGroupElements(EditScreen *parent
parent->addChildComponent(*modPane);
parent->addChildComponent(*outPane);

for (int i = 0; i < scxt::egPerGroup; ++i)
for (int i = 0; i < scxt::egsPerGroup; ++i)
{
auto egt = std::make_unique<edit_screen::AdsrPane>(parent->editor, i, forZone);
eg[i] = std::move(egt);
Expand Down
3 changes: 2 additions & 1 deletion src/configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,11 @@ static constexpr size_t maxProcessorFloatParams{9};
static constexpr size_t maxProcessorIntParams{5};

static constexpr uint16_t lfosPerZone{4};
static constexpr uint16_t egsPerZone{2};
static constexpr uint16_t maxSamplesPerZone{16};

static constexpr uint16_t lfosPerGroup{4};
static constexpr uint16_t egPerGroup{2};
static constexpr uint16_t egsPerGroup{2};
static constexpr uint16_t processorsPerZoneAndGroup{4};

/*
Expand Down
3 changes: 3 additions & 0 deletions src/engine/group.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,7 @@ const engine::Engine *Group::getEngine() const

void Group::setupOnUnstream(const engine::Engine &e)
{
onRoutingChanged();
rePrepareAndBindGroupMatrix();

for (auto i = 0U; i < engine::lfosPerZone; ++i)
Expand Down Expand Up @@ -495,5 +496,7 @@ bool Group::isActive() const
return haz || hae || ir;
}

void Group::onRoutingChanged() { SCLOG_ONCE("Implement Group LFO modulator use optimization"); }

template struct HasGroupZoneProcessors<Group>;
} // namespace scxt::engine
3 changes: 2 additions & 1 deletion src/engine/group.h
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ struct Group : MoveableOnly<Group>,
lipol outputAmp;
lipolOS outputAmpOS;

std::array<modulation::modulators::AdsrStorage, egPerGroup> gegStorage{};
std::array<modulation::modulators::AdsrStorage, egsPerGroup> gegStorage{};

std::array<modulation::ModulatorStorage, lfosPerGroup> modulatorStorage;
std::array<modulation::modulators::StepLFO, lfosPerGroup> stepLfos;
Expand All @@ -182,6 +182,7 @@ struct Group : MoveableOnly<Group>,
modulation::GroupMatrix modMatrix;
modulation::GroupMatrixEndpoints endpoints;
modulation::GroupMatrix::RoutingTable routingTable;
void onRoutingChanged();
void rePrepareAndBindGroupMatrix();

inline float envelope_rate_linear_nowrap(float f)
Expand Down
43 changes: 43 additions & 0 deletions src/engine/zone.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,49 @@ void Zone::terminateAllVoices()
toCleanUp[i]->cleanupVoice();
}
}
void Zone::onRoutingChanged()
{
voice::modulation::MatrixEndpoints::Sources usedForScanning(nullptr);
std::fill(lfosActive.begin(), lfosActive.end(), false);
egsActive[0] = true; // the AEG always runs
egsActive[1] = false;
auto doCheck = [this, &usedForScanning](const voice::modulation::MatrixEndpoints::SR &src) {
for (int i = 0; i < lfosPerZone; ++i)
{
if (src == usedForScanning.lfoSources.sources[i])
{
lfosActive[i] = true;
}
}
if (src == usedForScanning.aegSource)
{
egsActive[0] = true;
}

if (src == usedForScanning.eg2Source)
{
egsActive[1] = true;
}
};
for (auto &r : routingTable.routes)
{
// If we aren't mapped anywhere we don't care about this row
if (!r.target.has_value())
continue;

// Similarly if we aren't active
if (!r.active)
continue;

if (r.source.has_value())
doCheck(*r.source);

if (r.sourceVia.has_value())
doCheck(*r.sourceVia);
}
// SCLOG("Post check: " << SCD(lfosActive[0]) << SCD(lfosActive[1]) << SCD(lfosActive[2])
// << SCD(lfosActive[3]) << SCD(egsActive[0]) << SCD(egsActive[1]))
}

template struct HasGroupZoneProcessors<Zone>;
} // namespace scxt::engine
4 changes: 4 additions & 0 deletions src/engine/zone.h
Original file line number Diff line number Diff line change
Expand Up @@ -225,9 +225,13 @@ struct Zone : MoveableOnly<Zone>, HasGroupZoneProcessors<Zone>, SampleRateSuppor
void removeVoice(voice::Voice *);

voice::modulation::Matrix::RoutingTable routingTable;
void onRoutingChanged();

std::array<modulation::ModulatorStorage, lfosPerZone> modulatorStorage;

std::array<bool, lfosPerZone> lfosActive{};
std::array<bool, egsPerZone> egsActive{};

// 0 is the AEG, 1 is EG2
std::array<modulation::modulators::AdsrStorage, 2> egStorage;

Expand Down
99 changes: 50 additions & 49 deletions src/json/engine_traits.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,8 @@ SC_STREAMDEF(scxt::engine::Engine, SC_FROM({
to.getPatch()->setSampleRate(to.getSampleRate());
}))

SC_STREAMDEF(scxt::engine::Patch, SC_FROM({
v = {{"parts", from.getParts()}, {"busses", from.busses}};
}),
SC_TO({
SC_STREAMDEF(scxt::engine::Patch,
SC_FROM({ v = {{"parts", from.getParts()}, {"busses", from.busses}}; }), SC_TO({
auto &patch = to;
patch.resetToBlankPatch();

Expand Down Expand Up @@ -147,31 +145,32 @@ SC_STREAMDEF(
findOrSet(v, "s", false, to.solo);
}));

SC_STREAMDEF(
scxt::engine::Part, SC_FROM({
// TODO: Do a non-empty part stream with the If variant
v = {{"config", from.configuration}, {"groups", from.getGroups()}, {"macros", from.macros}};
}),
SC_TO({
auto &part = to;
part.clearGroups();

if (SC_UNSTREAMING_FROM_PRIOR_TO(0x2024'08'18))
{
findIf(v, "channel", part.configuration.channel);
}
else
{
findIf(v, "config", part.configuration);
}
findIf(v, "macros", part.macros);
auto vzones = v.at("groups").get_array();
for (const auto vz : vzones)
{
auto idx = part.addGroup() - 1;
vz.to(*(part.getGroup(idx)));
}
}))
SC_STREAMDEF(scxt::engine::Part, SC_FROM({
// TODO: Do a non-empty part stream with the If variant
v = {{"config", from.configuration},
{"groups", from.getGroups()},
{"macros", from.macros}};
}),
SC_TO({
auto &part = to;
part.clearGroups();

if (SC_UNSTREAMING_FROM_PRIOR_TO(0x2024'08'18))
{
findIf(v, "channel", part.configuration.channel);
}
else
{
findIf(v, "config", part.configuration);
}
findIf(v, "macros", part.macros);
auto vzones = v.at("groups").get_array();
for (const auto vz : vzones)
{
auto idx = part.addGroup() - 1;
vz.to(*(part.getGroup(idx)));
}
}))

SC_STREAMDEF(scxt::engine::Group::GroupOutputInfo, SC_FROM({
v = {{"amplitude", t.amplitude}, {"pan", t.pan},
Expand Down Expand Up @@ -377,6 +376,7 @@ SC_STREAMDEF(scxt::engine::Zone, SC_FROM({
findIfArray(v, "modulatorStorage", zone.modulatorStorage);
findOrDefault(v, "aegStorage", zone.egStorage[0]);
findOrDefault(v, "eg2Storage", zone.egStorage[1]);
zone.onRoutingChanged();
}));

SC_STREAMDEF(scxt::engine::KeyboardRange, SC_FROM({
Expand Down Expand Up @@ -409,15 +409,15 @@ SC_STREAMDEF(engine::Engine::EngineStatusMessage, SC_FROM({
findIf(v, "runningEnvironment", to.runningEnvironment);
}));

SC_STREAMDEF(
engine::Bus, SC_FROM({
v = {{"busSendStorage", t.busSendStorage}, {"busEffectStorage", t.busEffectStorage}};
}),
SC_TO({
findIf(v, "busSendStorage", to.busSendStorage);
findIf(v, "busEffectStorage", to.busEffectStorage);
to.resetSendState();
}));
SC_STREAMDEF(engine::Bus, SC_FROM({
v = {{"busSendStorage", t.busSendStorage},
{"busEffectStorage", t.busEffectStorage}};
}),
SC_TO({
findIf(v, "busSendStorage", to.busSendStorage);
findIf(v, "busEffectStorage", to.busEffectStorage);
to.resetSendState();
}));

STREAM_ENUM_WITH_DEFAULT(engine::Bus::BusSendStorage::AuxLocation,
engine::Bus::BusSendStorage::AuxLocation::POST_VCA,
Expand Down Expand Up @@ -478,18 +478,19 @@ SC_STREAMDEF(engine::BusEffectStorage, SC_FROM({
}
}));

SC_STREAMDEF(
engine::Patch::Busses, SC_FROM({
v = {{"mainBus", t.mainBus}, {"partBusses", t.partBusses}, {"auxBusses", t.auxBusses}};
}),
SC_TO({
findIf(v, "mainBus", to.mainBus);
findIf(v, "partBusses", to.partBusses);
findIf(v, "auxBusses", to.auxBusses);
SC_STREAMDEF(engine::Patch::Busses, SC_FROM({
v = {{"mainBus", t.mainBus},
{"partBusses", t.partBusses},
{"auxBusses", t.auxBusses}};
}),
SC_TO({
findIf(v, "mainBus", to.mainBus);
findIf(v, "partBusses", to.partBusses);
findIf(v, "auxBusses", to.auxBusses);

to.reconfigureSolo();
to.reconfigureOutputBusses();
}));
to.reconfigureSolo();
to.reconfigureOutputBusses();
}));

} // namespace scxt::json
#endif // SHORTCIRCUIT_ENGINE_TRAITS_H
16 changes: 11 additions & 5 deletions src/messaging/client/modulation_messages.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,16 @@ inline void indexedZoneRoutingRowUpdated(const indexedZoneRowUpdate_t &payload,
cont.scheduleAudioThreadCallback(
[index = i, row = r, zs = sz](auto &eng) {
for (const auto &z : zs)
eng.getPatch()
->getPart(z.part)
->getGroup(z.group)
->getZone(z.zone)
->routingTable.routes[index] = row;
{
auto &zone =
eng.getPatch()->getPart(z.part)->getGroup(z.group)->getZone(z.zone);
auto depthChange = (zone->routingTable.routes[index].depth != row.depth);
zone->routingTable.routes[index] = row;
if (!depthChange)
{
zone->onRoutingChanged();
}
}
},
[doUpdate = b](auto &eng) {
if (doUpdate)
Expand Down Expand Up @@ -106,6 +111,7 @@ inline void indexedGroupRoutingRowUpdated(const indexedGroupRowUpdate_t &payload
grp->routingTable.routes[index] = row;
if (structureDiff)
{
grp->onRoutingChanged();
grp->rePrepareAndBindGroupMatrix();
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/modulation/group_matrix.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ struct GroupMatrixEndpoints
sst::cpputils::make_array_bind_last_index<ProcessorTarget,
scxt::processorsPerZoneAndGroup>(e)},
outputTarget(e),
eg{sst::cpputils::make_array_bind_last_index<EGTarget, scxt::egPerGroup>(e)},
eg{sst::cpputils::make_array_bind_last_index<EGTarget, scxt::egsPerGroup>(e)},
selfModulation(e), sources(e)
{
// If there are group endpoints, we can merge them here
Expand All @@ -130,7 +130,7 @@ struct GroupMatrixEndpoints
}
void bind(GroupMatrix &m, engine::Group &g);
};
std::array<EGTarget, scxt::egPerGroup> eg;
std::array<EGTarget, scxt::egsPerGroup> eg;

struct LFOTarget : shared::LFOTargetEndpointData<TG, 'glfo'>
{
Expand Down
10 changes: 8 additions & 2 deletions src/modulation/has_modulators.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,14 @@ namespace scxt::modulation::shared

static_assert(lfosPerGroup == lfosPerZone,
"If this is false you need to template out the count below");
static_assert(egsPerGroup == egsPerZone,
"If this is false you need to template out the count below");
template <typename T> struct HasModulators
{
HasModulators(T *that) : eg{that, that}, egOS{that, that} {}

static constexpr uint16_t lfosPerObject{lfosPerZone};
static constexpr uint16_t egsPerObject{egsPerZone};

enum LFOEvaluator
{
Expand All @@ -66,8 +69,11 @@ template <typename T> struct HasModulators
T, blockSize << 1, sst::basic_blocks::modulators::TwentyFiveSecondExp>
ahdsrenvOS_t;

ahdsrenv_t eg[2];
ahdsrenvOS_t egOS[2];
ahdsrenv_t eg[egsPerObject];
ahdsrenvOS_t egOS[egsPerObject];

std::array<bool, lfosPerObject> lfosActive{};
std::array<bool, egsPerObject> egsActive{};
};
} // namespace scxt::modulation::shared
#endif // SHORTCIRCUITXT_HAS_MODULATORS_H
4 changes: 2 additions & 2 deletions src/selection/selection_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -587,7 +587,7 @@ void SelectionManager::sendDisplayDataForSingleGroup(int part, int group)
cms::groupOutputInfoUpdate_t{true, g->outputInfo},
*(engine.getMessageController()));

for (int i = 0; i < scxt::egPerGroup; ++i)
for (int i = 0; i < scxt::egsPerGroup; ++i)
{
serializationSendToClient(
cms::s2c_update_group_or_zone_adsr_view,
Expand Down Expand Up @@ -621,7 +621,7 @@ void SelectionManager::sendDisplayDataForSingleGroup(int part, int group)

void SelectionManager::sendDisplayDataForNoGroupSelected()
{
for (int i = 0; i < scxt::egPerGroup; ++i)
for (int i = 0; i < scxt::egsPerGroup; ++i)
{
serializationSendToClient(cms::s2c_update_group_or_zone_adsr_view,
cms::AdsrGroupOrZoneUpdate::s2c_payload_t{false, i, false, {}},
Expand Down
Loading

0 comments on commit 915cf4a

Please sign in to comment.