Skip to content

Commit

Permalink
Some data structure reworks ahead of modulation expansion
Browse files Browse the repository at this point in the history
Now each element has a MonOvalues and VoiceValues structure it
can reference.
  • Loading branch information
baconpaul committed Dec 24, 2024
1 parent dabfe09 commit 8ecff81
Show file tree
Hide file tree
Showing 9 changed files with 136 additions and 67 deletions.
6 changes: 3 additions & 3 deletions doc/design.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ SOURCE:
- waveshapes:
- TX waveshapes
- maybe a smoothed-saw and smoothed-square if i can figure out an analytic form i like
- 90%-100% of internal nyquist mute fades
- 90%-100% of internal nyquist mute fades (maybe ship without this tho)

MAIN:
- Voice limit in Main Area hooked up
Expand All @@ -18,7 +18,7 @@ MODULATION:
- Each item gets a modulation list from source set
- Monophonic Midi source
- Macro source
- Polyphonic midi source
- Polyphonic Voice Source
- MPE source
- Note expressions?

Expand All @@ -35,7 +35,7 @@ GENERAL AND CLEANUPS
- AM is somehow not quiet right. Signal to zero seems 'no modulation' not 'no output'
- Don't send VU etc when editor not attached
- Edit area says "click a knbo to edit on startup"
- LFO in Pulse and S&H need a tiny little LPF to avoid super-clicka on modulation nodes
- LFO in Pulse and S&H need a tiny little LPF to avoid super-clicka on modulation nodes (but not ratio nodes)



62 changes: 40 additions & 22 deletions src/dsp/matrix_node.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,15 @@ struct MatrixNodeFrom : public EnvelopeSupport<Patch::MatrixNode>,
public LFOSupport<Patch::MatrixNode>
{
OpSource &onto, &from;

const MonoValues &monoValues;
const VoiceValues &voiceValues;
const float &level, &activeV, &pmrmV, &lfoToDepth, &mulLfoV;
MatrixNodeFrom(const Patch::MatrixNode &mn, OpSource &on, OpSource &fr, const MonoValues &mv)
: onto(on), from(fr), level(mn.level), pmrmV(mn.pmOrRM), activeV(mn.active),
EnvelopeSupport(mn, mv), LFOSupport(mn, mv), lfoToDepth(mn.lfoToDepth),
mulLfoV(mn.envLfoSum)
MatrixNodeFrom(const Patch::MatrixNode &mn, OpSource &on, OpSource &fr, const MonoValues &mv,
const VoiceValues &vv)
: monoValues(mv), voiceValues(vv), onto(on), from(fr), level(mn.level), pmrmV(mn.pmOrRM),
activeV(mn.active), EnvelopeSupport(mn, mv, vv), LFOSupport(mn, mv),
lfoToDepth(mn.lfoToDepth), mulLfoV(mn.envLfoSum)
{
}

Expand All @@ -56,12 +60,12 @@ struct MatrixNodeFrom : public EnvelopeSupport<Patch::MatrixNode>,
}
}

void applyBlock(bool gated)
void applyBlock()
{
if (!active)
return;

envProcess(gated);
envProcess();
lfoProcess();
float mod alignas(16)[blockSize], modB alignas(16)[blockSize];
mech::mul_block<blockSize>(env.outputCache, from.output, mod);
Expand Down Expand Up @@ -104,10 +108,16 @@ struct MatrixNodeSelf : EnvelopeSupport<Patch::SelfNode>, LFOSupport<Patch::Self
{
OpSource &onto;
SRProvider sr;

const MonoValues &monoValues;
const VoiceValues &voiceValues;

const float &fbBase, &lfoToFB, &activeV, &lfoMulV;
MatrixNodeSelf(const Patch::SelfNode &sn, OpSource &on, const MonoValues &mv)
: sr(mv), onto(on), fbBase(sn.fbLevel), lfoToFB(sn.lfoToFB), activeV(sn.active),
lfoMulV(sn.envLfoSum), EnvelopeSupport(sn, mv), LFOSupport(sn, mv){};
MatrixNodeSelf(const Patch::SelfNode &sn, OpSource &on, const MonoValues &mv,
const VoiceValues &vv)
: 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){};
bool active{true}, lfoMul{false};

void attack()
Expand All @@ -120,12 +130,12 @@ struct MatrixNodeSelf : EnvelopeSupport<Patch::SelfNode>, LFOSupport<Patch::Self
lfoAttack();
}
}
void applyBlock(bool gated)
void applyBlock()
{
if (!active)
return;

envProcess(gated);
envProcess();
lfoProcess();
if (lfoMul)
{
Expand Down Expand Up @@ -154,13 +164,16 @@ struct MixerNode : EnvelopeSupport<Patch::MixerNode>, LFOSupport<Patch::MixerNod
OpSource &from;
SRProvider sr;

const MonoValues &monoValues;
const VoiceValues &voiceValues;

const float &level, &activeF, &pan, &lfoToLevel, &lfoToPan;
bool active{false};

MixerNode(const Patch::MixerNode &mn, OpSource &f, const MonoValues &mv)
: sr(mv), from(f), pan(mn.pan), level(mn.level), activeF(mn.active),
lfoToLevel(mn.lfoToLevel), lfoToPan(mn.lfoToPan), EnvelopeSupport(mn, mv),
LFOSupport(mn, mv)
MixerNode(const Patch::MixerNode &mn, OpSource &f, const MonoValues &mv, const VoiceValues &vv)
: monoValues(mv), voiceValues(vv), sr(mv), from(f), pan(mn.pan), level(mn.level),
activeF(mn.active), lfoToLevel(mn.lfoToLevel), lfoToPan(mn.lfoToPan),
EnvelopeSupport(mn, mv, vv), LFOSupport(mn, mv)
{
memset(output, 0, sizeof(output));
}
Expand All @@ -173,15 +186,15 @@ struct MixerNode : EnvelopeSupport<Patch::MixerNode>, LFOSupport<Patch::MixerNod
envAttack();
}

void renderBlock(bool gated)
void renderBlock()
{
if (!active)
{
return;
}
float vSum alignas(16)[blockSize];

envProcess(gated);
envProcess();
for (int j = 0; j < blockSize; ++j)
{
// use mech blah
Expand Down Expand Up @@ -212,30 +225,35 @@ struct OutputNode : EnvelopeSupport<Patch::OutputNode>
std::array<MixerNode, numOps> &fromArr;
SRProvider sr;

const MonoValues &monoValues;
const VoiceValues &voiceValues;

const float &level, &velSen;

OutputNode(const Patch::OutputNode &on, std::array<MixerNode, numOps> &f, const MonoValues &mv)
: sr(mv), fromArr(f), level(on.level), velSen(on.velSensitivity), EnvelopeSupport(on, mv)
OutputNode(const Patch::OutputNode &on, std::array<MixerNode, numOps> &f, const MonoValues &mv,
const VoiceValues &vv)
: monoValues(mv), voiceValues(vv), sr(mv), fromArr(f), level(on.level),
velSen(on.velSensitivity), EnvelopeSupport(on, mv, vv)
{
memset(output, 0, sizeof(output));
}

void attack() { envAttack(); }

void renderBlock(bool gated, float velocity)
void renderBlock()
{
for (const auto &from : fromArr)
{
mech::accumulate_from_to<blockSize>(from.output[0], output[0]);
mech::accumulate_from_to<blockSize>(from.output[1], output[1]);
}

envProcess(gated, false);
envProcess(false);
mech::scale_by<blockSize>(env.outputCache, output[0], output[1]);

// Apply main output
auto lv = level;
auto v = 1.0 - velSen * (1.0 - velocity);
auto v = 1.0 - velSen * (1.0 - voiceValues.velocity);
lv = 0.2 * v * lv * lv * lv;
mech::scale_by<blockSize>(lv, output[0], output[1]);
}
Expand Down
16 changes: 10 additions & 6 deletions src/dsp/node_support.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

#include "dsp/sr_provider.h"
#include "synth/mono_values.h"
#include "synth/voice_values.h"

namespace baconpaul::six_sines
{
Expand All @@ -33,12 +34,15 @@ template <typename T> struct EnvelopeSupport
{
SRProvider sr;

const MonoValues &monoValues;
const VoiceValues &voiceValues;

const float &delay, &attackv, &hold, &decay, &sustain, &release, &powerV;
const float &ash, &dsh, &rsh;
EnvelopeSupport(const T &mn, const MonoValues &mv)
: sr(mv), env(&sr), delay(mn.delay), attackv(mn.attack), hold(mn.hold), decay(mn.decay),
sustain(mn.sustain), release(mn.release), powerV(mn.envPower), ash(mn.aShape),
dsh(mn.dShape), rsh(mn.rShape)
EnvelopeSupport(const T &mn, const MonoValues &mv, const VoiceValues &vv)
: monoValues(mv), voiceValues(vv), sr(mv), env(&sr), delay(mn.delay), attackv(mn.attack),
hold(mn.hold), decay(mn.decay), sustain(mn.sustain), release(mn.release),
powerV(mn.envPower), ash(mn.aShape), dsh(mn.dShape), rsh(mn.rShape)
{
}

Expand Down Expand Up @@ -74,13 +78,13 @@ template <typename T> struct EnvelopeSupport
else
memset(env.outputCache, 0, sizeof(env.outputCache));
}
void envProcess(bool gated, bool maxIsForever = true)
void envProcess(bool maxIsForever = true)
{
if (!active || constantEnv)
return;

env.processBlockWithDelay(delay, attackv, hold, decay, sustain, release, ash, dsh, rsh,
gated, true);
voiceValues.gated, true);
}
};

Expand Down
12 changes: 7 additions & 5 deletions src/dsp/op_source.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "dsp/node_support.h"
#include "synth/patch.h"
#include "synth/mono_values.h"
#include "synth/voice_values.h"

namespace baconpaul::six_sines
{
Expand All @@ -38,6 +39,7 @@ struct alignas(16) OpSource : public EnvelopeSupport<Patch::SourceNode>,
float output alignas(16)[blockSize];

const MonoValues &monoValues;
const VoiceValues &voiceValues;

bool keytrack{true};
const float &ratio, &activeV, &envToRatio, &lfoToRatio, &lfoByEnv; // in frequency multiple
Expand All @@ -48,9 +50,9 @@ struct alignas(16) OpSource : public EnvelopeSupport<Patch::SourceNode>,
uint32_t phase;
uint32_t dPhase;

OpSource(const Patch::SourceNode &sn, const MonoValues &mv)
: monoValues(mv), EnvelopeSupport(sn, mv), LFOSupport(sn, mv), ratio(sn.ratio),
activeV(sn.active), envToRatio(sn.envToRatio), lfoToRatio(sn.lfoToRatio),
OpSource(const Patch::SourceNode &sn, const MonoValues &mv, const VoiceValues &vv)
: monoValues(mv), voiceValues(vv), EnvelopeSupport(sn, mv, vv), LFOSupport(sn, mv),
ratio(sn.ratio), activeV(sn.active), envToRatio(sn.envToRatio), lfoToRatio(sn.lfoToRatio),
lfoByEnv(sn.envLfoSum)
{
reset();
Expand Down Expand Up @@ -84,7 +86,7 @@ struct alignas(16) OpSource : public EnvelopeSupport<Patch::SourceNode>,
void setBaseFrequency(float freq) { baseFrequency = freq; }

float priorRF{-10000000};
void renderBlock(bool gated)
void renderBlock()
{
if (!active)
{
Expand All @@ -93,7 +95,7 @@ struct alignas(16) OpSource : public EnvelopeSupport<Patch::SourceNode>,
fbVal[1] = 0.f;
return;
}
envProcess(gated);
envProcess();
lfoProcess();
auto lfoFac = lfoByEnv > 0.5 ? env.outputCache[blockSize - 1] : 1.f;

Expand Down
3 changes: 2 additions & 1 deletion src/synth/synth.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,8 @@ void Synth::dumpVoiceList()
auto c = head;
while (c)
{
SXSNLOG(" c=" << std::hex << c << std::dec << " key=" << c->key << " u=" << c->used);
SXSNLOG(" c=" << std::hex << c << std::dec << " key=" << c->voiceValues.key
<< " u=" << c->used);
c = c->next;
}
}
Expand Down
27 changes: 16 additions & 11 deletions src/synth/synth.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,15 +72,15 @@ struct Synth
void retriggerVoiceWithNewNoteID(Voice *, int32_t, float) { assert(false); }
void moveVoice(Voice *v, uint16_t p, uint16_t c, uint16_t k, float ve)
{
v->key = k;
v->velocity = ve;
v->voiceValues.key = k;
v->voiceValues.velocity = ve;
}

void moveAndRetriggerVoice(Voice *v, uint16_t p, uint16_t c, uint16_t k, float ve)
{
v->key = k;
v->velocity = ve;
v->gated = true;
v->voiceValues.key = k;
v->voiceValues.velocity = ve;
v->voiceValues.gated = true;
v->retriggerAllEnvelopes();
}

Expand All @@ -96,7 +96,7 @@ struct Synth

void terminateVoice(Voice *voice)
{
voice->gated = false;
voice->voiceValues.gated = false;
voice->fadeBlocks = Voice::fadeOverBlocks;
}
int32_t initializeMultipleVoices(
Expand All @@ -117,10 +117,11 @@ struct Synth
{
obuf[0].voice = &synth.voices[i];
synth.voices[i].used = true;
synth.voices[i].gated = true;
synth.voices[i].key = key;
synth.voices[i].channel = ch;
synth.voices[i].velocity = vel;
synth.voices[i].voiceValues.gated = true;
synth.voices[i].voiceValues.key = key;
synth.voices[i].voiceValues.channel = ch;
synth.voices[i].voiceValues.velocity = vel;
synth.voices[i].voiceValues.releaseVelocity = 0;
synth.voices[i].attack();

synth.addToVoiceList(&synth.voices[i]);
Expand All @@ -132,7 +133,11 @@ struct Synth
}
return 0;
}
void releaseVoice(Voice *v, float) { v->gated = false; }
void releaseVoice(Voice *v, float rv)
{
v->voiceValues.gated = false;
v->voiceValues.releaseVelocity = rv;
}
void setNoteExpression(Voice *, int32_t, double) {}
void setVoicePolyphonicParameterModulation(Voice *, uint32_t, double) {}
void setPolyphonicAftertouch(Voice *, int8_t) {}
Expand Down
Loading

0 comments on commit 8ecff81

Please sign in to comment.