Skip to content

Commit

Permalink
Add a trance gate.
Browse files Browse the repository at this point in the history
  • Loading branch information
linuscu committed Sep 7, 2024
1 parent 8ece73a commit c7823c5
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 1 deletion.
2 changes: 1 addition & 1 deletion packages/math/include/math/MathFunc.h
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ namespace l::math::functions {
}

// Gain
// Remapping the unit interval into the unit interval by expanding the sidesand compressing the center, and keeping 1 / 2 mapped to 1 / 2, that can be done with the gain() function.This was a common function in RSL tutorials(the Renderman Shading Language).k = 1 is the identity curve, k < 1 produces the classic gain() shape, and k>1 produces "s" shaped curces.The curves are symmetric(and inverse) for k = a and k = 1 / a.
// Remapping the unit interval into the unit interval by expanding the sides and compressing the center, and keeping 1 / 2 mapped to 1 / 2, that can be done with the gain() function.This was a common function in RSL tutorials(the Renderman Shading Language).k = 1 is the identity curve, k < 1 produces the classic gain() shape, and k>1 produces "s" shaped curces.The curves are symmetric(and inverse) for k = a and k = 1 / a.
template<class T>
T gain(T x, T k)
{
Expand Down
53 changes: 53 additions & 0 deletions packages/nodegraph/include/nodegraph/NodeGraphOperations.h
Original file line number Diff line number Diff line change
Expand Up @@ -835,6 +835,59 @@ namespace l::nodegraph {
float mEnvelope = 0.0f;
};

/*********************************************************************/
class GraphEffectTranceGate : public NodeGraphOp {
public:
std::string defaultInStrings[6] = { "In 1", "In 2", "Bpm", "Fmod", "Attack", "Pattern" };
std::string defaultOutStrings[3] = { "Out 1", "Out 2" };

const std::vector< std::vector<float>> patterns = {
{0.7f, 0.0f, 0.7f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f },
{0.5f, 0.0f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f},
{0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f},
{1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f},
{0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f},
{1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f},
{1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f},
{0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f},
{1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f },
};

GraphEffectTranceGate(NodeGraphBase* node) :
NodeGraphOp(node, 6, 2, 0)
{}

virtual ~GraphEffectTranceGate() = default;
virtual void Reset() override;
virtual void Process(int32_t numSamples, std::vector<NodeGraphInput>& inputs, std::vector<NodeGraphOutput>& outputs) override;
virtual bool IsDataVisible(int8_t num) override {
return num >= 2 ? true : false;
}
virtual bool IsDataEditable(int8_t num) override {
return num >= 2 ? true : false;
}
virtual std::string_view GetInputName(int8_t inputChannel) override {
return defaultInStrings[inputChannel];
}
virtual std::string_view GetOutputName(int8_t outputChannel) override {
return defaultOutStrings[outputChannel];
}
virtual std::string_view GetName() override {
return "Trance Gate";
}

protected:
float mSamplesUntilUpdate = 0.0f;
int32_t mGateIndex = 0;
std::vector<float> mGate;
float mGainTarget = 1.0f;
float mGain = 1.0f;
float mGateSmoothing = 0.01f;
float mGateSmoothingNeg = 0.01f;
};


/*********************************************************************/
class GraphInputKeyboardPiano : public NodeGraphOp, public l::hid::INoteProcessor {
public:
Expand Down
1 change: 1 addition & 0 deletions packages/nodegraph/include/nodegraph/NodeGraphSchema.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ namespace l::nodegraph {
RegisterNodeType("Effect", 253, "Limiter");
RegisterNodeType("Effect", 254, "Envelope Follower");
RegisterNodeType("Effect", 255, "Saturator");
RegisterNodeType("Effect", 256, "Trance Gate");
RegisterNodeType("Input", 300, "Keyboard Piano");
RegisterNodeType("Input", 301, "Midi Keyboard");
RegisterNodeType("Input", 302, "Midi Knobs");
Expand Down
62 changes: 62 additions & 0 deletions packages/nodegraph/source/common/NodeGraphOperations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -872,6 +872,68 @@ namespace l::nodegraph {
outputs.at(1).mOutput = dry * in1 + wet * inPreamp1;
}

/*********************************************************************/
void GraphEffectTranceGate::Reset() {
// { "In 1", "In 2", "Bpm", "Fmod", "Attack", "Pattern"};

mGateIndex = 0;

mNode->SetInput(2, 60.0f);
mNode->SetInput(3, 1.0f);
mNode->SetInput(4, 0.001f);
mNode->SetInput(5, 0.0f);
mNode->SetInputBound(2, InputBound::INPUT_CUSTOM, 1.0f, 1000.0f);
mNode->SetInputBound(3, InputBound::INPUT_CUSTOM, 0.01f, 1.0f);
mNode->SetInputBound(4, InputBound::INPUT_0_TO_1);
mNode->SetInputBound(5, InputBound::INPUT_0_100);
}

void GraphEffectTranceGate::Process(int32_t numSamples, std::vector<NodeGraphInput>& inputs, std::vector<NodeGraphOutput>& outputs) {
// "Bpm", "Fmod", "Attack", "Pattern"


float bpm = inputs.at(2).Get();
//fmod = l::math::functions::pow(l::math::constants::E_f, (1.0f / 10.0f) * fmod); // range 0.1 - 10 with arg -1,1

float attack = inputs.at(4).Get();

size_t patternsSize = patterns.size();
int32_t patternId = static_cast<int32_t>(patternsSize * inputs.at(5).Get());
auto& gate = patterns[patternId % patternsSize];

size_t patternSize = gate.size();
float fmod = inputs.at(3).Get() / static_cast<float>(patternSize);
mGateIndex %= patternSize;

mGateSmoothing = attack * attack;
mGateSmoothingNeg = mGateSmoothing * 0.25f;

float freq = 44100.0f * 60.0f / bpm;

mSamplesUntilUpdate = l::audio::BatchUpdate(freq * fmod, mSamplesUntilUpdate, 0, numSamples,
[&]() {
mGainTarget = gate[mGateIndex];
mGateIndex = (mGateIndex + 1) % gate.size();
},
[&](int32_t start, int32_t end, bool) {
for (int32_t i = start; i < end; i++) {
float in0 = inputs.at(0).Get();
float in1 = inputs.at(1).Get();

float delta = mGainTarget - mGain;
if (delta > 0) {
mGain += mGateSmoothing * delta;
}
else {
mGain += mGateSmoothingNeg * delta;
}

outputs.at(0).mOutput = mGain * in0;
outputs.at(1).mOutput = mGain * in1;
}
});
}

/*********************************************************************/
void GraphInputKeyboardPiano::Process(int32_t, std::vector<NodeGraphInput>& inputs, std::vector<NodeGraphOutput>& outputs) {
for (size_t i = 0; i < inputs.size(); i++) {
Expand Down
3 changes: 3 additions & 0 deletions packages/nodegraph/source/common/NodeGraphSchema.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,9 @@ namespace l::nodegraph {
case 255:
node = mMainNodeGraph.NewNode<l::nodegraph::GraphEffectSaturator>(OutputType::Default);
break;
case 256:
node = mMainNodeGraph.NewNode<l::nodegraph::GraphEffectTranceGate>(OutputType::Default);
break;
case 300:
node = mMainNodeGraph.NewNode<l::nodegraph::GraphInputKeyboardPiano, l::hid::KeyState>(OutputType::Default, 1, mKeyState);
break;
Expand Down

0 comments on commit c7823c5

Please sign in to comment.