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 _______________________________________________ Linux-audio-dev mailing list Linux-audio-dev@lists.linuxaudio.org https://lists.linuxaudio.org/listinfo/linux-audio-dev