/*
* Created on Apr 15, 2007
*
* Copyright (c) 2006-2007 P.J.Leonard
*
* http://www.frinika.com
*
* This file is part of Frinika.
*
* Frinika is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* Frinika is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with Frinika; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package com.frinika.audio.analysis;
/**
* A fast but low precison (error ~ 1x10^-6) floating sinTable. feel free to do
* anything with this class. Alessandro Borges 2004
*/
import java.text.DecimalFormat;
public class FloatSinTable {
static final double[] table = build(720);
static double step;
static double invStep;
static int size = 0;
/**
* build sin table with size elements
*
* @param size
*/
final private static double[] build(int pSize) {
size = pSize;
double table[] = new double[size+1];
step = (float) (2d * Math.PI / size);
invStep = 1.0f / step;
for (int i = 0; i < size+1; i++) {
table[i] = Math.sin(step * ((double) i));
}
return table;
}
/**
* calculates fast sin, but with low precision.
*
* @param a
* angle in radians
* @return sin of angle a
*/
final public static double sinFast(double a) {
/*
* we need speed !
*
* if (a == Double.NaN) return Double.NaN; if (a == 0.0d) return 0.0d;
*/
int index = ((int) (a / step));
return table[index];
}
/**
* interpolated values of sin. Not so fast, but much more precise than
*
* @param ang
* angle in radians
* @return sin of angle a
*/
final public static double sin(float ang) {
int indexA = (int) (ang / step);
int indexB = (indexA + 1);
if (indexB >= size)
return table[indexA];
double a = table[indexA];
/*
* float b = table[indexB]; double real = Math.sin(ang); float w =
* (b-a); float x = ang - (indexA * step);//* invStep; w = w * x / step;
* a = a + w; return a ;
*/
return a + (table[indexB] - a) * (ang - (indexA * step)) * invStep;
}
/**
* Testing...
*
* @param args
*/
public static void main(String[] args) {
// FloatSinTable.build(4 * 360);
DecimalFormat df = new DecimalFormat("0.########");
int max = 10000000;
float pi = (float) Math.PI;
for (int i = 0; i < 20; i++) {
float angle = (float) (Math.random() * Math.PI * 2f);
double sinT = FloatSinTable.sin(angle);
float sin = (float) Math.sin(angle);
double delta = sin - sinT;
System.out.println("sin " + df.format(angle) + " :\t" + sinT
+ " : " + sin + " DELTA " + (delta));
}
long t1 = System.currentTimeMillis();
for (int i = 0; i < max; i++) {
double x = FloatSinTable.sin(pi);
}
long t2 = System.currentTimeMillis();
System.out.println("tempo SinTable: " + (t2 - t1));
long t3 = System.currentTimeMillis();
for (int i = 0; i < max; i++) {
float x = (float) Math.sin(pi);
}
long t4 = System.currentTimeMillis();
System.out.println("tempo Math.sin: " + (t4 - t3));
/** *** ********* */
long t5 = System.currentTimeMillis();
for (int i = 0; i < max; i++) {
double x = FloatSinTable.sinFast(pi);
}
long t6 = System.currentTimeMillis();
System.out.println("tempo Sintable fast: " + (t6 - t5));
}
}