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

Jonatan Liljedahl lijon at kymatica.com
Fri Nov 7 15:55:50 CET 2025


Thanks! The plan is one STM32G071 per voice. The MCU does all modulators,
clocks two juno-style DCOs, and CV control of analog VCAs and VCF. It also
has a noise generator and some FM oscillators, using the 2nd DAC channel
for audio out.

/Jonatan
http://kymatica.com


On Thu, 6 Nov 2025 at 21:23, Chris McDowell <declareupdate at gmail.com> wrote:

> Love it, nice cheap exp approximation. Are you running your whole synth on
> the G0?
>
> Cheers,
> Chris
>
> > On Nov 6, 2025, at 2:16 PM, Jonatan Liljedahl <lijon at kymatica.com>
> wrote:
> >
> > In my WIP polysynth project, I wanted full flexibility with
> > multi-stage envelope as in DX7, but with a curve setting per segment.
> > (as well as a bunch of other features)
> > So I do a ramp for each segment, apply curve bending, and then lerp it
> > into the correct from-to range. All in fixed point math, because it's
> > running on an STM32G0. It's a lot more operations than the typical
> > simple RC envelope, but I didn't find a cheaper way to get this
> > flexibility and curve shaping.
> >
> > env tick:
> >
> > int32_t y = e->phase >> 16;
> > int32_t K = k_lut[16+s->curve]; // K = 1 / (1-exp2(x))
> > y = K * ((1<<16) - exp2_s32_cheap(s->curve * y)) >> 15; // y = K *
> > (1-exp2(x * curve))
> >
> > lut:
> >
> > static int32_t k_lut[32] = { 32768, 32769, 32770, 32772, 32776, 32784,
> > 32800, 32832, 32896, 33026, 33288, 33825, 34952, 37449, 43690, 65536,
> > 0, -32768, -10922, -4681, -2184, -1057, -520, -258, -128, -64, -32,
> > -16, -8, -4, -2, -1};
> >
> > cheap exp2:
> >
> > uint32_t exp2_s32_cheap (int32_t x) {
> > const int32_t c = 0x57d8;
> > int32_t i = x >> 16;
> >
> > x &= 0xffff;
> > int32_t y = x*x;
> > y -= x << 16;
> > y >>= 16;
> > y *= c;
> > y >>= 16;
> > y += x + 0x10000;
> > if(i<0) return y >> -i;
> > else return y << i;
> > }
> >
> >> On Wed, Nov 5, 2025 at 11:00 PM Chris McDowell via Synth-diy
> >> <synth-diy at synth-diy.org> wrote:
> >>
> >> Howdy list,
> >>
> >> I've been thinking about this for about a decade. I use what the web
> calls a "leaky integrator" all over my synth code. I first used it as the
> basis of an envelope some 15 years ago when mimicking the Moog Rogue's
> strategy of providing a target and a "rate" to a lowpass filter built
> around a 3080 OTA. On an MCU with an FPU, it works pretty much great. the
> basics:
> >>
> >> output += (target - output) * rate
> >>
> >> where target changes based on what stage of an envelope we're in and
> rate is some small float coefficient calculated based on desired stage
> length in milliseconds.
> >>
> >> my question for this deep well of synth experience: is there a better
> way to do it? I came across a similar strategy on musicdsp.org recently
> that suggested baking the target into the coefficient, which does indeed
> save one subtract per iteration with the tradeoff that you have to do more
> math when changing envelope states. its use of log() (admittedly
> infrequently) makes me not all that interested, even if that's maybe a
> little irrational. If I find myself num_envelopes cycles away from meeting
> a timing deadline, I'll consider it...
> >>
> >> I'm familiar with Tom Wiltshire's envelope chip, which is another cool
> and very different strategy. What else is out there?!
> >>
> >> Cheers,
> >> Chris McDowell
> >> ________________________________________________________
> >> 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
> >
> >
> >
> > --
> > /Jonatan
> > http://kymatica.com
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://synth-diy.org/pipermail/synth-diy/attachments/20251107/762d9017/attachment.htm>


More information about the Synth-diy mailing list