12,243,333 members (45,122 online)
Technical Blog
alternative version

5.1K views
3 bookmarked
Posted

# Very Fast Sin Function for Java

, 3 Dec 2012 CPOL
 Rate this:
A very fast Sin function for Java.

Math.sin and the other transcendental functions in the JDKs java.lang.Math package tend to be very slow indeed. There are fast workarounds however.

The reason for the slowness is consistence. The library is designed to produce exactly the same results on all platforms. The results are standards compliant to the last binary bit. This just great if that is what you need. However, for some applications, like audio synthesis for example, it is total over kill.

In DSP outboard processors, wavetables have been used for years. The idea being that you pre-compute a set of values for a wave against phase angle. Then, when a value is required, its offset into the pre-computed table is used to get the value straight away. Sonic-Field stores audio at float (32 bit floating point) precision. A table big enough to hold all the possible values for the sin function where the phase angle is a float is way to big to be practical. It turns out that we really do not require anything like as big a table as that. A relatively modest table with linear interpolation gives results which are within float rounding error of the `Math.sin` values. The results are plenty good enough for audio work:

```static double[]             table = null;
static double               step;
static double               invStep;
static int                  size  = 0;

static
{
size = 10000;
table = new double[size];
step = 2d * Math.PI / size;
invStep = 1.0f / step;
for (int i = 0; i < size; ++i)
{
table[i] = Math.sin(step * i);
}
}

/** Find a linear interpolation from the table
*
* @param ang
* @return sin of angle a
*/
private final static double pi2   = PI * 2;

final public static double sin(double ang)
{
double t = ang % pi2;
int indexA = (int) (t / step);
int indexB = indexA + 1;
if (indexB >= size) return table[indexA];
double a = table[indexA];
return a + (table[indexB] - a) * (t - (indexA * step)) * invStep;
}```

The above code is straight from Sonic Field (and is therefore AGPL v3.0). It creates a 10 thousand element table. I tried a bigger table but it did not improve the results noticeably though less did degrade the accuracy rapidly. I have not micro-benchmarked the code, but Sonic Field patches using this code show the functions using sin running up to 10 times faster than using the `Math.sin` function.

## Share

 Web Developer United Kingdom
I am now a Software Systems Developer - Senior Principal at Micro Focus Plc. I am honoured to work in a team developing new compiler and runtime technology for Micro Focus.

My past includes a Ph.D. in computational quantum mechanics, software consultancy and several/various software development and architecture positions.

For more - see

blog: http://nerds-central.blogspot.com