On Sat, 24 Nov 2018 14:19:01 +0100 Fons Adriaensen <f...@linuxaudio.org> wrote:
>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' ? :-) Ummm, bad wording on my part. I meant out by 1. The difference would be made up next period. >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. Well in this particular case, it can't be less than zero - notwithstanding time travel :) >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, > Interesting. I'll look into this. -- Will J Godfrey http://www.musically.me.uk Just because you know what I'm talking about, it doesn't mean *I* do. _______________________________________________ Linux-audio-dev mailing list Linux-audio-dev@lists.linuxaudio.org https://lists.linuxaudio.org/listinfo/linux-audio-dev