Curved envelope

Hi folks,

Im working on a synth and I’d like to add an adjustable level of curve (both concave and convex) to the attack stage of my ADSR envelope generator.

Problem is, it looks like common solutions for similar problems (e.g. Bezier curves) are too computationally expensive.

My initial thought is to generate a series of line segments that approximate the desired curve. For example, i made a rough formula to approximate a variable “curving” of the line [y=x, 0<=x<=1] with 4 linear functions. It finds a point along [y=1-x], finds 2 line that intersect at it, then calculates 2 more lines to “smooth out” the “curve”:

The envelope would then use these 4 functions to determine the attack level at any given time (i.e. x value).

I feel like there could be a better solution. Has anybody else worked with this problem? I would appreciate any guidance or direction.

Thanks!

1 Like

Hi @Evan - I’m not sure if this is ‘guidance or direction’ but a few thoughts:

It sounds like you’re re-‘inventing’ Calculus.

There are two separate times you might have to do this and they can be chosen - when the musician changes the ADSR settings and-or when the musician-sequencer-whatever requests-‘hits’ a note to be played.

Perhaps you could do your ‘calculations’ - the ones that are too ‘expensive-long’ only when the ADSR settings are changed, save the results in a usable form-table, and use them when playing a note.

1 Like

If the functions are too computationally expensive, why not use something similar to wavetables:

  • generate the envelope using an external tool (Python script, etc)
  • allocate an array and store the precalculated envelope curve there
  • divide the array into segments (A, D, S, R, etc.)
  • stretch and interpolate each individual segment as needed

All things considered, this trades CPU cycles for memory and may not be the best approach. Somehow I think it would be possible to calculate the curves you need in realtime, provided the algorithm is optimized.

2 Likes

Thank you both for the well thought replies!

After coding everything up, i was actually surprised to see that the “curve” generated by 4 linear functions produced musically pleasing results. For now, think im going to accept that “good enough is good enough” and run with it even though it’s not an ideal solution. I’ll publish my (hideous) source code in a separate post once the project is done.

I particularly like the wavetable idea and will likely circle back and implement that later down the road. It seems like a clean solution since memory doesn’t seem to be a huge constraint for this project.

1 Like

IMHO, 4 linear functions should be more than sufficient. It is worth mentioning that logarithmic pots taper approximation uses only two linear segments (and the taper not even close to being logarithmic):

1 Like

For posterity, I did find an envelope curving implementation in DaisySP: https://github.com/electro-smith/DaisySP/blob/master/Source/Control/adenv.cpp

It seems to use an exponential function. Haven’t tried it out, though .

EDIT: Nevermind :stuck_out_tongue:

\todo - Implement Curve (its only linear for now).

Hi @Evan , the video below shows how to implement linear and exponential envelopes in C++ and may be helpful in you case:

3 Likes

That’s perfect, thanks a ton!