package net.sourceforge.jaad.aac.filterbank;
import net.sourceforge.jaad.aac.AACException;
/**
* This class is part of JAAD ( jaadec.sourceforge.net ) that is distributed
* under the Public Domain license. Code changes provided by the JCodec project
* are distributed under FreeBSD license.
*
* @author in-somnia
*/
class FFT implements FFTTables {
private final int length;
private final float[][] roots;
private final float[][] rev;
private float[] a, b, c, d, e1, e2;
FFT(int length) throws AACException {
this.length = length;
switch(length) {
case 64:
roots = FFT_TABLE_64;
break;
case 512:
roots = FFT_TABLE_512;
break;
case 60:
roots = FFT_TABLE_60;
break;
case 480:
roots = FFT_TABLE_480;
break;
default:
throw new AACException("unexpected FFT length: "+length);
}
//processing buffers
rev = new float[length][2];
a = new float[2];
b = new float[2];
c = new float[2];
d = new float[2];
e1 = new float[2];
e2 = new float[2];
}
void process(float[][] _in, boolean forward) {
final int imOff = (forward ? 2 : 1);
final int scale = (forward ? length: 1);
//bit-reversal
int ii = 0;
for(int i = 0; i<length; i++) {
rev[i][0] = _in[ii][0];
rev[i][1] = _in[ii][1];
int k = length>>1;
while(ii>=k&&k>0) {
ii -= k;
k >>= 1;
}
ii += k;
}
for(int i = 0; i<length; i++) {
_in[i][0] = rev[i][0];
_in[i][1] = rev[i][1];
}
//bottom base-4 round
for(int i = 0; i<length; i += 4) {
a[0] = _in[i][0]+_in[i+1][0];
a[1] = _in[i][1]+_in[i+1][1];
b[0] = _in[i+2][0]+_in[i+3][0];
b[1] = _in[i+2][1]+_in[i+3][1];
c[0] = _in[i][0]-_in[i+1][0];
c[1] = _in[i][1]-_in[i+1][1];
d[0] = _in[i+2][0]-_in[i+3][0];
d[1] = _in[i+2][1]-_in[i+3][1];
_in[i][0] = a[0]+b[0];
_in[i][1] = a[1]+b[1];
_in[i+2][0] = a[0]-b[0];
_in[i+2][1] = a[1]-b[1];
e1[0] = c[0]-d[1];
e1[1] = c[1]+d[0];
e2[0] = c[0]+d[1];
e2[1] = c[1]-d[0];
if(forward) {
_in[i+1][0] = e2[0];
_in[i+1][1] = e2[1];
_in[i+3][0] = e1[0];
_in[i+3][1] = e1[1];
}
else {
_in[i+1][0] = e1[0];
_in[i+1][1] = e1[1];
_in[i+3][0] = e2[0];
_in[i+3][1] = e2[1];
}
}
//iterations from bottom to top
int shift, m, km;
float rootRe, rootIm, zRe, zIm;
for(int i = 4; i<length; i <<= 1) {
shift = i<<1;
m = length/shift;
for(int j = 0; j<length; j += shift) {
for(int k = 0; k<i; k++) {
km = k*m;
rootRe = roots[km][0];
rootIm = roots[km][imOff];
zRe = _in[i+j+k][0]*rootRe-_in[i+j+k][1]*rootIm;
zIm = _in[i+j+k][0]*rootIm+_in[i+j+k][1]*rootRe;
_in[i+j+k][0] = (_in[j+k][0]-zRe)*scale;
_in[i+j+k][1] = (_in[j+k][1]-zIm)*scale;
_in[j+k][0] = (_in[j+k][0]+zRe)*scale;
_in[j+k][1] = (_in[j+k][1]+zIm)*scale;
}
}
}
}
}