Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Group Trigger stuff streams (but still does nothing) #1407

Merged
merged 2 commits into from
Oct 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/engine/group.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,8 @@ void Group::setupOnUnstream(const engine::Engine &e)
{
lfo.UpdatePhaseIncrement();
}

triggerConditions.setupOnUnstream(parentPart->groupTriggerInstrumentState);
}
void Group::onSampleRateChanged()
{
Expand Down
122 changes: 122 additions & 0 deletions src/engine/group_triggers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,125 @@
*/

#include "group_triggers.h"
#include "utils.h"

namespace scxt::engine
{

std::string toStringGroupTriggerID(const GroupTriggerID &p)
{
switch (p)
{
// lesson learned earlier was long names are not that handy debugging now the infra works
// and just make big files so use compact ones here
case GroupTriggerID::NONE:
return "n";
case GroupTriggerID::MACRO:
return "mcr";
case GroupTriggerID::MIDICC:
return "mcc";
}
return "n";
}
GroupTriggerID fromStringGroupTriggerID(const std::string &s)
{
static auto inverse = makeEnumInverse<GroupTriggerID, toStringGroupTriggerID>(
GroupTriggerID::NONE, GroupTriggerID::MIDICC);
auto p = inverse.find(s);
if (p == inverse.end())
return GroupTriggerID::NONE;
return p->second;
}

std::string GroupTriggerConditions::toStringGroupConditionsConjunction(const Conjunction &p)
{
switch (p)
{
case Conjunction::AND:
return "a";
case Conjunction::OR:
return "o";
case Conjunction::AND_NOT:
return "a!";
case Conjunction::OR_NOT:
return "o!";
}
return "a";
}
GroupTriggerConditions::Conjunction fromStringConditionsConjunction(const std::string &s)
{
static auto inverse =
makeEnumInverse<GroupTriggerConditions::Conjunction,
GroupTriggerConditions::toStringGroupConditionsConjunction>(
GroupTriggerConditions::Conjunction::AND, GroupTriggerConditions::Conjunction::OR_NOT);
auto p = inverse.find(s);
if (p == inverse.end())
return GroupTriggerConditions::Conjunction::AND;
return p->second;
}

struct GTMacro : GroupTrigger
{

GTMacro(GroupTriggerInstrumentState &onState, GroupTriggerStorage &onStorage)
: GroupTrigger(onState, onStorage)
{
}

bool value(const std::unique_ptr<Engine> &, const std::unique_ptr<Group> &) const override
{
return true;
}
datamodel::pmd argMetadata(int argNo) const override { return {}; }
};
struct GTMIDI1CC : GroupTrigger
{
GTMIDI1CC(GroupTriggerInstrumentState &onState, GroupTriggerStorage &onStorage)
: GroupTrigger(onState, onStorage)
{
}

bool value(const std::unique_ptr<Engine> &, const std::unique_ptr<Group> &) const override
{
return true;
}
datamodel::pmd argMetadata(int argNo) const override { return {}; }
};

GroupTrigger *makeGroupTrigger(GroupTriggerID id, GroupTriggerInstrumentState &gis,
GroupTriggerStorage &st, GroupTriggerBuffer &bf)
{
#define CS(id, tp) \
static_assert(sizeof(tp) < sizeof(GroupTriggerBuffer)); \
case id: \
return new (bf) tp(gis, st);
switch (id)
{
CS(GroupTriggerID::MIDICC, GTMIDI1CC);
CS(GroupTriggerID::MACRO, GTMacro);
case GroupTriggerID::NONE:
return nullptr;
}
return nullptr;
}

// THIS NEEDS ARGUMENTS of the state and so on
void GroupTriggerConditions::setupOnUnstream(GroupTriggerInstrumentState &gis)
{
for (int i = 0; i < triggerConditionsPerGroup; ++i)
{
auto &s = storage[i];
if (s.id == GroupTriggerID::NONE)
{
if (conditions[i])
conditions[i]->~GroupTrigger();
conditions[i] = nullptr;
}
else
{
conditions[i] = makeGroupTrigger(s.id, gis, s, conditionBuffers[i]);
}
}
}

} // namespace scxt::engine
70 changes: 59 additions & 11 deletions src/engine/group_triggers.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,18 @@

#include <memory>
#include <array>
#include <variant>

#include "configuration.h"
#include "utils.h"

#include "datamodel/metadata.h"

namespace scxt::engine
{

struct Engine;
struct Part;
struct Group;

/**
Expand All @@ -46,33 +51,76 @@ struct GroupTriggerInstrumentState
{
};

enum struct GroupTriggerID : int32_t
{
NONE,

MACRO,
MIDICC // if MIDICC is no longer last, adjust fromStringGfroupTRiggerID iteration
};

std::string toStringGroupTriggerID(const GroupTriggerID &p);
GroupTriggerID fromStringGroupTriggerID(const std::string &p);

struct GroupTriggerStorage
{
GroupTriggerID id{GroupTriggerID::NONE};
using argInterface_t = int32_t; // for now and just use ms for miliseconds and scale

static constexpr int32_t numArgs{2};
std::array<argInterface_t, numArgs> args{0, 0};
};
/**
* Calculate if a group is triggered
*/
struct GroupTrigger
{
GroupTriggerInstrumentState &state;
GroupTrigger(GroupTriggerInstrumentState &onState) : state(onState) {}
GroupTriggerStorage &storage;
GroupTrigger(GroupTriggerInstrumentState &onState, GroupTriggerStorage &onStorage)
: state(onState), storage(onStorage)
{
}
virtual ~GroupTrigger() = default;
virtual bool value(const std::unique_ptr<Group> &) const = 0;

datamodel::pmd argMetadata(int argNo) const;
std::string displayName;
virtual bool value(const std::unique_ptr<Engine> &, const std::unique_ptr<Group> &) const = 0;
virtual datamodel::pmd argMetadata(int argNo) const = 0;
};

std::unique_ptr<GroupTrigger> makeMacroGroupTrigger(GroupTriggerInstrumentState &);
std::unique_ptr<GroupTrigger> makeMIDI1CCGroupTrigger(GroupTriggerInstrumentState &);
// FIXME - make this sized more intelligently
using GroupTriggerBuffer = uint8_t[2048];

GroupTrigger *makeGroupTrigger(GroupTriggerID, GroupTriggerInstrumentState &, GroupTriggerStorage &,
GroupTriggerBuffer &);
std::string getGroupTriggerDisplayName(GroupTriggerID);

struct GroupTriggerConditions
{
std::array<std::unique_ptr<GroupTrigger>, scxt::triggerConditionsPerGroup> conditions;
std::array<bool, scxt::triggerConditionsPerGroup> active;
enum Conjunction
GroupTriggerConditions()
{
std::fill(conditions.begin(), conditions.end(), nullptr);
std::fill(active.begin(), active.end(), false);
}
std::array<GroupTriggerStorage, scxt::triggerConditionsPerGroup> storage{};
std::array<bool, scxt::triggerConditionsPerGroup> active{};

enum struct Conjunction : int32_t
{
AND,
OR
OR,
AND_NOT,
OR_NOT // add one to end or change position update the from in fromString
};

static std::string toStringGroupConditionsConjunction(const Conjunction &p);
static Conjunction fromStringConditionsConjunction(const std::string &p);

std::array<Conjunction, scxt::triggerConditionsPerGroup - 1> conjunctions;

void setupOnUnstream(GroupTriggerInstrumentState &);

protected:
std::array<GroupTriggerBuffer, scxt::triggerConditionsPerGroup> conditionBuffers;
std::array<GroupTrigger *, scxt::triggerConditionsPerGroup> conditions{};
};

} // namespace scxt::engine
Expand Down
40 changes: 39 additions & 1 deletion src/json/engine_traits.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#include "engine/keyboard.h"
#include "engine/macros.h"
#include "engine/engine.h"
#include "engine/group_triggers.h"

#include "scxt_traits.h"

Expand Down Expand Up @@ -226,6 +227,42 @@ SC_STREAMDEF(
}
}))

STREAM_ENUM(engine::GroupTriggerID, engine::toStringGroupTriggerID,
engine::fromStringGroupTriggerID);

SC_STREAMDEF(scxt::engine::GroupTriggerStorage, SC_FROM({
v = {{"id", from.id}, {"args", from.args}};
}),
SC_TO({
findIf(v, "id", to.id);
findIf(v, "args", to.args);
}));

STREAM_ENUM(engine::GroupTriggerConditions::Conjunction,
engine::GroupTriggerConditions::toStringGroupConditionsConjunction,
engine::GroupTriggerConditions::fromStringConditionsConjunction);

SC_STREAMDEF(scxt::engine::GroupTriggerConditions, SC_FROM({
bool anyConfigured{false};
for (const auto &c : from.storage)
{
anyConfigured |= (c.id != scxt::engine::GroupTriggerID::NONE);
}
if (anyConfigured)
{
v = {{"st", from.storage}, {"ac", from.active}, {"conj", from.conjunctions}};
}
else
{
v = tao::json::empty_object;
}
}),
SC_TO({
findIf(v, "st", to.storage);
findIf(v, "ac", to.active);
findIf(v, "conj", to.conjunctions);
}));

SC_STREAMDEF(scxt::engine::Group::GroupOutputInfo, SC_FROM({
v = {{"amplitude", t.amplitude}, {"pan", t.pan},
{"oversample", t.oversample}, {"velocitySensitivity", t.velocitySensitivity},
Expand All @@ -251,7 +288,8 @@ SC_STREAMDEF(scxt::engine::Group, SC_FROM({
{"routingTable", t.routingTable},
{"gegStorage", t.gegStorage},
{"modulatorStorage", t.modulatorStorage},
{"processorStorage", t.processorStorage}};
{"processorStorage", t.processorStorage},
{"triggerConditions", t.triggerConditions}};
}),
SC_TO({
auto &group = to;
Expand Down
2 changes: 1 addition & 1 deletion src/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ template <typename E, std::string (*F)(const E &)>
inline std::unordered_map<std::string, E> makeEnumInverse(const E &from, const E &to)
{
std::unordered_map<std::string, E> res;
for (auto i = (int32_t)from; i <= to; ++i)
for (auto i = (int32_t)from; i <= (int32_t)to; ++i)
{
res[F((E)i)] = (E)i;
}
Expand Down
Loading