Converter class implements the conversion of
+ * an MPEG audio file to a .WAV file. To convert an MPEG audio stream,
+ * just create an instance of this class and call the convert()
+ * method, passing in the names of the input and output files. You can
+ * pass in optional ProgressListener and
+ * Decoder.Params objects also to customize the conversion.
+ *
+ * @author MDM 12/12/99
+ * @since 0.0.7
+ */
+public class Converter
+{
+ /**
+ * Creates a new converter instance.
+ */
+ public Converter()
+ {
+ }
+
+ public synchronized void convert(String sourceName, String destName)
+ throws JavaLayerException
+ {
+ convert(sourceName, destName, null, null);
+ }
+
+ public synchronized void convert(String sourceName, String destName,
+ ProgressListener progressListener)
+ throws JavaLayerException
+ {
+ convert(sourceName, destName, progressListener, null);
+ }
+
+
+ public void convert(String sourceName, String destName,
+ ProgressListener progressListener, Decoder.Params decoderParams)
+ throws JavaLayerException
+ {
+ if (destName.length()==0)
+ destName = null;
+ try {
+ InputStream in = openInput(sourceName);
+ convert(in, destName, progressListener, decoderParams);
+ in.close();
+ } catch(IOException ioe) {
+ throw new JavaLayerException(ioe.getLocalizedMessage(), ioe);
+ }
+ }
+
+ public synchronized void convert(InputStream sourceStream, String destName,
+ ProgressListener progressListener, Decoder.Params decoderParams)
+ throws JavaLayerException
+ {
+ if (progressListener==null)
+ progressListener = PrintWriterProgressListener.newStdOut(
+ PrintWriterProgressListener.NO_DETAIL);
+ try {
+ if (!(sourceStream instanceof BufferedInputStream))
+ sourceStream = new BufferedInputStream(sourceStream);
+ int frameCount = -1;
+ if (sourceStream.markSupported()) {
+ sourceStream.mark(-1);
+ frameCount = countFrames(sourceStream);
+ sourceStream.reset();
+ }
+ progressListener.converterUpdate(ProgressListener.UPDATE_FRAME_COUNT, frameCount, 0);
+
+
+ Obuffer output = null;
+ Decoder decoder = new Decoder(decoderParams);
+ Bitstream stream = new Bitstream(sourceStream);
+
+ if (frameCount==-1)
+ frameCount = Integer.MAX_VALUE;
+
+ int frame = 0;
+ long startTime = System.currentTimeMillis();
+
+ try
+ {
+ for (; frameThrowable instance that
+ * was thrown.
+ *
+ * @return true to continue processing, or false
+ * to abort conversion.
+ *
+ * If this method returns false, the exception
+ * is propagated to the caller of the convert() method. If
+ * true is returned, the exception is silently
+ * ignored and the converter moves onto the next frame.
+ */
+ public boolean converterException(Throwable t);
+
+ }
+
+
+ /**
+ * Implementation of ProgressListener that writes
+ * notification text to a PrintWriter.
+ */
+ // REVIEW: i18n of text and order required.
+ static public class PrintWriterProgressListener implements ProgressListener
+ {
+ static public final int NO_DETAIL = 0;
+
+ /**
+ * Level of detail typically expected of expert
+ * users.
+ */
+ static public final int EXPERT_DETAIL = 1;
+
+ /**
+ * Verbose detail.
+ */
+ static public final int VERBOSE_DETAIL = 2;
+
+ /**
+ * Debug detail. All frame read notifications are shown.
+ */
+ static public final int DEBUG_DETAIL = 7;
+
+ static public final int MAX_DETAIL = 10;
+
+ private PrintWriter pw;
+
+ private int detailLevel;
+
+ static public PrintWriterProgressListener newStdOut(int detail)
+ {
+ return new PrintWriterProgressListener(
+ new PrintWriter(System.out, true), detail);
+ }
+
+ public PrintWriterProgressListener(PrintWriter writer, int detailLevel)
+ {
+ this.pw = writer;
+ this.detailLevel = detailLevel;
+ }
+
+
+ public boolean isDetail(int detail)
+ {
+ return (this.detailLevel >= detail);
+ }
+
+ public void converterUpdate(int updateID, int param1, int param2)
+ {
+ if (isDetail(VERBOSE_DETAIL))
+ {
+ switch (updateID)
+ {
+ case UPDATE_CONVERT_COMPLETE:
+ // catch divide by zero errors.
+ if (param2==0)
+ param2 = 1;
+
+ pw.println();
+ pw.println("Converted "+param2+" frames in "+param1+" ms ("+
+ (param1/param2)+" ms per frame.)");
+ }
+ }
+ }
+
+ public void parsedFrame(int frameNo, Header header)
+ {
+ if ((frameNo==0) && isDetail(VERBOSE_DETAIL))
+ {
+ String headerString = header.toString();
+ pw.println("File is a "+headerString);
+ }
+ else if (isDetail(MAX_DETAIL))
+ {
+ String headerString = header.toString();
+ pw.println("Prased frame "+frameNo+": "+headerString);
+ }
+ }
+
+ public void readFrame(int frameNo, Header header)
+ {
+ if ((frameNo==0) && isDetail(VERBOSE_DETAIL))
+ {
+ String headerString = header.toString();
+ pw.println("File is a "+headerString);
+ }
+ else if (isDetail(MAX_DETAIL))
+ {
+ String headerString = header.toString();
+ pw.println("Read frame "+frameNo+": "+headerString);
+ }
+ }
+
+ public void decodedFrame(int frameNo, Header header, Obuffer o)
+ {
+ if (isDetail(MAX_DETAIL))
+ {
+ String headerString = header.toString();
+ pw.println("Decoded frame "+frameNo+": "+headerString);
+ pw.println("Output: "+o);
+ }
+ else if (isDetail(VERBOSE_DETAIL))
+ {
+ if (frameNo==0)
+ {
+ pw.print("Converting.");
+ pw.flush();
+ }
+
+ if ((frameNo % 10)==0)
+ {
+ pw.print('.');
+ pw.flush();
+ }
+ }
+ }
+
+ public boolean converterException(Throwable t)
+ {
+ if (this.detailLevel>NO_DETAIL)
+ {
+ t.printStackTrace(pw);
+ pw.flush();
+ }
+ return false;
+ }
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/src/javazoom/jl/converter/RiffFile.java b/src/javazoom/jl/converter/RiffFile.java
new file mode 100644
index 00000000000..7fb93948c62
--- /dev/null
+++ b/src/javazoom/jl/converter/RiffFile.java
@@ -0,0 +1,495 @@
+/*
+ * 11/19/04 1.0 moved to LGPL.
+ * 02/23/99 JavaConversion by E.B
+ * Don Cross, April 1993.
+ * RIFF file format classes.
+ * See Chapter 8 of "Multimedia Programmer's Reference" in
+ * the Microsoft Windows SDK.
+ *
+ *-----------------------------------------------------------------------
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *----------------------------------------------------------------------
+ */
+
+package javazoom.jl.converter;
+
+import java.io.IOException;
+import java.io.RandomAccessFile;
+
+
+/**
+ * Class to manage RIFF files
+ */
+public class RiffFile
+{
+ class RiffChunkHeader
+ {
+ public int ckID = 0; // Four-character chunk ID
+ public int ckSize = 0; // Length of data in chunk
+ public RiffChunkHeader()
+ {}
+ }
+
+
+ // DDCRET
+ public static final int DDC_SUCCESS = 0; // The operation succeded
+ public static final int DDC_FAILURE = 1; // The operation failed for unspecified reasons
+ public static final int DDC_OUT_OF_MEMORY = 2; // Operation failed due to running out of memory
+ public static final int DDC_FILE_ERROR = 3; // Operation encountered file I/O error
+ public static final int DDC_INVALID_CALL = 4; // Operation was called with invalid parameters
+ public static final int DDC_USER_ABORT = 5; // Operation was aborted by the user
+ public static final int DDC_INVALID_FILE = 6; // File format does not match
+
+ // RiffFileMode
+ public static final int RFM_UNKNOWN = 0; // undefined type (can use to mean "N/A" or "not open")
+ public static final int RFM_WRITE = 1; // open for write
+ public static final int RFM_READ = 2; // open for read
+
+ private RiffChunkHeader riff_header; // header for whole file
+ protected int fmode; // current file I/O mode
+ protected RandomAccessFile file; // I/O stream to use
+
+ /**
+ * Dummy Constructor
+ */
+ public RiffFile()
+ {
+ file = null;
+ fmode = RFM_UNKNOWN;
+ riff_header = new RiffChunkHeader();
+
+ riff_header.ckID = FourCC("RIFF");
+ riff_header.ckSize = 0;
+ }
+
+ /**
+ * Return File Mode.
+ */
+ public int CurrentFileMode()
+ {return fmode;}
+
+ /**
+ * Open a RIFF file.
+ */
+ public int Open(String Filename, int NewMode)
+ {
+ int retcode = DDC_SUCCESS;
+
+ if ( fmode != RFM_UNKNOWN )
+ {
+ retcode = Close();
+ }
+
+ if ( retcode == DDC_SUCCESS )
+ {
+ switch ( NewMode )
+ {
+ case RFM_WRITE:
+ try
+ {
+ file = new RandomAccessFile(Filename,"rw");
+
+ try
+ {
+ // Write the RIFF header...
+ // We will have to come back later and patch it!
+ byte[] br = new byte[8];
+ br[0] = (byte) ((riff_header.ckID >>> 24) & 0x000000FF);
+ br[1] = (byte) ((riff_header.ckID >>> 16) & 0x000000FF);
+ br[2] = (byte) ((riff_header.ckID >>> 8) & 0x000000FF);
+ br[3] = (byte) (riff_header.ckID & 0x000000FF);
+
+ byte br4 = (byte) ((riff_header.ckSize >>> 24)& 0x000000FF);
+ byte br5 = (byte) ((riff_header.ckSize >>> 16)& 0x000000FF);
+ byte br6 = (byte) ((riff_header.ckSize >>> 8)& 0x000000FF);
+ byte br7 = (byte) (riff_header.ckSize & 0x000000FF);
+
+ br[4] = br7;
+ br[5] = br6;
+ br[6] = br5;
+ br[7] = br4;
+
+ file.write(br,0,8);
+ fmode = RFM_WRITE;
+ } catch (IOException ioe)
+ {
+ file.close();
+ fmode = RFM_UNKNOWN;
+ }
+ } catch (IOException ioe)
+ {
+ fmode = RFM_UNKNOWN;
+ retcode = DDC_FILE_ERROR;
+ }
+ break;
+
+ case RFM_READ:
+ try
+ {
+ file = new RandomAccessFile(Filename,"r");
+ try
+ {
+ // Try to read the RIFF header...
+ byte[] br = new byte[8];
+ file.read(br,0,8);
+ fmode = RFM_READ;
+ riff_header.ckID = ((br[0]<<24)& 0xFF000000) | ((br[1]<<16)&0x00FF0000) | ((br[2]<<8)&0x0000FF00) | (br[3]&0x000000FF);
+ riff_header.ckSize = ((br[4]<<24)& 0xFF000000) | ((br[5]<<16)&0x00FF0000) | ((br[6]<<8)&0x0000FF00) | (br[7]&0x000000FF);
+ } catch (IOException ioe)
+ {
+ file.close();
+ fmode = RFM_UNKNOWN;
+ }
+ } catch (IOException ioe)
+ {
+ fmode = RFM_UNKNOWN;
+ retcode = DDC_FILE_ERROR;
+ }
+ break;
+ default:
+ retcode = DDC_INVALID_CALL;
+ }
+ }
+ return retcode;
+ }
+
+ /**
+ * Write NumBytes data.
+ */
+ public int Write(byte[] Data, int NumBytes )
+ {
+ if ( fmode != RFM_WRITE )
+ {
+ return DDC_INVALID_CALL;
+ }
+ try
+ {
+ file.write(Data,0,NumBytes);
+ fmode = RFM_WRITE;
+ }
+ catch (IOException ioe)
+ {
+ return DDC_FILE_ERROR;
+ }
+ riff_header.ckSize += NumBytes;
+ return DDC_SUCCESS;
+ }
+
+
+
+ /**
+ * Write NumBytes data.
+ */
+ public int Write(short[] Data, int NumBytes )
+ {
+ byte[] theData = new byte[NumBytes];
+ int yc = 0;
+ for (int y = 0;yjlc class presents the JavaLayer
+ * Conversion functionality as a command-line program.
+ *
+ * @since 0.0.7
+ */
+public class jlc
+{
+
+ static public void main(String args[])
+ {
+ String[] argv;
+ long start = System.currentTimeMillis();
+ int argc = args.length + 1;
+ argv = new String[argc];
+ argv[0] = "jlc";
+ for(int i=0;i+ * The implementation stores single bits as a word in the buffer. If + * a bit is set, the corresponding word in the buffer will be non-zero. + * If a bit is clear, the corresponding word is zero. Although this + * may seem waseful, this can be a factor of two quicker than + * packing 8 bits to a byte and extracting. + *
+ */
+
+// REVIEW: there is no range checking, so buffer underflow or overflow
+// can silently occur.
+final class BitReserve
+{
+ /**
+ * Size of the internal buffer to store the reserved bits.
+ * Must be a power of 2. And x8, as each bit is stored as a single
+ * entry.
+ */
+ private static final int BUFSIZE = 4096*8;
+
+ /**
+ * Mask that can be used to quickly implement the
+ * modulus operation on BUFSIZE.
+ */
+ private static final int BUFSIZE_MASK = BUFSIZE-1;
+
+ private int offset, totbit, buf_byte_idx;
+ private final int[] buf = new int[BUFSIZE];
+ private int buf_bit_idx;
+
+ BitReserve()
+ {
+
+ offset = 0;
+ totbit = 0;
+ buf_byte_idx = 0;
+ }
+
+
+ /**
+ * Return totbit Field.
+ */
+ public int hsstell()
+ {
+ return(totbit);
+ }
+
+ /**
+ * Read a number bits from the bit stream.
+ * @param N the number of
+ */
+ public int hgetbits(int N)
+ {
+ totbit += N;
+
+ int val = 0;
+
+ int pos = buf_byte_idx;
+ if (pos+N < BUFSIZE)
+ {
+ while (N-- > 0)
+ {
+ val <<= 1;
+ val |= ((buf[pos++]!=0) ? 1 : 0);
+ }
+ }
+ else
+ {
+ while (N-- > 0)
+ {
+ val <<= 1;
+ val |= ((buf[pos]!=0) ? 1 : 0);
+ pos = (pos+1) & BUFSIZE_MASK;
+ }
+ }
+ buf_byte_idx = pos;
+ return val;
+ }
+
+
+
+ /**
+ * Read 1 bit from the bit stream.
+ */
+/*
+ public int hget1bit_old()
+ {
+ int val;
+ totbit++;
+ if (buf_bit_idx == 0)
+ {
+ buf_bit_idx = 8;
+ buf_byte_idx++;
+ }
+ // BUFSIZE = 4096 = 2^12, so
+ // buf_byte_idx%BUFSIZE == buf_byte_idx & 0xfff
+ val = buf[buf_byte_idx & BUFSIZE_MASK] & putmask[buf_bit_idx];
+ buf_bit_idx--;
+ val = val >>> buf_bit_idx;
+ return val;
+ }
+ */
+ /**
+ * Returns next bit from reserve.
+ * @returns 0 if next bit is reset, or 1 if next bit is set.
+ */
+ public int hget1bit()
+ {
+ totbit++;
+ int val = buf[buf_byte_idx];
+ buf_byte_idx = (buf_byte_idx+1) & BUFSIZE_MASK;
+ return val;
+ }
+
+ /**
+ * Retrieves bits from the reserve.
+ */
+/*
+ public int readBits(int[] out, int len)
+ {
+ if (buf_bit_idx == 0)
+ {
+ buf_bit_idx = 8;
+ buf_byte_idx++;
+ current = buf[buf_byte_idx & BUFSIZE_MASK];
+ }
+
+
+
+ // save total number of bits returned
+ len = buf_bit_idx;
+ buf_bit_idx = 0;
+
+ int b = current;
+ int count = len-1;
+
+ while (count >= 0)
+ {
+ out[count--] = (b & 0x1);
+ b >>>= 1;
+ }
+
+ totbit += len;
+ return len;
+ }
+ */
+
+ /**
+ * Write 8 bits into the bit stream.
+ */
+ public void hputbuf(int val)
+ {
+ int ofs = offset;
+ buf[ofs++] = val & 0x80;
+ buf[ofs++] = val & 0x40;
+ buf[ofs++] = val & 0x20;
+ buf[ofs++] = val & 0x10;
+ buf[ofs++] = val & 0x08;
+ buf[ofs++] = val & 0x04;
+ buf[ofs++] = val & 0x02;
+ buf[ofs++] = val & 0x01;
+
+ if (ofs==BUFSIZE)
+ offset = 0;
+ else
+ offset = ofs;
+
+ }
+
+ /**
+ * Rewind N bits in Stream.
+ */
+ public void rewindNbits(int N)
+ {
+ totbit -= N;
+ buf_byte_idx -= N;
+ if (buf_byte_idx<0)
+ buf_byte_idx += BUFSIZE;
+ }
+
+ /**
+ * Rewind N bytes in Stream.
+ */
+ public void rewindNbytes(int N)
+ {
+ int bits = (N << 3);
+ totbit -= bits;
+ buf_byte_idx -= bits;
+ if (buf_byte_idx<0)
+ buf_byte_idx += BUFSIZE;
+ }
+}
diff --git a/src/javazoom/jl/decoder/Bitstream.java b/src/javazoom/jl/decoder/Bitstream.java
new file mode 100644
index 00000000000..d91ea26f797
--- /dev/null
+++ b/src/javazoom/jl/decoder/Bitstream.java
@@ -0,0 +1,655 @@
+/*
+ * 11/19/04 1.0 moved to LGPL.
+ *
+ * 11/17/04 Uncomplete frames discarded. E.B, javalayer@javazoom.net
+ *
+ * 12/05/03 ID3v2 tag returned. E.B, javalayer@javazoom.net
+ *
+ * 12/12/99 Based on Ibitstream. Exceptions thrown on errors,
+ * Temporary removed seek functionality. mdm@techie.com
+ *
+ * 02/12/99 : Java Conversion by E.B , javalayer@javazoom.net
+ *
+ * 04/14/97 : Added function prototypes for new syncing and seeking
+ * mechanisms. Also made this file portable. Changes made by Jeff Tsay
+ *
+ * @(#) ibitstream.h 1.5, last edit: 6/15/94 16:55:34
+ * @(#) Copyright (C) 1993, 1994 Tobias Bading (bading@cs.tu-berlin.de)
+ * @(#) Berlin University of Technology
+ *-----------------------------------------------------------------------
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *----------------------------------------------------------------------
+ */
+
+package javazoom.jl.decoder;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PushbackInputStream;
+
+
+/**
+ * The
+ * The exception provides details of the exception condition
+ * in two ways:
+ * Bistream class is responsible for parsing
+ * an MPEG audio bitstream.
+ *
+ * REVIEW: much of the parsing currently occurs in the
+ * various decoders. This should be moved into this class and associated
+ * inner classes.
+ */
+public final class Bitstream implements BitstreamErrors
+{
+ /**
+ * Synchronization control constant for the initial
+ * synchronization to the start of a frame.
+ */
+ static byte INITIAL_SYNC = 0;
+
+ /**
+ * Synchronization control constant for non-initial frame
+ * synchronizations.
+ */
+ static byte STRICT_SYNC = 1;
+
+ // max. 1730 bytes per frame: 144 * 384kbit/s / 32000 Hz + 2 Bytes CRC
+ /**
+ * Maximum size of the frame buffer.
+ */
+ private static final int BUFFER_INT_SIZE = 433;
+
+ /**
+ * The frame buffer that holds the data for the current frame.
+ */
+ private final int[] framebuffer = new int[BUFFER_INT_SIZE];
+
+ /**
+ * Number of valid bytes in the frame buffer.
+ */
+ private int framesize;
+
+ /**
+ * The bytes read from the stream.
+ */
+ private byte[] frame_bytes = new byte[BUFFER_INT_SIZE*4];
+
+ /**
+ * Index into framebuffer where the next bits are
+ * retrieved.
+ */
+ private int wordpointer;
+
+ /**
+ * Number (0-31, from MSB to LSB) of next bit for get_bits()
+ */
+ private int bitindex;
+
+ /**
+ * The current specified syncword
+ */
+ private int syncword;
+
+ /**
+ * Audio header position in stream.
+ */
+ private int header_pos = 0;
+
+ /**
+ *
+ */
+ private boolean single_ch_mode;
+ //private int current_frame_number;
+ //private int last_frame_number;
+
+ private final int bitmask[] = {0, // dummy
+ 0x00000001, 0x00000003, 0x00000007, 0x0000000F,
+ 0x0000001F, 0x0000003F, 0x0000007F, 0x000000FF,
+ 0x000001FF, 0x000003FF, 0x000007FF, 0x00000FFF,
+ 0x00001FFF, 0x00003FFF, 0x00007FFF, 0x0000FFFF,
+ 0x0001FFFF };
+
+ private final PushbackInputStream source;
+
+ private final Header header = new Header();
+
+ private final byte syncbuf[] = new byte[4];
+
+ private Crc16[] crc = new Crc16[1];
+
+ private byte[] rawid3v2 = null;
+
+ private boolean firstframe = true;
+
+
+ /**
+ * Construct a IBitstream that reads data from a
+ * given InputStream.
+ *
+ * @param in The InputStream to read from.
+ */
+ public Bitstream(InputStream in)
+ {
+ if (in==null) throw new NullPointerException("in");
+ in = new BufferedInputStream(in);
+ loadID3v2(in);
+ firstframe = true;
+ //source = new PushbackInputStream(in, 1024);
+ source = new PushbackInputStream(in, BUFFER_INT_SIZE*4);
+
+ closeFrame();
+ //current_frame_number = -1;
+ //last_frame_number = -1;
+ }
+
+ /**
+ * Return position of the first audio header.
+ * @return size of ID3v2 tag frames.
+ */
+ public int header_pos()
+ {
+ return header_pos;
+ }
+
+ /**
+ * Load ID3v2 frames.
+ * @param in MP3 InputStream.
+ * @author JavaZOOM
+ */
+ private void loadID3v2(InputStream in)
+ {
+ int size = -1;
+ try
+ {
+ // Read ID3v2 header (10 bytes).
+ in.mark(10);
+ size = readID3v2Header(in);
+ header_pos = size;
+ }
+ catch (IOException e)
+ {}
+ finally
+ {
+ try
+ {
+ // Unread ID3v2 header (10 bytes).
+ in.reset();
+ }
+ catch (IOException e)
+ {}
+ }
+ // Load ID3v2 tags.
+ try
+ {
+ if (size > 0)
+ {
+ rawid3v2 = new byte[size];
+ in.read(rawid3v2,0,rawid3v2.length);
+ }
+ }
+ catch (IOException e)
+ {}
+ }
+
+ /**
+ * Parse ID3v2 tag header to find out size of ID3v2 frames.
+ * @param in MP3 InputStream
+ * @return size of ID3v2 frames + header
+ * @throws IOException
+ * @author JavaZOOM
+ */
+ private int readID3v2Header(InputStream in) throws IOException
+ {
+ byte[] id3header = new byte[4];
+ int size = -10;
+ in.read(id3header,0,3);
+ // Look for ID3v2
+ if ( (id3header[0]=='I') && (id3header[1]=='D') && (id3header[2]=='3'))
+ {
+ in.read(id3header,0,3);
+ int majorVersion = id3header[0];
+ int revision = id3header[1];
+ in.read(id3header,0,4);
+ size = (int) (id3header[0] << 21) + (id3header[1] << 14) + (id3header[2] << 7) + (id3header[3]);
+ }
+ return (size+10);
+ }
+
+ /**
+ * Return raw ID3v2 frames + header.
+ * @return ID3v2 InputStream or null if ID3v2 frames are not available.
+ */
+ public InputStream getRawID3v2()
+ {
+ if (rawid3v2 == null) return null;
+ else
+ {
+ ByteArrayInputStream bain = new ByteArrayInputStream(rawid3v2);
+ return bain;
+ }
+ }
+
+ /**
+ * Close the Bitstream.
+ * @throws BitstreamException
+ */
+ public void close() throws BitstreamException
+ {
+ try
+ {
+ source.close();
+ }
+ catch (IOException ex)
+ {
+ throw newBitstreamException(STREAM_ERROR, ex);
+ }
+ }
+
+ /**
+ * Reads and parses the next frame from the input source.
+ * @return the Header describing details of the frame read,
+ * or null if the end of the stream has been reached.
+ */
+ public Header readFrame() throws BitstreamException
+ {
+ Header result = null;
+ try
+ {
+ result = readNextFrame();
+ // E.B, Parse VBR (if any) first frame.
+ if (firstframe == true)
+ {
+ result.parseVBR(frame_bytes);
+ firstframe = false;
+ }
+ }
+ catch (BitstreamException ex)
+ {
+ if ((ex.getErrorCode()==INVALIDFRAME))
+ {
+ // Try to skip this frame.
+ //System.out.println("INVALIDFRAME");
+ try
+ {
+ closeFrame();
+ result = readNextFrame();
+ }
+ catch (BitstreamException e)
+ {
+ if ((e.getErrorCode()!=STREAM_EOF))
+ {
+ // wrap original exception so stack trace is maintained.
+ throw newBitstreamException(e.getErrorCode(), e);
+ }
+ }
+ }
+ else if ((ex.getErrorCode()!=STREAM_EOF))
+ {
+ // wrap original exception so stack trace is maintained.
+ throw newBitstreamException(ex.getErrorCode(), ex);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Read next MP3 frame.
+ * @return MP3 frame header.
+ * @throws BitstreamException
+ */
+ private Header readNextFrame() throws BitstreamException
+ {
+ if (framesize == -1)
+ {
+ nextFrame();
+ }
+ return header;
+ }
+
+
+ /**
+ * Read next MP3 frame.
+ * @throws BitstreamException
+ */
+ private void nextFrame() throws BitstreamException
+ {
+ // entire frame is read by the header class.
+ header.read_header(this, crc);
+ }
+
+ /**
+ * Unreads the bytes read from the frame.
+ * @throws BitstreamException
+ */
+ // REVIEW: add new error codes for this.
+ public void unreadFrame() throws BitstreamException
+ {
+ if (wordpointer==-1 && bitindex==-1 && (framesize>0))
+ {
+ try
+ {
+ source.unread(frame_bytes, 0, framesize);
+ }
+ catch (IOException ex)
+ {
+ throw newBitstreamException(STREAM_ERROR);
+ }
+ }
+ }
+
+ /**
+ * Close MP3 frame.
+ */
+ public void closeFrame()
+ {
+ framesize = -1;
+ wordpointer = -1;
+ bitindex = -1;
+ }
+
+ /**
+ * Determines if the next 4 bytes of the stream represent a
+ * frame header.
+ */
+ public boolean isSyncCurrentPosition(int syncmode) throws BitstreamException
+ {
+ int read = readBytes(syncbuf, 0, 4);
+ int headerstring = ((syncbuf[0] << 24) & 0xFF000000) | ((syncbuf[1] << 16) & 0x00FF0000) | ((syncbuf[2] << 8) & 0x0000FF00) | ((syncbuf[3] << 0) & 0x000000FF);
+
+ try
+ {
+ source.unread(syncbuf, 0, read);
+ }
+ catch (IOException ex)
+ {
+ }
+
+ boolean sync = false;
+ switch (read)
+ {
+ case 0:
+ sync = true;
+ break;
+ case 4:
+ sync = isSyncMark(headerstring, syncmode, syncword);
+ break;
+ }
+
+ return sync;
+ }
+
+
+ // REVIEW: this class should provide inner classes to
+ // parse the frame contents. Eventually, readBits will
+ // be removed.
+ public int readBits(int n)
+ {
+ return get_bits(n);
+ }
+
+ public int readCheckedBits(int n)
+ {
+ // REVIEW: implement CRC check.
+ return get_bits(n);
+ }
+
+ protected BitstreamException newBitstreamException(int errorcode)
+ {
+ return new BitstreamException(errorcode, null);
+ }
+ protected BitstreamException newBitstreamException(int errorcode, Throwable throwable)
+ {
+ return new BitstreamException(errorcode, throwable);
+ }
+
+ /**
+ * Get next 32 bits from bitstream.
+ * They are stored in the headerstring.
+ * syncmod allows Synchro flag ID
+ * The returned value is False at the end of stream.
+ */
+
+ int syncHeader(byte syncmode) throws BitstreamException
+ {
+ boolean sync;
+ int headerstring;
+ // read additional 2 bytes
+ int bytesRead = readBytes(syncbuf, 0, 3);
+
+ if (bytesRead!=3) throw newBitstreamException(STREAM_EOF, null);
+
+ headerstring = ((syncbuf[0] << 16) & 0x00FF0000) | ((syncbuf[1] << 8) & 0x0000FF00) | ((syncbuf[2] << 0) & 0x000000FF);
+
+ do
+ {
+ headerstring <<= 8;
+
+ if (readBytes(syncbuf, 3, 1)!=1)
+ throw newBitstreamException(STREAM_EOF, null);
+
+ headerstring |= (syncbuf[3] & 0x000000FF);
+
+ sync = isSyncMark(headerstring, syncmode, syncword);
+ }
+ while (!sync);
+
+ //current_frame_number++;
+ //if (last_frame_number < current_frame_number) last_frame_number = current_frame_number;
+
+ return headerstring;
+ }
+
+ public boolean isSyncMark(int headerstring, int syncmode, int word)
+ {
+ boolean sync = false;
+
+ if (syncmode == INITIAL_SYNC)
+ {
+ //sync = ((headerstring & 0xFFF00000) == 0xFFF00000);
+ sync = ((headerstring & 0xFFE00000) == 0xFFE00000); // SZD: MPEG 2.5
+ }
+ else
+ {
+ sync = ((headerstring & 0xFFF80C00) == word) &&
+ (((headerstring & 0x000000C0) == 0x000000C0) == single_ch_mode);
+ }
+
+ // filter out invalid sample rate
+ if (sync)
+ sync = (((headerstring >>> 10) & 3)!=3);
+ // filter out invalid layer
+ if (sync)
+ sync = (((headerstring >>> 17) & 3)!=0);
+ // filter out invalid version
+ if (sync)
+ sync = (((headerstring >>> 19) & 3)!=1);
+
+ return sync;
+ }
+
+ /**
+ * Reads the data for the next frame. The frame is not parsed
+ * until parse frame is called.
+ */
+ int read_frame_data(int bytesize) throws BitstreamException
+ {
+ int numread = 0;
+ numread = readFully(frame_bytes, 0, bytesize);
+ framesize = bytesize;
+ wordpointer = -1;
+ bitindex = -1;
+ return numread;
+ }
+
+ /**
+ * Parses the data previously read with read_frame_data().
+ */
+ void parse_frame() throws BitstreamException
+ {
+ // Convert Bytes read to int
+ int b=0;
+ byte[] byteread = frame_bytes;
+ int bytesize = framesize;
+
+ // Check ID3v1 TAG (True only if last frame).
+ //for (int t=0;t<(byteread.length)-2;t++)
+ //{
+ // if ((byteread[t]=='T') && (byteread[t+1]=='A') && (byteread[t+2]=='G'))
+ // {
+ // System.out.println("ID3v1 detected at offset "+t);
+ // throw newBitstreamException(INVALIDFRAME, null);
+ // }
+ //}
+
+ for (int k=0;kBistreamExceptions.
+ *
+ * @see BitstreamException
+ *
+ * @author MDM 12/12/99
+ * @since 0.0.6
+ */
+
+public interface BitstreamErrors extends JavaLayerErrors
+{
+
+ /**
+ * An undeterminable error occurred.
+ */
+ static public final int UNKNOWN_ERROR = BITSTREAM_ERROR + 0;
+
+ /**
+ * The header describes an unknown sample rate.
+ */
+ static public final int UNKNOWN_SAMPLE_RATE = BITSTREAM_ERROR + 1;
+
+ /**
+ * A problem occurred reading from the stream.
+ */
+ static public final int STREAM_ERROR = BITSTREAM_ERROR + 2;
+
+ /**
+ * The end of the stream was reached prematurely.
+ */
+ static public final int UNEXPECTED_EOF = BITSTREAM_ERROR + 3;
+
+ /**
+ * The end of the stream was reached.
+ */
+ static public final int STREAM_EOF = BITSTREAM_ERROR + 4;
+
+ /**
+ * Frame data are missing.
+ */
+ static public final int INVALIDFRAME = BITSTREAM_ERROR + 5;
+
+ /**
+ *
+ */
+ static public final int BITSTREAM_LAST = 0x1ff;
+
+}
diff --git a/src/javazoom/jl/decoder/BitstreamException.java b/src/javazoom/jl/decoder/BitstreamException.java
new file mode 100644
index 00000000000..e4afb1a1ff4
--- /dev/null
+++ b/src/javazoom/jl/decoder/BitstreamException.java
@@ -0,0 +1,71 @@
+/*
+ * 11/19/04 1.0 moved to LGPL.
+ * 12/12/99 Initial version. mdm@techie.com
+ *-----------------------------------------------------------------------
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *----------------------------------------------------------------------
+ */
+
+package javazoom.jl.decoder;
+
+/**
+ * Instances of BitstreamException are thrown
+ * when operations on a Bitstream fail.
+ * Throwable instance, if any, that was thrown
+ * indicating that an exceptional condition has occurred.
+ *
Decoder class encapsulates the details of
+ * decoding an MPEG audio frame.
+ *
+ * @author MDM
+ * @version 0.0.7 12/12/99
+ * @since 0.0.5
+ */
+public class Decoder implements DecoderErrors
+{
+ static private final Params DEFAULT_PARAMS = new Params();
+
+ /**
+ * The Bistream from which the MPEG audio frames are read.
+ */
+ //private Bitstream stream;
+
+ /**
+ * The Obuffer instance that will receive the decoded
+ * PCM samples.
+ */
+ private Obuffer output;
+
+ /**
+ * Synthesis filter for the left channel.
+ */
+ private SynthesisFilter filter1;
+
+ /**
+ * Sythesis filter for the right channel.
+ */
+ private SynthesisFilter filter2;
+
+ /**
+ * The decoder used to decode layer III frames.
+ */
+ private LayerIIIDecoder l3decoder;
+ private LayerIIDecoder l2decoder;
+ private LayerIDecoder l1decoder;
+
+ private int outputFrequency;
+ private int outputChannels;
+
+ private Equalizer equalizer = new Equalizer();
+
+ private Params params;
+
+ private boolean initialized;
+
+
+ /**
+ * Creates a new Decoder instance with default
+ * parameters.
+ */
+
+ public Decoder()
+ {
+ this(null);
+ }
+
+ /**
+ * Creates a new Decoder instance with default
+ * parameters.
+ *
+ * @param params The Params instance that describes
+ * the customizable aspects of the decoder.
+ */
+ public Decoder(Params params0)
+ {
+ if (params0==null)
+ params0 = DEFAULT_PARAMS;
+
+ params = params0;
+
+ Equalizer eq = params.getInitialEqualizerSettings();
+ if (eq!=null)
+ {
+ equalizer.setFrom(eq);
+ }
+ }
+
+ static public Params getDefaultParams()
+ {
+ return (Params)DEFAULT_PARAMS.clone();
+ }
+
+ public void setEqualizer(Equalizer eq)
+ {
+ if (eq==null)
+ eq = Equalizer.PASS_THRU_EQ;
+
+ equalizer.setFrom(eq);
+
+ float[] factors = equalizer.getBandFactors();
+
+ if (filter1!=null)
+ filter1.setEQ(factors);
+
+ if (filter2!=null)
+ filter2.setEQ(factors);
+ }
+
+ /**
+ * Decodes one frame from an MPEG audio bitstream.
+ *
+ * @param header The header describing the frame to decode.
+ * @param bitstream The bistream that provides the bits for te body of the frame.
+ *
+ * @return A SampleBuffer containing the decoded samples.
+ */
+ public Obuffer decodeFrame(Header header, Bitstream stream)
+ throws DecoderException
+ {
+ if (!initialized)
+ {
+ initialize(header);
+ }
+
+ int layer = header.layer();
+
+ output.clear_buffer();
+
+ FrameDecoder decoder = retrieveDecoder(header, stream, layer);
+
+ decoder.decodeFrame();
+
+ output.write_buffer(1);
+
+ return output;
+ }
+
+ /**
+ * Changes the output buffer. This will take effect the next time
+ * decodeFrame() is called.
+ */
+ public void setOutputBuffer(Obuffer out)
+ {
+ output = out;
+ }
+
+ /**
+ * Retrieves the sample frequency of the PCM samples output
+ * by this decoder. This typically corresponds to the sample
+ * rate encoded in the MPEG audio stream.
+ *
+ * @param the sample rate (in Hz) of the samples written to the
+ * output buffer when decoding.
+ */
+ public int getOutputFrequency()
+ {
+ return outputFrequency;
+ }
+
+ /**
+ * Retrieves the number of channels of PCM samples output by
+ * this decoder. This usually corresponds to the number of
+ * channels in the MPEG audio stream, although it may differ.
+ *
+ * @return The number of output channels in the decoded samples: 1
+ * for mono, or 2 for stereo.
+ *
+ */
+ public int getOutputChannels()
+ {
+ return outputChannels;
+ }
+
+ /**
+ * Retrieves the maximum number of samples that will be written to
+ * the output buffer when one frame is decoded. This can be used to
+ * help calculate the size of other buffers whose size is based upon
+ * the number of samples written to the output buffer. NB: this is
+ * an upper bound and fewer samples may actually be written, depending
+ * upon the sample rate and number of channels.
+ *
+ * @return The maximum number of samples that are written to the
+ * output buffer when decoding a single frame of MPEG audio.
+ */
+ public int getOutputBlockSize()
+ {
+ return Obuffer.OBUFFERSIZE;
+ }
+
+
+ protected DecoderException newDecoderException(int errorcode)
+ {
+ return new DecoderException(errorcode, null);
+ }
+
+ protected DecoderException newDecoderException(int errorcode, Throwable throwable)
+ {
+ return new DecoderException(errorcode, throwable);
+ }
+
+ protected FrameDecoder retrieveDecoder(Header header, Bitstream stream, int layer)
+ throws DecoderException
+ {
+ FrameDecoder decoder = null;
+
+ // REVIEW: allow channel output selection type
+ // (LEFT, RIGHT, BOTH, DOWNMIX)
+ switch (layer)
+ {
+ case 3:
+ if (l3decoder==null)
+ {
+ l3decoder = new LayerIIIDecoder(stream,
+ header, filter1, filter2,
+ output, OutputChannels.BOTH_CHANNELS);
+ }
+
+ decoder = l3decoder;
+ break;
+ case 2:
+ if (l2decoder==null)
+ {
+ l2decoder = new LayerIIDecoder();
+ l2decoder.create(stream,
+ header, filter1, filter2,
+ output, OutputChannels.BOTH_CHANNELS);
+ }
+ decoder = l2decoder;
+ break;
+ case 1:
+ if (l1decoder==null)
+ {
+ l1decoder = new LayerIDecoder();
+ l1decoder.create(stream,
+ header, filter1, filter2,
+ output, OutputChannels.BOTH_CHANNELS);
+ }
+ decoder = l1decoder;
+ break;
+ }
+
+ if (decoder==null)
+ {
+ throw newDecoderException(UNSUPPORTED_LAYER, null);
+ }
+
+ return decoder;
+ }
+
+ private void initialize(Header header)
+ throws DecoderException
+ {
+
+ // REVIEW: allow customizable scale factor
+ float scalefactor = 32700.0f;
+
+ int mode = header.mode();
+ int layer = header.layer();
+ int channels = mode==Header.SINGLE_CHANNEL ? 1 : 2;
+
+
+ // set up output buffer if not set up by client.
+ if (output==null)
+ output = new SampleBuffer(header.frequency(), channels);
+
+ float[] factors = equalizer.getBandFactors();
+ filter1 = new SynthesisFilter(0, scalefactor, factors);
+
+ // REVIEW: allow mono output for stereo
+ if (channels==2)
+ filter2 = new SynthesisFilter(1, scalefactor, factors);
+
+ outputChannels = channels;
+ outputFrequency = header.frequency();
+
+ initialized = true;
+ }
+
+ /**
+ * The Params class presents the customizable
+ * aspects of the decoder.
+ * + * Instances of this class are not thread safe. + */ + public static class Params implements Cloneable + { + private OutputChannels outputChannels = OutputChannels.BOTH; + + private Equalizer equalizer = new Equalizer(); + + public Params() + { + } + + public Object clone() + { + try + { + return super.clone(); + } + catch (CloneNotSupportedException ex) + { + throw new InternalError(this+": "+ex); + } + } + + public void setOutputChannels(OutputChannels out) + { + if (out==null) + throw new NullPointerException("out"); + + outputChannels = out; + } + + public OutputChannels getOutputChannels() + { + return outputChannels; + } + + /** + * Retrieves the equalizer settings that the decoder's equalizer + * will be initialized from. + *
+ * The Equalizer instance returned
+ * cannot be changed in real time to affect the
+ * decoder output as it is used only to initialize the decoders
+ * EQ settings. To affect the decoder's output in realtime,
+ * use the Equalizer returned from the getEqualizer() method on
+ * the decoder.
+ *
+ * @return The Equalizer used to initialize the
+ * EQ settings of the decoder.
+ */
+ public Equalizer getInitialEqualizerSettings()
+ {
+ return equalizer;
+ }
+
+ };
+}
+
diff --git a/src/javazoom/jl/decoder/DecoderErrors.java b/src/javazoom/jl/decoder/DecoderErrors.java
new file mode 100644
index 00000000000..686f2602213
--- /dev/null
+++ b/src/javazoom/jl/decoder/DecoderErrors.java
@@ -0,0 +1,45 @@
+/*
+ * 09/26/08 throw exception on subbband alloc error: Christopher G. Jennings (cjennings@acm.org)
+ * 11/19/04 1.0 moved to LGPL.
+ * 01/12/99 Initial version. mdm@techie.com
+ *-----------------------------------------------------------------------
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *----------------------------------------------------------------------
+ */
+
+package javazoom.jl.decoder;
+
+/**
+ * This interface provides constants describing the error
+ * codes used by the Decoder to indicate errors.
+ *
+ * @author MDM
+ */
+public interface DecoderErrors extends JavaLayerErrors
+{
+
+ static public final int UNKNOWN_ERROR = DECODER_ERROR + 0;
+
+ /**
+ * Layer not supported by the decoder.
+ */
+ static public final int UNSUPPORTED_LAYER = DECODER_ERROR + 1;
+
+ /**
+ * Illegal allocation in subband layer. Indicates a corrupt stream.
+ */
+ static public final int ILLEGAL_SUBBAND_ALLOCATION = DECODER_ERROR + 2;
+
+}
diff --git a/src/javazoom/jl/decoder/DecoderException.java b/src/javazoom/jl/decoder/DecoderException.java
new file mode 100644
index 00000000000..87638ad2642
--- /dev/null
+++ b/src/javazoom/jl/decoder/DecoderException.java
@@ -0,0 +1,61 @@
+/*
+ * 11/19/04 1.0 moved to LGPL.
+ * 01/12/99 Initial version. mdm@techie.com
+ *-----------------------------------------------------------------------
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *----------------------------------------------------------------------
+ */
+
+package javazoom.jl.decoder;
+
+/**
+ * The DecoderException represents the class of
+ * errors that can occur when decoding MPEG audio.
+ *
+ * @author MDM
+ */
+public class DecoderException extends JavaLayerException
+ implements DecoderErrors
+{
+ private int errorcode = UNKNOWN_ERROR;
+
+ public DecoderException(String msg, Throwable t)
+ {
+ super(msg, t);
+ }
+
+ public DecoderException(int errorcode, Throwable t)
+ {
+ this(getErrorString(errorcode), t);
+ this.errorcode = errorcode;
+ }
+
+ public int getErrorCode()
+ {
+ return errorcode;
+ }
+
+
+ static public String getErrorString(int errorcode)
+ {
+ // REVIEW: use resource file to map error codes
+ // to locale-sensitive strings.
+
+ return "Decoder errorcode "+Integer.toHexString(errorcode);
+ }
+
+
+}
+
diff --git a/src/javazoom/jl/decoder/Equalizer.java b/src/javazoom/jl/decoder/Equalizer.java
new file mode 100644
index 00000000000..439279e6100
--- /dev/null
+++ b/src/javazoom/jl/decoder/Equalizer.java
@@ -0,0 +1,227 @@
+/*
+ * 11/19/04 1.0 moved to LGPL.
+ * 12/12/99 Initial version. mdm@techie.com
+ *-----------------------------------------------------------------------
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *----------------------------------------------------------------------
+ */
+
+
+package javazoom.jl.decoder;
+
+/**
+ * The Equalizer class can be used to specify
+ * equalization settings for the MPEG audio decoder.
+ *
+ * The equalizer consists of 32 band-pass filters.
+ * Each band of the equalizer can take on a fractional value between
+ * -1.0 and +1.0.
+ * At -1.0, the input signal is attenuated by 6dB, at +1.0 the signal is
+ * amplified by 6dB.
+ *
+ * @see Decoder
+ *
+ * @author MDM
+ */
+public final class Equalizer
+{
+ /**
+ * Equalizer setting to denote that a given band will not be
+ * present in the output signal.
+ */
+ static public final float BAND_NOT_PRESENT = Float.NEGATIVE_INFINITY;
+
+ static public final Equalizer PASS_THRU_EQ = new Equalizer();
+
+ private static final int BANDS = 32;
+
+ private final float[] settings = new float[BANDS];
+
+ /**
+ * Creates a new
+ *
+ * @author MDM
+ */
+public class JavaLayerException extends Exception
+{
+
+ private Throwable exception;
+
+
+ public JavaLayerException()
+ {
+ }
+
+ public JavaLayerException(String msg)
+ {
+ super(msg);
+ }
+
+ public JavaLayerException(String msg, Throwable t)
+ {
+ super(msg);
+ exception = t;
+ }
+
+ public Throwable getException()
+ {
+ return exception;
+ }
+
+
+ public void printStackTrace()
+ {
+ printStackTrace(System.err);
+ }
+
+ public void printStackTrace(PrintStream ps)
+ {
+ if (this.exception==null)
+ {
+ super.printStackTrace(ps);
+ }
+ else
+ {
+ exception.printStackTrace();
+ }
+ }
+
+
+}
diff --git a/src/javazoom/jl/decoder/JavaLayerHook.java b/src/javazoom/jl/decoder/JavaLayerHook.java
new file mode 100644
index 00000000000..edd890dd693
--- /dev/null
+++ b/src/javazoom/jl/decoder/JavaLayerHook.java
@@ -0,0 +1,36 @@
+/*
+ * 11/19/04 1.0 moved to LGPL.
+ *-----------------------------------------------------------------------
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *----------------------------------------------------------------------
+ */
+
+package javazoom.jl.decoder;
+
+import java.io.InputStream;
+
+/**
+ * The
+ * When implementing a factory that provides an AudioDevice that uses
+ * class that may not be present, the factory should dynamically link to any
+ * specific implementation classes required to instantiate or test the audio
+ * implementation. This is so that the application as a whole
+ * can run without these classes being present. The audio
+ * device implementation, however, will usually statically link to the classes
+ * required. (See the JavaSound deivce and factory for an example
+ * of this.)
+ *
+ * @see FactoryRegistry
+ *
+ * @since 0.0.8
+ * @author Mat McGowan
+ */
+public abstract class AudioDeviceFactory
+{
+ /**
+ * Creates a new
+ * Instances of this class are thread-safe.
+ *
+ * @since 0.0.8
+ * @author Mat McGowan
+ */
+
+public class FactoryRegistry extends AudioDeviceFactory
+{
+ static private FactoryRegistry instance = null;
+
+ static synchronized public FactoryRegistry systemRegistry()
+ {
+ if (instance==null)
+ {
+ instance = new FactoryRegistry();
+ instance.registerDefaultFactories();
+ }
+ return instance;
+ }
+
+
+ protected Hashtable factories = new Hashtable();
+
+ /**
+ * Registers an Equalizer instance.
+ */
+ public Equalizer()
+ {
+ }
+
+// private Equalizer(float b1, float b2, float b3, float b4, float b5,
+// float b6, float b7, float b8, float b9, float b10, float b11,
+// float b12, float b13, float b14, float b15, float b16,
+// float b17, float b18, float b19, float b20);
+
+ public Equalizer(float[] settings)
+ {
+ setFrom(settings);
+ }
+
+ public Equalizer(EQFunction eq)
+ {
+ setFrom(eq);
+ }
+
+ public void setFrom(float[] eq)
+ {
+ reset();
+ int max = (eq.length > BANDS) ? BANDS : eq.length;
+
+ for (int i=0; iInputStreamSource implements a
+ * Source that provides data from an InputStream
+ * . Seeking functionality is not supported.
+ *
+ * @author MDM
+ */
+public class InputStreamSource implements Source
+{
+ private final InputStream in;
+
+ public InputStreamSource(InputStream in)
+ {
+ if (in==null)
+ throw new NullPointerException("in");
+
+ this.in = in;
+ }
+
+ public int read(byte[] b, int offs, int len)
+ throws IOException
+ {
+ int read = in.read(b, offs, len);
+ return read;
+ }
+
+ public boolean willReadBlock()
+ {
+ return true;
+ //boolean block = (in.available()==0);
+ //return block;
+ }
+
+ public boolean isSeekable()
+ {
+ return false;
+ }
+
+ public long tell()
+ {
+ return -1;
+ }
+
+ public long seek(long to)
+ {
+ return -1;
+ }
+
+ public long length()
+ {
+ return -1;
+ }
+}
diff --git a/src/javazoom/jl/decoder/JavaLayerError.java b/src/javazoom/jl/decoder/JavaLayerError.java
new file mode 100644
index 00000000000..042d83a5a4a
--- /dev/null
+++ b/src/javazoom/jl/decoder/JavaLayerError.java
@@ -0,0 +1,31 @@
+/*
+ * 11/19/04 1.0 moved to LGPL.
+ * 12/12/99 Initial version. mdm@techie.com
+ *-----------------------------------------------------------------------
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *----------------------------------------------------------------------
+ */
+
+package javazoom.jl.decoder;
+
+/**
+ * Work in progress.
+ *
+ * API usage errors may be handled by throwing an instance of this
+ * class, as per JMF 2.0.
+ */
+public class JavaLayerError extends Error
+{
+}
diff --git a/src/javazoom/jl/decoder/JavaLayerErrors.java b/src/javazoom/jl/decoder/JavaLayerErrors.java
new file mode 100644
index 00000000000..b141ce843d8
--- /dev/null
+++ b/src/javazoom/jl/decoder/JavaLayerErrors.java
@@ -0,0 +1,40 @@
+/*
+ * 11/19/04 1.0 moved to LGPL.
+ * 12/12/99 Initial version. mdm@techie.com
+ *-----------------------------------------------------------------------
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *----------------------------------------------------------------------
+ */
+
+package javazoom.jl.decoder;
+
+/**
+ * Exception erorr codes for components of the JavaLayer API.
+ */
+public interface JavaLayerErrors
+{
+ /**
+ * The first bitstream error code. See the {@link DecoderErrors DecoderErrors}
+ * interface for other bitstream error codes.
+ */
+ static public final int BITSTREAM_ERROR = 0x100;
+
+ /**
+ * The first decoder error code. See the {@link DecoderErrors DecoderErrors}
+ * interface for other decoder error codes.
+ */
+ static public final int DECODER_ERROR = 0x200;
+
+}
diff --git a/src/javazoom/jl/decoder/JavaLayerException.java b/src/javazoom/jl/decoder/JavaLayerException.java
new file mode 100644
index 00000000000..0767bf21770
--- /dev/null
+++ b/src/javazoom/jl/decoder/JavaLayerException.java
@@ -0,0 +1,80 @@
+/*
+ * 11/19/04 1.0 moved to LGPL.
+ * 12/12/99 Initial version. mdm@techie.com
+ *-----------------------------------------------------------------------
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *----------------------------------------------------------------------
+ */
+
+package javazoom.jl.decoder;
+
+import java.io.PrintStream;
+
+
+/**
+ * The JavaLayerException is the base class for all API-level
+ * exceptions thrown by JavaLayer. To facilitate conversion and
+ * common handling of exceptions from other domains, the class
+ * can delegate some functionality to a contained Throwable instance.
+ * JavaLayerHooks class allows developers to change
+ * the way the JavaLayer library uses Resources.
+ */
+
+public interface JavaLayerHook
+{
+ /**
+ * Retrieves the named resource. This allows resources to be
+ * obtained without specifying how they are retrieved.
+ */
+ public InputStream getResourceAsStream(String name);
+}
diff --git a/src/javazoom/jl/decoder/JavaLayerUtils.java b/src/javazoom/jl/decoder/JavaLayerUtils.java
new file mode 100644
index 00000000000..b7cd54848af
--- /dev/null
+++ b/src/javazoom/jl/decoder/JavaLayerUtils.java
@@ -0,0 +1,207 @@
+/*
+ * 11/19/04 1.0 moved to LGPL.
+ * 12/12/99 Initial version. mdm@techie.com
+ *-----------------------------------------------------------------------
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *----------------------------------------------------------------------
+ */
+
+package javazoom.jl.decoder;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InvalidClassException;
+import java.io.InvalidObjectException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.OutputStream;
+import java.lang.reflect.Array;
+
+/**
+ * The JavaLayerUtils class is not strictly part of the JavaLayer API.
+ * It serves to provide useful methods and system-wide hooks.
+ *
+ * @author MDM
+ */
+public class JavaLayerUtils
+{
+ static private JavaLayerHook hook = null;
+
+ /**
+ * Deserializes the object contained in the given input stream.
+ * @param in The input stream to deserialize an object from.
+ * @param cls The expected class of the deserialized object.
+ */
+ static public Object deserialize(InputStream in, Class cls)
+ throws IOException
+ {
+ if (cls==null)
+ throw new NullPointerException("cls");
+
+ Object obj = deserialize(in, cls);
+ if (!cls.isInstance(obj))
+ {
+ throw new InvalidObjectException("type of deserialized instance not of required class.");
+ }
+
+ return obj;
+ }
+
+ /**
+ * Deserializes an object from the given InputStream.
+ * The deserialization is delegated to an
+ * ObjectInputStream instance.
+ *
+ * @param in The InputStream to deserialize an object
+ * from.
+ *
+ * @return The object deserialized from the stream.
+ * @exception IOException is thrown if there was a problem reading
+ * the underlying stream, or an object could not be deserialized
+ * from the stream.
+ *
+ * @see java.io.ObjectInputStream
+ */
+ static public Object deserialize(InputStream in)
+ throws IOException
+ {
+ if (in==null)
+ throw new NullPointerException("in");
+
+ ObjectInputStream objIn = new ObjectInputStream(in);
+
+ Object obj;
+
+ try
+ {
+ obj = objIn.readObject();
+ }
+ catch (ClassNotFoundException ex)
+ {
+ throw new InvalidClassException(ex.toString());
+ }
+
+ return obj;
+ }
+
+ /**
+ * Deserializes an array from a given InputStream.
+ *
+ * @param in The InputStream to
+ * deserialize an object from.
+ *
+ * @param elemType The class denoting the type of the array
+ * elements.
+ * @param length The expected length of the array, or -1 if
+ * any length is expected.
+ */
+ static public Object deserializeArray(InputStream in, Class elemType, int length)
+ throws IOException
+ {
+ if (elemType==null)
+ throw new NullPointerException("elemType");
+
+ if (length<-1)
+ throw new IllegalArgumentException("length");
+
+ Object obj = deserialize(in);
+
+ Class cls = obj.getClass();
+
+
+ if (!cls.isArray())
+ throw new InvalidObjectException("object is not an array");
+
+ Class arrayElemType = cls.getComponentType();
+ if (arrayElemType!=elemType)
+ throw new InvalidObjectException("unexpected array component type");
+
+ if (length != -1)
+ {
+ int arrayLength = Array.getLength(obj);
+ if (arrayLength!=length)
+ throw new InvalidObjectException("array length mismatch");
+ }
+
+ return obj;
+ }
+
+ static public Object deserializeArrayResource(String name, Class elemType, int length)
+ throws IOException
+ {
+ InputStream str = getResourceAsStream(name);
+ if (str==null)
+ throw new IOException("unable to load resource '"+name+"'");
+
+ Object obj = deserializeArray(str, elemType, length);
+
+ return obj;
+ }
+
+ static public void serialize(OutputStream out, Object obj)
+ throws IOException
+ {
+ if (out==null)
+ throw new NullPointerException("out");
+
+ if (obj==null)
+ throw new NullPointerException("obj");
+
+ ObjectOutputStream objOut = new ObjectOutputStream(out);
+ objOut.writeObject(obj);
+
+ }
+
+ /**
+ * Sets the system-wide JavaLayer hook.
+ */
+ static synchronized public void setHook(JavaLayerHook hook0)
+ {
+ hook = hook0;
+ }
+
+ static synchronized public JavaLayerHook getHook()
+ {
+ return hook;
+ }
+
+ /**
+ * Retrieves an InputStream for a named resource.
+ *
+ * @param name The name of the resource. This must be a simple
+ * name, and not a qualified package name.
+ *
+ * @return The InputStream for the named resource, or null if
+ * the resource has not been found. If a hook has been
+ * provided, its getResourceAsStream() method is called
+ * to retrieve the resource.
+ */
+ static synchronized public InputStream getResourceAsStream(String name)
+ {
+ InputStream is = null;
+
+ if (hook!=null)
+ {
+ is = hook.getResourceAsStream(name);
+ }
+ else
+ {
+ Class cls = JavaLayerUtils.class;
+ is = cls.getResourceAsStream(name);
+ }
+
+ return is;
+ }
+}
diff --git a/src/javazoom/jl/decoder/LayerIDecoder.java b/src/javazoom/jl/decoder/LayerIDecoder.java
new file mode 100644
index 00000000000..fb936d2b913
--- /dev/null
+++ b/src/javazoom/jl/decoder/LayerIDecoder.java
@@ -0,0 +1,448 @@
+/*
+ * 09/26/08 throw exception on subbband alloc error: Christopher G. Jennings (cjennings@acm.org)
+ *
+ * 11/19/04 1.0 moved to LGPL.
+ *
+ * 12/12/99 Initial version. Adapted from javalayer.java
+ * and Subband*.java. mdm@techie.com
+ *
+ * 02/28/99 Initial version : javalayer.java by E.B
+ *-----------------------------------------------------------------------
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *----------------------------------------------------------------------
+ */
+
+package javazoom.jl.decoder;
+
+/**
+ * Implements decoding of MPEG Audio Layer I frames.
+ */
+class LayerIDecoder implements FrameDecoder
+{
+ protected Bitstream stream;
+ protected Header header;
+ protected SynthesisFilter filter1, filter2;
+ protected Obuffer buffer;
+ protected int which_channels;
+ protected int mode;
+
+ protected int num_subbands;
+ protected Subband[] subbands;
+ protected Crc16 crc = null; // new Crc16[1] to enable CRC checking.
+
+ public LayerIDecoder()
+ {
+ crc = new Crc16();
+ }
+
+ public void create(Bitstream stream0, Header header0,
+ SynthesisFilter filtera, SynthesisFilter filterb,
+ Obuffer buffer0, int which_ch0)
+ {
+ stream = stream0;
+ header = header0;
+ filter1 = filtera;
+ filter2 = filterb;
+ buffer = buffer0;
+ which_channels = which_ch0;
+
+ }
+
+ public void decodeFrame() throws DecoderException
+ {
+
+ num_subbands = header.number_of_subbands();
+ subbands = new Subband[32];
+ mode = header.mode();
+
+ createSubbands();
+
+ readAllocation();
+ readScaleFactorSelection();
+
+ if ((crc != null) || header.checksum_ok())
+ {
+ readScaleFactors();
+
+ readSampleData();
+ }
+
+ }
+
+ protected void createSubbands()
+ {
+ int i;
+ if (mode == Header.SINGLE_CHANNEL)
+ for (i = 0; i < num_subbands; ++i)
+ subbands[i] = new SubbandLayer1(i);
+ else if (mode == Header.JOINT_STEREO)
+ {
+ for (i = 0; i < header.intensity_stereo_bound(); ++i)
+ subbands[i] = new SubbandLayer1Stereo(i);
+ for (; i < num_subbands; ++i)
+ subbands[i] = new SubbandLayer1IntensityStereo(i);
+ }
+ else
+ {
+ for (i = 0; i < num_subbands; ++i)
+ subbands[i] = new SubbandLayer1Stereo(i);
+ }
+ }
+
+ protected void readAllocation() throws DecoderException
+ {
+ // start to read audio data:
+ for (int i = 0; i < num_subbands; ++i)
+ subbands[i].read_allocation(stream, header, crc);
+
+ }
+
+ protected void readScaleFactorSelection()
+ {
+ // scale factor selection not present for layer I.
+ }
+
+ protected void readScaleFactors()
+ {
+ for (int i = 0; i < num_subbands; ++i)
+ subbands[i].read_scalefactor(stream, header);
+ }
+
+ protected void readSampleData()
+ {
+ boolean read_ready = false;
+ boolean write_ready = false;
+ int mode = header.mode();
+ int i;
+ do
+ {
+ for (i = 0; i < num_subbands; ++i)
+ read_ready = subbands[i].read_sampledata(stream);
+ do
+ {
+ for (i = 0; i < num_subbands; ++i)
+ write_ready = subbands[i].put_next_sample(which_channels,filter1, filter2);
+
+ filter1.calculate_pcm_samples(buffer);
+ if ((which_channels == OutputChannels.BOTH_CHANNELS) && (mode != Header.SINGLE_CHANNEL))
+ filter2.calculate_pcm_samples(buffer);
+ } while (!write_ready);
+ } while (!read_ready);
+
+ }
+
+ /**
+ * Abstract base class for subband classes of layer I and II
+ */
+ static abstract class Subband
+ {
+ /*
+ * Changes from version 1.1 to 1.2:
+ * - array size increased by one, although a scalefactor with index 63
+ * is illegal (to prevent segmentation faults)
+ */
+ // Scalefactors for layer I and II, Annex 3-B.1 in ISO/IEC DIS 11172:
+ public static final float scalefactors[] =
+ {
+ 2.00000000000000f, 1.58740105196820f, 1.25992104989487f, 1.00000000000000f,
+ 0.79370052598410f, 0.62996052494744f, 0.50000000000000f, 0.39685026299205f,
+ 0.31498026247372f, 0.25000000000000f, 0.19842513149602f, 0.15749013123686f,
+ 0.12500000000000f, 0.09921256574801f, 0.07874506561843f, 0.06250000000000f,
+ 0.04960628287401f, 0.03937253280921f, 0.03125000000000f, 0.02480314143700f,
+ 0.01968626640461f, 0.01562500000000f, 0.01240157071850f, 0.00984313320230f,
+ 0.00781250000000f, 0.00620078535925f, 0.00492156660115f, 0.00390625000000f,
+ 0.00310039267963f, 0.00246078330058f, 0.00195312500000f, 0.00155019633981f,
+ 0.00123039165029f, 0.00097656250000f, 0.00077509816991f, 0.00061519582514f,
+ 0.00048828125000f, 0.00038754908495f, 0.00030759791257f, 0.00024414062500f,
+ 0.00019377454248f, 0.00015379895629f, 0.00012207031250f, 0.00009688727124f,
+ 0.00007689947814f, 0.00006103515625f, 0.00004844363562f, 0.00003844973907f,
+ 0.00003051757813f, 0.00002422181781f, 0.00001922486954f, 0.00001525878906f,
+ 0.00001211090890f, 0.00000961243477f, 0.00000762939453f, 0.00000605545445f,
+ 0.00000480621738f, 0.00000381469727f, 0.00000302772723f, 0.00000240310869f,
+ 0.00000190734863f, 0.00000151386361f, 0.00000120155435f, 0.00000000000000f /* illegal scalefactor */
+ };
+
+ public abstract void read_allocation (Bitstream stream, Header header, Crc16 crc) throws DecoderException;
+ public abstract void read_scalefactor (Bitstream stream, Header header);
+ public abstract boolean read_sampledata (Bitstream stream);
+ public abstract boolean put_next_sample (int channels, SynthesisFilter filter1, SynthesisFilter filter2);
+ };
+
+ /**
+ * Class for layer I subbands in single channel mode.
+ * Used for single channel mode
+ * and in derived class for intensity stereo mode
+ */
+ static class SubbandLayer1 extends Subband
+ {
+
+ // Factors and offsets for sample requantization
+ public static final float table_factor[] = {
+ 0.0f, (1.0f/2.0f) * (4.0f/3.0f), (1.0f/4.0f) * (8.0f/7.0f), (1.0f/8.0f) * (16.0f/15.0f),
+ (1.0f/16.0f) * (32.0f/31.0f), (1.0f/32.0f) * (64.0f/63.0f), (1.0f/64.0f) * (128.0f/127.0f),
+ (1.0f/128.0f) * (256.0f/255.0f), (1.0f/256.0f) * (512.0f/511.0f),
+ (1.0f/512.0f) * (1024.0f/1023.0f), (1.0f/1024.0f) * (2048.0f/2047.0f),
+ (1.0f/2048.0f) * (4096.0f/4095.0f), (1.0f/4096.0f) * (8192.0f/8191.0f),
+ (1.0f/8192.0f) * (16384.0f/16383.0f), (1.0f/16384.0f) * (32768.0f/32767.0f)
+ };
+
+ public static final float table_offset[] = {
+ 0.0f, ((1.0f/2.0f)-1.0f) * (4.0f/3.0f), ((1.0f/4.0f)-1.0f) * (8.0f/7.0f), ((1.0f/8.0f)-1.0f) * (16.0f/15.0f),
+ ((1.0f/16.0f)-1.0f) * (32.0f/31.0f), ((1.0f/32.0f)-1.0f) * (64.0f/63.0f), ((1.0f/64.0f)-1.0f) * (128.0f/127.0f),
+ ((1.0f/128.0f)-1.0f) * (256.0f/255.0f), ((1.0f/256.0f)-1.0f) * (512.0f/511.0f),
+ ((1.0f/512.0f)-1.0f) * (1024.0f/1023.0f), ((1.0f/1024.0f)-1.0f) * (2048.0f/2047.0f),
+ ((1.0f/2048.0f)-1.0f) * (4096.0f/4095.0f), ((1.0f/4096.0f)-1.0f) * (8192.0f/8191.0f),
+ ((1.0f/8192.0f)-1.0f) * (16384.0f/16383.0f), ((1.0f/16384.0f)-1.0f) * (32768.0f/32767.0f)
+ };
+
+ protected int subbandnumber;
+ protected int samplenumber;
+ protected int allocation;
+ protected float scalefactor;
+ protected int samplelength;
+ protected float sample;
+ protected float factor, offset;
+
+ /**
+ * Construtor.
+ */
+ public SubbandLayer1(int subbandnumber)
+ {
+ this.subbandnumber = subbandnumber;
+ samplenumber = 0;
+ }
+
+ /**
+ *
+ */
+ public void read_allocation(Bitstream stream, Header header, Crc16 crc) throws DecoderException
+ {
+ if ((allocation = stream.get_bits (4)) == 15)
+ {
+ // CGJ: catch this condition and throw appropriate exception
+ throw new DecoderException(DecoderErrors.ILLEGAL_SUBBAND_ALLOCATION, null);
+ // cerr << "WARNING: stream contains an illegal allocation!\n";
+ // MPEG-stream is corrupted!
+ }
+
+ if (crc != null) crc.add_bits (allocation, 4);
+ if (allocation != 0)
+ {
+ samplelength = allocation + 1;
+ factor = table_factor[allocation];
+ offset = table_offset[allocation];
+ }
+ }
+
+ /**
+ *
+ */
+ public void read_scalefactor(Bitstream stream, Header header)
+ {
+ if (allocation != 0) scalefactor = scalefactors[stream.get_bits(6)];
+ }
+
+ /**
+ *
+ */
+ public boolean read_sampledata(Bitstream stream)
+ {
+ if (allocation != 0)
+ {
+ sample = (float) (stream.get_bits(samplelength));
+ }
+ if (++samplenumber == 12)
+ {
+ samplenumber = 0;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ *
+ */
+ public boolean put_next_sample(int channels, SynthesisFilter filter1, SynthesisFilter filter2)
+ {
+ if ((allocation !=0) && (channels != OutputChannels.RIGHT_CHANNEL))
+ {
+ float scaled_sample = (sample * factor + offset) * scalefactor;
+ filter1.input_sample (scaled_sample, subbandnumber);
+ }
+ return true;
+ }
+ };
+
+ /**
+ * Class for layer I subbands in joint stereo mode.
+ */
+ static class SubbandLayer1IntensityStereo extends SubbandLayer1
+ {
+ protected float channel2_scalefactor;
+
+ /**
+ * Constructor
+ */
+ public SubbandLayer1IntensityStereo(int subbandnumber)
+ {
+ super(subbandnumber);
+ }
+
+ /**
+ *
+ */
+ public void read_allocation(Bitstream stream, Header header, Crc16 crc) throws DecoderException
+ {
+ super.read_allocation (stream, header, crc);
+ }
+
+ /**
+ *
+ */
+ public void read_scalefactor (Bitstream stream, Header header)
+ {
+ if (allocation != 0)
+ {
+ scalefactor = scalefactors[stream.get_bits(6)];
+ channel2_scalefactor = scalefactors[stream.get_bits(6)];
+ }
+ }
+
+ /**
+ *
+ */
+ public boolean read_sampledata(Bitstream stream)
+ {
+ return super.read_sampledata (stream);
+ }
+
+ /**
+ *
+ */
+ public boolean put_next_sample (int channels, SynthesisFilter filter1, SynthesisFilter filter2)
+ {
+ if (allocation !=0 )
+ {
+ sample = sample * factor + offset; // requantization
+ if (channels == OutputChannels.BOTH_CHANNELS)
+ {
+ float sample1 = sample * scalefactor,
+ sample2 = sample * channel2_scalefactor;
+ filter1.input_sample(sample1, subbandnumber);
+ filter2.input_sample(sample2, subbandnumber);
+ }
+ else if (channels == OutputChannels.LEFT_CHANNEL)
+ {
+ float sample1 = sample * scalefactor;
+ filter1.input_sample(sample1, subbandnumber);
+ }
+ else
+ {
+ float sample2 = sample * channel2_scalefactor;
+ filter1.input_sample(sample2, subbandnumber);
+ }
+ }
+ return true;
+ }
+ };
+
+ /**
+ * Class for layer I subbands in stereo mode.
+ */
+ static class SubbandLayer1Stereo extends SubbandLayer1
+ {
+ protected int channel2_allocation;
+ protected float channel2_scalefactor;
+ protected int channel2_samplelength;
+ protected float channel2_sample;
+ protected float channel2_factor, channel2_offset;
+
+
+ /**
+ * Constructor
+ */
+ public SubbandLayer1Stereo(int subbandnumber)
+ {
+ super(subbandnumber);
+ }
+
+ /**
+ *
+ */
+ public void read_allocation (Bitstream stream, Header header, Crc16 crc) throws DecoderException
+ {
+ allocation = stream.get_bits(4);
+ channel2_allocation = stream.get_bits(4);
+ if (crc != null)
+ {
+ crc.add_bits (allocation, 4);
+ crc.add_bits (channel2_allocation, 4);
+ }
+ if (allocation != 0)
+ {
+ samplelength = allocation + 1;
+ factor = table_factor[allocation];
+ offset = table_offset[allocation];
+ }
+ if (channel2_allocation != 0)
+ {
+ channel2_samplelength = channel2_allocation + 1;
+ channel2_factor = table_factor[channel2_allocation];
+ channel2_offset = table_offset[channel2_allocation];
+ }
+ }
+
+ /**
+ *
+ */
+ public void read_scalefactor(Bitstream stream, Header header)
+ {
+ if (allocation != 0) scalefactor = scalefactors[stream.get_bits(6)];
+ if (channel2_allocation != 0) channel2_scalefactor = scalefactors[stream.get_bits(6)];
+ }
+
+ /**
+ *
+ */
+ public boolean read_sampledata (Bitstream stream)
+ {
+ boolean returnvalue = super.read_sampledata(stream);
+ if (channel2_allocation != 0)
+ {
+ channel2_sample = (float) (stream.get_bits(channel2_samplelength));
+ }
+ return(returnvalue);
+ }
+
+ /**
+ *
+ */
+ public boolean put_next_sample(int channels, SynthesisFilter filter1, SynthesisFilter filter2)
+ {
+ super.put_next_sample (channels, filter1, filter2);
+ if ((channel2_allocation != 0) && (channels != OutputChannels.LEFT_CHANNEL))
+ {
+ float sample2 = (channel2_sample * channel2_factor + channel2_offset) *
+ channel2_scalefactor;
+ if (channels == OutputChannels.BOTH_CHANNELS)
+ filter2.input_sample (sample2, subbandnumber);
+ else
+ filter1.input_sample (sample2, subbandnumber);
+ }
+ return true;
+ }
+ };
+
+}
diff --git a/src/javazoom/jl/decoder/LayerIIDecoder.java b/src/javazoom/jl/decoder/LayerIIDecoder.java
new file mode 100644
index 00000000000..7265b1f8faf
--- /dev/null
+++ b/src/javazoom/jl/decoder/LayerIIDecoder.java
@@ -0,0 +1,1064 @@
+/*
+ * 11/19/04 1.0 moved to LGPL.
+ *
+ * 29/05/01 Michael Scheerer, Fixed some C++ to Java porting bugs.
+ *
+ * 16/07/01 Michael Scheerer, Catched a bug in method
+ * read_sampledata, which causes an outOfIndexException.
+ *
+ * 12/12/99 Initial version. Adapted from javalayer.java
+ * and Subband*.java. mdm@techie.com
+ *
+ * 02/28/99 Initial version : javalayer.java by E.B
+ *-----------------------------------------------------------------------
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *----------------------------------------------------------------------
+ */
+
+package javazoom.jl.decoder;
+
+/**
+ * Implements decoding of MPEG Audio Layer II frames.
+ */
+class LayerIIDecoder extends LayerIDecoder implements FrameDecoder
+{
+
+ public LayerIIDecoder()
+ {
+ }
+
+
+ protected void createSubbands()
+ {
+ int i;
+ if (mode == Header.SINGLE_CHANNEL)
+ for (i = 0; i < num_subbands; ++i)
+ subbands[i] = new SubbandLayer2(i);
+ else if (mode == Header.JOINT_STEREO)
+ {
+ for (i = 0; i < header.intensity_stereo_bound(); ++i)
+ subbands[i] = new SubbandLayer2Stereo(i);
+ for (; i < num_subbands; ++i)
+ subbands[i] = new SubbandLayer2IntensityStereo(i);
+ }
+ else
+ {
+ for (i = 0; i < num_subbands; ++i)
+ subbands[i] = new SubbandLayer2Stereo(i);
+ }
+
+ }
+
+ protected void readScaleFactorSelection()
+ {
+ for (int i = 0; i < num_subbands; ++i)
+ ((SubbandLayer2)subbands[i]).read_scalefactor_selection(stream, crc);
+ }
+
+
+
+ /**
+ * Class for layer II subbands in single channel mode.
+ */
+ static class SubbandLayer2 extends Subband
+ {
+ // this table contains 3 requantized samples for each legal codeword
+ // when grouped in 5 bits, i.e. 3 quantizationsteps per sample
+ public static final float grouping_5bits[] = new float[]
+ {
+ -2.0f/3.0f, -2.0f/3.0f, -2.0f/3.0f,
+ 0.0f, -2.0f/3.0f, -2.0f/3.0f,
+ 2.0f/3.0f, -2.0f/3.0f, -2.0f/3.0f,
+ -2.0f/3.0f, 0.0f, -2.0f/3.0f,
+ 0.0f, 0.0f, -2.0f/3.0f,
+ 2.0f/3.0f, 0.0f, -2.0f/3.0f,
+ -2.0f/3.0f, 2.0f/3.0f, -2.0f/3.0f,
+ 0.0f, 2.0f/3.0f, -2.0f/3.0f,
+ 2.0f/3.0f, 2.0f/3.0f, -2.0f/3.0f,
+ -2.0f/3.0f, -2.0f/3.0f, 0.0f,
+ 0.0f, -2.0f/3.0f, 0.0f,
+ 2.0f/3.0f, -2.0f/3.0f, 0.0f,
+ -2.0f/3.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f,
+ 2.0f/3.0f, 0.0f, 0.0f,
+ -2.0f/3.0f, 2.0f/3.0f, 0.0f,
+ 0.0f, 2.0f/3.0f, 0.0f,
+ 2.0f/3.0f, 2.0f/3.0f, 0.0f,
+ -2.0f/3.0f, -2.0f/3.0f, 2.0f/3.0f,
+ 0.0f, -2.0f/3.0f, 2.0f/3.0f,
+ 2.0f/3.0f, -2.0f/3.0f, 2.0f/3.0f,
+ -2.0f/3.0f, 0.0f, 2.0f/3.0f,
+ 0.0f, 0.0f, 2.0f/3.0f,
+ 2.0f/3.0f, 0.0f, 2.0f/3.0f,
+ -2.0f/3.0f, 2.0f/3.0f, 2.0f/3.0f,
+ 0.0f, 2.0f/3.0f, 2.0f/3.0f,
+ 2.0f/3.0f, 2.0f/3.0f, 2.0f/3.0f
+ };
+
+ // this table contains 3 requantized samples for each legal codeword
+ // when grouped in 7 bits, i.e. 5 quantizationsteps per sample
+ public static final float grouping_7bits[] = new float[]
+ {
+ -0.8f, -0.8f, -0.8f, -0.4f, -0.8f, -0.8f, 0.0f, -0.8f, -0.8f, 0.4f, -0.8f, -0.8f, 0.8f, -0.8f, -0.8f,
+ -0.8f, -0.4f, -0.8f, -0.4f, -0.4f, -0.8f, 0.0f, -0.4f, -0.8f, 0.4f, -0.4f, -0.8f, 0.8f, -0.4f, -0.8f,
+ -0.8f, 0.0f, -0.8f, -0.4f, 0.0f, -0.8f, 0.0f, 0.0f, -0.8f, 0.4f, 0.0f, -0.8f, 0.8f, 0.0f, -0.8f,
+ -0.8f, 0.4f, -0.8f, -0.4f, 0.4f, -0.8f, 0.0f, 0.4f, -0.8f, 0.4f, 0.4f, -0.8f, 0.8f, 0.4f, -0.8f,
+ -0.8f, 0.8f, -0.8f, -0.4f, 0.8f, -0.8f, 0.0f, 0.8f, -0.8f, 0.4f, 0.8f, -0.8f, 0.8f, 0.8f, -0.8f,
+ -0.8f, -0.8f, -0.4f, -0.4f, -0.8f, -0.4f, 0.0f, -0.8f, -0.4f, 0.4f, -0.8f, -0.4f, 0.8f, -0.8f, -0.4f,
+ -0.8f, -0.4f, -0.4f, -0.4f, -0.4f, -0.4f, 0.0f, -0.4f, -0.4f, 0.4f, -0.4f, -0.4f, 0.8f, -0.4f, -0.4f,
+ -0.8f, 0.0f, -0.4f, -0.4f, 0.0f, -0.4f, 0.0f, 0.0f, -0.4f, 0.4f, 0.0f, -0.4f, 0.8f, 0.0f, -0.4f,
+ -0.8f, 0.4f, -0.4f, -0.4f, 0.4f, -0.4f, 0.0f, 0.4f, -0.4f, 0.4f, 0.4f, -0.4f, 0.8f, 0.4f, -0.4f,
+ -0.8f, 0.8f, -0.4f, -0.4f, 0.8f, -0.4f, 0.0f, 0.8f, -0.4f, 0.4f, 0.8f, -0.4f, 0.8f, 0.8f, -0.4f,
+ -0.8f, -0.8f, 0.0f, -0.4f, -0.8f, 0.0f, 0.0f, -0.8f, 0.0f, 0.4f, -0.8f, 0.0f, 0.8f, -0.8f, 0.0f,
+ -0.8f, -0.4f, 0.0f, -0.4f, -0.4f, 0.0f, 0.0f, -0.4f, 0.0f, 0.4f, -0.4f, 0.0f, 0.8f, -0.4f, 0.0f,
+ -0.8f, 0.0f, 0.0f, -0.4f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.4f, 0.0f, 0.0f, 0.8f, 0.0f, 0.0f,
+ -0.8f, 0.4f, 0.0f, -0.4f, 0.4f, 0.0f, 0.0f, 0.4f, 0.0f, 0.4f, 0.4f, 0.0f, 0.8f, 0.4f, 0.0f,
+ -0.8f, 0.8f, 0.0f, -0.4f, 0.8f, 0.0f, 0.0f, 0.8f, 0.0f, 0.4f, 0.8f, 0.0f, 0.8f, 0.8f, 0.0f,
+ -0.8f, -0.8f, 0.4f, -0.4f, -0.8f, 0.4f, 0.0f, -0.8f, 0.4f, 0.4f, -0.8f, 0.4f, 0.8f, -0.8f, 0.4f,
+ -0.8f, -0.4f, 0.4f, -0.4f, -0.4f, 0.4f, 0.0f, -0.4f, 0.4f, 0.4f, -0.4f, 0.4f, 0.8f, -0.4f, 0.4f,
+ -0.8f, 0.0f, 0.4f, -0.4f, 0.0f, 0.4f, 0.0f, 0.0f, 0.4f, 0.4f, 0.0f, 0.4f, 0.8f, 0.0f, 0.4f,
+ -0.8f, 0.4f, 0.4f, -0.4f, 0.4f, 0.4f, 0.0f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.8f, 0.4f, 0.4f,
+ -0.8f, 0.8f, 0.4f, -0.4f, 0.8f, 0.4f, 0.0f, 0.8f, 0.4f, 0.4f, 0.8f, 0.4f, 0.8f, 0.8f, 0.4f,
+ -0.8f, -0.8f, 0.8f, -0.4f, -0.8f, 0.8f, 0.0f, -0.8f, 0.8f, 0.4f, -0.8f, 0.8f, 0.8f, -0.8f, 0.8f,
+ -0.8f, -0.4f, 0.8f, -0.4f, -0.4f, 0.8f, 0.0f, -0.4f, 0.8f, 0.4f, -0.4f, 0.8f, 0.8f, -0.4f, 0.8f,
+ -0.8f, 0.0f, 0.8f, -0.4f, 0.0f, 0.8f, 0.0f, 0.0f, 0.8f, 0.4f, 0.0f, 0.8f, 0.8f, 0.0f, 0.8f,
+ -0.8f, 0.4f, 0.8f, -0.4f, 0.4f, 0.8f, 0.0f, 0.4f, 0.8f, 0.4f, 0.4f, 0.8f, 0.8f, 0.4f, 0.8f,
+ -0.8f, 0.8f, 0.8f, -0.4f, 0.8f, 0.8f, 0.0f, 0.8f, 0.8f, 0.4f, 0.8f, 0.8f, 0.8f, 0.8f, 0.8f
+ };
+
+ // this table contains 3 requantized samples for each legal codeword
+ // when grouped in 10 bits, i.e. 9 quantizationsteps per sample
+ public static final float grouping_10bits[] =
+ {
+ -8.0f/9.0f, -8.0f/9.0f, -8.0f/9.0f, -6.0f/9.0f, -8.0f/9.0f, -8.0f/9.0f, -4.0f/9.0f, -8.0f/9.0f, -8.0f/9.0f,
+ -2.0f/9.0f, -8.0f/9.0f, -8.0f/9.0f, 0.0f, -8.0f/9.0f, -8.0f/9.0f, 2.0f/9.0f, -8.0f/9.0f, -8.0f/9.0f,
+ 4.0f/9.0f, -8.0f/9.0f, -8.0f/9.0f, 6.0f/9.0f, -8.0f/9.0f, -8.0f/9.0f, 8.0f/9.0f, -8.0f/9.0f, -8.0f/9.0f,
+ -8.0f/9.0f, -6.0f/9.0f, -8.0f/9.0f, -6.0f/9.0f, -6.0f/9.0f, -8.0f/9.0f, -4.0f/9.0f, -6.0f/9.0f, -8.0f/9.0f,
+ -2.0f/9.0f, -6.0f/9.0f, -8.0f/9.0f, 0.0f, -6.0f/9.0f, -8.0f/9.0f, 2.0f/9.0f, -6.0f/9.0f, -8.0f/9.0f,
+ 4.0f/9.0f, -6.0f/9.0f, -8.0f/9.0f, 6.0f/9.0f, -6.0f/9.0f, -8.0f/9.0f, 8.0f/9.0f, -6.0f/9.0f, -8.0f/9.0f,
+ -8.0f/9.0f, -4.0f/9.0f, -8.0f/9.0f, -6.0f/9.0f, -4.0f/9.0f, -8.0f/9.0f, -4.0f/9.0f, -4.0f/9.0f, -8.0f/9.0f,
+ -2.0f/9.0f, -4.0f/9.0f, -8.0f/9.0f, 0.0f, -4.0f/9.0f, -8.0f/9.0f, 2.0f/9.0f, -4.0f/9.0f, -8.0f/9.0f,
+ 4.0f/9.0f, -4.0f/9.0f, -8.0f/9.0f, 6.0f/9.0f, -4.0f/9.0f, -8.0f/9.0f, 8.0f/9.0f, -4.0f/9.0f, -8.0f/9.0f,
+ -8.0f/9.0f, -2.0f/9.0f, -8.0f/9.0f, -6.0f/9.0f, -2.0f/9.0f, -8.0f/9.0f, -4.0f/9.0f, -2.0f/9.0f, -8.0f/9.0f,
+ -2.0f/9.0f, -2.0f/9.0f, -8.0f/9.0f, 0.0f, -2.0f/9.0f, -8.0f/9.0f, 2.0f/9.0f, -2.0f/9.0f, -8.0f/9.0f,
+ 4.0f/9.0f, -2.0f/9.0f, -8.0f/9.0f, 6.0f/9.0f, -2.0f/9.0f, -8.0f/9.0f, 8.0f/9.0f, -2.0f/9.0f, -8.0f/9.0f,
+ -8.0f/9.0f, 0.0f, -8.0f/9.0f, -6.0f/9.0f, 0.0f, -8.0f/9.0f, -4.0f/9.0f, 0.0f, -8.0f/9.0f,
+ -2.0f/9.0f, 0.0f, -8.0f/9.0f, 0.0f, 0.0f, -8.0f/9.0f, 2.0f/9.0f, 0.0f, -8.0f/9.0f,
+ 4.0f/9.0f, 0.0f, -8.0f/9.0f, 6.0f/9.0f, 0.0f, -8.0f/9.0f, 8.0f/9.0f, 0.0f, -8.0f/9.0f,
+ -8.0f/9.0f, 2.0f/9.0f, -8.0f/9.0f, -6.0f/9.0f, 2.0f/9.0f, -8.0f/9.0f, -4.0f/9.0f, 2.0f/9.0f, -8.0f/9.0f,
+ -2.0f/9.0f, 2.0f/9.0f, -8.0f/9.0f, 0.0f, 2.0f/9.0f, -8.0f/9.0f, 2.0f/9.0f, 2.0f/9.0f, -8.0f/9.0f,
+ 4.0f/9.0f, 2.0f/9.0f, -8.0f/9.0f, 6.0f/9.0f, 2.0f/9.0f, -8.0f/9.0f, 8.0f/9.0f, 2.0f/9.0f, -8.0f/9.0f,
+ -8.0f/9.0f, 4.0f/9.0f, -8.0f/9.0f, -6.0f/9.0f, 4.0f/9.0f, -8.0f/9.0f, -4.0f/9.0f, 4.0f/9.0f, -8.0f/9.0f,
+ -2.0f/9.0f, 4.0f/9.0f, -8.0f/9.0f, 0.0f, 4.0f/9.0f, -8.0f/9.0f, 2.0f/9.0f, 4.0f/9.0f, -8.0f/9.0f,
+ 4.0f/9.0f, 4.0f/9.0f, -8.0f/9.0f, 6.0f/9.0f, 4.0f/9.0f, -8.0f/9.0f, 8.0f/9.0f, 4.0f/9.0f, -8.0f/9.0f,
+ -8.0f/9.0f, 6.0f/9.0f, -8.0f/9.0f, -6.0f/9.0f, 6.0f/9.0f, -8.0f/9.0f, -4.0f/9.0f, 6.0f/9.0f, -8.0f/9.0f,
+ -2.0f/9.0f, 6.0f/9.0f, -8.0f/9.0f, 0.0f, 6.0f/9.0f, -8.0f/9.0f, 2.0f/9.0f, 6.0f/9.0f, -8.0f/9.0f,
+ 4.0f/9.0f, 6.0f/9.0f, -8.0f/9.0f, 6.0f/9.0f, 6.0f/9.0f, -8.0f/9.0f, 8.0f/9.0f, 6.0f/9.0f, -8.0f/9.0f,
+ -8.0f/9.0f, 8.0f/9.0f, -8.0f/9.0f, -6.0f/9.0f, 8.0f/9.0f, -8.0f/9.0f, -4.0f/9.0f, 8.0f/9.0f, -8.0f/9.0f,
+ -2.0f/9.0f, 8.0f/9.0f, -8.0f/9.0f, 0.0f, 8.0f/9.0f, -8.0f/9.0f, 2.0f/9.0f, 8.0f/9.0f, -8.0f/9.0f,
+ 4.0f/9.0f, 8.0f/9.0f, -8.0f/9.0f, 6.0f/9.0f, 8.0f/9.0f, -8.0f/9.0f, 8.0f/9.0f, 8.0f/9.0f, -8.0f/9.0f,
+ -8.0f/9.0f, -8.0f/9.0f, -6.0f/9.0f, -6.0f/9.0f, -8.0f/9.0f, -6.0f/9.0f, -4.0f/9.0f, -8.0f/9.0f, -6.0f/9.0f,
+ -2.0f/9.0f, -8.0f/9.0f, -6.0f/9.0f, 0.0f, -8.0f/9.0f, -6.0f/9.0f, 2.0f/9.0f, -8.0f/9.0f, -6.0f/9.0f,
+ 4.0f/9.0f, -8.0f/9.0f, -6.0f/9.0f, 6.0f/9.0f, -8.0f/9.0f, -6.0f/9.0f, 8.0f/9.0f, -8.0f/9.0f, -6.0f/9.0f,
+ -8.0f/9.0f, -6.0f/9.0f, -6.0f/9.0f, -6.0f/9.0f, -6.0f/9.0f, -6.0f/9.0f, -4.0f/9.0f, -6.0f/9.0f, -6.0f/9.0f,
+ -2.0f/9.0f, -6.0f/9.0f, -6.0f/9.0f, 0.0f, -6.0f/9.0f, -6.0f/9.0f, 2.0f/9.0f, -6.0f/9.0f, -6.0f/9.0f,
+ 4.0f/9.0f, -6.0f/9.0f, -6.0f/9.0f, 6.0f/9.0f, -6.0f/9.0f, -6.0f/9.0f, 8.0f/9.0f, -6.0f/9.0f, -6.0f/9.0f,
+ -8.0f/9.0f, -4.0f/9.0f, -6.0f/9.0f, -6.0f/9.0f, -4.0f/9.0f, -6.0f/9.0f, -4.0f/9.0f, -4.0f/9.0f, -6.0f/9.0f,
+ -2.0f/9.0f, -4.0f/9.0f, -6.0f/9.0f, 0.0f, -4.0f/9.0f, -6.0f/9.0f, 2.0f/9.0f, -4.0f/9.0f, -6.0f/9.0f,
+ 4.0f/9.0f, -4.0f/9.0f, -6.0f/9.0f, 6.0f/9.0f, -4.0f/9.0f, -6.0f/9.0f, 8.0f/9.0f, -4.0f/9.0f, -6.0f/9.0f,
+ -8.0f/9.0f, -2.0f/9.0f, -6.0f/9.0f, -6.0f/9.0f, -2.0f/9.0f, -6.0f/9.0f, -4.0f/9.0f, -2.0f/9.0f, -6.0f/9.0f,
+ -2.0f/9.0f, -2.0f/9.0f, -6.0f/9.0f, 0.0f, -2.0f/9.0f, -6.0f/9.0f, 2.0f/9.0f, -2.0f/9.0f, -6.0f/9.0f,
+ 4.0f/9.0f, -2.0f/9.0f, -6.0f/9.0f, 6.0f/9.0f, -2.0f/9.0f, -6.0f/9.0f, 8.0f/9.0f, -2.0f/9.0f, -6.0f/9.0f,
+ -8.0f/9.0f, 0.0f, -6.0f/9.0f, -6.0f/9.0f, 0.0f, -6.0f/9.0f, -4.0f/9.0f, 0.0f, -6.0f/9.0f,
+ -2.0f/9.0f, 0.0f, -6.0f/9.0f, 0.0f, 0.0f, -6.0f/9.0f, 2.0f/9.0f, 0.0f, -6.0f/9.0f,
+ 4.0f/9.0f, 0.0f, -6.0f/9.0f, 6.0f/9.0f, 0.0f, -6.0f/9.0f, 8.0f/9.0f, 0.0f, -6.0f/9.0f,
+ -8.0f/9.0f, 2.0f/9.0f, -6.0f/9.0f, -6.0f/9.0f, 2.0f/9.0f, -6.0f/9.0f, -4.0f/9.0f, 2.0f/9.0f, -6.0f/9.0f,
+ -2.0f/9.0f, 2.0f/9.0f, -6.0f/9.0f, 0.0f, 2.0f/9.0f, -6.0f/9.0f, 2.0f/9.0f, 2.0f/9.0f, -6.0f/9.0f,
+ 4.0f/9.0f, 2.0f/9.0f, -6.0f/9.0f, 6.0f/9.0f, 2.0f/9.0f, -6.0f/9.0f, 8.0f/9.0f, 2.0f/9.0f, -6.0f/9.0f,
+ -8.0f/9.0f, 4.0f/9.0f, -6.0f/9.0f, -6.0f/9.0f, 4.0f/9.0f, -6.0f/9.0f, -4.0f/9.0f, 4.0f/9.0f, -6.0f/9.0f,
+ -2.0f/9.0f, 4.0f/9.0f, -6.0f/9.0f, 0.0f, 4.0f/9.0f, -6.0f/9.0f, 2.0f/9.0f, 4.0f/9.0f, -6.0f/9.0f,
+ 4.0f/9.0f, 4.0f/9.0f, -6.0f/9.0f, 6.0f/9.0f, 4.0f/9.0f, -6.0f/9.0f, 8.0f/9.0f, 4.0f/9.0f, -6.0f/9.0f,
+ -8.0f/9.0f, 6.0f/9.0f, -6.0f/9.0f, -6.0f/9.0f, 6.0f/9.0f, -6.0f/9.0f, -4.0f/9.0f, 6.0f/9.0f, -6.0f/9.0f,
+ -2.0f/9.0f, 6.0f/9.0f, -6.0f/9.0f, 0.0f, 6.0f/9.0f, -6.0f/9.0f, 2.0f/9.0f, 6.0f/9.0f, -6.0f/9.0f,
+ 4.0f/9.0f, 6.0f/9.0f, -6.0f/9.0f, 6.0f/9.0f, 6.0f/9.0f, -6.0f/9.0f, 8.0f/9.0f, 6.0f/9.0f, -6.0f/9.0f,
+ -8.0f/9.0f, 8.0f/9.0f, -6.0f/9.0f, -6.0f/9.0f, 8.0f/9.0f, -6.0f/9.0f, -4.0f/9.0f, 8.0f/9.0f, -6.0f/9.0f,
+ -2.0f/9.0f, 8.0f/9.0f, -6.0f/9.0f, 0.0f, 8.0f/9.0f, -6.0f/9.0f, 2.0f/9.0f, 8.0f/9.0f, -6.0f/9.0f,
+ 4.0f/9.0f, 8.0f/9.0f, -6.0f/9.0f, 6.0f/9.0f, 8.0f/9.0f, -6.0f/9.0f, 8.0f/9.0f, 8.0f/9.0f, -6.0f/9.0f,
+ -8.0f/9.0f, -8.0f/9.0f, -4.0f/9.0f, -6.0f/9.0f, -8.0f/9.0f, -4.0f/9.0f, -4.0f/9.0f, -8.0f/9.0f, -4.0f/9.0f,
+ -2.0f/9.0f, -8.0f/9.0f, -4.0f/9.0f, 0.0f, -8.0f/9.0f, -4.0f/9.0f, 2.0f/9.0f, -8.0f/9.0f, -4.0f/9.0f,
+ 4.0f/9.0f, -8.0f/9.0f, -4.0f/9.0f, 6.0f/9.0f, -8.0f/9.0f, -4.0f/9.0f, 8.0f/9.0f, -8.0f/9.0f, -4.0f/9.0f,
+ -8.0f/9.0f, -6.0f/9.0f, -4.0f/9.0f, -6.0f/9.0f, -6.0f/9.0f, -4.0f/9.0f, -4.0f/9.0f, -6.0f/9.0f, -4.0f/9.0f,
+ -2.0f/9.0f, -6.0f/9.0f, -4.0f/9.0f, 0.0f, -6.0f/9.0f, -4.0f/9.0f, 2.0f/9.0f, -6.0f/9.0f, -4.0f/9.0f,
+ 4.0f/9.0f, -6.0f/9.0f, -4.0f/9.0f, 6.0f/9.0f, -6.0f/9.0f, -4.0f/9.0f, 8.0f/9.0f, -6.0f/9.0f, -4.0f/9.0f,
+ -8.0f/9.0f, -4.0f/9.0f, -4.0f/9.0f, -6.0f/9.0f, -4.0f/9.0f, -4.0f/9.0f, -4.0f/9.0f, -4.0f/9.0f, -4.0f/9.0f,
+ -2.0f/9.0f, -4.0f/9.0f, -4.0f/9.0f, 0.0f, -4.0f/9.0f, -4.0f/9.0f, 2.0f/9.0f, -4.0f/9.0f, -4.0f/9.0f,
+ 4.0f/9.0f, -4.0f/9.0f, -4.0f/9.0f, 6.0f/9.0f, -4.0f/9.0f, -4.0f/9.0f, 8.0f/9.0f, -4.0f/9.0f, -4.0f/9.0f,
+ -8.0f/9.0f, -2.0f/9.0f, -4.0f/9.0f, -6.0f/9.0f, -2.0f/9.0f, -4.0f/9.0f, -4.0f/9.0f, -2.0f/9.0f, -4.0f/9.0f,
+ -2.0f/9.0f, -2.0f/9.0f, -4.0f/9.0f, 0.0f, -2.0f/9.0f, -4.0f/9.0f, 2.0f/9.0f, -2.0f/9.0f, -4.0f/9.0f,
+ 4.0f/9.0f, -2.0f/9.0f, -4.0f/9.0f, 6.0f/9.0f, -2.0f/9.0f, -4.0f/9.0f, 8.0f/9.0f, -2.0f/9.0f, -4.0f/9.0f,
+ -8.0f/9.0f, 0.0f, -4.0f/9.0f, -6.0f/9.0f, 0.0f, -4.0f/9.0f, -4.0f/9.0f, 0.0f, -4.0f/9.0f,
+ -2.0f/9.0f, 0.0f, -4.0f/9.0f, 0.0f, 0.0f, -4.0f/9.0f, 2.0f/9.0f, 0.0f, -4.0f/9.0f,
+ 4.0f/9.0f, 0.0f, -4.0f/9.0f, 6.0f/9.0f, 0.0f, -4.0f/9.0f, 8.0f/9.0f, 0.0f, -4.0f/9.0f,
+ -8.0f/9.0f, 2.0f/9.0f, -4.0f/9.0f, -6.0f/9.0f, 2.0f/9.0f, -4.0f/9.0f, -4.0f/9.0f, 2.0f/9.0f, -4.0f/9.0f,
+ -2.0f/9.0f, 2.0f/9.0f, -4.0f/9.0f, 0.0f, 2.0f/9.0f, -4.0f/9.0f, 2.0f/9.0f, 2.0f/9.0f, -4.0f/9.0f,
+ 4.0f/9.0f, 2.0f/9.0f, -4.0f/9.0f, 6.0f/9.0f, 2.0f/9.0f, -4.0f/9.0f, 8.0f/9.0f, 2.0f/9.0f, -4.0f/9.0f,
+ -8.0f/9.0f, 4.0f/9.0f, -4.0f/9.0f, -6.0f/9.0f, 4.0f/9.0f, -4.0f/9.0f, -4.0f/9.0f, 4.0f/9.0f, -4.0f/9.0f,
+ -2.0f/9.0f, 4.0f/9.0f, -4.0f/9.0f, 0.0f, 4.0f/9.0f, -4.0f/9.0f, 2.0f/9.0f, 4.0f/9.0f, -4.0f/9.0f,
+ 4.0f/9.0f, 4.0f/9.0f, -4.0f/9.0f, 6.0f/9.0f, 4.0f/9.0f, -4.0f/9.0f, 8.0f/9.0f, 4.0f/9.0f, -4.0f/9.0f,
+ -8.0f/9.0f, 6.0f/9.0f, -4.0f/9.0f, -6.0f/9.0f, 6.0f/9.0f, -4.0f/9.0f, -4.0f/9.0f, 6.0f/9.0f, -4.0f/9.0f,
+ -2.0f/9.0f, 6.0f/9.0f, -4.0f/9.0f, 0.0f, 6.0f/9.0f, -4.0f/9.0f, 2.0f/9.0f, 6.0f/9.0f, -4.0f/9.0f,
+ 4.0f/9.0f, 6.0f/9.0f, -4.0f/9.0f, 6.0f/9.0f, 6.0f/9.0f, -4.0f/9.0f, 8.0f/9.0f, 6.0f/9.0f, -4.0f/9.0f,
+ -8.0f/9.0f, 8.0f/9.0f, -4.0f/9.0f, -6.0f/9.0f, 8.0f/9.0f, -4.0f/9.0f, -4.0f/9.0f, 8.0f/9.0f, -4.0f/9.0f,
+ -2.0f/9.0f, 8.0f/9.0f, -4.0f/9.0f, 0.0f, 8.0f/9.0f, -4.0f/9.0f, 2.0f/9.0f, 8.0f/9.0f, -4.0f/9.0f,
+ 4.0f/9.0f, 8.0f/9.0f, -4.0f/9.0f, 6.0f/9.0f, 8.0f/9.0f, -4.0f/9.0f, 8.0f/9.0f, 8.0f/9.0f, -4.0f/9.0f,
+ -8.0f/9.0f, -8.0f/9.0f, -2.0f/9.0f, -6.0f/9.0f, -8.0f/9.0f, -2.0f/9.0f, -4.0f/9.0f, -8.0f/9.0f, -2.0f/9.0f,
+ -2.0f/9.0f, -8.0f/9.0f, -2.0f/9.0f, 0.0f, -8.0f/9.0f, -2.0f/9.0f, 2.0f/9.0f, -8.0f/9.0f, -2.0f/9.0f,
+ 4.0f/9.0f, -8.0f/9.0f, -2.0f/9.0f, 6.0f/9.0f, -8.0f/9.0f, -2.0f/9.0f, 8.0f/9.0f, -8.0f/9.0f, -2.0f/9.0f,
+ -8.0f/9.0f, -6.0f/9.0f, -2.0f/9.0f, -6.0f/9.0f, -6.0f/9.0f, -2.0f/9.0f, -4.0f/9.0f, -6.0f/9.0f, -2.0f/9.0f,
+ -2.0f/9.0f, -6.0f/9.0f, -2.0f/9.0f, 0.0f, -6.0f/9.0f, -2.0f/9.0f, 2.0f/9.0f, -6.0f/9.0f, -2.0f/9.0f,
+ 4.0f/9.0f, -6.0f/9.0f, -2.0f/9.0f, 6.0f/9.0f, -6.0f/9.0f, -2.0f/9.0f, 8.0f/9.0f, -6.0f/9.0f, -2.0f/9.0f,
+ -8.0f/9.0f, -4.0f/9.0f, -2.0f/9.0f, -6.0f/9.0f, -4.0f/9.0f, -2.0f/9.0f, -4.0f/9.0f, -4.0f/9.0f, -2.0f/9.0f,
+ -2.0f/9.0f, -4.0f/9.0f, -2.0f/9.0f, 0.0f, -4.0f/9.0f, -2.0f/9.0f, 2.0f/9.0f, -4.0f/9.0f, -2.0f/9.0f,
+ 4.0f/9.0f, -4.0f/9.0f, -2.0f/9.0f, 6.0f/9.0f, -4.0f/9.0f, -2.0f/9.0f, 8.0f/9.0f, -4.0f/9.0f, -2.0f/9.0f,
+ -8.0f/9.0f, -2.0f/9.0f, -2.0f/9.0f, -6.0f/9.0f, -2.0f/9.0f, -2.0f/9.0f, -4.0f/9.0f, -2.0f/9.0f, -2.0f/9.0f,
+ -2.0f/9.0f, -2.0f/9.0f, -2.0f/9.0f, 0.0f, -2.0f/9.0f, -2.0f/9.0f, 2.0f/9.0f, -2.0f/9.0f, -2.0f/9.0f,
+ 4.0f/9.0f, -2.0f/9.0f, -2.0f/9.0f, 6.0f/9.0f, -2.0f/9.0f, -2.0f/9.0f, 8.0f/9.0f, -2.0f/9.0f, -2.0f/9.0f,
+ -8.0f/9.0f, 0.0f, -2.0f/9.0f, -6.0f/9.0f, 0.0f, -2.0f/9.0f, -4.0f/9.0f, 0.0f, -2.0f/9.0f,
+ -2.0f/9.0f, 0.0f, -2.0f/9.0f, 0.0f, 0.0f, -2.0f/9.0f, 2.0f/9.0f, 0.0f, -2.0f/9.0f,
+ 4.0f/9.0f, 0.0f, -2.0f/9.0f, 6.0f/9.0f, 0.0f, -2.0f/9.0f, 8.0f/9.0f, 0.0f, -2.0f/9.0f,
+ -8.0f/9.0f, 2.0f/9.0f, -2.0f/9.0f, -6.0f/9.0f, 2.0f/9.0f, -2.0f/9.0f, -4.0f/9.0f, 2.0f/9.0f, -2.0f/9.0f,
+ -2.0f/9.0f, 2.0f/9.0f, -2.0f/9.0f, 0.0f, 2.0f/9.0f, -2.0f/9.0f, 2.0f/9.0f, 2.0f/9.0f, -2.0f/9.0f,
+ 4.0f/9.0f, 2.0f/9.0f, -2.0f/9.0f, 6.0f/9.0f, 2.0f/9.0f, -2.0f/9.0f, 8.0f/9.0f, 2.0f/9.0f, -2.0f/9.0f,
+ -8.0f/9.0f, 4.0f/9.0f, -2.0f/9.0f, -6.0f/9.0f, 4.0f/9.0f, -2.0f/9.0f, -4.0f/9.0f, 4.0f/9.0f, -2.0f/9.0f,
+ -2.0f/9.0f, 4.0f/9.0f, -2.0f/9.0f, 0.0f, 4.0f/9.0f, -2.0f/9.0f, 2.0f/9.0f, 4.0f/9.0f, -2.0f/9.0f,
+ 4.0f/9.0f, 4.0f/9.0f, -2.0f/9.0f, 6.0f/9.0f, 4.0f/9.0f, -2.0f/9.0f, 8.0f/9.0f, 4.0f/9.0f, -2.0f/9.0f,
+ -8.0f/9.0f, 6.0f/9.0f, -2.0f/9.0f, -6.0f/9.0f, 6.0f/9.0f, -2.0f/9.0f, -4.0f/9.0f, 6.0f/9.0f, -2.0f/9.0f,
+ -2.0f/9.0f, 6.0f/9.0f, -2.0f/9.0f, 0.0f, 6.0f/9.0f, -2.0f/9.0f, 2.0f/9.0f, 6.0f/9.0f, -2.0f/9.0f,
+ 4.0f/9.0f, 6.0f/9.0f, -2.0f/9.0f, 6.0f/9.0f, 6.0f/9.0f, -2.0f/9.0f, 8.0f/9.0f, 6.0f/9.0f, -2.0f/9.0f,
+ -8.0f/9.0f, 8.0f/9.0f, -2.0f/9.0f, -6.0f/9.0f, 8.0f/9.0f, -2.0f/9.0f, -4.0f/9.0f, 8.0f/9.0f, -2.0f/9.0f,
+ -2.0f/9.0f, 8.0f/9.0f, -2.0f/9.0f, 0.0f, 8.0f/9.0f, -2.0f/9.0f, 2.0f/9.0f, 8.0f/9.0f, -2.0f/9.0f,
+ 4.0f/9.0f, 8.0f/9.0f, -2.0f/9.0f, 6.0f/9.0f, 8.0f/9.0f, -2.0f/9.0f, 8.0f/9.0f, 8.0f/9.0f, -2.0f/9.0f,
+ -8.0f/9.0f, -8.0f/9.0f, 0.0f, -6.0f/9.0f, -8.0f/9.0f, 0.0f, -4.0f/9.0f, -8.0f/9.0f, 0.0f,
+ -2.0f/9.0f, -8.0f/9.0f, 0.0f, 0.0f, -8.0f/9.0f, 0.0f, 2.0f/9.0f, -8.0f/9.0f, 0.0f,
+ 4.0f/9.0f, -8.0f/9.0f, 0.0f, 6.0f/9.0f, -8.0f/9.0f, 0.0f, 8.0f/9.0f, -8.0f/9.0f, 0.0f,
+ -8.0f/9.0f, -6.0f/9.0f, 0.0f, -6.0f/9.0f, -6.0f/9.0f, 0.0f, -4.0f/9.0f, -6.0f/9.0f, 0.0f,
+ -2.0f/9.0f, -6.0f/9.0f, 0.0f, 0.0f, -6.0f/9.0f, 0.0f, 2.0f/9.0f, -6.0f/9.0f, 0.0f,
+ 4.0f/9.0f, -6.0f/9.0f, 0.0f, 6.0f/9.0f, -6.0f/9.0f, 0.0f, 8.0f/9.0f, -6.0f/9.0f, 0.0f,
+ -8.0f/9.0f, -4.0f/9.0f, 0.0f, -6.0f/9.0f, -4.0f/9.0f, 0.0f, -4.0f/9.0f, -4.0f/9.0f, 0.0f,
+ -2.0f/9.0f, -4.0f/9.0f, 0.0f, 0.0f, -4.0f/9.0f, 0.0f, 2.0f/9.0f, -4.0f/9.0f, 0.0f,
+ 4.0f/9.0f, -4.0f/9.0f, 0.0f, 6.0f/9.0f, -4.0f/9.0f, 0.0f, 8.0f/9.0f, -4.0f/9.0f, 0.0f,
+ -8.0f/9.0f, -2.0f/9.0f, 0.0f, -6.0f/9.0f, -2.0f/9.0f, 0.0f, -4.0f/9.0f, -2.0f/9.0f, 0.0f,
+ -2.0f/9.0f, -2.0f/9.0f, 0.0f, 0.0f, -2.0f/9.0f, 0.0f, 2.0f/9.0f, -2.0f/9.0f, 0.0f,
+ 4.0f/9.0f, -2.0f/9.0f, 0.0f, 6.0f/9.0f, -2.0f/9.0f, 0.0f, 8.0f/9.0f, -2.0f/9.0f, 0.0f,
+ -8.0f/9.0f, 0.0f, 0.0f, -6.0f/9.0f, 0.0f, 0.0f, -4.0f/9.0f, 0.0f, 0.0f,
+ -2.0f/9.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.0f/9.0f, 0.0f, 0.0f,
+ 4.0f/9.0f, 0.0f, 0.0f, 6.0f/9.0f, 0.0f, 0.0f, 8.0f/9.0f, 0.0f, 0.0f,
+ -8.0f/9.0f, 2.0f/9.0f, 0.0f, -6.0f/9.0f, 2.0f/9.0f, 0.0f, -4.0f/9.0f, 2.0f/9.0f, 0.0f,
+ -2.0f/9.0f, 2.0f/9.0f, 0.0f, 0.0f, 2.0f/9.0f, 0.0f, 2.0f/9.0f, 2.0f/9.0f, 0.0f,
+ 4.0f/9.0f, 2.0f/9.0f, 0.0f, 6.0f/9.0f, 2.0f/9.0f, 0.0f, 8.0f/9.0f, 2.0f/9.0f, 0.0f,
+ -8.0f/9.0f, 4.0f/9.0f, 0.0f, -6.0f/9.0f, 4.0f/9.0f, 0.0f, -4.0f/9.0f, 4.0f/9.0f, 0.0f,
+ -2.0f/9.0f, 4.0f/9.0f, 0.0f, 0.0f, 4.0f/9.0f, 0.0f, 2.0f/9.0f, 4.0f/9.0f, 0.0f,
+ 4.0f/9.0f, 4.0f/9.0f, 0.0f, 6.0f/9.0f, 4.0f/9.0f, 0.0f, 8.0f/9.0f, 4.0f/9.0f, 0.0f,
+ -8.0f/9.0f, 6.0f/9.0f, 0.0f, -6.0f/9.0f, 6.0f/9.0f, 0.0f, -4.0f/9.0f, 6.0f/9.0f, 0.0f,
+ -2.0f/9.0f, 6.0f/9.0f, 0.0f, 0.0f, 6.0f/9.0f, 0.0f, 2.0f/9.0f, 6.0f/9.0f, 0.0f,
+ 4.0f/9.0f, 6.0f/9.0f, 0.0f, 6.0f/9.0f, 6.0f/9.0f, 0.0f, 8.0f/9.0f, 6.0f/9.0f, 0.0f,
+ -8.0f/9.0f, 8.0f/9.0f, 0.0f, -6.0f/9.0f, 8.0f/9.0f, 0.0f, -4.0f/9.0f, 8.0f/9.0f, 0.0f,
+ -2.0f/9.0f, 8.0f/9.0f, 0.0f, 0.0f, 8.0f/9.0f, 0.0f, 2.0f/9.0f, 8.0f/9.0f, 0.0f,
+ 4.0f/9.0f, 8.0f/9.0f, 0.0f, 6.0f/9.0f, 8.0f/9.0f, 0.0f, 8.0f/9.0f, 8.0f/9.0f, 0.0f,
+ -8.0f/9.0f, -8.0f/9.0f, 2.0f/9.0f, -6.0f/9.0f, -8.0f/9.0f, 2.0f/9.0f, -4.0f/9.0f, -8.0f/9.0f, 2.0f/9.0f,
+ -2.0f/9.0f, -8.0f/9.0f, 2.0f/9.0f, 0.0f, -8.0f/9.0f, 2.0f/9.0f, 2.0f/9.0f, -8.0f/9.0f, 2.0f/9.0f,
+ 4.0f/9.0f, -8.0f/9.0f, 2.0f/9.0f, 6.0f/9.0f, -8.0f/9.0f, 2.0f/9.0f, 8.0f/9.0f, -8.0f/9.0f, 2.0f/9.0f,
+ -8.0f/9.0f, -6.0f/9.0f, 2.0f/9.0f, -6.0f/9.0f, -6.0f/9.0f, 2.0f/9.0f, -4.0f/9.0f, -6.0f/9.0f, 2.0f/9.0f,
+ -2.0f/9.0f, -6.0f/9.0f, 2.0f/9.0f, 0.0f, -6.0f/9.0f, 2.0f/9.0f, 2.0f/9.0f, -6.0f/9.0f, 2.0f/9.0f,
+ 4.0f/9.0f, -6.0f/9.0f, 2.0f/9.0f, 6.0f/9.0f, -6.0f/9.0f, 2.0f/9.0f, 8.0f/9.0f, -6.0f/9.0f, 2.0f/9.0f,
+ -8.0f/9.0f, -4.0f/9.0f, 2.0f/9.0f, -6.0f/9.0f, -4.0f/9.0f, 2.0f/9.0f, -4.0f/9.0f, -4.0f/9.0f, 2.0f/9.0f,
+ -2.0f/9.0f, -4.0f/9.0f, 2.0f/9.0f, 0.0f, -4.0f/9.0f, 2.0f/9.0f, 2.0f/9.0f, -4.0f/9.0f, 2.0f/9.0f,
+ 4.0f/9.0f, -4.0f/9.0f, 2.0f/9.0f, 6.0f/9.0f, -4.0f/9.0f, 2.0f/9.0f, 8.0f/9.0f, -4.0f/9.0f, 2.0f/9.0f,
+ -8.0f/9.0f, -2.0f/9.0f, 2.0f/9.0f, -6.0f/9.0f, -2.0f/9.0f, 2.0f/9.0f, -4.0f/9.0f, -2.0f/9.0f, 2.0f/9.0f,
+ -2.0f/9.0f, -2.0f/9.0f, 2.0f/9.0f, 0.0f, -2.0f/9.0f, 2.0f/9.0f, 2.0f/9.0f, -2.0f/9.0f, 2.0f/9.0f,
+ 4.0f/9.0f, -2.0f/9.0f, 2.0f/9.0f, 6.0f/9.0f, -2.0f/9.0f, 2.0f/9.0f, 8.0f/9.0f, -2.0f/9.0f, 2.0f/9.0f,
+ -8.0f/9.0f, 0.0f, 2.0f/9.0f, -6.0f/9.0f, 0.0f, 2.0f/9.0f, -4.0f/9.0f, 0.0f, 2.0f/9.0f,
+ -2.0f/9.0f, 0.0f, 2.0f/9.0f, 0.0f, 0.0f, 2.0f/9.0f, 2.0f/9.0f, 0.0f, 2.0f/9.0f,
+ 4.0f/9.0f, 0.0f, 2.0f/9.0f, 6.0f/9.0f, 0.0f, 2.0f/9.0f, 8.0f/9.0f, 0.0f, 2.0f/9.0f,
+ -8.0f/9.0f, 2.0f/9.0f, 2.0f/9.0f, -6.0f/9.0f, 2.0f/9.0f, 2.0f/9.0f, -4.0f/9.0f, 2.0f/9.0f, 2.0f/9.0f,
+ -2.0f/9.0f, 2.0f/9.0f, 2.0f/9.0f, 0.0f, 2.0f/9.0f, 2.0f/9.0f, 2.0f/9.0f, 2.0f/9.0f, 2.0f/9.0f,
+ 4.0f/9.0f, 2.0f/9.0f, 2.0f/9.0f, 6.0f/9.0f, 2.0f/9.0f, 2.0f/9.0f, 8.0f/9.0f, 2.0f/9.0f, 2.0f/9.0f,
+ -8.0f/9.0f, 4.0f/9.0f, 2.0f/9.0f, -6.0f/9.0f, 4.0f/9.0f, 2.0f/9.0f, -4.0f/9.0f, 4.0f/9.0f, 2.0f/9.0f,
+ -2.0f/9.0f, 4.0f/9.0f, 2.0f/9.0f, 0.0f, 4.0f/9.0f, 2.0f/9.0f, 2.0f/9.0f, 4.0f/9.0f, 2.0f/9.0f,
+ 4.0f/9.0f, 4.0f/9.0f, 2.0f/9.0f, 6.0f/9.0f, 4.0f/9.0f, 2.0f/9.0f, 8.0f/9.0f, 4.0f/9.0f, 2.0f/9.0f,
+ -8.0f/9.0f, 6.0f/9.0f, 2.0f/9.0f, -6.0f/9.0f, 6.0f/9.0f, 2.0f/9.0f, -4.0f/9.0f, 6.0f/9.0f, 2.0f/9.0f,
+ -2.0f/9.0f, 6.0f/9.0f, 2.0f/9.0f, 0.0f, 6.0f/9.0f, 2.0f/9.0f, 2.0f/9.0f, 6.0f/9.0f, 2.0f/9.0f,
+ 4.0f/9.0f, 6.0f/9.0f, 2.0f/9.0f, 6.0f/9.0f, 6.0f/9.0f, 2.0f/9.0f, 8.0f/9.0f, 6.0f/9.0f, 2.0f/9.0f,
+ -8.0f/9.0f, 8.0f/9.0f, 2.0f/9.0f, -6.0f/9.0f, 8.0f/9.0f, 2.0f/9.0f, -4.0f/9.0f, 8.0f/9.0f, 2.0f/9.0f,
+ -2.0f/9.0f, 8.0f/9.0f, 2.0f/9.0f, 0.0f, 8.0f/9.0f, 2.0f/9.0f, 2.0f/9.0f, 8.0f/9.0f, 2.0f/9.0f,
+ 4.0f/9.0f, 8.0f/9.0f, 2.0f/9.0f, 6.0f/9.0f, 8.0f/9.0f, 2.0f/9.0f, 8.0f/9.0f, 8.0f/9.0f, 2.0f/9.0f,
+ -8.0f/9.0f, -8.0f/9.0f, 4.0f/9.0f, -6.0f/9.0f, -8.0f/9.0f, 4.0f/9.0f, -4.0f/9.0f, -8.0f/9.0f, 4.0f/9.0f,
+ -2.0f/9.0f, -8.0f/9.0f, 4.0f/9.0f, 0.0f, -8.0f/9.0f, 4.0f/9.0f, 2.0f/9.0f, -8.0f/9.0f, 4.0f/9.0f,
+ 4.0f/9.0f, -8.0f/9.0f, 4.0f/9.0f, 6.0f/9.0f, -8.0f/9.0f, 4.0f/9.0f, 8.0f/9.0f, -8.0f/9.0f, 4.0f/9.0f,
+ -8.0f/9.0f, -6.0f/9.0f, 4.0f/9.0f, -6.0f/9.0f, -6.0f/9.0f, 4.0f/9.0f, -4.0f/9.0f, -6.0f/9.0f, 4.0f/9.0f,
+ -2.0f/9.0f, -6.0f/9.0f, 4.0f/9.0f, 0.0f, -6.0f/9.0f, 4.0f/9.0f, 2.0f/9.0f, -6.0f/9.0f, 4.0f/9.0f,
+ 4.0f/9.0f, -6.0f/9.0f, 4.0f/9.0f, 6.0f/9.0f, -6.0f/9.0f, 4.0f/9.0f, 8.0f/9.0f, -6.0f/9.0f, 4.0f/9.0f,
+ -8.0f/9.0f, -4.0f/9.0f, 4.0f/9.0f, -6.0f/9.0f, -4.0f/9.0f, 4.0f/9.0f, -4.0f/9.0f, -4.0f/9.0f, 4.0f/9.0f,
+ -2.0f/9.0f, -4.0f/9.0f, 4.0f/9.0f, 0.0f, -4.0f/9.0f, 4.0f/9.0f, 2.0f/9.0f, -4.0f/9.0f, 4.0f/9.0f,
+ 4.0f/9.0f, -4.0f/9.0f, 4.0f/9.0f, 6.0f/9.0f, -4.0f/9.0f, 4.0f/9.0f, 8.0f/9.0f, -4.0f/9.0f, 4.0f/9.0f,
+ -8.0f/9.0f, -2.0f/9.0f, 4.0f/9.0f, -6.0f/9.0f, -2.0f/9.0f, 4.0f/9.0f, -4.0f/9.0f, -2.0f/9.0f, 4.0f/9.0f,
+ -2.0f/9.0f, -2.0f/9.0f, 4.0f/9.0f, 0.0f, -2.0f/9.0f, 4.0f/9.0f, 2.0f/9.0f, -2.0f/9.0f, 4.0f/9.0f,
+ 4.0f/9.0f, -2.0f/9.0f, 4.0f/9.0f, 6.0f/9.0f, -2.0f/9.0f, 4.0f/9.0f, 8.0f/9.0f, -2.0f/9.0f, 4.0f/9.0f,
+ -8.0f/9.0f, 0.0f, 4.0f/9.0f, -6.0f/9.0f, 0.0f, 4.0f/9.0f, -4.0f/9.0f, 0.0f, 4.0f/9.0f,
+ -2.0f/9.0f, 0.0f, 4.0f/9.0f, 0.0f, 0.0f, 4.0f/9.0f, 2.0f/9.0f, 0.0f, 4.0f/9.0f,
+ 4.0f/9.0f, 0.0f, 4.0f/9.0f, 6.0f/9.0f, 0.0f, 4.0f/9.0f, 8.0f/9.0f, 0.0f, 4.0f/9.0f,
+ -8.0f/9.0f, 2.0f/9.0f, 4.0f/9.0f, -6.0f/9.0f, 2.0f/9.0f, 4.0f/9.0f, -4.0f/9.0f, 2.0f/9.0f, 4.0f/9.0f,
+ -2.0f/9.0f, 2.0f/9.0f, 4.0f/9.0f, 0.0f, 2.0f/9.0f, 4.0f/9.0f, 2.0f/9.0f, 2.0f/9.0f, 4.0f/9.0f,
+ 4.0f/9.0f, 2.0f/9.0f, 4.0f/9.0f, 6.0f/9.0f, 2.0f/9.0f, 4.0f/9.0f, 8.0f/9.0f, 2.0f/9.0f, 4.0f/9.0f,
+ -8.0f/9.0f, 4.0f/9.0f, 4.0f/9.0f, -6.0f/9.0f, 4.0f/9.0f, 4.0f/9.0f, -4.0f/9.0f, 4.0f/9.0f, 4.0f/9.0f,
+ -2.0f/9.0f, 4.0f/9.0f, 4.0f/9.0f, 0.0f, 4.0f/9.0f, 4.0f/9.0f, 2.0f/9.0f, 4.0f/9.0f, 4.0f/9.0f,
+ 4.0f/9.0f, 4.0f/9.0f, 4.0f/9.0f, 6.0f/9.0f, 4.0f/9.0f, 4.0f/9.0f, 8.0f/9.0f, 4.0f/9.0f, 4.0f/9.0f,
+ -8.0f/9.0f, 6.0f/9.0f, 4.0f/9.0f, -6.0f/9.0f, 6.0f/9.0f, 4.0f/9.0f, -4.0f/9.0f, 6.0f/9.0f, 4.0f/9.0f,
+ -2.0f/9.0f, 6.0f/9.0f, 4.0f/9.0f, 0.0f, 6.0f/9.0f, 4.0f/9.0f, 2.0f/9.0f, 6.0f/9.0f, 4.0f/9.0f,
+ 4.0f/9.0f, 6.0f/9.0f, 4.0f/9.0f, 6.0f/9.0f, 6.0f/9.0f, 4.0f/9.0f, 8.0f/9.0f, 6.0f/9.0f, 4.0f/9.0f,
+ -8.0f/9.0f, 8.0f/9.0f, 4.0f/9.0f, -6.0f/9.0f, 8.0f/9.0f, 4.0f/9.0f, -4.0f/9.0f, 8.0f/9.0f, 4.0f/9.0f,
+ -2.0f/9.0f, 8.0f/9.0f, 4.0f/9.0f, 0.0f, 8.0f/9.0f, 4.0f/9.0f, 2.0f/9.0f, 8.0f/9.0f, 4.0f/9.0f,
+ 4.0f/9.0f, 8.0f/9.0f, 4.0f/9.0f, 6.0f/9.0f, 8.0f/9.0f, 4.0f/9.0f, 8.0f/9.0f, 8.0f/9.0f, 4.0f/9.0f,
+ -8.0f/9.0f, -8.0f/9.0f, 6.0f/9.0f, -6.0f/9.0f, -8.0f/9.0f, 6.0f/9.0f, -4.0f/9.0f, -8.0f/9.0f, 6.0f/9.0f,
+ -2.0f/9.0f, -8.0f/9.0f, 6.0f/9.0f, 0.0f, -8.0f/9.0f, 6.0f/9.0f, 2.0f/9.0f, -8.0f/9.0f, 6.0f/9.0f,
+ 4.0f/9.0f, -8.0f/9.0f, 6.0f/9.0f, 6.0f/9.0f, -8.0f/9.0f, 6.0f/9.0f, 8.0f/9.0f, -8.0f/9.0f, 6.0f/9.0f,
+ -8.0f/9.0f, -6.0f/9.0f, 6.0f/9.0f, -6.0f/9.0f, -6.0f/9.0f, 6.0f/9.0f, -4.0f/9.0f, -6.0f/9.0f, 6.0f/9.0f,
+ -2.0f/9.0f, -6.0f/9.0f, 6.0f/9.0f, 0.0f, -6.0f/9.0f, 6.0f/9.0f, 2.0f/9.0f, -6.0f/9.0f, 6.0f/9.0f,
+ 4.0f/9.0f, -6.0f/9.0f, 6.0f/9.0f, 6.0f/9.0f, -6.0f/9.0f, 6.0f/9.0f, 8.0f/9.0f, -6.0f/9.0f, 6.0f/9.0f,
+ -8.0f/9.0f, -4.0f/9.0f, 6.0f/9.0f, -6.0f/9.0f, -4.0f/9.0f, 6.0f/9.0f, -4.0f/9.0f, -4.0f/9.0f, 6.0f/9.0f,
+ -2.0f/9.0f, -4.0f/9.0f, 6.0f/9.0f, 0.0f, -4.0f/9.0f, 6.0f/9.0f, 2.0f/9.0f, -4.0f/9.0f, 6.0f/9.0f,
+ 4.0f/9.0f, -4.0f/9.0f, 6.0f/9.0f, 6.0f/9.0f, -4.0f/9.0f, 6.0f/9.0f, 8.0f/9.0f, -4.0f/9.0f, 6.0f/9.0f,
+ -8.0f/9.0f, -2.0f/9.0f, 6.0f/9.0f, -6.0f/9.0f, -2.0f/9.0f, 6.0f/9.0f, -4.0f/9.0f, -2.0f/9.0f, 6.0f/9.0f,
+ -2.0f/9.0f, -2.0f/9.0f, 6.0f/9.0f, 0.0f, -2.0f/9.0f, 6.0f/9.0f, 2.0f/9.0f, -2.0f/9.0f, 6.0f/9.0f,
+ 4.0f/9.0f, -2.0f/9.0f, 6.0f/9.0f, 6.0f/9.0f, -2.0f/9.0f, 6.0f/9.0f, 8.0f/9.0f, -2.0f/9.0f, 6.0f/9.0f,
+ -8.0f/9.0f, 0.0f, 6.0f/9.0f, -6.0f/9.0f, 0.0f, 6.0f/9.0f, -4.0f/9.0f, 0.0f, 6.0f/9.0f,
+ -2.0f/9.0f, 0.0f, 6.0f/9.0f, 0.0f, 0.0f, 6.0f/9.0f, 2.0f/9.0f, 0.0f, 6.0f/9.0f,
+ 4.0f/9.0f, 0.0f, 6.0f/9.0f, 6.0f/9.0f, 0.0f, 6.0f/9.0f, 8.0f/9.0f, 0.0f, 6.0f/9.0f,
+ -8.0f/9.0f, 2.0f/9.0f, 6.0f/9.0f, -6.0f/9.0f, 2.0f/9.0f, 6.0f/9.0f, -4.0f/9.0f, 2.0f/9.0f, 6.0f/9.0f,
+ -2.0f/9.0f, 2.0f/9.0f, 6.0f/9.0f, 0.0f, 2.0f/9.0f, 6.0f/9.0f, 2.0f/9.0f, 2.0f/9.0f, 6.0f/9.0f,
+ 4.0f/9.0f, 2.0f/9.0f, 6.0f/9.0f, 6.0f/9.0f, 2.0f/9.0f, 6.0f/9.0f, 8.0f/9.0f, 2.0f/9.0f, 6.0f/9.0f,
+ -8.0f/9.0f, 4.0f/9.0f, 6.0f/9.0f, -6.0f/9.0f, 4.0f/9.0f, 6.0f/9.0f, -4.0f/9.0f, 4.0f/9.0f, 6.0f/9.0f,
+ -2.0f/9.0f, 4.0f/9.0f, 6.0f/9.0f, 0.0f, 4.0f/9.0f, 6.0f/9.0f, 2.0f/9.0f, 4.0f/9.0f, 6.0f/9.0f,
+ 4.0f/9.0f, 4.0f/9.0f, 6.0f/9.0f, 6.0f/9.0f, 4.0f/9.0f, 6.0f/9.0f, 8.0f/9.0f, 4.0f/9.0f, 6.0f/9.0f,
+ -8.0f/9.0f, 6.0f/9.0f, 6.0f/9.0f, -6.0f/9.0f, 6.0f/9.0f, 6.0f/9.0f, -4.0f/9.0f, 6.0f/9.0f, 6.0f/9.0f,
+ -2.0f/9.0f, 6.0f/9.0f, 6.0f/9.0f, 0.0f, 6.0f/9.0f, 6.0f/9.0f, 2.0f/9.0f, 6.0f/9.0f, 6.0f/9.0f,
+ 4.0f/9.0f, 6.0f/9.0f, 6.0f/9.0f, 6.0f/9.0f, 6.0f/9.0f, 6.0f/9.0f, 8.0f/9.0f, 6.0f/9.0f, 6.0f/9.0f,
+ -8.0f/9.0f, 8.0f/9.0f, 6.0f/9.0f, -6.0f/9.0f, 8.0f/9.0f, 6.0f/9.0f, -4.0f/9.0f, 8.0f/9.0f, 6.0f/9.0f,
+ -2.0f/9.0f, 8.0f/9.0f, 6.0f/9.0f, 0.0f, 8.0f/9.0f, 6.0f/9.0f, 2.0f/9.0f, 8.0f/9.0f, 6.0f/9.0f,
+ 4.0f/9.0f, 8.0f/9.0f, 6.0f/9.0f, 6.0f/9.0f, 8.0f/9.0f, 6.0f/9.0f, 8.0f/9.0f, 8.0f/9.0f, 6.0f/9.0f,
+ -8.0f/9.0f, -8.0f/9.0f, 8.0f/9.0f, -6.0f/9.0f, -8.0f/9.0f, 8.0f/9.0f, -4.0f/9.0f, -8.0f/9.0f, 8.0f/9.0f,
+ -2.0f/9.0f, -8.0f/9.0f, 8.0f/9.0f, 0.0f, -8.0f/9.0f, 8.0f/9.0f, 2.0f/9.0f, -8.0f/9.0f, 8.0f/9.0f,
+ 4.0f/9.0f, -8.0f/9.0f, 8.0f/9.0f, 6.0f/9.0f, -8.0f/9.0f, 8.0f/9.0f, 8.0f/9.0f, -8.0f/9.0f, 8.0f/9.0f,
+ -8.0f/9.0f, -6.0f/9.0f, 8.0f/9.0f, -6.0f/9.0f, -6.0f/9.0f, 8.0f/9.0f, -4.0f/9.0f, -6.0f/9.0f, 8.0f/9.0f,
+ -2.0f/9.0f, -6.0f/9.0f, 8.0f/9.0f, 0.0f, -6.0f/9.0f, 8.0f/9.0f, 2.0f/9.0f, -6.0f/9.0f, 8.0f/9.0f,
+ 4.0f/9.0f, -6.0f/9.0f, 8.0f/9.0f, 6.0f/9.0f, -6.0f/9.0f, 8.0f/9.0f, 8.0f/9.0f, -6.0f/9.0f, 8.0f/9.0f,
+ -8.0f/9.0f, -4.0f/9.0f, 8.0f/9.0f, -6.0f/9.0f, -4.0f/9.0f, 8.0f/9.0f, -4.0f/9.0f, -4.0f/9.0f, 8.0f/9.0f,
+ -2.0f/9.0f, -4.0f/9.0f, 8.0f/9.0f, 0.0f, -4.0f/9.0f, 8.0f/9.0f, 2.0f/9.0f, -4.0f/9.0f, 8.0f/9.0f,
+ 4.0f/9.0f, -4.0f/9.0f, 8.0f/9.0f, 6.0f/9.0f, -4.0f/9.0f, 8.0f/9.0f, 8.0f/9.0f, -4.0f/9.0f, 8.0f/9.0f,
+ -8.0f/9.0f, -2.0f/9.0f, 8.0f/9.0f, -6.0f/9.0f, -2.0f/9.0f, 8.0f/9.0f, -4.0f/9.0f, -2.0f/9.0f, 8.0f/9.0f,
+ -2.0f/9.0f, -2.0f/9.0f, 8.0f/9.0f, 0.0f, -2.0f/9.0f, 8.0f/9.0f, 2.0f/9.0f, -2.0f/9.0f, 8.0f/9.0f,
+ 4.0f/9.0f, -2.0f/9.0f, 8.0f/9.0f, 6.0f/9.0f, -2.0f/9.0f, 8.0f/9.0f, 8.0f/9.0f, -2.0f/9.0f, 8.0f/9.0f,
+ -8.0f/9.0f, 0.0f, 8.0f/9.0f, -6.0f/9.0f, 0.0f, 8.0f/9.0f, -4.0f/9.0f, 0.0f, 8.0f/9.0f,
+ -2.0f/9.0f, 0.0f, 8.0f/9.0f, 0.0f, 0.0f, 8.0f/9.0f, 2.0f/9.0f, 0.0f, 8.0f/9.0f,
+ 4.0f/9.0f, 0.0f, 8.0f/9.0f, 6.0f/9.0f, 0.0f, 8.0f/9.0f, 8.0f/9.0f, 0.0f, 8.0f/9.0f,
+ -8.0f/9.0f, 2.0f/9.0f, 8.0f/9.0f, -6.0f/9.0f, 2.0f/9.0f, 8.0f/9.0f, -4.0f/9.0f, 2.0f/9.0f, 8.0f/9.0f,
+ -2.0f/9.0f, 2.0f/9.0f, 8.0f/9.0f, 0.0f, 2.0f/9.0f, 8.0f/9.0f, 2.0f/9.0f, 2.0f/9.0f, 8.0f/9.0f,
+ 4.0f/9.0f, 2.0f/9.0f, 8.0f/9.0f, 6.0f/9.0f, 2.0f/9.0f, 8.0f/9.0f, 8.0f/9.0f, 2.0f/9.0f, 8.0f/9.0f,
+ -8.0f/9.0f, 4.0f/9.0f, 8.0f/9.0f, -6.0f/9.0f, 4.0f/9.0f, 8.0f/9.0f, -4.0f/9.0f, 4.0f/9.0f, 8.0f/9.0f,
+ -2.0f/9.0f, 4.0f/9.0f, 8.0f/9.0f, 0.0f, 4.0f/9.0f, 8.0f/9.0f, 2.0f/9.0f, 4.0f/9.0f, 8.0f/9.0f,
+ 4.0f/9.0f, 4.0f/9.0f, 8.0f/9.0f, 6.0f/9.0f, 4.0f/9.0f, 8.0f/9.0f, 8.0f/9.0f, 4.0f/9.0f, 8.0f/9.0f,
+ -8.0f/9.0f, 6.0f/9.0f, 8.0f/9.0f, -6.0f/9.0f, 6.0f/9.0f, 8.0f/9.0f, -4.0f/9.0f, 6.0f/9.0f, 8.0f/9.0f,
+ -2.0f/9.0f, 6.0f/9.0f, 8.0f/9.0f, 0.0f, 6.0f/9.0f, 8.0f/9.0f, 2.0f/9.0f, 6.0f/9.0f, 8.0f/9.0f,
+ 4.0f/9.0f, 6.0f/9.0f, 8.0f/9.0f, 6.0f/9.0f, 6.0f/9.0f, 8.0f/9.0f, 8.0f/9.0f, 6.0f/9.0f, 8.0f/9.0f,
+ -8.0f/9.0f, 8.0f/9.0f, 8.0f/9.0f, -6.0f/9.0f, 8.0f/9.0f, 8.0f/9.0f, -4.0f/9.0f, 8.0f/9.0f, 8.0f/9.0f,
+ -2.0f/9.0f, 8.0f/9.0f, 8.0f/9.0f, 0.0f, 8.0f/9.0f, 8.0f/9.0f, 2.0f/9.0f, 8.0f/9.0f, 8.0f/9.0f,
+ 4.0f/9.0f, 8.0f/9.0f, 8.0f/9.0f, 6.0f/9.0f, 8.0f/9.0f, 8.0f/9.0f, 8.0f/9.0f, 8.0f/9.0f, 8.0f/9.0f
+ };
+
+ // data taken from ISO/IEC DIS 11172, Annexes 3-B.2[abcd] and 3-B.4:
+
+ // subbands 0-2 in tables 3-B.2a and 2b: (index is allocation)
+ public static final int table_ab1_codelength[] =
+ // bits per codeword
+ { 0, 5, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
+
+ public static final float table_ab1_groupingtables[][] =
+ // pointer to sample grouping table, or NULL-pointer if ungrouped
+ { null, grouping_5bits, null, null, null, null, null, null, null, null, null, null, null, null, null, null };
+
+ public static final float table_ab1_factor[] =
+ // factor for requantization: (real)sample * factor - 1.0 gives requantized sample
+ { 0.0f, 1.0f/2.0f, 1.0f/4.0f, 1.0f/8.0f, 1.0f/16.0f, 1.0f/32.0f, 1.0f/64.0f,
+ 1.0f/128.0f, 1.0f/256.0f, 1.0f/512.0f, 1.0f/1024.0f, 1.0f/2048.0f,
+ 1.0f/4096.0f, 1.0f/8192.0f, 1.0f/16384.0f, 1.0f/32768.0f };
+
+ public static final float table_ab1_c[] =
+ // factor c for requantization from table 3-B.4
+ { 0.0f, 1.33333333333f, 1.14285714286f, 1.06666666666f, 1.03225806452f,
+ 1.01587301587f, 1.00787401575f, 1.00392156863f, 1.00195694716f, 1.00097751711f,
+ 1.00048851979f, 1.00024420024f, 1.00012208522f, 1.00006103888f, 1.00003051851f,
+ 1.00001525902f };
+
+ public static final float table_ab1_d[] =
+ // addend d for requantization from table 3-B.4
+ { 0.0f, 0.50000000000f, 0.25000000000f, 0.12500000000f, 0.06250000000f,
+ 0.03125000000f, 0.01562500000f, 0.00781250000f, 0.00390625000f, 0.00195312500f,
+ 0.00097656250f, 0.00048828125f, 0.00024414063f, 0.00012207031f, 0.00006103516f,
+ 0.00003051758f };
+
+ // subbands 3-... tables 3-B.2a and 2b:
+ public static final float[] table_ab234_groupingtables[] =
+ { null, grouping_5bits, grouping_7bits, null, grouping_10bits, null, null, null, null, null, null, null, null, null, null, null };
+
+ // subbands 3-10 in tables 3-B.2a and 2b:
+ public static final int table_ab2_codelength[] =
+ { 0, 5, 7, 3, 10, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16 };
+ public static final float table_ab2_factor[] =
+ { 0.0f, 1.0f/2.0f, 1.0f/4.0f, 1.0f/4.0f, 1.0f/8.0f, 1.0f/8.0f, 1.0f/16.0f,
+ 1.0f/32.0f, 1.0f/64.0f, 1.0f/128.0f, 1.0f/256.0f, 1.0f/512.0f,
+ 1.0f/1024.0f, 1.0f/2048.0f, 1.0f/4096.0f, 1.0f/32768.0f };
+ public static final float table_ab2_c[] =
+ { 0.0f, 1.33333333333f, 1.60000000000f, 1.14285714286f, 1.77777777777f,
+ 1.06666666666f, 1.03225806452f, 1.01587301587f, 1.00787401575f, 1.00392156863f,
+ 1.00195694716f, 1.00097751711f, 1.00048851979f, 1.00024420024f, 1.00012208522f,
+ 1.00001525902f };
+ public static final float table_ab2_d[] =
+ { 0.0f, 0.50000000000f, 0.50000000000f, 0.25000000000f, 0.50000000000f,
+ 0.12500000000f, 0.06250000000f, 0.03125000000f, 0.01562500000f, 0.00781250000f,
+ 0.00390625000f, 0.00195312500f, 0.00097656250f, 0.00048828125f, 0.00024414063f,
+ 0.00003051758f };
+
+ // subbands 11-22 in tables 3-B.2a and 2b:
+ public static final int table_ab3_codelength[] = { 0, 5, 7, 3, 10, 4, 5, 16 };
+ public static final float table_ab3_factor[] =
+ { 0.0f, 1.0f/2.0f, 1.0f/4.0f, 1.0f/4.0f, 1.0f/8.0f, 1.0f/8.0f, 1.0f/16.0f, 1.0f/32768.0f };
+ public static final float table_ab3_c[] =
+ { 0.0f, 1.33333333333f, 1.60000000000f, 1.14285714286f, 1.77777777777f,
+ 1.06666666666f, 1.03225806452f, 1.00001525902f };
+ public static final float table_ab3_d[] =
+ { 0.0f, 0.50000000000f, 0.50000000000f, 0.25000000000f, 0.50000000000f,
+ 0.12500000000f, 0.06250000000f, 0.00003051758f };
+
+ // subbands 23-... in tables 3-B.2a and 2b:
+ public static final int table_ab4_codelength[] = { 0, 5, 7, 16 };
+ public static final float table_ab4_factor[] = { 0.0f, 1.0f/2.0f, 1.0f/4.0f, 1.0f/32768.0f };
+ public static final float table_ab4_c[] = { 0.0f, 1.33333333333f, 1.60000000000f, 1.00001525902f };
+ public static final float table_ab4_d[] = { 0.0f, 0.50000000000f, 0.50000000000f, 0.00003051758f };
+
+ // subbands in tables 3-B.2c and 2d:
+ public static final int table_cd_codelength[] =
+ { 0, 5, 7, 10, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
+ public static final float table_cd_groupingtables[][] =
+ { null, grouping_5bits, grouping_7bits, grouping_10bits, null, null, null, null, null, null, null, null, null, null, null, null };
+ public static final float table_cd_factor[] =
+ { 0.0f, 1.0f/2.0f, 1.0f/4.0f, 1.0f/8.0f, 1.0f/8.0f, 1.0f/16.0f, 1.0f/32.0f, 1.0f/64.0f,
+ 1.0f/128.0f, 1.0f/256.0f, 1.0f/512.0f, 1.0f/1024.0f, 1.0f/2048.0f, 1.0f/4096.0f,
+ 1.0f/8192.0f, 1.0f/16384.0f };
+ public static final float table_cd_c[] =
+ { 0.0f, 1.33333333333f, 1.60000000000f, 1.77777777777f, 1.06666666666f,
+ 1.03225806452f, 1.01587301587f, 1.00787401575f, 1.00392156863f, 1.00195694716f,
+ 1.00097751711f, 1.00048851979f, 1.00024420024f, 1.00012208522f, 1.00006103888f,
+ 1.00003051851f };
+ public static final float table_cd_d[] =
+ { 0.0f, 0.50000000000f, 0.50000000000f, 0.50000000000f, 0.12500000000f,
+ 0.06250000000f, 0.03125000000f, 0.01562500000f, 0.00781250000f, 0.00390625000f,
+ 0.00195312500f, 0.00097656250f, 0.00048828125f, 0.00024414063f, 0.00012207031f,
+ 0.00006103516f };
+
+
+
+ protected int subbandnumber;
+ protected int allocation;
+ protected int scfsi;
+ protected float scalefactor1, scalefactor2, scalefactor3;
+ protected int[] codelength = {0};
+ protected float groupingtable[][] = new float[2][];
+ //protected float[][] groupingtable = {{0},{0}} ;
+ protected float[] factor = {0.0f};
+ protected int groupnumber;
+ protected int samplenumber;
+ protected float[] samples = new float[3];
+ protected float[] c = {0};
+ protected float[] d = {0};
+ /**
+ * Constructor
+ */
+ public SubbandLayer2(int subbandnumber)
+ {
+ this.subbandnumber = subbandnumber;
+ groupnumber = samplenumber = 0;
+ }
+
+
+ /**
+ *
+ */
+ protected int get_allocationlength (Header header)
+ {
+ if (header.version() == Header.MPEG1)
+ {
+ int channel_bitrate = header.bitrate_index();
+
+ // calculate bitrate per channel:
+ if (header.mode() != Header.SINGLE_CHANNEL)
+ if (channel_bitrate == 4)
+ channel_bitrate = 1;
+ else
+ channel_bitrate -= 4;
+
+ if (channel_bitrate == 1 || channel_bitrate == 2)
+ // table 3-B.2c or 3-B.2d
+ if (subbandnumber <= 1)
+ return 4;
+ else
+ return 3;
+ else
+ // tables 3-B.2a or 3-B.2b
+ if (subbandnumber <= 10)
+ return 4;
+ else if (subbandnumber <= 22)
+ return 3;
+ else
+ return 2;
+ }
+ else
+ { // MPEG-2 LSF -- Jeff
+
+ // table B.1 of ISO/IEC 13818-3
+ if (subbandnumber <= 3)
+ return 4;
+ else if (subbandnumber <= 10)
+ return 3;
+ else
+ return 2;
+ }
+ }
+
+ /**
+ *
+ */
+ protected void prepare_sample_reading(Header header, int allocation,
+ //float[][] groupingtable,
+ int channel,
+ float[] factor, int[] codelength,
+ float[] c, float[] d)
+ {
+ int channel_bitrate = header.bitrate_index();
+ // calculate bitrate per channel:
+ if (header.mode() != Header.SINGLE_CHANNEL)
+ if (channel_bitrate == 4)
+ channel_bitrate = 1;
+ else
+ channel_bitrate -= 4;
+
+ if (channel_bitrate == 1 || channel_bitrate == 2)
+ {
+ // table 3-B.2c or 3-B.2d
+ groupingtable[channel] = table_cd_groupingtables[allocation];
+ factor[0] = table_cd_factor[allocation];
+ codelength[0] = table_cd_codelength[allocation];
+ c[0] = table_cd_c[allocation];
+ d[0] = table_cd_d[allocation];
+ }
+ else
+ {
+ // tables 3-B.2a or 3-B.2b
+ if (subbandnumber <= 2)
+ {
+ groupingtable[channel] = table_ab1_groupingtables[allocation];
+ factor[0] = table_ab1_factor[allocation];
+ codelength[0] = table_ab1_codelength[allocation];
+ c[0] = table_ab1_c[allocation];
+ d[0] = table_ab1_d[allocation];
+ }
+ else
+ {
+ groupingtable[channel] = table_ab234_groupingtables[allocation];
+ if (subbandnumber <= 10)
+ {
+ factor[0] = table_ab2_factor[allocation];
+ codelength[0] = table_ab2_codelength[allocation];
+ c[0] = table_ab2_c[allocation];
+ d[0] = table_ab2_d[allocation];
+ }
+ else if (subbandnumber <= 22)
+ {
+ factor[0] = table_ab3_factor[allocation];
+ codelength[0] = table_ab3_codelength[allocation];
+ c[0] = table_ab3_c[allocation];
+ d[0] = table_ab3_d[allocation];
+ }
+ else
+ {
+ factor[0] = table_ab4_factor[allocation];
+ codelength[0] = table_ab4_codelength[allocation];
+ c[0] = table_ab4_c[allocation];
+ d[0] = table_ab4_d[allocation];
+ }
+ }
+ }
+ }
+
+
+ /**
+ *
+ */
+ public void read_allocation(Bitstream stream, Header header, Crc16 crc)
+ {
+ int length = get_allocationlength(header);
+ allocation = stream.get_bits(length);
+ if (crc != null)
+ crc.add_bits(allocation, length);
+ }
+
+ /**
+ *
+ */
+ public void read_scalefactor_selection (Bitstream stream, Crc16 crc)
+ {
+ if (allocation != 0)
+ {
+ scfsi = stream.get_bits(2);
+ if (crc != null) crc.add_bits(scfsi, 2);
+ }
+ }
+
+ /**
+ *
+ */
+ public void read_scalefactor (Bitstream stream, Header header)
+ {
+ if (allocation != 0)
+ {
+ switch (scfsi)
+ {
+ case 0:
+ scalefactor1 = scalefactors[stream.get_bits(6)];
+ scalefactor2 = scalefactors[stream.get_bits(6)];
+ scalefactor3 = scalefactors[stream.get_bits(6)];
+ break;
+ case 1:
+ scalefactor1 = scalefactor2 = scalefactors[stream.get_bits(6)];
+ scalefactor3 = scalefactors[stream.get_bits(6)];
+ break;
+ case 2:
+ scalefactor1 = scalefactor2 = scalefactor3 = scalefactors[stream.get_bits(6)];
+ break;
+ case 3:
+ scalefactor1 = scalefactors[stream.get_bits(6)];
+ scalefactor2 = scalefactor3 = scalefactors[stream.get_bits(6)];
+ break;
+ }
+ prepare_sample_reading(header, allocation, 0,
+ factor, codelength, c, d);
+ }
+ }
+
+ /**
+ *
+ */
+ public boolean read_sampledata (Bitstream stream)
+ {
+ if (allocation != 0)
+ if (groupingtable[0] != null)
+ {
+ int samplecode = stream.get_bits(codelength[0]);
+ // create requantized samples:
+ samplecode += samplecode << 1;
+ float[] target = samples;
+ float[] source = groupingtable[0];
+ /*
+ int tmp = 0;
+ int temp = 0;
+ target[tmp++] = source[samplecode + temp];
+ temp++;
+ target[tmp++] = source[samplecode + temp];
+ temp++;
+ target[tmp] = source[samplecode + temp];
+ */
+ //Bugfix:
+ int tmp = 0;
+ int temp = samplecode;
+
+ if(temp > source.length - 3) temp = source.length - 3;
+
+ target[tmp] = source[temp];
+ temp++;tmp++;
+ target[tmp] = source[temp];
+ temp++;tmp++;
+ target[tmp] = source[temp];
+
+ // memcpy (samples, groupingtable + samplecode, 3 * sizeof (real));
+ }
+ else
+ {
+ samples[0] = (float) ((stream.get_bits(codelength[0])) * factor[0] - 1.0);
+ samples[1] = (float) ((stream.get_bits(codelength[0])) * factor[0] - 1.0);
+ samples[2] = (float) ((stream.get_bits(codelength[0])) * factor[0] - 1.0);
+ }
+
+ samplenumber = 0;
+ if (++groupnumber == 12)
+ return true;
+ else
+ return false;
+ }
+
+ /**
+ *
+ */
+ public boolean put_next_sample(int channels, SynthesisFilter filter1, SynthesisFilter filter2)
+ {
+ if ((allocation != 0) && (channels != OutputChannels.RIGHT_CHANNEL))
+ {
+ float sample = samples[samplenumber];
+
+ if (groupingtable[0] == null)
+ sample = (sample + d[0]) * c[0];
+ if (groupnumber <= 4)
+ sample *= scalefactor1;
+ else if (groupnumber <= 8)
+ sample *= scalefactor2;
+ else
+ sample *= scalefactor3;
+ filter1.input_sample(sample, subbandnumber);
+ }
+
+ if (++samplenumber == 3)
+ return true;
+ else
+ return false;
+ }
+ };
+
+ /**
+ * Class for layer II subbands in joint stereo mode.
+ */
+ static class SubbandLayer2IntensityStereo extends SubbandLayer2
+ {
+ protected int channel2_scfsi;
+ protected float channel2_scalefactor1, channel2_scalefactor2, channel2_scalefactor3;
+
+ /**
+ * Constructor
+ */
+ public SubbandLayer2IntensityStereo (int subbandnumber)
+ {
+ super(subbandnumber);
+ }
+
+ /**
+ *
+ */
+ public void read_allocation(Bitstream stream, Header header, Crc16 crc)
+ {
+ super.read_allocation (stream, header, crc);
+ }
+
+ /**
+ *
+ */
+ public void read_scalefactor_selection(Bitstream stream, Crc16 crc)
+ {
+ if (allocation != 0)
+ {
+ scfsi = stream.get_bits(2);
+ channel2_scfsi = stream.get_bits(2);
+ if (crc != null)
+ {
+ crc.add_bits(scfsi, 2);
+ crc.add_bits(channel2_scfsi, 2);
+ }
+ }
+ }
+
+ /**
+ *
+ */
+ public void read_scalefactor(Bitstream stream, Header header)
+ {
+ if (allocation != 0)
+ {
+ super.read_scalefactor(stream, header);
+ switch (channel2_scfsi)
+ {
+ case 0:
+ channel2_scalefactor1 = scalefactors[stream.get_bits(6)];
+ channel2_scalefactor2 = scalefactors[stream.get_bits(6)];
+ channel2_scalefactor3 = scalefactors[stream.get_bits(6)];
+ break;
+
+ case 1:
+ channel2_scalefactor1 = channel2_scalefactor2 = scalefactors[stream.get_bits (6)];
+ channel2_scalefactor3 = scalefactors[stream.get_bits(6)];
+ break;
+
+ case 2:
+ channel2_scalefactor1 = channel2_scalefactor2 =
+ channel2_scalefactor3 = scalefactors[stream.get_bits(6)];
+ break;
+
+ case 3:
+ channel2_scalefactor1 = scalefactors[stream.get_bits(6)];
+ channel2_scalefactor2 = channel2_scalefactor3 = scalefactors[stream.get_bits (6)];
+ break;
+ }
+ }
+
+ }
+
+ /**
+ *
+ */
+ public boolean read_sampledata(Bitstream stream)
+ {
+ return super.read_sampledata (stream);
+ }
+
+ /**
+ *
+ */
+ public boolean put_next_sample(int channels, SynthesisFilter filter1, SynthesisFilter filter2)
+ {
+ if (allocation != 0)
+ {
+ float sample = samples[samplenumber];
+
+ if (groupingtable[0] == null)
+ sample = (sample + d[0]) * c[0];
+ if (channels == OutputChannels.BOTH_CHANNELS)
+ {
+ float sample2 = sample;
+ if (groupnumber <= 4)
+ {
+ sample *= scalefactor1;
+ sample2 *= channel2_scalefactor1;
+ }
+ else if (groupnumber <= 8)
+ {
+ sample *= scalefactor2;
+ sample2 *= channel2_scalefactor2;
+ }
+ else
+ {
+ sample *= scalefactor3;
+ sample2 *= channel2_scalefactor3;
+ }
+ filter1.input_sample(sample, subbandnumber);
+ filter2.input_sample(sample2, subbandnumber);
+ }
+ else if (channels == OutputChannels.LEFT_CHANNEL)
+ {
+ if (groupnumber <= 4)
+ sample *= scalefactor1;
+ else if (groupnumber <= 8)
+ sample *= scalefactor2;
+ else
+ sample *= scalefactor3;
+ filter1.input_sample(sample, subbandnumber);
+ }
+ else
+ {
+ if (groupnumber <= 4)
+ sample *= channel2_scalefactor1;
+ else if (groupnumber <= 8)
+ sample *= channel2_scalefactor2;
+ else
+ sample *= channel2_scalefactor3;
+ filter1.input_sample(sample, subbandnumber);
+ }
+ }
+
+ if (++samplenumber == 3)
+ return true;
+ else
+ return false;
+ }
+ };
+
+ /**
+ * Class for layer II subbands in stereo mode.
+ */
+ static class SubbandLayer2Stereo extends SubbandLayer2
+ {
+ protected int channel2_allocation;
+ protected int channel2_scfsi;
+ protected float channel2_scalefactor1, channel2_scalefactor2, channel2_scalefactor3;
+ //protected boolean channel2_grouping; ???? Never used!
+ protected int[] channel2_codelength = {0};
+ //protected float[][] channel2_groupingtable = {{0},{0}};
+ protected float[] channel2_factor = {0};
+ protected float[] channel2_samples;
+ protected float[] channel2_c = {0};
+ protected float[] channel2_d = {0};
+
+ /**
+ * Constructor
+ */
+ public SubbandLayer2Stereo(int subbandnumber)
+ {
+ super(subbandnumber);
+ channel2_samples = new float[3];
+ }
+
+ /**
+ *
+ */
+ public void read_allocation (Bitstream stream, Header header, Crc16 crc)
+ {
+ int length = get_allocationlength(header);
+ allocation = stream.get_bits(length);
+ channel2_allocation = stream.get_bits(length);
+ if (crc != null)
+ {
+ crc.add_bits(allocation, length);
+ crc.add_bits(channel2_allocation, length);
+ }
+ }
+
+ /**
+ *
+ */
+ public void read_scalefactor_selection(Bitstream stream, Crc16 crc)
+ {
+ if (allocation != 0)
+ {
+ scfsi = stream.get_bits(2);
+ if (crc != null)
+ crc.add_bits(scfsi, 2);
+ }
+ if (channel2_allocation != 0)
+ {
+ channel2_scfsi = stream.get_bits(2);
+ if (crc != null)
+ crc.add_bits(channel2_scfsi, 2);
+ }
+ }
+
+ /**
+ *
+ */
+ public void read_scalefactor(Bitstream stream, Header header)
+ {
+ super.read_scalefactor(stream, header);
+ if (channel2_allocation != 0)
+ {
+ switch (channel2_scfsi)
+ {
+ case 0:
+ channel2_scalefactor1 = scalefactors[stream.get_bits(6)];
+ channel2_scalefactor2 = scalefactors[stream.get_bits(6)];
+ channel2_scalefactor3 = scalefactors[stream.get_bits(6)];
+ break;
+
+ case 1:
+ channel2_scalefactor1 = channel2_scalefactor2 =
+ scalefactors[stream.get_bits(6)];
+ channel2_scalefactor3 = scalefactors[stream.get_bits(6)];
+ break;
+
+ case 2:
+ channel2_scalefactor1 = channel2_scalefactor2 =
+ channel2_scalefactor3 = scalefactors[stream.get_bits(6)];
+ break;
+
+ case 3:
+ channel2_scalefactor1 = scalefactors[stream.get_bits(6)];
+ channel2_scalefactor2 = channel2_scalefactor3 =
+ scalefactors[stream.get_bits(6)];
+ break;
+ }
+ prepare_sample_reading(header, channel2_allocation, 1,
+ channel2_factor, channel2_codelength, channel2_c,
+ channel2_d);
+ }
+ }
+
+ /**
+ *
+ */
+ public boolean read_sampledata (Bitstream stream)
+ {
+ boolean returnvalue = super.read_sampledata(stream);
+
+ if (channel2_allocation != 0)
+ if (groupingtable[1] != null)
+ {
+ int samplecode = stream.get_bits(channel2_codelength[0]);
+ // create requantized samples:
+ samplecode += samplecode << 1;
+ /*
+ float[] target = channel2_samples;
+ float[] source = channel2_groupingtable[0];
+ int tmp = 0;
+ int temp = 0;
+ target[tmp++] = source[samplecode + temp];
+ temp++;
+ target[tmp++] = source[samplecode + temp];
+ temp++;
+ target[tmp] = source[samplecode + temp];
+ // memcpy (channel2_samples, channel2_groupingtable + samplecode, 3 * sizeof (real));
+ */
+ float[] target = channel2_samples;
+ float[] source = groupingtable[1];
+ int tmp = 0;
+ int temp = samplecode;
+ target[tmp] = source[temp];
+ temp++;tmp++;
+ target[tmp] = source[temp];
+ temp++;tmp++;
+ target[tmp] = source[temp];
+
+ }
+ else
+ {
+ channel2_samples[0] = (float) ((stream.get_bits(channel2_codelength[0])) *
+ channel2_factor[0] - 1.0);
+ channel2_samples[1] = (float) ((stream.get_bits(channel2_codelength[0])) *
+ channel2_factor[0] - 1.0);
+ channel2_samples[2] = (float) ((stream.get_bits(channel2_codelength[0])) *
+ channel2_factor[0] - 1.0);
+ }
+ return returnvalue;
+ }
+
+ /**
+ *
+ */
+ public boolean put_next_sample(int channels, SynthesisFilter filter1, SynthesisFilter filter2)
+ {
+ boolean returnvalue = super.put_next_sample(channels, filter1, filter2);
+ if ((channel2_allocation != 0) && (channels != OutputChannels.LEFT_CHANNEL))
+ {
+ float sample = channel2_samples[samplenumber - 1];
+
+ if (groupingtable[1] == null)
+ sample = (sample + channel2_d[0]) * channel2_c[0];
+
+ if (groupnumber <= 4)
+ sample *= channel2_scalefactor1;
+ else if (groupnumber <= 8)
+ sample *= channel2_scalefactor2;
+ else
+ sample *= channel2_scalefactor3;
+ if (channels == OutputChannels.BOTH_CHANNELS)
+ filter2.input_sample(sample, subbandnumber);
+ else
+ filter1.input_sample(sample, subbandnumber);
+ }
+ return returnvalue;
+ }
+ }
+}
diff --git a/src/javazoom/jl/decoder/LayerIIIDecoder.java b/src/javazoom/jl/decoder/LayerIIIDecoder.java
new file mode 100644
index 00000000000..6d62d202e45
--- /dev/null
+++ b/src/javazoom/jl/decoder/LayerIIIDecoder.java
@@ -0,0 +1,2439 @@
+/*
+ * 11/19/04 1.0 moved to LGPL.
+ *
+ * 18/06/01 Michael Scheerer, Fixed bugs which causes
+ * negative indexes in method huffmann_decode and in method
+ * dequanisize_sample.
+ *
+ * 16/07/01 Michael Scheerer, Catched a bug in method
+ * huffmann_decode, which causes an outOfIndexException.
+ * Cause : Indexnumber of 24 at SfBandIndex,
+ * which has only a length of 22. I have simply and dirty
+ * fixed the index to <= 22, because I'm not really be able
+ * to fix the bug. The Indexnumber is taken from the MP3
+ * file and the origin Ma-Player with the same code works
+ * well.
+ *
+ * 02/19/99 Java Conversion by E.B, javalayer@javazoom.net
+ *-----------------------------------------------------------------------
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *----------------------------------------------------------------------
+ */
+
+package javazoom.jl.decoder;
+
+/**
+ * Class Implementing Layer 3 Decoder.
+ *
+ * @since 0.0
+ */
+final class LayerIIIDecoder implements FrameDecoder
+{
+ final double d43 = (4.0/3.0);
+
+ public int[] scalefac_buffer;
+
+ // MDM: removed, as this wasn't being used.
+ //private float CheckSumOut1d = 0.0f;
+ private int CheckSumHuff = 0;
+ private int[] is_1d;
+ private float[][][] ro;
+ private float[][][] lr;
+ private float[] out_1d;
+ private float[][] prevblck;
+ private float[][] k;
+ private int[] nonzero;
+ private Bitstream stream;
+ private Header header;
+ private SynthesisFilter filter1, filter2;
+ private Obuffer buffer;
+ private int which_channels;
+ private BitReserve br;
+ private III_side_info_t si;
+
+ private temporaire2[] III_scalefac_t;
+ private temporaire2[] scalefac;
+ // private III_scalefac_t scalefac;
+
+ private int max_gr;
+ private int frame_start;
+ private int part2_start;
+ private int channels;
+ private int first_channel;
+ private int last_channel;
+ private int sfreq;
+
+
+ /**
+ * Constructor.
+ */
+ // REVIEW: these constructor arguments should be moved to the
+ // decodeFrame() method, where possible, so that one
+ public LayerIIIDecoder(Bitstream stream0, Header header0,
+ SynthesisFilter filtera, SynthesisFilter filterb,
+ Obuffer buffer0, int which_ch0)
+ {
+ huffcodetab.inithuff();
+ is_1d = new int[SBLIMIT*SSLIMIT+4];
+ ro = new float[2][SBLIMIT][SSLIMIT];
+ lr = new float[2][SBLIMIT][SSLIMIT];
+ out_1d = new float[SBLIMIT*SSLIMIT];
+ prevblck = new float[2][SBLIMIT*SSLIMIT];
+ k = new float[2][SBLIMIT*SSLIMIT];
+ nonzero = new int[2];
+
+ //III_scalefact_t
+ III_scalefac_t = new temporaire2[2];
+ III_scalefac_t[0] = new temporaire2();
+ III_scalefac_t[1] = new temporaire2();
+ scalefac = III_scalefac_t;
+ // L3TABLE INIT
+
+ sfBandIndex = new SBI[9]; // SZD: MPEG2.5 +3 indices
+ int[] l0 = {0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576};
+ int[] s0 = {0,4,8,12,18,24,32,42,56,74,100,132,174,192};
+ int[] l1 = {0,6,12,18,24,30,36,44,54,66,80,96,114,136,162,194,232,278,330,394,464,540,576};
+ int[] s1 = {0,4,8,12,18,26,36,48,62,80,104,136,180,192};
+ int[] l2 = {0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576};
+ int[] s2 = {0,4,8,12,18,26,36,48,62,80,104,134,174,192};
+
+ int[] l3 = {0,4,8,12,16,20,24,30,36,44,52,62,74,90,110,134,162,196,238,288,342,418,576};
+ int[] s3 = {0,4,8,12,16,22,30,40,52,66,84,106,136,192};
+ int[] l4 = {0,4,8,12,16,20,24,30,36,42,50,60,72,88,106,128,156,190,230,276,330,384,576};
+ int[] s4 = {0,4,8,12,16,22,28,38,50,64,80,100,126,192};
+ int[] l5 = {0,4,8,12,16,20,24,30,36,44,54,66,82,102,126,156,194,240,296,364,448,550,576};
+ int[] s5 = {0,4,8,12,16,22,30,42,58,78,104,138,180,192};
+ // SZD: MPEG2.5
+ int[] l6 = {0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576};
+ int[] s6 = {0,4,8,12,18,26,36,48,62,80,104,134,174,192};
+ int[] l7 = {0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576};
+ int[] s7 = {0,4,8,12,18,26,36,48,62,80,104,134,174,192};
+ int[] l8 = {0,12,24,36,48,60,72,88,108,132,160,192,232,280,336,400,476,566,568,570,572,574,576};
+ int[] s8 = {0,8,16,24,36,52,72,96,124,160,162,164,166,192};
+
+ sfBandIndex[0]= new SBI(l0,s0);
+ sfBandIndex[1]= new SBI(l1,s1);
+ sfBandIndex[2]= new SBI(l2,s2);
+
+ sfBandIndex[3]= new SBI(l3,s3);
+ sfBandIndex[4]= new SBI(l4,s4);
+ sfBandIndex[5]= new SBI(l5,s5);
+ //SZD: MPEG2.5
+ sfBandIndex[6]= new SBI(l6,s6);
+ sfBandIndex[7]= new SBI(l7,s7);
+ sfBandIndex[8]= new SBI(l8,s8);
+ // END OF L3TABLE INIT
+
+ if(reorder_table == null) { // SZD: generate LUT
+ reorder_table = new int[9][];
+ for(int i = 0; i < 9; i++)
+ reorder_table[i] = reorder(sfBandIndex[i].s);
+ }
+
+ // Sftable
+ int[] ll0 = {0, 6, 11, 16, 21};
+ int[] ss0 = {0, 6, 12};
+ sftable = new Sftable(ll0,ss0);
+ // END OF Sftable
+
+ // scalefac_buffer
+ scalefac_buffer = new int[54];
+ // END OF scalefac_buffer
+
+ stream = stream0;
+ header = header0;
+ filter1 = filtera;
+ filter2 = filterb;
+ buffer = buffer0;
+ which_channels = which_ch0;
+
+ frame_start = 0;
+ channels = (header.mode() == Header.SINGLE_CHANNEL) ? 1 : 2;
+ max_gr = (header.version() == Header.MPEG1) ? 2 : 1;
+
+ sfreq = header.sample_frequency() +
+ ((header.version() == Header.MPEG1) ? 3 :
+ (header.version() == Header.MPEG25_LSF) ? 6 : 0); // SZD
+
+ if (channels == 2)
+ {
+ switch (which_channels)
+ {
+ case OutputChannels.LEFT_CHANNEL:
+ case OutputChannels.DOWNMIX_CHANNELS:
+ first_channel = last_channel = 0;
+ break;
+
+ case OutputChannels.RIGHT_CHANNEL:
+ first_channel = last_channel = 1;
+ break;
+
+ case OutputChannels.BOTH_CHANNELS:
+ default:
+ first_channel = 0;
+ last_channel = 1;
+ break;
+ }
+ }
+ else
+ {
+ first_channel = last_channel = 0;
+ }
+
+ for(int ch=0;ch<2;ch++)
+ for (int j=0; j<576; j++)
+ prevblck[ch][j] = 0.0f;
+
+ nonzero[0] = nonzero[1] = 576;
+
+ br = new BitReserve();
+ si = new III_side_info_t();
+ }
+
+ /**
+ * Notify decoder that a seek is being made.
+ */
+ public void seek_notify()
+ {
+ frame_start = 0;
+ for(int ch=0;ch<2;ch++)
+ for (int j=0; j<576; j++)
+ prevblck[ch][j] = 0.0f;
+ br = new BitReserve();
+ }
+
+ public void decodeFrame()
+ {
+ decode();
+ }
+
+ /**
+ * Decode one frame, filling the buffer with the output samples.
+ */
+
+ // subband samples are buffered and passed to the
+ // SynthesisFilter in one go.
+ private float[] samples1 = new float[32];
+ private float[] samples2 = new float[32];
+
+ public void decode()
+ {
+ int nSlots = header.slots();
+ int flush_main;
+ int gr, ch, ss, sb, sb18;
+ int main_data_end;
+ int bytes_to_discard;
+ int i;
+
+ get_side_info();
+
+ for (i=0; iOutputChannels instance
+ * corresponding to the given channel code.
+ *
+ * @param code one of the OutputChannels channel code constants.
+ *
+ * @throws IllegalArgumentException if code is not a valid
+ * channel code.
+ */
+ static public OutputChannels fromInt(int code)
+ {
+ switch (code)
+ {
+ case LEFT_CHANNEL:
+ return LEFT;
+ case RIGHT_CHANNEL:
+ return RIGHT;
+ case BOTH_CHANNELS:
+ return BOTH;
+ case DOWNMIX_CHANNELS:
+ return DOWNMIX;
+ default:
+ throw new IllegalArgumentException("Invalid channel code: "+code);
+ }
+ }
+
+ private OutputChannels(int channels)
+ {
+ outputChannels = channels;
+
+ if (channels<0 || channels>3)
+ throw new IllegalArgumentException("channels");
+ }
+
+ /**
+ * Retrieves the code representing the desired output channels.
+ * Will be one of LEFT_CHANNEL, RIGHT_CHANNEL, BOTH_CHANNELS
+ * or DOWNMIX_CHANNELS.
+ *
+ * @return the channel code represented by this instance.
+ */
+ public int getChannelsOutputCode()
+ {
+ return outputChannels;
+ }
+
+ /**
+ * Retrieves the number of output channels represented
+ * by this channel output type.
+ *
+ * @return The number of output channels for this channel output
+ * type. This will be 2 for BOTH_CHANNELS only, and 1
+ * for all other types.
+ */
+ public int getChannelCount()
+ {
+ int count = (outputChannels==BOTH_CHANNELS) ? 2 : 1;
+ return count;
+ }
+
+
+ public boolean equals(Object o)
+ {
+ boolean equals = false;
+
+ if (o instanceof OutputChannels)
+ {
+ OutputChannels oc = (OutputChannels)o;
+ equals = (oc.outputChannels == outputChannels);
+ }
+
+ return equals;
+ }
+
+ public int hashCode()
+ {
+ return outputChannels;
+ }
+
+}
diff --git a/src/javazoom/jl/decoder/SampleBuffer.java b/src/javazoom/jl/decoder/SampleBuffer.java
new file mode 100644
index 00000000000..3bc0fe853ac
--- /dev/null
+++ b/src/javazoom/jl/decoder/SampleBuffer.java
@@ -0,0 +1,132 @@
+/*
+ * 11/19/04 1.0 moved to LGPL.
+ *
+ * 12/12/99 Initial Version based on FileObuffer. mdm@techie.com.
+ *
+ * FileObuffer:
+ * 15/02/99 Java Conversion by E.B ,javalayer@javazoom.net
+ *
+ *-----------------------------------------------------------------------
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *----------------------------------------------------------------------
+ */
+
+package javazoom.jl.decoder;
+
+/**
+ * The SampleBuffer class implements an output buffer
+ * that provides storage for a fixed size block of samples.
+ */
+public class SampleBuffer extends Obuffer
+{
+ private short[] buffer;
+ private int[] bufferp;
+ private int channels;
+ private int frequency;
+
+ /**
+ * Constructor
+ */
+ public SampleBuffer(int sample_frequency, int number_of_channels)
+ {
+ buffer = new short[OBUFFERSIZE];
+ bufferp = new int[MAXCHANNELS];
+ channels = number_of_channels;
+ frequency = sample_frequency;
+
+ for (int i = 0; i < number_of_channels; ++i)
+ bufferp[i] = (short)i;
+
+ }
+
+ public int getChannelCount()
+ {
+ return this.channels;
+ }
+
+ public int getSampleFrequency()
+ {
+ return this.frequency;
+ }
+
+ public short[] getBuffer()
+ {
+ return this.buffer;
+ }
+
+ public int getBufferLength()
+ {
+ return bufferp[0];
+ }
+
+ /**
+ * Takes a 16 Bit PCM sample.
+ */
+ public void append(int channel, short value)
+ {
+ buffer[bufferp[channel]] = value;
+ bufferp[channel] += channels;
+ }
+
+ public void appendSamples(int channel, float[] f)
+ {
+ int pos = bufferp[channel];
+
+ short s;
+ float fs;
+ for (int i=0; i<32;)
+ {
+ fs = f[i++];
+ fs = (fs>32767.0f ? 32767.0f
+ : (fs < -32767.0f ? -32767.0f : fs));
+
+ s = (short)fs;
+ buffer[pos] = s;
+ pos += channels;
+ }
+
+ bufferp[channel] = pos;
+ }
+
+
+ /**
+ * Write the samples to the file (Random Acces).
+ */
+ public void write_buffer(int val)
+ {
+
+ //for (int i = 0; i < channels; ++i)
+ // bufferp[i] = (short)i;
+
+ }
+
+ public void close()
+ {}
+
+ /**
+ *
+ */
+ public void clear_buffer()
+ {
+ for (int i = 0; i < channels; ++i)
+ bufferp[i] = (short)i;
+ }
+
+ /**
+ *
+ */
+ public void set_stop_flag()
+ {}
+}
diff --git a/src/javazoom/jl/decoder/Source.java b/src/javazoom/jl/decoder/Source.java
new file mode 100644
index 00000000000..f4d7316a2f5
--- /dev/null
+++ b/src/javazoom/jl/decoder/Source.java
@@ -0,0 +1,49 @@
+/*
+ * 11/19/04 1.0 moved to LGPL.
+ *-----------------------------------------------------------------------
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *----------------------------------------------------------------------
+ */
+
+package javazoom.jl.decoder;
+
+import java.io.IOException;
+
+/**
+ * Work in progress.
+ *
+ * Class to describe a seekable data source.
+ *
+ */
+public interface Source
+{
+
+ public static final long LENGTH_UNKNOWN = -1;
+
+ public int read(byte[] b, int offs, int len)
+ throws IOException;
+
+
+ public boolean willReadBlock();
+
+ public boolean isSeekable();
+
+ public long length();
+
+ public long tell();
+
+ public long seek(long pos);
+
+}
diff --git a/src/javazoom/jl/decoder/SynthesisFilter.java b/src/javazoom/jl/decoder/SynthesisFilter.java
new file mode 100644
index 00000000000..b657b51835f
--- /dev/null
+++ b/src/javazoom/jl/decoder/SynthesisFilter.java
@@ -0,0 +1,1817 @@
+/*
+ * 11/19/04 1.0 moved to LGPL.
+ *
+ * 04/01/00 Fixes for running under build 23xx Microsoft JVM. mdm.
+ *
+ * 19/12/99 Performance improvements to compute_pcm_samples().
+ * Mat McGowan. mdm@techie.com.
+ *
+ * 16/02/99 Java Conversion by E.B , javalayer@javazoom.net
+ *
+ * @(#) synthesis_filter.h 1.8, last edit: 6/15/94 16:52:00
+ * @(#) Copyright (C) 1993, 1994 Tobias Bading (bading@cs.tu-berlin.de)
+ * @(#) Berlin University of Technology
+ *
+ *-----------------------------------------------------------------------
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *----------------------------------------------------------------------
+ */
+package javazoom.jl.decoder;
+
+import java.io.IOException;
+
+/**
+ * A class for the synthesis filter bank.
+ * This class does a fast downsampling from 32, 44.1 or 48 kHz to 8 kHz, if ULAW is defined.
+ * Frequencies above 4 kHz are removed by ignoring higher subbands.
+ */
+final class SynthesisFilter
+{
+ private float[] v1;
+ private float[] v2;
+ private float[] actual_v; // v1 or v2
+ private int actual_write_pos; // 0-15
+ private float[] samples; // 32 new subband samples
+ private int channel;
+ private float scalefactor;
+ private float[] eq;
+
+ /**
+ * Quality value for controlling CPU usage/quality tradeoff.
+ */
+ /*
+ private int quality;
+
+ private int v_inc;
+
+
+
+ public static final int HIGH_QUALITY = 1;
+ public static final int MEDIUM_QUALITY = 2;
+ public static final int LOW_QUALITY = 4;
+ */
+
+ /**
+ * Contructor.
+ * The scalefactor scales the calculated float pcm samples to short values
+ * (raw pcm samples are in [-1.0, 1.0], if no violations occur).
+ */
+ public SynthesisFilter(int channelnumber, float factor, float[] eq0)
+ {
+ if (d==null)
+ {
+ d = load_d();
+ d16 = splitArray(d, 16);
+ }
+
+ v1 = new float[512];
+ v2 = new float[512];
+ samples = new float[32];
+ channel = channelnumber;
+ scalefactor = factor;
+ setEQ(eq);
+ //setQuality(HIGH_QUALITY);
+
+ reset();
+ }
+
+ public void setEQ(float[] eq0)
+ {
+ this.eq = eq0;
+ if (eq==null)
+ {
+ eq = new float[32];
+ for (int i=0; i<32; i++)
+ eq[i] = 1.0f;
+ }
+ if (eq.length<32)
+ {
+ throw new IllegalArgumentException("eq0");
+ }
+
+ }
+
+ /*
+ private void setQuality(int quality0)
+ {
+ switch (quality0)
+ {
+ case HIGH_QUALITY:
+ case MEDIUM_QUALITY:
+ case LOW_QUALITY:
+ v_inc = 16 * quality0;
+ quality = quality0;
+ break;
+ default :
+ throw new IllegalArgumentException("Unknown quality value");
+ }
+ }
+
+ public int getQuality()
+ {
+ return quality;
+ }
+ */
+
+ /**
+ * Reset the synthesis filter.
+ */
+ public void reset()
+ {
+ //float[] floatp;
+ // float[] floatp2;
+
+ // initialize v1[] and v2[]:
+ //for (floatp = v1 + 512, floatp2 = v2 + 512; floatp > v1; )
+ // *--floatp = *--floatp2 = 0.0;
+ for (int p=0;p<512;p++)
+ v1[p] = v2[p] = 0.0f;
+
+ // initialize samples[]:
+ //for (floatp = samples + 32; floatp > samples; )
+ // *--floatp = 0.0;
+ for (int p2=0;p2<32;p2++)
+ samples[p2] = 0.0f;
+
+ actual_v = v1;
+ actual_write_pos = 15;
+ }
+
+
+ /**
+ * Inject Sample.
+ */
+ public void input_sample(float sample, int subbandnumber)
+ {
+ samples[subbandnumber] = eq[subbandnumber]*sample;
+ }
+
+ public void input_samples(float[] s)
+ {
+ for (int i=31; i>=0; i--)
+ {
+ samples[i] = s[i]*eq[i];
+ }
+ }
+
+ /**
+ * Compute new values via a fast cosine transform.
+ */
+ private void compute_new_v()
+ {
+ // p is fully initialized from x1
+ //float[] p = _p;
+ // pp is fully initialized from p
+ //float[] pp = _pp;
+
+ //float[] new_v = _new_v;
+
+ //float[] new_v = new float[32]; // new V[0-15] and V[33-48] of Figure 3-A.2 in ISO DIS 11172-3
+ //float[] p = new float[16];
+ //float[] pp = new float[16];
+
+ /*
+ for (int i=31; i>=0; i--)
+ {
+ new_v[i] = 0.0f;
+ }
+ */
+
+ float new_v0, new_v1, new_v2, new_v3, new_v4, new_v5, new_v6, new_v7, new_v8, new_v9;
+ float new_v10, new_v11, new_v12, new_v13, new_v14, new_v15, new_v16, new_v17, new_v18, new_v19;
+ float new_v20, new_v21, new_v22, new_v23, new_v24, new_v25, new_v26, new_v27, new_v28, new_v29;
+ float new_v30, new_v31;
+
+ new_v0 = new_v1 = new_v2 = new_v3 = new_v4 = new_v5 = new_v6 = new_v7 = new_v8 = new_v9 =
+ new_v10 = new_v11 = new_v12 = new_v13 = new_v14 = new_v15 = new_v16 = new_v17 = new_v18 = new_v19 =
+ new_v20 = new_v21 = new_v22 = new_v23 = new_v24 = new_v25 = new_v26 = new_v27 = new_v28 = new_v29 =
+ new_v30 = new_v31 = 0.0f;
+
+
+// float[] new_v = new float[32]; // new V[0-15] and V[33-48] of Figure 3-A.2 in ISO DIS 11172-3
+// float[] p = new float[16];
+// float[] pp = new float[16];
+
+ float[] s = samples;
+
+ float s0 = s[0];
+ float s1 = s[1];
+ float s2 = s[2];
+ float s3 = s[3];
+ float s4 = s[4];
+ float s5 = s[5];
+ float s6 = s[6];
+ float s7 = s[7];
+ float s8 = s[8];
+ float s9 = s[9];
+ float s10 = s[10];
+ float s11 = s[11];
+ float s12 = s[12];
+ float s13 = s[13];
+ float s14 = s[14];
+ float s15 = s[15];
+ float s16 = s[16];
+ float s17 = s[17];
+ float s18 = s[18];
+ float s19 = s[19];
+ float s20 = s[20];
+ float s21 = s[21];
+ float s22 = s[22];
+ float s23 = s[23];
+ float s24 = s[24];
+ float s25 = s[25];
+ float s26 = s[26];
+ float s27 = s[27];
+ float s28 = s[28];
+ float s29 = s[29];
+ float s30 = s[30];
+ float s31 = s[31];
+
+ float p0 = s0 + s31;
+ float p1 = s1 + s30;
+ float p2 = s2 + s29;
+ float p3 = s3 + s28;
+ float p4 = s4 + s27;
+ float p5 = s5 + s26;
+ float p6 = s6 + s25;
+ float p7 = s7 + s24;
+ float p8 = s8 + s23;
+ float p9 = s9 + s22;
+ float p10 = s10 + s21;
+ float p11 = s11 + s20;
+ float p12 = s12 + s19;
+ float p13 = s13 + s18;
+ float p14 = s14 + s17;
+ float p15 = s15 + s16;
+
+ float pp0 = p0 + p15;
+ float pp1 = p1 + p14;
+ float pp2 = p2 + p13;
+ float pp3 = p3 + p12;
+ float pp4 = p4 + p11;
+ float pp5 = p5 + p10;
+ float pp6 = p6 + p9;
+ float pp7 = p7 + p8;
+ float pp8 = (p0 - p15) * cos1_32;
+ float pp9 = (p1 - p14) * cos3_32;
+ float pp10 = (p2 - p13) * cos5_32;
+ float pp11 = (p3 - p12) * cos7_32;
+ float pp12 = (p4 - p11) * cos9_32;
+ float pp13 = (p5 - p10) * cos11_32;
+ float pp14 = (p6 - p9) * cos13_32;
+ float pp15 = (p7 - p8) * cos15_32;
+
+ p0 = pp0 + pp7;
+ p1 = pp1 + pp6;
+ p2 = pp2 + pp5;
+ p3 = pp3 + pp4;
+ p4 = (pp0 - pp7) * cos1_16;
+ p5 = (pp1 - pp6) * cos3_16;
+ p6 = (pp2 - pp5) * cos5_16;
+ p7 = (pp3 - pp4) * cos7_16;
+ p8 = pp8 + pp15;
+ p9 = pp9 + pp14;
+ p10 = pp10 + pp13;
+ p11 = pp11 + pp12;
+ p12 = (pp8 - pp15) * cos1_16;
+ p13 = (pp9 - pp14) * cos3_16;
+ p14 = (pp10 - pp13) * cos5_16;
+ p15 = (pp11 - pp12) * cos7_16;
+
+
+ pp0 = p0 + p3;
+ pp1 = p1 + p2;
+ pp2 = (p0 - p3) * cos1_8;
+ pp3 = (p1 - p2) * cos3_8;
+ pp4 = p4 + p7;
+ pp5 = p5 + p6;
+ pp6 = (p4 - p7) * cos1_8;
+ pp7 = (p5 - p6) * cos3_8;
+ pp8 = p8 + p11;
+ pp9 = p9 + p10;
+ pp10 = (p8 - p11) * cos1_8;
+ pp11 = (p9 - p10) * cos3_8;
+ pp12 = p12 + p15;
+ pp13 = p13 + p14;
+ pp14 = (p12 - p15) * cos1_8;
+ pp15 = (p13 - p14) * cos3_8;
+
+ p0 = pp0 + pp1;
+ p1 = (pp0 - pp1) * cos1_4;
+ p2 = pp2 + pp3;
+ p3 = (pp2 - pp3) * cos1_4;
+ p4 = pp4 + pp5;
+ p5 = (pp4 - pp5) * cos1_4;
+ p6 = pp6 + pp7;
+ p7 = (pp6 - pp7) * cos1_4;
+ p8 = pp8 + pp9;
+ p9 = (pp8 - pp9) * cos1_4;
+ p10 = pp10 + pp11;
+ p11 = (pp10 - pp11) * cos1_4;
+ p12 = pp12 + pp13;
+ p13 = (pp12 - pp13) * cos1_4;
+ p14 = pp14 + pp15;
+ p15 = (pp14 - pp15) * cos1_4;
+
+ // this is pretty insane coding
+ float tmp1;
+ new_v19/*36-17*/ = -(new_v4 = (new_v12 = p7) + p5) - p6;
+ new_v27/*44-17*/ = -p6 - p7 - p4;
+ new_v6 = (new_v10 = (new_v14 = p15) + p11) + p13;
+ new_v17/*34-17*/ = -(new_v2 = p15 + p13 + p9) - p14;
+ new_v21/*38-17*/ = (tmp1 = -p14 - p15 - p10 - p11) - p13;
+ new_v29/*46-17*/ = -p14 - p15 - p12 - p8;
+ new_v25/*42-17*/ = tmp1 - p12;
+ new_v31/*48-17*/ = -p0;
+ new_v0 = p1;
+ new_v23/*40-17*/ = -(new_v8 = p3) - p2;
+
+ p0 = (s0 - s31) * cos1_64;
+ p1 = (s1 - s30) * cos3_64;
+ p2 = (s2 - s29) * cos5_64;
+ p3 = (s3 - s28) * cos7_64;
+ p4 = (s4 - s27) * cos9_64;
+ p5 = (s5 - s26) * cos11_64;
+ p6 = (s6 - s25) * cos13_64;
+ p7 = (s7 - s24) * cos15_64;
+ p8 = (s8 - s23) * cos17_64;
+ p9 = (s9 - s22) * cos19_64;
+ p10 = (s10 - s21) * cos21_64;
+ p11 = (s11 - s20) * cos23_64;
+ p12 = (s12 - s19) * cos25_64;
+ p13 = (s13 - s18) * cos27_64;
+ p14 = (s14 - s17) * cos29_64;
+ p15 = (s15 - s16) * cos31_64;
+
+
+ pp0 = p0 + p15;
+ pp1 = p1 + p14;
+ pp2 = p2 + p13;
+ pp3 = p3 + p12;
+ pp4 = p4 + p11;
+ pp5 = p5 + p10;
+ pp6 = p6 + p9;
+ pp7 = p7 + p8;
+ pp8 = (p0 - p15) * cos1_32;
+ pp9 = (p1 - p14) * cos3_32;
+ pp10 = (p2 - p13) * cos5_32;
+ pp11 = (p3 - p12) * cos7_32;
+ pp12 = (p4 - p11) * cos9_32;
+ pp13 = (p5 - p10) * cos11_32;
+ pp14 = (p6 - p9) * cos13_32;
+ pp15 = (p7 - p8) * cos15_32;
+
+
+ p0 = pp0 + pp7;
+ p1 = pp1 + pp6;
+ p2 = pp2 + pp5;
+ p3 = pp3 + pp4;
+ p4 = (pp0 - pp7) * cos1_16;
+ p5 = (pp1 - pp6) * cos3_16;
+ p6 = (pp2 - pp5) * cos5_16;
+ p7 = (pp3 - pp4) * cos7_16;
+ p8 = pp8 + pp15;
+ p9 = pp9 + pp14;
+ p10 = pp10 + pp13;
+ p11 = pp11 + pp12;
+ p12 = (pp8 - pp15) * cos1_16;
+ p13 = (pp9 - pp14) * cos3_16;
+ p14 = (pp10 - pp13) * cos5_16;
+ p15 = (pp11 - pp12) * cos7_16;
+
+
+ pp0 = p0 + p3;
+ pp1 = p1 + p2;
+ pp2 = (p0 - p3) * cos1_8;
+ pp3 = (p1 - p2) * cos3_8;
+ pp4 = p4 + p7;
+ pp5 = p5 + p6;
+ pp6 = (p4 - p7) * cos1_8;
+ pp7 = (p5 - p6) * cos3_8;
+ pp8 = p8 + p11;
+ pp9 = p9 + p10;
+ pp10 = (p8 - p11) * cos1_8;
+ pp11 = (p9 - p10) * cos3_8;
+ pp12 = p12 + p15;
+ pp13 = p13 + p14;
+ pp14 = (p12 - p15) * cos1_8;
+ pp15 = (p13 - p14) * cos3_8;
+
+
+ p0 = pp0 + pp1;
+ p1 = (pp0 - pp1) * cos1_4;
+ p2 = pp2 + pp3;
+ p3 = (pp2 - pp3) * cos1_4;
+ p4 = pp4 + pp5;
+ p5 = (pp4 - pp5) * cos1_4;
+ p6 = pp6 + pp7;
+ p7 = (pp6 - pp7) * cos1_4;
+ p8 = pp8 + pp9;
+ p9 = (pp8 - pp9) * cos1_4;
+ p10 = pp10 + pp11;
+ p11 = (pp10 - pp11) * cos1_4;
+ p12 = pp12 + pp13;
+ p13 = (pp12 - pp13) * cos1_4;
+ p14 = pp14 + pp15;
+ p15 = (pp14 - pp15) * cos1_4;
+
+
+ // manually doing something that a compiler should handle sucks
+ // coding like this is hard to read
+ float tmp2;
+ new_v5 = (new_v11 = (new_v13 = (new_v15 = p15) + p7) + p11)
+ + p5 + p13;
+ new_v7 = (new_v9 = p15 + p11 + p3) + p13;
+ new_v16/*33-17*/ = -(new_v1 = (tmp1 = p13 + p15 + p9) + p1) - p14;
+ new_v18/*35-17*/ = -(new_v3 = tmp1 + p5 + p7) - p6 - p14;
+
+ new_v22/*39-17*/ = (tmp1 = -p10 - p11 - p14 - p15)
+ - p13 - p2 - p3;
+ new_v20/*37-17*/ = tmp1 - p13 - p5 - p6 - p7;
+ new_v24/*41-17*/ = tmp1 - p12 - p2 - p3;
+ new_v26/*43-17*/ = tmp1 - p12 - (tmp2 = p4 + p6 + p7);
+ new_v30/*47-17*/ = (tmp1 = -p8 - p12 - p14 - p15) - p0;
+ new_v28/*45-17*/ = tmp1 - tmp2;
+
+ // insert V[0-15] (== new_v[0-15]) into actual v:
+ // float[] x2 = actual_v + actual_write_pos;
+ float dest[] = actual_v;
+
+ int pos = actual_write_pos;
+
+ dest[0 + pos] = new_v0;
+ dest[16 + pos] = new_v1;
+ dest[32 + pos] = new_v2;
+ dest[48 + pos] = new_v3;
+ dest[64 + pos] = new_v4;
+ dest[80 + pos] = new_v5;
+ dest[96 + pos] = new_v6;
+ dest[112 + pos] = new_v7;
+ dest[128 + pos] = new_v8;
+ dest[144 + pos] = new_v9;
+ dest[160 + pos] = new_v10;
+ dest[176 + pos] = new_v11;
+ dest[192 + pos] = new_v12;
+ dest[208 + pos] = new_v13;
+ dest[224 + pos] = new_v14;
+ dest[240 + pos] = new_v15;
+
+ // V[16] is always 0.0:
+ dest[256 + pos] = 0.0f;
+
+ // insert V[17-31] (== -new_v[15-1]) into actual v:
+ dest[272 + pos] = -new_v15;
+ dest[288 + pos] = -new_v14;
+ dest[304 + pos] = -new_v13;
+ dest[320 + pos] = -new_v12;
+ dest[336 + pos] = -new_v11;
+ dest[352 + pos] = -new_v10;
+ dest[368 + pos] = -new_v9;
+ dest[384 + pos] = -new_v8;
+ dest[400 + pos] = -new_v7;
+ dest[416 + pos] = -new_v6;
+ dest[432 + pos] = -new_v5;
+ dest[448 + pos] = -new_v4;
+ dest[464 + pos] = -new_v3;
+ dest[480 + pos] = -new_v2;
+ dest[496 + pos] = -new_v1;
+
+ // insert V[32] (== -new_v[0]) into other v:
+ dest = (actual_v==v1) ? v2 : v1;
+
+ dest[0 + pos] = -new_v0;
+ // insert V[33-48] (== new_v[16-31]) into other v:
+ dest[16 + pos] = new_v16;
+ dest[32 + pos] = new_v17;
+ dest[48 + pos] = new_v18;
+ dest[64 + pos] = new_v19;
+ dest[80 + pos] = new_v20;
+ dest[96 + pos] = new_v21;
+ dest[112 + pos] = new_v22;
+ dest[128 + pos] = new_v23;
+ dest[144 + pos] = new_v24;
+ dest[160 + pos] = new_v25;
+ dest[176 + pos] = new_v26;
+ dest[192 + pos] = new_v27;
+ dest[208 + pos] = new_v28;
+ dest[224 + pos] = new_v29;
+ dest[240 + pos] = new_v30;
+ dest[256 + pos] = new_v31;
+
+ // insert V[49-63] (== new_v[30-16]) into other v:
+ dest[272 + pos] = new_v30;
+ dest[288 + pos] = new_v29;
+ dest[304 + pos] = new_v28;
+ dest[320 + pos] = new_v27;
+ dest[336 + pos] = new_v26;
+ dest[352 + pos] = new_v25;
+ dest[368 + pos] = new_v24;
+ dest[384 + pos] = new_v23;
+ dest[400 + pos] = new_v22;
+ dest[416 + pos] = new_v21;
+ dest[432 + pos] = new_v20;
+ dest[448 + pos] = new_v19;
+ dest[464 + pos] = new_v18;
+ dest[480 + pos] = new_v17;
+ dest[496 + pos] = new_v16;
+/*
+ }
+ else
+ {
+ v1[0 + actual_write_pos] = -new_v0;
+ // insert V[33-48] (== new_v[16-31]) into other v:
+ v1[16 + actual_write_pos] = new_v16;
+ v1[32 + actual_write_pos] = new_v17;
+ v1[48 + actual_write_pos] = new_v18;
+ v1[64 + actual_write_pos] = new_v19;
+ v1[80 + actual_write_pos] = new_v20;
+ v1[96 + actual_write_pos] = new_v21;
+ v1[112 + actual_write_pos] = new_v22;
+ v1[128 + actual_write_pos] = new_v23;
+ v1[144 + actual_write_pos] = new_v24;
+ v1[160 + actual_write_pos] = new_v25;
+ v1[176 + actual_write_pos] = new_v26;
+ v1[192 + actual_write_pos] = new_v27;
+ v1[208 + actual_write_pos] = new_v28;
+ v1[224 + actual_write_pos] = new_v29;
+ v1[240 + actual_write_pos] = new_v30;
+ v1[256 + actual_write_pos] = new_v31;
+
+ // insert V[49-63] (== new_v[30-16]) into other v:
+ v1[272 + actual_write_pos] = new_v30;
+ v1[288 + actual_write_pos] = new_v29;
+ v1[304 + actual_write_pos] = new_v28;
+ v1[320 + actual_write_pos] = new_v27;
+ v1[336 + actual_write_pos] = new_v26;
+ v1[352 + actual_write_pos] = new_v25;
+ v1[368 + actual_write_pos] = new_v24;
+ v1[384 + actual_write_pos] = new_v23;
+ v1[400 + actual_write_pos] = new_v22;
+ v1[416 + actual_write_pos] = new_v21;
+ v1[432 + actual_write_pos] = new_v20;
+ v1[448 + actual_write_pos] = new_v19;
+ v1[464 + actual_write_pos] = new_v18;
+ v1[480 + actual_write_pos] = new_v17;
+ v1[496 + actual_write_pos] = new_v16;
+ }
+*/
+ }
+
+ /**
+ * Compute new values via a fast cosine transform.
+ */
+ private void compute_new_v_old()
+ {
+ // p is fully initialized from x1
+ //float[] p = _p;
+ // pp is fully initialized from p
+ //float[] pp = _pp;
+
+ //float[] new_v = _new_v;
+
+ float[] new_v = new float[32]; // new V[0-15] and V[33-48] of Figure 3-A.2 in ISO DIS 11172-3
+ float[] p = new float[16];
+ float[] pp = new float[16];
+
+
+ for (int i=31; i>=0; i--)
+ {
+ new_v[i] = 0.0f;
+ }
+
+// float[] new_v = new float[32]; // new V[0-15] and V[33-48] of Figure 3-A.2 in ISO DIS 11172-3
+// float[] p = new float[16];
+// float[] pp = new float[16];
+
+ float[] x1 = samples;
+
+ p[0] = x1[0] + x1[31];
+ p[1] = x1[1] + x1[30];
+ p[2] = x1[2] + x1[29];
+ p[3] = x1[3] + x1[28];
+ p[4] = x1[4] + x1[27];
+ p[5] = x1[5] + x1[26];
+ p[6] = x1[6] + x1[25];
+ p[7] = x1[7] + x1[24];
+ p[8] = x1[8] + x1[23];
+ p[9] = x1[9] + x1[22];
+ p[10] = x1[10] + x1[21];
+ p[11] = x1[11] + x1[20];
+ p[12] = x1[12] + x1[19];
+ p[13] = x1[13] + x1[18];
+ p[14] = x1[14] + x1[17];
+ p[15] = x1[15] + x1[16];
+
+ pp[0] = p[0] + p[15];
+ pp[1] = p[1] + p[14];
+ pp[2] = p[2] + p[13];
+ pp[3] = p[3] + p[12];
+ pp[4] = p[4] + p[11];
+ pp[5] = p[5] + p[10];
+ pp[6] = p[6] + p[9];
+ pp[7] = p[7] + p[8];
+ pp[8] = (p[0] - p[15]) * cos1_32;
+ pp[9] = (p[1] - p[14]) * cos3_32;
+ pp[10] = (p[2] - p[13]) * cos5_32;
+ pp[11] = (p[3] - p[12]) * cos7_32;
+ pp[12] = (p[4] - p[11]) * cos9_32;
+ pp[13] = (p[5] - p[10]) * cos11_32;
+ pp[14] = (p[6] - p[9]) * cos13_32;
+ pp[15] = (p[7] - p[8]) * cos15_32;
+
+ p[0] = pp[0] + pp[7];
+ p[1] = pp[1] + pp[6];
+ p[2] = pp[2] + pp[5];
+ p[3] = pp[3] + pp[4];
+ p[4] = (pp[0] - pp[7]) * cos1_16;
+ p[5] = (pp[1] - pp[6]) * cos3_16;
+ p[6] = (pp[2] - pp[5]) * cos5_16;
+ p[7] = (pp[3] - pp[4]) * cos7_16;
+ p[8] = pp[8] + pp[15];
+ p[9] = pp[9] + pp[14];
+ p[10] = pp[10] + pp[13];
+ p[11] = pp[11] + pp[12];
+ p[12] = (pp[8] - pp[15]) * cos1_16;
+ p[13] = (pp[9] - pp[14]) * cos3_16;
+ p[14] = (pp[10] - pp[13]) * cos5_16;
+ p[15] = (pp[11] - pp[12]) * cos7_16;
+
+
+ pp[0] = p[0] + p[3];
+ pp[1] = p[1] + p[2];
+ pp[2] = (p[0] - p[3]) * cos1_8;
+ pp[3] = (p[1] - p[2]) * cos3_8;
+ pp[4] = p[4] + p[7];
+ pp[5] = p[5] + p[6];
+ pp[6] = (p[4] - p[7]) * cos1_8;
+ pp[7] = (p[5] - p[6]) * cos3_8;
+ pp[8] = p[8] + p[11];
+ pp[9] = p[9] + p[10];
+ pp[10] = (p[8] - p[11]) * cos1_8;
+ pp[11] = (p[9] - p[10]) * cos3_8;
+ pp[12] = p[12] + p[15];
+ pp[13] = p[13] + p[14];
+ pp[14] = (p[12] - p[15]) * cos1_8;
+ pp[15] = (p[13] - p[14]) * cos3_8;
+
+ p[0] = pp[0] + pp[1];
+ p[1] = (pp[0] - pp[1]) * cos1_4;
+ p[2] = pp[2] + pp[3];
+ p[3] = (pp[2] - pp[3]) * cos1_4;
+ p[4] = pp[4] + pp[5];
+ p[5] = (pp[4] - pp[5]) * cos1_4;
+ p[6] = pp[6] + pp[7];
+ p[7] = (pp[6] - pp[7]) * cos1_4;
+ p[8] = pp[8] + pp[9];
+ p[9] = (pp[8] - pp[9]) * cos1_4;
+ p[10] = pp[10] + pp[11];
+ p[11] = (pp[10] - pp[11]) * cos1_4;
+ p[12] = pp[12] + pp[13];
+ p[13] = (pp[12] - pp[13]) * cos1_4;
+ p[14] = pp[14] + pp[15];
+ p[15] = (pp[14] - pp[15]) * cos1_4;
+
+ // this is pretty insane coding
+ float tmp1;
+ new_v[36-17] = -(new_v[4] = (new_v[12] = p[7]) + p[5]) - p[6];
+ new_v[44-17] = -p[6] - p[7] - p[4];
+ new_v[6] = (new_v[10] = (new_v[14] = p[15]) + p[11]) + p[13];
+ new_v[34-17] = -(new_v[2] = p[15] + p[13] + p[9]) - p[14];
+ new_v[38-17] = (tmp1 = -p[14] - p[15] - p[10] - p[11]) - p[13];
+ new_v[46-17] = -p[14] - p[15] - p[12] - p[8];
+ new_v[42-17] = tmp1 - p[12];
+ new_v[48-17] = -p[0];
+ new_v[0] = p[1];
+ new_v[40-17] = -(new_v[8] = p[3]) - p[2];
+
+ p[0] = (x1[0] - x1[31]) * cos1_64;
+ p[1] = (x1[1] - x1[30]) * cos3_64;
+ p[2] = (x1[2] - x1[29]) * cos5_64;
+ p[3] = (x1[3] - x1[28]) * cos7_64;
+ p[4] = (x1[4] - x1[27]) * cos9_64;
+ p[5] = (x1[5] - x1[26]) * cos11_64;
+ p[6] = (x1[6] - x1[25]) * cos13_64;
+ p[7] = (x1[7] - x1[24]) * cos15_64;
+ p[8] = (x1[8] - x1[23]) * cos17_64;
+ p[9] = (x1[9] - x1[22]) * cos19_64;
+ p[10] = (x1[10] - x1[21]) * cos21_64;
+ p[11] = (x1[11] - x1[20]) * cos23_64;
+ p[12] = (x1[12] - x1[19]) * cos25_64;
+ p[13] = (x1[13] - x1[18]) * cos27_64;
+ p[14] = (x1[14] - x1[17]) * cos29_64;
+ p[15] = (x1[15] - x1[16]) * cos31_64;
+
+
+ pp[0] = p[0] + p[15];
+ pp[1] = p[1] + p[14];
+ pp[2] = p[2] + p[13];
+ pp[3] = p[3] + p[12];
+ pp[4] = p[4] + p[11];
+ pp[5] = p[5] + p[10];
+ pp[6] = p[6] + p[9];
+ pp[7] = p[7] + p[8];
+ pp[8] = (p[0] - p[15]) * cos1_32;
+ pp[9] = (p[1] - p[14]) * cos3_32;
+ pp[10] = (p[2] - p[13]) * cos5_32;
+ pp[11] = (p[3] - p[12]) * cos7_32;
+ pp[12] = (p[4] - p[11]) * cos9_32;
+ pp[13] = (p[5] - p[10]) * cos11_32;
+ pp[14] = (p[6] - p[9]) * cos13_32;
+ pp[15] = (p[7] - p[8]) * cos15_32;
+
+
+ p[0] = pp[0] + pp[7];
+ p[1] = pp[1] + pp[6];
+ p[2] = pp[2] + pp[5];
+ p[3] = pp[3] + pp[4];
+ p[4] = (pp[0] - pp[7]) * cos1_16;
+ p[5] = (pp[1] - pp[6]) * cos3_16;
+ p[6] = (pp[2] - pp[5]) * cos5_16;
+ p[7] = (pp[3] - pp[4]) * cos7_16;
+ p[8] = pp[8] + pp[15];
+ p[9] = pp[9] + pp[14];
+ p[10] = pp[10] + pp[13];
+ p[11] = pp[11] + pp[12];
+ p[12] = (pp[8] - pp[15]) * cos1_16;
+ p[13] = (pp[9] - pp[14]) * cos3_16;
+ p[14] = (pp[10] - pp[13]) * cos5_16;
+ p[15] = (pp[11] - pp[12]) * cos7_16;
+
+
+ pp[0] = p[0] + p[3];
+ pp[1] = p[1] + p[2];
+ pp[2] = (p[0] - p[3]) * cos1_8;
+ pp[3] = (p[1] - p[2]) * cos3_8;
+ pp[4] = p[4] + p[7];
+ pp[5] = p[5] + p[6];
+ pp[6] = (p[4] - p[7]) * cos1_8;
+ pp[7] = (p[5] - p[6]) * cos3_8;
+ pp[8] = p[8] + p[11];
+ pp[9] = p[9] + p[10];
+ pp[10] = (p[8] - p[11]) * cos1_8;
+ pp[11] = (p[9] - p[10]) * cos3_8;
+ pp[12] = p[12] + p[15];
+ pp[13] = p[13] + p[14];
+ pp[14] = (p[12] - p[15]) * cos1_8;
+ pp[15] = (p[13] - p[14]) * cos3_8;
+
+
+ p[0] = pp[0] + pp[1];
+ p[1] = (pp[0] - pp[1]) * cos1_4;
+ p[2] = pp[2] + pp[3];
+ p[3] = (pp[2] - pp[3]) * cos1_4;
+ p[4] = pp[4] + pp[5];
+ p[5] = (pp[4] - pp[5]) * cos1_4;
+ p[6] = pp[6] + pp[7];
+ p[7] = (pp[6] - pp[7]) * cos1_4;
+ p[8] = pp[8] + pp[9];
+ p[9] = (pp[8] - pp[9]) * cos1_4;
+ p[10] = pp[10] + pp[11];
+ p[11] = (pp[10] - pp[11]) * cos1_4;
+ p[12] = pp[12] + pp[13];
+ p[13] = (pp[12] - pp[13]) * cos1_4;
+ p[14] = pp[14] + pp[15];
+ p[15] = (pp[14] - pp[15]) * cos1_4;
+
+
+ // manually doing something that a compiler should handle sucks
+ // coding like this is hard to read
+ float tmp2;
+ new_v[5] = (new_v[11] = (new_v[13] = (new_v[15] = p[15]) + p[7]) + p[11])
+ + p[5] + p[13];
+ new_v[7] = (new_v[9] = p[15] + p[11] + p[3]) + p[13];
+ new_v[33-17] = -(new_v[1] = (tmp1 = p[13] + p[15] + p[9]) + p[1]) - p[14];
+ new_v[35-17] = -(new_v[3] = tmp1 + p[5] + p[7]) - p[6] - p[14];
+
+ new_v[39-17] = (tmp1 = -p[10] - p[11] - p[14] - p[15])
+ - p[13] - p[2] - p[3];
+ new_v[37-17] = tmp1 - p[13] - p[5] - p[6] - p[7];
+ new_v[41-17] = tmp1 - p[12] - p[2] - p[3];
+ new_v[43-17] = tmp1 - p[12] - (tmp2 = p[4] + p[6] + p[7]);
+ new_v[47-17] = (tmp1 = -p[8] - p[12] - p[14] - p[15]) - p[0];
+ new_v[45-17] = tmp1 - tmp2;
+
+ // insert V[0-15] (== new_v[0-15]) into actual v:
+ x1 = new_v;
+ // float[] x2 = actual_v + actual_write_pos;
+ float[] dest = actual_v;
+
+ dest[0 + actual_write_pos] = x1[0];
+ dest[16 + actual_write_pos] = x1[1];
+ dest[32 + actual_write_pos] = x1[2];
+ dest[48 + actual_write_pos] = x1[3];
+ dest[64 + actual_write_pos] = x1[4];
+ dest[80 + actual_write_pos] = x1[5];
+ dest[96 + actual_write_pos] = x1[6];
+ dest[112 + actual_write_pos] = x1[7];
+ dest[128 + actual_write_pos] = x1[8];
+ dest[144 + actual_write_pos] = x1[9];
+ dest[160 + actual_write_pos] = x1[10];
+ dest[176 + actual_write_pos] = x1[11];
+ dest[192 + actual_write_pos] = x1[12];
+ dest[208 + actual_write_pos] = x1[13];
+ dest[224 + actual_write_pos] = x1[14];
+ dest[240 + actual_write_pos] = x1[15];
+
+ // V[16] is always 0.0:
+ dest[256 + actual_write_pos] = 0.0f;
+
+ // insert V[17-31] (== -new_v[15-1]) into actual v:
+ dest[272 + actual_write_pos] = -x1[15];
+ dest[288 + actual_write_pos] = -x1[14];
+ dest[304 + actual_write_pos] = -x1[13];
+ dest[320 + actual_write_pos] = -x1[12];
+ dest[336 + actual_write_pos] = -x1[11];
+ dest[352 + actual_write_pos] = -x1[10];
+ dest[368 + actual_write_pos] = -x1[9];
+ dest[384 + actual_write_pos] = -x1[8];
+ dest[400 + actual_write_pos] = -x1[7];
+ dest[416 + actual_write_pos] = -x1[6];
+ dest[432 + actual_write_pos] = -x1[5];
+ dest[448 + actual_write_pos] = -x1[4];
+ dest[464 + actual_write_pos] = -x1[3];
+ dest[480 + actual_write_pos] = -x1[2];
+ dest[496 + actual_write_pos] = -x1[1];
+
+ // insert V[32] (== -new_v[0]) into other v:
+
+ }
+
+ /**
+ * Compute PCM Samples.
+ */
+
+ private float[] _tmpOut = new float[32];
+
+
+ private void compute_pcm_samples0(Obuffer buffer)
+ {
+ final float[] vp = actual_v;
+ //int inc = v_inc;
+ final float[] tmpOut = _tmpOut;
+ int dvp =0;
+
+ // fat chance of having this loop unroll
+ for( int i=0; i<32; i++)
+ {
+ float pcm_sample;
+ final float[] dp = d16[i];
+ pcm_sample = (float)(((vp[0 + dvp] * dp[0]) +
+ (vp[15 + dvp] * dp[1]) +
+ (vp[14 + dvp] * dp[2]) +
+ (vp[13 + dvp] * dp[3]) +
+ (vp[12 + dvp] * dp[4]) +
+ (vp[11 + dvp] * dp[5]) +
+ (vp[10 + dvp] * dp[6]) +
+ (vp[9 + dvp] * dp[7]) +
+ (vp[8 + dvp] * dp[8]) +
+ (vp[7 + dvp] * dp[9]) +
+ (vp[6 + dvp] * dp[10]) +
+ (vp[5 + dvp] * dp[11]) +
+ (vp[4 + dvp] * dp[12]) +
+ (vp[3 + dvp] * dp[13]) +
+ (vp[2 + dvp] * dp[14]) +
+ (vp[1 + dvp] * dp[15])
+ ) * scalefactor);
+
+ tmpOut[i] = pcm_sample;
+
+ dvp += 16;
+ } // for
+ }
+
+ private void compute_pcm_samples1(Obuffer buffer)
+ {
+ final float[] vp = actual_v;
+ //int inc = v_inc;
+ final float[] tmpOut = _tmpOut;
+ int dvp =0;
+
+ // fat chance of having this loop unroll
+ for( int i=0; i<32; i++)
+ {
+ final float[] dp = d16[i];
+ float pcm_sample;
+
+ pcm_sample = (float)(((vp[1 + dvp] * dp[0]) +
+ (vp[0 + dvp] * dp[1]) +
+ (vp[15 + dvp] * dp[2]) +
+ (vp[14 + dvp] * dp[3]) +
+ (vp[13 + dvp] * dp[4]) +
+ (vp[12 + dvp] * dp[5]) +
+ (vp[11 + dvp] * dp[6]) +
+ (vp[10 + dvp] * dp[7]) +
+ (vp[9 + dvp] * dp[8]) +
+ (vp[8 + dvp] * dp[9]) +
+ (vp[7 + dvp] * dp[10]) +
+ (vp[6 + dvp] * dp[11]) +
+ (vp[5 + dvp] * dp[12]) +
+ (vp[4 + dvp] * dp[13]) +
+ (vp[3 + dvp] * dp[14]) +
+ (vp[2 + dvp] * dp[15])
+ ) * scalefactor);
+
+ tmpOut[i] = pcm_sample;
+
+ dvp += 16;
+ } // for
+ }
+ private void compute_pcm_samples2(Obuffer buffer)
+ {
+ final float[] vp = actual_v;
+
+ //int inc = v_inc;
+ final float[] tmpOut = _tmpOut;
+ int dvp =0;
+
+ // fat chance of having this loop unroll
+ for( int i=0; i<32; i++)
+ {
+ final float[] dp = d16[i];
+ float pcm_sample;
+
+ pcm_sample = (float)(((vp[2 + dvp] * dp[0]) +
+ (vp[1 + dvp] * dp[1]) +
+ (vp[0 + dvp] * dp[2]) +
+ (vp[15 + dvp] * dp[3]) +
+ (vp[14 + dvp] * dp[4]) +
+ (vp[13 + dvp] * dp[5]) +
+ (vp[12 + dvp] * dp[6]) +
+ (vp[11 + dvp] * dp[7]) +
+ (vp[10 + dvp] * dp[8]) +
+ (vp[9 + dvp] * dp[9]) +
+ (vp[8 + dvp] * dp[10]) +
+ (vp[7 + dvp] * dp[11]) +
+ (vp[6 + dvp] * dp[12]) +
+ (vp[5 + dvp] * dp[13]) +
+ (vp[4 + dvp] * dp[14]) +
+ (vp[3 + dvp] * dp[15])
+ ) * scalefactor);
+
+ tmpOut[i] = pcm_sample;
+
+ dvp += 16;
+ } // for
+ }
+
+ private void compute_pcm_samples3(Obuffer buffer)
+ {
+ final float[] vp = actual_v;
+
+ int idx = 0;
+ //int inc = v_inc;
+ final float[] tmpOut = _tmpOut;
+ int dvp =0;
+
+ // fat chance of having this loop unroll
+ for( int i=0; i<32; i++)
+ {
+ final float[] dp = d16[i];
+ float pcm_sample;
+
+ pcm_sample = (float)(((vp[3 + dvp] * dp[0]) +
+ (vp[2 + dvp] * dp[1]) +
+ (vp[1 + dvp] * dp[2]) +
+ (vp[0 + dvp] * dp[3]) +
+ (vp[15 + dvp] * dp[4]) +
+ (vp[14 + dvp] * dp[5]) +
+ (vp[13 + dvp] * dp[6]) +
+ (vp[12 + dvp] * dp[7]) +
+ (vp[11 + dvp] * dp[8]) +
+ (vp[10 + dvp] * dp[9]) +
+ (vp[9 + dvp] * dp[10]) +
+ (vp[8 + dvp] * dp[11]) +
+ (vp[7 + dvp] * dp[12]) +
+ (vp[6 + dvp] * dp[13]) +
+ (vp[5 + dvp] * dp[14]) +
+ (vp[4 + dvp] * dp[15])
+ ) * scalefactor);
+
+ tmpOut[i] = pcm_sample;
+
+ dvp += 16;
+ } // for
+ }
+
+ private void compute_pcm_samples4(Obuffer buffer)
+ {
+ final float[] vp = actual_v;
+
+ //int inc = v_inc;
+ final float[] tmpOut = _tmpOut;
+ int dvp =0;
+
+ // fat chance of having this loop unroll
+ for( int i=0; i<32; i++)
+ {
+ final float[] dp = d16[i];
+ float pcm_sample;
+
+ pcm_sample = (float)(((vp[4 + dvp] * dp[0]) +
+ (vp[3 + dvp] * dp[1]) +
+ (vp[2 + dvp] * dp[2]) +
+ (vp[1 + dvp] * dp[3]) +
+ (vp[0 + dvp] * dp[4]) +
+ (vp[15 + dvp] * dp[5]) +
+ (vp[14 + dvp] * dp[6]) +
+ (vp[13 + dvp] * dp[7]) +
+ (vp[12 + dvp] * dp[8]) +
+ (vp[11 + dvp] * dp[9]) +
+ (vp[10 + dvp] * dp[10]) +
+ (vp[9 + dvp] * dp[11]) +
+ (vp[8 + dvp] * dp[12]) +
+ (vp[7 + dvp] * dp[13]) +
+ (vp[6 + dvp] * dp[14]) +
+ (vp[5 + dvp] * dp[15])
+ ) * scalefactor);
+
+ tmpOut[i] = pcm_sample;
+
+ dvp += 16;
+ } // for
+ }
+
+ private void compute_pcm_samples5(Obuffer buffer)
+ {
+ final float[] vp = actual_v;
+
+ //int inc = v_inc;
+ final float[] tmpOut = _tmpOut;
+ int dvp =0;
+
+ // fat chance of having this loop unroll
+ for( int i=0; i<32; i++)
+ {
+ final float[] dp = d16[i];
+ float pcm_sample;
+
+ pcm_sample = (float)(((vp[5 + dvp] * dp[0]) +
+ (vp[4 + dvp] * dp[1]) +
+ (vp[3 + dvp] * dp[2]) +
+ (vp[2 + dvp] * dp[3]) +
+ (vp[1 + dvp] * dp[4]) +
+ (vp[0 + dvp] * dp[5]) +
+ (vp[15 + dvp] * dp[6]) +
+ (vp[14 + dvp] * dp[7]) +
+ (vp[13 + dvp] * dp[8]) +
+ (vp[12 + dvp] * dp[9]) +
+ (vp[11 + dvp] * dp[10]) +
+ (vp[10 + dvp] * dp[11]) +
+ (vp[9 + dvp] * dp[12]) +
+ (vp[8 + dvp] * dp[13]) +
+ (vp[7 + dvp] * dp[14]) +
+ (vp[6 + dvp] * dp[15])
+ ) * scalefactor);
+
+ tmpOut[i] = pcm_sample;
+
+ dvp += 16;
+ } // for
+ }
+
+ private void compute_pcm_samples6(Obuffer buffer)
+ {
+ final float[] vp = actual_v;
+ //int inc = v_inc;
+ final float[] tmpOut = _tmpOut;
+ int dvp =0;
+
+ // fat chance of having this loop unroll
+ for( int i=0; i<32; i++)
+ {
+ final float[] dp = d16[i];
+ float pcm_sample;
+
+ pcm_sample = (float)(((vp[6 + dvp] * dp[0]) +
+ (vp[5 + dvp] * dp[1]) +
+ (vp[4 + dvp] * dp[2]) +
+ (vp[3 + dvp] * dp[3]) +
+ (vp[2 + dvp] * dp[4]) +
+ (vp[1 + dvp] * dp[5]) +
+ (vp[0 + dvp] * dp[6]) +
+ (vp[15 + dvp] * dp[7]) +
+ (vp[14 + dvp] * dp[8]) +
+ (vp[13 + dvp] * dp[9]) +
+ (vp[12 + dvp] * dp[10]) +
+ (vp[11 + dvp] * dp[11]) +
+ (vp[10 + dvp] * dp[12]) +
+ (vp[9 + dvp] * dp[13]) +
+ (vp[8 + dvp] * dp[14]) +
+ (vp[7 + dvp] * dp[15])
+ ) * scalefactor);
+
+ tmpOut[i] = pcm_sample;
+
+ dvp += 16;
+ } // for
+ }
+
+ private void compute_pcm_samples7(Obuffer buffer)
+ {
+ final float[] vp = actual_v;
+
+ //int inc = v_inc;
+ final float[] tmpOut = _tmpOut;
+ int dvp =0;
+
+ // fat chance of having this loop unroll
+ for( int i=0; i<32; i++)
+ {
+ final float[] dp = d16[i];
+ float pcm_sample;
+
+ pcm_sample = (float)(((vp[7 + dvp] * dp[0]) +
+ (vp[6 + dvp] * dp[1]) +
+ (vp[5 + dvp] * dp[2]) +
+ (vp[4 + dvp] * dp[3]) +
+ (vp[3 + dvp] * dp[4]) +
+ (vp[2 + dvp] * dp[5]) +
+ (vp[1 + dvp] * dp[6]) +
+ (vp[0 + dvp] * dp[7]) +
+ (vp[15 + dvp] * dp[8]) +
+ (vp[14 + dvp] * dp[9]) +
+ (vp[13 + dvp] * dp[10]) +
+ (vp[12 + dvp] * dp[11]) +
+ (vp[11 + dvp] * dp[12]) +
+ (vp[10 + dvp] * dp[13]) +
+ (vp[9 + dvp] * dp[14]) +
+ (vp[8 + dvp] * dp[15])
+ ) * scalefactor);
+
+ tmpOut[i] = pcm_sample;
+
+ dvp += 16;
+ } // for
+ }
+ private void compute_pcm_samples8(Obuffer buffer)
+ {
+ final float[] vp = actual_v;
+
+ //int inc = v_inc;
+ final float[] tmpOut = _tmpOut;
+ int dvp =0;
+
+ // fat chance of having this loop unroll
+ for( int i=0; i<32; i++)
+ {
+ final float[] dp = d16[i];
+ float pcm_sample;
+
+ pcm_sample = (float)(((vp[8 + dvp] * dp[0]) +
+ (vp[7 + dvp] * dp[1]) +
+ (vp[6 + dvp] * dp[2]) +
+ (vp[5 + dvp] * dp[3]) +
+ (vp[4 + dvp] * dp[4]) +
+ (vp[3 + dvp] * dp[5]) +
+ (vp[2 + dvp] * dp[6]) +
+ (vp[1 + dvp] * dp[7]) +
+ (vp[0 + dvp] * dp[8]) +
+ (vp[15 + dvp] * dp[9]) +
+ (vp[14 + dvp] * dp[10]) +
+ (vp[13 + dvp] * dp[11]) +
+ (vp[12 + dvp] * dp[12]) +
+ (vp[11 + dvp] * dp[13]) +
+ (vp[10 + dvp] * dp[14]) +
+ (vp[9 + dvp] * dp[15])
+ ) * scalefactor);
+
+ tmpOut[i] = pcm_sample;
+
+ dvp += 16;
+ } // for
+ }
+
+ private void compute_pcm_samples9(Obuffer buffer)
+ {
+ final float[] vp = actual_v;
+
+ //int inc = v_inc;
+ final float[] tmpOut = _tmpOut;
+ int dvp =0;
+
+ // fat chance of having this loop unroll
+ for( int i=0; i<32; i++)
+ {
+ final float[] dp = d16[i];
+ float pcm_sample;
+
+ pcm_sample = (float)(((vp[9 + dvp] * dp[0]) +
+ (vp[8 + dvp] * dp[1]) +
+ (vp[7 + dvp] * dp[2]) +
+ (vp[6 + dvp] * dp[3]) +
+ (vp[5 + dvp] * dp[4]) +
+ (vp[4 + dvp] * dp[5]) +
+ (vp[3 + dvp] * dp[6]) +
+ (vp[2 + dvp] * dp[7]) +
+ (vp[1 + dvp] * dp[8]) +
+ (vp[0 + dvp] * dp[9]) +
+ (vp[15 + dvp] * dp[10]) +
+ (vp[14 + dvp] * dp[11]) +
+ (vp[13 + dvp] * dp[12]) +
+ (vp[12 + dvp] * dp[13]) +
+ (vp[11 + dvp] * dp[14]) +
+ (vp[10 + dvp] * dp[15])
+ ) * scalefactor);
+
+ tmpOut[i] = pcm_sample;
+
+ dvp += 16;
+ } // for
+ }
+
+ private void compute_pcm_samples10(Obuffer buffer)
+ {
+ final float[] vp = actual_v;
+ //int inc = v_inc;
+ final float[] tmpOut = _tmpOut;
+ int dvp =0;
+
+ // fat chance of having this loop unroll
+ for( int i=0; i<32; i++)
+ {
+ final float[] dp = d16[i];
+ float pcm_sample;
+
+ pcm_sample = (float)(((vp[10 + dvp] * dp[0]) +
+ (vp[9 + dvp] * dp[1]) +
+ (vp[8 + dvp] * dp[2]) +
+ (vp[7 + dvp] * dp[3]) +
+ (vp[6 + dvp] * dp[4]) +
+ (vp[5 + dvp] * dp[5]) +
+ (vp[4 + dvp] * dp[6]) +
+ (vp[3 + dvp] * dp[7]) +
+ (vp[2 + dvp] * dp[8]) +
+ (vp[1 + dvp] * dp[9]) +
+ (vp[0 + dvp] * dp[10]) +
+ (vp[15 + dvp] * dp[11]) +
+ (vp[14 + dvp] * dp[12]) +
+ (vp[13 + dvp] * dp[13]) +
+ (vp[12 + dvp] * dp[14]) +
+ (vp[11 + dvp] * dp[15])
+ ) * scalefactor);
+
+ tmpOut[i] = pcm_sample;
+
+ dvp += 16;
+ } // for
+ }
+ private void compute_pcm_samples11(Obuffer buffer)
+ {
+ final float[] vp = actual_v;
+
+ //int inc = v_inc;
+ final float[] tmpOut = _tmpOut;
+ int dvp =0;
+
+ // fat chance of having this loop unroll
+ for( int i=0; i<32; i++)
+ {
+ final float[] dp = d16[i];
+ float pcm_sample;
+
+ pcm_sample = (float)(((vp[11 + dvp] * dp[0]) +
+ (vp[10 + dvp] * dp[1]) +
+ (vp[9 + dvp] * dp[2]) +
+ (vp[8 + dvp] * dp[3]) +
+ (vp[7 + dvp] * dp[4]) +
+ (vp[6 + dvp] * dp[5]) +
+ (vp[5 + dvp] * dp[6]) +
+ (vp[4 + dvp] * dp[7]) +
+ (vp[3 + dvp] * dp[8]) +
+ (vp[2 + dvp] * dp[9]) +
+ (vp[1 + dvp] * dp[10]) +
+ (vp[0 + dvp] * dp[11]) +
+ (vp[15 + dvp] * dp[12]) +
+ (vp[14 + dvp] * dp[13]) +
+ (vp[13 + dvp] * dp[14]) +
+ (vp[12 + dvp] * dp[15])
+ ) * scalefactor);
+
+ tmpOut[i] = pcm_sample;
+
+ dvp += 16;
+ } // for
+ }
+ private void compute_pcm_samples12(Obuffer buffer)
+ {
+ final float[] vp = actual_v;
+ //int inc = v_inc;
+ final float[] tmpOut = _tmpOut;
+ int dvp =0;
+
+ // fat chance of having this loop unroll
+ for( int i=0; i<32; i++)
+ {
+ final float[] dp = d16[i];
+ float pcm_sample;
+
+ pcm_sample = (float)(((vp[12 + dvp] * dp[0]) +
+ (vp[11 + dvp] * dp[1]) +
+ (vp[10 + dvp] * dp[2]) +
+ (vp[9 + dvp] * dp[3]) +
+ (vp[8 + dvp] * dp[4]) +
+ (vp[7 + dvp] * dp[5]) +
+ (vp[6 + dvp] * dp[6]) +
+ (vp[5 + dvp] * dp[7]) +
+ (vp[4 + dvp] * dp[8]) +
+ (vp[3 + dvp] * dp[9]) +
+ (vp[2 + dvp] * dp[10]) +
+ (vp[1 + dvp] * dp[11]) +
+ (vp[0 + dvp] * dp[12]) +
+ (vp[15 + dvp] * dp[13]) +
+ (vp[14 + dvp] * dp[14]) +
+ (vp[13 + dvp] * dp[15])
+ ) * scalefactor);
+
+ tmpOut[i] = pcm_sample;
+
+ dvp += 16;
+ } // for
+ }
+ private void compute_pcm_samples13(Obuffer buffer)
+ {
+ final float[] vp = actual_v;
+
+ //int inc = v_inc;
+ final float[] tmpOut = _tmpOut;
+ int dvp =0;
+
+ // fat chance of having this loop unroll
+ for( int i=0; i<32; i++)
+ {
+ final float[] dp = d16[i];
+ float pcm_sample;
+
+ pcm_sample = (float)(((vp[13 + dvp] * dp[0]) +
+ (vp[12 + dvp] * dp[1]) +
+ (vp[11 + dvp] * dp[2]) +
+ (vp[10 + dvp] * dp[3]) +
+ (vp[9 + dvp] * dp[4]) +
+ (vp[8 + dvp] * dp[5]) +
+ (vp[7 + dvp] * dp[6]) +
+ (vp[6 + dvp] * dp[7]) +
+ (vp[5 + dvp] * dp[8]) +
+ (vp[4 + dvp] * dp[9]) +
+ (vp[3 + dvp] * dp[10]) +
+ (vp[2 + dvp] * dp[11]) +
+ (vp[1 + dvp] * dp[12]) +
+ (vp[0 + dvp] * dp[13]) +
+ (vp[15 + dvp] * dp[14]) +
+ (vp[14 + dvp] * dp[15])
+ ) * scalefactor);
+
+ tmpOut[i] = pcm_sample;
+
+ dvp += 16;
+ } // for
+ }
+ private void compute_pcm_samples14(Obuffer buffer)
+ {
+ final float[] vp = actual_v;
+
+ //int inc = v_inc;
+ final float[] tmpOut = _tmpOut;
+ int dvp =0;
+
+ // fat chance of having this loop unroll
+ for( int i=0; i<32; i++)
+ {
+ final float[] dp = d16[i];
+ float pcm_sample;
+
+ pcm_sample = (float)(((vp[14 + dvp] * dp[0]) +
+ (vp[13 + dvp] * dp[1]) +
+ (vp[12 + dvp] * dp[2]) +
+ (vp[11 + dvp] * dp[3]) +
+ (vp[10 + dvp] * dp[4]) +
+ (vp[9 + dvp] * dp[5]) +
+ (vp[8 + dvp] * dp[6]) +
+ (vp[7 + dvp] * dp[7]) +
+ (vp[6 + dvp] * dp[8]) +
+ (vp[5 + dvp] * dp[9]) +
+ (vp[4 + dvp] * dp[10]) +
+ (vp[3 + dvp] * dp[11]) +
+ (vp[2 + dvp] * dp[12]) +
+ (vp[1 + dvp] * dp[13]) +
+ (vp[0 + dvp] * dp[14]) +
+ (vp[15 + dvp] * dp[15])
+ ) * scalefactor);
+
+ tmpOut[i] = pcm_sample;
+
+ dvp += 16;
+ } // for
+ }
+ private void compute_pcm_samples15(Obuffer buffer)
+ {
+ final float[] vp = actual_v;
+
+ //int inc = v_inc;
+ final float[] tmpOut = _tmpOut;
+ int dvp =0;
+
+ // fat chance of having this loop unroll
+ for( int i=0; i<32; i++)
+ {
+ float pcm_sample;
+ final float dp[] = d16[i];
+ pcm_sample = (float)(((vp[15 + dvp] * dp[0]) +
+ (vp[14 + dvp] * dp[1]) +
+ (vp[13 + dvp] * dp[2]) +
+ (vp[12 + dvp] * dp[3]) +
+ (vp[11 + dvp] * dp[4]) +
+ (vp[10 + dvp] * dp[5]) +
+ (vp[9 + dvp] * dp[6]) +
+ (vp[8 + dvp] * dp[7]) +
+ (vp[7 + dvp] * dp[8]) +
+ (vp[6 + dvp] * dp[9]) +
+ (vp[5 + dvp] * dp[10]) +
+ (vp[4 + dvp] * dp[11]) +
+ (vp[3 + dvp] * dp[12]) +
+ (vp[2 + dvp] * dp[13]) +
+ (vp[1 + dvp] * dp[14]) +
+ (vp[0 + dvp] * dp[15])
+ ) * scalefactor);
+
+ tmpOut[i] = pcm_sample;
+ dvp += 16;
+ } // for
+ }
+
+private void compute_pcm_samples(Obuffer buffer)
+{
+
+ switch (actual_write_pos)
+ {
+ case 0:
+ compute_pcm_samples0(buffer);
+ break;
+ case 1:
+ compute_pcm_samples1(buffer);
+ break;
+ case 2:
+ compute_pcm_samples2(buffer);
+ break;
+ case 3:
+ compute_pcm_samples3(buffer);
+ break;
+ case 4:
+ compute_pcm_samples4(buffer);
+ break;
+ case 5:
+ compute_pcm_samples5(buffer);
+ break;
+ case 6:
+ compute_pcm_samples6(buffer);
+ break;
+ case 7:
+ compute_pcm_samples7(buffer);
+ break;
+ case 8:
+ compute_pcm_samples8(buffer);
+ break;
+ case 9:
+ compute_pcm_samples9(buffer);
+ break;
+ case 10:
+ compute_pcm_samples10(buffer);
+ break;
+ case 11:
+ compute_pcm_samples11(buffer);
+ break;
+ case 12:
+ compute_pcm_samples12(buffer);
+ break;
+ case 13:
+ compute_pcm_samples13(buffer);
+ break;
+ case 14:
+ compute_pcm_samples14(buffer);
+ break;
+ case 15:
+ compute_pcm_samples15(buffer);
+ break;
+ }
+
+ if (buffer!=null)
+ {
+ buffer.appendSamples(channel, _tmpOut);
+ }
+
+/*
+ // MDM: I was considering putting in quality control for
+ // low-spec CPUs, but the performance gain (about 10-15%)
+ // did not justify the considerable drop in audio quality.
+ switch (inc)
+ {
+ case 16:
+ buffer.appendSamples(channel, tmpOut);
+ break;
+ case 32:
+ for (int i=0; i<16; i++)
+ {
+ buffer.append(channel, (short)tmpOut[i]);
+ buffer.append(channel, (short)tmpOut[i]);
+ }
+ break;
+ case 64:
+ for (int i=0; i<8; i++)
+ {
+ buffer.append(channel, (short)tmpOut[i]);
+ buffer.append(channel, (short)tmpOut[i]);
+ buffer.append(channel, (short)tmpOut[i]);
+ buffer.append(channel, (short)tmpOut[i]);
+ }
+ break;
+
+ }
+*/
+ }
+
+ /**
+ * Calculate 32 PCM samples and put the into the Obuffer-object.
+ */
+
+ public void calculate_pcm_samples(Obuffer buffer)
+ {
+ compute_new_v();
+ compute_pcm_samples(buffer);
+
+ actual_write_pos = (actual_write_pos + 1) & 0xf;
+ actual_v = (actual_v == v1) ? v2 : v1;
+
+ // initialize samples[]:
+ //for (register float *floatp = samples + 32; floatp > samples; )
+ // *--floatp = 0.0f;
+
+ // MDM: this may not be necessary. The Layer III decoder always
+ // outputs 32 subband samples, but I haven't checked layer I & II.
+ for (int p=0;p<32;p++)
+ samples[p] = 0.0f;
+ }
+
+
+ private static final double MY_PI = 3.14159265358979323846;
+ private static final float cos1_64 =(float) (1.0 / (2.0 * Math.cos(MY_PI / 64.0)));
+ private static final float cos3_64 =(float) (1.0 / (2.0 * Math.cos(MY_PI * 3.0 / 64.0)));
+ private static final float cos5_64 =(float) (1.0 / (2.0 * Math.cos(MY_PI * 5.0 / 64.0)));
+ private static final float cos7_64 =(float) (1.0 / (2.0 * Math.cos(MY_PI * 7.0 / 64.0)));
+ private static final float cos9_64 =(float) (1.0 / (2.0 * Math.cos(MY_PI * 9.0 / 64.0)));
+ private static final float cos11_64 =(float) (1.0 / (2.0 * Math.cos(MY_PI * 11.0 / 64.0)));
+ private static final float cos13_64 =(float) (1.0 / (2.0 * Math.cos(MY_PI * 13.0 / 64.0)));
+ private static final float cos15_64 =(float) (1.0 / (2.0 * Math.cos(MY_PI * 15.0 / 64.0)));
+ private static final float cos17_64 =(float) (1.0 / (2.0 * Math.cos(MY_PI * 17.0 / 64.0)));
+ private static final float cos19_64 =(float) (1.0 / (2.0 * Math.cos(MY_PI * 19.0 / 64.0)));
+ private static final float cos21_64 =(float) (1.0 / (2.0 * Math.cos(MY_PI * 21.0 / 64.0)));
+ private static final float cos23_64 =(float) (1.0 / (2.0 * Math.cos(MY_PI * 23.0 / 64.0)));
+ private static final float cos25_64 =(float) (1.0 / (2.0 * Math.cos(MY_PI * 25.0 / 64.0)));
+ private static final float cos27_64 =(float) (1.0 / (2.0 * Math.cos(MY_PI * 27.0 / 64.0)));
+ private static final float cos29_64 =(float) (1.0 / (2.0 * Math.cos(MY_PI * 29.0 / 64.0)));
+ private static final float cos31_64 =(float) (1.0 / (2.0 * Math.cos(MY_PI * 31.0 / 64.0)));
+ private static final float cos1_32 =(float) (1.0 / (2.0 * Math.cos(MY_PI / 32.0)));
+ private static final float cos3_32 =(float) (1.0 / (2.0 * Math.cos(MY_PI * 3.0 / 32.0)));
+ private static final float cos5_32 =(float) (1.0 / (2.0 * Math.cos(MY_PI * 5.0 / 32.0)));
+ private static final float cos7_32 =(float) (1.0 / (2.0 * Math.cos(MY_PI * 7.0 / 32.0)));
+ private static final float cos9_32 =(float) (1.0 / (2.0 * Math.cos(MY_PI * 9.0 / 32.0)));
+ private static final float cos11_32 =(float) (1.0 / (2.0 * Math.cos(MY_PI * 11.0 / 32.0)));
+ private static final float cos13_32 =(float) (1.0 / (2.0 * Math.cos(MY_PI * 13.0 / 32.0)));
+ private static final float cos15_32 =(float) (1.0 / (2.0 * Math.cos(MY_PI * 15.0 / 32.0)));
+ private static final float cos1_16 =(float) (1.0 / (2.0 * Math.cos(MY_PI / 16.0)));
+ private static final float cos3_16 =(float) (1.0 / (2.0 * Math.cos(MY_PI * 3.0 / 16.0)));
+ private static final float cos5_16 =(float) (1.0 / (2.0 * Math.cos(MY_PI * 5.0 / 16.0)));
+ private static final float cos7_16 =(float) (1.0 / (2.0 * Math.cos(MY_PI * 7.0 / 16.0)));
+ private static final float cos1_8 =(float) (1.0 / (2.0 * Math.cos(MY_PI / 8.0)));
+ private static final float cos3_8 =(float) (1.0 / (2.0 * Math.cos(MY_PI * 3.0 / 8.0)));
+ private static final float cos1_4 =(float) (1.0 / (2.0 * Math.cos(MY_PI / 4.0)));
+
+ // Note: These values are not in the same order
+ // as in Annex 3-B.3 of the ISO/IEC DIS 11172-3
+ // private float d[] = {0.000000000, -4.000442505};
+
+ private static float d[] = null;
+
+ /**
+ * d[] split into subarrays of length 16. This provides for
+ * more faster access by allowing a block of 16 to be addressed
+ * with constant offset.
+ **/
+ private static float d16[][] = null;
+
+ /**
+ * Loads the data for the d[] from the resource SFd.ser.
+ * @return the loaded values for d[].
+ */
+ static private float[] load_d()
+ {
+ try
+ {
+ Class elemType = Float.TYPE;
+ Object o = JavaLayerUtils.deserializeArrayResource("sfd.ser", elemType, 512);
+ return (float[])o;
+ }
+ catch (IOException ex)
+ {
+ throw new ExceptionInInitializerError(ex);
+ }
+ }
+
+ /**
+ * Converts a 1D array into a number of smaller arrays. This is used
+ * to achieve offset + constant indexing into an array. Each sub-array
+ * represents a block of values of the original array.
+ * @param array The array to split up into blocks.
+ * @param blockSize The size of the blocks to split the array
+ * into. This must be an exact divisor of
+ * the length of the array, or some data
+ * will be lost from the main array.
+ *
+ * @return An array of arrays in which each element in the returned
+ * array will be of length blockSize.
+ */
+ static private float[][] splitArray(final float[] array, final int blockSize)
+ {
+ int size = array.length / blockSize;
+ float[][] split = new float[size][];
+ for (int i=0; iAudioDevice interface provides an abstraction for
+ * a device capable of sounding audio samples. Samples are written to
+ * the device wia the write() method. The device assumes
+ * that these samples are signed 16-bit samples taken at the output frequency
+ * of the decoder. If the decoder outputs more than one channel, the samples for
+ * each channel are assumed to appear consecutively, with the lower numbered
+ * channels preceeding higher-numbered channels. E.g. if there are two
+ * channels, the samples will appear in this order:
+ *
+ *
+ * @since 0.0.8
+ * @author Mat McGowan
+ */
+public interface AudioDevice
+{
+ /**
+ * Prepares the AudioDevice for playback of audio samples.
+ * @param decoder The decoder that will be providing the audio
+ * samples.
+ *
+ * If the audio device is already open, this method returns silently.
+ *
+ */
+ public void open(Decoder decoder) throws JavaLayerException;
+
+ /**
+ * Retrieves the open state of this audio device.
+ *
+ * @return
+ *
+ * l0, r0, l1, r1, l2, r2...
+ *
+ * where
+ * lx indicates the xth sample on channel 0
+ * rx indicates the xth sample on channel 1
+ * true if this audio device is open and playing
+ * audio samples, or false otherwise.
+ */
+ public boolean isOpen();
+
+ /**
+ * Writes a number of samples to this AudioDevice.
+ *
+ * @param samples The array of signed 16-bit samples to write
+ * to the audio device.
+ * @param offs The offset of the first sample.
+ * @param len The number of samples to write.
+ *
+ * This method may return prior to the samples actually being played
+ * by the audio device.
+ */
+ public void write(short[] samples, int offs, int len) throws JavaLayerException;
+
+
+ /**
+ * Closes this audio device. Any currently playing audio is stopped
+ * as soon as possible. Any previously written audio data that has not been heard
+ * is discarded.
+ *
+ * The implementation should ensure that any threads currently blocking
+ * on the device (e.g. during a write or flush
+ * operation should be unblocked by this method.
+ */
+ public void close();
+
+
+ /**
+ * Blocks until all audio samples previously written to this audio device have
+ * been heard.
+ */
+ public void flush();
+
+ /**
+ * Retrieves the current playback position in milliseconds.
+ */
+ public int getPosition();
+}
diff --git a/src/javazoom/jl/player/AudioDeviceBase.java b/src/javazoom/jl/player/AudioDeviceBase.java
new file mode 100644
index 00000000000..37860f4a3c3
--- /dev/null
+++ b/src/javazoom/jl/player/AudioDeviceBase.java
@@ -0,0 +1,177 @@
+/*
+ * 11/19/04 1.0 moved to LGPL.
+ * 29/01/00 Initial version. mdm@techie.com
+ *-----------------------------------------------------------------------
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *----------------------------------------------------------------------
+ */
+
+package javazoom.jl.player;
+
+import javazoom.jl.decoder.Decoder;
+import javazoom.jl.decoder.JavaLayerException;
+
+/**
+ * The AudioDeviceBase class provides a simple thread-safe
+ * implementation of the AudioDevice interface.
+ * Template methods are provided for subclasses to override and
+ * in doing so provide the implementation for the main operations
+ * of the AudioDevice interface.
+ *
+ * @since 0.0.8
+ * @author Mat McGowan
+ */
+/*
+ * REVIEW: It is desirable to be able to use the decoder whe
+ * in the implementation of open(), but the decoder
+ * has not yet read a frame, and so much of the
+ * desired information (sample rate, channels etc.)
+ * are not available.
+ */
+public abstract class AudioDeviceBase implements AudioDevice
+{
+ private boolean open = false;
+
+ private Decoder decoder = null;
+
+ /**
+ * Opens this audio device.
+ *
+ * @param decoder The decoder that will provide audio data
+ * to this audio device.
+ */
+ public synchronized void open(Decoder decoder) throws JavaLayerException
+ {
+ if (!isOpen())
+ {
+ this.decoder = decoder;
+ openImpl();
+ setOpen(true);
+ }
+ }
+
+ /**
+ * Template method to provide the
+ * implementation for the opening of the audio device.
+ */
+ protected void openImpl() throws JavaLayerException
+ {
+ }
+
+ /**
+ * Sets the open state for this audio device.
+ */
+ protected void setOpen(boolean open)
+ {
+ this.open = open;
+ }
+
+ /**
+ * Determines if this audio device is open or not.
+ *
+ * @return true if the audio device is open,
+ * false if it is not.
+ */
+ public synchronized boolean isOpen()
+ {
+ return open;
+ }
+
+ /**
+ * Closes this audio device. If the device is currently playing
+ * audio, playback is stopped immediately without flushing
+ * any buffered audio data.
+ */
+ public synchronized void close()
+ {
+ if (isOpen())
+ {
+ closeImpl();
+ setOpen(false);
+ decoder = null;
+ }
+ }
+
+ /**
+ * Template method to provide the implementation for
+ * closing the audio device.
+ */
+ protected void closeImpl()
+ {
+ }
+
+ /**
+ * Writes audio data to this audio device. Audio data is
+ * assumed to be in the output format of the decoder. This
+ * method may return before the data has actually been sounded
+ * by the device if the device buffers audio samples.
+ *
+ * @param samples The samples to write to the audio device.
+ * @param offs The offset into the array of the first sample to write.
+ * @param len The number of samples from the array to write.
+ * @throws JavaLayerException if the audio data could not be
+ * written to the audio device.
+ * If the audio device is not open, this method does nthing.
+ */
+ public void write(short[] samples, int offs, int len)
+ throws JavaLayerException
+ {
+ if (isOpen())
+ {
+ writeImpl(samples, offs, len);
+ }
+ }
+
+ /**
+ * Template method to provide the implementation for
+ * writing audio samples to the audio device.
+ */
+ protected void writeImpl(short[] samples, int offs, int len)
+ throws JavaLayerException
+ {
+ }
+
+ /**
+ * Waits for any buffered audio samples to be played by the
+ * audio device. This method should only be called prior
+ * to closing the device.
+ */
+ public void flush()
+ {
+ if (isOpen())
+ {
+ flushImpl();
+ }
+ }
+
+ /**
+ * Template method to provide the implementation for
+ * flushing any buffered audio data.
+ */
+ protected void flushImpl()
+ {
+ }
+
+ /**
+ * Retrieves the decoder that provides audio data to this
+ * audio device.
+ *
+ * @return The associated decoder.
+ */
+ protected Decoder getDecoder()
+ {
+ return decoder;
+ }
+}
diff --git a/src/javazoom/jl/player/AudioDeviceFactory.java b/src/javazoom/jl/player/AudioDeviceFactory.java
new file mode 100644
index 00000000000..148b37198aa
--- /dev/null
+++ b/src/javazoom/jl/player/AudioDeviceFactory.java
@@ -0,0 +1,87 @@
+/*
+ * 11/19/04 1.0 moved to LGPL.
+ * 29/01/00 Initial version. mdm@techie.com
+ *-----------------------------------------------------------------------
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *----------------------------------------------------------------------
+ */
+
+package javazoom.jl.player;
+
+import javazoom.jl.decoder.JavaLayerException;
+
+/**
+ * An AudioDeviceFactory class is responsible for creating
+ * a specific AudioDevice implementation. A factory implementation
+ * can be as simple or complex as desired and may support just one implementation
+ * or may return several implementations depending upon the execution
+ * environment.
+ * AudioDevice.
+ *
+ * @return a new instance of a specific class of AudioDevice.
+ * @throws JavaLayerException if an instance of AudioDevice could not
+ * be created.
+ */
+ public abstract AudioDevice createAudioDevice() throws JavaLayerException;
+
+ /**
+ * Creates an instance of an AudioDevice implementation.
+ * @param loader The ClassLoader to use to
+ * load the named class, or null to use the
+ * system class loader.
+ * @param name The name of the class to load.
+ * @return A newly-created instance of the audio device class.
+ */
+ protected AudioDevice instantiate(ClassLoader loader, String name)
+ throws ClassNotFoundException,
+ IllegalAccessException,
+ InstantiationException
+ {
+ AudioDevice dev = null;
+
+ Class cls = null;
+ if (loader==null)
+ {
+ cls = Class.forName(name);
+ }
+ else
+ {
+ cls = loader.loadClass(name);
+ }
+
+ Object o = cls.newInstance();
+ dev = (AudioDevice)o;
+
+ return dev;
+ }
+}
diff --git a/src/javazoom/jl/player/FactoryRegistry.java b/src/javazoom/jl/player/FactoryRegistry.java
new file mode 100644
index 00000000000..833c37011eb
--- /dev/null
+++ b/src/javazoom/jl/player/FactoryRegistry.java
@@ -0,0 +1,129 @@
+/*
+ * 11/19/04 1.0 moved to LGPL.
+ * 29/01/00 Initial version. mdm@techie.com
+ *-----------------------------------------------------------------------
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *----------------------------------------------------------------------
+ */
+
+package javazoom.jl.player;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import javazoom.jl.decoder.JavaLayerException;
+
+/**
+ * The FactoryRegistry class stores the factories
+ * for all the audio device implementations available in the system.
+ * AudioDeviceFactory instance
+ * with this registry.
+ */
+ public void addFactory(AudioDeviceFactory factory)
+ {
+ factories.put(factory.getClass(), factory);
+ }
+
+ public void removeFactoryType(Class cls)
+ {
+ factories.remove(cls);
+ }
+
+ public void removeFactory(AudioDeviceFactory factory)
+ {
+ factories.remove(factory.getClass());
+ }
+
+ public AudioDevice createAudioDevice() throws JavaLayerException
+ {
+ AudioDevice device = null;
+ AudioDeviceFactory[] factories = getFactoriesPriority();
+
+ if (factories==null)
+ throw new JavaLayerException(this+": no factories registered");
+
+ JavaLayerException lastEx = null;
+ for (int i=0; (device==null) && (iNullAudioDevice implements a silent, no-op
+ * audio device. This is useful for testing purposes.
+ *
+ * @since 0.0.8
+ * @author Mat McGowan
+ */
+public class NullAudioDevice extends AudioDeviceBase
+{
+
+ public int getPosition()
+ {
+ return 0;
+ }
+}
diff --git a/src/javazoom/jl/player/Player.java b/src/javazoom/jl/player/Player.java
new file mode 100644
index 00000000000..c3020575f94
--- /dev/null
+++ b/src/javazoom/jl/player/Player.java
@@ -0,0 +1,251 @@
+/*
+ * 11/19/04 1.0 moved to LGPL.
+ * 29/01/00 Initial version. mdm@techie.com
+ *-----------------------------------------------------------------------
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *----------------------------------------------------------------------
+ */
+
+package javazoom.jl.player;
+
+import java.io.InputStream;
+
+import javazoom.jl.decoder.Bitstream;
+import javazoom.jl.decoder.BitstreamException;
+import javazoom.jl.decoder.Decoder;
+import javazoom.jl.decoder.Header;
+import javazoom.jl.decoder.JavaLayerException;
+import javazoom.jl.decoder.SampleBuffer;
+
+/**
+ * The Player class implements a simple player for playback
+ * of an MPEG audio stream.
+ *
+ * @author Mat McGowan
+ * @since 0.0.8
+ */
+
+// REVIEW: the audio device should not be opened until the
+// first MPEG audio frame has been decoded.
+public class Player
+{
+ /**
+ * The current frame number.
+ */
+ private int frame = 0;
+
+ /**
+ * The MPEG audio bitstream.
+ */
+ // javac blank final bug.
+ /*final*/ private Bitstream bitstream;
+
+ /**
+ * The MPEG audio decoder.
+ */
+ /*final*/ private Decoder decoder;
+
+ /**
+ * The AudioDevice the audio samples are written to.
+ */
+ private AudioDevice audio;
+
+ /**
+ * Has the player been closed?
+ */
+ private boolean closed = false;
+
+ /**
+ * Has the player played back all frames from the stream?
+ */
+ private boolean complete = false;
+
+ private int lastPosition = 0;
+
+ /**
+ * Creates a new Player instance.
+ */
+ public Player(InputStream stream) throws JavaLayerException
+ {
+ this(stream, null);
+ }
+
+ public Player(InputStream stream, AudioDevice device) throws JavaLayerException
+ {
+ bitstream = new Bitstream(stream);
+ decoder = new Decoder();
+
+ if (device!=null)
+ {
+ audio = device;
+ }
+ else
+ {
+ FactoryRegistry r = FactoryRegistry.systemRegistry();
+ audio = r.createAudioDevice();
+ }
+ audio.open(decoder);
+ }
+
+ public void play() throws JavaLayerException
+ {
+ play(Integer.MAX_VALUE);
+ }
+
+ /**
+ * Plays a number of MPEG audio frames.
+ *
+ * @param frames The number of frames to play.
+ * @return true if the last frame was played, or false if there are
+ * more frames.
+ */
+ public boolean play(int frames) throws JavaLayerException
+ {
+ boolean ret = true;
+
+ while (frames-- > 0 && ret)
+ {
+ ret = decodeFrame();
+ }
+
+ if (!ret)
+ {
+ // last frame, ensure all data flushed to the audio device.
+ AudioDevice out = audio;
+ if (out!=null)
+ {
+ out.flush();
+ synchronized (this)
+ {
+ complete = (!closed);
+ close();
+ }
+ }
+ }
+ return ret;
+ }
+
+ /**
+ * Cloases this player. Any audio currently playing is stopped
+ * immediately.
+ */
+ public synchronized void close()
+ {
+ AudioDevice out = audio;
+ if (out!=null)
+ {
+ closed = true;
+ audio = null;
+ // this may fail, so ensure object state is set up before
+ // calling this method.
+ out.close();
+ lastPosition = out.getPosition();
+ try
+ {
+ bitstream.close();
+ }
+ catch (BitstreamException ex)
+ {
+ }
+ }
+ }
+
+ /**
+ * Returns the completed status of this player.
+ *
+ * @return true if all available MPEG audio frames have been
+ * decoded, or false otherwise.
+ */
+ public synchronized boolean isComplete()
+ {
+ return complete;
+ }
+
+ /**
+ * Retrieves the position in milliseconds of the current audio
+ * sample being played. This method delegates to the
+ * AudioDevice that is used by this player to sound
+ * the decoded audio samples.
+ */
+ public int getPosition()
+ {
+ int position = lastPosition;
+
+ AudioDevice out = audio;
+ if (out!=null)
+ {
+ position = out.getPosition();
+ }
+ return position;
+ }
+
+ /**
+ * Decodes a single frame.
+ *
+ * @return true if there are no more frames to decode, false otherwise.
+ */
+ protected boolean decodeFrame() throws JavaLayerException
+ {
+ try
+ {
+ AudioDevice out = audio;
+ if (out==null)
+ return false;
+
+ Header h = bitstream.readFrame();
+
+ if (h==null)
+ return false;
+
+ // sample buffer set when decoder constructed
+ SampleBuffer output = (SampleBuffer)decoder.decodeFrame(h, bitstream);
+
+ synchronized (this)
+ {
+ out = audio;
+ if (out!=null)
+ {
+ out.write(output.getBuffer(), 0, output.getBufferLength());
+ }
+ }
+
+ bitstream.closeFrame();
+ }
+ catch (RuntimeException ex)
+ {
+ throw new JavaLayerException("Exception decoding audio frame", ex);
+ }
+/*
+ catch (IOException ex)
+ {
+ System.out.println("exception decoding audio frame: "+ex);
+ return false;
+ }
+ catch (BitstreamException bitex)
+ {
+ System.out.println("exception decoding audio frame: "+bitex);
+ return false;
+ }
+ catch (DecoderException decex)
+ {
+ System.out.println("exception decoding audio frame: "+decex);
+ return false;
+ }
+*/
+ return true;
+ }
+
+
+}
diff --git a/src/javazoom/jl/player/PlayerApplet.java b/src/javazoom/jl/player/PlayerApplet.java
new file mode 100644
index 00000000000..ecfa0b8fefd
--- /dev/null
+++ b/src/javazoom/jl/player/PlayerApplet.java
@@ -0,0 +1,246 @@
+/*
+ * 11/19/04 1.0 moved to LGPL.
+ * 29/01/00 Initial version. mdm@techie.com
+ *-----------------------------------------------------------------------
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *----------------------------------------------------------------------
+ */
+
+package javazoom.jl.player;
+
+import java.applet.Applet;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+
+import javazoom.jl.decoder.JavaLayerException;
+
+/**
+ * A simple applet that plays an MPEG audio file.
+ * The URL (relative to the document base)
+ * is passed as the "audioURL" parameter.
+ *
+ * @author Mat McGowan
+ * @since 0.0.8
+ */
+public class PlayerApplet extends Applet implements Runnable
+{
+ static public final String AUDIO_PARAMETER = "audioURL";
+
+ /**
+ * The Player used to play the MPEG audio file.
+ */
+ private Player player = null;
+
+ /**
+ * The thread that runs the player.
+ */
+ private Thread playerThread = null;
+
+ private String fileName = null;
+
+
+ /**
+ * Retrieves the AudioDevice instance that will
+ * be used to sound the audio data.
+ *
+ * @return an audio device instance that will be used to
+ * sound the audio stream.
+ */
+ protected AudioDevice getAudioDevice() throws JavaLayerException
+ {
+ return FactoryRegistry.systemRegistry().createAudioDevice();
+ }
+
+ /**
+ * Retrieves the InputStream that provides the MPEG audio
+ * stream data.
+ *
+ * @return an InputStream from which the MPEG audio data
+ * is read, or null if an error occurs.
+ */
+ protected InputStream getAudioStream()
+ {
+ InputStream in = null;
+
+ try
+ {
+ URL url = getAudioURL();
+ if (url!=null)
+ in = url.openStream();
+ }
+ catch (IOException ex)
+ {
+ System.err.println(ex);
+ }
+ return in;
+ }
+
+ protected String getAudioFileName()
+ {
+ String urlString = fileName;
+ if (urlString==null)
+ {
+ urlString = getParameter(AUDIO_PARAMETER);
+ }
+ return urlString;
+ }
+
+ protected URL getAudioURL()
+ {
+ String urlString = getAudioFileName();
+ URL url = null;
+ if (urlString!=null)
+ {
+ try
+ {
+ url = new URL(getDocumentBase(), urlString);
+ }
+ catch (Exception ex)
+ {
+ System.err.println(ex);
+ }
+ }
+ return url;
+ }
+
+ /**
+ * Sets the URL of the audio stream to play.
+ */
+ public void setFileName(String name)
+ {
+ fileName = name;
+ }
+
+ public String getFileName()
+ {
+ return fileName;
+ }
+
+ /**
+ * Stops the audio player. If the player is already stopped
+ * this method is a no-op.
+ */
+ protected void stopPlayer() throws JavaLayerException
+ {
+ if (player!=null)
+ {
+ player.close();
+ player = null;
+ playerThread = null;
+ }
+ }
+
+ /**
+ * Decompresses audio data from an InputStream and plays it
+ * back through an AudioDevice. The playback is run on a newly
+ * created thread.
+ *
+ * @param in The InputStream that provides the MPEG audio data.
+ * @param dev The AudioDevice to use to sound the decompressed data.
+ *
+ * @throws JavaLayerException if there was a problem decoding
+ * or playing the audio data.
+ */
+ protected void play(InputStream in, AudioDevice dev) throws JavaLayerException
+ {
+ stopPlayer();
+
+ if (in!=null && dev!=null)
+ {
+ player = new Player(in, dev);
+ playerThread = createPlayerThread();
+ playerThread.start();
+ }
+ }
+
+ /**
+ * Creates a new thread used to run the audio player.
+ * @return A new Thread that, once started, runs the audio player.
+ */
+ protected Thread createPlayerThread()
+ {
+ return new Thread(this, "Audio player thread");
+ }
+
+ /**
+ * Initializes this applet.
+ */
+ public void init()
+ {
+ }
+
+ /**
+ * Starts this applet. An input stream and audio device
+ * are created and passed to the play() method.
+ */
+ public void start()
+ {
+ String name = getAudioFileName();
+ try
+ {
+ InputStream in = getAudioStream();
+ AudioDevice dev = getAudioDevice();
+ play(in, dev);
+ }
+ catch (JavaLayerException ex)
+ {
+ synchronized (System.err)
+ {
+ System.err.println("Unable to play "+name);
+ ex.printStackTrace(System.err);
+ }
+ }
+ }
+
+ /**
+ * Stops this applet. If audio is currently playing, it is
+ * stopped.
+ */
+ public void stop()
+ {
+ try
+ {
+ stopPlayer();
+ }
+ catch (JavaLayerException ex)
+ {
+ System.err.println(ex);
+ }
+ }
+
+ public void destroy()
+ {
+ }
+
+ /**
+ * The run method for the audio player thread. Simply calls
+ * play() on the player to play the entire stream.
+ */
+ public void run()
+ {
+ if (player!=null)
+ {
+ try
+ {
+ player.play();
+ }
+ catch (JavaLayerException ex)
+ {
+ System.err.println("Problem playing audio: "+ex);
+ }
+ }
+ }
+}
diff --git a/src/javazoom/jl/player/advanced/AdvancedPlayer.java b/src/javazoom/jl/player/advanced/AdvancedPlayer.java
new file mode 100644
index 00000000000..ac0d939730a
--- /dev/null
+++ b/src/javazoom/jl/player/advanced/AdvancedPlayer.java
@@ -0,0 +1,242 @@
+/*
+ * 11/19/04 1.0 moved to LGPL.
+ *-----------------------------------------------------------------------
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *----------------------------------------------------------------------
+ */
+
+package javazoom.jl.player.advanced;
+
+import java.io.InputStream;
+
+import javazoom.jl.decoder.Bitstream;
+import javazoom.jl.decoder.BitstreamException;
+import javazoom.jl.decoder.Decoder;
+import javazoom.jl.decoder.Header;
+import javazoom.jl.decoder.JavaLayerException;
+import javazoom.jl.decoder.SampleBuffer;
+import javazoom.jl.player.AudioDevice;
+import javazoom.jl.player.FactoryRegistry;
+
+/**
+ * a hybrid of javazoom.jl.player.Player tweeked to include play(startFrame, endFrame)
+ * hopefully this will be included in the api
+ */
+public class AdvancedPlayer
+{
+ /** The MPEG audio bitstream.*/
+ private Bitstream bitstream;
+ /** The MPEG audio decoder. */
+ private Decoder decoder;
+ /** The AudioDevice the audio samples are written to. */
+ private AudioDevice audio;
+ /** Has the player been closed? */
+ private boolean closed = false;
+ /** Has the player played back all frames from the stream? */
+ private boolean complete = false;
+ private int lastPosition = 0;
+ /** Listener for the playback process */
+ private PlaybackListener listener;
+
+ /**
+ * Creates a new Player instance.
+ */
+ public AdvancedPlayer(InputStream stream) throws JavaLayerException
+ {
+ this(stream, null);
+ }
+
+ public AdvancedPlayer(InputStream stream, AudioDevice device) throws JavaLayerException
+ {
+ bitstream = new Bitstream(stream);
+
+ if (device!=null) audio = device;
+ else audio = FactoryRegistry.systemRegistry().createAudioDevice();
+ audio.open(decoder = new Decoder());
+ }
+
+ public void play() throws JavaLayerException
+ {
+ play(Integer.MAX_VALUE);
+ }
+
+ /**
+ * Plays a number of MPEG audio frames.
+ *
+ * @param frames The number of frames to play.
+ * @return true if the last frame was played, or false if there are
+ * more frames.
+ */
+ public boolean play(int frames) throws JavaLayerException
+ {
+ boolean ret = true;
+
+ // report to listener
+ if(listener != null) listener.playbackStarted(createEvent(PlaybackEvent.STARTED));
+
+ while (frames-- > 0 && ret)
+ {
+ ret = decodeFrame();
+ }
+
+// if (!ret)
+ {
+ // last frame, ensure all data flushed to the audio device.
+ AudioDevice out = audio;
+ if (out != null)
+ {
+// System.out.println(audio.getPosition());
+ out.flush();
+// System.out.println(audio.getPosition());
+ synchronized (this)
+ {
+ complete = (!closed);
+ close();
+ }
+
+ // report to listener
+ if(listener != null) listener.playbackFinished(createEvent(out, PlaybackEvent.STOPPED));
+ }
+ }
+ return ret;
+ }
+
+ /**
+ * Cloases this player. Any audio currently playing is stopped
+ * immediately.
+ */
+ public synchronized void close()
+ {
+ AudioDevice out = audio;
+ if (out != null)
+ {
+ closed = true;
+ audio = null;
+ // this may fail, so ensure object state is set up before
+ // calling this method.
+ out.close();
+ lastPosition = out.getPosition();
+ try
+ {
+ bitstream.close();
+ }
+ catch (BitstreamException ex)
+ {}
+ }
+ }
+
+ /**
+ * Decodes a single frame.
+ *
+ * @return true if there are no more frames to decode, false otherwise.
+ */
+ protected boolean decodeFrame() throws JavaLayerException
+ {
+ try
+ {
+ AudioDevice out = audio;
+ if (out == null) return false;
+
+ Header h = bitstream.readFrame();
+ if (h == null) return false;
+
+ // sample buffer set when decoder constructed
+ SampleBuffer output = (SampleBuffer) decoder.decodeFrame(h, bitstream);
+
+ synchronized (this)
+ {
+ out = audio;
+ if(out != null)
+ {
+ out.write(output.getBuffer(), 0, output.getBufferLength());
+ }
+ }
+
+ bitstream.closeFrame();
+ }
+ catch (RuntimeException ex)
+ {
+ throw new JavaLayerException("Exception decoding audio frame", ex);
+ }
+ return true;
+ }
+
+ /**
+ * skips over a single frame
+ * @return false if there are no more frames to decode, true otherwise.
+ */
+ protected boolean skipFrame() throws JavaLayerException
+ {
+ Header h = bitstream.readFrame();
+ if (h == null) return false;
+ bitstream.closeFrame();
+ return true;
+ }
+
+ /**
+ * Plays a range of MPEG audio frames
+ * @param start The first frame to play
+ * @param end The last frame to play
+ * @return true if the last frame was played, or false if there are more frames.
+ */
+ public boolean play(final int start, final int end) throws JavaLayerException
+ {
+ boolean ret = true;
+ int offset = start;
+ while (offset-- > 0 && ret) ret = skipFrame();
+ return play(end - start);
+ }
+
+ /**
+ * Constructs a PlaybackEvent
+ */
+ private PlaybackEvent createEvent(int id)
+ {
+ return createEvent(audio, id);
+ }
+
+ /**
+ * Constructs a PlaybackEvent
+ */
+ private PlaybackEvent createEvent(AudioDevice dev, int id)
+ {
+ return new PlaybackEvent(this, id, dev.getPosition());
+ }
+
+ /**
+ * sets the PlaybackListener
+ */
+ public void setPlayBackListener(PlaybackListener listener)
+ {
+ this.listener = listener;
+ }
+
+ /**
+ * gets the PlaybackListener
+ */
+ public PlaybackListener getPlayBackListener()
+ {
+ return listener;
+ }
+
+ /**
+ * closes the player and notifies PlaybackListener
+ */
+ public void stop()
+ {
+ listener.playbackFinished(createEvent(PlaybackEvent.STOPPED));
+ close();
+ }
+}
\ No newline at end of file
diff --git a/src/javazoom/jl/player/advanced/PlaybackEvent.java b/src/javazoom/jl/player/advanced/PlaybackEvent.java
new file mode 100644
index 00000000000..d46edcc3c40
--- /dev/null
+++ b/src/javazoom/jl/player/advanced/PlaybackEvent.java
@@ -0,0 +1,51 @@
+/*
+ * 11/19/04 1.0 moved to LGPL.
+ *-----------------------------------------------------------------------
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *----------------------------------------------------------------------
+ */
+
+package javazoom.jl.player.advanced;
+
+/**
+ * An event which indicates a Player has performed an 'playback action'
+ * @author Paul Stanton (http://wanto.f2o.org/)
+ */
+public class PlaybackEvent
+{
+ public static int STOPPED = 1;
+ public static int STARTED = 2;
+
+ private AdvancedPlayer source;
+ private int frame;
+ private int id;
+
+ public PlaybackEvent(AdvancedPlayer source, int id, int frame)
+ {
+ this.id = id;
+ this.source = source;
+ this.frame = frame;
+ }
+
+ public int getId(){return id;}
+ public void setId(int id){this.id = id;}
+
+ public int getFrame(){return frame;}
+ public void setFrame(int frame){this.frame = frame;}
+
+ public AdvancedPlayer getSource(){return source;}
+ public void setSource(AdvancedPlayer source){this.source = source;}
+
+}
diff --git a/src/javazoom/jl/player/advanced/PlaybackListener.java b/src/javazoom/jl/player/advanced/PlaybackListener.java
new file mode 100644
index 00000000000..a0149bfd279
--- /dev/null
+++ b/src/javazoom/jl/player/advanced/PlaybackListener.java
@@ -0,0 +1,30 @@
+/*
+ * 11/19/04 1.0 moved to LGPL.
+ *-----------------------------------------------------------------------
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *----------------------------------------------------------------------
+ */
+
+package javazoom.jl.player.advanced;
+
+/**
+ * Listener for javalayer Player playback
+ * @author Paul Stanton (http://wanto.f2o.org/)
+ */
+public abstract class PlaybackListener
+{
+ public void playbackStarted(PlaybackEvent evt){}
+ public void playbackFinished(PlaybackEvent evt){}
+}
diff --git a/src/javazoom/jl/player/advanced/jlap.java b/src/javazoom/jl/player/advanced/jlap.java
new file mode 100644
index 00000000000..16ce9bc0718
--- /dev/null
+++ b/src/javazoom/jl/player/advanced/jlap.java
@@ -0,0 +1,116 @@
+/*
+ * 11/19/04 1.0 moved to LGPL.
+ *-----------------------------------------------------------------------
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *----------------------------------------------------------------------
+ */
+
+package javazoom.jl.player.advanced;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import javazoom.jl.decoder.JavaLayerException;
+
+/**
+ * This class implements a sample player using Playback listener.
+ */
+public class jlap
+{
+
+ public static void main(String[] args)
+ {
+ jlap test = new jlap();
+ if (args.length != 1)
+ {
+ test.showUsage();
+ System.exit(0);
+ }
+ else
+ {
+ try
+ {
+ test.play(args[0]);
+ }
+ catch (Exception ex)
+ {
+ System.err.println(ex.getMessage());
+ System.exit(0);
+ }
+ }
+ }
+
+ public void play(String filename) throws JavaLayerException, IOException
+ {
+ InfoListener lst = new InfoListener();
+ playMp3(new File(filename), lst);
+ }
+
+ public void showUsage()
+ {
+ System.out.println("Usage: jla jlp class implements a simple command-line
+ * player for MPEG audio files.
+ *
+ * @author Mat McGowan (mdm@techie.com)
+ */
+public class jlp
+{
+ private String fFilename = null;
+ private boolean remote = false;
+
+ public static void main(String[] args)
+ {
+ int retval = 0;
+ try
+ {
+ jlp player = createInstance(args);
+ if (player!=null)
+ player.play();
+ }
+ catch (Exception ex)
+ {
+ System.err.println(ex);
+ ex.printStackTrace(System.err);
+ retval = 1;
+ }
+ System.exit(retval);
+ }
+
+ static public jlp createInstance(String[] args)
+ {
+ jlp player = new jlp();
+ if (!player.parseArgs(args))
+ player = null;
+ return player;
+ }
+
+ private jlp()
+ {
+ }
+
+ public jlp(String filename)
+ {
+ init(filename);
+ }
+
+ protected void init(String filename)
+ {
+ fFilename = filename;
+ }
+
+ protected boolean parseArgs(String[] args)
+ {
+ boolean parsed = false;
+ if (args.length == 1)
+ {
+ init(args[0]);
+ parsed = true;
+ remote = false;
+ }
+ else if (args.length == 2)
+ {
+ if (!(args[0].equals("-url")))
+ {
+ showUsage();
+ }
+ else
+ {
+ init(args[1]);
+ parsed = true;
+ remote = true;
+ }
+ }
+ else
+ {
+ showUsage();
+ }
+ return parsed;
+ }
+
+ public void showUsage()
+ {
+ System.out.println("Usage: jlp [-url]