
Spin Semiconductor Support forum

View previous topic :: View next topic 
Author 
Message 
MacroMachines
Joined: 12 Dec 2014 Posts: 70 Location: Detroit,MI

Posted: Sat Aug 20, 2016 2:45 am Post subject: tanH soft clipping 


Im wondering if there is a way to get tanh(x) style function in the FV1? 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'=1f^{2} with f(0)=0 and the nonlinear boundary value problem:
1/2fn=f3f; 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.121.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:  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=f11f12;
f12=f0*f12;
f7=f0*f7,
f0=f11f12;
f12=f0*f12;
rts(db);
f7=f0*f7,
f0=f11f12;
f0=f0*f7;

_________________ http://MacroMachines.net
Digital Control for your Analog Soul. 

Back to top 


Iconnu
Joined: 17 Apr 2014 Posts: 10


Back to top 


MacroMachines
Joined: 12 Dec 2014 Posts: 70 Location: Detroit,MI

Posted: Sat Aug 20, 2016 9:09 am Post subject: 


http://www.musicdsp.org/showone.php?id=238:
This is a rational function to approximate a tanhlike soft clipper. It is based on the padeapproximation 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 C2continuous.
Code:  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. 

Back to top 


MacroMachines
Joined: 12 Dec 2014 Posts: 70 Location: Detroit,MI

Posted: Sat Aug 20, 2016 10:15 am Post subject: 


Thank you Iconnu,
I am curious if you know how I might begin to go about boiling this down into FV1 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.com/2011/02/lamberts_cf_opt_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/comment/6179#Comment_6179
(e^xe^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*(bG)))/(exp(x*G)+exp(x*G)) _________________ http://MacroMachines.net
Digital Control for your Analog Soul. 

Back to top 


MacroMachines
Joined: 12 Dec 2014 Posts: 70 Location: Detroit,MI

Posted: Sat Aug 20, 2016 10:42 am Post subject: 


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. 

Back to top 


Iconnu
Joined: 17 Apr 2014 Posts: 10

Posted: Sat Aug 20, 2016 1:05 pm Post subject: 


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 

Back to top 


MacroMachines
Joined: 12 Dec 2014 Posts: 70 Location: Detroit,MI

Posted: Sun Aug 21, 2016 5:36 pm Post subject: 


Wow! thank you so much
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 mathtarded 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!
Again, thank you very much this was tremendously helpful and enlightening! _________________ http://MacroMachines.net
Digital Control for your Analog Soul. 

Back to top 




You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum

Powered by phpBB © 2001, 2005 phpBB Group
