Plaits: MODEL cv to Envelope Decay mod

Following @lylem 's advice I have modded Plaits to use the MODEL cv input to modify the envelope decay. I replaced patch.decay with patch.decay + modulations.engine everywhere (two places in voice.cc)

However! I run into a problem, I have to multiply for attenuation:

const float short_decay = (200.0f * kBlockSize) / kSampleRate *
SemitonesToRatio(-96.0f * (patch.decay + modulations.engine * 0.3));

I had to add that * 0.3 to attenuate the cv value in every place that I add modulations.engine, or else the sound would simply stop working when the env decay was manually turned all the way up and there was too much modification added from the cv (+8V, I think)

I found 0.3 by trial and error, but it is a bit limited–the effect is hardly noticeable. Does anyone know: What is the actual maximum value allowed for patch.decay? And how do you find that out? Thank you!

2 Likes

This seems like a great idea.

There are occasions when I sequence something through the Model input, but 99% of the time I stick with one model at a time.

I do however find myself ‘performing’ changes on the decay envelope, so this would be a useful mod for me and I imagine others as well.

One question I have is: will there be a way (eg: button combo, et.al) to switch between model and decay without reloading the firmware?

The lookup table used for the SemitonesToRatio function has a limited size and the argument passed to this function must be between -127.0f and +127.0f.

If you don’t take that into account, some combination of the decay setting and modulation will cause the argument to go outside of this range.

Outside of this range, the function will return garbage (arbitrary data interpreted as floats).

I suggest you to do something like this:

float decay = (patch.decay + modulations.engine) * -96.0f;
CONSTRAIN(decay, -127.0f, 127.0f);
const float short_decay = (200.0f * kBlockSize) / kSampleRate * \
    SemitonesToRatio(decay);
1 Like

Also keep in mind that the final value of short_decay must not exceed 1.0f.

It might be safer to do this:

CONSTRAIN(decay, -127.0f, 0.0f);

1 Like

Thank you!

I ended up doing this, for those playing along at home:

//bgFMI This block allows us to mod decay with the MODAL cv input.
float cv_decay = -96.0f * (patch.decay + (modulations.engine * 0.5f));
CONSTRAIN(cv_decay, -127.0f, 127.0f);
float short_decay = (200.0f * kBlockSize) / kSampleRate *
SemitonesToRatio(cv_decay);
CONSTRAIN(short_decay,-1.0f,1.0f);

and then

//bgFMI replaced patch.decay with cv_decay from above
cv_decay = -72.0f * (patch.decay + (modulations.engine * 0.5f)) + 12.0f * hf;
CONSTRAIN(cv_decay,-127.0f,127.0f);
float decay_tail = (20.0f * kBlockSize) / kSampleRate *
SemitonesToRatio(cv_decay) - short_decay;
CONSTRAIN(decay_tail,-1.0f,1.0f);

And wherever it says engine_cv_=modulations.engine change that to engine_cv_=0.0f

It sounds great so far, and I haven’t had it crash on me yet, though I am suspicious about that -1.0f. It’s a little toooo poppy when the ENV is all the way low and the CV is negative.

My next trick will be to get the LPG to be lower when it’s set all the way low.

1 Like