/* * 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.ps2; //hybrid analysis filterbank: splits lower frequency bands class HybridFilterbank implements FilterbankTables { //in: 64 x 38 complex, out: 91 x 32 complex public static void analyze(float[][][] in, float[][][] out, boolean use34) { if(use34) { splitBands4(in[0], out, 0, FILTER_34_12, 12); splitBands4(in[1], out, 12, FILTER_34_8, 8); splitBands4(in[2], out, 20, FILTER_34_4, 4); splitBands4(in[3], out, 24, FILTER_34_4, 4); splitBands4(in[4], out, 28, FILTER_34_4, 4); } else { splitBands6(in[0], out, 0); splitBands2(in[1], out, 6, true); splitBands2(in[2], out, 8, false); } } //type B filtering for 2 bands; in: 38 complex, out:32 complex private static void splitBands2(float[][] in, float[][][] out, int outOff, boolean reverse) { final float[] tmp1 = new float[2]; final float[] tmp2 = new float[2]; int i, j; for(i = 0; i<32; i++) { tmp1[0] = FILTER_20_2[6]*in[i+6][0]; tmp1[1] = FILTER_20_2[6]*in[i+6][1]; tmp2[0] = 0.0f; tmp2[1] = 0.0f; for(j = 0; j<6; j += 2) { tmp2[0] += FILTER_20_2[j+1]*(in[i+j+1][0]+in[i+12-j-1][0]); tmp2[1] += FILTER_20_2[j+1]*(in[i+j+1][1]+in[i+12-j-1][1]); } if(reverse) { out[outOff+1][i][0] = tmp1[0]+tmp2[0]; out[outOff+1][i][1] = tmp1[1]+tmp2[1]; out[outOff][i][0] = tmp1[0]-tmp2[0]; out[outOff][i][1] = tmp1[1]-tmp2[1]; } else { out[outOff][i][0] = tmp1[0]+tmp2[0]; out[outOff][i][1] = tmp1[1]+tmp2[1]; out[outOff+1][i][0] = tmp1[0]-tmp2[0]; out[outOff+1][i][1] = tmp1[1]-tmp2[1]; } } } //type A filtering for 8 bands with summation; in: 38 complex, out:32 complex private static void splitBands6(float[][] in, float[][][] out, int outOff) { final float[][] tmp = new float[8][2]; final float[] sum = new float[2]; int i, j, k; for(i = 0; i<32; i++) { for(k = 0; k<8; k++) { sum[0] = FILTER_20_8[k][6][0]*in[i+6][0]; sum[1] = FILTER_20_8[k][6][0]*in[i+6][1]; for(j = 0; j<6; j++) { sum[0] += FILTER_20_8[k][j][0]*(in[i+j][0]+in[i+12-j][0]) -FILTER_20_8[k][j][1]*(in[i+j][1]-in[i+12-j][1]); sum[1] += FILTER_20_8[k][j][0]*(in[i+j][1]+in[i+12-j][1]) +FILTER_20_8[k][j][1]*(in[i+j][0]-in[i+12-j][0]); } tmp[k][0] = sum[0]; tmp[k][1] = sum[1]; } out[outOff+0][i][0] = tmp[6][0]; out[outOff+0][i][1] = tmp[6][1]; out[outOff+1][i][0] = tmp[7][0]; out[outOff+1][i][1] = tmp[7][1]; out[outOff+2][i][0] = tmp[0][0]; out[outOff+2][i][1] = tmp[0][1]; out[outOff+3][i][0] = tmp[1][0]; out[outOff+3][i][1] = tmp[1][1]; out[outOff+4][i][0] = tmp[2][0]+tmp[5][0]; out[outOff+4][i][1] = tmp[2][1]+tmp[5][1]; out[outOff+5][i][0] = tmp[3][0]+tmp[4][0]; out[outOff+5][i][1] = tmp[3][1]+tmp[4][1]; } } //type A filtering for 4/8/12 bands; in: 38 complex, out:32 complex private static void splitBands4(float[][] in, float[][][] out, int outOff, float[][][] filter, int len) { final float[] sum = new float[2]; int i, j, k; for(i = 0; i<len; i++) { for(k = 0; k<len; k++) { sum[0] = filter[k][6][0]*in[i+6][0]; sum[1] = filter[k][6][0]*in[i+6][1]; for(j = 0; j<6; j++) { sum[0] += filter[k][j][0]*(in[i+j][0]+in[i+12-j][0]) -filter[k][j][1]*(in[i+j][1]-in[i+12-j][1]); sum[1] += filter[k][j][0]*(in[i+j][1]+in[i+12-j][1]) +filter[k][j][1]*(in[i+j][0]-in[i+12-j][0]); } out[outOff+k][i][0] = sum[0]; out[outOff+k][i][1] = sum[1]; } } } //in: 91 x 32 complex, out: 64 x 32 complex for SBR public static void synthesize(float[][][] in, float[][][] out, boolean use34) { int n, k; if(use34) { for(n = 0; n<32; n++) { //sum first 32 into 5 for(k = 0; k<5; k++) { out[k][n][0] = 0; out[k][n][1] = 0; } for(k = 0; k<12; k++) { out[0][n][0] += in[k][n][0]; out[0][n][1] += in[k][n][1]; } for(k = 12; k<19; k++) { out[1][n][0] += in[k][n][0]; out[1][n][1] += in[k][n][1]; } for(k = 20; k<24; k++) { out[2][n][0] += in[k][n][0]; out[2][n][1] += in[k][n][1]; out[3][n][0] += in[k+4][n][0]; out[3][n][1] += in[k+4][n][1]; out[4][n][0] += in[k+8][n][0]; out[4][n][1] += in[k+8][n][1]; } //copy remaining 59 for(k = 0; k<59; k++) { out[k+5][n][0] = in[k+32][n][0]; out[k+5][n][1] = in[k+32][n][1]; } } } else { for(n = 0; n<32; n++) { //sum first 10 into 3 out[0][n][0] = in[0][n][0]+in[1][n][0]+in[2][n][0] +in[3][n][0]+in[4][n][0]+in[5][n][0]; out[0][n][1] = in[0][n][1]+in[1][n][1]+in[2][n][1] +in[3][n][1]+in[4][n][1]+in[5][n][1]; out[1][n][0] = in[6][n][0]+in[7][n][0]; out[1][n][1] = in[6][n][1]+in[7][n][1]; out[2][n][0] = in[8][n][0]+in[9][n][0]; out[2][n][1] = in[8][n][1]+in[9][n][1]; //copy remaining 61 for(k = 0; k<61; k++) { out[k+3][n][0] = in[k+10][n][0]; out[k+3][n][1] = in[k+10][n][1]; } } } } }