Friday, June 11, 2021

Envelope stage curve calculations

For the XM8 we want different response curves to choose from for each stage. By default, the stage is linear. We then use lookup tables to get other responses.

Each curve is stretched in time and amplitude by the envelope code, so the only requirement is that a curve starts at (0,0) and ends at (1,1) (or, for ease of use here, starts at (0,1) and ends at (1,0).

Below are the general formulas for three types of curves - squared, exponential and logarithmic. As neither exponential nor logarithmic will pass through the necessary points by default, we add a multiplier and a constant to fit the curve. In addition, we add a parameter that can change the steepness of the curve to give the user some variation (the Andromeda A6 has three exponential and three logarithmic to choose froom.

The Modor synthesizer also has the option of using squared reciprocal and reciprocal. I've dropped these in favour of multiple variations of the others. 


General goal


We want various curves that go from (x, y) = (0, 0) to (1, 1),  or from (1,0) to (0,1):


Squared

A rising variant, going from (0,0) to (1,1), would be

y = x^2

The falling variant, going from (1,0) to (0, 1) would be

y = (1-x)^2 

These functions already fulfill the requirements.




Exponential

General exponential functions can be written as

y = ae^(bx) + c


where

- a transposes along x

- c transposes along y

- b selects steepness. Larger b = steeper curve

b chooses the "steepness" of the curve.


To solve, select a value for b and solve two eqations using the coordinates of the start and end points.


The solution for a rising curve is:

a = 1 / (e^b - 1)

c = -a

https://www.desmos.com/calculator/qquhqjlrjv


The solution for a falling curve is:

a = 1 / (1 - e^b)

c = (1-a)

https://www.desmos.com/calculator/73ufmkfxlb


Approximate values for b used by the Andromeda: 2.2 ("normal", exp 1), 4.4 (exp 2), 5.5 (exp3)


Logarithmic

For same range:

General formula

y = log(x+a) / b + c

where

- a transposes along x

- c transposes along y

- b selects steepness. Larger absolute value for b equals steeper curve. (positive values for rising curve, negative for falling)


The general solution:

Rising: (x, y) = (0, 0) to (1, 1):

a = 1 / (10^b - 1)

c = -log (a) / b

b > 0

https://www.desmos.com/calculator/tyfhantqj8



Falling: (x, y) = (0, 1) to (1, 0)

a = 10^b / (1-10^b)

c = -log(1+a) / b

b < 0

https://www.desmos.com/calculator/s9wahlimnm

The andromeda looks like it uses a b of approx 1.3, 1.7 and 2.2





For the natural logarithm, ln, the solution is:

y = ln(x+a) / b + c


Rising: (x, y) = (0, 0) to (1, 1):

a = 1 / (e^b - 1)

c = -ln (a) / b

b > 0

https://www.desmos.com/calculator/wxkxquiaqn

The andromeda looks like it uses a b of approx 3, 4 and 5


Falling: (x, y) = (0, 1) to (1, 0)

a = e^b / (1-e^b)

c = -ln(1+a) / b

b < 0


PS: The log and ln functions look exactly the same, only b varies.



Usage in envelope code

Our envelope lookup code uses 16bit unsigned ints, so both the x (time) and y (amplitude needs to go from 0 to 65535. This is easily achieved by dividing x with 65535 and multiplying the whole expression with 65535, ex:

y = 65535 * (ae^(-bx/65535) + c)


All testing was done with https://www.desmos.com/calculator