From 9fee0ec4ca0c5b7a334cc29dbb58e76c7a4c736e Mon Sep 17 00:00:00 2001 From: Michiel Van Der Kolk Date: Mon, 11 Jul 2005 15:42:37 +0000 Subject: Songdb java version, source. only 1.5 compatible git-svn-id: svn://svn.rockbox.org/rockbox/trunk@7101 a1c6a512-1295-4272-9138-f99709370657 --- songdbj/javazoom/jl/converter/Converter.java | 411 ++++ songdbj/javazoom/jl/converter/RiffFile.java | 495 ++++ songdbj/javazoom/jl/converter/WaveFile.java | 522 +++++ songdbj/javazoom/jl/converter/WaveFileObuffer.java | 141 ++ songdbj/javazoom/jl/converter/jlc.java | 216 ++ songdbj/javazoom/jl/decoder/BitReserve.java | 223 ++ songdbj/javazoom/jl/decoder/Bitstream.java | 655 ++++++ songdbj/javazoom/jl/decoder/BitstreamErrors.java | 72 + .../javazoom/jl/decoder/BitstreamException.java | 71 + songdbj/javazoom/jl/decoder/Control.java | 57 + songdbj/javazoom/jl/decoder/Crc16.java | 70 + songdbj/javazoom/jl/decoder/Decoder.java | 357 +++ songdbj/javazoom/jl/decoder/DecoderErrors.java | 38 + songdbj/javazoom/jl/decoder/DecoderException.java | 61 + songdbj/javazoom/jl/decoder/Equalizer.java | 227 ++ songdbj/javazoom/jl/decoder/FrameDecoder.java | 38 + songdbj/javazoom/jl/decoder/Header.java | 762 ++++++ songdbj/javazoom/jl/decoder/InputStreamSource.java | 80 + songdbj/javazoom/jl/decoder/JavaLayerError.java | 31 + songdbj/javazoom/jl/decoder/JavaLayerErrors.java | 40 + .../javazoom/jl/decoder/JavaLayerException.java | 80 + songdbj/javazoom/jl/decoder/JavaLayerHook.java | 36 + songdbj/javazoom/jl/decoder/JavaLayerUtils.java | 207 ++ songdbj/javazoom/jl/decoder/LayerIDecoder.java | 444 ++++ songdbj/javazoom/jl/decoder/LayerIIDecoder.java | 1064 +++++++++ songdbj/javazoom/jl/decoder/LayerIIIDecoder.java | 2439 ++++++++++++++++++++ songdbj/javazoom/jl/decoder/Manager.java | 46 + songdbj/javazoom/jl/decoder/Obuffer.java | 88 + songdbj/javazoom/jl/decoder/OutputChannels.java | 143 ++ songdbj/javazoom/jl/decoder/SampleBuffer.java | 132 ++ songdbj/javazoom/jl/decoder/Source.java | 49 + songdbj/javazoom/jl/decoder/SynthesisFilter.java | 1817 +++++++++++++++ songdbj/javazoom/jl/decoder/au2lin.ser | Bin 0 -> 539 bytes songdbj/javazoom/jl/decoder/huffcodetab.java | 600 +++++ songdbj/javazoom/jl/decoder/l3reorder.ser | Bin 0 -> 13925 bytes songdbj/javazoom/jl/decoder/lin2au.ser | Bin 0 -> 16411 bytes songdbj/javazoom/jl/decoder/readme.txt | 15 + songdbj/javazoom/jl/decoder/sfd.ser | Bin 0 -> 2075 bytes songdbj/javazoom/jl/player/AudioDevice.java | 103 + songdbj/javazoom/jl/player/AudioDeviceBase.java | 177 ++ songdbj/javazoom/jl/player/AudioDeviceFactory.java | 87 + songdbj/javazoom/jl/player/FactoryRegistry.java | 129 ++ .../javazoom/jl/player/JavaSoundAudioDevice.java | 215 ++ .../jl/player/JavaSoundAudioDeviceFactory.java | 85 + songdbj/javazoom/jl/player/NullAudioDevice.java | 37 + songdbj/javazoom/jl/player/Player.java | 251 ++ songdbj/javazoom/jl/player/PlayerApplet.java | 246 ++ .../jl/player/advanced/AdvancedPlayer.java | 242 ++ .../javazoom/jl/player/advanced/PlaybackEvent.java | 51 + .../jl/player/advanced/PlaybackListener.java | 30 + songdbj/javazoom/jl/player/advanced/jlap.java | 116 + songdbj/javazoom/jl/player/jlp.java | 176 ++ 52 files changed, 13672 insertions(+) create mode 100644 songdbj/javazoom/jl/converter/Converter.java create mode 100644 songdbj/javazoom/jl/converter/RiffFile.java create mode 100644 songdbj/javazoom/jl/converter/WaveFile.java create mode 100644 songdbj/javazoom/jl/converter/WaveFileObuffer.java create mode 100644 songdbj/javazoom/jl/converter/jlc.java create mode 100644 songdbj/javazoom/jl/decoder/BitReserve.java create mode 100644 songdbj/javazoom/jl/decoder/Bitstream.java create mode 100644 songdbj/javazoom/jl/decoder/BitstreamErrors.java create mode 100644 songdbj/javazoom/jl/decoder/BitstreamException.java create mode 100644 songdbj/javazoom/jl/decoder/Control.java create mode 100644 songdbj/javazoom/jl/decoder/Crc16.java create mode 100644 songdbj/javazoom/jl/decoder/Decoder.java create mode 100644 songdbj/javazoom/jl/decoder/DecoderErrors.java create mode 100644 songdbj/javazoom/jl/decoder/DecoderException.java create mode 100644 songdbj/javazoom/jl/decoder/Equalizer.java create mode 100644 songdbj/javazoom/jl/decoder/FrameDecoder.java create mode 100644 songdbj/javazoom/jl/decoder/Header.java create mode 100644 songdbj/javazoom/jl/decoder/InputStreamSource.java create mode 100644 songdbj/javazoom/jl/decoder/JavaLayerError.java create mode 100644 songdbj/javazoom/jl/decoder/JavaLayerErrors.java create mode 100644 songdbj/javazoom/jl/decoder/JavaLayerException.java create mode 100644 songdbj/javazoom/jl/decoder/JavaLayerHook.java create mode 100644 songdbj/javazoom/jl/decoder/JavaLayerUtils.java create mode 100644 songdbj/javazoom/jl/decoder/LayerIDecoder.java create mode 100644 songdbj/javazoom/jl/decoder/LayerIIDecoder.java create mode 100644 songdbj/javazoom/jl/decoder/LayerIIIDecoder.java create mode 100644 songdbj/javazoom/jl/decoder/Manager.java create mode 100644 songdbj/javazoom/jl/decoder/Obuffer.java create mode 100644 songdbj/javazoom/jl/decoder/OutputChannels.java create mode 100644 songdbj/javazoom/jl/decoder/SampleBuffer.java create mode 100644 songdbj/javazoom/jl/decoder/Source.java create mode 100644 songdbj/javazoom/jl/decoder/SynthesisFilter.java create mode 100644 songdbj/javazoom/jl/decoder/au2lin.ser create mode 100644 songdbj/javazoom/jl/decoder/huffcodetab.java create mode 100644 songdbj/javazoom/jl/decoder/l3reorder.ser create mode 100644 songdbj/javazoom/jl/decoder/lin2au.ser create mode 100644 songdbj/javazoom/jl/decoder/readme.txt create mode 100644 songdbj/javazoom/jl/decoder/sfd.ser create mode 100644 songdbj/javazoom/jl/player/AudioDevice.java create mode 100644 songdbj/javazoom/jl/player/AudioDeviceBase.java create mode 100644 songdbj/javazoom/jl/player/AudioDeviceFactory.java create mode 100644 songdbj/javazoom/jl/player/FactoryRegistry.java create mode 100644 songdbj/javazoom/jl/player/JavaSoundAudioDevice.java create mode 100644 songdbj/javazoom/jl/player/JavaSoundAudioDeviceFactory.java create mode 100644 songdbj/javazoom/jl/player/NullAudioDevice.java create mode 100644 songdbj/javazoom/jl/player/Player.java create mode 100644 songdbj/javazoom/jl/player/PlayerApplet.java create mode 100644 songdbj/javazoom/jl/player/advanced/AdvancedPlayer.java create mode 100644 songdbj/javazoom/jl/player/advanced/PlaybackEvent.java create mode 100644 songdbj/javazoom/jl/player/advanced/PlaybackListener.java create mode 100644 songdbj/javazoom/jl/player/advanced/jlap.java create mode 100644 songdbj/javazoom/jl/player/jlp.java (limited to 'songdbj/javazoom/jl') diff --git a/songdbj/javazoom/jl/converter/Converter.java b/songdbj/javazoom/jl/converter/Converter.java new file mode 100644 index 0000000000..845082e626 --- /dev/null +++ b/songdbj/javazoom/jl/converter/Converter.java @@ -0,0 +1,411 @@ +/* + * 11/19/04 1.0 moved to LGPL. + * 12/12/99 Original verion. 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.converter; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintWriter; + +import javazoom.jl.decoder.Bitstream; +import javazoom.jl.decoder.Decoder; +import javazoom.jl.decoder.Header; +import javazoom.jl.decoder.JavaLayerException; +import javazoom.jl.decoder.Obuffer; + +/** + * The 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 (; frameupdateID parameter can take these values: + * + * UPDATE_FRAME_COUNT: param1 is the frame count, or -1 if not known. + * UPDATE_CONVERT_COMPLETE: param1 is the conversion time, param2 + * is the number of frames converted. + */ + public void converterUpdate(int updateID, int param1, int param2); + + /** + * If the converter wishes to make a first pass over the + * audio frames, this is called as each frame is parsed. + */ + public void parsedFrame(int frameNo, Header header); + + /** + * This method is called after each frame has been read, + * but before it has been decoded. + * + * @param frameNo The 0-based sequence number of the frame. + * @param header The Header rerpesenting the frame just read. + */ + public void readFrame(int frameNo, Header header); + + /** + * This method is called after a frame has been decoded. + * + * @param frameNo The 0-based sequence number of the frame. + * @param header The Header rerpesenting the frame just read. + * @param o The Obuffer the deocded data was written to. + */ + public void decodedFrame(int frameNo, Header header, Obuffer o); + + /** + * Called when an exception is thrown during while converting + * a frame. + * + * @param t The Throwable 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/songdbj/javazoom/jl/converter/RiffFile.java b/songdbj/javazoom/jl/converter/RiffFile.java new file mode 100644 index 0000000000..fb5d9e53c6 --- /dev/null +++ b/songdbj/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;y>> 8) & 0x00FF); + } + if ( fmode != RFM_WRITE ) + { + return DDC_INVALID_CALL; + } + try + { + file.write(theData,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(RiffChunkHeader Triff_header, int NumBytes ) + { + byte[] br = new byte[8]; + br[0] = (byte) ((Triff_header.ckID >>> 24) & 0x000000FF); + br[1] = (byte) ((Triff_header.ckID >>> 16) & 0x000000FF); + br[2] = (byte) ((Triff_header.ckID >>> 8) & 0x000000FF); + br[3] = (byte) (Triff_header.ckID & 0x000000FF); + + byte br4 = (byte) ((Triff_header.ckSize >>> 24)& 0x000000FF); + byte br5 = (byte) ((Triff_header.ckSize >>> 16)& 0x000000FF); + byte br6 = (byte) ((Triff_header.ckSize >>> 8)& 0x000000FF); + byte br7 = (byte) (Triff_header.ckSize & 0x000000FF); + + br[4] = br7; + br[5] = br6; + br[6] = br5; + br[7] = br4; + + if ( fmode != RFM_WRITE ) + { + return DDC_INVALID_CALL; + } + try + { + file.write(br,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 ) + { + short theData = (short) ( ((Data>>>8)&0x00FF) | ((Data<<8)&0xFF00) ); + if ( fmode != RFM_WRITE ) + { + return DDC_INVALID_CALL; + } + try + { + file.writeShort(theData); + fmode = RFM_WRITE; + } catch (IOException ioe) + { + return DDC_FILE_ERROR; + } + riff_header.ckSize += NumBytes; + return DDC_SUCCESS; + } + /** + * Write NumBytes data. + */ + public int Write(int Data, int NumBytes ) + { + short theDataL = (short) ((Data>>>16)&0x0000FFFF); + short theDataR = (short) (Data&0x0000FFFF); + short theDataLI = (short) ( ((theDataL>>>8)&0x00FF) | ((theDataL<<8)&0xFF00) ); + short theDataRI = (short) ( ((theDataR>>>8)&0x00FF) | ((theDataR<<8)&0xFF00) ); + int theData = ((theDataRI<<16)&0xFFFF0000) | (theDataLI&0x0000FFFF); + if ( fmode != RFM_WRITE ) + { + return DDC_INVALID_CALL; + } + try + { + file.writeInt(theData); + fmode = RFM_WRITE; + } catch (IOException ioe) + { + return DDC_FILE_ERROR; + } + riff_header.ckSize += NumBytes; + return DDC_SUCCESS; + } + + + + /** + * Read NumBytes data. + */ + public int Read (byte[] Data, int NumBytes) + { + int retcode = DDC_SUCCESS; + try + { + file.read(Data,0,NumBytes); + } catch (IOException ioe) + { + retcode = DDC_FILE_ERROR; + } + return retcode; + } + + /** + * Expect NumBytes data. + */ + public int Expect(String Data, int NumBytes ) + { + byte target = 0; + int cnt = 0; + try + { + while ((NumBytes--) != 0) + { + target = file.readByte(); + if (target != Data.charAt(cnt++)) return DDC_FILE_ERROR; + } + } catch (IOException ioe) + { + return DDC_FILE_ERROR; + } + return DDC_SUCCESS; + } + + /** + * Close Riff File. + * Length is written too. + */ + public int Close() + { + int retcode = DDC_SUCCESS; + + switch ( fmode ) + { + case RFM_WRITE: + try + { + file.seek(0); + try + { + 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); + + br[7] = (byte) ((riff_header.ckSize >>> 24)& 0x000000FF); + br[6] = (byte) ((riff_header.ckSize >>> 16)& 0x000000FF); + br[5] = (byte) ((riff_header.ckSize >>> 8)& 0x000000FF); + br[4] = (byte) (riff_header.ckSize & 0x000000FF); + file.write(br,0,8); + file.close(); + } catch (IOException ioe) + { + retcode = DDC_FILE_ERROR; + } + } catch (IOException ioe) + { + retcode = DDC_FILE_ERROR; + } + break; + + case RFM_READ: + try + { + file.close(); + } catch (IOException ioe) + { + retcode = DDC_FILE_ERROR; + } + break; + } + file = null; + fmode = RFM_UNKNOWN; + return retcode; + } + + /** + * Return File Position. + */ + public long CurrentFilePosition() + { + long position; + try + { + position = file.getFilePointer(); + } catch (IOException ioe) + { + position = -1; + } + return position; + } + + /** + * Write Data to specified offset. + */ + public int Backpatch (long FileOffset, RiffChunkHeader Data, int NumBytes ) + { + if (file == null) + { + return DDC_INVALID_CALL; + } + try + { + file.seek(FileOffset); + } catch (IOException ioe) + { + return DDC_FILE_ERROR; + } + return Write ( Data, NumBytes ); + } + + public int Backpatch (long FileOffset, byte[] Data, int NumBytes ) + { + if (file == null) + { + return DDC_INVALID_CALL; + } + try + { + file.seek(FileOffset); + } catch (IOException ioe) + { + return DDC_FILE_ERROR; + } + return Write ( Data, NumBytes ); + } + + + /** + * Seek in the File. + */ + protected int Seek(long offset) + { + int rc; + try + { + file.seek(offset); + rc = DDC_SUCCESS; + } catch (IOException ioe) + { + rc = DDC_FILE_ERROR; + } + return rc; + } + + /** + * Error Messages. + */ + private String DDCRET_String(int retcode) + { + switch ( retcode ) + { + case DDC_SUCCESS: return "DDC_SUCCESS"; + case DDC_FAILURE: return "DDC_FAILURE"; + case DDC_OUT_OF_MEMORY: return "DDC_OUT_OF_MEMORY"; + case DDC_FILE_ERROR: return "DDC_FILE_ERROR"; + case DDC_INVALID_CALL: return "DDC_INVALID_CALL"; + case DDC_USER_ABORT: return "DDC_USER_ABORT"; + case DDC_INVALID_FILE: return "DDC_INVALID_FILE"; + } + return "Unknown Error"; + } + + /** + * Fill the header. + */ + public static int FourCC(String ChunkName) + { + byte[] p = {0x20,0x20,0x20,0x20}; + ChunkName.getBytes(0,4,p,0); + int ret = (((p[0] << 24)& 0xFF000000) | ((p[1] << 16)&0x00FF0000) | ((p[2] << 8)&0x0000FF00) | (p[3]&0x000000FF)); + return ret; + } + +} diff --git a/songdbj/javazoom/jl/converter/WaveFile.java b/songdbj/javazoom/jl/converter/WaveFile.java new file mode 100644 index 0000000000..f158d7a39a --- /dev/null +++ b/songdbj/javazoom/jl/converter/WaveFile.java @@ -0,0 +1,522 @@ +/* + * 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; + +/** + * Class allowing WaveFormat Access + */ +public class WaveFile extends RiffFile +{ + public static final int MAX_WAVE_CHANNELS = 2; + + class WaveFormat_ChunkData + { + public short wFormatTag = 0; // Format category (PCM=1) + public short nChannels = 0; // Number of channels (mono=1, stereo=2) + public int nSamplesPerSec = 0; // Sampling rate [Hz] + public int nAvgBytesPerSec = 0; + public short nBlockAlign = 0; + public short nBitsPerSample = 0; + + public WaveFormat_ChunkData() + { + wFormatTag = 1; // PCM + Config(44100,(short)16,(short)1); + } + + public void Config (int NewSamplingRate, short NewBitsPerSample, short NewNumChannels) + { + nSamplesPerSec = NewSamplingRate; + nChannels = NewNumChannels; + nBitsPerSample = NewBitsPerSample; + nAvgBytesPerSec = (nChannels * nSamplesPerSec * nBitsPerSample) / 8; + nBlockAlign = (short) ((nChannels * nBitsPerSample) / 8); + } + } + + + class WaveFormat_Chunk + { + public RiffChunkHeader header; + public WaveFormat_ChunkData data; + + public WaveFormat_Chunk() + { + header = new RiffChunkHeader(); + data = new WaveFormat_ChunkData(); + header.ckID = FourCC("fmt "); + header.ckSize = 16; + } + + public int VerifyValidity() + { + boolean ret = header.ckID == FourCC("fmt ") && + + (data.nChannels == 1 || data.nChannels == 2) && + + data.nAvgBytesPerSec == ( data.nChannels * + data.nSamplesPerSec * + data.nBitsPerSample ) / 8 && + + data.nBlockAlign == ( data.nChannels * + data.nBitsPerSample ) / 8; + if (ret == true) return 1; + else return 0; + } + } + + public class WaveFileSample + { + public short[] chan; + + public WaveFileSample() + {chan = new short[WaveFile.MAX_WAVE_CHANNELS];} + } + + private WaveFormat_Chunk wave_format; + private RiffChunkHeader pcm_data; + private long pcm_data_offset = 0; // offset of 'pcm_data' in output file + private int num_samples = 0; + + + /** + * Constructs a new WaveFile instance. + */ + public WaveFile() + { + pcm_data = new RiffChunkHeader(); + wave_format = new WaveFormat_Chunk(); + pcm_data.ckID = FourCC("data"); + pcm_data.ckSize = 0; + num_samples = 0; + } + + /** + * + * + public int OpenForRead (String Filename) + { + // Verify filename parameter as best we can... + if (Filename == null) + { + return DDC_INVALID_CALL; + } + int retcode = Open ( Filename, RFM_READ ); + + if ( retcode == DDC_SUCCESS ) + { + retcode = Expect ( "WAVE", 4 ); + + if ( retcode == DDC_SUCCESS ) + { + retcode = Read(wave_format,24); + + if ( retcode == DDC_SUCCESS && !wave_format.VerifyValidity() ) + { + // This isn't standard PCM, so we don't know what it is! + retcode = DDC_FILE_ERROR; + } + + if ( retcode == DDC_SUCCESS ) + { + pcm_data_offset = CurrentFilePosition(); + + // Figure out number of samples from + // file size, current file position, and + // WAVE header. + retcode = Read (pcm_data, 8 ); + num_samples = filelength(fileno(file)) - CurrentFilePosition(); + num_samples /= NumChannels(); + num_samples /= (BitsPerSample() / 8); + } + } + } + return retcode; + }*/ + + /** + * + */ + public int OpenForWrite (String Filename, int SamplingRate, short BitsPerSample, short NumChannels) + { + // Verify parameters... + if ( (Filename==null) || + (BitsPerSample != 8 && BitsPerSample != 16) || + NumChannels < 1 || NumChannels > 2 ) + { + return DDC_INVALID_CALL; + } + + wave_format.data.Config ( SamplingRate, BitsPerSample, NumChannels ); + + int retcode = Open ( Filename, RFM_WRITE ); + + if ( retcode == DDC_SUCCESS ) + { + byte [] theWave = {(byte)'W',(byte)'A',(byte)'V',(byte)'E'}; + retcode = Write ( theWave, 4 ); + + if ( retcode == DDC_SUCCESS ) + { + // Ecriture de wave_format + retcode = Write (wave_format.header, 8); + retcode = Write (wave_format.data.wFormatTag, 2); + retcode = Write (wave_format.data.nChannels, 2); + retcode = Write (wave_format.data.nSamplesPerSec, 4); + retcode = Write (wave_format.data.nAvgBytesPerSec, 4); + retcode = Write (wave_format.data.nBlockAlign, 2); + retcode = Write (wave_format.data.nBitsPerSample, 2); + /* byte[] br = new byte[16]; + br[0] = (byte) ((wave_format.data.wFormatTag >> 8) & 0x00FF); + br[1] = (byte) (wave_format.data.wFormatTag & 0x00FF); + + br[2] = (byte) ((wave_format.data.nChannels >> 8) & 0x00FF); + br[3] = (byte) (wave_format.data.nChannels & 0x00FF); + + br[4] = (byte) ((wave_format.data.nSamplesPerSec >> 24)& 0x000000FF); + br[5] = (byte) ((wave_format.data.nSamplesPerSec >> 16)& 0x000000FF); + br[6] = (byte) ((wave_format.data.nSamplesPerSec >> 8)& 0x000000FF); + br[7] = (byte) (wave_format.data.nSamplesPerSec & 0x000000FF); + + br[8] = (byte) ((wave_format.data.nAvgBytesPerSec>> 24)& 0x000000FF); + br[9] = (byte) ((wave_format.data.nAvgBytesPerSec >> 16)& 0x000000FF); + br[10] = (byte) ((wave_format.data.nAvgBytesPerSec >> 8)& 0x000000FF); + br[11] = (byte) (wave_format.data.nAvgBytesPerSec & 0x000000FF); + + br[12] = (byte) ((wave_format.data.nBlockAlign >> 8) & 0x00FF); + br[13] = (byte) (wave_format.data.nBlockAlign & 0x00FF); + + br[14] = (byte) ((wave_format.data.nBitsPerSample >> 8) & 0x00FF); + br[15] = (byte) (wave_format.data.nBitsPerSample & 0x00FF); + retcode = Write (br, 16); */ + + + if ( retcode == DDC_SUCCESS ) + { + pcm_data_offset = CurrentFilePosition(); + retcode = Write ( pcm_data, 8 ); + } + } + } + + return retcode; + } + + /** + * + * + public int ReadSample ( short[] Sample ) + { + + }*/ + + /** + * + * + public int WriteSample( short[] Sample ) + { + int retcode = DDC_SUCCESS; + switch ( wave_format.data.nChannels ) + { + case 1: + switch ( wave_format.data.nBitsPerSample ) + { + case 8: + pcm_data.ckSize += 1; + retcode = Write ( Sample, 1 ); + break; + + case 16: + pcm_data.ckSize += 2; + retcode = Write ( Sample, 2 ); + break; + + default: + retcode = DDC_INVALID_CALL; + } + break; + + case 2: + switch ( wave_format.data.nBitsPerSample ) + { + case 8: + retcode = Write ( Sample, 1 ); + if ( retcode == DDC_SUCCESS ) + { + // &Sample[1] + retcode = Write (Sample, 1 ); + if ( retcode == DDC_SUCCESS ) + { + pcm_data.ckSize += 2; + } + } + break; + + case 16: + retcode = Write ( Sample, 2 ); + if ( retcode == DDC_SUCCESS ) + { + // &Sample[1] + retcode = Write (Sample, 2 ); + if ( retcode == DDC_SUCCESS ) + { + pcm_data.ckSize += 4; + } + } + break; + + default: + retcode = DDC_INVALID_CALL; + } + break; + + default: + retcode = DDC_INVALID_CALL; + } + + return retcode; + }*/ + + /** + * + * + public int SeekToSample ( long SampleIndex ) + { + if ( SampleIndex >= NumSamples() ) + { + return DDC_INVALID_CALL; + } + int SampleSize = (BitsPerSample() + 7) / 8; + int rc = Seek ( pcm_data_offset + 8 + + SampleSize * NumChannels() * SampleIndex ); + return rc; + }*/ + + /** + * Write 16-bit audio + */ + public int WriteData ( short[] data, int numData ) + { + int extraBytes = numData * 2; + pcm_data.ckSize += extraBytes; + return super.Write ( data, extraBytes ); + } + + /** + * Read 16-bit audio. + * + public int ReadData (short[] data, int numData) + {return super.Read ( data, numData * 2);} */ + + /** + * Write 8-bit audio. + * + public int WriteData ( byte[] data, int numData ) + { + pcm_data.ckSize += numData; + return super.Write ( data, numData ); + }*/ + + /** + * Read 8-bit audio. + * + public int ReadData ( byte[] data, int numData ) + {return super.Read ( data, numData );} */ + + + /** + * + * + public int ReadSamples (int num, int [] WaveFileSample) + { + + }*/ + + /** + * + * + public int WriteMonoSample ( short[] SampleData ) + { + switch ( wave_format.data.nBitsPerSample ) + { + case 8: + pcm_data.ckSize += 1; + return Write ( SampleData, 1 ); + + case 16: + pcm_data.ckSize += 2; + return Write ( SampleData, 2 ); + } + return DDC_INVALID_CALL; + }*/ + + /** + * + * + public int WriteStereoSample ( short[] LeftSample, short[] RightSample ) + { + int retcode = DDC_SUCCESS; + switch ( wave_format.data.nBitsPerSample ) + { + case 8: + retcode = Write ( LeftSample, 1 ); + if ( retcode == DDC_SUCCESS ) + { + retcode = Write ( RightSample, 1 ); + if ( retcode == DDC_SUCCESS ) + { + pcm_data.ckSize += 2; + } + } + break; + + case 16: + retcode = Write ( LeftSample, 2 ); + if ( retcode == DDC_SUCCESS ) + { + retcode = Write ( RightSample, 2 ); + if ( retcode == DDC_SUCCESS ) + { + pcm_data.ckSize += 4; + } + } + break; + + default: + retcode = DDC_INVALID_CALL; + } + return retcode; + }*/ + + /** + * + * + public int ReadMonoSample ( short[] Sample ) + { + int retcode = DDC_SUCCESS; + switch ( wave_format.data.nBitsPerSample ) + { + case 8: + byte[] x = {0}; + retcode = Read ( x, 1 ); + Sample[0] = (short)(x[0]); + break; + + case 16: + retcode = Read ( Sample, 2 ); + break; + + default: + retcode = DDC_INVALID_CALL; + } + return retcode; + }*/ + + /** + * + * + public int ReadStereoSample ( short[] LeftSampleData, short[] RightSampleData ) + { + int retcode = DDC_SUCCESS; + byte[] x = new byte[2]; + short[] y = new short[2]; + switch ( wave_format.data.nBitsPerSample ) + { + case 8: + retcode = Read ( x, 2 ); + L[0] = (short) ( x[0] ); + R[0] = (short) ( x[1] ); + break; + + case 16: + retcode = Read ( y, 4 ); + L[0] = (short) ( y[0] ); + R[0] = (short) ( y[1] ); + break; + + default: + retcode = DDC_INVALID_CALL; + } + return retcode; + }*/ + + + /** + * + */ + public int Close() + { + int rc = DDC_SUCCESS; + + if ( fmode == RFM_WRITE ) + rc = Backpatch ( pcm_data_offset, pcm_data, 8 ); + if ( rc == DDC_SUCCESS ) + rc = super.Close(); + return rc; + } + + // [Hz] + public int SamplingRate() + {return wave_format.data.nSamplesPerSec;} + + public short BitsPerSample() + {return wave_format.data.nBitsPerSample;} + + public short NumChannels() + {return wave_format.data.nChannels;} + + public int NumSamples() + {return num_samples;} + + + /** + * Open for write using another wave file's parameters... + */ + public int OpenForWrite (String Filename, WaveFile OtherWave ) + { + return OpenForWrite ( Filename, + OtherWave.SamplingRate(), + OtherWave.BitsPerSample(), + OtherWave.NumChannels() ); + } + + /** + * + */ + public long CurrentFilePosition() + { + return super.CurrentFilePosition(); + } + + /* public int FourCC(String ChunkName) + { + byte[] p = {0x20,0x20,0x20,0x20}; + ChunkName.getBytes(0,4,p,0); + int ret = (((p[0] << 24)& 0xFF000000) | ((p[1] << 16)&0x00FF0000) | ((p[2] << 8)&0x0000FF00) | (p[3]&0x000000FF)); + return ret; + }*/ + +} \ No newline at end of file diff --git a/songdbj/javazoom/jl/converter/WaveFileObuffer.java b/songdbj/javazoom/jl/converter/WaveFileObuffer.java new file mode 100644 index 0000000000..eaa1dd46d4 --- /dev/null +++ b/songdbj/javazoom/jl/converter/WaveFileObuffer.java @@ -0,0 +1,141 @@ +/* + * 11/19/04 1.0 moved to LGPL. + * + * 12/12/99 0.0.7 Renamed class, additional constructor arguments + * and larger write buffers. mdm@techie.com. + * + * 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.converter; + +import javazoom.jl.decoder.Obuffer; + +/** + * Implements an Obuffer by writing the data to + * a file in RIFF WAVE format. + * + * @since 0.0 + */ + + +public class WaveFileObuffer extends Obuffer +{ + private short[] buffer; + private short[] bufferp; + private int channels; + private WaveFile outWave; + + /** + * Creates a new WareFileObuffer instance. + * + * @param number_of_channels + * The number of channels of audio data + * this buffer will receive. + * + * @param freq The sample frequency of the samples in the buffer. + * + * @param fileName The filename to write the data to. + */ + public WaveFileObuffer(int number_of_channels, int freq, String FileName) + { + if (FileName==null) + throw new NullPointerException("FileName"); + + buffer = new short[OBUFFERSIZE]; + bufferp = new short[MAXCHANNELS]; + channels = number_of_channels; + + for (int i = 0; i < number_of_channels; ++i) + bufferp[i] = (short)i; + + outWave = new WaveFile(); + + int rc = outWave.OpenForWrite (FileName,freq,(short)16,(short)channels); + } + + /** + * Takes a 16 Bit PCM sample. + */ + public void append(int channel, short value) + { + buffer[bufferp[channel]] = value; + bufferp[channel] += channels; + } + + /** + * Write the samples to the file (Random Acces). + */ + short[] myBuffer = new short[2]; + public void write_buffer(int val) + { + + int k = 0; + int rc = 0; + + rc = outWave.WriteData(buffer, bufferp[0]); + // REVIEW: handle RiffFile errors. + /* + for (int j=0;j>8)&0x000000FF) | ((buffer[j]<<8)&0x0000FF00)); + //myBuffer[1] = (short) (((buffer[j+1]>>8)&0x000000FF) | ((buffer[j+1]<<8)&0x0000FF00)); + myBuffer[0] = buffer[j]; + myBuffer[1] = buffer[j+1]; + rc = outWave.WriteData (myBuffer,2); + } + */ + for (int i = 0; i < channels; ++i) bufferp[i] = (short)i; + } + + public void close() + { + outWave.Close(); + } + + /** + * + */ + public void clear_buffer() + {} + + /** + * + */ + public void set_stop_flag() + {} + + /* + * Create STDOUT buffer + * + * + public static Obuffer create_stdout_obuffer(MPEG_Args maplay_args) + { + Obuffer thebuffer = null; + int mode = maplay_args.MPEGheader.mode(); + int which_channels = maplay_args.which_c; + if (mode == Header.single_channel || which_channels != MPEG_Args.both) + thebuffer = new FileObuffer(1,maplay_args.output_filename); + else + thebuffer = new FileObuffer(2,maplay_args.output_filename); + return(thebuffer); + } + */ +} diff --git a/songdbj/javazoom/jl/converter/jlc.java b/songdbj/javazoom/jl/converter/jlc.java new file mode 100644 index 0000000000..57c84eba4a --- /dev/null +++ b/songdbj/javazoom/jl/converter/jlc.java @@ -0,0 +1,216 @@ +/* + * 11/19/04 1.0 moved to LGPL. + * + * 29/01/00 Initial version. mdm@techie.com + * + * 12/12/99 JavaLayer 0.0.7 mdm@techie.com + * + * 14/02/99 MPEG_Args Based Class - E.B + * Adapted from javalayer and MPEG_Args. + * Doc'ed and integerated with JL converter. Removed + * Win32 specifics from original Maplay code. + *----------------------------------------------------------------------- + * 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.PrintWriter; + +import javazoom.jl.decoder.Crc16; +import javazoom.jl.decoder.JavaLayerException; +import javazoom.jl.decoder.OutputChannels; + +/** + * The jlc 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;i2) + { + try + { + String level = argv[i].substring(2); + verbose_level = Integer.parseInt(level); + } + catch (NumberFormatException ex) + { + System.err.println("Invalid verbose level. Using default."); + } + } + System.out.println("Verbose Activated (level "+verbose_level+")"); + } + /* else if (argv[i].equals("-s")) + ma.stdout_mode = true; */ + else if (argv[i].equals("-p")) + { + if (++i == argc) + { + System.out.println("Please specify an output filename after the -p option!"); + System.exit (1); + } + //output_mode = O_WAVEFILE; + output_filename = argv[i]; + } + /*else if (argv[i].equals("-f")) + { + if (++i == argc) + { + System.out.println("Please specify a new scalefactor after the -f option!"); + System.exit(1); + } + ma.use_own_scalefactor = true; + // ma.scalefactor = argv[i]; + }*/ + else return Usage(); + } + else + { + filename = argv[i]; + System.out.println("FileName = "+argv[i]); + if (filename == null) return Usage(); + } + i++; + } + if (filename == null) + return Usage(); + + return true; + } + + + /** + * Usage of JavaLayer. + */ + public boolean Usage() + { + System.out.println("JavaLayer Converter :"); + System.out.println(" -v[x] verbose mode. "); + System.out.println(" default = 2"); + /* System.out.println(" -s write u-law samples at 8 kHz rate to stdout"); + System.out.println(" -l decode only the left channel"); + System.out.println(" -r decode only the right channel"); + System.out.println(" -d downmix mode (layer III only)"); + System.out.println(" -s write pcm samples to stdout"); + System.out.println(" -d downmix mode (layer III only)");*/ + System.out.println(" -p name output as a PCM wave file"); + System.out.println(""); + System.out.println(" More info on http://www.javazoom.net"); + /* System.out.println(" -f ushort use this scalefactor instead of the default value 32768");*/ + return false; + } + }; +}; \ No newline at end of file diff --git a/songdbj/javazoom/jl/decoder/BitReserve.java b/songdbj/javazoom/jl/decoder/BitReserve.java new file mode 100644 index 0000000000..a5d3056d61 --- /dev/null +++ b/songdbj/javazoom/jl/decoder/BitReserve.java @@ -0,0 +1,223 @@ +/* + * 11/19/04 1.0 moved to LGPL. + * + * 12/12/99 0.0.7 Implementation stores single bits + * as ints for better performance. mdm@techie.com. + * + * 02/28/99 0.0 Java Conversion by E.B, javalayer@javazoom.net + * + * Adapted from the public c code by Jeff Tsay. + * + *----------------------------------------------------------------------- + * 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; + +/** + * Implementation of Bit Reservoir for Layer III. + *

+ * 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/songdbj/javazoom/jl/decoder/Bitstream.java b/songdbj/javazoom/jl/decoder/Bitstream.java new file mode 100644 index 0000000000..cebbd5b03b --- /dev/null +++ b/songdbj/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 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;k>> (32 - sum)) & bitmask[number_of_bits]; + // returnvalue = (wordpointer[0] >> (32 - sum)) & bitmask[number_of_bits]; + if ((bitindex += number_of_bits) == 32) + { + bitindex = 0; + wordpointer++; // added by me! + } + return returnvalue; + } + + // E.B : Check that ? + //((short[])&returnvalue)[0] = ((short[])wordpointer + 1)[0]; + //wordpointer++; // Added by me! + //((short[])&returnvalue + 1)[0] = ((short[])wordpointer)[0]; + int Right = (framebuffer[wordpointer] & 0x0000FFFF); + wordpointer++; + int Left = (framebuffer[wordpointer] & 0xFFFF0000); + returnvalue = ((Right << 16) & 0xFFFF0000) | ((Left >>> 16)& 0x0000FFFF); + + returnvalue >>>= 48 - sum; // returnvalue >>= 16 - (number_of_bits - (32 - bitindex)) + returnvalue &= bitmask[number_of_bits]; + bitindex = sum - 32; + return returnvalue; +} + + /** + * Set the word we want to sync the header to. + * In Big-Endian byte order + */ + void set_syncword(int syncword0) + { + syncword = syncword0 & 0xFFFFFF3F; + single_ch_mode = ((syncword0 & 0x000000C0) == 0x000000C0); + } + /** + * Reads the exact number of bytes from the source + * input stream into a byte array. + * + * @param b The byte array to read the specified number + * of bytes into. + * @param offs The index in the array where the first byte + * read should be stored. + * @param len the number of bytes to read. + * + * @exception BitstreamException is thrown if the specified + * number of bytes could not be read from the stream. + */ + private int readFully(byte[] b, int offs, int len) + throws BitstreamException + { + int nRead = 0; + try + { + while (len > 0) + { + int bytesread = source.read(b, offs, len); + if (bytesread == -1) + { + while (len-->0) + { + b[offs++] = 0; + } + break; + //throw newBitstreamException(UNEXPECTED_EOF, new EOFException()); + } + nRead = nRead + bytesread; + offs += bytesread; + len -= bytesread; + } + } + catch (IOException ex) + { + throw newBitstreamException(STREAM_ERROR, ex); + } + return nRead; + } + + /** + * Simlar to readFully, but doesn't throw exception when + * EOF is reached. + */ + private int readBytes(byte[] b, int offs, int len) + throws BitstreamException + { + int totalBytesRead = 0; + try + { + while (len > 0) + { + int bytesread = source.read(b, offs, len); + if (bytesread == -1) + { + break; + } + totalBytesRead += bytesread; + offs += bytesread; + len -= bytesread; + } + } + catch (IOException ex) + { + throw newBitstreamException(STREAM_ERROR, ex); + } + return totalBytesRead; + } +} diff --git a/songdbj/javazoom/jl/decoder/BitstreamErrors.java b/songdbj/javazoom/jl/decoder/BitstreamErrors.java new file mode 100644 index 0000000000..2bdee6d797 --- /dev/null +++ b/songdbj/javazoom/jl/decoder/BitstreamErrors.java @@ -0,0 +1,72 @@ +/* + * 11/19/04 1.0 moved to LGPL. + * 11/17/04 INVALIDFRAME code added. javalayer@javazoom.net + * 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; + +/** + * This interface describes all error codes that can be thrown + * in BistreamExceptions. + * + * @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/songdbj/javazoom/jl/decoder/BitstreamException.java b/songdbj/javazoom/jl/decoder/BitstreamException.java new file mode 100644 index 0000000000..99faa8962d --- /dev/null +++ b/songdbj/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. + *

+ * The exception provides details of the exception condition + * in two ways: + *

  1. + * as an error-code describing the nature of the error + *


  2. + * as the Throwable instance, if any, that was thrown + * indicating that an exceptional condition has occurred. + *

+ * + * @since 0.0.6 + * @author MDM 12/12/99 + */ + +public class BitstreamException extends JavaLayerException + implements BitstreamErrors +{ + private int errorcode = UNKNOWN_ERROR; + + public BitstreamException(String msg, Throwable t) + { + super(msg, t); + } + + public BitstreamException(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 bundle to map error codes + // to locale-sensitive strings. + + return "Bitstream errorcode "+Integer.toHexString(errorcode); + } + + +} diff --git a/songdbj/javazoom/jl/decoder/Control.java b/songdbj/javazoom/jl/decoder/Control.java new file mode 100644 index 0000000000..080ed5215e --- /dev/null +++ b/songdbj/javazoom/jl/decoder/Control.java @@ -0,0 +1,57 @@ +/* + * 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; + +/** + * Work in progress. + */ + +public interface Control +{ + + /** + * Starts playback of the media presented by this control. + */ + public void start(); + + /** + * Stops playback of the media presented by this control. + */ + public void stop(); + + public boolean isPlaying(); + + public void pause(); + + + public boolean isRandomAccess(); + + /** + * Retrieves the current position. + */ + public double getPosition(); + + /** + * + */ + public void setPosition(double d); + + +} diff --git a/songdbj/javazoom/jl/decoder/Crc16.java b/songdbj/javazoom/jl/decoder/Crc16.java new file mode 100644 index 0000000000..c35cc19341 --- /dev/null +++ b/songdbj/javazoom/jl/decoder/Crc16.java @@ -0,0 +1,70 @@ +/* + * 11/19/04 : 1.0 moved to LGPL. + * + * 02/12/99 : Java Conversion by E.B , javalayer@javazoom.net + * + * @(#) crc.h 1.5, last edit: 6/15/94 16:55:32 + * @(#) 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; + +/** + * 16-Bit CRC checksum + */ +public final class Crc16 +{ + private static short polynomial=(short)0x8005; + private short crc; + + /** + * Dummy Constructor + */ + public Crc16() + { + crc = (short) 0xFFFF; + } + + /** + * Feed a bitstring to the crc calculation (0 < length <= 32). + */ + public void add_bits (int bitstring, int length) + { + int bitmask = 1 << (length - 1); + do + if (((crc & 0x8000) == 0) ^ ((bitstring & bitmask) == 0 )) + { + crc <<= 1; + crc ^= polynomial; + } + else + crc <<= 1; + while ((bitmask >>>= 1) != 0); + } + + /** + * Return the calculated checksum. + * Erase it for next calls to add_bits(). + */ + public short checksum() + { + short sum = crc; + crc = (short) 0xFFFF; + return sum; + } +} diff --git a/songdbj/javazoom/jl/decoder/Decoder.java b/songdbj/javazoom/jl/decoder/Decoder.java new file mode 100644 index 0000000000..076f9dea27 --- /dev/null +++ b/songdbj/javazoom/jl/decoder/Decoder.java @@ -0,0 +1,357 @@ +/* + * 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 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/songdbj/javazoom/jl/decoder/DecoderErrors.java b/songdbj/javazoom/jl/decoder/DecoderErrors.java new file mode 100644 index 0000000000..66c1935051 --- /dev/null +++ b/songdbj/javazoom/jl/decoder/DecoderErrors.java @@ -0,0 +1,38 @@ +/* + * 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; +} diff --git a/songdbj/javazoom/jl/decoder/DecoderException.java b/songdbj/javazoom/jl/decoder/DecoderException.java new file mode 100644 index 0000000000..b75710870f --- /dev/null +++ b/songdbj/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/songdbj/javazoom/jl/decoder/Equalizer.java b/songdbj/javazoom/jl/decoder/Equalizer.java new file mode 100644 index 0000000000..57545a939d --- /dev/null +++ b/songdbj/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 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; i=0) && (band=0) && (band 1.0f) + return 1.0f; + if (eq < -1.0f) + return -1.0f; + + return eq; + } + + /** + * Retrieves an array of floats whose values represent a + * scaling factor that can be applied to linear samples + * in each band to provide the equalization represented by + * this instance. + * + * @return an array of factors that can be applied to the + * subbands. + */ + float[] getBandFactors() + { + float[] factors = new float[BANDS]; + for (int i=0, maxCount=BANDS; i>> 19) & 1); + if (((headerstring >>> 20) & 1) == 0) // SZD: MPEG2.5 detection + if (h_version == MPEG2_LSF) + h_version = MPEG25_LSF; + else + throw stream.newBitstreamException(Bitstream.UNKNOWN_ERROR); + if ((h_sample_frequency = ((headerstring >>> 10) & 3)) == 3) + { + throw stream.newBitstreamException(Bitstream.UNKNOWN_ERROR); + } + } + h_layer = 4 - (headerstring >>> 17) & 3; + h_protection_bit = (headerstring >>> 16) & 1; + h_bitrate_index = (headerstring >>> 12) & 0xF; + h_padding_bit = (headerstring >>> 9) & 1; + h_mode = ((headerstring >>> 6) & 3); + h_mode_extension = (headerstring >>> 4) & 3; + if (h_mode == JOINT_STEREO) + h_intensity_stereo_bound = (h_mode_extension << 2) + 4; + else + h_intensity_stereo_bound = 0; // should never be used + if (((headerstring >>> 3) & 1) == 1) + h_copyright = true; + if (((headerstring >>> 2) & 1) == 1) + h_original = true; + // calculate number of subbands: + if (h_layer == 1) + h_number_of_subbands = 32; + else + { + channel_bitrate = h_bitrate_index; + // calculate bitrate per channel: + if (h_mode != SINGLE_CHANNEL) + if (channel_bitrate == 4) + channel_bitrate = 1; + else + channel_bitrate -= 4; + if ((channel_bitrate == 1) || (channel_bitrate == 2)) + if (h_sample_frequency == THIRTYTWO) + h_number_of_subbands = 12; + else + h_number_of_subbands = 8; + else if ((h_sample_frequency == FOURTYEIGHT) || ((channel_bitrate >= 3) && (channel_bitrate <= 5))) + h_number_of_subbands = 27; + else + h_number_of_subbands = 30; + } + if (h_intensity_stereo_bound > h_number_of_subbands) + h_intensity_stereo_bound = h_number_of_subbands; + // calculate framesize and nSlots + calculate_framesize(); + // read framedata: + int framesizeloaded = stream.read_frame_data(framesize); + if ((framesize >=0) && (framesizeloaded != framesize)) + { + // Data loaded does not match to expected framesize, + // it might be an ID3v1 TAG. (Fix 11/17/04). + throw stream.newBitstreamException(Bitstream.INVALIDFRAME); + } + if (stream.isSyncCurrentPosition(syncmode)) + { + if (syncmode == Bitstream.INITIAL_SYNC) + { + syncmode = Bitstream.STRICT_SYNC; + stream.set_syncword(headerstring & 0xFFF80CC0); + } + sync = true; + } + else + { + stream.unreadFrame(); + } + } + while (!sync); + stream.parse_frame(); + if (h_protection_bit == 0) + { + // frame contains a crc checksum + checksum = (short) stream.get_bits(16); + if (crc == null) + crc = new Crc16(); + crc.add_bits(headerstring, 16); + crcp[0] = crc; + } + else + crcp[0] = null; + if (h_sample_frequency == FOURTYFOUR_POINT_ONE) + { + /* + if (offset == null) + { + int max = max_number_of_frames(stream); + offset = new int[max]; + for(int i=0; i 0) && (cf == lf)) + { + offset[cf] = offset[cf-1] + h_padding_bit; + } + else + { + offset[0] = h_padding_bit; + } + */ + } + } + + /** + * Parse frame to extract optionnal VBR frame. + * @param firstframe + * @author E.B (javalayer@javazoom.net) + */ + void parseVBR(byte[] firstframe) throws BitstreamException + { + // Trying Xing header. + String xing = "Xing"; + byte tmp[] = new byte[4]; + int offset = 0; + // Compute "Xing" offset depending on MPEG version and channels. + if (h_version == MPEG1) + { + if (h_mode == SINGLE_CHANNEL) offset=21-4; + else offset=36-4; + } + else + { + if (h_mode == SINGLE_CHANNEL) offset=13-4; + else offset = 21-4; + } + try + { + System.arraycopy(firstframe, offset, tmp, 0, 4); + // Is "Xing" ? + if (xing.equals(new String(tmp))) + { + //Yes. + h_vbr = true; + h_vbr_frames = -1; + h_vbr_bytes = -1; + h_vbr_scale = -1; + h_vbr_toc = new byte[100]; + + int length = 4; + // Read flags. + byte flags[] = new byte[4]; + System.arraycopy(firstframe, offset + length, flags, 0, flags.length); + length += flags.length; + // Read number of frames (if available). + if ((flags[3] & (byte) (1 << 0)) != 0) + { + System.arraycopy(firstframe, offset + length, tmp, 0, tmp.length); + h_vbr_frames = (tmp[0] << 24)&0xFF000000 | (tmp[1] << 16)&0x00FF0000 | (tmp[2] << 8)&0x0000FF00 | tmp[3]&0x000000FF; + length += 4; + } + // Read size (if available). + if ((flags[3] & (byte) (1 << 1)) != 0) + { + System.arraycopy(firstframe, offset + length, tmp, 0, tmp.length); + h_vbr_bytes = (tmp[0] << 24)&0xFF000000 | (tmp[1] << 16)&0x00FF0000 | (tmp[2] << 8)&0x0000FF00 | tmp[3]&0x000000FF; + length += 4; + } + // Read TOC (if available). + if ((flags[3] & (byte) (1 << 2)) != 0) + { + System.arraycopy(firstframe, offset + length, h_vbr_toc, 0, h_vbr_toc.length); + length += h_vbr_toc.length; + } + // Read scale (if available). + if ((flags[3] & (byte) (1 << 3)) != 0) + { + System.arraycopy(firstframe, offset + length, tmp, 0, tmp.length); + h_vbr_scale = (tmp[0] << 24)&0xFF000000 | (tmp[1] << 16)&0x00FF0000 | (tmp[2] << 8)&0x0000FF00 | tmp[3]&0x000000FF; + length += 4; + } + //System.out.println("VBR:"+xing+" Frames:"+ h_vbr_frames +" Size:"+h_vbr_bytes); + } + } + catch (ArrayIndexOutOfBoundsException e) + { + throw new BitstreamException("XingVBRHeader Corrupted",e); + } + + // Trying VBRI header. + String vbri = "VBRI"; + offset = 36-4; + try + { + System.arraycopy(firstframe, offset, tmp, 0, 4); + // Is "VBRI" ? + if (vbri.equals(new String(tmp))) + { + //Yes. + h_vbr = true; + h_vbr_frames = -1; + h_vbr_bytes = -1; + h_vbr_scale = -1; + h_vbr_toc = new byte[100]; + // Bytes. + int length = 4 + 6; + System.arraycopy(firstframe, offset + length, tmp, 0, tmp.length); + h_vbr_bytes = (tmp[0] << 24)&0xFF000000 | (tmp[1] << 16)&0x00FF0000 | (tmp[2] << 8)&0x0000FF00 | tmp[3]&0x000000FF; + length += 4; + // Frames. + System.arraycopy(firstframe, offset + length, tmp, 0, tmp.length); + h_vbr_frames = (tmp[0] << 24)&0xFF000000 | (tmp[1] << 16)&0x00FF0000 | (tmp[2] << 8)&0x0000FF00 | tmp[3]&0x000000FF; + length += 4; + //System.out.println("VBR:"+vbri+" Frames:"+ h_vbr_frames +" Size:"+h_vbr_bytes); + // TOC + // TODO + } + } + catch (ArrayIndexOutOfBoundsException e) + { + throw new BitstreamException("VBRIVBRHeader Corrupted",e); + } + } + + // Functions to query header contents: + /** + * Returns version. + */ + public int version() { return h_version; } + + /** + * Returns Layer ID. + */ + public int layer() { return h_layer; } + + /** + * Returns bitrate index. + */ + public int bitrate_index() { return h_bitrate_index; } + + /** + * Returns Sample Frequency. + */ + public int sample_frequency() { return h_sample_frequency; } + + /** + * Returns Frequency. + */ + public int frequency() {return frequencies[h_version][h_sample_frequency];} + + /** + * Returns Mode. + */ + public int mode() { return h_mode; } + + /** + * Returns Protection bit. + */ + public boolean checksums() + { + if (h_protection_bit == 0) return true; + else return false; + } + + /** + * Returns Copyright. + */ + public boolean copyright() { return h_copyright; } + + /** + * Returns Original. + */ + public boolean original() { return h_original; } + + /** + * Return VBR. + * @return true if VBR header is found + */ + public boolean vbr() { return h_vbr; } + + /** + * Return VBR scale. + * @return scale of -1 if not available + */ + public int vbr_scale() { return h_vbr_scale; } + + /** + * Return VBR TOC. + * @return vbr toc ot null if not available + */ + public byte[] vbr_toc() { return h_vbr_toc; } + + /** + * Returns Checksum flag. + * Compares computed checksum with stream checksum. + */ + public boolean checksum_ok () { return (checksum == crc.checksum()); } + + // Seeking and layer III stuff + /** + * Returns Layer III Padding bit. + */ + public boolean padding() + { + if (h_padding_bit == 0) return false; + else return true; + } + + /** + * Returns Slots. + */ + public int slots() { return nSlots; } + + /** + * Returns Mode Extension. + */ + public int mode_extension() { return h_mode_extension; } + + // E.B -> private to public + public static final int bitrates[][][] = { + {{0 /*free format*/, 32000, 48000, 56000, 64000, 80000, 96000, + 112000, 128000, 144000, 160000, 176000, 192000 ,224000, 256000, 0}, + {0 /*free format*/, 8000, 16000, 24000, 32000, 40000, 48000, + 56000, 64000, 80000, 96000, 112000, 128000, 144000, 160000, 0}, + {0 /*free format*/, 8000, 16000, 24000, 32000, 40000, 48000, + 56000, 64000, 80000, 96000, 112000, 128000, 144000, 160000, 0}}, + + {{0 /*free format*/, 32000, 64000, 96000, 128000, 160000, 192000, + 224000, 256000, 288000, 320000, 352000, 384000, 416000, 448000, 0}, + {0 /*free format*/, 32000, 48000, 56000, 64000, 80000, 96000, + 112000, 128000, 160000, 192000, 224000, 256000, 320000, 384000, 0}, + {0 /*free format*/, 32000, 40000, 48000, 56000, 64000, 80000, + 96000, 112000, 128000, 160000, 192000, 224000, 256000, 320000, 0}}, + // SZD: MPEG2.5 + {{0 /*free format*/, 32000, 48000, 56000, 64000, 80000, 96000, + 112000, 128000, 144000, 160000, 176000, 192000 ,224000, 256000, 0}, + {0 /*free format*/, 8000, 16000, 24000, 32000, 40000, 48000, + 56000, 64000, 80000, 96000, 112000, 128000, 144000, 160000, 0}, + {0 /*free format*/, 8000, 16000, 24000, 32000, 40000, 48000, + 56000, 64000, 80000, 96000, 112000, 128000, 144000, 160000, 0}}, + + }; + + // E.B -> private to public + /** + * Calculate Frame size. + * Calculates framesize in bytes excluding header size. + */ + public int calculate_framesize() + { + + if (h_layer == 1) + { + framesize = (12 * bitrates[h_version][0][h_bitrate_index]) / + frequencies[h_version][h_sample_frequency]; + if (h_padding_bit != 0 ) framesize++; + framesize <<= 2; // one slot is 4 bytes long + nSlots = 0; + } + else + { + framesize = (144 * bitrates[h_version][h_layer - 1][h_bitrate_index]) / + frequencies[h_version][h_sample_frequency]; + if (h_version == MPEG2_LSF || h_version == MPEG25_LSF) framesize >>= 1; // SZD + if (h_padding_bit != 0) framesize++; + // Layer III slots + if (h_layer == 3) + { + if (h_version == MPEG1) + { + nSlots = framesize - ((h_mode == SINGLE_CHANNEL) ? 17 : 32) // side info size + - ((h_protection_bit!=0) ? 0 : 2) // CRC size + - 4; // header size + } + else + { // MPEG-2 LSF, SZD: MPEG-2.5 LSF + nSlots = framesize - ((h_mode == SINGLE_CHANNEL) ? 9 : 17) // side info size + - ((h_protection_bit!=0) ? 0 : 2) // CRC size + - 4; // header size + } + } + else + { + nSlots = 0; + } + } + framesize -= 4; // subtract header size + return framesize; + } + + /** + * Returns the maximum number of frames in the stream. + * @param streamsize + * @return number of frames + */ + public int max_number_of_frames(int streamsize) // E.B + { + if (h_vbr == true) return h_vbr_frames; + else + { + if ((framesize + 4 - h_padding_bit) == 0) return 0; + else return(streamsize / (framesize + 4 - h_padding_bit)); + } + } + + /** + * Returns the maximum number of frames in the stream. + * @param streamsize + * @return number of frames + */ + public int min_number_of_frames(int streamsize) // E.B + { + if (h_vbr == true) return h_vbr_frames; + else + { + if ((framesize + 5 - h_padding_bit) == 0) return 0; + else return(streamsize / (framesize + 5 - h_padding_bit)); + } + } + + + /** + * Returns ms/frame. + * @return milliseconds per frame + */ + public float ms_per_frame() // E.B + { + if (h_vbr == true) + { + double tpf = h_vbr_time_per_frame[layer()] / frequency(); + if ((h_version == MPEG2_LSF) || (h_version == MPEG25_LSF)) tpf /= 2; + return ((float) (tpf * 1000)); + } + else + { + float ms_per_frame_array[][] = {{8.707483f, 8.0f, 12.0f}, + {26.12245f, 24.0f, 36.0f}, + {26.12245f, 24.0f, 36.0f}}; + return(ms_per_frame_array[h_layer-1][h_sample_frequency]); + } + } + + /** + * Returns total ms. + * @param streamsize + * @return total milliseconds + */ + public float total_ms(int streamsize) // E.B + { + return(max_number_of_frames(streamsize) * ms_per_frame()); + } + + /** + * Returns synchronized header. + */ + public int getSyncHeader() // E.B + { + return _headerstring; + } + + // functions which return header informations as strings: + /** + * Return Layer version. + */ + public String layer_string() + { + switch (h_layer) + { + case 1: + return "I"; + case 2: + return "II"; + case 3: + return "III"; + } + return null; + } + + // E.B -> private to public + public static final String bitrate_str[][][] = { + {{"free format", "32 kbit/s", "48 kbit/s", "56 kbit/s", "64 kbit/s", + "80 kbit/s", "96 kbit/s", "112 kbit/s", "128 kbit/s", "144 kbit/s", + "160 kbit/s", "176 kbit/s", "192 kbit/s", "224 kbit/s", "256 kbit/s", + "forbidden"}, + {"free format", "8 kbit/s", "16 kbit/s", "24 kbit/s", "32 kbit/s", + "40 kbit/s", "48 kbit/s", "56 kbit/s", "64 kbit/s", "80 kbit/s", + "96 kbit/s", "112 kbit/s", "128 kbit/s", "144 kbit/s", "160 kbit/s", + "forbidden"}, + {"free format", "8 kbit/s", "16 kbit/s", "24 kbit/s", "32 kbit/s", + "40 kbit/s", "48 kbit/s", "56 kbit/s", "64 kbit/s", "80 kbit/s", + "96 kbit/s", "112 kbit/s", "128 kbit/s", "144 kbit/s", "160 kbit/s", + "forbidden"}}, + + {{"free format", "32 kbit/s", "64 kbit/s", "96 kbit/s", "128 kbit/s", + "160 kbit/s", "192 kbit/s", "224 kbit/s", "256 kbit/s", "288 kbit/s", + "320 kbit/s", "352 kbit/s", "384 kbit/s", "416 kbit/s", "448 kbit/s", + "forbidden"}, + {"free format", "32 kbit/s", "48 kbit/s", "56 kbit/s", "64 kbit/s", + "80 kbit/s", "96 kbit/s", "112 kbit/s", "128 kbit/s", "160 kbit/s", + "192 kbit/s", "224 kbit/s", "256 kbit/s", "320 kbit/s", "384 kbit/s", + "forbidden"}, + {"free format", "32 kbit/s", "40 kbit/s", "48 kbit/s", "56 kbit/s", + "64 kbit/s", "80 kbit/s" , "96 kbit/s", "112 kbit/s", "128 kbit/s", + "160 kbit/s", "192 kbit/s", "224 kbit/s", "256 kbit/s", "320 kbit/s", + "forbidden"}}, + // SZD: MPEG2.5 + {{"free format", "32 kbit/s", "48 kbit/s", "56 kbit/s", "64 kbit/s", + "80 kbit/s", "96 kbit/s", "112 kbit/s", "128 kbit/s", "144 kbit/s", + "160 kbit/s", "176 kbit/s", "192 kbit/s", "224 kbit/s", "256 kbit/s", + "forbidden"}, + {"free format", "8 kbit/s", "16 kbit/s", "24 kbit/s", "32 kbit/s", + "40 kbit/s", "48 kbit/s", "56 kbit/s", "64 kbit/s", "80 kbit/s", + "96 kbit/s", "112 kbit/s", "128 kbit/s", "144 kbit/s", "160 kbit/s", + "forbidden"}, + {"free format", "8 kbit/s", "16 kbit/s", "24 kbit/s", "32 kbit/s", + "40 kbit/s", "48 kbit/s", "56 kbit/s", "64 kbit/s", "80 kbit/s", + "96 kbit/s", "112 kbit/s", "128 kbit/s", "144 kbit/s", "160 kbit/s", + "forbidden"}}, + }; + + /** + * Return Bitrate. + * @return bitrate in bps + */ + public String bitrate_string() + { + if (h_vbr == true) + { + return Integer.toString(bitrate()/1000)+" kb/s"; + } + else return bitrate_str[h_version][h_layer - 1][h_bitrate_index]; + } + + /** + * Return Bitrate. + * @return bitrate in bps and average bitrate for VBR header + */ + public int bitrate() + { + if (h_vbr == true) + { + return ((int) ((h_vbr_bytes * 8) / (ms_per_frame() * h_vbr_frames)))*1000; + } + else return bitrates[h_version][h_layer - 1][h_bitrate_index]; + } + + /** + * Return Instant Bitrate. + * Bitrate for VBR is not constant. + * @return bitrate in bps + */ + public int bitrate_instant() + { + return bitrates[h_version][h_layer - 1][h_bitrate_index]; + } + + /** + * Returns Frequency + * @return frequency string in kHz + */ + public String sample_frequency_string() + { + switch (h_sample_frequency) + { + case THIRTYTWO: + if (h_version == MPEG1) + return "32 kHz"; + else if (h_version == MPEG2_LSF) + return "16 kHz"; + else // SZD + return "8 kHz"; + case FOURTYFOUR_POINT_ONE: + if (h_version == MPEG1) + return "44.1 kHz"; + else if (h_version == MPEG2_LSF) + return "22.05 kHz"; + else // SZD + return "11.025 kHz"; + case FOURTYEIGHT: + if (h_version == MPEG1) + return "48 kHz"; + else if (h_version == MPEG2_LSF) + return "24 kHz"; + else // SZD + return "12 kHz"; + } + return(null); + } + + /** + * Returns Mode. + */ + public String mode_string() + { + switch (h_mode) + { + case STEREO: + return "Stereo"; + case JOINT_STEREO: + return "Joint stereo"; + case DUAL_CHANNEL: + return "Dual channel"; + case SINGLE_CHANNEL: + return "Single channel"; + } + return null; + } + + /** + * Returns Version. + * @return MPEG-1 or MPEG-2 LSF or MPEG-2.5 LSF + */ + public String version_string() + { + switch (h_version) + { + case MPEG1: + return "MPEG-1"; + case MPEG2_LSF: + return "MPEG-2 LSF"; + case MPEG25_LSF: // SZD + return "MPEG-2.5 LSF"; + } + return(null); + } + + /** + * Returns the number of subbands in the current frame. + * @return number of subbands + */ + public int number_of_subbands() {return h_number_of_subbands;} + + /** + * Returns Intensity Stereo. + * (Layer II joint stereo only). + * Returns the number of subbands which are in stereo mode, + * subbands above that limit are in intensity stereo mode. + * @return intensity + */ + public int intensity_stereo_bound() {return h_intensity_stereo_bound;} +} diff --git a/songdbj/javazoom/jl/decoder/InputStreamSource.java b/songdbj/javazoom/jl/decoder/InputStreamSource.java new file mode 100644 index 0000000000..5c62947049 --- /dev/null +++ b/songdbj/javazoom/jl/decoder/InputStreamSource.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.IOException; +import java.io.InputStream; + +/** + * Work In Progress. + * + * An instance of InputStreamSource 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/songdbj/javazoom/jl/decoder/JavaLayerError.java b/songdbj/javazoom/jl/decoder/JavaLayerError.java new file mode 100644 index 0000000000..d9910bcc71 --- /dev/null +++ b/songdbj/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/songdbj/javazoom/jl/decoder/JavaLayerErrors.java b/songdbj/javazoom/jl/decoder/JavaLayerErrors.java new file mode 100644 index 0000000000..3b9c2ff9d7 --- /dev/null +++ b/songdbj/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/songdbj/javazoom/jl/decoder/JavaLayerException.java b/songdbj/javazoom/jl/decoder/JavaLayerException.java new file mode 100644 index 0000000000..e7a50a8340 --- /dev/null +++ b/songdbj/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. + *

+ * + * @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/songdbj/javazoom/jl/decoder/JavaLayerHook.java b/songdbj/javazoom/jl/decoder/JavaLayerHook.java new file mode 100644 index 0000000000..352059433d --- /dev/null +++ b/songdbj/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 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/songdbj/javazoom/jl/decoder/JavaLayerUtils.java b/songdbj/javazoom/jl/decoder/JavaLayerUtils.java new file mode 100644 index 0000000000..c9ce3838e5 --- /dev/null +++ b/songdbj/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/songdbj/javazoom/jl/decoder/LayerIDecoder.java b/songdbj/javazoom/jl/decoder/LayerIDecoder.java new file mode 100644 index 0000000000..b633dd2403 --- /dev/null +++ b/songdbj/javazoom/jl/decoder/LayerIDecoder.java @@ -0,0 +1,444 @@ +/* + * 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() + { + + 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() + { + // 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); + 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) + { + if ((allocation = stream.get_bits (4)) == 15) ; + // 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) + { + 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) + { + 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/songdbj/javazoom/jl/decoder/LayerIIDecoder.java b/songdbj/javazoom/jl/decoder/LayerIIDecoder.java new file mode 100644 index 0000000000..7265b1f8fa --- /dev/null +++ b/songdbj/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/songdbj/javazoom/jl/decoder/LayerIIIDecoder.java b/songdbj/javazoom/jl/decoder/LayerIIIDecoder.java new file mode 100644 index 0000000000..602badf0f2 --- /dev/null +++ b/songdbj/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; i>> 3; // of previous frame + + if ((flush_main = (br.hsstell() & 7)) != 0) { + br.hgetbits(8 - flush_main); + main_data_end++; + } + + bytes_to_discard = frame_start - main_data_end + - si.main_data_begin; + + frame_start += nSlots; + + if (bytes_to_discard < 0) + return; + + if (main_data_end > 4096) { + frame_start -= 4096; + br.rewindNbytes(4096); + } + + for (; bytes_to_discard > 0; bytes_to_discard--) + br.hgetbits(8); + + for (gr=0;gr>> 4) / 5 ; + new_slen[1] = (scalefac_comp >>> 4) % 5 ; + new_slen[2] = (scalefac_comp & 0xF) >>> 2 ; + new_slen[3] = (scalefac_comp & 3); + si.ch[ch].gr[gr].preflag = 0; + blocknumber = 0; + + } else if (scalefac_comp < 500) { + + new_slen[0] = ((scalefac_comp - 400) >>> 2) / 5 ; + new_slen[1] = ((scalefac_comp - 400) >>> 2) % 5 ; + new_slen[2] = (scalefac_comp - 400 ) & 3 ; + new_slen[3] = 0; + si.ch[ch].gr[gr].preflag = 0; + blocknumber = 1; + + } else if (scalefac_comp < 512) { + + new_slen[0] = (scalefac_comp - 500 ) / 3 ; + new_slen[1] = (scalefac_comp - 500) % 3 ; + new_slen[2] = 0; + new_slen[3] = 0; + si.ch[ch].gr[gr].preflag = 1; + blocknumber = 2; + } + } + + if((((mode_ext == 1) || (mode_ext == 3)) && (ch == 1))) + { + int_scalefac_comp = scalefac_comp >>> 1; + + if (int_scalefac_comp < 180) + { + new_slen[0] = int_scalefac_comp / 36 ; + new_slen[1] = (int_scalefac_comp % 36 ) / 6 ; + new_slen[2] = (int_scalefac_comp % 36) % 6; + new_slen[3] = 0; + si.ch[ch].gr[gr].preflag = 0; + blocknumber = 3; + } else if (int_scalefac_comp < 244) { + new_slen[0] = ((int_scalefac_comp - 180 ) & 0x3F) >>> 4 ; + new_slen[1] = ((int_scalefac_comp - 180) & 0xF) >>> 2 ; + new_slen[2] = (int_scalefac_comp - 180 ) & 3 ; + new_slen[3] = 0; + si.ch[ch].gr[gr].preflag = 0; + blocknumber = 4; + } else if (int_scalefac_comp < 255) { + new_slen[0] = (int_scalefac_comp - 244 ) / 3 ; + new_slen[1] = (int_scalefac_comp - 244 ) % 3 ; + new_slen[2] = 0 ; + new_slen[3] = 0; + si.ch[ch].gr[gr].preflag = 0; + blocknumber = 5; + } + } + + for (int x=0; x<45; x++) // why 45, not 54? + scalefac_buffer[x] = 0; + + m = 0; + for (int i=0; i<4;i++) { + for (int j = 0; j < nr_of_sfb_block[blocknumber][blocktypenumber][i]; + j++) + { + scalefac_buffer[m] = (new_slen[i] == 0) ? 0 : + br.hgetbits(new_slen[i]); + m++; + + } // for (unint32 j ... + } // for (uint32 i ... + } + + /** + * + */ + private void get_LSF_scale_factors(int ch, int gr) + { + int m = 0; + int sfb, window; + gr_info_s gr_info = (si.ch[ch].gr[gr]); + + get_LSF_scale_data(ch, gr); + + if ((gr_info.window_switching_flag != 0) && (gr_info.block_type == 2)) { + if (gr_info.mixed_block_flag != 0) { // MIXED + for (sfb = 0; sfb < 8; sfb++) + { + scalefac[ch].l[sfb] = scalefac_buffer[m]; + m++; + } + for (sfb = 3; sfb < 12; sfb++) { + for (window=0; window<3; window++) + { + scalefac[ch].s[window][sfb] = scalefac_buffer[m]; + m++; + } + } + for (window=0; window<3; window++) + scalefac[ch].s[window][12] = 0; + + } else { // SHORT + + for (sfb = 0; sfb < 12; sfb++) { + for (window=0; window<3; window++) + { + scalefac[ch].s[window][sfb] = scalefac_buffer[m]; + m++; + } + } + + for (window=0; window<3; window++) + scalefac[ch].s[window][12] = 0; + } + } else { // LONG types 0,1,3 + + for (sfb = 0; sfb < 21; sfb++) { + scalefac[ch].l[sfb] = scalefac_buffer[m]; + m++; + } + scalefac[ch].l[21] = 0; // Jeff + scalefac[ch].l[22] = 0; + } + } + + /** + * + */ + int[] x = {0}; + int[] y = {0}; + int[] v = {0}; + int[] w = {0}; + private void huffman_decode(int ch, int gr) + { + x[0] = 0; + y[0] = 0; + v[0] = 0; + w[0] = 0; + + int part2_3_end = part2_start + si.ch[ch].gr[gr].part2_3_length; + int num_bits; + int region1Start; + int region2Start; + int index; + + int buf, buf1; + + huffcodetab h; + + // Find region boundary for short block case + + if ( ((si.ch[ch].gr[gr].window_switching_flag) != 0) && + (si.ch[ch].gr[gr].block_type == 2) ) { + + // Region2. + //MS: Extrahandling for 8KHZ + region1Start = (sfreq == 8) ? 72 : 36; // sfb[9/3]*3=36 or in case 8KHZ = 72 + region2Start = 576; // No Region2 for short block case + + } else { // Find region boundary for long block case + + buf = si.ch[ch].gr[gr].region0_count + 1; + buf1 = buf + si.ch[ch].gr[gr].region1_count + 1; + + if(buf1 > sfBandIndex[sfreq].l.length - 1) buf1 = sfBandIndex[sfreq].l.length - 1; + + region1Start = sfBandIndex[sfreq].l[buf]; + region2Start = sfBandIndex[sfreq].l[buf1]; /* MI */ + } + + index = 0; + // Read bigvalues area + for (int i=0; i<(si.ch[ch].gr[gr].big_values<<1); i+=2) { + if (i= is_1d.length) System.out.println("i0="+i+"/"+(si.ch[ch].gr[gr].big_values<<1)+" Index="+index+" is_1d="+is_1d.length); + + is_1d[index++] = x[0]; + is_1d[index++] = y[0]; + + CheckSumHuff = CheckSumHuff + x[0] + y[0]; + // System.out.println("x = "+x[0]+" y = "+y[0]); + } + + // Read count1 area + h = huffcodetab.ht[si.ch[ch].gr[gr].count1table_select+32]; + num_bits = br.hsstell(); + + while ((num_bits < part2_3_end) && (index < 576)) { + + huffcodetab.huffman_decoder(h, x, y, v, w, br); + + is_1d[index++] = v[0]; + is_1d[index++] = w[0]; + is_1d[index++] = x[0]; + is_1d[index++] = y[0]; + CheckSumHuff = CheckSumHuff + v[0] + w[0] + x[0] + y[0]; + // System.out.println("v = "+v[0]+" w = "+w[0]); + // System.out.println("x = "+x[0]+" y = "+y[0]); + num_bits = br.hsstell(); + } + + if (num_bits > part2_3_end) { + br.rewindNbits(num_bits - part2_3_end); + index-=4; + } + + num_bits = br.hsstell(); + + // Dismiss stuffing bits + if (num_bits < part2_3_end) + br.hgetbits(part2_3_end - num_bits); + + // Zero out rest + + if (index < 576) + nonzero[ch] = index; + else + nonzero[ch] = 576; + + if (index < 0) index = 0; + + // may not be necessary + for (; index<576; index++) + is_1d[index] = 0; + } + + /** + * + */ + private void i_stereo_k_values(int is_pos, int io_type, int i) + { + if (is_pos == 0) { + k[0][i] = 1.0f; + k[1][i] = 1.0f; + } else if ((is_pos & 1) != 0) { + k[0][i] = io[io_type][(is_pos + 1) >>> 1]; + k[1][i] = 1.0f; + } else { + k[0][i] = 1.0f; + k[1][i] = io[io_type][is_pos >>> 1]; + } + } + + /** + * + */ + private void dequantize_sample(float xr[][], int ch, int gr) + { + gr_info_s gr_info = (si.ch[ch].gr[gr]); + int cb=0; + int next_cb_boundary; + int cb_begin = 0; + int cb_width = 0; + int index=0, t_index, j; + float g_gain; + float[][] xr_1d = xr; + + // choose correct scalefactor band per block type, initalize boundary + + if ((gr_info.window_switching_flag !=0 ) && (gr_info.block_type == 2) ) { + if (gr_info.mixed_block_flag != 0) + next_cb_boundary=sfBandIndex[sfreq].l[1]; // LONG blocks: 0,1,3 + else { + cb_width = sfBandIndex[sfreq].s[1]; + next_cb_boundary = (cb_width << 2) - cb_width; + cb_begin = 0; + } + } else { + next_cb_boundary=sfBandIndex[sfreq].l[1]; // LONG blocks: 0,1,3 + } + + // Compute overall (global) scaling. + + g_gain = (float) Math.pow(2.0 , (0.25 * (gr_info.global_gain - 210.0))); + + for (j=0; j 0) xr_1d[quotien][reste] = g_gain * t_43[abv]; + else + { + if (-abv < t_43.length) xr_1d[quotien][reste] = -g_gain * t_43[-abv]; + else xr_1d[quotien][reste] = -g_gain * (float)Math.pow(-abv, d43); + } + } + else + { + if (is_1d[j] > 0) xr_1d[quotien][reste] = g_gain * (float)Math.pow(abv, d43); + else xr_1d[quotien][reste] = -g_gain * (float)Math.pow(-abv, d43); + } + } + } + + // apply formula per block type + for (j=0; j= 36)) )) + { + + t_index = (index - cb_begin) / cb_width; + /* xr[sb][ss] *= pow(2.0, ((-2.0 * gr_info.subblock_gain[t_index]) + -(0.5 * (1.0 + gr_info.scalefac_scale) + * scalefac[ch].s[t_index][cb]))); */ + int idx = scalefac[ch].s[t_index][cb] + << gr_info.scalefac_scale; + idx += (gr_info.subblock_gain[t_index] << 2); + + xr_1d[quotien][reste] *= two_to_negative_half_pow[idx]; + + } else { // LONG block types 0,1,3 & 1st 2 subbands of switched blocks + /* xr[sb][ss] *= pow(2.0, -0.5 * (1.0+gr_info.scalefac_scale) + * (scalefac[ch].l[cb] + + gr_info.preflag * pretab[cb])); */ + int idx = scalefac[ch].l[cb]; + + if (gr_info.preflag != 0) + idx += pretab[cb]; + + idx = idx << gr_info.scalefac_scale; + xr_1d[quotien][reste] *= two_to_negative_half_pow[idx]; + } + index++; + } + + for (j=nonzero[ch]; j<576; j++) + { + // Modif E.B 02/22/99 + int reste = j % SSLIMIT; + int quotien = (int) ((j-reste)/SSLIMIT); + if(reste < 0) reste = 0; + if(quotien < 0) quotien = 0; + xr_1d[quotien][reste] = 0.0f; + } + + return; + } + + /** + * + */ + private void reorder(float xr[][], int ch, int gr) + { + gr_info_s gr_info = (si.ch[ch].gr[gr]); + int freq, freq3; + int index; + int sfb, sfb_start, sfb_lines; + int src_line, des_line; + float[][] xr_1d = xr; + + if ((gr_info.window_switching_flag !=0) && (gr_info.block_type == 2)) { + + for(index=0; index<576; index++) + out_1d[index] = 0.0f; + + if (gr_info.mixed_block_flag !=0 ) { + // NO REORDER FOR LOW 2 SUBBANDS + for (index = 0; index < 36; index++) + { + // Modif E.B 02/22/99 + int reste = index % SSLIMIT; + int quotien = (int) ((index-reste)/SSLIMIT); + out_1d[index] = xr_1d[quotien][reste]; + } + // REORDERING FOR REST SWITCHED SHORT + /*for( sfb=3,sfb_start=sfBandIndex[sfreq].s[3], + sfb_lines=sfBandIndex[sfreq].s[4] - sfb_start; + sfb < 13; sfb++,sfb_start = sfBandIndex[sfreq].s[sfb], + sfb_lines = sfBandIndex[sfreq].s[sfb+1] - sfb_start ) + {*/ + for( sfb=3; sfb < 13; sfb++) + { + //System.out.println("sfreq="+sfreq+" sfb="+sfb+" sfBandIndex="+sfBandIndex.length+" sfBandIndex[sfreq].s="+sfBandIndex[sfreq].s.length); + sfb_start = sfBandIndex[sfreq].s[sfb]; + sfb_lines = sfBandIndex[sfreq].s[sfb+1] - sfb_start; + + int sfb_start3 = (sfb_start << 2) - sfb_start; + + for(freq=0, freq3=0; freq=3; sfb-- ) { + i = sfBandIndex[sfreq].s[sfb]; + lines = sfBandIndex[sfreq].s[sfb+1] - i; + i = (i << 2) - i + (j+1) * lines - 1; + + while (lines > 0) { + if (ro[1][i/18][i%18] != 0.0f) { + // MDM: in java, array access is very slow. + // Is quicker to compute div and mod values. + //if (ro[1][ss_div[i]][ss_mod[i]] != 0.0f) { + sfbcnt = sfb; + sfb = -10; + lines = -10; + } + + lines--; + i--; + + } // while (lines > 0) + + } // for (sfb=12 ... + sfb = sfbcnt + 1; + + if (sfb > max_sfb) + max_sfb = sfb; + + while(sfb < 12) { + temp = sfBandIndex[sfreq].s[sfb]; + sb = sfBandIndex[sfreq].s[sfb+1] - temp; + i = (temp << 2) - temp + j * sb; + + for ( ; sb > 0; sb--) { + is_pos[i] = scalefac[1].s[j][sfb]; + if (is_pos[i] != 7) + if (lsf) + i_stereo_k_values(is_pos[i], io_type, i); + else + is_ratio[i] = TAN12[is_pos[i]]; + + i++; + } // for (; sb>0... + sfb++; + } // while (sfb < 12) + sfb = sfBandIndex[sfreq].s[10]; + sb = sfBandIndex[sfreq].s[11] - sfb; + sfb = (sfb << 2) - sfb + j * sb; + temp = sfBandIndex[sfreq].s[11]; + sb = sfBandIndex[sfreq].s[12] - temp; + i = (temp << 2) - temp + j * sb; + + for (; sb > 0; sb--) { + is_pos[i] = is_pos[sfb]; + + if (lsf) { + k[0][i] = k[0][sfb]; + k[1][i] = k[1][sfb]; + } else { + is_ratio[i] = is_ratio[sfb]; + } + i++; + } // for (; sb > 0 ... + } + if (max_sfb <= 3) { + i = 2; + ss = 17; + sb = -1; + while (i >= 0) { + if (ro[1][i][ss] != 0.0f) { + sb = (i<<4) + (i<<1) + ss; + i = -1; + } else { + ss--; + if (ss < 0) { + i--; + ss = 17; + } + } // if (ro ... + } // while (i>=0) + i = 0; + while (sfBandIndex[sfreq].l[i] <= sb) + i++; + sfb = i; + i = sfBandIndex[sfreq].l[i]; + for (; sfb<8; sfb++) { + sb = sfBandIndex[sfreq].l[sfb+1]-sfBandIndex[sfreq].l[sfb]; + for (; sb>0; sb--) { + is_pos[i] = scalefac[1].l[sfb]; + if (is_pos[i] != 7) + if (lsf) + i_stereo_k_values(is_pos[i], io_type, i); + else + is_ratio[i] = TAN12[is_pos[i]]; + i++; + } // for (; sb>0 ... + } // for (; sfb<8 ... + } // for (j=0 ... + } else { // if (gr_info.mixed_block_flag) + for (int j=0; j<3; j++) { + int sfbcnt; + sfbcnt = -1; + for( sfb=12; sfb >=0; sfb-- ) + { + temp = sfBandIndex[sfreq].s[sfb]; + lines = sfBandIndex[sfreq].s[sfb+1] - temp; + i = (temp << 2) - temp + (j+1) * lines - 1; + + while (lines > 0) { + if (ro[1][i/18][i%18] != 0.0f) { + // MDM: in java, array access is very slow. + // Is quicker to compute div and mod values. + //if (ro[1][ss_div[i]][ss_mod[i]] != 0.0f) { + sfbcnt = sfb; + sfb = -10; + lines = -10; + } + lines--; + i--; + } // while (lines > 0) */ + + } // for (sfb=12 ... + sfb = sfbcnt + 1; + while(sfb<12) { + temp = sfBandIndex[sfreq].s[sfb]; + sb = sfBandIndex[sfreq].s[sfb+1] - temp; + i = (temp << 2) - temp + j * sb; + for ( ; sb > 0; sb--) { + is_pos[i] = scalefac[1].s[j][sfb]; + if (is_pos[i] != 7) + if (lsf) + i_stereo_k_values(is_pos[i], io_type, i); + else + is_ratio[i] = TAN12[is_pos[i]]; + i++; + } // for (; sb>0 ... + sfb++; + } // while (sfb<12) + + temp = sfBandIndex[sfreq].s[10]; + temp2= sfBandIndex[sfreq].s[11]; + sb = temp2 - temp; + sfb = (temp << 2) - temp + j * sb; + sb = sfBandIndex[sfreq].s[12] - temp2; + i = (temp2 << 2) - temp2 + j * sb; + + for (; sb>0; sb--) { + is_pos[i] = is_pos[sfb]; + + if (lsf) { + k[0][i] = k[0][sfb]; + k[1][i] = k[1][sfb]; + } else { + is_ratio[i] = is_ratio[sfb]; + } + i++; + } // for (; sb>0 ... + } // for (sfb=12 + } // for (j=0 ... + } else { // if (gr_info.window_switching_flag ... + i = 31; + ss = 17; + sb = 0; + while (i >= 0) { + if (ro[1][i][ss] != 0.0f) { + sb = (i<<4) + (i<<1) + ss; + i = -1; + } else { + ss--; + if (ss < 0) { + i--; + ss = 17; + } + } + } + i = 0; + while (sfBandIndex[sfreq].l[i] <= sb) + i++; + + sfb = i; + i = sfBandIndex[sfreq].l[i]; + for (; sfb<21; sfb++) { + sb = sfBandIndex[sfreq].l[sfb+1] - sfBandIndex[sfreq].l[sfb]; + for (; sb > 0; sb--) { + is_pos[i] = scalefac[1].l[sfb]; + if (is_pos[i] != 7) + if (lsf) + i_stereo_k_values(is_pos[i], io_type, i); + else + is_ratio[i] = TAN12[is_pos[i]]; + i++; + } + } + sfb = sfBandIndex[sfreq].l[20]; + for (sb = 576 - sfBandIndex[sfreq].l[21]; (sb > 0) && (i<576); sb--) + { + is_pos[i] = is_pos[sfb]; // error here : i >=576 + + if (lsf) { + k[0][i] = k[0][sfb]; + k[1][i] = k[1][sfb]; + } else { + is_ratio[i] = is_ratio[sfb]; + } + i++; + } // if (gr_info.mixed_block_flag) + } // if (gr_info.window_switching_flag ... + } // if (i_stereo) + + i = 0; + for(sb=0;sb 32767.0f) ? 32767 : + ((sample < -32768.0f) ? -32768 : + (short) sample)); + } + + /** + * Write the samples to the file or directly to the audio hardware. + */ + public abstract void write_buffer(int val); + public abstract void close(); + + /** + * Clears all data in the buffer (for seeking). + */ + public abstract void clear_buffer(); + + /** + * Notify the buffer that the user has stopped the stream. + */ + public abstract void set_stop_flag(); +} diff --git a/songdbj/javazoom/jl/decoder/OutputChannels.java b/songdbj/javazoom/jl/decoder/OutputChannels.java new file mode 100644 index 0000000000..58c8310de7 --- /dev/null +++ b/songdbj/javazoom/jl/decoder/OutputChannels.java @@ -0,0 +1,143 @@ +/* + * 11/19/04 1.0 moved to LGPL. + * 12/12/99 Initial implementation. 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; + + +/** + * A Type-safe representation of the the supported output channel + * constants. + * + * This class is immutable and, hence, is thread safe. + * + * @author Mat McGowan 12/12/99 + * @since 0.0.7 + */ +public class OutputChannels +{ + /** + * Flag to indicate output should include both channels. + */ + public static final int BOTH_CHANNELS = 0; + + /** + * Flag to indicate output should include the left channel only. + */ + public static final int LEFT_CHANNEL = 1; + + /** + * Flag to indicate output should include the right channel only. + */ + public static final int RIGHT_CHANNEL = 2; + + /** + * Flag to indicate output is mono. + */ + public static final int DOWNMIX_CHANNELS = 3; + + + public static final OutputChannels LEFT = new OutputChannels(LEFT_CHANNEL); + public static final OutputChannels RIGHT = new OutputChannels(RIGHT_CHANNEL); + public static final OutputChannels BOTH = new OutputChannels(BOTH_CHANNELS); + public static final OutputChannels DOWNMIX = new OutputChannels(DOWNMIX_CHANNELS); + + + private /*final*/ int outputChannels; + + /** + * Creates an OutputChannels 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/songdbj/javazoom/jl/decoder/SampleBuffer.java b/songdbj/javazoom/jl/decoder/SampleBuffer.java new file mode 100644 index 0000000000..ba4bfa060f --- /dev/null +++ b/songdbj/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/songdbj/javazoom/jl/decoder/Source.java b/songdbj/javazoom/jl/decoder/Source.java new file mode 100644 index 0000000000..9d6a5d732e --- /dev/null +++ b/songdbj/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/songdbj/javazoom/jl/decoder/SynthesisFilter.java b/songdbj/javazoom/jl/decoder/SynthesisFilter.java new file mode 100644 index 0000000000..581ab03cc2 --- /dev/null +++ b/songdbj/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; i array.length) + { + len = array.length-offs; + } + + if (len < 0) + len = 0; + + float[] subarray = new float[len]; + for (int i=0; i>> 4; + y[0] = h.val[point][1] & 0xf; + error = 0; + break; + } + + // hget1bit() is called thousands of times, and so needs to be + // ultra fast. + /* + if (bitIndex==bitsAvailable) + { + bitsAvailable = br.readBits(bits, 32); + bitIndex = 0; + } + */ + //if (bits[bitIndex++]!=0) + if (br.hget1bit()!=0) + { + while (h.val[point][1] >= MXOFF) point += h.val[point][1]; + point += h.val[point][1]; + } + else + { + while (h.val[point][0] >= MXOFF) point += h.val[point][0]; + point += h.val[point][0]; + } + level >>>= 1; + // MDM: ht[0] is always 0; + } while ((level !=0 ) || (point < 0 /*ht[0].treelen*/) ); + + // put back any bits not consumed + /* + int unread = (bitsAvailable-bitIndex); + if (unread>0) + br.rewindNbits(unread); + */ + /* Process sign encodings for quadruples tables. */ + // System.out.println(h.tablename); + if (h.tablename0 == '3' && (h.tablename1 == '2' || h.tablename1 == '3')) + { + v[0] = (y[0]>>3) & 1; + w[0] = (y[0]>>2) & 1; + x[0] = (y[0]>>1) & 1; + y[0] = y[0] & 1; + + /* v, w, x and y are reversed in the bitstream. + switch them around to make test bistream work. */ + + if (v[0]!=0) + if (br.hget1bit() != 0) v[0] = -v[0]; + if (w[0]!=0) + if (br.hget1bit() != 0) w[0] = -w[0]; + if (x[0]!=0) + if (br.hget1bit() != 0) x[0] = -x[0]; + if (y[0]!=0) + if (br.hget1bit() != 0) y[0] = -y[0]; + } + else + { + // Process sign and escape encodings for dual tables. + // x and y are reversed in the test bitstream. + // Reverse x and y here to make test bitstream work. + + if (h.linbits != 0) + if ((h.xlen-1) == x[0]) + x[0] += br.hgetbits(h.linbits); + if (x[0] != 0) + if (br.hget1bit() != 0) x[0] = -x[0]; + if (h.linbits != 0) + if ((h.ylen-1) == y[0]) + y[0] += br.hgetbits(h.linbits); + if (y[0] != 0) + if (br.hget1bit() != 0) y[0] = -y[0]; + } + return error; + } + + public static void inithuff() + { + + if (ht!=null) + return; + + ht = new huffcodetab[HTN]; + ht[0] = new huffcodetab("0 ",0,0,0,0,-1,null,null,ValTab0,0); + ht[1] = new huffcodetab("1 ",2,2,0,0,-1,null,null,ValTab1,7); + ht[2] = new huffcodetab("2 ",3,3,0,0,-1,null,null,ValTab2,17); + ht[3] = new huffcodetab("3 ",3,3,0,0,-1,null,null,ValTab3,17); + ht[4] = new huffcodetab("4 ",0,0,0,0,-1,null,null,ValTab4,0); + ht[5] = new huffcodetab("5 ",4,4,0,0,-1,null,null,ValTab5,31); + ht[6] = new huffcodetab("6 ",4,4,0,0,-1,null,null,ValTab6,31); + ht[7] = new huffcodetab("7 ",6,6,0,0,-1,null,null,ValTab7,71); + ht[8] = new huffcodetab("8 ",6,6,0,0,-1,null,null,ValTab8,71); + ht[9] = new huffcodetab("9 ",6,6,0,0,-1,null,null,ValTab9,71); + ht[10] = new huffcodetab("10 ",8,8,0,0,-1,null,null,ValTab10,127); + ht[11] = new huffcodetab("11 ",8,8,0,0,-1,null,null,ValTab11,127); + ht[12] = new huffcodetab("12 ",8,8,0,0,-1,null,null,ValTab12,127); + ht[13] = new huffcodetab("13 ",16,16,0,0,-1,null,null,ValTab13,511); + ht[14] = new huffcodetab("14 ",0,0,0,0,-1,null,null,ValTab14,0); + ht[15] = new huffcodetab("15 ",16,16,0,0,-1,null,null,ValTab15,511); + ht[16] = new huffcodetab("16 ",16,16,1,1,-1,null,null,ValTab16,511); + ht[17] = new huffcodetab("17 ",16,16,2,3,16,null,null,ValTab16,511); + ht[18] = new huffcodetab("18 ",16,16,3,7,16,null,null,ValTab16,511); + ht[19] = new huffcodetab("19 ",16,16,4,15,16,null,null,ValTab16,511); + ht[20] = new huffcodetab("20 ",16,16,6,63,16,null,null,ValTab16,511); + ht[21] = new huffcodetab("21 ",16,16,8,255,16,null,null,ValTab16,511); + ht[22] = new huffcodetab("22 ",16,16,10,1023,16,null,null,ValTab16,511); + ht[23] = new huffcodetab("23 ",16,16,13,8191,16,null,null,ValTab16,511); + ht[24] = new huffcodetab("24 ",16,16,4,15,-1,null,null,ValTab24,512); + ht[25] = new huffcodetab("25 ",16,16,5,31,24,null,null,ValTab24,512); + ht[26] = new huffcodetab("26 ",16,16,6,63,24,null,null,ValTab24,512); + ht[27] = new huffcodetab("27 ",16,16,7,127,24,null,null,ValTab24,512); + ht[28] = new huffcodetab("28 ",16,16,8,255,24,null,null,ValTab24,512); + ht[29] = new huffcodetab("29 ",16,16,9,511,24,null,null,ValTab24,512); + ht[30] = new huffcodetab("30 ",16,16,11,2047,24,null,null,ValTab24,512); + ht[31] = new huffcodetab("31 ",16,16,13,8191,24,null,null,ValTab24,512); + ht[32] = new huffcodetab("32 ",1,16,0,0,-1,null,null,ValTab32,31); + ht[33] = new huffcodetab("33 ",1,16,0,0,-1,null,null,ValTab33,31); + } +} diff --git a/songdbj/javazoom/jl/decoder/l3reorder.ser b/songdbj/javazoom/jl/decoder/l3reorder.ser new file mode 100644 index 0000000000..d7e3e0fa61 Binary files /dev/null and b/songdbj/javazoom/jl/decoder/l3reorder.ser differ diff --git a/songdbj/javazoom/jl/decoder/lin2au.ser b/songdbj/javazoom/jl/decoder/lin2au.ser new file mode 100644 index 0000000000..258231516e Binary files /dev/null and b/songdbj/javazoom/jl/decoder/lin2au.ser differ diff --git a/songdbj/javazoom/jl/decoder/readme.txt b/songdbj/javazoom/jl/decoder/readme.txt new file mode 100644 index 0000000000..7a765ec7dc --- /dev/null +++ b/songdbj/javazoom/jl/decoder/readme.txt @@ -0,0 +1,15 @@ + +TODO: + + +Implement high-level Player and Converter classes. + +Add MP1 and MP2 support and test. + +Add option to run each "stage" on own thread. +E.g. read & parse input, decode subbands, subband synthesis, audio output. + +Retrofit seek support (temporarily removed when reworking classes.) + + +Document and give example code. \ No newline at end of file diff --git a/songdbj/javazoom/jl/decoder/sfd.ser b/songdbj/javazoom/jl/decoder/sfd.ser new file mode 100644 index 0000000000..e65b782f36 Binary files /dev/null and b/songdbj/javazoom/jl/decoder/sfd.ser differ diff --git a/songdbj/javazoom/jl/player/AudioDevice.java b/songdbj/javazoom/jl/player/AudioDevice.java new file mode 100644 index 0000000000..45c28600e6 --- /dev/null +++ b/songdbj/javazoom/jl/player/AudioDevice.java @@ -0,0 +1,103 @@ +/* + * 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 AudioDevice 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: + *


+ * 
+ *		l0, r0, l1, r1, l2, r2...
+ * 
+ * where 
+ *	lx indicates the xth sample on channel 0
+ *  rx indicates the xth sample on channel 1
+ * 
+ * + * @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 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/songdbj/javazoom/jl/player/AudioDeviceBase.java b/songdbj/javazoom/jl/player/AudioDeviceBase.java new file mode 100644 index 0000000000..d9c84f08e7 --- /dev/null +++ b/songdbj/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/songdbj/javazoom/jl/player/AudioDeviceFactory.java b/songdbj/javazoom/jl/player/AudioDeviceFactory.java new file mode 100644 index 0000000000..2d502d2aad --- /dev/null +++ b/songdbj/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. + *

+ * 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 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/songdbj/javazoom/jl/player/FactoryRegistry.java b/songdbj/javazoom/jl/player/FactoryRegistry.java new file mode 100644 index 0000000000..8919995802 --- /dev/null +++ b/songdbj/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. + *

+ * 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 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) && (iJavaSoundAudioDevice implements an audio + * device by using the JavaSound API. + * + * @since 0.0.8 + * @author Mat McGowan + */ +public class JavaSoundAudioDevice extends AudioDeviceBase +{ + private SourceDataLine source = null; + + private AudioFormat fmt = null; + + private byte[] byteBuf = new byte[4096]; + + protected void setAudioFormat(AudioFormat fmt0) + { + fmt = fmt0; + } + + protected AudioFormat getAudioFormat() + { + if (fmt==null) + { + Decoder decoder = getDecoder(); + fmt = new AudioFormat(decoder.getOutputFrequency(), + 16, + decoder.getOutputChannels(), + true, + false); + } + return fmt; + } + + protected DataLine.Info getSourceLineInfo() + { + AudioFormat fmt = getAudioFormat(); + //DataLine.Info info = new DataLine.Info(SourceDataLine.class, fmt, 4000); + DataLine.Info info = new DataLine.Info(SourceDataLine.class, fmt); + return info; + } + + public void open(AudioFormat fmt) throws JavaLayerException + { + if (!isOpen()) + { + setAudioFormat(fmt); + openImpl(); + setOpen(true); + } + } + + protected void openImpl() + throws JavaLayerException + { + } + + + // createSource fix. + protected void createSource() throws JavaLayerException + { + Throwable t = null; + try + { + Line line = AudioSystem.getLine(getSourceLineInfo()); + if (line instanceof SourceDataLine) + { + source = (SourceDataLine)line; + //source.open(fmt, millisecondsToBytes(fmt, 2000)); + source.open(fmt); + /* + if (source.isControlSupported(FloatControl.Type.MASTER_GAIN)) + { + FloatControl c = (FloatControl)source.getControl(FloatControl.Type.MASTER_GAIN); + c.setValue(c.getMaximum()); + }*/ + source.start(); + + } + } catch (RuntimeException ex) + { + t = ex; + } + catch (LinkageError ex) + { + t = ex; + } + catch (LineUnavailableException ex) + { + t = ex; + } + if (source==null) throw new JavaLayerException("cannot obtain source audio line", t); + } + + public int millisecondsToBytes(AudioFormat fmt, int time) + { + return (int)(time*(fmt.getSampleRate()*fmt.getChannels()*fmt.getSampleSizeInBits())/8000.0); + } + + protected void closeImpl() + { + if (source!=null) + { + source.close(); + } + } + + protected void writeImpl(short[] samples, int offs, int len) + throws JavaLayerException + { + if (source==null) + createSource(); + + byte[] b = toByteArray(samples, offs, len); + source.write(b, 0, len*2); + } + + protected byte[] getByteArray(int length) + { + if (byteBuf.length < length) + { + byteBuf = new byte[length+1024]; + } + return byteBuf; + } + + protected byte[] toByteArray(short[] samples, int offs, int len) + { + byte[] b = getByteArray(len*2); + int idx = 0; + short s; + while (len-- > 0) + { + s = samples[offs++]; + b[idx++] = (byte)s; + b[idx++] = (byte)(s>>>8); + } + return b; + } + + protected void flushImpl() + { + if (source!=null) + { + source.drain(); + } + } + + public int getPosition() + { + int pos = 0; + if (source!=null) + { + pos = (int)(source.getMicrosecondPosition()/1000); + } + return pos; + } + + /** + * Runs a short test by playing a short silent sound. + */ + public void test() + throws JavaLayerException + { + try + { + open(new AudioFormat(22050, 16, 1, true, false)); + short[] data = new short[22050/10]; + write(data, 0, data.length); + flush(); + close(); + } + catch (RuntimeException ex) + { + throw new JavaLayerException("Device test failed: "+ex); + } + + } +} diff --git a/songdbj/javazoom/jl/player/JavaSoundAudioDeviceFactory.java b/songdbj/javazoom/jl/player/JavaSoundAudioDeviceFactory.java new file mode 100644 index 0000000000..92af492f65 --- /dev/null +++ b/songdbj/javazoom/jl/player/JavaSoundAudioDeviceFactory.java @@ -0,0 +1,85 @@ +/* + * 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; + +/** + * This class is responsible for creating instances of the + * JavaSoundAudioDevice. The audio device implementation is loaded + * and tested dynamically as not all systems will have support + * for JavaSound, or they may have the incorrect version. + */ +public class JavaSoundAudioDeviceFactory extends AudioDeviceFactory +{ + private boolean tested = false; + + static private final String DEVICE_CLASS_NAME = "javazoom.jl.player.JavaSoundAudioDevice"; + + public synchronized AudioDevice createAudioDevice() + throws JavaLayerException + { + if (!tested) + { + testAudioDevice(); + tested = true; + } + + try + { + return createAudioDeviceImpl(); + } + catch (Exception ex) + { + throw new JavaLayerException("unable to create JavaSound device: "+ex); + } + catch (LinkageError ex) + { + throw new JavaLayerException("unable to create JavaSound device: "+ex); + } + } + + protected JavaSoundAudioDevice createAudioDeviceImpl() + throws JavaLayerException + { + ClassLoader loader = getClass().getClassLoader(); + try + { + JavaSoundAudioDevice dev = (JavaSoundAudioDevice)instantiate(loader, DEVICE_CLASS_NAME); + return dev; + } + catch (Exception ex) + { + throw new JavaLayerException("Cannot create JavaSound device", ex); + } + catch (LinkageError ex) + { + throw new JavaLayerException("Cannot create JavaSound device", ex); + } + + } + + public void testAudioDevice() throws JavaLayerException + { + JavaSoundAudioDevice dev = createAudioDeviceImpl(); + dev.test(); + } +} diff --git a/songdbj/javazoom/jl/player/NullAudioDevice.java b/songdbj/javazoom/jl/player/NullAudioDevice.java new file mode 100644 index 0000000000..4145feecd4 --- /dev/null +++ b/songdbj/javazoom/jl/player/NullAudioDevice.java @@ -0,0 +1,37 @@ +/* + * 11/19/04 1.0 moved o 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; + +/** + * The NullAudioDevice 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/songdbj/javazoom/jl/player/Player.java b/songdbj/javazoom/jl/player/Player.java new file mode 100644 index 0000000000..32fb1f3051 --- /dev/null +++ b/songdbj/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/songdbj/javazoom/jl/player/PlayerApplet.java b/songdbj/javazoom/jl/player/PlayerApplet.java new file mode 100644 index 0000000000..d7c7dc2ffc --- /dev/null +++ b/songdbj/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/songdbj/javazoom/jl/player/advanced/AdvancedPlayer.java b/songdbj/javazoom/jl/player/advanced/AdvancedPlayer.java new file mode 100644 index 0000000000..45a31e46e1 --- /dev/null +++ b/songdbj/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/songdbj/javazoom/jl/player/advanced/PlaybackEvent.java b/songdbj/javazoom/jl/player/advanced/PlaybackEvent.java new file mode 100644 index 0000000000..08e3cae958 --- /dev/null +++ b/songdbj/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/songdbj/javazoom/jl/player/advanced/PlaybackListener.java b/songdbj/javazoom/jl/player/advanced/PlaybackListener.java new file mode 100644 index 0000000000..9b042988b8 --- /dev/null +++ b/songdbj/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/songdbj/javazoom/jl/player/advanced/jlap.java b/songdbj/javazoom/jl/player/advanced/jlap.java new file mode 100644 index 0000000000..beedea6716 --- /dev/null +++ b/songdbj/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 "); + System.out.println(""); + System.out.println(" e.g. : java javazoom.jl.player.advanced.jlap localfile.mp3"); + } + + public static AdvancedPlayer playMp3(File mp3, PlaybackListener listener) throws IOException, JavaLayerException + { + return playMp3(mp3, 0, Integer.MAX_VALUE, listener); + } + + public static AdvancedPlayer playMp3(File mp3, int start, int end, PlaybackListener listener) throws IOException, JavaLayerException + { + return playMp3(new BufferedInputStream(new FileInputStream(mp3)), start, end, listener); + } + + public static AdvancedPlayer playMp3(final InputStream is, final int start, final int end, PlaybackListener listener) throws JavaLayerException + { + final AdvancedPlayer player = new AdvancedPlayer(is); + player.setPlayBackListener(listener); + // run in new thread + new Thread() + { + public void run() + { + try + { + player.play(start, end); + } + catch (Exception e) + { + throw new RuntimeException(e.getMessage()); + } + } + }.start(); + return player; + } + + public class InfoListener extends PlaybackListener + { + public void playbackStarted(PlaybackEvent evt) + { + System.out.println("Play started from frame " + evt.getFrame()); + } + + public void playbackFinished(PlaybackEvent evt) + { + System.out.println("Play completed at frame " + evt.getFrame()); + System.exit(0); + } + } +} \ No newline at end of file diff --git a/songdbj/javazoom/jl/player/jlp.java b/songdbj/javazoom/jl/player/jlp.java new file mode 100644 index 0000000000..ddb3d5ecca --- /dev/null +++ b/songdbj/javazoom/jl/player/jlp.java @@ -0,0 +1,176 @@ +/* + * 11/19/04 1.0 moved to LGPL. + * + * 06/04/01 Streaming support added. javalayer@javazoom.net + * + * 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.BufferedInputStream; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; + +import javazoom.jl.decoder.JavaLayerException; + +/** + * The 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] "); + System.out.println(""); + System.out.println(" e.g. : java javazoom.jl.player.jlp localfile.mp3"); + System.out.println(" java javazoom.jl.player.jlp -url http://www.server.com/remotefile.mp3"); + System.out.println(" java javazoom.jl.player.jlp -url http://www.shoutcastserver.com:8000"); + } + + public void play() + throws JavaLayerException + { + try + { + System.out.println("playing "+fFilename+"..."); + InputStream in = null; + if (remote == true) in = getURLInputStream(); + else in = getInputStream(); + AudioDevice dev = getAudioDevice(); + Player player = new Player(in, dev); + player.play(); + } + catch (IOException ex) + { + throw new JavaLayerException("Problem playing file "+fFilename, ex); + } + catch (Exception ex) + { + throw new JavaLayerException("Problem playing file "+fFilename, ex); + } + } + + /** + * Playing file from URL (Streaming). + */ + protected InputStream getURLInputStream() + throws Exception + { + + URL url = new URL(fFilename); + InputStream fin = url.openStream(); + BufferedInputStream bin = new BufferedInputStream(fin); + return bin; + } + + /** + * Playing file from FileInputStream. + */ + protected InputStream getInputStream() + throws IOException + { + FileInputStream fin = new FileInputStream(fFilename); + BufferedInputStream bin = new BufferedInputStream(fin); + return bin; + } + + protected AudioDevice getAudioDevice() + throws JavaLayerException + { + return FactoryRegistry.systemRegistry().createAudioDevice(); + } + +} -- cgit v1.2.3