Board index » delphi » Faster Frac() imlementation?

Faster Frac() imlementation?


2008-07-26 04:02:36 PM
delphi15
Hi all.. maybe you can help me. I am working on a freeware realtime
audio application for the Asus EEE pc (a little notebook with a modest
630MHz Celeron M). I am trying to optimize my time critical routines as
much as possible.. (why waste cpu cycles on things that don't improve
sound quality, right?)
For linear interpolation, which I frequently need to do, I typically
have to apply the Ceil and the Frac functions. The Fastcode Ceil
functions have helped me improve performance significantly..
Does something faster for Frac also exist? (My own silly basm
experiments all turned out slower than the RTL Frac :-)
Any help greatly appreciated. Thanks!
 
 

Re:Faster Frac() imlementation?

Hello Anybody,
<XXXX@XXXXX.COM>schrieb im Newsbeitrag
...
Quote
For linear interpolation, which I frequently need to do, I typically
have to apply the Ceil and the Frac functions. The Fastcode Ceil
functions have helped me improve performance significantly..

Does something faster for Frac also exist? (My own silly basm
experiments all turned out slower than the RTL Frac :-)

Any help greatly appreciated. Thanks!
Change all to integer-mathematics, than you don't need ceil or frac.
(my crystal ball is broken, show me the code ;-)
mfg.
Herby
--
www.hubert-seidel.de
 

Re:Faster Frac() imlementation?

Quote
>Does something faster for Frac also exist?
Change all to integer-mathematics, than you don't need ceil or frac.
(my crystal ball is broken, show me the code ;-)
Here is my most simplified linear interpolation mechanism.
I don't see how floating point maths can be avoided.
//round the current pointer into my sample data up
p2 := ceil( fIndex );
// determine the previous sample index (and avoid going lower than
sample 0)
p1 := pred( p2 );
if p1 < 0 then p1 := 0;
// pointer is probably somewhere between samples.. determine where...
fract := frac( fIndex );
// get the 2 nearest samples from the sample data
h1 := sample[p1];
h2 := sample[p2];
// now calculate the interpolated value using the difference between
these two samples
delta := h2 - h1;
result := round( h1 + ( fract * delta ) );
 

Re:Faster Frac() imlementation?

Hello Anybody,
<XXXX@XXXXX.COM>schrieb im Newsbeitrag
Quote
>>Does something faster for Frac also exist?

>Change all to integer-mathematics, than you don't need ceil or frac.
>(my crystal ball is broken, show me the code ;-)

Here is my most simplified linear interpolation mechanism.
I don't see how floating point maths can be avoided.
You can use fixpoint arithmetic e.g. 24:8 (in a 32bit Integer)
when 0..1 can represented with 8 Bits (0..255).
Quote
//round the current pointer into my sample data up
p2 := ceil( fIndex );
// determine the previous sample index (and avoid going lower than
sample 0)
p1 := pred( p2 );
if p1 < 0 then p1 := 0;
// pointer is probably somewhere between samples.. determine where...
fract := frac( fIndex );
// get the 2 nearest samples from the sample data
h1 := sample[p1];
h2 := sample[p2];
// now calculate the interpolated value using the difference between
these two samples
delta := h2 - h1;
result := round( h1 + ( fract * delta ) );
You can play with 4 Scollbars and this:
procedure TForm1.ScrollBarSample1_0_65535Change(Sender: TObject);
begin
Calculate;
end;
procedure TForm1.ScrollBarSample2_0_65535Change(Sender: TObject);
begin
Calculate;
end;
procedure TForm1.ScrollBarGradient_0_255Change(Sender: TObject);
begin
Calculate;
end;
procedure TForm1.Calculate;
var
s1,s2,g,t:integer;
begin
s1:= ScrollBarSample1_0_65535.Position; // First sample 16bit
s2:= ScrollBarSample2_0_65535.Position; // Second sample 16bit
g := ScrollBarGradient_0_255.Position; // gradient 8bit
t := s1+ (((s2-s1)*g) div 256);
ScrollBarTarget_0_65535.Position := t;
Caption := '('+IntToStr(s1)+'..'+IntToStr(s2)+') ['+FormatFloat('0.000',
g/256)+']='+IntToStr(t)
end;
###### [not tested !!! only an example/examination to the understanding, it
can be optimize]
// determine the previous sample index
p1 := fIndex div 256;
p2 := p1 + 1;
// pointer is probably somewhere between samples.. determine where...
fract := fIndex and 255;
// get the 2 nearest samples from the sample data
h1 := sample[p1];
h2 := sample[p2];
// now calculate the interpolated value using the difference between these
two samples
delta := h2 - h1;
result := h1+ (((h2-h1)*delta) div 256);
######
mfg.
Herby
--
www.hubert-seidel.de
 

Re:Faster Frac() imlementation?

Hello Anybody,
<XXXX@XXXXX.COM>schrieb im Newsbeitrag
Quote
>>Does something faster for Frac also exist?

>Change all to integer-mathematics, than you don't need ceil or frac.
>(my crystal ball is broken, show me the code ;-)

Here is my most simplified linear interpolation mechanism.
I don't see how floating point maths can be avoided.
You can use fixpoint arithmetic e.g. 24:8 (in a 32bit Integer)
when 0..1 can represented with 8 Bits (0..255).
Quote
//round the current pointer into my sample data up
p2 := ceil( fIndex );
// determine the previous sample index (and avoid going lower than
sample 0)
p1 := pred( p2 );
if p1 < 0 then p1 := 0;
// pointer is probably somewhere between samples.. determine where...
fract := frac( fIndex );
// get the 2 nearest samples from the sample data
h1 := sample[p1];
h2 := sample[p2];
// now calculate the interpolated value using the difference between
these two samples
delta := h2 - h1;
result := round( h1 + ( fract * delta ) );
You can play with 4 Scollbars and this:
procedure TForm1.ScrollBarSample1_0_65535Change(Sender: TObject);
begin
Calculate;
end;
procedure TForm1.ScrollBarSample2_0_65535Change(Sender: TObject);
begin
Calculate;
end;
procedure TForm1.ScrollBarGradient_0_255Change(Sender: TObject);
begin
Calculate;
end;
procedure TForm1.Calculate;
var
s1,s2,g,t:integer;
begin
s1:= ScrollBarSample1_0_65535.Position; // First sample 16bit
s2:= ScrollBarSample2_0_65535.Position; // Second sample 16bit
g := ScrollBarGradient_0_255.Position; // gradient 8bit
t := s1+ (((s2-s1)*g) div 256);
ScrollBarTarget_0_65535.Position := t;
Caption := '('+IntToStr(s1)+'..'+IntToStr(s2)+') ['+FormatFloat('0.000',
g/256)+']='+IntToStr(t)
end;
###### [not tested !!! only an example/examination to the understanding, it
can be optimize]
// determine the previous sample index
p1 := fIndex div 256;
p2 := p1 + 1;
// pointer is probably somewhere between samples.. determine where...
fract := fIndex and 255;
// get the 2 nearest samples from the sample data
h1 := sample[p1];
h2 := sample[p2];
// now calculate the interpolated value using the difference between these
two samples
delta := h2 - h1;
result := h1+ ((delta*frac) div 256);
######
mfg.
Herby
--
www.hubert-seidel.de
 

Re:Faster Frac() imlementation?

On 26 jul, 13:37, "Hubert Seidel" <XXXX@XXXXX.COM>writes:
Quote
Hello Anybody,

[snipped code]
// now calculate the interpolated value using the difference between these
two samples
delta := h2 - h1;
result := h1+ ((delta*frac) div 256);
Thanks.. that looks like it may speed things up quite a bit! I am going
to play around with that.
I may even be able to translate that into asm with my limited
assembler skills.
Thanks a lot!
Bram
 

Re:Faster Frac() imlementation?

On Jul 26, 10:02 am, XXXX@XXXXX.COM writes:
Quote
Hi all.. maybe you can help me. I am working on a freeware realtime

Just for information, you seem to be posting to USENET (via google
groups?) instead of using the newsserver of codegear directly. Posts
to USENET normally don't show up on the codegear servers. (Except the
ones from Hubert his ISP forwards messages to the codegear server
somehow).
support.codegear.com/newsgroups/
also see (4th item) www.teamb.com/newsgroups/faqs
Pieter
 

Re:Faster Frac() imlementation?

Quote
<XXXX@XXXXX.COM>schrieb im Newsbeitrag
news:XXXX@XXXXX.COM...
It looks like the OP is posting questions to Google.
Thus none of his posts are arriving here.
He needs to use a newreader and post to a
newsgroup provider instead of a search engine.
newsgroups.borland.com is a valid news server
for the borland-only groups.
 

Re:Faster Frac() imlementation?

Hi Hubert,
"Hubert Seidel" <XXXX@XXXXX.COM>writes:
Quote
You can use fixpoint arithmetic e.g. 24:8 (in a 32bit Integer)
when 0..1 can represented with 8 Bits (0..255).
Thanks for this! I am now busy replacing my all time-critical routines which use floating point with a fixed point mechanism based on the one you proposed and I have already achieved a 200% speed increase.
I've never thought about fixed point arithmatics before but it is simply perfect for many of my everyday purposes.
Cheers!
Bram