Quote:
Originally Posted by sai'ke
Hey Tale, what did you notice that made you think it doesn't like sudden changes in gain? I've been trying it on pulses of gain, and notice no adverse effects?

Just send a sine wave (e.g. JS: synthesis/tonegenerator) through the JSFX below, and manually change gain at once between e.g. 0 and 60 dB a few times, and you will see spikes in the output. This doesn't happen with antialiasing turned off. I guess it's basically the same issue as with Direct Form biquads.
Code:
desc:Tanh saturation
slider1:0<0,60,1>Gain (dB)
slider2:1<0,1,1{Off,On}>AntiAliasing
@init
function tanh(x)
(
2 / (exp(x * 2) + 1)  1;
);
function tanh_aa(x)
instance(y)
local(old_x, old_y, dx)
(
old_x = this.x;
old_y = y;
abs(x) > log(2^511) ? (
x = sign(x);
this.x = x * log(2^511);
y = log(2^511)  log(2);
x;
) : (
this.x = x;
y = x  log(2 / (exp(x * 2) + 1));
dx = x  old_x;
abs(dx) > 0.0000000001 ? (y  old_y) / dx : 2 / (exp((x + old_x)) + 1)  1;
);
);
@slider
a = exp(slider1 * log(10)/20);
b = 1/a;
@sample
x = (spl0 + spl1) * 0.5;
y = aa.tanh_aa(x * a);
slider2 < 0.5 ? y = tanh(x * a);
spl0 = spl1 = y * b;
Quote:
Originally Posted by sai'ke
I'm curious why you write the value to compare with as log(2^511)? I realize that's close to 354, but is there some reason that would be more performant?

No... In fact, using 354 might be safer. But log(2^511) at least hints to where that number came from: The smallest nondenormal 64bit double floatingpoint number is 2^(1022).
BTW, I forgot to say that your oneliner tanh is really great for use in JSFX (and probably C/C++ as well). I was using (exp(2*x)1)/(exp(2*x)+1), but that requires a variable to store exp(2*x), and it's worse at maintaining precision. So thanks!