/* * Java port of ogg demultiplexer. * Copyright (c) 2004 Jonathan Hueber. * * License conditions are the same as OggVorbis. See README. * 1a39e335700bec46ae31a38e2156a898 */ /******************************************************************** * * * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * * * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002 * * by the XIPHOPHORUS Company http://www.xiph.org/ * * * ********************************************************************/ package net.sourceforge.jffmpeg.codecs.audio.vorbis.residue; import net.sourceforge.jffmpeg.codecs.audio.vorbis.CodeBook; import net.sourceforge.jffmpeg.codecs.audio.vorbis.VorbisDecoder; import net.sourceforge.jffmpeg.codecs.audio.vorbis.OggReader; public class Residue0 extends Residue { protected int begin; protected int end; protected int grouping; protected int partitions; protected int groupbook; protected int[] secondstages; protected int[] booklist = new int[ 32 * 8 ]; private static int icount( int v ) { int ret = 0; while( v > 0 ) { ret += v&1; v >>= 1; } return ret; } public void unpack( OggReader oggRead ) { begin = (int)oggRead.getBits( 24 ); end = (int)oggRead.getBits( 24 ); grouping = (int)oggRead.getBits( 24 ) + 1; partitions = (int)oggRead.getBits( 6 ) + 1; groupbook = (int)oggRead.getBits( 8 ); secondstages = new int[ partitions ]; int acc = 0; for ( int i = 0; i < partitions; i++ ) { int cascade = (int)oggRead.getBits( 3 ); if ( oggRead.getBits(1) == 1 ) { cascade |= ((int)oggRead.getBits( 5 )) << 3; } secondstages[i] = cascade; acc += icount( cascade ); } for ( int i = 0; i < acc; i++ ) { booklist[i] = (int)oggRead.getBits(8); } } protected int partvals; protected int stages; protected long[][] decodemap; protected CodeBook[][] partbooks; protected CodeBook phrasebook; public void look( VorbisDecoder vorbis ) { int parts = partitions; partbooks = new CodeBook[ parts ][]; phrasebook = vorbis.getCodeBook( groupbook ); int dim = phrasebook.getDim(); // System.out.println( "residue_look" ); int maxstage=0; int acc = 0; for ( int j = 0; j < parts; j++ ) { int stages = ilog(secondstages[j]); if( stages != 0 ) { if( stages > maxstage ) maxstage = stages; partbooks[ j ] = new CodeBook[ stages ]; for(int k = 0; k < stages; k++ ) { if ( (secondstages[j] & (1<<k)) != 0 ) { partbooks[j][k]= vorbis.getCodeBook( booklist[acc++] ); } } } } partvals = (int)Math.rint( Math.pow( (double)parts, (double)dim ) ); decodemap = new long[ partvals ][ dim ]; stages = maxstage; for ( int j = 0; j < partvals; j++ ) { long val=j; long mult= partvals / parts; for( int k = 0; k < dim; k++ ) { long deco = val / mult; val -= deco * mult; mult /= parts; decodemap[j][k] = deco; //System.out.println( "decodemap[" + j + "][" + k + "]=" + deco ); } } } private static final int ilog( int v ) { int ret=0; while( v > 0 ) { ret++; v >>= 1; } return ret; } // public abstract void forward(); public void inverse( OggReader oggRead, float[][] in, int[] nonZero, int channels ) { // System.out.println( "Residue0 inverse" ); int used = 0; for ( int i = 0; i < channels; i++ ) { if ( nonZero[ i ] != 0 ) { in[ used++ ] = in[ i ]; } } if ( used > 0 ) { _01inverse( oggRead, in, used ); } } protected void _01inverse( OggReader oggRead, float[][] in, int ch ) { /* move all this setup out later */ int samples_per_partition = grouping; int partitions_per_word = phrasebook.getDim(); int n = end - begin; int partvals = n/samples_per_partition; int partwords = (partvals+partitions_per_word-1)/partitions_per_word; long[][][] partword = new long[ ch ][ partwords ][]; for( int s = 0; s < stages; s++ ) { /* each loop decodes on partition codeword containing partitions_pre_word partitions */ int i = 0; int l = 0; for ( ; i < partvals; l++ ) { if( s == 0 ) { /* fetch the partition word for each channel */ for ( int j = 0; j < ch; j++ ) { int temp = phrasebook.decode( oggRead ); partword[j][l] = decodemap[temp]; } } /* now we decode residual values for the partitions */ for( int k = 0; k < partitions_per_word && i < partvals; k++, i++ ) { for( int j = 0; j < ch; j++ ) { long offset = begin + i * samples_per_partition; int pw = (int)partword[j][l][k]; if ( (secondstages[ pw ] & (1<<s)) != 0 ) { CodeBook stagebook=partbooks[pw][s]; if ( stagebook != null ) { decodepart( oggRead, stagebook, in[j], (int)offset, samples_per_partition); } } } } } } } /** * Overrriden in Residue 1 */ protected void decodepart( OggReader oggRead, CodeBook b, float[] in, int offset, int spp ) { b.decodevs_add( in, offset, oggRead, spp ); } }