/* * Copyright (C) 2011 in-somnia * * This file is part of JAAD. * * JAAD is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 3 of the * License, or (at your option) any later version. * * JAAD 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 Lesser General * Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. * If not, see <http://www.gnu.org/licenses/>. */ package net.sourceforge.jaad.aac.filterbank; import net.sourceforge.jaad.aac.AACException; 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; } } } } }