/*
* Java port of ffmpeg mp3 decoder.
* Copyright (c) 2003 Jonathan Hueber.
*
* Copyright (c) 2000, 2001 Fabrice Bellard.
*
* This library 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 2 of the License, or (at your option) any later version.
*
* This library 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, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* See Credits file and Readme for details
*/
package net.sourceforge.jffmpeg.codecs.audio.mpeg.mp3;
import net.sourceforge.jffmpeg.codecs.audio.mpeg.mp3.data.Table;
/**
*
*/
public class SoundOutput {
private static final int[] mdct_win;
/* cos(pi*i/18) */
public static final int C1_18 = FIXR(0.98480775301220805936);
public static final int C2_18 = FIXR(0.93969262078590838405);
public static final int C3_18 = FIXR(0.86602540378443864676);
public static final int C4_18 = FIXR(0.76604444311897803520);
public static final int C5_18 = FIXR(0.64278760968653932632);
public static final int C6_18 = FIXR(0.5);
public static final int C7_18 = FIXR(0.34202014332566873304);
public static final int C8_18 = FIXR(0.17364817766693034885);
/* 0.5 / cos(pi*(2*i+1)/36) */
public static final int[] icos36 = new int[] {
FIXR(0.50190991877167369479),
FIXR(0.51763809020504152469),
FIXR(0.55168895948124587824),
FIXR(0.61038729438072803416),
FIXR(0.70710678118654752439),
FIXR(0.87172339781054900991),
FIXR(1.18310079157624925896),
FIXR(1.93185165257813657349),
FIXR(5.73685662283492756461),
};
public static final int icos72[] = new int[] {
/* 0.5 / cos(pi*(2*i+19)/72) */
FIXR(0.74009361646113053152),
FIXR(0.82133981585229078570),
FIXR(0.93057949835178895673),
FIXR(1.08284028510010010928),
FIXR(1.30656296487637652785),
FIXR(1.66275476171152078719),
FIXR(2.31011315767264929558),
FIXR(3.83064878777019433457),
FIXR(11.46279281302667383546),
/* 0.5 / cos(pi*(2*(i + 18) +19)/72) */
FIXR(-0.67817085245462840086),
FIXR(-0.63023620700513223342),
FIXR(-0.59284452371708034528),
FIXR(-0.56369097343317117734),
FIXR(-0.54119610014619698439),
FIXR(-0.52426456257040533932),
FIXR(-0.51213975715725461845),
FIXR(-0.50431448029007636036),
FIXR(-0.50047634258165998492)
};
int[] imdct36TmpBuffer = new int[ 18 ];
private void imdct36( int[] out, int[] in, int offset ) {
int i, j, t0, t1, t2, t3, s0, s1, s2, s3;
long in3_3, in6_6;
for(i=17 + offset;i>=1 + offset;i--)
in[i] += in[i-1];
for(i=17 + offset;i>=3 + offset;i-=2)
in[i] += in[i-2];
for(j=0;j<2;j++) {
int jin = j + offset;
in3_3 = MUL64(in[jin + 2*3], C3_18);
in6_6 = MUL64(in[jin + 2*6], C6_18);
imdct36TmpBuffer[j + 0] = FRAC_RND(MUL64(in[jin + 2*1], C1_18) + in3_3 +
MUL64(in[jin + 2*5], C5_18) + MUL64(in[jin + 2*7], C7_18));
imdct36TmpBuffer[j + 2] = in[jin + 2*0] + FRAC_RND(MUL64(in[jin + 2*2], C2_18) +
MUL64(in[jin + 2*4], C4_18) + in6_6 +
MUL64(in[jin + 2*8], C8_18));
imdct36TmpBuffer[j + 4] = FRAC_RND(MUL64(in[jin + 2*1] - in[jin + 2*5] - in[jin + 2*7], C3_18));
imdct36TmpBuffer[j + 6] = FRAC_RND(MUL64(in[jin + 2*2] - in[jin + 2*4] - in[jin + 2*8], C6_18)) -
in[jin + 2*6] + in[jin + 2*0];
imdct36TmpBuffer[j + 8] = FRAC_RND(MUL64(in[jin + 2*1], C5_18) - in3_3 -
MUL64(in[jin + 2*5], C7_18) + MUL64(in[jin + 2*7], C1_18));
imdct36TmpBuffer[j + 10] = in[jin + 2*0] + FRAC_RND(MUL64(-in[jin + 2*2], C8_18) -
MUL64(in[jin + 2*4], C2_18) + in6_6 +
MUL64(in[jin + 2*8], C4_18));
imdct36TmpBuffer[j + 12] = FRAC_RND(MUL64(in[jin + 2*1], C7_18) - in3_3 +
MUL64(in[jin + 2*5], C1_18) -
MUL64(in[jin + 2*7], C5_18));
imdct36TmpBuffer[j + 14] = in[jin + 2*0] + FRAC_RND(MUL64(-in[jin + 2*2], C4_18) +
MUL64(in[jin + 2*4], C8_18) + in6_6 -
MUL64(in[jin + 2*8], C2_18));
imdct36TmpBuffer[j + 16] = in[jin + 2*0] - in[jin + 2*2] + in[jin + 2*4] - in[jin + 2*6] + in[jin + 2*8];
}
i = 0;
for(j=0;j<4;j++) {
t0 = imdct36TmpBuffer[i];
t1 = imdct36TmpBuffer[i + 2];
s0 = t1 + t0;
s2 = t1 - t0;
t2 = imdct36TmpBuffer[i + 1];
t3 = imdct36TmpBuffer[i + 3];
s1 = MULL(t3 + t2, icos36[j]);
s3 = MULL(t3 - t2, icos36[8 - j]);
t0 = MULL(s0 + s1, icos72[9 + 8 - j]);
t1 = MULL(s0 - s1, icos72[8 - j]);
out[18 + 9 + j] = t0;
out[18 + 8 - j] = t0;
out[9 + j] = -t1;
out[8 - j] = t1;
t0 = MULL(s2 + s3, icos72[9+j]);
t1 = MULL(s2 - s3, icos72[j]);
out[18 + 9 + (8 - j)] = t0;
out[18 + j] = t0;
out[9 + (8 - j)] = -t1;
out[j] = t1;
i += 4;
}
s0 = imdct36TmpBuffer[16];
s1 = MULL(imdct36TmpBuffer[17], icos36[4]);
t0 = MULL(s0 + s1, icos72[9 + 4]);
t1 = MULL(s0 - s1, icos72[4]);
out[18 + 9 + 4] = t0;
out[18 + 8 - 4] = t0;
out[9 + 4] = -t1;
out[8 - 4] = t1;
}
/* cos(pi*i/24) */
public static final int C1 = FIXR(0.99144486137381041114);
public static final int C3 = FIXR(0.92387953251128675612);
public static final int C5 = FIXR(0.79335334029123516458);
public static final int C7 = FIXR(0.60876142900872063941);
public static final int C9 = FIXR(0.38268343236508977173);
public static final int C11 = FIXR(0.13052619222005159154);
private void imdct12( int[] out, int[] in ) {
int tmp;
long in1_3, in1_9, in4_3, in4_9;
in1_3 = MUL64(in[1], C3);
in1_9 = MUL64(in[1], C9);
in4_3 = MUL64(in[4], C3);
in4_9 = MUL64(in[4], C9);
tmp = FRAC_RND(MUL64(in[0], C7) - in1_3 - MUL64(in[2], C11) +
MUL64(in[3], C1) - in4_9 - MUL64(in[5], C5));
out[0] = tmp;
out[5] = -tmp;
tmp = FRAC_RND(MUL64(in[0] - in[3], C9) - in1_3 +
MUL64(in[2] + in[5], C3) - in4_9);
out[1] = tmp;
out[4] = -tmp;
tmp = FRAC_RND(MUL64(in[0], C11) - in1_9 + MUL64(in[2], C7) -
MUL64(in[3], C5) + in4_3 - MUL64(in[5], C1));
out[2] = tmp;
out[3] = -tmp;
tmp = FRAC_RND(MUL64(-in[0], C5) + in1_9 + MUL64(in[2], C1) +
MUL64(in[3], C11) - in4_3 - MUL64(in[5], C7));
out[6] = tmp;
out[11] = tmp;
tmp = FRAC_RND(MUL64(-in[0] + in[3], C3) - in1_9 +
MUL64(in[2] + in[5], C9) + in4_3);
out[7] = tmp;
out[10] = tmp;
tmp = FRAC_RND(-MUL64(in[0], C1) - in1_3 - MUL64(in[2], C5) -
MUL64(in[3], C7) - in4_9 - MUL64(in[5], C11));
out[8] = tmp;
out[9] = tmp;
}
int[] computerImdctTmpBuffer = new int[ 36 ];
int[] computerImdctTmpBuffer2 = new int[ 12 ];
int[] computerImdctTmpIn = new int[ 6 ];
public void computeImdct( Granule granule,
int[] sb_samples,
int[] mdct_buf ) {
int[] sb_hybrid = granule.getSbHybrid();
/* Caluculate sblimit (the last non-zero block) */
int pointer = 576;
int pointer1 = 2 * 18;
while ( pointer >= pointer1 ) {
pointer -= 6;
if ( (sb_hybrid[ pointer ] | sb_hybrid[ pointer + 1 ]
| sb_hybrid[ pointer + 2 ] | sb_hybrid[ pointer + 3 ]
| sb_hybrid[ pointer + 4 ] | sb_hybrid[ pointer + 5 ]) != 0 ) {
break;
}
}
int sblimit = pointer / 18 + 1;
int bufferPointer = 0;
/* Calculate the end of the long section */
int mdct_long_end = 0;
if ( granule.getBlockType() == 2 ) {
if ( granule.getSwitchPoint() ) {
mdct_long_end = 2;
}
} else {
mdct_long_end = sblimit;
}
/* Long wavelengths */
pointer = 0;
for ( int j = 0; j < mdct_long_end; j++ ) {
imdct36( computerImdctTmpBuffer, sb_hybrid, pointer );
/* System.out.println( "imdct36" );
for ( int p = 0; p < out.length; p++ ) {
System.out.print( out[ p ] + " " );
}
System.out.println();
*/
int outPtr = j;
int win1;
if ( granule.getSwitchPoint() && j < 2 ) {
win1 = 0;
} else {
win1 = 36 * granule.getBlockType();
}
win1 += (4 * 36) & (-(j & 1) );
for ( int i = 0; i < 18; i++ ) {
sb_samples[ outPtr ] = MULL( computerImdctTmpBuffer[ i ], mdct_win[ win1 + i ] ) + mdct_buf[ bufferPointer + i];
mdct_buf[ bufferPointer + i ] = MULL( computerImdctTmpBuffer[ i + 18 ], mdct_win[ win1 + i + 18 ] );
outPtr += Granule.SBLIMIT;
/*
System.out.println( out[ i ] + " " + mdct_win[ win1 + i ] + " "
+ out[ i+18 ] + " " + mdct_win[ win1 + i + 18 ] );
*/
}
pointer += 18;
bufferPointer += 18;
}
// System.out.println( "Point A" );
for ( int j = mdct_long_end; j < sblimit; j++ ) {
for ( int i = 0; i < 6; i++ ) {
computerImdctTmpBuffer[ i ] = 0;
computerImdctTmpBuffer[ i + 6 ] = 0;
computerImdctTmpBuffer[ i + 30 ] = 0;
}
int win = (4 * 36) & (-(j & 1) );
int buf2 = 6;
for ( int k = 0; k < 3; k++ ) {
int ptr1 = pointer + k;
for ( int i = 0; i < 6; i++ ) {
computerImdctTmpIn[ i ] = sb_hybrid[ ptr1 ];
ptr1 += 3;
// System.out.println( "--" + in[ i ] );
}
imdct12( computerImdctTmpBuffer2, computerImdctTmpIn );
for ( int i = 0; i < 6; i++ ) {
computerImdctTmpBuffer[ buf2 + i ] = MULL( computerImdctTmpBuffer2[ i ], mdct_win[ 2 * 36 + win + i ] ) + computerImdctTmpBuffer[ buf2 + i ];
computerImdctTmpBuffer[ buf2 + i + 6 ] = MULL( computerImdctTmpBuffer2[ i + 6 ], mdct_win[ 2 * 36 + win + i + 6 ] );
/*
System.out.println( out2[ i ] + " " + mdct_win[ 2 * 36 + win + i ] + " "
+ out2[ i+6 ] + " " + mdct_win[ 2 * 36 + win + i + 6 ] );
*/
}
buf2 += 6;
}
/* Overlap */
int out_ptr = 0;
for ( int i = 0; i < 18; i++ ) {
sb_samples[ j + out_ptr ] = computerImdctTmpBuffer[ i ] + mdct_buf[ bufferPointer + i ];
mdct_buf[ bufferPointer + i ] = computerImdctTmpBuffer[ i + 18 ];
out_ptr += Granule.SBLIMIT;
}
bufferPointer += 18;
pointer += 18;
}
/* System.out.println( "Sample dump A" );
for ( int i = 0; i < 576; i++ ) {
System.out.print( " " + sb_samples[i] );
if ( (i % 18) == 17 ) System.out.println();
}
*/
/* Zero bands */
for ( int j = sblimit; j < Granule.SBLIMIT; j++ ) {
int out_ptr = j;
for ( int i = 0; i < 18; i++ ) {
sb_samples[ out_ptr ] = mdct_buf[ bufferPointer + i ];
mdct_buf[ bufferPointer + i ] = 0;
out_ptr += Granule.SBLIMIT;
}
bufferPointer += 18;
}
/*
System.out.println( "Sample dump" );
for ( int i = 0; i < 576; i++ ) {
System.out.print( " " + sb_samples[i] );
if ( (i % 18) == 17 ) System.out.println();
}
**/
}
/* butterfly operator */
private final void BF(int[] tab, int tabPointer, int a, int b, int c) {
a += tabPointer;
b+= tabPointer;
int tmp0 = tab[a] + tab[b];
int tmp1 = tab[a] - tab[b];
tab[a] = tmp0;
tab[b] = MULL(tmp1, c);
}
public final void BF1(int[] tab, int tabPointer, int a, int b, int c, int d) {
BF(tab, tabPointer, a, b, COS4_0);
BF(tab, tabPointer, c, d, -COS4_0);
tab[tabPointer + c] += tab[tabPointer + d];
}
public final void BF2(int[] tab, int tabPointer, int a, int b, int c, int d) {
BF(tab, tabPointer, a, b, COS4_0);
BF(tab, tabPointer, c, d, -COS4_0);
tab[tabPointer + c] += tab[tabPointer + d];
tab[tabPointer + a] += tab[tabPointer + c];
tab[tabPointer + c] += tab[tabPointer + b];
tab[tabPointer + b] += tab[tabPointer + d];
}
/* cos(i*pi/64) */
public static final int COS0_0 = FIXR(0.50060299823519630134);
public static final int COS0_1 = FIXR(0.50547095989754365998);
public static final int COS0_2 = FIXR(0.51544730992262454697);
public static final int COS0_3 = FIXR(0.53104259108978417447);
public static final int COS0_4 = FIXR(0.55310389603444452782);
public static final int COS0_5 = FIXR(0.58293496820613387367);
public static final int COS0_6 = FIXR(0.62250412303566481615);
public static final int COS0_7 = FIXR(0.67480834145500574602);
public static final int COS0_8 = FIXR(0.74453627100229844977);
public static final int COS0_9 = FIXR(0.83934964541552703873);
public static final int COS0_10 = FIXR(0.97256823786196069369);
public static final int COS0_11 = FIXR(1.16943993343288495515);
public static final int COS0_12 = FIXR(1.48416461631416627724);
public static final int COS0_13 = FIXR(2.05778100995341155085);
public static final int COS0_14 = FIXR(3.40760841846871878570);
public static final int COS0_15 = FIXR(10.19000812354805681150);
public static final int COS1_0 = FIXR(0.50241928618815570551);
public static final int COS1_1 = FIXR(0.52249861493968888062);
public static final int COS1_2 = FIXR(0.56694403481635770368);
public static final int COS1_3 = FIXR(0.64682178335999012954);
public static final int COS1_4 = FIXR(0.78815462345125022473);
public static final int COS1_5 = FIXR(1.06067768599034747134);
public static final int COS1_6 = FIXR(1.72244709823833392782);
public static final int COS1_7 = FIXR(5.10114861868916385802);
public static final int COS2_0 = FIXR(0.50979557910415916894);
public static final int COS2_1 = FIXR(0.60134488693504528054);
public static final int COS2_2 = FIXR(0.89997622313641570463);
public static final int COS2_3 = FIXR(2.56291544774150617881);
public static final int COS3_0 = FIXR(0.54119610014619698439);
public static final int COS3_1 = FIXR(1.30656296487637652785);
public static final int COS4_0 = FIXR(0.70710678118654752439);
/* DCT32 without 1/sqrt(2) coef zero scaling. */
private void dct32(int[] out, int in[], int inPointer) {
/* pass 1 */
BF(in, inPointer, 0, 31, COS0_0);
BF(in, inPointer, 1, 30, COS0_1);
BF(in, inPointer, 2, 29, COS0_2);
BF(in, inPointer, 3, 28, COS0_3);
BF(in, inPointer, 4, 27, COS0_4);
BF(in, inPointer, 5, 26, COS0_5);
BF(in, inPointer, 6, 25, COS0_6);
BF(in, inPointer, 7, 24, COS0_7);
BF(in, inPointer, 8, 23, COS0_8);
BF(in, inPointer, 9, 22, COS0_9);
BF(in, inPointer, 10, 21, COS0_10);
BF(in, inPointer, 11, 20, COS0_11);
BF(in, inPointer, 12, 19, COS0_12);
BF(in, inPointer, 13, 18, COS0_13);
BF(in, inPointer, 14, 17, COS0_14);
BF(in, inPointer, 15, 16, COS0_15);
/* pass 2 */
BF(in, inPointer, 0, 15, COS1_0);
BF(in, inPointer, 1, 14, COS1_1);
BF(in, inPointer, 2, 13, COS1_2);
BF(in, inPointer, 3, 12, COS1_3);
BF(in, inPointer, 4, 11, COS1_4);
BF(in, inPointer, 5, 10, COS1_5);
BF(in, inPointer, 6, 9, COS1_6);
BF(in, inPointer, 7, 8, COS1_7);
BF(in, inPointer, 16, 31, -COS1_0);
BF(in, inPointer, 17, 30, -COS1_1);
BF(in, inPointer, 18, 29, -COS1_2);
BF(in, inPointer, 19, 28, -COS1_3);
BF(in, inPointer, 20, 27, -COS1_4);
BF(in, inPointer, 21, 26, -COS1_5);
BF(in, inPointer, 22, 25, -COS1_6);
BF(in, inPointer, 23, 24, -COS1_7);
/* pass 3 */
BF(in, inPointer, 0, 7, COS2_0);
BF(in, inPointer, 1, 6, COS2_1);
BF(in, inPointer, 2, 5, COS2_2);
BF(in, inPointer, 3, 4, COS2_3);
BF(in, inPointer, 8, 15, -COS2_0);
BF(in, inPointer, 9, 14, -COS2_1);
BF(in, inPointer, 10, 13, -COS2_2);
BF(in, inPointer, 11, 12, -COS2_3);
BF(in, inPointer, 16, 23, COS2_0);
BF(in, inPointer, 17, 22, COS2_1);
BF(in, inPointer, 18, 21, COS2_2);
BF(in, inPointer, 19, 20, COS2_3);
BF(in, inPointer, 24, 31, -COS2_0);
BF(in, inPointer, 25, 30, -COS2_1);
BF(in, inPointer, 26, 29, -COS2_2);
BF(in, inPointer, 27, 28, -COS2_3);
/* pass 4 */
BF(in, inPointer, 0, 3, COS3_0);
BF(in, inPointer, 1, 2, COS3_1);
BF(in, inPointer, 4, 7, -COS3_0);
BF(in, inPointer, 5, 6, -COS3_1);
BF(in, inPointer, 8, 11, COS3_0);
BF(in, inPointer, 9, 10, COS3_1);
BF(in, inPointer, 12, 15, -COS3_0);
BF(in, inPointer, 13, 14, -COS3_1);
BF(in, inPointer, 16, 19, COS3_0);
BF(in, inPointer, 17, 18, COS3_1);
BF(in, inPointer, 20, 23, -COS3_0);
BF(in, inPointer, 21, 22, -COS3_1);
BF(in, inPointer, 24, 27, COS3_0);
BF(in, inPointer, 25, 26, COS3_1);
BF(in, inPointer, 28, 31, -COS3_0);
BF(in, inPointer, 29, 30, -COS3_1);
/* pass 5 */
BF1(in, inPointer, 0, 1, 2, 3);
BF2(in, inPointer, 4, 5, 6, 7);
BF1(in, inPointer, 8, 9, 10, 11);
BF2(in, inPointer, 12, 13, 14, 15);
BF1(in, inPointer, 16, 17, 18, 19);
BF2(in, inPointer, 20, 21, 22, 23);
BF1(in, inPointer, 24, 25, 26, 27);
BF2(in, inPointer, 28, 29, 30, 31);
/* pass 6 */
in[ inPointer + 8 ] += in[ inPointer + 12 ];
in[ inPointer + 12 ] += in[ inPointer + 10 ];
in[ inPointer + 10 ] += in[ inPointer + 14 ];
in[ inPointer + 14 ] += in[ inPointer + 9 ];
in[ inPointer + 9 ] += in[ inPointer + 13 ];
in[ inPointer + 13 ] += in[ inPointer + 11 ];
in[ inPointer + 11 ] += in[ inPointer + 15 ];
out[ 0] = in[ inPointer + 0];
out[16] = in[ inPointer + 1];
out[ 8] = in[ inPointer + 2];
out[24] = in[ inPointer + 3];
out[ 4] = in[ inPointer + 4];
out[20] = in[ inPointer + 5];
out[12] = in[ inPointer + 6];
out[28] = in[ inPointer + 7];
out[ 2] = in[ inPointer + 8];
out[18] = in[ inPointer + 9];
out[10] = in[ inPointer + 10];
out[26] = in[ inPointer + 11];
out[ 6] = in[ inPointer + 12];
out[22] = in[ inPointer + 13];
out[14] = in[ inPointer + 14];
out[30] = in[ inPointer + 15];
in[ inPointer + 24 ] += in[ inPointer + 28 ];
in[ inPointer + 28 ] += in[ inPointer + 26 ];
in[ inPointer + 26 ] += in[ inPointer + 30 ];
in[ inPointer + 30 ] += in[ inPointer + 25 ];
in[ inPointer + 25 ] += in[ inPointer + 29 ];
in[ inPointer + 29 ] += in[ inPointer + 27 ];
in[ inPointer + 27 ] += in[ inPointer + 31 ];
out[ 1] = in[ inPointer + 16] + in[ inPointer + 24];
out[17] = in[ inPointer + 17] + in[ inPointer + 25];
out[ 9] = in[ inPointer + 18] + in[ inPointer + 26];
out[25] = in[ inPointer + 19] + in[ inPointer + 27];
out[ 5] = in[ inPointer + 20] + in[ inPointer + 28];
out[21] = in[ inPointer + 21] + in[ inPointer + 29];
out[13] = in[ inPointer + 22] + in[ inPointer + 30];
out[29] = in[ inPointer + 23] + in[ inPointer + 31];
out[ 3] = in[ inPointer + 24] + in[ inPointer + 20];
out[19] = in[ inPointer + 25] + in[ inPointer + 21];
out[11] = in[ inPointer + 26] + in[ inPointer + 22];
out[27] = in[ inPointer + 27] + in[ inPointer + 23];
out[ 7] = in[ inPointer + 28] + in[ inPointer + 18];
out[23] = in[ inPointer + 29] + in[ inPointer + 19];
out[15] = in[ inPointer + 30] + in[ inPointer + 17];
out[31] = in[ inPointer + 31];
}
private long SUM8( long sum, int windowOffset, int[] synth_buffer, int bufferPointer ) {
sum += MUL64( window[ 0 * 64 + windowOffset ], synth_buffer[ 0 * 64 + bufferPointer ] );
sum += MUL64( window[ 1 * 64 + windowOffset ], synth_buffer[ 1 * 64 + bufferPointer ] );
sum += MUL64( window[ 2 * 64 + windowOffset ], synth_buffer[ 2 * 64 + bufferPointer ] );
sum += MUL64( window[ 3 * 64 + windowOffset ], synth_buffer[ 3 * 64 + bufferPointer ] );
sum += MUL64( window[ 4 * 64 + windowOffset ], synth_buffer[ 4 * 64 + bufferPointer ] );
sum += MUL64( window[ 5 * 64 + windowOffset ], synth_buffer[ 5 * 64 + bufferPointer ] );
sum += MUL64( window[ 6 * 64 + windowOffset ], synth_buffer[ 6 * 64 + bufferPointer ] );
sum += MUL64( window[ 7 * 64 + windowOffset ], synth_buffer[ 7 * 64 + bufferPointer ] );
return sum;
}
private long SUB8( long sum, int windowOffset, int[] synth_buffer, int bufferPointer ) {
sum -= MUL64( window[ 0 * 64 + windowOffset ], synth_buffer[ 0 * 64 + bufferPointer ] );
sum -= MUL64( window[ 1 * 64 + windowOffset ], synth_buffer[ 1 * 64 + bufferPointer ] );
sum -= MUL64( window[ 2 * 64 + windowOffset ], synth_buffer[ 2 * 64 + bufferPointer ] );
sum -= MUL64( window[ 3 * 64 + windowOffset ], synth_buffer[ 3 * 64 + bufferPointer ] );
sum -= MUL64( window[ 4 * 64 + windowOffset ], synth_buffer[ 4 * 64 + bufferPointer ] );
sum -= MUL64( window[ 5 * 64 + windowOffset ], synth_buffer[ 5 * 64 + bufferPointer ] );
sum -= MUL64( window[ 6 * 64 + windowOffset ], synth_buffer[ 6 * 64 + bufferPointer ] );
sum -= MUL64( window[ 7 * 64 + windowOffset ], synth_buffer[ 7 * 64 + bufferPointer ] );
return sum;
}
private void OUT_SAMPLE(long sum, byte[] out, int outPointer) {
int sum1 = (int)((sum + (((long)1) << (OUT_SHIFT - 1))) >> OUT_SHIFT);
if ( sum1 < -32768 ) { sum1 = -32768;}
else if ( sum1 > 32767 ) { sum1 = 32767;}
// System.out.println( sum );
out[ outPointer ] = (byte)(sum1 & 0xff);
out[ outPointer + 1 ] = (byte)((sum1 >> 8) & 0xff);
}
private int[] synth_buf_offset = new int[ 2 ];
private int[][] synth_buf = new int[ 2 ][ 512 * 2 ];
private int[] synth_filterTmpBuffer = new int[32];
public int synth_filter( int channel, int nb_channels,
byte[] out, int outPointer,
int[] in, int inPointer ) {
/* MPA_INT *synth_buf, *p;
MPA_INT *w;
int j, offset, v;
long sum;
*/
dct32(synth_filterTmpBuffer, in, inPointer);
if ( Granule.debug ) {
System.out.println( "dct32" );
for ( int i = 0; i < 32; i++ ) {
System.out.print( synth_filterTmpBuffer[ i ] + " " );
}
System.out.println();
}
int offset = synth_buf_offset[channel];
int[] synth_buffer = synth_buf[channel];
for(int j=0;j<32;j++) {
synth_buffer[ j + offset ] = synth_filterTmpBuffer[ j ];
}
/* copy to avoid wrap */
System.arraycopy( synth_buffer, offset, synth_buffer, offset + 512, 32 );
/* I am here */
// System.out.println( "A" );
int windowOffset = 0;
long sum = 0;
int p;
for(int j=0;j<16;j++) {
sum = 0;
p = offset + 16 + j; /* 0-15 */
sum = SUM8(sum, windowOffset, synth_buffer, p);
p = offset + 48 - j; /* 32-47 */
sum = SUB8(sum, windowOffset + 32, synth_buffer, p);
OUT_SAMPLE(sum, out, outPointer);
outPointer += 2 * nb_channels; // CHECKME
windowOffset++;
}
// System.out.println( "B" );
p = offset + 32; /* 48 */
sum = 0;
sum = SUB8(sum, windowOffset + 32, synth_buffer, p);
OUT_SAMPLE(sum, out, outPointer);
outPointer += 2 * nb_channels; // CHECKME
windowOffset++;
// System.out.println( "C" );
for(int j=17;j<32;j++) {
sum = 0;
p = offset + 48 - j; /* 0-15 */
sum = SUB8(sum, windowOffset, synth_buffer, p);
p = offset + 16 + j; /* 32-47 */
sum = SUB8(sum, windowOffset + 32, synth_buffer, p);
OUT_SAMPLE(sum, out, outPointer);
outPointer += 2 * nb_channels; // CHECKME
windowOffset++;
}
offset = (offset - 32) & 511;
synth_buf_offset[channel] = offset;
return outPointer;
}
private static final int[] window = new int[ 512 ];
private static final int FRAC_BITS = 23;
private static final int WFRAC_BITS = 16;
public static final int OUT_SHIFT = WFRAC_BITS + FRAC_BITS - 15;
private static final int MULL( int a, int b ) {
return (int)(((long)a * (long)b) >> FRAC_BITS);
}
static {
mdct_win = new int[ 8 * 36 ];
int i,j;
/* compute mdct windows */
for(i=0;i<36;i++) {
int v;
v = FIXR(Granule.sin(Granule.M_PI * (i + 0.5) / 36.0));
mdct_win[0 * 36 + i] = v;
mdct_win[1 * 36 + i] = v;
mdct_win[3 * 36 + i] = v;
}
for(i=0;i<6;i++) {
mdct_win[1 * 36 + 18 + i] = FIXR(1.0);
mdct_win[1 * 36 + 24 + i] = FIXR(Granule.sin(Granule.M_PI * ((i + 6) + 0.5) / 12.0));
mdct_win[1 * 36 + 30 + i] = FIXR(0.0);
mdct_win[3 * 36 + i] = FIXR(0.0);
mdct_win[3 * 36 + 6 + i] = FIXR(Granule.sin(Granule.M_PI * (i + 0.5) / 12.0));
mdct_win[3 * 36 + 12 + i] = FIXR(1.0);
}
for(i=0;i<12;i++)
mdct_win[2 * 36 + i] = FIXR(Granule.sin(Granule.M_PI * (i + 0.5) / 12.0));
/* NOTE: we do frequency inversion adter the MDCT by changing
the sign of the right window coefs */
for(j=0;j<4;j++) {
for(i=0;i<36;i+=2) {
mdct_win[ (j + 4) * 36 + i ] = mdct_win[j * 36 + i];
mdct_win[ (j + 4) * 36 + i + 1 ] = -mdct_win[j * 36 + i + 1];
}
}
/*
for(j=0;j<8;j++) {
// System.out.println( "win" + j + "=" );
for(i=0;i<36;i++)
System.out.print( "" + mdct_win[j * 36 + i] + ", " );
System.out.println();
}
*/
/* window */
/* max = 18760, max sum over all 16 coefs : 44736 */
int[] mpa_enwindow = Table.getMpaEnTable();
for(i=0;i<257;i++) {
int v;
v = mpa_enwindow[i];
window[i] = v;
if ((i & 63) != 0)
v = -v;
if (i != 0)
window[512 - i] = v;
}
}
public static final int FIXR( double a ) {
return (int)(a * (1 << FRAC_BITS) + 0.5);
}
public static final long MUL64( long a, long b ) {
return a * b;
}
public static int FRAC_RND( long a ) {
return (int)((a + ((1 << FRAC_BITS)/2)) >> FRAC_BITS);
}
}