[sdiy] software / firmware envelopes in C (or anything else)

Chris Rogers teukros at gmail.com
Fri Nov 7 00:19:37 CET 2025


I have a custom envelope implementation in my Yarns fork:
https://github.com/rcrogers/yarns-loom/blob/main/yarns/envelope.cc

Includes user-configurable modulation of ADSR parameters by note-on
velocity, plus a "Peak" modulation that changes the height of the A/D peak
https://github.com/rcrogers/yarns-loom/blob/main/yarns/part.cc#L815

This started as the much simpler Braids envelope:
https://github.com/pichenettes/eurorack/blob/master/braids/envelope.h#L76

These envelopes are the most CPU-intensive process in the system.  I found
that I got better performance by:
- Using templated functions to transform conditionality in the main render
loop from run-time to compile-time (learned this from Emilie Gillet's tips
<https://pichenettes.github.io/mutable-instruments-documentation/tech_notes/stm32_miscellania/>
)
- Avoiding as much per-sample multiplication as possible. I found that the
number of multiplication operations needed to generate one output sample is
a pretty good heuristic for CPU cost.
    - Rendering a separate envelope per modulation destination (voice
timbre, voice gain, voice CV out) with a scale baked in at note start.
This lets you perform modulation by straight addition of samples, instead
of having to multiply each sample by a scaling factor per destination.
    - Using a LUT of phase-dependent bit-shifts
<https://github.com/rcrogers/yarns-loom/blob/main/yarns/resources/lookup_tables.py#L128>
to do a "polygonal" approximation from a linear slope to the
phase-dependent slope of the approximated curve.  These slopes feed an
accumulator, again replacing multiplication with addition

On Thu, Nov 6, 2025 at 5:55 PM chris <chris at chrismusic.de> wrote:

> Why not multiply velocity into the attack and sustain target levels
> instead of the resulting envelope?
>
> You get the attack rate approaching behavior for free, and it omits lots
> of multiplications for each env sample.
>
> Am I missing something here?
>
>
> Chris (another one)
>
>
> On 06/11/2025 23:13, Tom Wiltshire wrote:
> > Many thanks, Chris.
> >
> > Yes, multiplying the envelope output by velocity will cause an abrupt
> jump if the envelope isn't at zero. Running the attack to a new higher
> level is a a neater way of doing it, avoids the problem, and makes a lot of
> sense. I like it.
> >
> > "Velocity modulation" seems a bit weird to me since MIDI only deals with
> velocity at note on and note off. At other times, surely some other
> variable would make more sense? How can you change the velocity of a key
> press after it's occurred? It seems a bit meaningless. I can see that if
> "velocity" is simply some variable that is multiplied by the envelope
> output before it is used, you could modulate it as much as you like in your
> firmware, but physically, it stops making sense - furthermore it causes the
> problems you've identified.
> >
> >
> >> On 6 Nov 2025, at 18:38, Chris McDowell <declareupdate at gmail.com>
> wrote:
> >>
> >> My use of the term "side effects" was sloppy, because I think there's
> only one and it is the primary effect. An envelope through a VCA can jump
> abruptly, where this one will only jump as abruptly as the envelope stage
> rates allow. It will only ever ramp toward new targets.
> >>
> >> If it's a monophonic implementation and in a legato mode with previous
> notes held, new notes cause the output to ramp toward the new sustain value
> at the rate of decay. In a non-legato mode, new notes cause the output to
> ramp toward velocity * 2.0 at the rate of attack.
> >>
> >> If it is a polyphonic synth, it only comes in to play when a voice is
> stolen. The volume or cutoff or whatever of that voice will ramp toward
> velocity * 2.0 from wherever it happens to be.
> >>
> >> I had thought for a bit that adding slew to a velocity signal
> controlling a VCA could be one solution, but what rate to choose for that
> slew is unclear and it interacts with the rest of the envelope output. I
> like the simplicity of my envelopes only ever operating via targets and
> rates.
> >>
> >> This is a limitation I don't love in the Prophet REV2, for example. It
> welcomes pretty flexible velocity modulation, but it is always an abrupt
> effect. I have not consciously encountered a velocity implementation like
> mine in the wild.
> >>
> >> Chris McDowell
> >>
> >>
> >>> On Nov 6, 2025, at 8:11 AM, Tom Wiltshire <tom at electricdruid.net>
> wrote:
> >>>
> >>>
> >>>
> >>>> On 6 Nov 2025, at 12:44, Chris McDowell via Synth-diy <
> synth-diy at synth-diy.org> wrote:
> >>>>
> >>>> When velocity is involved, I set the attack target to 2 * velocity,
> and the sustain level to sustain * velocity, instead of multiplying the
> envelope output by velocity.  this has some side effects but feels a lot
> more natural to me
> >>> Interesting. What's the difference? At first glance, that sounds like
> it would be the same (at least for constant-time envelopes - I can see
> constant-rate envelopes would change).
> >>>
> >>>
> >
> > ________________________________________________________
> > This is the Synth-diy mailing list
> > Submit email to: Synth-diy at synth-diy.org
> > View archive at: https://synth-diy.org/pipermail/synth-diy/
> > Check your settings at: https://synth-diy.org/mailman/listinfo/synth-diy
> > Selling or trading? Use marketplace at synth-diy.org
> ________________________________________________________
> This is the Synth-diy mailing list
> Submit email to: Synth-diy at synth-diy.org
> View archive at: https://synth-diy.org/pipermail/synth-diy/
> Check your settings at: https://synth-diy.org/mailman/listinfo/synth-diy
> Selling or trading? Use marketplace at synth-diy.org
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://synth-diy.org/pipermail/synth-diy/attachments/20251106/bbb94a48/attachment.htm>


More information about the Synth-diy mailing list