Skip to content

Commit

Permalink
Feedback gets a matrix; RNG fix (#16)
Browse files Browse the repository at this point in the history
  • Loading branch information
baconpaul authored Dec 29, 2024
1 parent 30a5342 commit 3f32fa5
Show file tree
Hide file tree
Showing 10 changed files with 130 additions and 15 deletions.
2 changes: 1 addition & 1 deletion doc/design.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ SOURCE:
MODULATION:
- Put modulation in
- matrix
- feedback
- mixer
- main
- Unison Sources
- Random sources (put a float in each ModulationSupport and set them in bind)

PATCH SELECTOR:
- Jog Buttons for next/prev
Expand Down
2 changes: 1 addition & 1 deletion libs/sst/sst-basic-blocks
71 changes: 64 additions & 7 deletions src/dsp/matrix_node.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,19 +104,22 @@ struct MatrixNodeFrom : public EnvelopeSupport<Patch::MatrixNode>,
}
};

struct MatrixNodeSelf : EnvelopeSupport<Patch::SelfNode>, LFOSupport<Patch::SelfNode>
struct MatrixNodeSelf : EnvelopeSupport<Patch::SelfNode>,
LFOSupport<Patch::SelfNode>,
ModulationSupport<Patch::SelfNode>
{
OpSource &onto;
SRProvider sr;

const Patch::SelfNode &selfNode;
const MonoValues &monoValues;
const VoiceValues &voiceValues;

const float &fbBase, &lfoToFB, &activeV, &lfoMulV;
MatrixNodeSelf(const Patch::SelfNode &sn, OpSource &on, MonoValues &mv, const VoiceValues &vv)
: monoValues(mv), voiceValues(vv), sr(mv), onto(on), fbBase(sn.fbLevel),
: selfNode(sn), monoValues(mv), voiceValues(vv), sr(mv), onto(on), fbBase(sn.fbLevel),
lfoToFB(sn.lfoToFB), activeV(sn.active), lfoMulV(sn.envLfoSum),
EnvelopeSupport(sn, mv, vv), LFOSupport(sn, mv){};
EnvelopeSupport(sn, mv, vv), LFOSupport(sn, mv), ModulationSupport(sn, mv, vv){};
bool active{true}, lfoMul{false};

void attack()
Expand All @@ -125,6 +128,8 @@ struct MatrixNodeSelf : EnvelopeSupport<Patch::SelfNode>, LFOSupport<Patch::Self
lfoMul = lfoMulV > 0.5;
if (active)
{
bindModulation();
calculateModulation();
envAttack();
lfoAttack();
}
Expand All @@ -134,24 +139,76 @@ struct MatrixNodeSelf : EnvelopeSupport<Patch::SelfNode>, LFOSupport<Patch::Self
if (!active)
return;

calculateModulation();
envProcess();
lfoProcess();
if (lfoMul)
{
for (int j = 0; j < blockSize; ++j)
{
onto.feedbackLevel[j] =
(int32_t)((1 << 24) * (env.outputCache[j] * lfoToFB * lfo.outputBlock[j]) *
fbBase);
(int32_t)((1 << 24) * (((env.outputCache[j] * lfoAtten * lfoToFB * lfo.outputBlock[j]) *
fbBase * depthAtten) + fbMod));
}
}
else
{
for (int j = 0; j < blockSize; ++j)
{
onto.feedbackLevel[j] =
(int32_t)((1 << 24) * (env.outputCache[j] + lfoToFB * lfo.outputBlock[j]) *
fbBase);
(int32_t)((1 << 24) * (((env.outputCache[j] + lfoAtten * lfoToFB * lfo.outputBlock[j]) *
fbBase * depthAtten) + fbMod));
}
}


}

float fbMod{0.f};
float depthAtten{1.0};
float lfoAtten{1.0};

void calculateModulation()
{
depthAtten = 1.f;
lfoAtten = 1.f;
fbMod = 0.f;
attackMod = 0.f;
rateMod = 0.f;

if (!anySources)
return;

for (int i = 0; i < numModsPer; ++i)
{
if (sourcePointers[i] &&
(int)selfNode.modtarget[i].value != Patch::SelfNode::TargetID::NONE)
{
// targets: env depth atten, lfo dept atten, direct adjust, env attack, lfo rate
auto dp = depthPointers[i];
if (!dp)
continue;
auto d = *dp;
switch ((Patch::SelfNode::TargetID)selfNode.modtarget[i].value)
{
case Patch::SelfNode::DIRECT:
fbMod += d * *sourcePointers[i];
break;
case Patch::SelfNode::DEPTH_ATTEN:
depthAtten *= 1.0 - d * (1.0 - std::clamp(*sourcePointers[i], 0.f, 1.f));
break;
case Patch::SelfNode::LFO_DEPTH_ATTEN:
lfoAtten *= 1.0 - d * (1.0 - std::clamp(*sourcePointers[i], 0.f, 1.f));
break;
case Patch::SelfNode::ENV_ATTACK:
attackMod += d * *sourcePointers[i];
break;
case Patch::SelfNode::LFO_RATE:
rateMod += d * *sourcePointers[i] * 4;
break;
default:
break;
}
}
}
}
Expand Down
11 changes: 11 additions & 0 deletions src/dsp/node_support.h
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ template <typename T> struct ModulationSupport
const VoiceValues &voiceValues;

// array makes ref clumsy so show pointers instead
bool anySources{false};
std::array<const float *, numModsPer> sourcePointers;
std::array<const float *, numModsPer> depthPointers;
std::array<float, numModsPer> priorModulation;
Expand All @@ -219,14 +220,24 @@ template <typename T> struct ModulationSupport

void bindModulation()
{
bool changed{false};
for (int i = 0; i < numModsPer; ++i)
{
if (priorModulation[i] != paramBundle.modsource[i].value)
{
rebindPointer(i);
changed = true;
priorModulation[i] = paramBundle.modsource[i].value;
}
}
if (changed)
{
anySources = false;
for (int i = 0; i < numModsPer; ++i)
{
anySources |= (sourcePointers[i] != nullptr);
}
}
}

void rebindPointer(int which)
Expand Down
6 changes: 5 additions & 1 deletion src/dsp/op_source.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,10 @@ struct alignas(16) OpSource : public EnvelopeSupport<Patch::SourceNode>,

if (active)
{
bindModulation();
calculateModulation();
envAttack();
lfoAttack();
bindModulation();

phase = 4 << 27;
if (voiceValues.phaseRandom)
Expand Down Expand Up @@ -156,6 +156,10 @@ struct alignas(16) OpSource : public EnvelopeSupport<Patch::SourceNode>,
ratioMod = 0.f;
attackMod = 0.f;
rateMod = 0.f;

if (!anySources)
return;

for (int i = 0; i < numModsPer; ++i)
{
if (sourcePointers[i] &&
Expand Down
44 changes: 41 additions & 3 deletions src/synth/patch.h
Original file line number Diff line number Diff line change
Expand Up @@ -447,8 +447,29 @@ struct Patch
return res;
}
};
struct SelfNode : public DAHDSRMixin, LFOMixin
struct SelfNode : public DAHDSRMixin, LFOMixin, ModulationMixin
{
// These stream
enum TargetID
{
NONE = 0,
DIRECT = 10,
DEPTH_ATTEN = 20,
LFO_DEPTH_ATTEN = 30,

ENV_ATTACK = 40,
LFO_RATE = 50
};

std::vector<std::pair<TargetID, std::string>> targetList{
{TargetID::NONE, "Off"},
{TargetID::DIRECT, "Feedback Level"},
{TargetID::DEPTH_ATTEN, "Mod Depth"},
{TargetID::LFO_DEPTH_ATTEN, "LFO Depth"},
{TargetID::ENV_ATTACK, "Env Attack"},
{TargetID::LFO_RATE, "LFO Rate"},
};

// Once streamed you cant change these bases or the individual ids inside
static constexpr uint32_t idBase{10000}, idStride{100};
SelfNode(size_t idx)
Expand Down Expand Up @@ -476,8 +497,18 @@ struct Patch
.withID(id(26, idx))
.withRange(0, 1)
.withDefault(0)
.withUnorderedMapFormatting({{0, "+"}, {1, "x"}}))

.withUnorderedMapFormatting({{0, "+"}, {1, "x"}})),
ModulationMixin(name(idx), id(40, idx)),
modtarget(scpu::make_array_lambda<Param, numModsPer>(
[this, idx](int i)
{
return md_t()
.withName(name(idx) + " Mod Target " + std::to_string(i))
.withGroupName(name(idx))
.withRange(0, 2000)
.withDefault(TargetID::NONE)
.withID(id(55 + i, idx));
}))
{
}

Expand All @@ -487,11 +518,18 @@ struct Patch
Param fbLevel, lfoToFB, envLfoSum;
Param active;

std::array<Param, numModsPer> modtarget;

std::vector<Param *> params()
{
std::vector<Param *> res{&fbLevel, &active, &lfoToFB, &envLfoSum};
appendDAHDSRParams(res);
appendLFOParams(res);

for (int i = 0; i < numModsPer; ++i)
res.push_back(&modtarget[i]);
appendModulationParams(res);

return res;
}
};
Expand Down
1 change: 0 additions & 1 deletion src/synth/synth.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,6 @@ struct Synth
auto stb = (b - 8192) * 1.0 / 8192;
v->voiceValues.mpeBendNormalized = stb;
v->voiceValues.mpeBendInSemis = stb * synth.patch.output.mpeBendRange.value;
;
}
void setVoiceMIDIMPEChannelPressure(Voice *v, int8_t p)
{
Expand Down
1 change: 1 addition & 0 deletions src/ui/matrix-sub-panel.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "six-sines-editor.h"
#include "dahdsr-components.h"
#include "lfo-components.h"
#include "modulation-components.h"

namespace baconpaul::six_sines::ui
{
Expand Down
3 changes: 3 additions & 0 deletions src/ui/self-sub-panel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ void SelfSubPanel::setSelectedIndex(int idx)
auto &n = editor.patchCopy.selfNodes[idx];
setupDAHDSR(editor, editor.patchCopy.selfNodes[idx]);
setupLFO(editor, editor.patchCopy.selfNodes[idx]);
setupModulation(editor, editor.patchCopy.selfNodes[idx]);

createComponent(editor, *this, n.lfoToFB, lfoToFb, lfoToFbD);
addAndMakeVisible(*lfoToFb);
Expand All @@ -55,6 +56,8 @@ void SelfSubPanel::resized()
auto r = layoutLFOAt(pn.getX(), p.getY(), uicMargin + uicKnobSize);

positionKnobAndLabel(r.getX() - uicKnobSize, r.getY() + uicTitleLabelHeight, lfoToFb, lfoToFbL);

layoutModulation(p);
}

} // namespace baconpaul::six_sines::ui
4 changes: 3 additions & 1 deletion src/ui/self-sub-panel.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,15 @@
#include "six-sines-editor.h"
#include "dahdsr-components.h"
#include "lfo-components.h"
#include "modulation-components.h"

namespace baconpaul::six_sines::ui
{
struct SelfSubPanel : juce::Component,
HasEditor,
DAHDSRComponents<SelfSubPanel, Patch::SelfNode>,
LFOComponents<SelfSubPanel, Patch::SelfNode>
LFOComponents<SelfSubPanel, Patch::SelfNode>,
ModulationComponents<SelfSubPanel, Patch::SelfNode>
{
SelfSubPanel(SixSinesEditor &);
~SelfSubPanel();
Expand Down

0 comments on commit 3f32fa5

Please sign in to comment.