tanH soft clipping

Algorithm development and general DSP issues

Moderator: frank

Post Reply
MacroMachines
Posts: 71
Joined: Fri Dec 12, 2014 10:45 pm
Location: Detroit,MI
Contact:

tanH soft clipping

Post by MacroMachines »

Im wondering if there is a way to get tanh(x) style function in the FV-1? I use it alot in my algorithm designs for warm clean saturation, but I really have no idea how i would replicate these nice non linearities in assembler with the available opcodes. I am guessing it would have something to do with log/exp?

Hyperbolic tangent
The hyperbolic tangent is the solution to the differential equation
f'=1-f^{2} with f(0)=0 and the nonlinear boundary value problem:
1/2fn=f3-f; f(o)=f1(infinity) = 0

I am not a math pro and I really don't know what this means. I am trying to learn as its becoming useful in this DSP design world but damn its like learning a new language from trying to google the definition of each word hah.

Some music DSP info that is somewhat enlightening :
http://www.musicdsp.org/showone.php?id=178

"tanh(x) = sinh(x)/cosh(x)
= (exp(x) - exp(-x))/(exp(x) + exp(-x))
= (exp(2x) - 1)/(exp(2x) + 1)"

he also explains a taylor series for the exp approximation. but the above equation looks like something that could happen in spinASM relatively easily, but how to account for the /16 aspect of the exp opcode?

in the comments of the thread I found these:
tanh (x) = 1 - 2 / (exp (2*x) + 1)

tanh(x/2)~ x/(abs(x)+3/(2+x*x))

tanh(x/2) ~ x/(abs(x)+2/(2.12-1.44*abs(x)+x*x)) Maximum normalized difference 0.0063 from real tanh (x/2) - good enough now.


Here's the Analog Devices "Sharc" DSP translation of the tanh function (inline processing of register f0):

Code: Select all

f11 = 2.; 
f0 = f0 * f11; 
f11 = abs f0; 
f3 = 3.;	
f12 = f11+f3; 
f12 = f11*f2; 
f3 = 6.; 
f12 = f12+f3; 
f0 = f0*f12; 
f12 = f11*f12; 
f7 = 12.; 
f12 = f12+f3; 
f11 = 2.; 
f0 = recips f12, 
f7=f0; 
f12=f0*f12; 
f7=f0*f7, 
f0=f11-f12; 
f12=f0*f12; 
f7=f0*f7, 
f0=f11-f12; 
f12=f0*f12; 
rts(db); 
f7=f0*f7, 
f0=f11-f12;
f0=f0*f7; 
http://MacroMachines.net
Digital Control for your Analog Soul.
Iconnu
Posts: 10
Joined: Thu Apr 17, 2014 7:49 pm

Post by Iconnu »

from:

https://varietyofsound.wordpress.com/20 ... -fraction/


x2 = x * x

a := x·(135135 + x2·(17325 + x2·(378 + x2)))

b := 135135 + x2·(62370 + x2·(3150 + 28·x2))

tanh(x) = a/b


dividing each by 135135

a := x·(1 + x2·(0.1282051282 + x2·(0.002797202797 + x2)))

b := 1 + x2·(0.4615384615 + x2·(0.02331002331 + 0.0002072002072·x2))

Iconnu
MacroMachines
Posts: 71
Joined: Fri Dec 12, 2014 10:45 pm
Location: Detroit,MI
Contact:

Post by MacroMachines »

http://www.musicdsp.org/showone.php?id=238:



This is a rational function to approximate a tanh-like soft clipper. It is based on the pade-approximation of the tanh function with tweaked coefficients.

The function is in the range x=-3..3 and outputs the range y=-1..1. Beyond this range the output must be clamped to -1..1.

The first to derivatives of the function vanish at -3 and 3, so the transition to the hard clipped region is C2-continuous.

Code: Select all

Code : 
float rational_tanh(x)
{
    if( x < -3 )
        return -1;
    else if( x > 3 )
        return 1;
    else
        return x * ( 27 + x * x ) / ( 27 + 9 * x * x );
}
http://MacroMachines.net
Digital Control for your Analog Soul.
MacroMachines
Posts: 71
Joined: Fri Dec 12, 2014 10:45 pm
Location: Detroit,MI
Contact:

Post by MacroMachines »

Iconnu wrote:from:

https://varietyofsound.wordpress.com/20 ... -fraction/


x2 = x * x

a := x·(135135 + x2·(17325 + x2·(378 + x2)))

b := 135135 + x2·(62370 + x2·(3150 + 28·x2))

tanh(x) = a/b


dividing each by 135135

a := x·(1 + x2·(0.1282051282 + x2·(0.002797202797 + x2)))

b := 1 + x2·(0.4615384615 + x2·(0.02331002331 + 0.0002072002072·x2))

Iconnu

Thank you Iconnu,

I am curious if you know how I might begin to go about boiling this down into FV-1 opcodes, especially with regard to the divide by 16 and multiply by 16 that happen in log/exp.

EDIT: I just read the article and they have an assembler code image : https://varietyofsound.files.wordpress. ... pt_asm.png
" 13 multiply/adds plus a division " so if I use MAC ops like RDAX and SOF, if I am not mistaken I still need to use exp/log for the division, but I really am not sure if I understand how to do that. The knowledge base sheds a little insight:

__________________
To accomplish this, we will produce a 1/X output from the detector, and divide the result by 4 (multiply by 0.25). To produce 1/X, we do:

EXP( LOG (1) - LOG(X) )
This is simple division, and since LOG(1) is always zero, we can effectively find 1/X by taking the LOG, changing the result's sign, and doing an EXP on the result. Only changing the sign of the LOG result however, will produce an EXP result that is out of range. The LOG2 of 0.25 (our threshold) is -2, and after the LOG scaling of 16, will be numerically represented as -2/16, or -0.125. We will then change the sign of the LOG value by multiplying it by -1, giving us a +0.125 result. We want the output from the EXP function at this point to be 1, which requires a 0 value going into the EXP function. To accomplish this, we will write:

LOG -1.0,-0.125
EXP 1,0

____________________


I also found an asymmetric version that I remembered from the audulus forum:
http://folk.ntnu.no/oyvinbra/gdsp/Lesson4Modtanh.html
http://forum.audulus.com/discussion/com ... mment_6179

(e^x-e^-x)/(e^x+e^-x)

this asymmetric version a and b are offset values for positive and negative parts of the wave, it sounds good and useful for distortion. G is gain and x is input.
(exp(x*(a+G))-exp(x*(b-G)))/(exp(x*G)+exp(x*-G))
http://MacroMachines.net
Digital Control for your Analog Soul.
MacroMachines
Posts: 71
Joined: Fri Dec 12, 2014 10:45 pm
Location: Detroit,MI
Contact:

Post by MacroMachines »

EXP( LOG(X) - LOG(Y) ) = X/Y.


rereading the knowledge base on log/exp for the 5th time I think Im getting it now that I have an incentive

EXP( LOG(X) + LOG(Y) ) = X*Y.
Further, numbers could be divided:
EXP( LOG(X) - LOG(Y) ) = X/Y.
Finally, any number can be raised to any power with the use of LOG and EXP.

EXP( LOG(X) *2) = X2.
EXP( LOG(X) / 2) = X0.5 (square root)
http://MacroMachines.net
Digital Control for your Analog Soul.
Iconnu
Posts: 10
Joined: Thu Apr 17, 2014 7:49 pm

Post by Iconnu »

writing this down a little bit quick since I need to go out...

EQU X2 REG0
EQU X REG1
EQU A REG2
EQU B REG3
EQU TANH REG4

; X has been calculated and it resides in the register already...

LDAX X
MULX X
WRAX X2,0

; CALC A

LDAX X2
SOF 1, 0.002797202797
MULX X2
SOF 1, 0.1282051282
MULX X2
MULX X
RDAX X,1
WRAX A,0

;CALC B

LDAX X2
SOF 0.0002072002072, 0
SOF 1, 0.02331002331
MULX X2
SOF 1, 0.4615384615
MULX X2
SOF 1, 0.5
SOF 1, 0.5
WRAX B,0

LDAX B
LOG -1.0,-0.125
EXP 1,0
MULX A
; include a few SOF statements below to compensate level as "needed"
SOF -2,0
SOF -1,0
; etc....
;
WRAX TANH,0 ; your approx tanh value for X
MacroMachines
Posts: 71
Joined: Fri Dec 12, 2014 10:45 pm
Location: Detroit,MI
Contact:

Post by MacroMachines »

Wow! thank you so much :D
so I guess you divided the two by using log -1, -.125 and exp 1, 0 ?
Iconnu wrote: LDAX B
LOG -1.0,-0.125
EXP 1,0
MULX A
Wow thank you!! Ok, so now I understand the spin knowledge base bit on 1/x.. I am a bit math-tarded so I had forgotten that 1/x was what I need in this workflow for most of my division.

"This is simple division, and since LOG(1) is always zero, we can effectively find 1/X by taking the LOG, changing the result's sign, and doing an EXP on the result. Only changing the sign of the LOG result however, will produce an EXP result that is out of range. The LOG2 of 0.25 (our threshold) is -2, and after the LOG scaling of 16, will be numerically represented as -2/16, or -0.125. We will then change the sign of the LOG value by multiplying it by -1, giving us a +0.125 result. We want the output from the EXP function at this point to be 1, which requires a 0 value going into the EXP function. To accomplish this, we will write:

LOG -1.0,-0.125
EXP 1,0
"



I think I am also beginning to understand that floating point is probably where tanh really shines.. because you can get a great scaled signal that never hard clips. very curious to see how this will work out in fixed point with an approximation like this. I will check it out right now! :D

Again, thank you very much this was tremendously helpful and enlightening!
http://MacroMachines.net
Digital Control for your Analog Soul.
Post Reply