- Added Stasis.

- Added JLayer libraries.
This commit is contained in:
jendave
2011-08-06 03:08:29 +00:00
parent ea1b6daf3d
commit 2f6aeeede8
55 changed files with 13762 additions and 1 deletions

52
.gitattributes vendored
View File

@@ -256,6 +256,58 @@ src/forge/gui/ForgeAction.java svneol=native#text/plain
src/forge/gui/ListChooser.java svneol=native#text/plain
src/forge/properties/ForgeProps.java svneol=native#text/plain
src/forge/properties/NewConstants.java svneol=native#text/plain
src/javazoom/jl/converter/Converter.java -text svneol=native#text/plain
src/javazoom/jl/converter/RiffFile.java -text svneol=native#text/plain
src/javazoom/jl/converter/WaveFile.java -text svneol=native#text/plain
src/javazoom/jl/converter/WaveFileObuffer.java -text svneol=native#text/plain
src/javazoom/jl/converter/jlc.java -text svneol=native#text/plain
src/javazoom/jl/decoder/BitReserve.java -text svneol=native#text/plain
src/javazoom/jl/decoder/Bitstream.java -text svneol=native#text/plain
src/javazoom/jl/decoder/BitstreamErrors.java -text svneol=native#text/plain
src/javazoom/jl/decoder/BitstreamException.java -text svneol=native#text/plain
src/javazoom/jl/decoder/Control.java -text svneol=native#text/plain
src/javazoom/jl/decoder/Crc16.java -text svneol=native#text/plain
src/javazoom/jl/decoder/Decoder.java -text svneol=native#text/plain
src/javazoom/jl/decoder/DecoderErrors.java -text svneol=native#text/plain
src/javazoom/jl/decoder/DecoderException.java -text svneol=native#text/plain
src/javazoom/jl/decoder/Equalizer.java -text svneol=native#text/plain
src/javazoom/jl/decoder/FrameDecoder.java -text svneol=native#text/plain
src/javazoom/jl/decoder/Header.java -text svneol=native#text/plain
src/javazoom/jl/decoder/InputStreamSource.java -text svneol=native#text/plain
src/javazoom/jl/decoder/JavaLayerError.java -text svneol=native#text/plain
src/javazoom/jl/decoder/JavaLayerErrors.java -text svneol=native#text/plain
src/javazoom/jl/decoder/JavaLayerException.java -text svneol=native#text/plain
src/javazoom/jl/decoder/JavaLayerHook.java -text svneol=native#text/plain
src/javazoom/jl/decoder/JavaLayerUtils.java -text svneol=native#text/plain
src/javazoom/jl/decoder/LayerIDecoder.java svneol=native#text/plain
src/javazoom/jl/decoder/LayerIIDecoder.java svneol=native#text/plain
src/javazoom/jl/decoder/LayerIIIDecoder.java -text svneol=native#text/plain
src/javazoom/jl/decoder/Manager.java -text svneol=native#text/plain
src/javazoom/jl/decoder/Obuffer.java -text svneol=native#text/plain
src/javazoom/jl/decoder/OutputChannels.java -text svneol=native#text/plain
src/javazoom/jl/decoder/SampleBuffer.java -text svneol=native#text/plain
src/javazoom/jl/decoder/Source.java -text svneol=native#text/plain
src/javazoom/jl/decoder/SynthesisFilter.java -text svneol=native#text/plain
src/javazoom/jl/decoder/au2lin.ser -text svneol=unset#unset
src/javazoom/jl/decoder/huffcodetab.java -text svneol=native#text/plain
src/javazoom/jl/decoder/l3reorder.ser -text svneol=unset#unset
src/javazoom/jl/decoder/lin2au.ser -text svneol=unset#unset
src/javazoom/jl/decoder/readme.txt -text svneol=native#text/plain
src/javazoom/jl/decoder/sfd.ser -text svneol=unset#unset
src/javazoom/jl/player/AudioDevice.java -text svneol=native#text/plain
src/javazoom/jl/player/AudioDeviceBase.java -text svneol=native#text/plain
src/javazoom/jl/player/AudioDeviceFactory.java -text svneol=native#text/plain
src/javazoom/jl/player/FactoryRegistry.java -text svneol=native#text/plain
src/javazoom/jl/player/JavaSoundAudioDevice.java -text svneol=native#text/plain
src/javazoom/jl/player/JavaSoundAudioDeviceFactory.java -text svneol=native#text/plain
src/javazoom/jl/player/NullAudioDevice.java -text svneol=native#text/plain
src/javazoom/jl/player/Player.java -text svneol=native#text/plain
src/javazoom/jl/player/PlayerApplet.java -text svneol=native#text/plain
src/javazoom/jl/player/advanced/AdvancedPlayer.java -text svneol=native#text/plain
src/javazoom/jl/player/advanced/PlaybackEvent.java -text svneol=native#text/plain
src/javazoom/jl/player/advanced/PlaybackListener.java -text svneol=native#text/plain
src/javazoom/jl/player/advanced/jlap.java -text svneol=native#text/plain
src/javazoom/jl/player/jlp.java -text svneol=native#text/plain
src/org/jdesktop/swingx/MultiSplitLayout.java -text svneol=native#text/plain
src/org/jdesktop/swingx/MultiSplitPane.java -text svneol=native#text/plain
src/treeProperties/PropertyElement.java svneol=native#text/plain

View File

@@ -1,3 +1,9 @@
Stasis
1 U
Enchantment
Players skip their untap steps.
At the beginning of your upkeep, sacrifice Stasis unless you pay:U
Cosmic Horror
3 B B B
Creature

View File

@@ -15,7 +15,7 @@ public class Input_Untap extends Input
if(isMarbleTitanInPlay())
marbleUntap();
else
else if(!isStasisInPlay())
regularUntap();
GameActionUtil.executeUpkeepEffects();
@@ -51,6 +51,25 @@ public class Input_Untap extends Input
return all.size() > 0;
}
private boolean isStasisInPlay()
{
CardList all = new CardList();
all.addAll(AllZone.Human_Play.getCards());
all.addAll(AllZone.Computer_Play.getCards());
all = all.filter(new CardListFilter()
{
public boolean addCard(Card c) {
return c.getName().equals("Stasis");
}
});
return all.size() > 0;
}
private void regularUntap()
{
PlayerZone p = AllZone.getZone(Constant.Zone.Play, AllZone.Phase.getActivePlayer());

View File

@@ -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 <code>Converter</code> 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 <code>ProgressListener</code> and
* <code>Decoder.Params</code> 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 (; frame<frameCount; frame++)
{
try
{
Header header = stream.readFrame();
if (header==null)
break;
progressListener.readFrame(frame, header);
if (output==null)
{
// REVIEW: Incorrect functionality.
// the decoder should provide decoded
// frequency and channels output as it may differ from
// the source (e.g. when downmixing stereo to mono.)
int channels = (header.mode()==Header.SINGLE_CHANNEL) ? 1 : 2;
int freq = header.frequency();
output = new WaveFileObuffer(channels, freq, destName);
decoder.setOutputBuffer(output);
}
Obuffer decoderOutput = decoder.decodeFrame(header, stream);
// REVIEW: the way the output buffer is set
// on the decoder is a bit dodgy. Even though
// this exception should never happen, we test to be sure.
if (decoderOutput!=output)
throw new InternalError("Output buffers are different.");
progressListener.decodedFrame(frame, header, output);
stream.closeFrame();
}
catch (Exception ex)
{
boolean stop = !progressListener.converterException(ex);
if (stop)
{
throw new JavaLayerException(ex.getLocalizedMessage(), ex);
}
}
}
}
finally
{
if (output!=null)
output.close();
}
int time = (int)(System.currentTimeMillis()-startTime);
progressListener.converterUpdate(ProgressListener.UPDATE_CONVERT_COMPLETE,
time, frame);
}
catch (IOException ex)
{
throw new JavaLayerException(ex.getLocalizedMessage(), ex);
}
}
protected int countFrames(InputStream in)
{
return -1;
}
protected InputStream openInput(String fileName)
throws IOException
{
// ensure name is abstract path name
File file = new File(fileName);
InputStream fileIn = new FileInputStream(file);
BufferedInputStream bufIn = new BufferedInputStream(fileIn);
return bufIn;
}
/**
* This interface is used by the Converter to provide
* notification of tasks being carried out by the converter,
* and to provide new information as it becomes available.
*/
static public interface ProgressListener
{
public static final int UPDATE_FRAME_COUNT = 1;
/**
* Conversion is complete. Param1 contains the time
* to convert in milliseconds. Param2 contains the number
* of MPEG audio frames converted.
*/
public static final int UPDATE_CONVERT_COMPLETE = 2;
/**
* Notifies the listener that new information is available.
*
* @param updateID Code indicating the information that has been
* updated.
*
* @param param1 Parameter whose value depends upon the update code.
* @param param2 Parameter whose value depends upon the update code.
*
* The <code>updateID</code> 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 <code>Throwable</code> instance that
* was thrown.
*
* @return <code>true</code> to continue processing, or false
* to abort conversion.
*
* If this method returns <code>false</code>, the exception
* is propagated to the caller of the convert() method. If
* <code>true</code> is returned, the exception is silently
* ignored and the converter moves onto the next frame.
*/
public boolean converterException(Throwable t);
}
/**
* Implementation of <code>ProgressListener</code> that writes
* notification text to a <code>PrintWriter</code>.
*/
// 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;
}
}
}

View File

@@ -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<NumBytes;y=y+2)
{
theData[y] = (byte) (Data[yc] & 0x00FF);
theData[y+1] =(byte) ((Data[yc++] >>> 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;
}
}

View File

@@ -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;
}*/
}

View File

@@ -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<bufferp[0];j=j+2)
{
//myBuffer[0] = (short)(((buffer[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);
}
*/
}

View File

@@ -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 <code>jlc</code> class presents the JavaLayer
* Conversion functionality as a command-line program.
*
* @since 0.0.7
*/
public class jlc
{
static public void main(String args[])
{
String[] argv;
long start = System.currentTimeMillis();
int argc = args.length + 1;
argv = new String[argc];
argv[0] = "jlc";
for(int i=0;i<args.length;i++)
argv[i+1] = args[i];
jlcArgs ma = new jlcArgs();
if (!ma.processArgs(argv))
System.exit(1);
Converter conv = new Converter();
int detail = (ma.verbose_mode ?
ma.verbose_level :
Converter.PrintWriterProgressListener.NO_DETAIL);
Converter.ProgressListener listener =
new Converter.PrintWriterProgressListener(
new PrintWriter(System.out, true), detail);
try
{
conv.convert(ma.filename, ma.output_filename, listener);
}
catch (JavaLayerException ex)
{
System.err.println("Convertion failure: "+ex);
}
System.exit(0);
}
/**
* Class to contain arguments for maplay.
*/
static class jlcArgs
{
// channel constants moved into OutputChannels class.
//public static final int both = 0;
//public static final int left = 1;
//public static final int right = 2;
//public static final int downmix = 3;
public int which_c;
public int output_mode;
public boolean use_own_scalefactor;
public float scalefactor;
public String output_filename;
public String filename;
//public boolean stdout_mode;
public boolean verbose_mode;
public int verbose_level = 3;
public jlcArgs()
{
which_c = OutputChannels.BOTH_CHANNELS;
use_own_scalefactor = false;
scalefactor = (float) 32768.0;
//stdout_mode = false;
verbose_mode = false;
}
/**
* Process user arguments.
*
* Returns true if successful.
*/
public boolean processArgs(String[] argv)
{
filename = null;
Crc16[] crc;
crc = new Crc16[1];
int i;
int argc = argv.length;
//stdout_mode = false;
verbose_mode = false;
output_mode = OutputChannels.BOTH_CHANNELS;
output_filename = "";
if (argc < 2 || argv[1].equals("-h"))
return Usage();
i = 1;
while (i < argc)
{
/* System.out.println("Option = "+argv[i]);*/
if (argv[i].charAt(0) == '-')
{
if (argv[i].startsWith("-v"))
{
verbose_mode = true;
if (argv[i].length()>2)
{
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;
}
};
};

View File

@@ -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.
* <p>
* 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.
* <p>
*/
// 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;
}
}

View File

@@ -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 <code>Bistream</code> class is responsible for parsing
* an MPEG audio bitstream.
*
* <b>REVIEW:</b> 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 <code>framebuffer</code> 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<bytesize;k=k+4)
{
int convert = 0;
byte b0 = 0;
byte b1 = 0;
byte b2 = 0;
byte b3 = 0;
b0 = byteread[k];
if (k+1<bytesize) b1 = byteread[k+1];
if (k+2<bytesize) b2 = byteread[k+2];
if (k+3<bytesize) b3 = byteread[k+3];
framebuffer[b++] = ((b0 << 24) &0xFF000000) | ((b1 << 16) & 0x00FF0000) | ((b2 << 8) & 0x0000FF00) | (b3 & 0x000000FF);
}
wordpointer = 0;
bitindex = 0;
}
/**
* Read bits from buffer into the lower bits of an unsigned int.
* The LSB contains the latest read bit of the stream.
* (1 <= number_of_bits <= 16)
*/
public int get_bits(int number_of_bits)
{
int returnvalue = 0;
int sum = bitindex + number_of_bits;
// E.B
// There is a problem here, wordpointer could be -1 ?!
if (wordpointer < 0) wordpointer = 0;
// E.B : End.
if (sum <= 32)
{
// all bits contained in *wordpointer
returnvalue = (framebuffer[wordpointer] >>> (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;
}
}

View File

@@ -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 <code>BistreamException</code>s.
*
* @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;
}

View File

@@ -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 <code>BitstreamException</code> are thrown
* when operations on a <code>Bitstream</code> fail.
* <p>
* The exception provides details of the exception condition
* in two ways:
* <ol><li>
* as an error-code describing the nature of the error
* </li><br></br><li>
* as the <code>Throwable</code> instance, if any, that was thrown
* indicating that an exceptional condition has occurred.
* </li></ol></p>
*
* @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);
}
}

View File

@@ -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);
}

View File

@@ -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;
}
}

View File

@@ -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 <code>Decoder</code> 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 <code>Decoder</code> instance with default
* parameters.
*/
public Decoder()
{
this(null);
}
/**
* Creates a new <code>Decoder</code> instance with default
* parameters.
*
* @param params The <code>Params</code> 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 <code>Params</code> class presents the customizable
* aspects of the decoder.
* <p>
* 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.
* <p>
* The <code>Equalizer</code> 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 <code>Equalizer</code> used to initialize the
* EQ settings of the decoder.
*/
public Equalizer getInitialEqualizerSettings()
{
return equalizer;
}
};
}

View File

@@ -0,0 +1,45 @@
/*
* 09/26/08 throw exception on subbband alloc error: Christopher G. Jennings (cjennings@acm.org)
* 11/19/04 1.0 moved to LGPL.
* 01/12/99 Initial version. mdm@techie.com
*-----------------------------------------------------------------------
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*----------------------------------------------------------------------
*/
package javazoom.jl.decoder;
/**
* This interface provides constants describing the error
* codes used by the Decoder to indicate errors.
*
* @author MDM
*/
public interface DecoderErrors extends JavaLayerErrors
{
static public final int UNKNOWN_ERROR = DECODER_ERROR + 0;
/**
* Layer not supported by the decoder.
*/
static public final int UNSUPPORTED_LAYER = DECODER_ERROR + 1;
/**
* Illegal allocation in subband layer. Indicates a corrupt stream.
*/
static public final int ILLEGAL_SUBBAND_ALLOCATION = DECODER_ERROR + 2;
}

View File

@@ -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 <code>DecoderException</code> 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);
}
}

View File

@@ -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 <code>Equalizer</code> class can be used to specify
* equalization settings for the MPEG audio decoder.
* <p>
* 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 <code>Equalizer</code> 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<max; i++)
{
settings[i] = limit(eq[i]);
}
}
public void setFrom(EQFunction eq)
{
reset();
int max = BANDS;
for (int i=0; i<max; i++)
{
settings[i] = limit(eq.getBand(i));
}
}
/**
* Sets the bands of this equalizer to the value the bands of
* another equalizer. Bands that are not present in both equalizers are ignored.
*/
public void setFrom(Equalizer eq)
{
if (eq!=this)
{
setFrom(eq.settings);
}
}
/**
* Sets all bands to 0.0
*/
public void reset()
{
for (int i=0; i<BANDS; i++)
{
settings[i] = 0.0f;
}
}
/**
* Retrieves the number of bands present in this equalizer.
*/
public int getBandCount()
{
return settings.length;
}
public float setBand(int band, float neweq)
{
float eq = 0.0f;
if ((band>=0) && (band<BANDS))
{
eq = settings[band];
settings[band] = limit(neweq);
}
return eq;
}
/**
* Retrieves the eq setting for a given band.
*/
public float getBand(int band)
{
float eq = 0.0f;
if ((band>=0) && (band<BANDS))
{
eq = settings[band];
}
return eq;
}
private float limit(float eq)
{
if (eq==BAND_NOT_PRESENT)
return eq;
if (eq > 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<maxCount; i++)
{
factors[i] = getBandFactor(settings[i]);
}
return factors;
}
/**
* Converts an equalizer band setting to a sample factor.
* The factor is determined by the function f = 2^n where
* n is the equalizer band setting in the range [-1.0,1.0].
*
*/
float getBandFactor(float eq)
{
if (eq==BAND_NOT_PRESENT)
return 0.0f;
float f = (float)Math.pow(2.0, eq);
return f;
}
static abstract public class EQFunction
{
/**
* Returns the setting of a band in the equalizer.
*
* @param band The index of the band to retrieve the setting
* for.
*
* @return the setting of the specified band. This is a value between
* -1 and +1.
*/
public float getBand(int band)
{
return 0.0f;
}
}
}

View File

@@ -0,0 +1,39 @@
/*
* 09/26/08 throw exception on subbband alloc error: Christopher G. Jennings (cjennings@acm.org)
* 11/19/04 1.0 moved to LGPL.
* 12/12/99 Initial version. 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;
/**
* Implementations of FrameDecoder are responsible for decoding
* an MPEG audio frame.
*
*/
//REVIEW: the interface currently is too thin. There should be
// methods to specify the output buffer, the synthesis filters and
// possibly other objects used by the decoder.
public interface FrameDecoder
{
/**
* Decodes one frame of MPEG audio.
*/
public void decodeFrame() throws DecoderException;
}

View File

@@ -0,0 +1,762 @@
/*
* 11/19/04 : 1.0 moved to LGPL.
* VBRI header support added, E.B javalayer@javazoom.net
*
* 12/04/03 : VBR (XING) header support added, E.B javalayer@javazoom.net
*
* 02/13/99 : Java Conversion by JavaZOOM , E.B javalayer@javazoom.net
*
* Declarations for MPEG header class
* A few layer III, MPEG-2 LSF, and seeking modifications made by Jeff Tsay.
* Last modified : 04/19/97
*
* @(#) header.h 1.7, last edit: 6/15/94 16:55:33
* @(#) 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;
/**
* Class for extracting information from a frame header.
*/
public final class Header
{
public static final int[][] frequencies =
{{22050, 24000, 16000, 1},
{44100, 48000, 32000, 1},
{11025, 12000, 8000, 1}}; // SZD: MPEG25
/**
* Constant for MPEG-2 LSF version
*/
public static final int MPEG2_LSF = 0;
public static final int MPEG25_LSF = 2; // SZD
/**
* Constant for MPEG-1 version
*/
public static final int MPEG1 = 1;
public static final int STEREO = 0;
public static final int JOINT_STEREO = 1;
public static final int DUAL_CHANNEL = 2;
public static final int SINGLE_CHANNEL = 3;
public static final int FOURTYFOUR_POINT_ONE = 0;
public static final int FOURTYEIGHT=1;
public static final int THIRTYTWO=2;
private int h_layer, h_protection_bit, h_bitrate_index,
h_padding_bit, h_mode_extension;
private int h_version;
private int h_mode;
private int h_sample_frequency;
private int h_number_of_subbands, h_intensity_stereo_bound;
private boolean h_copyright, h_original;
// VBR support added by E.B
private double[] h_vbr_time_per_frame = {-1, 384, 1152, 1152};
private boolean h_vbr;
private int h_vbr_frames;
private int h_vbr_scale;
private int h_vbr_bytes;
private byte[] h_vbr_toc;
private byte syncmode = Bitstream.INITIAL_SYNC;
private Crc16 crc;
public short checksum;
public int framesize;
public int nSlots;
private int _headerstring = -1; // E.B
Header()
{
}
public String toString()
{
StringBuffer buffer = new StringBuffer(200);
buffer.append("Layer ");
buffer.append(layer_string());
buffer.append(" frame ");
buffer.append(mode_string());
buffer.append(' ');
buffer.append(version_string());
if (!checksums())
buffer.append(" no");
buffer.append(" checksums");
buffer.append(' ');
buffer.append(sample_frequency_string());
buffer.append(',');
buffer.append(' ');
buffer.append(bitrate_string());
String s = buffer.toString();
return s;
}
/**
* Read a 32-bit header from the bitstream.
*/
void read_header(Bitstream stream, Crc16[] crcp) throws BitstreamException
{
int headerstring;
int channel_bitrate;
boolean sync = false;
do
{
headerstring = stream.syncHeader(syncmode);
_headerstring = headerstring; // E.B
if (syncmode == Bitstream.INITIAL_SYNC)
{
h_version = ((headerstring >>> 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<max; i++) offset[i] = 0;
}
// E.B : Investigate more
int cf = stream.current_frame();
int lf = stream.last_frame();
if ((cf > 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;}
}

View File

@@ -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;
/**
* <i>Work In Progress.</i>
*
* An instance of <code>InputStreamSource</code> implements a
* <code>Source</code> that provides data from an <code>InputStream
* </code>. 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;
}
}

View File

@@ -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
{
}

View File

@@ -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;
}

View File

@@ -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.
* <p>
*
* @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();
}
}
}

View File

@@ -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 <code>JavaLayerHooks</code> 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);
}

View File

@@ -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 <code>InputStream</code>.
* The deserialization is delegated to an <code>
* ObjectInputStream</code> instance.
*
* @param in The <code>InputStream</code> 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 <code>InputStream</code>.
*
* @param in The <code>InputStream</code> 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;
}
}

View File

@@ -0,0 +1,448 @@
/*
* 09/26/08 throw exception on subbband alloc error: Christopher G. Jennings (cjennings@acm.org)
*
* 11/19/04 1.0 moved to LGPL.
*
* 12/12/99 Initial version. Adapted from javalayer.java
* and Subband*.java. mdm@techie.com
*
* 02/28/99 Initial version : javalayer.java by E.B
*-----------------------------------------------------------------------
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*----------------------------------------------------------------------
*/
package javazoom.jl.decoder;
/**
* Implements decoding of MPEG Audio Layer I frames.
*/
class LayerIDecoder implements FrameDecoder
{
protected Bitstream stream;
protected Header header;
protected SynthesisFilter filter1, filter2;
protected Obuffer buffer;
protected int which_channels;
protected int mode;
protected int num_subbands;
protected Subband[] subbands;
protected Crc16 crc = null; // new Crc16[1] to enable CRC checking.
public LayerIDecoder()
{
crc = new Crc16();
}
public void create(Bitstream stream0, Header header0,
SynthesisFilter filtera, SynthesisFilter filterb,
Obuffer buffer0, int which_ch0)
{
stream = stream0;
header = header0;
filter1 = filtera;
filter2 = filterb;
buffer = buffer0;
which_channels = which_ch0;
}
public void decodeFrame() throws DecoderException
{
num_subbands = header.number_of_subbands();
subbands = new Subband[32];
mode = header.mode();
createSubbands();
readAllocation();
readScaleFactorSelection();
if ((crc != null) || header.checksum_ok())
{
readScaleFactors();
readSampleData();
}
}
protected void createSubbands()
{
int i;
if (mode == Header.SINGLE_CHANNEL)
for (i = 0; i < num_subbands; ++i)
subbands[i] = new SubbandLayer1(i);
else if (mode == Header.JOINT_STEREO)
{
for (i = 0; i < header.intensity_stereo_bound(); ++i)
subbands[i] = new SubbandLayer1Stereo(i);
for (; i < num_subbands; ++i)
subbands[i] = new SubbandLayer1IntensityStereo(i);
}
else
{
for (i = 0; i < num_subbands; ++i)
subbands[i] = new SubbandLayer1Stereo(i);
}
}
protected void readAllocation() throws DecoderException
{
// start to read audio data:
for (int i = 0; i < num_subbands; ++i)
subbands[i].read_allocation(stream, header, crc);
}
protected void readScaleFactorSelection()
{
// scale factor selection not present for layer I.
}
protected void readScaleFactors()
{
for (int i = 0; i < num_subbands; ++i)
subbands[i].read_scalefactor(stream, header);
}
protected void readSampleData()
{
boolean read_ready = false;
boolean write_ready = false;
int mode = header.mode();
int i;
do
{
for (i = 0; i < num_subbands; ++i)
read_ready = subbands[i].read_sampledata(stream);
do
{
for (i = 0; i < num_subbands; ++i)
write_ready = subbands[i].put_next_sample(which_channels,filter1, filter2);
filter1.calculate_pcm_samples(buffer);
if ((which_channels == OutputChannels.BOTH_CHANNELS) && (mode != Header.SINGLE_CHANNEL))
filter2.calculate_pcm_samples(buffer);
} while (!write_ready);
} while (!read_ready);
}
/**
* Abstract base class for subband classes of layer I and II
*/
static abstract class Subband
{
/*
* Changes from version 1.1 to 1.2:
* - array size increased by one, although a scalefactor with index 63
* is illegal (to prevent segmentation faults)
*/
// Scalefactors for layer I and II, Annex 3-B.1 in ISO/IEC DIS 11172:
public static final float scalefactors[] =
{
2.00000000000000f, 1.58740105196820f, 1.25992104989487f, 1.00000000000000f,
0.79370052598410f, 0.62996052494744f, 0.50000000000000f, 0.39685026299205f,
0.31498026247372f, 0.25000000000000f, 0.19842513149602f, 0.15749013123686f,
0.12500000000000f, 0.09921256574801f, 0.07874506561843f, 0.06250000000000f,
0.04960628287401f, 0.03937253280921f, 0.03125000000000f, 0.02480314143700f,
0.01968626640461f, 0.01562500000000f, 0.01240157071850f, 0.00984313320230f,
0.00781250000000f, 0.00620078535925f, 0.00492156660115f, 0.00390625000000f,
0.00310039267963f, 0.00246078330058f, 0.00195312500000f, 0.00155019633981f,
0.00123039165029f, 0.00097656250000f, 0.00077509816991f, 0.00061519582514f,
0.00048828125000f, 0.00038754908495f, 0.00030759791257f, 0.00024414062500f,
0.00019377454248f, 0.00015379895629f, 0.00012207031250f, 0.00009688727124f,
0.00007689947814f, 0.00006103515625f, 0.00004844363562f, 0.00003844973907f,
0.00003051757813f, 0.00002422181781f, 0.00001922486954f, 0.00001525878906f,
0.00001211090890f, 0.00000961243477f, 0.00000762939453f, 0.00000605545445f,
0.00000480621738f, 0.00000381469727f, 0.00000302772723f, 0.00000240310869f,
0.00000190734863f, 0.00000151386361f, 0.00000120155435f, 0.00000000000000f /* illegal scalefactor */
};
public abstract void read_allocation (Bitstream stream, Header header, Crc16 crc) throws DecoderException;
public abstract void read_scalefactor (Bitstream stream, Header header);
public abstract boolean read_sampledata (Bitstream stream);
public abstract boolean put_next_sample (int channels, SynthesisFilter filter1, SynthesisFilter filter2);
};
/**
* Class for layer I subbands in single channel mode.
* Used for single channel mode
* and in derived class for intensity stereo mode
*/
static class SubbandLayer1 extends Subband
{
// Factors and offsets for sample requantization
public static final float table_factor[] = {
0.0f, (1.0f/2.0f) * (4.0f/3.0f), (1.0f/4.0f) * (8.0f/7.0f), (1.0f/8.0f) * (16.0f/15.0f),
(1.0f/16.0f) * (32.0f/31.0f), (1.0f/32.0f) * (64.0f/63.0f), (1.0f/64.0f) * (128.0f/127.0f),
(1.0f/128.0f) * (256.0f/255.0f), (1.0f/256.0f) * (512.0f/511.0f),
(1.0f/512.0f) * (1024.0f/1023.0f), (1.0f/1024.0f) * (2048.0f/2047.0f),
(1.0f/2048.0f) * (4096.0f/4095.0f), (1.0f/4096.0f) * (8192.0f/8191.0f),
(1.0f/8192.0f) * (16384.0f/16383.0f), (1.0f/16384.0f) * (32768.0f/32767.0f)
};
public static final float table_offset[] = {
0.0f, ((1.0f/2.0f)-1.0f) * (4.0f/3.0f), ((1.0f/4.0f)-1.0f) * (8.0f/7.0f), ((1.0f/8.0f)-1.0f) * (16.0f/15.0f),
((1.0f/16.0f)-1.0f) * (32.0f/31.0f), ((1.0f/32.0f)-1.0f) * (64.0f/63.0f), ((1.0f/64.0f)-1.0f) * (128.0f/127.0f),
((1.0f/128.0f)-1.0f) * (256.0f/255.0f), ((1.0f/256.0f)-1.0f) * (512.0f/511.0f),
((1.0f/512.0f)-1.0f) * (1024.0f/1023.0f), ((1.0f/1024.0f)-1.0f) * (2048.0f/2047.0f),
((1.0f/2048.0f)-1.0f) * (4096.0f/4095.0f), ((1.0f/4096.0f)-1.0f) * (8192.0f/8191.0f),
((1.0f/8192.0f)-1.0f) * (16384.0f/16383.0f), ((1.0f/16384.0f)-1.0f) * (32768.0f/32767.0f)
};
protected int subbandnumber;
protected int samplenumber;
protected int allocation;
protected float scalefactor;
protected int samplelength;
protected float sample;
protected float factor, offset;
/**
* Construtor.
*/
public SubbandLayer1(int subbandnumber)
{
this.subbandnumber = subbandnumber;
samplenumber = 0;
}
/**
*
*/
public void read_allocation(Bitstream stream, Header header, Crc16 crc) throws DecoderException
{
if ((allocation = stream.get_bits (4)) == 15)
{
// CGJ: catch this condition and throw appropriate exception
throw new DecoderException(DecoderErrors.ILLEGAL_SUBBAND_ALLOCATION, null);
// cerr << "WARNING: stream contains an illegal allocation!\n";
// MPEG-stream is corrupted!
}
if (crc != null) crc.add_bits (allocation, 4);
if (allocation != 0)
{
samplelength = allocation + 1;
factor = table_factor[allocation];
offset = table_offset[allocation];
}
}
/**
*
*/
public void read_scalefactor(Bitstream stream, Header header)
{
if (allocation != 0) scalefactor = scalefactors[stream.get_bits(6)];
}
/**
*
*/
public boolean read_sampledata(Bitstream stream)
{
if (allocation != 0)
{
sample = (float) (stream.get_bits(samplelength));
}
if (++samplenumber == 12)
{
samplenumber = 0;
return true;
}
return false;
}
/**
*
*/
public boolean put_next_sample(int channels, SynthesisFilter filter1, SynthesisFilter filter2)
{
if ((allocation !=0) && (channels != OutputChannels.RIGHT_CHANNEL))
{
float scaled_sample = (sample * factor + offset) * scalefactor;
filter1.input_sample (scaled_sample, subbandnumber);
}
return true;
}
};
/**
* Class for layer I subbands in joint stereo mode.
*/
static class SubbandLayer1IntensityStereo extends SubbandLayer1
{
protected float channel2_scalefactor;
/**
* Constructor
*/
public SubbandLayer1IntensityStereo(int subbandnumber)
{
super(subbandnumber);
}
/**
*
*/
public void read_allocation(Bitstream stream, Header header, Crc16 crc) throws DecoderException
{
super.read_allocation (stream, header, crc);
}
/**
*
*/
public void read_scalefactor (Bitstream stream, Header header)
{
if (allocation != 0)
{
scalefactor = scalefactors[stream.get_bits(6)];
channel2_scalefactor = scalefactors[stream.get_bits(6)];
}
}
/**
*
*/
public boolean read_sampledata(Bitstream stream)
{
return super.read_sampledata (stream);
}
/**
*
*/
public boolean put_next_sample (int channels, SynthesisFilter filter1, SynthesisFilter filter2)
{
if (allocation !=0 )
{
sample = sample * factor + offset; // requantization
if (channels == OutputChannels.BOTH_CHANNELS)
{
float sample1 = sample * scalefactor,
sample2 = sample * channel2_scalefactor;
filter1.input_sample(sample1, subbandnumber);
filter2.input_sample(sample2, subbandnumber);
}
else if (channels == OutputChannels.LEFT_CHANNEL)
{
float sample1 = sample * scalefactor;
filter1.input_sample(sample1, subbandnumber);
}
else
{
float sample2 = sample * channel2_scalefactor;
filter1.input_sample(sample2, subbandnumber);
}
}
return true;
}
};
/**
* Class for layer I subbands in stereo mode.
*/
static class SubbandLayer1Stereo extends SubbandLayer1
{
protected int channel2_allocation;
protected float channel2_scalefactor;
protected int channel2_samplelength;
protected float channel2_sample;
protected float channel2_factor, channel2_offset;
/**
* Constructor
*/
public SubbandLayer1Stereo(int subbandnumber)
{
super(subbandnumber);
}
/**
*
*/
public void read_allocation (Bitstream stream, Header header, Crc16 crc) throws DecoderException
{
allocation = stream.get_bits(4);
channel2_allocation = stream.get_bits(4);
if (crc != null)
{
crc.add_bits (allocation, 4);
crc.add_bits (channel2_allocation, 4);
}
if (allocation != 0)
{
samplelength = allocation + 1;
factor = table_factor[allocation];
offset = table_offset[allocation];
}
if (channel2_allocation != 0)
{
channel2_samplelength = channel2_allocation + 1;
channel2_factor = table_factor[channel2_allocation];
channel2_offset = table_offset[channel2_allocation];
}
}
/**
*
*/
public void read_scalefactor(Bitstream stream, Header header)
{
if (allocation != 0) scalefactor = scalefactors[stream.get_bits(6)];
if (channel2_allocation != 0) channel2_scalefactor = scalefactors[stream.get_bits(6)];
}
/**
*
*/
public boolean read_sampledata (Bitstream stream)
{
boolean returnvalue = super.read_sampledata(stream);
if (channel2_allocation != 0)
{
channel2_sample = (float) (stream.get_bits(channel2_samplelength));
}
return(returnvalue);
}
/**
*
*/
public boolean put_next_sample(int channels, SynthesisFilter filter1, SynthesisFilter filter2)
{
super.put_next_sample (channels, filter1, filter2);
if ((channel2_allocation != 0) && (channels != OutputChannels.LEFT_CHANNEL))
{
float sample2 = (channel2_sample * channel2_factor + channel2_offset) *
channel2_scalefactor;
if (channels == OutputChannels.BOTH_CHANNELS)
filter2.input_sample (sample2, subbandnumber);
else
filter1.input_sample (sample2, subbandnumber);
}
return true;
}
};
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,46 @@
/*
* 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.
*
* Manages a number of controls.
*/
public class Manager //implements Control
{
public void addControl(Control c)
{
}
public void removeControl(Control c)
{
}
public void removeAll()
{
}
// control interface delegates to a managed control
}

View File

@@ -0,0 +1,88 @@
/*
* 11/19/04 1.0 moved to LGPL.
* 12/12/99 Added appendSamples() method for efficiency. MDM.
* 15/02/99 ,Java Conversion by E.B ,ebsp@iname.com, JavaLayer
*
* Declarations for output buffer, includes operating system
* implementation of the virtual Obuffer. Optional routines
* enabling seeks and stops added by Jeff Tsay.
*
* @(#) obuffer.h 1.8, last edit: 6/15/94 16:51:56
* @(#) Copyright (C) 1993, 1994 Tobias Bading (bading@cs.tu-berlin.de)
* @(#) Berlin University of Technology
*
* Idea and first implementation for u-law output with fast downsampling by
* Jim Boucher (jboucher@flash.bu.edu)
*
* LinuxObuffer class written by
* Louis P. Kruger (lpkruger@phoenix.princeton.edu)
*-----------------------------------------------------------------------
* 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;
/**
* Base Class for audio output.
*/
public abstract class Obuffer
{
public static final int OBUFFERSIZE = 2 * 1152; // max. 2 * 1152 samples per frame
public static final int MAXCHANNELS = 2; // max. number of channels
/**
* Takes a 16 Bit PCM sample.
*/
public abstract void append(int channel, short value);
/**
* Accepts 32 new PCM samples.
*/
public void appendSamples(int channel, float[] f)
{
short s;
for (int i=0; i<32;)
{
s = clip(f[i++]);
append(channel, s);
}
}
/**
* Clip Sample to 16 Bits
*/
private final short clip(float sample)
{
return ((sample > 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();
}

View File

@@ -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 <code>OutputChannels</code> 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;
}
}

View File

@@ -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 <code>SampleBuffer</code> 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()
{}
}

View File

@@ -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);
}

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@@ -0,0 +1,600 @@
/*
* 11/19/04 1.0 moved to LGPL.
* 16/11/99 Renamed class, added javadoc, and changed table
* name from String to 3 chars. mdm@techie.com
* 02/15/99 Java Conversion by E.B, javalayer@javazoom.net
*
* 04/19/97 : Adapted from the ISO MPEG Audio Subgroup Software Simulation
* Group's public c source for its MPEG audio decoder. Miscellaneous
* changes by Jeff Tsay (ctsay@pasteur.eecs.berkeley.edu).
*-----------------------------------------------------------------------
* Copyright (c) 1991 MPEG/audio software simulation group, All Rights Reserved
* MPEG/audio coding/decoding software, work in progress
* NOT for public distribution until verified and approved by the
* MPEG/audio committee. For further information, please contact
* Davis Pan, 508-493-2241, e-mail: pan@3d.enet.dec.com
*
* VERSION 4.1
* changes made since last update:
* date programmers comment
* 27.2.92 F.O.Witte (ITT Intermetall)
* 8/24/93 M. Iwadare Changed for 1 pass decoding.
* 7/14/94 J. Koller useless 'typedef' before huffcodetab removed
*-----------------------------------------------------------------------
* 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 to implements Huffman decoder.
*/
final class huffcodetab
{
private static final int MXOFF=250;
private static final int HTN=34;
private char tablename0 = ' '; /* string, containing table_description */
private char tablename1 = ' '; /* string, containing table_description */
private char tablename2 = ' '; /* string, containing table_description */
private int xlen; /* max. x-index+ */
private int ylen; /* max. y-index+ */
private int linbits; /* number of linbits */
private int linmax; /* max number to be stored in linbits */
private int ref; /* a positive value indicates a reference */
private int[] table=null; /* pointer to array[xlen][ylen] */
private int[] hlen=null; /* pointer to array[xlen][ylen] */
private int[][] val=null; /* decoder tree */
private int treelen; /* length of decoder tree */
private static int ValTab0[][] = {
{0,0} // dummy
};
private static int ValTab1[][] = {
{2,1},{0,0},{2,1},{0,16},{2,1},{0,1},{0,17},
};
private static int ValTab2[][] = {
{2,1},{0,0},{4,1},{2,1},{0,16},{0,1},{2,1},{0,17},{4,1},{2,1},
{0,32},{0,33},{2,1},{0,18},{2,1},{0,2},{0,34},
};
private static int ValTab3[][] = {
{4,1},{2,1},{0,0},{0,1},{2,1},{0,17},{2,1},{0,16},{4,1},{2,1},
{0,32},{0,33},{2,1},{0,18},{2,1},{0,2},{0,34},
};
private static int ValTab4[][] = {{0,0}}; // dummy
private static int ValTab5[][] = {
{2,1},{0,0},{4,1},{2,1},{0,16},{0,1},{2,1},{0,17},{8,1},{4,1},
{2,1},{0,32},{0,2},{2,1},{0,33},{0,18},{8,1},{4,1},{2,1},{0,34},
{0,48},{2,1},{0,3},{0,19},{2,1},{0,49},{2,1},{0,50},{2,1},{0,35},
{0,51},
};
private static int ValTab6[][] = {
{6,1},{4,1},{2,1},{0,0},{0,16},{0,17},{6,1},{2,1},{0,1},{2,1},
{0,32},{0,33},{6,1},{2,1},{0,18},{2,1},{0,2},{0,34},{4,1},{2,1},
{0,49},{0,19},{4,1},{2,1},{0,48},{0,50},{2,1},{0,35},{2,1},{0,3},
{0,51},
};
private static int ValTab7[][] = {
{2,1},{0,0},{4,1},{2,1},{0,16},{0,1},{8,1},{2,1},{0,17},{4,1},
{2,1},{0,32},{0,2},{0,33},{18,1},{6,1},{2,1},{0,18},{2,1},{0,34},
{0,48},{4,1},{2,1},{0,49},{0,19},{4,1},{2,1},{0,3},{0,50},{2,1},
{0,35},{0,4},{10,1},{4,1},{2,1},{0,64},{0,65},{2,1},{0,20},{2,1},
{0,66},{0,36},{12,1},{6,1},{4,1},{2,1},{0,51},{0,67},{0,80},{4,1},
{2,1},{0,52},{0,5},{0,81},{6,1},{2,1},{0,21},{2,1},{0,82},{0,37},
{4,1},{2,1},{0,68},{0,53},{4,1},{2,1},{0,83},{0,84},{2,1},{0,69},
{0,85},
};
private static int ValTab8[][] = {
{6,1},{2,1},{0,0},{2,1},{0,16},{0,1},{2,1},{0,17},{4,1},{2,1},
{0,33},{0,18},{14,1},{4,1},{2,1},{0,32},{0,2},{2,1},{0,34},{4,1},
{2,1},{0,48},{0,3},{2,1},{0,49},{0,19},{14,1},{8,1},{4,1},{2,1},
{0,50},{0,35},{2,1},{0,64},{0,4},{2,1},{0,65},{2,1},{0,20},{0,66},
{12,1},{6,1},{2,1},{0,36},{2,1},{0,51},{0,80},{4,1},{2,1},{0,67},
{0,52},{0,81},{6,1},{2,1},{0,21},{2,1},{0,5},{0,82},{6,1},{2,1},
{0,37},{2,1},{0,68},{0,53},{2,1},{0,83},{2,1},{0,69},{2,1},{0,84},
{0,85},
};
private static int ValTab9[][] = {
{8,1},{4,1},{2,1},{0,0},{0,16},{2,1},{0,1},{0,17},{10,1},{4,1},
{2,1},{0,32},{0,33},{2,1},{0,18},{2,1},{0,2},{0,34},{12,1},{6,1},
{4,1},{2,1},{0,48},{0,3},{0,49},{2,1},{0,19},{2,1},{0,50},{0,35},
{12,1},{4,1},{2,1},{0,65},{0,20},{4,1},{2,1},{0,64},{0,51},{2,1},
{0,66},{0,36},{10,1},{6,1},{4,1},{2,1},{0,4},{0,80},{0,67},{2,1},
{0,52},{0,81},{8,1},{4,1},{2,1},{0,21},{0,82},{2,1},{0,37},{0,68},
{6,1},{4,1},{2,1},{0,5},{0,84},{0,83},{2,1},{0,53},{2,1},{0,69},
{0,85},
};
private static int ValTab10[][] = {
{2,1},{0,0},{4,1},{2,1},{0,16},{0,1},{10,1},{2,1},{0,17},{4,1},
{2,1},{0,32},{0,2},{2,1},{0,33},{0,18},{28,1},{8,1},{4,1},{2,1},
{0,34},{0,48},{2,1},{0,49},{0,19},{8,1},{4,1},{2,1},{0,3},{0,50},
{2,1},{0,35},{0,64},{4,1},{2,1},{0,65},{0,20},{4,1},{2,1},{0,4},
{0,51},{2,1},{0,66},{0,36},{28,1},{10,1},{6,1},{4,1},{2,1},{0,80},
{0,5},{0,96},{2,1},{0,97},{0,22},{12,1},{6,1},{4,1},{2,1},{0,67},
{0,52},{0,81},{2,1},{0,21},{2,1},{0,82},{0,37},{4,1},{2,1},{0,38},
{0,54},{0,113},{20,1},{8,1},{2,1},{0,23},{4,1},{2,1},{0,68},{0,83},
{0,6},{6,1},{4,1},{2,1},{0,53},{0,69},{0,98},{2,1},{0,112},{2,1},
{0,7},{0,100},{14,1},{4,1},{2,1},{0,114},{0,39},{6,1},{2,1},{0,99},
{2,1},{0,84},{0,85},{2,1},{0,70},{0,115},{8,1},{4,1},{2,1},{0,55},
{0,101},{2,1},{0,86},{0,116},{6,1},{2,1},{0,71},{2,1},{0,102},{0,117},
{4,1},{2,1},{0,87},{0,118},{2,1},{0,103},{0,119},
};
private static int ValTab11[][] = {
{6,1},{2,1},{0,0},{2,1},{0,16},{0,1},{8,1},{2,1},{0,17},{4,1},
{2,1},{0,32},{0,2},{0,18},{24,1},{8,1},{2,1},{0,33},{2,1},{0,34},
{2,1},{0,48},{0,3},{4,1},{2,1},{0,49},{0,19},{4,1},{2,1},{0,50},
{0,35},{4,1},{2,1},{0,64},{0,4},{2,1},{0,65},{0,20},{30,1},{16,1},
{10,1},{4,1},{2,1},{0,66},{0,36},{4,1},{2,1},{0,51},{0,67},{0,80},
{4,1},{2,1},{0,52},{0,81},{0,97},{6,1},{2,1},{0,22},{2,1},{0,6},
{0,38},{2,1},{0,98},{2,1},{0,21},{2,1},{0,5},{0,82},{16,1},{10,1},
{6,1},{4,1},{2,1},{0,37},{0,68},{0,96},{2,1},{0,99},{0,54},{4,1},
{2,1},{0,112},{0,23},{0,113},{16,1},{6,1},{4,1},{2,1},{0,7},{0,100},
{0,114},{2,1},{0,39},{4,1},{2,1},{0,83},{0,53},{2,1},{0,84},{0,69},
{10,1},{4,1},{2,1},{0,70},{0,115},{2,1},{0,55},{2,1},{0,101},{0,86},
{10,1},{6,1},{4,1},{2,1},{0,85},{0,87},{0,116},{2,1},{0,71},{0,102},
{4,1},{2,1},{0,117},{0,118},{2,1},{0,103},{0,119},
};
private static int ValTab12[][] = {
{12,1},{4,1},{2,1},{0,16},{0,1},{2,1},{0,17},{2,1},{0,0},{2,1},
{0,32},{0,2},{16,1},{4,1},{2,1},{0,33},{0,18},{4,1},{2,1},{0,34},
{0,49},{2,1},{0,19},{2,1},{0,48},{2,1},{0,3},{0,64},{26,1},{8,1},
{4,1},{2,1},{0,50},{0,35},{2,1},{0,65},{0,51},{10,1},{4,1},{2,1},
{0,20},{0,66},{2,1},{0,36},{2,1},{0,4},{0,80},{4,1},{2,1},{0,67},
{0,52},{2,1},{0,81},{0,21},{28,1},{14,1},{8,1},{4,1},{2,1},{0,82},
{0,37},{2,1},{0,83},{0,53},{4,1},{2,1},{0,96},{0,22},{0,97},{4,1},
{2,1},{0,98},{0,38},{6,1},{4,1},{2,1},{0,5},{0,6},{0,68},{2,1},
{0,84},{0,69},{18,1},{10,1},{4,1},{2,1},{0,99},{0,54},{4,1},{2,1},
{0,112},{0,7},{0,113},{4,1},{2,1},{0,23},{0,100},{2,1},{0,70},{0,114},
{10,1},{6,1},{2,1},{0,39},{2,1},{0,85},{0,115},{2,1},{0,55},{0,86},
{8,1},{4,1},{2,1},{0,101},{0,116},{2,1},{0,71},{0,102},{4,1},{2,1},
{0,117},{0,87},{2,1},{0,118},{2,1},{0,103},{0,119},
};
private static int ValTab13[][] = {
{2,1},{0,0},{6,1},{2,1},{0,16},{2,1},{0,1},{0,17},{28,1},{8,1},
{4,1},{2,1},{0,32},{0,2},{2,1},{0,33},{0,18},{8,1},{4,1},{2,1},
{0,34},{0,48},{2,1},{0,3},{0,49},{6,1},{2,1},{0,19},{2,1},{0,50},
{0,35},{4,1},{2,1},{0,64},{0,4},{0,65},{70,1},{28,1},{14,1},{6,1},
{2,1},{0,20},{2,1},{0,51},{0,66},{4,1},{2,1},{0,36},{0,80},{2,1},
{0,67},{0,52},{4,1},{2,1},{0,81},{0,21},{4,1},{2,1},{0,5},{0,82},
{2,1},{0,37},{2,1},{0,68},{0,83},{14,1},{8,1},{4,1},{2,1},{0,96},
{0,6},{2,1},{0,97},{0,22},{4,1},{2,1},{0,128},{0,8},{0,129},{16,1},
{8,1},{4,1},{2,1},{0,53},{0,98},{2,1},{0,38},{0,84},{4,1},{2,1},
{0,69},{0,99},{2,1},{0,54},{0,112},{6,1},{4,1},{2,1},{0,7},{0,85},
{0,113},{2,1},{0,23},{2,1},{0,39},{0,55},{72,1},{24,1},{12,1},{4,1},
{2,1},{0,24},{0,130},{2,1},{0,40},{4,1},{2,1},{0,100},{0,70},{0,114},
{8,1},{4,1},{2,1},{0,132},{0,72},{2,1},{0,144},{0,9},{2,1},{0,145},
{0,25},{24,1},{14,1},{8,1},{4,1},{2,1},{0,115},{0,101},{2,1},{0,86},
{0,116},{4,1},{2,1},{0,71},{0,102},{0,131},{6,1},{2,1},{0,56},{2,1},
{0,117},{0,87},{2,1},{0,146},{0,41},{14,1},{8,1},{4,1},{2,1},{0,103},
{0,133},{2,1},{0,88},{0,57},{2,1},{0,147},{2,1},{0,73},{0,134},{6,1},
{2,1},{0,160},{2,1},{0,104},{0,10},{2,1},{0,161},{0,26},{68,1},{24,1},
{12,1},{4,1},{2,1},{0,162},{0,42},{4,1},{2,1},{0,149},{0,89},{2,1},
{0,163},{0,58},{8,1},{4,1},{2,1},{0,74},{0,150},{2,1},{0,176},{0,11},
{2,1},{0,177},{0,27},{20,1},{8,1},{2,1},{0,178},{4,1},{2,1},{0,118},
{0,119},{0,148},{6,1},{4,1},{2,1},{0,135},{0,120},{0,164},{4,1},{2,1},
{0,105},{0,165},{0,43},{12,1},{6,1},{4,1},{2,1},{0,90},{0,136},{0,179},
{2,1},{0,59},{2,1},{0,121},{0,166},{6,1},{4,1},{2,1},{0,106},{0,180},
{0,192},{4,1},{2,1},{0,12},{0,152},{0,193},{60,1},{22,1},{10,1},{6,1},
{2,1},{0,28},{2,1},{0,137},{0,181},{2,1},{0,91},{0,194},{4,1},{2,1},
{0,44},{0,60},{4,1},{2,1},{0,182},{0,107},{2,1},{0,196},{0,76},{16,1},
{8,1},{4,1},{2,1},{0,168},{0,138},{2,1},{0,208},{0,13},{2,1},{0,209},
{2,1},{0,75},{2,1},{0,151},{0,167},{12,1},{6,1},{2,1},{0,195},{2,1},
{0,122},{0,153},{4,1},{2,1},{0,197},{0,92},{0,183},{4,1},{2,1},{0,29},
{0,210},{2,1},{0,45},{2,1},{0,123},{0,211},{52,1},{28,1},{12,1},{4,1},
{2,1},{0,61},{0,198},{4,1},{2,1},{0,108},{0,169},{2,1},{0,154},{0,212},
{8,1},{4,1},{2,1},{0,184},{0,139},{2,1},{0,77},{0,199},{4,1},{2,1},
{0,124},{0,213},{2,1},{0,93},{0,224},{10,1},{4,1},{2,1},{0,225},{0,30},
{4,1},{2,1},{0,14},{0,46},{0,226},{8,1},{4,1},{2,1},{0,227},{0,109},
{2,1},{0,140},{0,228},{4,1},{2,1},{0,229},{0,186},{0,240},{38,1},{16,1},
{4,1},{2,1},{0,241},{0,31},{6,1},{4,1},{2,1},{0,170},{0,155},{0,185},
{2,1},{0,62},{2,1},{0,214},{0,200},{12,1},{6,1},{2,1},{0,78},{2,1},
{0,215},{0,125},{2,1},{0,171},{2,1},{0,94},{0,201},{6,1},{2,1},{0,15},
{2,1},{0,156},{0,110},{2,1},{0,242},{0,47},{32,1},{16,1},{6,1},{4,1},
{2,1},{0,216},{0,141},{0,63},{6,1},{2,1},{0,243},{2,1},{0,230},{0,202},
{2,1},{0,244},{0,79},{8,1},{4,1},{2,1},{0,187},{0,172},{2,1},{0,231},
{0,245},{4,1},{2,1},{0,217},{0,157},{2,1},{0,95},{0,232},{30,1},{12,1},
{6,1},{2,1},{0,111},{2,1},{0,246},{0,203},{4,1},{2,1},{0,188},{0,173},
{0,218},{8,1},{2,1},{0,247},{4,1},{2,1},{0,126},{0,127},{0,142},{6,1},
{4,1},{2,1},{0,158},{0,174},{0,204},{2,1},{0,248},{0,143},{18,1},{8,1},
{4,1},{2,1},{0,219},{0,189},{2,1},{0,234},{0,249},{4,1},{2,1},{0,159},
{0,235},{2,1},{0,190},{2,1},{0,205},{0,250},{14,1},{4,1},{2,1},{0,221},
{0,236},{6,1},{4,1},{2,1},{0,233},{0,175},{0,220},{2,1},{0,206},{0,251},
{8,1},{4,1},{2,1},{0,191},{0,222},{2,1},{0,207},{0,238},{4,1},{2,1},
{0,223},{0,239},{2,1},{0,255},{2,1},{0,237},{2,1},{0,253},{2,1},{0,252},
{0,254},
};
private static int ValTab14[][] = {
{0,0} // dummy
};
private static int ValTab15[][] = {
{16,1},{6,1},{2,1},{0,0},{2,1},{0,16},{0,1},{2,1},{0,17},{4,1},
{2,1},{0,32},{0,2},{2,1},{0,33},{0,18},{50,1},{16,1},{6,1},{2,1},
{0,34},{2,1},{0,48},{0,49},{6,1},{2,1},{0,19},{2,1},{0,3},{0,64},
{2,1},{0,50},{0,35},{14,1},{6,1},{4,1},{2,1},{0,4},{0,20},{0,65},
{4,1},{2,1},{0,51},{0,66},{2,1},{0,36},{0,67},{10,1},{6,1},{2,1},
{0,52},{2,1},{0,80},{0,5},{2,1},{0,81},{0,21},{4,1},{2,1},{0,82},
{0,37},{4,1},{2,1},{0,68},{0,83},{0,97},{90,1},{36,1},{18,1},{10,1},
{6,1},{2,1},{0,53},{2,1},{0,96},{0,6},{2,1},{0,22},{0,98},{4,1},
{2,1},{0,38},{0,84},{2,1},{0,69},{0,99},{10,1},{6,1},{2,1},{0,54},
{2,1},{0,112},{0,7},{2,1},{0,113},{0,85},{4,1},{2,1},{0,23},{0,100},
{2,1},{0,114},{0,39},{24,1},{16,1},{8,1},{4,1},{2,1},{0,70},{0,115},
{2,1},{0,55},{0,101},{4,1},{2,1},{0,86},{0,128},{2,1},{0,8},{0,116},
{4,1},{2,1},{0,129},{0,24},{2,1},{0,130},{0,40},{16,1},{8,1},{4,1},
{2,1},{0,71},{0,102},{2,1},{0,131},{0,56},{4,1},{2,1},{0,117},{0,87},
{2,1},{0,132},{0,72},{6,1},{4,1},{2,1},{0,144},{0,25},{0,145},{4,1},
{2,1},{0,146},{0,118},{2,1},{0,103},{0,41},{92,1},{36,1},{18,1},{10,1},
{4,1},{2,1},{0,133},{0,88},{4,1},{2,1},{0,9},{0,119},{0,147},{4,1},
{2,1},{0,57},{0,148},{2,1},{0,73},{0,134},{10,1},{6,1},{2,1},{0,104},
{2,1},{0,160},{0,10},{2,1},{0,161},{0,26},{4,1},{2,1},{0,162},{0,42},
{2,1},{0,149},{0,89},{26,1},{14,1},{6,1},{2,1},{0,163},{2,1},{0,58},
{0,135},{4,1},{2,1},{0,120},{0,164},{2,1},{0,74},{0,150},{6,1},{4,1},
{2,1},{0,105},{0,176},{0,177},{4,1},{2,1},{0,27},{0,165},{0,178},{14,1},
{8,1},{4,1},{2,1},{0,90},{0,43},{2,1},{0,136},{0,151},{2,1},{0,179},
{2,1},{0,121},{0,59},{8,1},{4,1},{2,1},{0,106},{0,180},{2,1},{0,75},
{0,193},{4,1},{2,1},{0,152},{0,137},{2,1},{0,28},{0,181},{80,1},{34,1},
{16,1},{6,1},{4,1},{2,1},{0,91},{0,44},{0,194},{6,1},{4,1},{2,1},
{0,11},{0,192},{0,166},{2,1},{0,167},{0,122},{10,1},{4,1},{2,1},{0,195},
{0,60},{4,1},{2,1},{0,12},{0,153},{0,182},{4,1},{2,1},{0,107},{0,196},
{2,1},{0,76},{0,168},{20,1},{10,1},{4,1},{2,1},{0,138},{0,197},{4,1},
{2,1},{0,208},{0,92},{0,209},{4,1},{2,1},{0,183},{0,123},{2,1},{0,29},
{2,1},{0,13},{0,45},{12,1},{4,1},{2,1},{0,210},{0,211},{4,1},{2,1},
{0,61},{0,198},{2,1},{0,108},{0,169},{6,1},{4,1},{2,1},{0,154},{0,184},
{0,212},{4,1},{2,1},{0,139},{0,77},{2,1},{0,199},{0,124},{68,1},{34,1},
{18,1},{10,1},{4,1},{2,1},{0,213},{0,93},{4,1},{2,1},{0,224},{0,14},
{0,225},{4,1},{2,1},{0,30},{0,226},{2,1},{0,170},{0,46},{8,1},{4,1},
{2,1},{0,185},{0,155},{2,1},{0,227},{0,214},{4,1},{2,1},{0,109},{0,62},
{2,1},{0,200},{0,140},{16,1},{8,1},{4,1},{2,1},{0,228},{0,78},{2,1},
{0,215},{0,125},{4,1},{2,1},{0,229},{0,186},{2,1},{0,171},{0,94},{8,1},
{4,1},{2,1},{0,201},{0,156},{2,1},{0,241},{0,31},{6,1},{4,1},{2,1},
{0,240},{0,110},{0,242},{2,1},{0,47},{0,230},{38,1},{18,1},{8,1},{4,1},
{2,1},{0,216},{0,243},{2,1},{0,63},{0,244},{6,1},{2,1},{0,79},{2,1},
{0,141},{0,217},{2,1},{0,187},{0,202},{8,1},{4,1},{2,1},{0,172},{0,231},
{2,1},{0,126},{0,245},{8,1},{4,1},{2,1},{0,157},{0,95},{2,1},{0,232},
{0,142},{2,1},{0,246},{0,203},{34,1},{18,1},{10,1},{6,1},{4,1},{2,1},
{0,15},{0,174},{0,111},{2,1},{0,188},{0,218},{4,1},{2,1},{0,173},{0,247},
{2,1},{0,127},{0,233},{8,1},{4,1},{2,1},{0,158},{0,204},{2,1},{0,248},
{0,143},{4,1},{2,1},{0,219},{0,189},{2,1},{0,234},{0,249},{16,1},{8,1},
{4,1},{2,1},{0,159},{0,220},{2,1},{0,205},{0,235},{4,1},{2,1},{0,190},
{0,250},{2,1},{0,175},{0,221},{14,1},{6,1},{4,1},{2,1},{0,236},{0,206},
{0,251},{4,1},{2,1},{0,191},{0,237},{2,1},{0,222},{0,252},{6,1},{4,1},
{2,1},{0,207},{0,253},{0,238},{4,1},{2,1},{0,223},{0,254},{2,1},{0,239},
{0,255},
};
private static int ValTab16[][] = {
{2,1},{0,0},{6,1},{2,1},{0,16},{2,1},{0,1},{0,17},{42,1},{8,1},
{4,1},{2,1},{0,32},{0,2},{2,1},{0,33},{0,18},{10,1},{6,1},{2,1},
{0,34},{2,1},{0,48},{0,3},{2,1},{0,49},{0,19},{10,1},{4,1},{2,1},
{0,50},{0,35},{4,1},{2,1},{0,64},{0,4},{0,65},{6,1},{2,1},{0,20},
{2,1},{0,51},{0,66},{4,1},{2,1},{0,36},{0,80},{2,1},{0,67},{0,52},
{138,1},{40,1},{16,1},{6,1},{4,1},{2,1},{0,5},{0,21},{0,81},{4,1},
{2,1},{0,82},{0,37},{4,1},{2,1},{0,68},{0,53},{0,83},{10,1},{6,1},
{4,1},{2,1},{0,96},{0,6},{0,97},{2,1},{0,22},{0,98},{8,1},{4,1},
{2,1},{0,38},{0,84},{2,1},{0,69},{0,99},{4,1},{2,1},{0,54},{0,112},
{0,113},{40,1},{18,1},{8,1},{2,1},{0,23},{2,1},{0,7},{2,1},{0,85},
{0,100},{4,1},{2,1},{0,114},{0,39},{4,1},{2,1},{0,70},{0,101},{0,115},
{10,1},{6,1},{2,1},{0,55},{2,1},{0,86},{0,8},{2,1},{0,128},{0,129},
{6,1},{2,1},{0,24},{2,1},{0,116},{0,71},{2,1},{0,130},{2,1},{0,40},
{0,102},{24,1},{14,1},{8,1},{4,1},{2,1},{0,131},{0,56},{2,1},{0,117},
{0,132},{4,1},{2,1},{0,72},{0,144},{0,145},{6,1},{2,1},{0,25},{2,1},
{0,9},{0,118},{2,1},{0,146},{0,41},{14,1},{8,1},{4,1},{2,1},{0,133},
{0,88},{2,1},{0,147},{0,57},{4,1},{2,1},{0,160},{0,10},{0,26},{8,1},
{2,1},{0,162},{2,1},{0,103},{2,1},{0,87},{0,73},{6,1},{2,1},{0,148},
{2,1},{0,119},{0,134},{2,1},{0,161},{2,1},{0,104},{0,149},{220,1},{126,1},
{50,1},{26,1},{12,1},{6,1},{2,1},{0,42},{2,1},{0,89},{0,58},{2,1},
{0,163},{2,1},{0,135},{0,120},{8,1},{4,1},{2,1},{0,164},{0,74},{2,1},
{0,150},{0,105},{4,1},{2,1},{0,176},{0,11},{0,177},{10,1},{4,1},{2,1},
{0,27},{0,178},{2,1},{0,43},{2,1},{0,165},{0,90},{6,1},{2,1},{0,179},
{2,1},{0,166},{0,106},{4,1},{2,1},{0,180},{0,75},{2,1},{0,12},{0,193},
{30,1},{14,1},{6,1},{4,1},{2,1},{0,181},{0,194},{0,44},{4,1},{2,1},
{0,167},{0,195},{2,1},{0,107},{0,196},{8,1},{2,1},{0,29},{4,1},{2,1},
{0,136},{0,151},{0,59},{4,1},{2,1},{0,209},{0,210},{2,1},{0,45},{0,211},
{18,1},{6,1},{4,1},{2,1},{0,30},{0,46},{0,226},{6,1},{4,1},{2,1},
{0,121},{0,152},{0,192},{2,1},{0,28},{2,1},{0,137},{0,91},{14,1},{6,1},
{2,1},{0,60},{2,1},{0,122},{0,182},{4,1},{2,1},{0,76},{0,153},{2,1},
{0,168},{0,138},{6,1},{2,1},{0,13},{2,1},{0,197},{0,92},{4,1},{2,1},
{0,61},{0,198},{2,1},{0,108},{0,154},{88,1},{86,1},{36,1},{16,1},{8,1},
{4,1},{2,1},{0,139},{0,77},{2,1},{0,199},{0,124},{4,1},{2,1},{0,213},
{0,93},{2,1},{0,224},{0,14},{8,1},{2,1},{0,227},{4,1},{2,1},{0,208},
{0,183},{0,123},{6,1},{4,1},{2,1},{0,169},{0,184},{0,212},{2,1},{0,225},
{2,1},{0,170},{0,185},{24,1},{10,1},{6,1},{4,1},{2,1},{0,155},{0,214},
{0,109},{2,1},{0,62},{0,200},{6,1},{4,1},{2,1},{0,140},{0,228},{0,78},
{4,1},{2,1},{0,215},{0,229},{2,1},{0,186},{0,171},{12,1},{4,1},{2,1},
{0,156},{0,230},{4,1},{2,1},{0,110},{0,216},{2,1},{0,141},{0,187},{8,1},
{4,1},{2,1},{0,231},{0,157},{2,1},{0,232},{0,142},{4,1},{2,1},{0,203},
{0,188},{0,158},{0,241},{2,1},{0,31},{2,1},{0,15},{0,47},{66,1},{56,1},
{2,1},{0,242},{52,1},{50,1},{20,1},{8,1},{2,1},{0,189},{2,1},{0,94},
{2,1},{0,125},{0,201},{6,1},{2,1},{0,202},{2,1},{0,172},{0,126},{4,1},
{2,1},{0,218},{0,173},{0,204},{10,1},{6,1},{2,1},{0,174},{2,1},{0,219},
{0,220},{2,1},{0,205},{0,190},{6,1},{4,1},{2,1},{0,235},{0,237},{0,238},
{6,1},{4,1},{2,1},{0,217},{0,234},{0,233},{2,1},{0,222},{4,1},{2,1},
{0,221},{0,236},{0,206},{0,63},{0,240},{4,1},{2,1},{0,243},{0,244},{2,1},
{0,79},{2,1},{0,245},{0,95},{10,1},{2,1},{0,255},{4,1},{2,1},{0,246},
{0,111},{2,1},{0,247},{0,127},{12,1},{6,1},{2,1},{0,143},{2,1},{0,248},
{0,249},{4,1},{2,1},{0,159},{0,250},{0,175},{8,1},{4,1},{2,1},{0,251},
{0,191},{2,1},{0,252},{0,207},{4,1},{2,1},{0,253},{0,223},{2,1},{0,254},
{0,239},
};
private static int ValTab24[][] = {
{60,1},{8,1},{4,1},{2,1},{0,0},{0,16},{2,1},{0,1},{0,17},{14,1},
{6,1},{4,1},{2,1},{0,32},{0,2},{0,33},{2,1},{0,18},{2,1},{0,34},
{2,1},{0,48},{0,3},{14,1},{4,1},{2,1},{0,49},{0,19},{4,1},{2,1},
{0,50},{0,35},{4,1},{2,1},{0,64},{0,4},{0,65},{8,1},{4,1},{2,1},
{0,20},{0,51},{2,1},{0,66},{0,36},{6,1},{4,1},{2,1},{0,67},{0,52},
{0,81},{6,1},{4,1},{2,1},{0,80},{0,5},{0,21},{2,1},{0,82},{0,37},
{250,1},{98,1},{34,1},{18,1},{10,1},{4,1},{2,1},{0,68},{0,83},{2,1},
{0,53},{2,1},{0,96},{0,6},{4,1},{2,1},{0,97},{0,22},{2,1},{0,98},
{0,38},{8,1},{4,1},{2,1},{0,84},{0,69},{2,1},{0,99},{0,54},{4,1},
{2,1},{0,113},{0,85},{2,1},{0,100},{0,70},{32,1},{14,1},{6,1},{2,1},
{0,114},{2,1},{0,39},{0,55},{2,1},{0,115},{4,1},{2,1},{0,112},{0,7},
{0,23},{10,1},{4,1},{2,1},{0,101},{0,86},{4,1},{2,1},{0,128},{0,8},
{0,129},{4,1},{2,1},{0,116},{0,71},{2,1},{0,24},{0,130},{16,1},{8,1},
{4,1},{2,1},{0,40},{0,102},{2,1},{0,131},{0,56},{4,1},{2,1},{0,117},
{0,87},{2,1},{0,132},{0,72},{8,1},{4,1},{2,1},{0,145},{0,25},{2,1},
{0,146},{0,118},{4,1},{2,1},{0,103},{0,41},{2,1},{0,133},{0,88},{92,1},
{34,1},{16,1},{8,1},{4,1},{2,1},{0,147},{0,57},{2,1},{0,148},{0,73},
{4,1},{2,1},{0,119},{0,134},{2,1},{0,104},{0,161},{8,1},{4,1},{2,1},
{0,162},{0,42},{2,1},{0,149},{0,89},{4,1},{2,1},{0,163},{0,58},{2,1},
{0,135},{2,1},{0,120},{0,74},{22,1},{12,1},{4,1},{2,1},{0,164},{0,150},
{4,1},{2,1},{0,105},{0,177},{2,1},{0,27},{0,165},{6,1},{2,1},{0,178},
{2,1},{0,90},{0,43},{2,1},{0,136},{0,179},{16,1},{10,1},{6,1},{2,1},
{0,144},{2,1},{0,9},{0,160},{2,1},{0,151},{0,121},{4,1},{2,1},{0,166},
{0,106},{0,180},{12,1},{6,1},{2,1},{0,26},{2,1},{0,10},{0,176},{2,1},
{0,59},{2,1},{0,11},{0,192},{4,1},{2,1},{0,75},{0,193},{2,1},{0,152},
{0,137},{67,1},{34,1},{16,1},{8,1},{4,1},{2,1},{0,28},{0,181},{2,1},
{0,91},{0,194},{4,1},{2,1},{0,44},{0,167},{2,1},{0,122},{0,195},{10,1},
{6,1},{2,1},{0,60},{2,1},{0,12},{0,208},{2,1},{0,182},{0,107},{4,1},
{2,1},{0,196},{0,76},{2,1},{0,153},{0,168},{16,1},{8,1},{4,1},{2,1},
{0,138},{0,197},{2,1},{0,92},{0,209},{4,1},{2,1},{0,183},{0,123},{2,1},
{0,29},{0,210},{9,1},{4,1},{2,1},{0,45},{0,211},{2,1},{0,61},{0,198},
{85,250},{4,1},{2,1},{0,108},{0,169},{2,1},{0,154},{0,212},{32,1},{16,1},
{8,1},{4,1},{2,1},{0,184},{0,139},{2,1},{0,77},{0,199},{4,1},{2,1},
{0,124},{0,213},{2,1},{0,93},{0,225},{8,1},{4,1},{2,1},{0,30},{0,226},
{2,1},{0,170},{0,185},{4,1},{2,1},{0,155},{0,227},{2,1},{0,214},{0,109},
{20,1},{10,1},{6,1},{2,1},{0,62},{2,1},{0,46},{0,78},{2,1},{0,200},
{0,140},{4,1},{2,1},{0,228},{0,215},{4,1},{2,1},{0,125},{0,171},{0,229},
{10,1},{4,1},{2,1},{0,186},{0,94},{2,1},{0,201},{2,1},{0,156},{0,110},
{8,1},{2,1},{0,230},{2,1},{0,13},{2,1},{0,224},{0,14},{4,1},{2,1},
{0,216},{0,141},{2,1},{0,187},{0,202},{74,1},{2,1},{0,255},{64,1},{58,1},
{32,1},{16,1},{8,1},{4,1},{2,1},{0,172},{0,231},{2,1},{0,126},{0,217},
{4,1},{2,1},{0,157},{0,232},{2,1},{0,142},{0,203},{8,1},{4,1},{2,1},
{0,188},{0,218},{2,1},{0,173},{0,233},{4,1},{2,1},{0,158},{0,204},{2,1},
{0,219},{0,189},{16,1},{8,1},{4,1},{2,1},{0,234},{0,174},{2,1},{0,220},
{0,205},{4,1},{2,1},{0,235},{0,190},{2,1},{0,221},{0,236},{8,1},{4,1},
{2,1},{0,206},{0,237},{2,1},{0,222},{0,238},{0,15},{4,1},{2,1},{0,240},
{0,31},{0,241},{4,1},{2,1},{0,242},{0,47},{2,1},{0,243},{0,63},{18,1},
{8,1},{4,1},{2,1},{0,244},{0,79},{2,1},{0,245},{0,95},{4,1},{2,1},
{0,246},{0,111},{2,1},{0,247},{2,1},{0,127},{0,143},{10,1},{4,1},{2,1},
{0,248},{0,249},{4,1},{2,1},{0,159},{0,175},{0,250},{8,1},{4,1},{2,1},
{0,251},{0,191},{2,1},{0,252},{0,207},{4,1},{2,1},{0,253},{0,223},{2,1},
{0,254},{0,239},
};
private static int ValTab32[][] = {
{2,1},{0,0},{8,1},{4,1},{2,1},{0,8},{0,4},{2,1},{0,1},{0,2},
{8,1},{4,1},{2,1},{0,12},{0,10},{2,1},{0,3},{0,6},{6,1},{2,1},
{0,9},{2,1},{0,5},{0,7},{4,1},{2,1},{0,14},{0,13},{2,1},{0,15},
{0,11},
};
private static int ValTab33[][] = {
{16,1},{8,1},{4,1},{2,1},{0,0},{0,1},{2,1},{0,2},{0,3},{4,1},
{2,1},{0,4},{0,5},{2,1},{0,6},{0,7},{8,1},{4,1},{2,1},{0,8},
{0,9},{2,1},{0,10},{0,11},{4,1},{2,1},{0,12},{0,13},{2,1},{0,14},
{0,15},
};
public static huffcodetab[] ht = null; /* Simulate extern struct */
private static int[] bitbuf = new int[32];
/**
* Big Constructor : Computes all Huffman Tables.
*/
private huffcodetab(String S,int XLEN, int YLEN, int LINBITS, int LINMAX, int REF,
int[] TABLE, int[] HLEN, int[][] VAL, int TREELEN)
{
tablename0 = S.charAt(0);
tablename1 = S.charAt(1);
tablename2 = S.charAt(2);
xlen = XLEN;
ylen = YLEN;
linbits = LINBITS;
linmax = LINMAX;
ref = REF;
table = TABLE;
hlen = HLEN;
val = VAL;
treelen = TREELEN;
}
/**
* Do the huffman-decoding.
* note! for counta,countb -the 4 bit value is returned in y,
* discard x.
*/
public static int huffman_decoder(huffcodetab h, int[] x, int[] y, int[] v, int[] w, BitReserve br)
{
// array of all huffcodtable headers
// 0..31 Huffman code table 0..31
// 32,33 count1-tables
int dmask = 1 << ((4 * 8) - 1);
int hs = 4 * 8;
int level;
int point = 0;
int error = 1;
level = dmask;
if (h.val == null) return 2;
/* table 0 needs no bits */
if ( h.treelen == 0)
{
x[0] = y[0] = 0;
return 0;
}
/* Lookup in Huffman table. */
/*int bitsAvailable = 0;
int bitIndex = 0;
int bits[] = bitbuf;*/
do
{
if (h.val[point][0]==0)
{ /*end of tree*/
x[0] = h.val[point][1] >>> 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);
}
}

Binary file not shown.

Binary file not shown.

View File

@@ -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.

Binary file not shown.

View File

@@ -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 <code>AudioDevice</code> 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:
* <pre><code>
*
* l0, r0, l1, r1, l2, r2...
*
* where
* l<i>x</i> indicates the <i>x</i>th sample on channel 0
* r<i>x</i> indicates the <i>x</i>th sample on channel 1
* </code></pre>
*
* @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 <code>true</code> if this audio device is open and playing
* audio samples, or <code>false</code> otherwise.
*/
public boolean isOpen();
/**
* Writes a number of samples to this <code>AudioDevice</code>.
*
* @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 <code>write</code> or <code>flush</code>
* 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();
}

View File

@@ -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 <code>AudioDeviceBase</code> class provides a simple thread-safe
* implementation of the <code>AudioDevice</code> interface.
* Template methods are provided for subclasses to override and
* in doing so provide the implementation for the main operations
* of the <code>AudioDevice</code> 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 <code>true</code> if the audio device is open,
* <code>false</code> 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;
}
}

View File

@@ -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 <code>AudioDeviceFactory</code> class is responsible for creating
* a specific <code>AudioDevice</code> 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.
* <p>
* 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 <code>AudioDevice</code>.
*
* @return a new instance of a specific class of <code>AudioDevice</code>.
* @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 <code>ClassLoader</code> 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;
}
}

View File

@@ -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 <code>FactoryRegistry</code> class stores the factories
* for all the audio device implementations available in the system.
* <p>
* 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 <code>AudioDeviceFactory</code> 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) && (i<factories.length); i++)
{
try
{
device = factories[i].createAudioDevice();
}
catch (JavaLayerException ex)
{
lastEx = ex;
}
}
if (device==null && lastEx!=null)
{
throw new JavaLayerException("Cannot create AudioDevice", lastEx);
}
return device;
}
protected AudioDeviceFactory[] getFactoriesPriority()
{
AudioDeviceFactory[] fa = null;
synchronized (factories)
{
int size = factories.size();
if (size!=0)
{
fa = new AudioDeviceFactory[size];
int idx = 0;
Enumeration e = factories.elements();
while (e.hasMoreElements())
{
AudioDeviceFactory factory = (AudioDeviceFactory)e.nextElement();
fa[idx++] = factory;
}
}
}
return fa;
}
protected void registerDefaultFactories()
{
addFactory(new JavaSoundAudioDeviceFactory());
}
}

View File

@@ -0,0 +1,215 @@
/*
* 11/26/04 Buffer size modified to support JRE 1.5 optimizations.
* (CPU usage < 1% under P4/2Ghz, RAM < 12MB).
* jlayer@javazoom.net
* 11/19/04 1.0 moved to LGPL.
* 06/04/01 Too fast playback fixed. mdm@techie.com
* 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 javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.Line;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javazoom.jl.decoder.Decoder;
import javazoom.jl.decoder.JavaLayerException;
/**
* The <code>JavaSoundAudioDevice</code> 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);
}
}
}

View File

@@ -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();
}
}

View File

@@ -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 <code>NullAudioDevice</code> 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;
}
}

View File

@@ -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 <code>Player</code> 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 <code>Player</code> 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 <code>
* AudioDevice</code> 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;
}
}

View File

@@ -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 <code>AudioDevice</code> 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);
}
}
}
}

View File

@@ -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 <code>play(startFrame, endFrame)</code>
* 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 <code>Player</code> 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 <code>PlaybackEvent</code>
*/
private PlaybackEvent createEvent(int id)
{
return createEvent(audio, id);
}
/**
* Constructs a <code>PlaybackEvent</code>
*/
private PlaybackEvent createEvent(AudioDevice dev, int id)
{
return new PlaybackEvent(this, id, dev.getPosition());
}
/**
* sets the <code>PlaybackListener</code>
*/
public void setPlayBackListener(PlaybackListener listener)
{
this.listener = listener;
}
/**
* gets the <code>PlaybackListener</code>
*/
public PlaybackListener getPlayBackListener()
{
return listener;
}
/**
* closes the player and notifies <code>PlaybackListener</code>
*/
public void stop()
{
listener.playbackFinished(createEvent(PlaybackEvent.STOPPED));
close();
}
}

View File

@@ -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 <code>Player</code> 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;}
}

View File

@@ -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){}
}

View File

@@ -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 <filename>");
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);
}
}
}

View File

@@ -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 <code>jlp</code> 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] <filename>");
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();
}
}