/*
* 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.sbr;
/**
* Quadrature mirror filter for analysis
* @author in-somnia
*/
class QMFAnalysis implements FilterbankTables {
private final Filterbank filterBank;
private final float[] x, sum;
private final float[][] tmpIn, tmpOut;
private int xIndex;
QMFAnalysis(Filterbank filterBank, int channels) {
this.filterBank = filterBank;
x = new float[20*channels];
sum = new float[64];
tmpIn = new float[32][2];
tmpOut = new float[32][2];
xIndex = 0;
}
void performAnalysis32(float[] in, float[][][] out, int offset, int kx, int len) {
int off = 0;
int n;
for(int l = 0; l<len; l++) {
//add new samples to input buffer x
for(n = 32-1; n>=0; n--) {
x[xIndex+n] = in[off];
x[xIndex+n+320] = in[off];
off++;
}
//window and summation to create array u
for(n = 0; n<64; n++) {
sum[n] = (x[xIndex+n]*QMF_C[2*n])
+(x[xIndex+n+64]*QMF_C[2*(n+64)])
+(x[xIndex+n+128]*QMF_C[2*(n+128)])
+(x[xIndex+n+192]*QMF_C[2*(n+192)])
+(x[xIndex+n+256]*QMF_C[2*(n+256)]);
}
//update ringbuffer index
xIndex -= 32;
if(xIndex<0) xIndex = (320-32);
//reordering
tmpIn[31][1] = sum[1];
tmpIn[0][0] = sum[0];
for(n = 1; n<31; n++) {
tmpIn[31-n][1] = sum[n+1];
tmpIn[n][0] = -sum[64-n];
}
tmpIn[0][1] = sum[32];
tmpIn[31][0] = -sum[33];
filterBank.computeDCT4Kernel(tmpIn, tmpOut);
//reordering
for(n = 0; n<16; n++) {
if(2*n+1<kx) {
out[l+offset][2*n][0] = 2.0f*tmpOut[n][0];
out[l+offset][2*n][1] = 2.0f*tmpOut[n][1];
out[l+offset][2*n+1][0] = -2.0f*tmpOut[31-n][1];
out[l+offset][2*n+1][1] = -2.0f*tmpOut[31-n][0];
}
else {
if(2*n<kx) {
out[l+offset][2*n][0] = 2.0f*tmpOut[n][0];
out[l+offset][2*n][1] = 2.0f*tmpOut[n][1];
}
else {
out[l+offset][2*n][0] = 0;
out[l+offset][2*n][1] = 0;
}
out[l+offset][2*n+1][0] = 0;
out[l+offset][2*n+1][1] = 0;
}
}
}
}
}