Math help for ADSR curved Decay and Relase segments
-
- KVRAF
- Topic Starter
- 1579 posts since 14 Oct, 2002
Hi guys,
my math knowledge is really modest, i'm trying to solve a thing a about an ADSR with variable curved segments.
The following link is what i did with Desmos an online graph calculator.
https://www.desmos.com/calculator/2p237rbfrn
Everything works for the Attack segment because the y range is 0..1.
But when the range is 1..S for the Decay segment and S..0 for the Release segment i can't get a formula to let pass a curve with an arbitrary exponent value (as in my Attack formula) on two given points on x,y plane.
I guess i could try to calculate the curve in the 0..1 range and then do some kind of translation and stretch/compression to fit the curve on the given points.
Any help, book, tutorial, hints?
I can't find anything really useful for this on the net.
Many thanks!
a.
my math knowledge is really modest, i'm trying to solve a thing a about an ADSR with variable curved segments.
The following link is what i did with Desmos an online graph calculator.
https://www.desmos.com/calculator/2p237rbfrn
Everything works for the Attack segment because the y range is 0..1.
But when the range is 1..S for the Decay segment and S..0 for the Release segment i can't get a formula to let pass a curve with an arbitrary exponent value (as in my Attack formula) on two given points on x,y plane.
I guess i could try to calculate the curve in the 0..1 range and then do some kind of translation and stretch/compression to fit the curve on the given points.
Any help, book, tutorial, hints?
I can't find anything really useful for this on the net.
Many thanks!
a.
-
- KVRian
- 853 posts since 13 Mar, 2012
So you have:Everything works for the Attack segment because the y range is 0..1.
x = f(y, exp)
which works
Why not simply extending the math from a above with a range and offset?But when the range is 1..S for the Decay segment and S..0 for the Release segment i can't get a formula to let pass a curve with an arbitrary exponent value (as in my Attack formula) on two given points on x,y plane.
Like:
x = (f(y, exp) * (range - offset)) + offset
On decay range=S and offset=1 (you might need to adapt the sign, depending if you look at range being negative, because decay decreases, or if you want to work positive range values)
On release range=S and offset=0
~~ ॐ http://soundcloud.com/mfr ॐ ~~
-
- KVRAF
- 3080 posts since 17 Apr, 2005 from S.E. TN
Hi lalo
Maybe it isn't what you want in curved lines, but have you looked at hermite interpolation?
You could search "hermite" on this page-- http://www.musicdsp.org/archive.php?classid=5#93
That kind of hermite basically tries to automatically draw smooth curves which always pass thru the control points. So the exact curve chosen would be determined by the equation, calculating whatever is necessary to smoothly connect the control points.
However if you want "user adjustable" curves of different shapes, on the same set of control points-- Maybe splines? Drawing of curves in such as adobe illustrator, twiddling the curve by dragging control points, are typically splines.
Maybe it isn't what you want in curved lines, but have you looked at hermite interpolation?
You could search "hermite" on this page-- http://www.musicdsp.org/archive.php?classid=5#93
That kind of hermite basically tries to automatically draw smooth curves which always pass thru the control points. So the exact curve chosen would be determined by the equation, calculating whatever is necessary to smoothly connect the control points.
However if you want "user adjustable" curves of different shapes, on the same set of control points-- Maybe splines? Drawing of curves in such as adobe illustrator, twiddling the curve by dragging control points, are typically splines.
-
- KVRAF
- Topic Starter
- 1579 posts since 14 Oct, 2002
Many thanks guys!
Thanks to PurpleSunray suggestions i came up with this.
I think is a good starting point for my Reaktor Core envelope project, and eventually i can do Max external or a full VST incorporating these elements i'm workin' on.
https://www.desmos.com/calculator/9ikgovu8zt
Thanks JCJR for your suggestions, i'll look into it when i'll need more complex control curves.
best!
a.
Thanks to PurpleSunray suggestions i came up with this.
I think is a good starting point for my Reaktor Core envelope project, and eventually i can do Max external or a full VST incorporating these elements i'm workin' on.
https://www.desmos.com/calculator/9ikgovu8zt
Thanks JCJR for your suggestions, i'll look into it when i'll need more complex control curves.
best!
a.
- KVRAF
- 3055 posts since 10 Nov, 2013 from Germany
-
- KVRAF
- Topic Starter
- 1579 posts since 14 Oct, 2002
Thanks again!
And how to do the same thing with a true exponential curve like
y = a^x
?
And how to do the same thing with a true exponential curve like
y = a^x
?
- KVRAF
- 12555 posts since 7 Dec, 2004
The simple format for this is like so:
lerp(start, end, f(x))
Where f(x) is your "curve".
lerp(start, end, f(x))
Where f(x) is your "curve".
Free plug-ins for Windows, MacOS and Linux. Xhip Synthesizer v8.0 and Xhip Effects Bundle v6.7.
The coder's credo: We believe our work is neither clever nor difficult; it is done because we thought it would be easy.
Work less; get more done.
The coder's credo: We believe our work is neither clever nor difficult; it is done because we thought it would be easy.
Work less; get more done.
-
- KVRAF
- Topic Starter
- 1579 posts since 14 Oct, 2002
thanks aciddose.
is "lerp" linear interpolation?
how to do computationally a lerp of a curve?
thanks
a.
is "lerp" linear interpolation?
how to do computationally a lerp of a curve?
thanks
a.
- KVRAF
- 12555 posts since 7 Dec, 2004
I just told you that.
lerp(x,y,z) = x + (y - x) * z
psh(min, max, z) = min * exp(log(max / min) * z)
lerp(0, 1, x) = straight line
lerp(0, 1, 1 - psh(0.01, 1, 1 - x) = log attack with 101% asymptote
lerp(0, 1, 2 - psh(0.5, 1, 1 - x) * 2) = log attack with 200% asymptote
lerp(1, 0.5, 1 - ps(0.01, 1, 1 - x)) = decay to 50.5% (to 1/100th)
Although this requires only a few muls and a call to exp() or approximation it is incredibly expensive compared to computing a lossy-integrator. The flexibility of parametrization of the curve is not free.
There are also a lot of complexities introduced as you attempt to model the functionality of a typical lossy-integrator based envelope (tracks sustain parameter at decay rate) and the slight benefit of exact timing is countered by the fact you must introduce direct discontinuities into the resulting waveform.
lerp(x,y,z) = x + (y - x) * z
psh(min, max, z) = min * exp(log(max / min) * z)
lerp(0, 1, x) = straight line
lerp(0, 1, 1 - psh(0.01, 1, 1 - x) = log attack with 101% asymptote
lerp(0, 1, 2 - psh(0.5, 1, 1 - x) * 2) = log attack with 200% asymptote
lerp(1, 0.5, 1 - ps(0.01, 1, 1 - x)) = decay to 50.5% (to 1/100th)
Although this requires only a few muls and a call to exp() or approximation it is incredibly expensive compared to computing a lossy-integrator. The flexibility of parametrization of the curve is not free.
There are also a lot of complexities introduced as you attempt to model the functionality of a typical lossy-integrator based envelope (tracks sustain parameter at decay rate) and the slight benefit of exact timing is countered by the fact you must introduce direct discontinuities into the resulting waveform.
Free plug-ins for Windows, MacOS and Linux. Xhip Synthesizer v8.0 and Xhip Effects Bundle v6.7.
The coder's credo: We believe our work is neither clever nor difficult; it is done because we thought it would be easy.
Work less; get more done.
The coder's credo: We believe our work is neither clever nor difficult; it is done because we thought it would be easy.
Work less; get more done.
-
- KVRAF
- Topic Starter
- 1579 posts since 14 Oct, 2002
Hi aciddose,
my math is still not at an advanced level and my electronic knowledge has still not touched a lossy integrator.
What's "psh"? and what's "ps"?
many thanks!
my math is still not at an advanced level and my electronic knowledge has still not touched a lossy integrator.
What's "psh"? and what's "ps"?
many thanks!
-
- KVRian
- 1379 posts since 26 Apr, 2004 from UK
ps is a typo, it's psh. And psh is defined in the post.
- KVRAF
- 12555 posts since 7 Dec, 2004
Here is another wrapper that simplifies usage of psh() for envelopes (it has other uses.)
esh(a, x) = 1 - (psh(a, 1, 1 - x) - a) * (1 / (1 - a))
This allows you to use:
lerp(start, end, esh(1 - 1/asymptote, x))
or:
lerp(start, end, esh(threshold, x))
For example in a decay you'd likely want to set the threshold based upon some value in decibels. For example -40 dB = 0.01
Your timing is a simple linear 0 -> 1, d = 1 / T
The "decay time" however which is printed should likely be computed based upon some section of the curve. Generally 90% to 10% is used although -20 dB (1/10) and others are also common.
The "linear" length of that section of the envelope will then be different from the timing value you print.
You should find that if you use low "threshold" values the timing will seem much too long with a very sharp logarithmic attack/decay. If you use high values the discontinuity will become too large at the end of the segment. The only solution available is to apply different values for each. Select the discontinuity you are comfortable with, then adjust the timing value displayed using one of the common systems.
"psh" is just a quick function name, you can rename the function whatever you like as I'm not aware of any similar "standard" function. The name is an abbreviation of "power shape".
esh(a, x) = 1 - (psh(a, 1, 1 - x) - a) * (1 / (1 - a))
This allows you to use:
lerp(start, end, esh(1 - 1/asymptote, x))
or:
lerp(start, end, esh(threshold, x))
For example in a decay you'd likely want to set the threshold based upon some value in decibels. For example -40 dB = 0.01
Your timing is a simple linear 0 -> 1, d = 1 / T
The "decay time" however which is printed should likely be computed based upon some section of the curve. Generally 90% to 10% is used although -20 dB (1/10) and others are also common.
The "linear" length of that section of the envelope will then be different from the timing value you print.
You should find that if you use low "threshold" values the timing will seem much too long with a very sharp logarithmic attack/decay. If you use high values the discontinuity will become too large at the end of the segment. The only solution available is to apply different values for each. Select the discontinuity you are comfortable with, then adjust the timing value displayed using one of the common systems.
"psh" is just a quick function name, you can rename the function whatever you like as I'm not aware of any similar "standard" function. The name is an abbreviation of "power shape".
Free plug-ins for Windows, MacOS and Linux. Xhip Synthesizer v8.0 and Xhip Effects Bundle v6.7.
The coder's credo: We believe our work is neither clever nor difficult; it is done because we thought it would be easy.
Work less; get more done.
The coder's credo: We believe our work is neither clever nor difficult; it is done because we thought it would be easy.
Work less; get more done.
-
- KVRAF
- 3388 posts since 29 May, 2001 from New York, NY
Here's another approach if want super fast performance:
So you can compute the next point based on the previous point and the derivative. However you need a division, but you can apply the same principle:
and compute the next point based on the previous one without the division.
If I remember correctly, I had stability problems with x=0 so I had to offset everything by a small constant, and offset it back.
Code: Select all
y=x^n
dy = x^(n-1) dx = n y dx / x
Code: Select all
z=1/x
dz = -1/(x^2) dx = -z*z dx.
If I remember correctly, I had stability problems with x=0 so I had to offset everything by a small constant, and offset it back.
- KVRAF
- 12555 posts since 7 Dec, 2004
At which point you're just computing a lossy-integrator. You can't input a random variable for x as in psh(..., x).
This is problematic if you want bi-directional loops or random jumping capability.
Using an approximation for exp (via float exponent) is actually very fast, significantly faster than integrating from the start point to some mid-point selected during a random jump.
It is possible to pre-compute fixed points (points known where jumps will occur) and use these to correct the cumulative error from integration. This is the method my envelopes in Xhip use. Integration is used to within 0.01 (1e-2 or -40 dB) immediately followed by a correction. The exception is during decay/release where the sustain stage is not entered (sustain = 0) the threshold is then 1e-4 or -80 dB.
Since we're dealing with integration a second-order impulse can be used to anti-alias the edges of the envelope (ala "minblamp") and any sharp edges can be anti-aliased with the first-order impulse ("minblep"). This can allow state change to occur between samples which can slightly increase the accuracy of a very short envelope segment (<100 us) although I don't bother with this.
In a parameterized envelope it may make sense especially where it may be used at audio rate as a generic modulator (replacing LFOs and envelopes.)
This is problematic if you want bi-directional loops or random jumping capability.
Using an approximation for exp (via float exponent) is actually very fast, significantly faster than integrating from the start point to some mid-point selected during a random jump.
It is possible to pre-compute fixed points (points known where jumps will occur) and use these to correct the cumulative error from integration. This is the method my envelopes in Xhip use. Integration is used to within 0.01 (1e-2 or -40 dB) immediately followed by a correction. The exception is during decay/release where the sustain stage is not entered (sustain = 0) the threshold is then 1e-4 or -80 dB.
Since we're dealing with integration a second-order impulse can be used to anti-alias the edges of the envelope (ala "minblamp") and any sharp edges can be anti-aliased with the first-order impulse ("minblep"). This can allow state change to occur between samples which can slightly increase the accuracy of a very short envelope segment (<100 us) although I don't bother with this.
In a parameterized envelope it may make sense especially where it may be used at audio rate as a generic modulator (replacing LFOs and envelopes.)
Free plug-ins for Windows, MacOS and Linux. Xhip Synthesizer v8.0 and Xhip Effects Bundle v6.7.
The coder's credo: We believe our work is neither clever nor difficult; it is done because we thought it would be easy.
Work less; get more done.
The coder's credo: We believe our work is neither clever nor difficult; it is done because we thought it would be easy.
Work less; get more done.
-
- KVRian
- 833 posts since 21 Feb, 2006 from FI