[sdiy] Update - OT - Linear interpolation in C
Mikko Helin
maohelin at gmail.com
Wed Feb 2 20:04:00 CET 2011
Hi,
Nice and compact indeed. I tried using the __builtin_lac,
__builtin_mac and __builtin_sac functions and ended up with this kind
of code:
__inline__ static fractional linearInterpolation(register fractional
this, register fractional next, register fractional phase)
{
register int resultA asm("A");
resultA = __builtin_lac(this,0);
next -= this;
this = ((phase & 0x00FF) << 7); /* from assembler code, don't know if
correct */
resultA = __builtin_mac(resultA, this, next, NULL, NULL, 0, NULL,
NULL, 0, 0, 0);
this = __builtin_sac(resultA , 0);
return this;
}
The disassembled code looks like this:
312: 00 00 ca lac w0, #0x0, A
314: af b8 97 mov.w [w15-12], w1
316: 3f b8 97 mov.w [w15-10], w0
318: 00 80 50 sub.w w1, w0, w0
31a: a0 bf 9f mov.w w0, [w15-12]
31c: 03 80 fb ze w3, w0
31e: 47 00 dd sl.w w0, #0x7, w0
320: b0 bf 9f mov.w w0, [w15-10]
322: af ba 97 mov.w [w15-12], w5
324: 3f ba 97 mov.w [w15-10], w4
326: 12 01 c0 mac w4 * w5, A
328: 00 00 cc sac A, #0x0, w0
32a: b0 bf 9f mov.w w0, [w15-10]
32c: 3f b8 97 mov.w [w15-10], w0
The compiled code looks quite stupid (and the C-source code ugly), but
if you know how the compiler generates code you might be able to
improve from this. You can inline it but not from already inlined
function. Not good IMHO, it's seems to be better to write all DSP
stuff in assembly.
- Mikko
On Wed, Feb 2, 2011 at 5:49 PM, Richie Burnett
<rburnett at richieburnett.co.uk> wrote:
> Hi Tom,
>
> You can save a few instructions and registers by doing this...
>
>
> ; These variables come into assembly as:
> ; W4 - point1
> ; W5 - point2
> ; W6 - interpolation index
> _Lerp:
> ; Do the interp
> lac W4, A ; Load point1 value into Accum A
> msc W4*W6, A ; Sub scaled point1 value as interp index increases
> mac W5*W6, A ; Add scaled point2 value as interp index increases
> ; Get the result and return
> sac.r A, W0 ; Truncate and round result, store to W0
>
>
> The key things are loading the two sample values (I call them y0 and y1) that
> you want to interpolate between, straight into MAC registers w4 and w5. That
> saves two registers and two move instructions.
>
> And you only need one interpolation index. (You don't need to generate the one
> that's going in the opposite direction.) Initialise the accumulator with y0
> then as the index increases you "crossfade" from y0 to y1 by progressively
> subtracting a scaled amount of y0 and progressively adding a scaled amount of y1
> to the accumulator.
>
> You can also make use of the first MSC instruction to pre-fetch the y1 value
> from memory ready for use in the MAC that follows. This is useful if y0 and y1
> ultimately get pulled from an LUT in data-memory or via Program Space
> Visibility.
>
> If the interpolated lookup is part of a realtime audio synthesis loop then you
> might also consider loosing the Return instruction. Calls and Returns waste 3
> instruction cycles each because they trash the instruction execution pipeline.
>
> Hve spent quite a lot of time optimising interpolated look-up on dsPIC so
> hopefully this is helpful,
>
> -Richie Burnett,
>
>
>
> _______________________________________________
> Synth-diy mailing list
> Synth-diy at dropmix.xs4all.nl
> http://dropmix.xs4all.nl/mailman/listinfo/synth-diy
>
More information about the Synth-diy
mailing list