From the original SynthMaker forum (2004–2014), with its members’ names and dates.
MichaelBenjamin ·
i merged the softclip module (was it original synthmaker? i lost track of who made it) with the asm hardclip, hardwired the softclip variables to 0.8 and 1/0.8=1.25, and optimized the register usage. from 84 down to 48 cycles.
this module works good as a final stage, if you use it before you can delete out the marked hardclip.
you can adjust the clip and clipdiv variables to your liking. clipdiv = 1/clip
use it like you want, here is the code:
Thanks for sharing! And building on MyCo's edits:
streamin in;streamout out;
float clip=.8;float clipdiv=1.25;
float maxClip=.99;float minClip=-.99; //renamed to clairfy
float F1=1;float F0P25=.25; //"F1"=1.0 standard SM naming
movaps xmm0,in;
mulps xmm0,clip;
movaps xmm7,xmm0;
mulps xmm0,xmm0; //=mulps xmm0,xmm7, but can execute with above movaps
mulps xmm0,F0P25; //swapped
mulps xmm7,clipdiv; //swapped
addps xmm0,F1;
divps xmm7,xmm0;
minps xmm7,maxClip;
maxps xmm7,minClip;
movaps out,xmm7;
Saves 3 cycles on both Core2 & AMD64. The 2 mulps swapped seems to save 0.5 cycle on AMD64?
I prefer to use label-names for variables that are likely to change, like the maxClip (I'd play with hard-clipping +/-0.9999), & mnemonic names for hard-static variables, like F1=1.0, FP5=0.5, so they can be re-used easier, especially when merging with other code.
infuzion ·
infuzion wrote: Saves 3 cycles on both Core2 & AMD64.
TomC may have discovered why 3 cycles are save buy not needing to fetch a 2nd register.
MichaelBenjamin ·
latest version uses 40 cycles on my amd x2, 8 less, very good. this optimizing game is actually quite fun:)
bootsy ·
Can you please write the used softclip function down here for reference?
Most people - like me 😉 - are too lazy to disassemble the code.
MichaelBenjamin ·
i only got the asm, but it should be like this:
in=in*0.8;
out=in;
in=in*in*0.25+1;
out=out*1.25;
out=max(min(-0.99,(out/in)),0.99);