Wenfei wrote:

> float percentage;

> for (j = 0; j < 10000000; j++) {

> percentage = sinf(frequency * j * 2 * 3.14159 / sampleFreq );

> buffer[totalBytes] =ceilf(volume * percentage) + volume;

> totalBytes++;

> }
sinf() appears to be a Microsoft VC++ extension that computes sin() but

uses only 32-bit floats. Interesting that the zealots in this

newsgroup didn't call you on that.

Ok, anyhow remembering our trigonometry:

sin(a + b) = sin(a)*cos(b) + sin(b)cos(a)

cos(a + b) = cos(a)*cos(b) - sin(b)sin(a)

Now we can strength reduce the argument to sinf:

arg += (freqency*2*3.14159/sampleFreq);

But that value is a constant:

arg += deltaAngle; /* deltaAngle is precomputed as:

freqency*2*3.14159/sampleFreq */

So we can simplify this to:

s1 = percentage*cos(deltaAngle) + c*sin(deltaAngle);

c = c*cos(deltaAngle) + percentage*sin(deltaAngle);

percentage = s1;

And of course we can replace the cos(deltaAngle) and sin(deltaAngle)

with some precomputed values, and we initialize c to 1, and percentage

to 0.

This removes all the trigonometric functions altogether.

The problem is that it will have "accumulating accuracy" problems.

These problems are not trivial, because you will lose the sin^2+cos^2=1

property, which will start scaling your results (either upward or

downward) globally, which could get bad.

A simple way to mitigate this is to split the loop into groups of, say,

100 or 1000 at a time, and reset the parameters with their true

mathematical value with the raw sin/cos functions:

percentage = sinf (frequency * j * 2 * 3.14159 / sampleFreq);

c = cosf (frequency * j * 2 * 3.14159 / sampleFreq);

> Because the float variable, the above loop take 2 seconds in c or c++

> on Linux machine. Does anybody has a solution to reduce the time?
This takes time because you are calling sinf(), not because its

floating point.

--

Paul Hsieh

http://www.pobox.com/~qed/
http://bstring.sf.net/