Erik de Castro Lopo wrote:
On Tue, 29 Jun 2004 10:19:32 +0200
Benno Senoner <sbenno(a)gardena.net> wrote:
In LinuxSampler we do
double increment;
double fullindex;
int integer;
double fractional;
for (;;)
{
/* Bunch of other code. */
fullindex += increment;
integer = lrintf(fullindex);
fractional = fullindex - integer;
}
Have you tried compiling your code with gcc-3.4? Do you have a test suite
that will pick up if the above construct turns out wrong?
Lets say that after the addition of increment, the value of fullindex
in the 80 bit internal representation is 1.99999999999999999999999.
Pass that number through lrint and you get 2 and subtract 2 from the
80 bit internal representation and you get -0.00000000000000000000001
which is excatly the sort of problem I was trying to avoid.
I did not benchmark the above code against yours
but I think it should
be faster.
<>
I value correct-ness above speed :-).
Perhaps I should have added that our code is used to get the fractional
part and integer part in our code
is used to perform interpolation (either linear or cubic).
And even the above code based on lrintf() or FISTL can in some cases
return integer=x and fractional = 1.0
the value returned by the interpolator is still correct (we discussed
this years ago on the music-dsp, I'm too lazy
to dig in the archives). Even if it's a bit below zero, thanks to the
continuity of the polynomial interpolator you don't get
bogus results.
This is why we believe it's the fastest (staying in the floating point
domain) method possible (and stil correct for our purpose, aka doing
interpolation).
One could go a bit further and use a fixed point int part/fract part
index like Steve described. In that case you
could optimize the cubic interpolation (as Juan L. does in
cheesetracker) and look up the coefficients from tables.
But I think in case of LinuxSampler it would not buy us a big
performance increase since we do lots of other stuff too, I could be wrong.
At a later stage we will experiment with this to see if we can squeeze
out even more performance from the interpolator,
but for now there are more important things to do like providing
perfect GIG playback etc.
(plus instead
of lrintf() we use an asm FISTL macro which is a bit
faster (around 10% IIRC).
lrintf() is portable (ISO C99 standard), FISTL is not.
of course, but since we encapsulated all in a static inlined C++ class
the #ifdefs in that class use the most
efficient code depending from what architecture you are compiling on.
cheers,
Benno
http://www.linuxsampler.org