No Expression Patches
• This thread is an exercise in patches that have the no expression nodes except numerical constants as a design constraint. Just for the challenge of it.
• I It's interesting that the adsr node does not consistently respond to the square wave from the oscillator object.
• Ideally I would like an improved expression statement that has no overhead other than the calculation itself, but if that is not feasible, a few more arithmetic nodes would go a long way to make calculations simpler. I have not found any appreciable CPU load from constant expressions, but I have not done any exhaustive testing so I'm can't say I'm sure about that. I know we already have a constant node, but one that allowed text entry and displayed it's value would be useful. I tried using the constant node and setting it's min, max and value, but without attaching a value meter it was too confusing. I would also like to see a subtract node, divide node, negation node and some comparison nodes, although a more efficient expression node would definitely be preferable.
• Taylor’s going to make the expression node as fast as the arithmetic nodes - its a part of his ongoing optimization project! :) Still cool stuff though @robertsyrett - I made a flipflop out of arithmetic nodes once.
• @stsschoen I think comparison nodes are the things I immediately miss the most! I think for the purposes of this thread, I may have to make an exception for x/y expression as the historical divide node has been deprecated and I can't seem to find an old patch with it in it. The comparison nodes (<,>,==, etc) I feel like there is a clever way to make them which isn't necessarily CPU efficient.

>I made a flipflop out of arithmetic nodes once.
@biminiroad That would be super cool to post!
• The ADSR behavior also intrigued me so I did some testing. Here are my results:
The attack, decay and release knobs all set a time between 0 and 1 seconds. The sustain knob sets a percentage value. All slopes are linear.

1. Attack - starts when the input (i) goes from <= 0 to > 0
The initial gate height (g) is captured
The attack rate is calculated by g/at (attack time). The output (o) rises from it's value at the start of the attack phase at the rate calculated until either (o == g) or i <= 0. Note that the attack time is constant (set by the knob) and the rate varies depending on the gate height.<br />
2. Decay - starts when the attack phase ends. The rate is calculated from g/dt (decay time). Note that the decay rate is not dependent on the sustain level. Decay ends when o reaches the sustain level or i <= 0. The actual decay period is dependent on the setting, gate height, and sustain level so long as the gate remains above zero<br />
3. Sustain level - This sets the sustain value as a percentage of the initial gate height. Higher initial gate values result in a higher output for the same sustain setting. Ends when i <= 0.<br />
4. Release - starts when i <= 0. The rate is calculated from the initial gate height and release time (rt). It is not dependent on the sustain level. The release phase ends when o == 0 or the ADSR is retriggered (i > 0)

If the ADSR is retriggered before the end of the release phase the output value (o) will never reach 0. It will rise at the attack rate from its value at the time of the retrigger until o==g. The attack rate is the same as if o had reached 0 before the retrigger.

The key take-aways are that the knobs do not set a constant rate, they set a time value and the actual rates will vary depending on the initial gate height. Sustain values are also dependent on the initial gate height. Once the initial gate height has been captured, the value of the gate is ignored until the gate <= 0. Retriggering the ADSR before it has completed will restart the cycle without the input reaching zero.<br />Hope this is useful.