From the original SynthMaker forum (2004–2014), with its members’ names and dates.
infuzion ·
Liqih aka SM's Luisi posted this to get rid of denormals & unheard volumes to help with CPU:
streamin set;
streamout get;
get = set&((set>0.0000001)|(set<-0.0000001));
which I can ASM easily to:
streamin i;streamout o;
float F0P0000001000=0.0000001000;
float FM0P0000001000=-0.0000001000;
movaps xmm0,i;
cmpps xmm0,F0P0000001000,6;
movaps xmm1,i;
cmpps xmm1,FM0P0000001000,1;
orps xmm0,xmm1;
andps xmm0,i;
movaps o,xmm0;
But I think it can be 1-2 cycles smaller if this can be done:
streamin i;streamout o;
float fSomeNum=???;float fSomeNumInvert=value of 1/???;
int iBitMask=??? (likely the NOT of someNum in Int form)
movaps xmm0,i;
mulps xmm0,fSomeNum;
andps xmm0,iBitMask;
mulps xmm0,fSomeNumInvert;
movaps o,xmm0;
So I need some help for what the fSomeNum & iBitMask will be. I think this is the best approach, if it will work also with negative numbers also. If not, then a round off hack is needed.
cheers
rl ·
I think to remove denormals you have to _set_ (andps) the register to zero. Not sure, but I think mulps won't help in this situation, otherwise the result just continues in denormal mode.
Has someone some coding which has easy to reproduce denormalizing problems?
I'd like to do some tests with a dither algorithm I've implemented some weeks ago.
Thanks.
Tom
infuzion ·
TomC wrote: Has someone some coding which has easy to reproduce denormalizing problems?
I think denormals can be created where ever you have feedback that can become smaller, such as some filters, or reverb. You can try to make the signal-in very very small to try to start some denormals maybe.
TomC ·
If the following code does what I think it should do it's about one cycle better
than what we had so far:
Edit:...and it's as fast as MyCo's 'rounding hack' without relying on the implied rounding of the architecture.
infuzion ·
TomC wrote: If the following code does what I think it should do it's about one cycle better
In my own test bed, it is 1 cycle faster than my ASM version of Lusi's, but the same using the CPU tester from the WIKI.
How can one test if the output is correct? I'm a bit brain-dead right now & have to go to work, & I can't see if either has the right output 🙂
cheers
TomC ·
infuzion wrote:
TomC wrote: If the following code does what I think it should do it's about one cycle better
In my own test bed, it is 1 cycle faster than my ASM version of Lusi's, but the same using the CPU tester from the WIKI.
How can one test if the output is correct? I'm a bit brain-dead right now & have to go to work, & I can't see if either has the right output 🙂
cheers
Testing is quite simple: instead of 0.00000001 use 0.5 as denormalise value, put
an OSC with variable gain (from 0-1) in front and route the signal to a signal analyzer.
Everything below 0.5 changes to 0.
Cheers.
Tom
infuzion ·
MyCo, yours didn't work 🙁
TomC wrote: If the following code does what I think it should do it's about one cycle better than what we had so far:
So TomC wins the prize, saving 1 cycle on my AMD64 laptop. It reads much better than mine & uses only 1 register. I liked the scissors also.
Here is my little tweak to help make it more understandable & plop in easier:
streamin in;streamout out;
movaps xmm0,in;
//Start Denormalise -- 8< -- 8< --
float fNeg140db=1e-007;
int ABSMASK=2147483647;
andps xmm0,ABSMASK;
cmpps xmm0,fNeg140db,6;
andps xmm0,in;
//End Denormalise -- 8< -- 8< --
movaps out,xmm0;
Thanks for all the help! 😍
edit: I think there should be a Code command of this.
MyCo ·
infuzion wrote: MyCo, yours didn't work 🙁
how do you come to this? Try to put in:
5.877471754111438e-39
and you'll see that it works.
BTW: the way TomCs code work was also my idea, it's ripped out of the HP filter code that I translated for aliasant:
Code tips x a beginner
This uses 1e-038 as denormal cutoff, which is more exact than TomCs 1e-7.
BTW2: The 1e-7 is not a denormal cutoff, eg. if you put in 1e-8 in TomC's example you'll get 0 as result, but 1e-8 is not a denormal, because its exponent field is 01100100 (it's only a denormal if the field is completely filled with zero)
TomC ·
MyCo wrote: BTW: the way TomCs code work was also my idea, it's ripped out of the HP filter code that I translated for aliasant:
Code tips x a beginner
Believe it or not but I didn't copy it from your coding, I only looked at your second posting (for obvious reasons) where it already was removed.
It's the straight forward approach anyway, so we're most probably aren't the first ones to "invent" (thanks BALTHOR 🙂 ) this anyway.
Tom
infuzion ·
MyCo wrote: This uses 1e-038 as denormal cutoff, which is more exact than TomCs 1e-7.
Ah, you are correct, 1e-7 is really -140db, which most consider to be out of range of hearing, so to limit wasted CPU cycles. I'm assuming that the -140db cut would also rid of denormals please? Sorry if I was confusing in saying "denormal" in my first post :/
But yes, if one wanted only to rid of denormals & keep all other sound information there, then your technique is fastest. I was just intending to cut out a bit more, & have the range to be adjustable.
TomC ·
infuzion wrote:
MyCo wrote: This uses 1e-038 as denormal cutoff, which is more exact than TomCs 1e-7.
Ah, you are correct, 1e-7 is really -140db, which most consider to be out of range of hearing, so to limit wasted CPU cycles.
That was my intention (in fact, I used what was in the original posting, thought about it later and decided that it's close enough to the -144db min dynamic range a 24 bit recording can theoretically use).
I'm assuming that the -140db cut would also rid of denormals please? Sorry if I was confusing in saying "denormal" in my first post :/
It's bigger than denormal numbers, so it removes them, too.
Cheers.
Tom
TomC ·
MyCo wrote: 5359&start=120#40535
This uses 1e-038 as denormal cutoff, which is more exact than TomCs 1e-7.
Would you mind explaining this a bit more?
From my understanding of IEEE 754 normal positive numbers go from 10^−95 to 9.999999 × 10^96, so why 10^-38 and not lets say 10^-39 or 10^-37?
Curious.
Tom
MyCo ·
the smalles normal number is 1.1754944e-38 so if there is something below that number, the CPU has to switch in an trial & error mode, where it starts looping through values until it fits.
TomC ·
MyCo wrote: the smalles normal number is 1.1754944e-38 so if there is something below that number, the CPU has to switch in an trial & error mode, where it starts looping through values until it fits.