Looks good if I understand it. I'm a little unclear on a couple of things though:

1. Order of operations is not 100% clear. Are we doing parenthesis->multiplication(and division)->addition, or something else? I usually just use a million parenthesis. ;)
2. X squared keeping the original sign is not (|x| + x). I'm just assuming that (x^2) means x squared keeping original sign, and not... that other thing.

On Mon, May 13, 2013 at 3:48 PM, Paul Giblock <drfaygo@gmail.com> wrote:
For anyone interested, here is how I decided to resolve this for the lmms-lv2 port:

All three envelopes (vol, cut, res) behave the same: attack controls how long the envelope takes to reach 100% value, where it says for the length of hold (or until the note is released). The sustain amount is now a percentage of the maximum value instead of (1-max) as in LMMS. Thus, decay is how long it takes to reach the sustain level. Finally, release is how long it takes for the envelope to reach zero from the current value -- regardless of the current state of the envelope. This provides a continuous function, and is in-line with all the descriptions of an AHDSR envelope that I've read. Note, channel (instrument) volume is not a factor here, that is performed AFTER mixing all the instrument's notes together.

The big mystery in LMMS is how this envelope level (assume the output is between 0 and 1) maps to instrument parameters. For this, we let amt be the modulation amount (between -1 and 1). lfo_volume is the value of the volume LFO (between -1 and 1). Also, I use (x^2) as a shorthand for (|x| + x), that is: x squared, while maintaining the original sign.

envelope_volume = envelope_level * amt + (1-amt), if amt >= 0
envelope_volume = envelope_level * amt + 1, otherwise

volume = (envelope_volume * lfo_volume)^2, if lfo_modulate_env
volume = (envelope_volume + lfo_volume)^2, otherwise

LMMS, thus maps the envelope value to a velocity quadratically instead of linear or exponentially. Perhaps due to the perceived volume difference? Also, the volume envelope "Amount" knob is the ratio of enveloped to non-enveloped signal -- not the maximum volume.  This seems fine to me, although I might adjust the quadratic mapping to something more musical such as dB? The cutoff and resonance envelopes do not perform the same "mixing" operation. Thus, the amt value is actually the magnitude of the envelope:

envelope_cut = envelope_level * amt

cut = knob_cut + (envelope_cut * lfo_cut)^2 * 6000.0, if lfo_modulate_env
cut = knob_cut + (envelope_cut + lfo_cut)^2 * 6000.0, otherwise

The resonance envelope and LFO behave the same as the cutoff, but is scaled to 2.0 instead of 6000.0.  I personally feel this whole system is adequate and fairly straight-forward. However, I will try to replace as many of these magic [0..1] or [-1..1] parameters with proper values and units. Seconds for attack, hold, decay, release. Percentage for sustain. Perhaps dB for volume amount and Hz for cutoff -- although that may not be possible due to the dynamic nature of those two knobs.

-- Paul

AlienVault Unified Security Management (USM) platform delivers complete
security visibility with the essential security capabilities. Easily and
efficiently configure, manage, and operate all of your security controls
from a single console and one unified framework. Download a free trial.
LMMS-devel mailing list