Not necessarily. If you use a level-threshold for terminating the envelope stage (rather than trying to predict the time at which it terminates), then any error accumulation will result in slight timing error, but won't cause any other harm.Music Engineer wrote: ↑Tue May 24, 2022 11:09 am I suppose, the error accumulation could be problematic though - especially for the concave shapes which would require an unstable filter
Envelope shapes in sfz
- KVRAF
- 7890 posts since 12 Feb, 2006 from Helsinki, Finland
-
Music Engineer Music Engineer https://www.kvraudio.com/forum/memberlist.php?mode=viewprofile&u=15959
- KVRAF
- Topic Starter
- 4285 posts since 8 Mar, 2004 from Berlin, Germany
Interesting idea. One would trade one type of error for another. One could also just re-initialize the state every couple of hundreds or thousands of samples according to a closed form formula for what it should be at that instant.
- KVRAF
- 1748 posts since 2 Jul, 2018
Could you post a code snippet of this?Music Engineer wrote: ↑Tue May 24, 2022 10:32 am That shouldn't be a problem. I'm scaling and shifting the raw leaky integrator output anyway to exactly hit the desired endpoints and I'm also fitzdazzing my denormals (FTZ/DAZ) on the framework side.
Thanks
-
Music Engineer Music Engineer https://www.kvraudio.com/forum/memberlist.php?mode=viewprofile&u=15959
- KVRAF
- Topic Starter
- 4285 posts since 8 Mar, 2004 from Berlin, Germany
I'm currently just calling
_MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON); // #defined in xmmintrin.h
_MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON); // #defined in pmmintrin.h
at the entry of my plugin class processing function. But this is crude not really production ready yet. You probably rather want to use something like this:
https://forum.juce.com/t/state-of-the-a ... tion/16802
https://blog.audio-tk.com/2016/09/20/au ... denormals/
...or do you mean the scale-and-shift stuff?
_MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON); // #defined in xmmintrin.h
_MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON); // #defined in pmmintrin.h
at the entry of my plugin class processing function. But this is crude not really production ready yet. You probably rather want to use something like this:
https://forum.juce.com/t/state-of-the-a ... tion/16802
https://blog.audio-tk.com/2016/09/20/au ... denormals/
...or do you mean the scale-and-shift stuff?
- KVRAF
- 1748 posts since 2 Jul, 2018
Sorry for beeing unclear. I did refer to the scale-and-shift stuff.
By the way: Do we still need to take care of the denormals also on the Mac - especially on the M1 machines. Not sure here.
By the way: Do we still need to take care of the denormals also on the Mac - especially on the M1 machines. Not sure here.
-
Music Engineer Music Engineer https://www.kvraudio.com/forum/memberlist.php?mode=viewprofile&u=15959
- KVRAF
- Topic Starter
- 4285 posts since 8 Mar, 2004 from Berlin, Germany
My code for this is probably a bit hard to decipher, so maybe this plot is clearer:
https://www.desmos.com/calculator/wvhvokixrr
The first (red) function is the regular unmodified decaying exponential with a decay time of "T" (usually called tau but desmos doesn't like this for a parameter). Then there is a second parameter that I called "a" which determines the desired end time of the envelope segment (here: a=2.4). I first subtract the value that the envelope actually hits at x=2.4 to make it hit zero at the end (blue) and then I scale the whole function by the reciprocal of 1 minus this offset to scale the start-value back up to one (green).
So the shift is given by s = exp(t_end/tau) and the scale (applied post-shift) is 1/(1-s)
Edit: This is my envelope generator code as used in Straightliner:
https://github.com/RobinSchmidt/RS-MET/ ... odulator.h
https://github.com/RobinSchmidt/RS-MET/ ... ulator.cpp
relevant are the
rsBreakpointModulator<T>::getSample()
function the .h and the
rsBreakpointModulator<T>::setupStateVariables()
function in the .cpp file for the per-sample-processing and per-breakpoint-handling code and there in particular the "ANALOG" branches. ...but it's about 15 years ago that I wrote this, so I don't really know anymore how it works in detail. But this envelope uses recursive implementations of all available shapes and uses appropriate scale-and-shift formulas (aka affine transforms) to hit the desired start- and endpoints exactly.
https://www.desmos.com/calculator/wvhvokixrr
The first (red) function is the regular unmodified decaying exponential with a decay time of "T" (usually called tau but desmos doesn't like this for a parameter). Then there is a second parameter that I called "a" which determines the desired end time of the envelope segment (here: a=2.4). I first subtract the value that the envelope actually hits at x=2.4 to make it hit zero at the end (blue) and then I scale the whole function by the reciprocal of 1 minus this offset to scale the start-value back up to one (green).
So the shift is given by s = exp(t_end/tau) and the scale (applied post-shift) is 1/(1-s)
Edit: This is my envelope generator code as used in Straightliner:
https://github.com/RobinSchmidt/RS-MET/ ... odulator.h
https://github.com/RobinSchmidt/RS-MET/ ... ulator.cpp
relevant are the
rsBreakpointModulator<T>::getSample()
function the .h and the
rsBreakpointModulator<T>::setupStateVariables()
function in the .cpp file for the per-sample-processing and per-breakpoint-handling code and there in particular the "ANALOG" branches. ...but it's about 15 years ago that I wrote this, so I don't really know anymore how it works in detail. But this envelope uses recursive implementations of all available shapes and uses appropriate scale-and-shift formulas (aka affine transforms) to hit the desired start- and endpoints exactly.
Last edited by Music Engineer on Wed May 25, 2022 12:51 pm, edited 4 times in total.
-
Music Engineer Music Engineer https://www.kvraudio.com/forum/memberlist.php?mode=viewprofile&u=15959
- KVRAF
- Topic Starter
- 4285 posts since 8 Mar, 2004 from Berlin, Germany
There are other ways of thinking about this in terms of "aiming beyond the actual target" but I usually think about this in terms scale-and-shift (or rather shift-and-scale in this case - which is the same thing, just using a different value for the shift)
Last edited by Music Engineer on Wed May 25, 2022 11:37 am, edited 2 times in total.
-
Music Engineer Music Engineer https://www.kvraudio.com/forum/memberlist.php?mode=viewprofile&u=15959
- KVRAF
- Topic Starter
- 4285 posts since 8 Mar, 2004 from Berlin, Germany
In what sense do they approximate the exp shape? Least squares? I guess, if I would try to get a polynomial approximation of a parameterized exp (or really any other function), I'd probably first try to match the values and one or more derivatives at the endpoints, i.e. use some formulas based on the idea of Hermite interpolation. Another option could be to use an interpolation polynomial matching the target function at judiciously selected x-values (maybe at the roots of (suitably scaled-and-shifted) Chebychev polynomials?)...in any case, one would need something that gives easily evaluatable formulas for the polynomial coeffs in terms of the shape parameter.Markus Krause wrote: ↑Tue May 24, 2022 10:14 am Modulation and random-access works well with the formulas posted above. I use them in my synths since many years. They are a polynomal approximation of the exp shape.
Last edited by Music Engineer on Wed May 25, 2022 12:55 pm, edited 1 time in total.
- KVRAF
- 1748 posts since 2 Jul, 2018
They have been tweaked for musicality and low CPU.
What they do is that they shape a linear slope ranging from [0;1] to an exp-style slope ranging from [0;1].
You can see the input X as the Y axis of a linear ADSR ranging from [0;1]. envshape is valid for [-1;1]. An envshape of 0 returns the linear slope. You get good analog ('exp style') results with an envshape of 0.8.
What they do is that they shape a linear slope ranging from [0;1] to an exp-style slope ranging from [0;1].
You can see the input X as the Y axis of a linear ADSR ranging from [0;1]. envshape is valid for [-1;1]. An envshape of 0 returns the linear slope. You get good analog ('exp style') results with an envshape of 0.8.
-
Music Engineer Music Engineer https://www.kvraudio.com/forum/memberlist.php?mode=viewprofile&u=15959
- KVRAF
- Topic Starter
- 4285 posts since 8 Mar, 2004 from Berlin, Germany
Ah - OK, I see. So, it's some hand-tuned function. Thanks for sharing. I'll take a closer look at them soon.They have been tweaked for musicality and low CPU.
-
- KVRian
- 833 posts since 21 Feb, 2006 from FI
Hmm... have you checked how liquidsfz (by Stefan Westerfeld) implements those ampeg_* opcodes in mentioned in opening post - https://github.com/swesterfeld/liquidsfz
- KVRAF
- 7890 posts since 12 Feb, 2006 from Helsinki, Finland
I tried looking at the loader (to see where the parameters go) and it looks an awful lot like it doesn't actually parse _shape even if those are mentioned in the opcode list.juha_p wrote: ↑Tue May 24, 2022 8:59 pm Hmm... have you checked how liquidsfz (by Stefan Westerfeld) implements those ampeg_* opcodes in mentioned in opening post - https://github.com/swesterfeld/liquidsfz
-
Music Engineer Music Engineer https://www.kvraudio.com/forum/memberlist.php?mode=viewprofile&u=15959
- KVRAF
- Topic Starter
- 4285 posts since 8 Mar, 2004 from Berlin, Germany
No - I wasn't aware of that project yet. Yet another FOSS sfz engine! Great! Another resource to figure out how to interpret the spec. Thanks for the hint!juha_p wrote: ↑Tue May 24, 2022 8:59 pm Hmm... have you checked how liquidsfz (by Stefan Westerfeld) implements those ampeg_* opcodes in mentioned in opening post - https://github.com/swesterfeld/liquidsfz
-
Music Engineer Music Engineer https://www.kvraudio.com/forum/memberlist.php?mode=viewprofile&u=15959
- KVRAF
- Topic Starter
- 4285 posts since 8 Mar, 2004 from Berlin, Germany
Ah - yes - you mean here at line 508?:
https://github.com/swesterfeld/liquidsf ... /loader.cc
yeah...that's where I would expect to see them as well