[LAD] Is -ffast-math safe for audio?

Fons Adriaensen fons at linuxaudio.org
Sat Nov 24 14:19:01 CET 2018


On Sat, Nov 24, 2018 at 10:49:46AM +0000, Will Godfrey wrote:

> >The safe way is of course:
> >
> >int i = (int) floorf (p);
> >float f = p - i;
 
> I'd been mulling over *exactly* that point for some time. My reasoning being
> that in the latter case, if the integer was slightly wrong then using it for
> the subtraction should give a remainder that was also slightly wrong, but in a
> direction that tends to compensate for the error.

How can an int be 'slightly wrong' ? :-)
The advantage of the 'safe' way is that you always have p == i + f.

> The other thing, is why do we need the floorf? Or in the original example
> (which was taken from working code) truncf?
> A straight cast to int seems to give exactly the same result, and is at least
> twice as fast with -O3 and about 4 times as fast unoptimised.

We want f >= 0, so rounding must be towards -inf. Casting will truncate
(i.e. round towards zero). This gives the correct result only if p >= 0.
That may be all you need, but I wouldn't like to depend  on it.

There is a way to avoid all float to int conversions, at least outside
the per-sample loops.

Suppose you have a wavetable of size L, current position is float p,
and increment is float f. To generate N samples you'd have something
like:


for (i = 0; i < N; i++)
{
    k = floorf (p);
    u = p - k;

    // use k, u to interpolate in wavetable

    p += f;
    if (p >= L) p -= L;
}

To avoid floorf() inside the loop, instead of maintaining p and f
as floats, split both of them from the start into an integer and
float part:

k = floorf (p);
u = p - k;

kf = floorf (f);
uf = f - kf;

for (i = 0; i < N; i++)
{
    // use k, u to  interpolate in wavetable

    k += kf;
    u += uf;
    if (u >= 1.0f) 
    {
    	k += 1;
	u -= 1;
    }
    if (k >= L) k -= L;
    // or k &= L-1 if L is a power of 2.	
}


Ciao,

-- 
FA





More information about the Linux-audio-dev mailing list