kaj ·
I wish synthmaker team could reconsider the definition of exp() of the code component, because the current version of exp() formidably costs a lot of CPU power. 🙁
From the original SynthMaker forum (2004–2014), with its members’ names and dates.
kaj ·
I wish synthmaker team could reconsider the definition of exp() of the code component, because the current version of exp() formidably costs a lot of CPU power. 🙁
Mo ·
Welcome to the fourum, kaj
First use the green primitives where sample accuracy not is important (controller data etc.).
If you only using mono stream (no pack or poly), you can cut down on calculated channels in ASM code. Means the code is processing only one channel instead of 4 = 1/4 cpu use.
Would look like this:
// Mono exp streamin in; streamout out; float smIntVarE=2.71828183; float smIntVarHalf=0.5; float smIntVarTemp3=0.0; float smIntVarTemp=0.0; float smIntVarTemp2=0.0; movaps xmm0,smIntVarE; movaps smIntVarTemp,xmm0; movaps xmm0,in; movaps smIntVarTemp2,xmm0; fld smIntVarTemp2[0]; fld smIntVarTemp[0]; fyl2x; fld st(0); fld smIntVarHalf[0]; fsub; frndint; fxch; fld st(1); fsub; f2xm1; fld1; fadd; fxch; fld1; fscale; fstp st(1); fmul; fstp smIntVarTemp3[0]; movaps xmm0,smIntVarTemp3; movaps out,xmm0;
kaj ·
Thanks for advice. Sorry, I cannot yet figure out assembler code... I wanted to make Hyperbolic Tangent Distortion, which means tanh(x) = exp(x)-exp(-x) / exp(x)+exp(-x). I was able to make it as mono channel, but it costs a lot of CPU power so that it is less practical...
Mo ·
You would need to run it in blue mono if its for a VST FX. White poly are only for synths and depends of the midi to voice system to run. You will then only use one channel [0] with mono. So when your code are ready, connect a text primitive to the code primitive, copy the text to assembler primitive and delete the code for the 3 unused channels. Please post your final code in an .osm file if you need help for the optimizing.
kaj ·
The code is very simple (but costs a lot of CPU power...)
monoin in; monoin pregain; monoout out; float sig1, sig2; sig1 = in * pregain; sig2 = -1 * in * pregain; out = (exp(sig1)-exp(sig2))/(exp(sig1)+exp(sig2));
Mo ·
That code does not seem to work of some reason.?
Mo ·
It does work. It just need 2 inputs, so my mistake.
Try with this code in a ASM primitive. Should be 1/4 of the cpu use.
// Mono Hyperbolic Tangent Distortion monoin in; monoin pregain; monoout out; float smIntVarE=2.71828183; float smIntVarHalf=0.5; float smIntVarTemp3=0.0; float smIntVarTemp=0.0; float smIntVarTemp2=0.0; float sig1=0; float sig2=0; float FM1=-1; movaps xmm0,in; mulps xmm0,pregain; movaps sig1,xmm0; movaps xmm0,FM1; mulps xmm0,in; movaps xmm1,xmm0; mulps xmm1,pregain; movaps sig2,xmm1; movaps xmm0,smIntVarE; movaps smIntVarTemp,xmm0; movaps xmm0,sig1; movaps smIntVarTemp2,xmm0; fld smIntVarTemp2[0]; fld smIntVarTemp[0]; fyl2x; fld st(0); fld smIntVarHalf[0]; fsub; frndint; fxch; fld st(1); fsub; f2xm1; fld1; fadd; fxch; fld1; fscale; fstp st(1); fmul; fstp smIntVarTemp3[0]; movaps xmm0,smIntVarTemp3; movaps xmm1,smIntVarE; movaps smIntVarTemp,xmm1; movaps xmm1,sig2; movaps smIntVarTemp2,xmm1; fld smIntVarTemp2[0]; fld smIntVarTemp[0]; fyl2x; fld st(0); fld smIntVarHalf[0]; fsub; frndint; fxch; fld st(1); fsub; f2xm1; fld1; fadd; fxch; fld1; fscale; fstp st(1); fmul; fstp smIntVarTemp3[0]; movaps xmm1,smIntVarTemp3; subps xmm0,xmm1; movaps xmm1,smIntVarE; movaps smIntVarTemp,xmm1; movaps xmm1,sig1; movaps smIntVarTemp2,xmm1; fld smIntVarTemp2[0]; fld smIntVarTemp[0]; fyl2x; fld st(0); fld smIntVarHalf[0]; fsub; frndint; fxch; fld st(1); fsub; f2xm1; fld1; fadd; fxch; fld1; fscale; fstp st(1); fmul; fstp smIntVarTemp3[0]; movaps xmm1,smIntVarTemp3; movaps xmm2,smIntVarE; movaps smIntVarTemp,xmm2; movaps xmm2,sig2; movaps smIntVarTemp2,xmm2; fld smIntVarTemp2[0]; fld smIntVarTemp[0]; fyl2x; fld st(0); fld smIntVarHalf[0]; fsub; frndint; fxch; fld st(1); fsub; f2xm1; fld1; fadd; fxch; fld1; fscale; fstp st(1); fmul; fstp smIntVarTemp3[0]; movaps xmm2,smIntVarTemp3; addps xmm1,xmm2; divps xmm0,xmm1; movaps out,xmm0;
kaj ·
Thanks a lot. 🙂 It works fine. How to do? I have to compare your code with mine...
Mo ·
Just deleted the code for channel [1], [2] and [3] as they are not needed with mono.
trogluddite ·
Welcome to SM, Kaj, You might be interested in the thread HERE. In it, bootsy shows a method for generating tanh without using the exp function - I've had a little play and the approximation is stunningly close given the ultra-low CPU load.
It also has the advantage that it keeps all four sse channels - you can often use that to your advantage with the 'mono4' type streams and the pack/unpack primitives to process multiple signals without any extra CPU load. For example, you could process L and R of a stereo signal independently, but using just one code block.
kaj ·
Hi, trogluddite. Thanks for advice. I too tried several approximation (e.g. min-max approximation), but I did not know Lambert's continued fraction for tanh(x) that bootsy showed. I tried it. Maybe it is the best method as far as I know.
// Lambert's continued fraction for tanh(x) streamin in; streamin pregain; streamout out; float a,b,x, xx; x = in * pregain; xx = x*x; a=(((xx + 378)*xx + 17325)*xx + 135135) * x; b=((28*xx + 3150)*xx + 62370)*xx + 135135; out = a/b;
infuzion ·
kaj wrote: but I did not know Lambert's continued fraction for tanh(x) that bootsy showed. I tried it. Maybe it is the best method as far as I know.
I agree; fastest & most accurate.
Wrote something here? To have a post removed or your name hidden, write to [email protected].