Tanh approximations

DSP, Plugin and Host development discussion.
RELATED
PRODUCTS

Post

Interesting. In fact I had problems with exponentials in a component's model I wanted to simulate. I have replaced the direct calculus of my model with a table look-up, and some very simple linear interpolation. I have decreased the CPU consumption of my algorithms significantly, without loss in precision, using a 400x400 values table. But in fact, it's a little different of what you have been talking about, I don't approximate a function in its full range, but a set of equations using functions in a limited range...

Post

I always write things a few ways and time the code using the CPU indicator in a real host.

Sometimes tables win, sometimes they don't. When I use tables, I try to create them at init, to be sure that I can switch away from the table if I need to.

In my youth I'd just stick the numbers in and inevitably I'd forget where they came from.

And since Christian didn't test it, I'm going to assume my second function (with the ifs) in the message at Wed Sep 16, 2009 8:45 pm is the best.
Swing is the difference between a drum machine and a sex machine.

Post

mistertoast wrote:And since Christian didn't test it, I'm going to assume my second function (with the ifs) in the message at Wed Sep 16, 2009 8:45 pm is the best.
I did test it, but didn't post results as it was not much different to the other versions you posted.

To test everything yourself you can download my VST Plugin Analyser for free and write a small test plugin just applying the tanh approximation to the output. Use the harmonic distortion test ([CTRL] + H) to compare results.

My implementation of that plugin is available in my open source project here:
http://delphiasiovst.svn.sourceforge.ne ... aveshaper/ (using my own VST framework)

Christian
Last edited by Christian Budde on Fri Sep 18, 2009 4:30 pm, edited 1 time in total.

Post

Christian Budde wrote:
mistertoast wrote:And since Christian didn't test it, I'm going to assume my second function (with the ifs) in the message at Wed Sep 16, 2009 8:45 pm is the best.
I did test it, but didn't post results as it was not much different to the other versions you posted.

Christian
Sorry, I was kidding. :-) I believed you.
Swing is the difference between a drum machine and a sex machine.

Post

Christian Budde wrote:Hi,

Well, if you compare your version to the once I posted it is far off. The overtone structure doesn't look like a tanh() nor does a real tanh() contains odd harmonics, which indicates asymmetries. I haven't tried your approximation, but I'm sure it should be worse even compared by eye!

Christian
oops! I had multiplied by x^2 instead of x at one point, which threw everything off. Fixed now.

Post

Dozius wrote:
D1J1T wrote: I wrote this code in SSE assembler for use in Synthmaker. "streamin" and "streamout" data types are four packed single precision floats (128 bits), i.e., the four upped samples. iirc, this takes about 40 cycles per (128 bit) sample on an Athlon X2, not counting the overhead for up/downsampling. Those first 3 lines are (3.4e+38|0.999999|0.1) to get a zero followed by 31 ones.
For and absolute mask it's faster just to use an int equal to 2147483647, then it becomes only one AND operation. Although, you don't even need to do an absolute at all in this situation. Instead of doing all that sign flipping just do a min then a max and your done.

This

Code: Select all

movaps xmm7,F3P4;
orps xmm7,F0P9;
orps xmm7,F0P1;	
movaps xmm0,in;		//xmm0=x
movaps xmm1,xmm0;	//xmm1=x
andps xmm0,xmm7;	//xmm0=|x|
minps xmm0,F3;		//clamp |x| to 3.05059
andnps xmm7,xmm1;	//get the original sign
orps xmm0,xmm7;	//restore it to the clamped values
becomes this

Code: Select all

movaps xmm0,in;
minps xmm0,F3;  //F3 = 3.05059
maxps xmm0,FM3; //FM3 = -3.05059
You are, of course, correct about this. But I did have a reason for it- I didn't think to change it until you pointed it out. Synthmaker changes ints to floats, so the int masking trick doesn't work. I had done that just to see if it worked (it did).
Dozius wrote:Your code also doesn't match your approximation. The coefficients are different and your missing some operations. I think maybe you pasted the wrong code?
Fixed! The approximation I originally posted was for arctan, not tanh.

Post

D1J1T wrote:Synthmaker changes ints to floats, so the int masking trick doesn't work.
It's correct that the code module cannot use ints and that green ints connected to streams become floats but the ASM module in SM can define and use ints, it's what I always use when I need an absolute mask. Sorry to be so off topic but here is an example of an abs operation in asm in SM.

Code: Select all

streamin i;streamout o;
int absmask=2147483647; // 0x7fffffff;
movaps xmm0,i;
andps xmm0, absmask;
movaps o,xmm0;

Post

Have found an other one that seems very accurate at a first sight, but has some error around 0.0 where it should be flat:

Code: Select all

x *= 2.0;
return x/(abs(x)+2.0/(2.12-1.44*abs(x)+x*x));
TAL Software GmbH
https://tal-software.com/

Post

ToguAudioLine wrote:Have found an other one that seems very accurate at a first sight, but has some error around 0.0 where it should be flat:

Code: Select all

x *= 2.0;
return x/(abs(x)+2.0/(2.12-1.44*abs(x)+x*x));
This is based off that:

Y=X/(abs(X)+A/(B-C*abs(X)+X*X))

A = 0.43448473351E-01
B = 0.11932825377E+00
C = 0.15402606842E+00
Swing is the difference between a drum machine and a sex machine.

Post

Hi,

I've plotted both, but none is really close, especially when it comes to the harmonic structure.

and here they are:

Image
(original ToguAudioLine code)

Image
(modified ToguAudioLine code by mistertoast)

You can see that they produce far more harmonics then the original function.

Christian
Last edited by Christian Budde on Sat Sep 19, 2009 6:45 pm, edited 1 time in total.

Post

Christian Budde wrote:Hi,

I've plotted both, but none is really close, especially when it comes to the harmonic structure.

Christian
It's interesting how you can get close to the shape of the curve but still not match the higher harmonics at all.

So in one applications (maybe an audiorate one) one approximation might be better, and in another application (maybe a control rate one) another could be better.
Swing is the difference between a drum machine and a sex machine.

Post

(double post)
Last edited by Christian Budde on Sat Sep 19, 2009 6:44 pm, edited 1 time in total.

Post

Curve fitting programs typically evaluate fitness with some kind of sum of the squares of the errors.

If I made a curve-fitting program that tried to match an FFT rather than the curve itself, we'd find all kinds of new approximations we've probably never tried before.
Swing is the difference between a drum machine and a sex machine.

Post

mistertoast wrote:Curve fitting programs typically evaluate fitness with some kind of sum of the squares of the errors.

If I made a curve-fitting program that tried to match an FFT rather than the curve itself, we'd find all kinds of new approximations we've probably never tried before.
Well, both are directly connected. You need to find a perfect balance for time and frequency domain. The presented approach using the fast power 2 approximation qualifies for this IMHO. At lest the 4 term expression, where the discontinuity is below a certain threshold. It is maybe not as fast as some other approximations, but quite close in both time and frequency domain.

As I said before the other waveshapers are tempting, but when it comes to close circuit modeling you probably want the best deal with the least performance. Other than that it always depends on the application. In case the input is within a certain range only you might be able to beat my solution hands down, but my proposed solution has the advantage to have an equal error across the whole range! And it makes use of the algorithms optimized on the CPU already for other purposes (float<->int conversation), available in SSE & Co as well...

I don't see any progress in developing further versions with slightly different coefficients and hardly any improvements, which is the reason why I won't post further plots here anymore. Some pages before I posted the instructions, so anyone interested can do this at home.

Christian

Post

"I don't see any progress in developing further versions with slightly different coefficients and hardly any improvements, which is the reason why I won't post further plots here anymore. Some pages before I posted the instructions, so anyone interested can do this at home."

Agreed. At this point I'm only interested in other curves entirely, not coefficient optimization.
Swing is the difference between a drum machine and a sex machine.

Post Reply

Return to “DSP and Plugin Development”