Table Lookup for tanh() versus other solutions
-
- KVRist
- 56 posts since 16 Mar, 2014
Btw the same argument holds for 2-sample polyBLEP and oversampling in the context of generating band-limited saw and similar waveforms.
- KVRAF
- 7964 posts since 12 Feb, 2006 from Helsinki, Finland
Well.. yeah, except in the BLEP case it's computationally cheaper to use a longer BLEP without oversampling (or with just a little bit; I like 2x 'cos it means you get to have a wide transition which plays better with non-linearities down the line).martinvicanek wrote: ↑Sun May 26, 2024 4:00 pm Btw the same argument holds for 2-sample polyBLEP and oversampling in the context of generating band-limited saw and similar waveforms.
-
- KVRer
- 17 posts since 18 Jul, 2008
I've only done second-order ADAA thus far with hard clipping. Given the simplicity of this F2 (relative to, for example, the dilogarithm needed for tanh() proper), is seems this could be done fairly easily.martinvicanek wrote: ↑Sun May 26, 2024 8:59 amFrankly no, I never implemented 2nd order ADAA. The expressions grow quickly with increasing order. In my opinion, it is more efficient to stick to 1st order ADAA and increase oversampling if needed.Dogue wrote: ↑Fri May 24, 2024 5:29 pm I am curious about doing a second-order ADAA with this. F2 looks like:
Have you done second-order ADAA with this?Code: Select all
0.5x * sqrt(1+x^2) + 0.5ln|x + sqrt(1+x^2)|
Using oversampling—at least with the methods I'm using—creates a ripple in the waveform, with maximum amplitude values around +/-1.3. Of course, we can just lower the output gain, although in cases of clipping or of using saturation within a feedback loop, this might be less than ideal, hence the attraction (for me) of higher-order ADAA.
-
- KVRian
- 841 posts since 21 Feb, 2006 from FI
Back to the topic... I've been using this reasonably fast (at least w/ GCC) tanh() approximation for many:
https://www.desmos.com/calculator/s2vjhcbuni
https://godbolt.org/z/ePbMe4a3f
Code: Select all
float fast_tanh(float x){
float p = 2.0f * std::pow(x, 2.0f) + 1.17f;
return (x * p)/(std::abs(x * p) + 1.0f);
}
https://godbolt.org/z/ePbMe4a3f