Remove unused code and compiled

This commit is contained in:
PeytonPlayz595 2023-07-17 01:41:00 -04:00
parent 75f5ec3985
commit c48e9cfe02
45 changed files with 2335 additions and 8551 deletions

4644
js/app.js

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -38,7 +38,10 @@ import java.awt.*;
import java.io.*;
import java.nio.IntBuffer;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
public final class Minecraft implements Runnable {
@ -622,8 +625,6 @@ public final class Minecraft implements Runnable {
GL11.glColor4f(1.0F, 1.0F, 1.0F, (MathHelper.sin((float)System.currentTimeMillis() / 100.0F) * 0.2F + 0.4F) * 0.5F);
if(var89.cracks > 0.0F) {
GL11.glBlendFunc(774, 768);
var108 = new TextureLocation("/terrain.png").bindTexture();
GL11.glBindTexture(3553, var108);
GL11.glColor4f(1.0F, 1.0F, 1.0F, 0.5F);
GL11.glPushMatrix();
Block var10000 = (var114 = var89.level.getTile(var102.x, var102.y, var102.z)) > 0?Block.blocks[var114]:null;

View File

@ -39,7 +39,6 @@ public final class BlockSelectScreen extends GuiScreen {
drawCenteredString(this.fontRenderer, "Select block", this.width / 2, 40, 16777215);
Tessellator tessellator = Tessellator.instance;
var2 = new TextureLocation("/terrain.png").bindTexture();
GL11.glBindTexture(3553, var2);
for(var2 = 0; var2 < SessionData.allowedBlocks.size(); ++var2) {
Block var4 = (Block)SessionData.allowedBlocks.get(var2);

View File

@ -6,6 +6,8 @@ import org.lwjgl.opengl.GL11;
import com.mojang.minecraft.GameSettings;
import com.mojang.minecraft.render.RenderEngine;
import com.mojang.minecraft.render.TextureLocation;
import net.lax1dude.eaglercraft.EaglerImage;
import net.lax1dude.eaglercraft.GLAllocation;
import net.lax1dude.eaglercraft.adapter.Tessellator;
@ -15,7 +17,7 @@ public class FontRenderer {
public FontRenderer(GameSettings gamesettings, String s) {
RenderEngine r = new RenderEngine();
charWidth = new int[256];
fontTextureName = 0;
fontTextureName = null;
EaglerImage bufferedimage = GL11.loadPNG(GL11.loadResourceBytes(s));
int i = bufferedimage.w;
int j = bufferedimage.h;
@ -49,7 +51,7 @@ public class FontRenderer {
charWidth[k] = j2 + 2;
}
fontTextureName = r.allocateAndSetupTexture(bufferedimage);
fontTextureName = s;
fontDisplayLists = GLAllocation.generateDisplayLists(288);
Tessellator tessellator = Tessellator.instance;
for (int i1 = 0; i1 < 256; i1++) {
@ -116,7 +118,8 @@ public class FontRenderer {
k = (k & 0xfcfcfc) >> 2;
k += l;
}
GL11.glBindTexture(3553 /* GL_TEXTURE_2D */, fontTextureName);
//GL11.glBindTexture(3553 /* GL_TEXTURE_2D */, fontTextureName);
new TextureLocation(fontTextureName).bindTexture();
float f = (float) (k >> 16 & 0xff) / 255F;
float f1 = (float) (k >> 8 & 0xff) / 255F;
float f2 = (float) (k & 0xff) / 255F;
@ -170,7 +173,7 @@ public class FontRenderer {
}
private int charWidth[];
public int fontTextureName;
public String fontTextureName;
private int fontDisplayLists;
private IntBuffer buffer;

View File

@ -141,7 +141,7 @@ public class RenderEngine {
}
}
private HashMap<String, Integer> textureMap;
public static HashMap<String, Integer> textureMap;
private HashMap<Integer, EaglerImage> textureNameToImageMap;
private IntBuffer singleIntBuffer;
private ByteBuffer imageDataB1;

View File

@ -40,5 +40,4 @@ public class TextureLocation {
}
private static final ArrayList<TextureLocation> locations = new ArrayList();
}

View File

@ -1,107 +0,0 @@
/*
* $ProjectName$
* $ProjectRevision$
* -----------------------------------------------------------
* $Id: BasicStream.java,v 1.1 2003/08/08 19:48:22 jarnbjo Exp $
* -----------------------------------------------------------
*
* $Author: jarnbjo $
*
* Description:
*
* Copyright 2002-2003 Tor-Einar Jarnbjo
* -----------------------------------------------------------
*
* Change History
* -----------------------------------------------------------
* $Log: BasicStream.java,v $
*
*/
package de.jarnbjo.ogg;
import java.io.*;
import java.net.*;
import java.util.*;
/**
* Implementation of the <code>PhysicalOggStream</code> interface for reading
* an Ogg stream from a URL. This class performs
* no internal caching, and will not read data from the network before
* requested to do so. It is intended to be used in non-realtime applications
* like file download managers or similar.
*/
public class BasicStream implements PhysicalOggStream {
private boolean closed=false;
private InputStream sourceStream;
private Object drainLock=new Object();
private LinkedList pageCache=new LinkedList();
private long numberOfSamples=-1;
private int position=0;
private HashMap logicalStreams=new HashMap();
private OggPage firstPage;
public BasicStream(InputStream sourceStream) throws OggFormatException, IOException {
firstPage=OggPage.create(sourceStream);
position+=firstPage.getTotalLength();
LogicalOggStreamImpl los=new LogicalOggStreamImpl(this, firstPage.getStreamSerialNumber());
logicalStreams.put(new Integer(firstPage.getStreamSerialNumber()), los);
los.checkFormat(firstPage);
}
public Collection getLogicalStreams() {
return logicalStreams.values();
}
public boolean isOpen() {
return !closed;
}
public void close() throws IOException {
closed=true;
sourceStream.close();
}
public int getContentLength() {
return -1;
}
public int getPosition() {
return position;
}
int pageNumber=2;
public OggPage getOggPage(int index) throws IOException {
if(firstPage!=null) {
OggPage tmp=firstPage;
firstPage=null;
return tmp;
}
else {
OggPage page=OggPage.create(sourceStream);
position+=page.getTotalLength();
return page;
}
}
private LogicalOggStream getLogicalStream(int serialNumber) {
return (LogicalOggStream)logicalStreams.get(new Integer(serialNumber));
}
public void setTime(long granulePosition) throws IOException {
throw new UnsupportedOperationException("Method not supported by this class");
}
/**
* @return always <code>false</code>
*/
public boolean isSeekable() {
return false;
}
}

View File

@ -1,246 +0,0 @@
/*
* $ProjectName$
* $ProjectRevision$
* -----------------------------------------------------------
* $Id: CachedUrlStream.java,v 1.1 2003/04/10 19:48:22 jarnbjo Exp $
* -----------------------------------------------------------
*
* $Author: jarnbjo $
*
* Description:
*
* Copyright 2002-2003 Tor-Einar Jarnbjo
* -----------------------------------------------------------
*
* Change History
* -----------------------------------------------------------
* $Log: CachedUrlStream.java,v $
* Revision 1.1 2003/04/10 19:48:22 jarnbjo
* no message
*
*
*/
package de.jarnbjo.ogg;
import java.io.*;
import java.net.*;
import java.util.*;
/**
* Implementation of the <code>PhysicalOggStream</code> interface for reading
* and caching an Ogg stream from a URL. This class reads the data as fast as
* possible from the URL, caches it locally either in memory or on disk, and
* supports seeking within the available data.
*/
public class CachedUrlStream implements PhysicalOggStream {
private boolean closed=false;
private URLConnection source;
private InputStream sourceStream;
private Object drainLock=new Object();
private RandomAccessFile drain;
private byte[] memoryCache;
private ArrayList pageOffsets=new ArrayList();
private ArrayList pageLengths=new ArrayList();
private long numberOfSamples=-1;
private long cacheLength;
private HashMap logicalStreams=new HashMap();
private LoaderThread loaderThread;
/**
* Creates an instance of this class, using a memory cache.
*/
public CachedUrlStream(URL source) throws OggFormatException, IOException {
this(source, null);
}
/**
* Creates an instance of this class, using the specified file as cache. The
* file is not automatically deleted when this class is disposed.
*/
public CachedUrlStream(URL source, RandomAccessFile drain) throws OggFormatException, IOException {
this.source=source.openConnection();
if(drain==null) {
int contentLength=this.source.getContentLength();
if(contentLength==-1) {
throw new IOException("The URLConncetion's content length must be set when operating with a in-memory cache.");
}
memoryCache=new byte[contentLength];
}
this.drain=drain;
this.sourceStream=this.source.getInputStream();
loaderThread=new LoaderThread(sourceStream, drain, memoryCache);
new Thread(loaderThread).start();
while(!loaderThread.isBosDone() || pageOffsets.size()<20) {
System.out.print("pageOffsets.size(): "+pageOffsets.size()+"\r");
try {
Thread.sleep(200);
}
catch (InterruptedException ex) {
}
}
System.out.println();
System.out.println("caching "+pageOffsets.size()+"/20 pages\r");
}
public Collection getLogicalStreams() {
return logicalStreams.values();
}
public boolean isOpen() {
return !closed;
}
public void close() throws IOException {
closed=true;
sourceStream.close();
}
public long getCacheLength() {
return cacheLength;
}
/*
private OggPage getNextPage() throws EndOfOggStreamException, IOException, OggFormatException {
return getNextPage(false);
}
private OggPage getNextPage(boolean skipData) throws EndOfOggStreamException, IOException, OggFormatException {
return OggPage.create(sourceStream, skipData);
}
*/
public OggPage getOggPage(int index) throws IOException {
synchronized(drainLock) {
Long offset=(Long)pageOffsets.get(index);
Long length=(Long)pageLengths.get(index);
if(offset!=null) {
if(drain!=null) {
drain.seek(offset.longValue());
return OggPage.create(drain);
}
else {
byte[] tmpArray=new byte[length.intValue()];
System.arraycopy(memoryCache, offset.intValue(), tmpArray, 0, length.intValue());
return OggPage.create(tmpArray);
}
}
else {
return null;
}
}
}
private LogicalOggStream getLogicalStream(int serialNumber) {
return (LogicalOggStream)logicalStreams.get(new Integer(serialNumber));
}
public void setTime(long granulePosition) throws IOException {
for(Iterator iter=logicalStreams.values().iterator(); iter.hasNext(); ) {
LogicalOggStream los=(LogicalOggStream)iter.next();
los.setTime(granulePosition);
}
}
public class LoaderThread implements Runnable {
private InputStream source;
private RandomAccessFile drain;
private byte[] memoryCache;
private boolean bosDone=false;
private int pageNumber;
public LoaderThread(InputStream source, RandomAccessFile drain, byte[] memoryCache) {
this.source=source;
this.drain=drain;
this.memoryCache=memoryCache;
}
public void run() {
try {
boolean eos=false;
byte[] buffer=new byte[8192];
while(!eos) {
OggPage op=OggPage.create(source);
synchronized (drainLock) {
int listSize=pageOffsets.size();
long pos=
listSize>0?
((Long)pageOffsets.get(listSize-1)).longValue()+
((Long)pageLengths.get(listSize-1)).longValue():
0;
byte[] arr1=op.getHeader();
byte[] arr2=op.getSegmentTable();
byte[] arr3=op.getData();
if(drain!=null) {
drain.seek(pos);
drain.write(arr1);
drain.write(arr2);
drain.write(arr3);
}
else {
System.arraycopy(arr1, 0, memoryCache, (int)pos, arr1.length);
System.arraycopy(arr2, 0, memoryCache, (int)pos+arr1.length, arr2.length);
System.arraycopy(arr3, 0, memoryCache, (int)pos+arr1.length+arr2.length, arr3.length);
}
pageOffsets.add(new Long(pos));
pageLengths.add(new Long(arr1.length+arr2.length+arr3.length));
}
if(!op.isBos()) {
bosDone=true;
//System.out.println("bosDone=true;");
}
if(op.isEos()) {
eos=true;
}
LogicalOggStreamImpl los=(LogicalOggStreamImpl)getLogicalStream(op.getStreamSerialNumber());
if(los==null) {
los=new LogicalOggStreamImpl(CachedUrlStream.this, op.getStreamSerialNumber());
logicalStreams.put(new Integer(op.getStreamSerialNumber()), los);
los.checkFormat(op);
}
los.addPageNumberMapping(pageNumber);
los.addGranulePosition(op.getAbsoluteGranulePosition());
pageNumber++;
cacheLength=op.getAbsoluteGranulePosition();
//System.out.println("read page: "+pageNumber);
}
}
catch(EndOfOggStreamException e) {
// ok
}
catch(IOException e) {
e.printStackTrace();
}
}
public boolean isBosDone() {
return bosDone;
}
}
public boolean isSeekable() {
return true;
}
}

View File

@ -1,35 +0,0 @@
/*
* $ProjectName$
* $ProjectRevision$
* -----------------------------------------------------------
* $Id: EndOfOggStreamException.java,v 1.1 2003/03/03 21:02:20 jarnbjo Exp $
* -----------------------------------------------------------
*
* $Author: jarnbjo $
*
* Description:
*
* Copyright 2002-2003 Tor-Einar Jarnbjo
* -----------------------------------------------------------
*
* Change History
* -----------------------------------------------------------
* $Log: EndOfOggStreamException.java,v $
* Revision 1.1 2003/03/03 21:02:20 jarnbjo
* no message
*
*/
package de.jarnbjo.ogg;
import java.io.IOException;
/**
* Exception thrown when reaching the end of an Ogg stream
*/
public class EndOfOggStreamException extends IOException {
public EndOfOggStreamException() {
}
}

View File

@ -1,148 +0,0 @@
/*
* $ProjectName$
* $ProjectRevision$
* -----------------------------------------------------------
* $Id: FileStream.java,v 1.1 2003/04/10 19:48:22 jarnbjo Exp $
* -----------------------------------------------------------
*
* $Author: jarnbjo $
*
* Description:
*
* Copyright 2002-2003 Tor-Einar Jarnbjo
* -----------------------------------------------------------
*
* Change History
* -----------------------------------------------------------
* $Log: FileStream.java,v $
* Revision 1.1 2003/04/10 19:48:22 jarnbjo
* no message
*
*
*/
package de.jarnbjo.ogg;
import java.io.*;
import java.util.*;
/**
* Implementation of the <code>PhysicalOggStream</code> interface for accessing
* normal disk files.
*/
public class FileStream implements PhysicalOggStream {
private boolean closed=false;
private RandomAccessFile source;
private long[] pageOffsets;
private long numberOfSamples=-1;
private HashMap logicalStreams=new HashMap();
/**
* Creates access to the specified file through the <code>PhysicalOggStream</code> interface.
* The specified source file must have been opened for reading.
*
* @param source the file to read from
*
* @throws OggFormatException if the stream format is incorrect
* @throws IOException if some other IO error occurs when reading the file
*/
public FileStream(RandomAccessFile source) throws OggFormatException, IOException {
this.source=source;
ArrayList po=new ArrayList();
int pageNumber=0;
try {
while(true) {
po.add(new Long(this.source.getFilePointer()));
// skip data if pageNumber>0
OggPage op=getNextPage(pageNumber>0);
if(op==null) {
break;
}
LogicalOggStreamImpl los=(LogicalOggStreamImpl)getLogicalStream(op.getStreamSerialNumber());
if(los==null) {
los=new LogicalOggStreamImpl(this, op.getStreamSerialNumber());
logicalStreams.put(new Integer(op.getStreamSerialNumber()), los);
}
if(pageNumber==0) {
los.checkFormat(op);
}
los.addPageNumberMapping(pageNumber);
los.addGranulePosition(op.getAbsoluteGranulePosition());
if(pageNumber>0) {
this.source.seek(this.source.getFilePointer()+op.getTotalLength());
}
pageNumber++;
}
}
catch(EndOfOggStreamException e) {
// ok
}
catch(IOException e) {
throw e;
}
//System.out.println("pageNumber: "+pageNumber);
this.source.seek(0L);
pageOffsets=new long[po.size()];
int i=0;
Iterator iter=po.iterator();
while(iter.hasNext()) {
pageOffsets[i++]=((Long)iter.next()).longValue();
}
}
public Collection getLogicalStreams() {
return logicalStreams.values();
}
public boolean isOpen() {
return !closed;
}
public void close() throws IOException {
closed=true;
source.close();
}
private OggPage getNextPage() throws EndOfOggStreamException, IOException, OggFormatException {
return getNextPage(false);
}
private OggPage getNextPage(boolean skipData) throws EndOfOggStreamException, IOException, OggFormatException {
return OggPage.create(source, skipData);
}
public OggPage getOggPage(int index) throws IOException {
source.seek(pageOffsets[index]);
return OggPage.create(source);
}
private LogicalOggStream getLogicalStream(int serialNumber) {
return (LogicalOggStream)logicalStreams.get(new Integer(serialNumber));
}
public void setTime(long granulePosition) throws IOException {
for(Iterator iter=logicalStreams.values().iterator(); iter.hasNext(); ) {
LogicalOggStream los=(LogicalOggStream)iter.next();
los.setTime(granulePosition);
}
}
/**
* @return always <code>true</code>
*/
public boolean isSeekable() {
return true;
}
}

View File

@ -1,145 +0,0 @@
/*
* $ProjectName$
* $ProjectRevision$
* -----------------------------------------------------------
* $Id: LogicalOggStream.java,v 1.2 2003/04/10 19:48:22 jarnbjo Exp $
* -----------------------------------------------------------
*
* $Author: jarnbjo $
*
* Description:
*
* Copyright 2002-2003 Tor-Einar Jarnbjo
* -----------------------------------------------------------
*
* Change History
* -----------------------------------------------------------
* $Log: LogicalOggStream.java,v $
* Revision 1.2 2003/04/10 19:48:22 jarnbjo
* no message
*
* Revision 1.1 2003/03/03 21:02:20 jarnbjo
* no message
*
*/
package de.jarnbjo.ogg;
import java.io.IOException;
/**
* Interface providing access to a logical Ogg stream as part of a
* physical Ogg stream.
*/
public interface LogicalOggStream {
public static final String FORMAT_UNKNOWN = "application/octet-stream";
public static final String FORMAT_VORBIS = "audio/x-vorbis";
public static final String FORMAT_FLAC = "audio/x-flac";
public static final String FORMAT_THEORA = "video/x-theora";
/**
* <i>Note:</i> To read from the stream, you must use either
* this method or the method <code>getNextOggPacket</code>.
* Mixing calls to the two methods will cause data corruption.
*
* @return the next Ogg page
*
* @see #getNextOggPacket()
*
* @throws OggFormatException if the ogg stream is corrupted
* @throws IOException if some other IO error occurs
*/
public OggPage getNextOggPage() throws OggFormatException, IOException;
/**
* <i>Note:</i> To read from the stream, you must use either
* this method or the method <code>getNextOggPage</code>.
* Mixing calls to the two methods will cause data corruption.
*
* @return the next packet as a byte array
*
* @see #getNextOggPage()
*
* @throws OggFormatException if the ogg stream is corrupted
* @throws IOException if some other IO error occurs
*/
public byte[] getNextOggPacket() throws OggFormatException, IOException;
/**
* Checks if this stream is open for reading.
*
* @return <code>true</code> if this stream is open for reading,
* <code>false</code> otherwise
*/
public boolean isOpen();
/**
* Closes this stream. After invoking this method, no further access
* to the streams data is possible.
*
* @throws IOException if an IO error occurs
*/
public void close() throws IOException;
/**
* Sets the stream's position to the beginning of the stream.
* This method does not work if the physical Ogg stream is not
* seekable.
*
* @throws OggFormatException if the ogg stream is corrupted
* @throws IOException if some other IO error occurs
*/
public void reset() throws OggFormatException, IOException;
/**
* This method does not work if the physical Ogg stream is not
* seekable.
*
* @return the granule position of the last page within
* this stream
*/
public long getMaximumGranulePosition();
/**
* This method is invoked on all logical streams when
* calling the same method on the physical stream. The
* same restrictions as mentioned there apply.
* This method does not work if the physical Ogg stream is not
* seekable.
*
* @param granulePosition
*
* @see PhysicalOggStream#setTime(long)
*
* @throws IOException if an IO error occurs
*/
public void setTime(long granulePosition) throws IOException;
/**
* @return the last parsed granule position of this stream
*/
public long getTime();
/**
* @return the content type of this stream
*
* @see #FORMAT_UNKNOWN
* @see #FORMAT_VORBIS
* @see #FORMAT_FLAC
* @see #FORMAT_THEORA
*/
public String getFormat();
}

View File

@ -1,207 +0,0 @@
/*
* $ProjectName$
* $ProjectRevision$
* -----------------------------------------------------------
* $Id: LogicalOggStreamImpl.java,v 1.3 2003/03/31 00:23:04 jarnbjo Exp $
* -----------------------------------------------------------
*
* $Author: jarnbjo $
*
* Description:
*
* Copyright 2002-2003 Tor-Einar Jarnbjo
* -----------------------------------------------------------
*
* Change History
* -----------------------------------------------------------
* $Log: LogicalOggStreamImpl.java,v $
* Revision 1.3 2003/03/31 00:23:04 jarnbjo
* no message
*
* Revision 1.2 2003/03/16 01:11:26 jarnbjo
* no message
*
* Revision 1.1 2003/03/03 21:02:20 jarnbjo
* no message
*
*/
package de.jarnbjo.ogg;
import java.io.*;
import java.util.*;
public class LogicalOggStreamImpl implements LogicalOggStream {
private PhysicalOggStream source;
private int serialNumber;
private ArrayList pageNumberMapping=new ArrayList();
private ArrayList granulePositions=new ArrayList();
private int pageIndex=0;
private OggPage currentPage;
private int currentSegmentIndex;
private boolean open=true;
private String format=FORMAT_UNKNOWN;
public LogicalOggStreamImpl(PhysicalOggStream source, int serialNumber) {
this.source=source;
this.serialNumber=serialNumber;
}
public void addPageNumberMapping(int physicalPageNumber) {
pageNumberMapping.add(new Integer(physicalPageNumber));
}
public void addGranulePosition(long granulePosition) {
granulePositions.add(new Long(granulePosition));
}
public synchronized void reset() throws OggFormatException, IOException {
currentPage=null;
currentSegmentIndex=0;
pageIndex=0;
}
public synchronized OggPage getNextOggPage() throws EndOfOggStreamException, OggFormatException, IOException {
if(source.isSeekable()) {
currentPage=source.getOggPage(((Integer)pageNumberMapping.get(pageIndex++)).intValue());
}
else {
currentPage=source.getOggPage(-1);
}
return currentPage;
}
public synchronized byte[] getNextOggPacket() throws EndOfOggStreamException, OggFormatException, IOException {
ByteArrayOutputStream res=new ByteArrayOutputStream();
int segmentLength=0;
if(currentPage==null) {
currentPage=getNextOggPage();
}
do {
if(currentSegmentIndex>=currentPage.getSegmentOffsets().length) {
currentSegmentIndex=0;
if(!currentPage.isEos()) {
if(source.isSeekable() && pageNumberMapping.size()<=pageIndex) {
while(pageNumberMapping.size()<=pageIndex+10) {
try {
Thread.sleep(1000);
}
catch (InterruptedException ex) {
}
}
}
currentPage=getNextOggPage();
if(res.size()==0 && currentPage.isContinued()) {
boolean done=false;
while(!done) {
if(currentPage.getSegmentLengths()[currentSegmentIndex++]!=255) {
done=true;
}
if(currentSegmentIndex>currentPage.getSegmentTable().length) {
currentPage=source.getOggPage(((Integer)pageNumberMapping.get(pageIndex++)).intValue());
}
}
}
}
else {
throw new EndOfOggStreamException();
}
}
segmentLength=currentPage.getSegmentLengths()[currentSegmentIndex];
res.write(currentPage.getData(), currentPage.getSegmentOffsets()[currentSegmentIndex], segmentLength);
currentSegmentIndex++;
} while(segmentLength==255);
return res.toByteArray();
}
public boolean isOpen() {
return open;
}
public void close() throws IOException {
open=false;
}
public long getMaximumGranulePosition() {
Long mgp=(Long)granulePositions.get(granulePositions.size()-1);
return mgp.longValue();
}
public synchronized long getTime() {
return currentPage!=null?currentPage.getAbsoluteGranulePosition():-1;
}
public synchronized void setTime(long granulePosition) throws IOException {
int page=0;
for(page=0; page<granulePositions.size(); page++) {
Long gp=(Long)granulePositions.get(page);
if(gp.longValue()>granulePosition) {
break;
}
}
pageIndex=page;
currentPage=source.getOggPage(((Integer)pageNumberMapping.get(pageIndex++)).intValue());
currentSegmentIndex=0;
int segmentLength=0;
do {
if(currentSegmentIndex>=currentPage.getSegmentOffsets().length) {
currentSegmentIndex=0;
if(pageIndex>=pageNumberMapping.size()) {
throw new EndOfOggStreamException();
}
currentPage=source.getOggPage(((Integer)pageNumberMapping.get(pageIndex++)).intValue());
}
segmentLength=currentPage.getSegmentLengths()[currentSegmentIndex];
currentSegmentIndex++;
} while(segmentLength==255);
}
public void checkFormat(OggPage page) {
byte[] data=page.getData();
if(data.length>=7 &&
data[1]==0x76 &&
data[2]==0x6f &&
data[3]==0x72 &&
data[4]==0x62 &&
data[5]==0x69 &&
data[6]==0x73) {
format=FORMAT_VORBIS;
}
else if(data.length>=7 &&
data[1]==0x74 &&
data[2]==0x68 &&
data[3]==0x65 &&
data[4]==0x6f &&
data[5]==0x72 &&
data[6]==0x61) {
format=FORMAT_THEORA;
}
else if (data.length==4 &&
data[0]==0x66 &&
data[1]==0x4c &&
data[2]==0x61 &&
data[3]==0x43) {
format=FORMAT_FLAC;
}
}
public String getFormat() {
return format;
}
}

View File

@ -1,40 +0,0 @@
/*
* $ProjectName$
* $ProjectRevision$
* -----------------------------------------------------------
* $Id: OggFormatException.java,v 1.1 2003/03/03 21:02:20 jarnbjo Exp $
* -----------------------------------------------------------
*
* $Author: jarnbjo $
*
* Description:
*
* Copyright 2002-2003 Tor-Einar Jarnbjo
* -----------------------------------------------------------
*
* Change History
* -----------------------------------------------------------
* $Log: OggFormatException.java,v $
* Revision 1.1 2003/03/03 21:02:20 jarnbjo
* no message
*
*/
package de.jarnbjo.ogg;
import java.io.IOException;
/**
* Exception thrown when trying to read a corrupted Ogg stream.
*/
public class OggFormatException extends IOException {
public OggFormatException() {
super();
}
public OggFormatException(String message) {
super(message);
}
}

View File

@ -1,425 +0,0 @@
/*
* $ProjectName$
* $ProjectRevision$
* -----------------------------------------------------------
* $Id: OggPage.java,v 1.3 2003/04/10 19:48:22 jarnbjo Exp $
* -----------------------------------------------------------
*
* $Author: jarnbjo $
*
* Description:
*
* Copyright 2002-2003 Tor-Einar Jarnbjo
* -----------------------------------------------------------
*
* Change History
* -----------------------------------------------------------
* $Log: OggPage.java,v $
* Revision 1.3 2003/04/10 19:48:22 jarnbjo
* no message
*
* Revision 1.2 2003/03/31 00:23:04 jarnbjo
* no message
*
* Revision 1.1 2003/03/03 21:02:20 jarnbjo
* no message
*
*/
package de.jarnbjo.ogg;
import java.io.*;
import de.jarnbjo.util.io.*;
/**
* <p>An instance of this class represents an ogg page read from an ogg file
* or network stream. It has no public constructor, but instances can be
* created by the <code>create</code> methods, supplying a JMF stream or
* a <code>RandomAccessFile</code>
* which is positioned at the beginning of an Ogg page.</p>
*
* <p>Furtheron, the class provides methods for accessing the raw page data,
* as well as data attributes like segmenting information, sequence number,
* stream serial number, chechsum and wether this page is the beginning or
* end of a logical bitstream (BOS, EOS) and if the page data starts with a
* continued packet or a fresh data packet.</p>
*/
public class OggPage {
private int version;
private boolean continued, bos, eos;
private long absoluteGranulePosition;
private int streamSerialNumber, pageSequenceNumber, pageCheckSum;
private int[] segmentOffsets;
private int[] segmentLengths;
private int totalLength;
private byte[] header, segmentTable, data;
protected OggPage() {
}
private OggPage(
int version,
boolean continued,
boolean bos,
boolean eos,
long absoluteGranulePosition,
int streamSerialNumber,
int pageSequenceNumber,
int pageCheckSum,
int[] segmentOffsets,
int[] segmentLengths,
int totalLength,
byte[] header,
byte[] segmentTable,
byte[] data) {
this.version=version;
this.continued=continued;
this.bos=bos;
this.eos=eos;
this.absoluteGranulePosition=absoluteGranulePosition;
this.streamSerialNumber=streamSerialNumber;
this.pageSequenceNumber=pageSequenceNumber;
this.pageCheckSum=pageCheckSum;
this.segmentOffsets=segmentOffsets;
this.segmentLengths=segmentLengths;
this.totalLength=totalLength;
this.header=header;
this.segmentTable=segmentTable;
this.data=data;
}
/**
* this method equals to create(RandomAccessFile source, false)
*
* @see #create(RandomAccessFile, boolean)
*/
public static OggPage create(RandomAccessFile source) throws IOException, EndOfOggStreamException, OggFormatException {
return create(source, false);
}
/**
* This method is called to read data from the current position in the
* specified RandomAccessFile and create a new OggPage instance based on the data
* read. If the parameter <code>skipData</code> is set to <code>true</code>,
* the actual page segments (page data) is skipped and not read into
* memory. This mode is useful when scanning through an ogg file to build
* a seek table.
*
* @param source the source from which the ogg page is generated
* @param skipData if set to <code>true</code>, the actual page data is not read into memory
* @return an ogg page created by reading data from the specified source, starting at the current position
* @throws FormatException if the data read from the specified source is not matching the specification for an ogg page
* @throws EndOfStreamException if it is not possible to read an entire ogg page from the specified source
* @throws IOException if some other I/O error is detected when reading from the source
*
* @see #create(RandomAccessFile)
*/
public static OggPage create(RandomAccessFile source, boolean skipData) throws IOException, EndOfOggStreamException, OggFormatException {
return create((Object)source, skipData);
}
/**
* this method equals to create(InputStream source, false)
*
* @see #create(InputStream, boolean)
*/
public static OggPage create(InputStream source) throws IOException, EndOfOggStreamException, OggFormatException {
return create(source, false);
}
/**
* This method is called to read data from the current position in the
* specified InpuStream and create a new OggPage instance based on the data
* read. If the parameter <code>skipData</code> is set to <code>true</code>,
* the actual page segments (page data) is skipped and not read into
* memory. This mode is useful when scanning through an ogg file to build
* a seek table.
*
* @param source the source from which the ogg page is generated
* @param skipData if set to <code>true</code>, the actual page data is not read into memory
* @return an ogg page created by reading data from the specified source, starting at the current position
* @throws FormatException if the data read from the specified source is not matching the specification for an ogg page
* @throws EndOfStreamException if it is not possible to read an entire ogg page from the specified source
* @throws IOException if some other I/O error is detected when reading from the source
*
* @see #create(InputStream)
*/
public static OggPage create(InputStream source, boolean skipData) throws IOException, EndOfOggStreamException, OggFormatException {
return create((Object)source, skipData);
}
/**
* this method equals to create(byte[] source, false)
*
* @see #create(byte[], boolean)
*/
public static OggPage create(byte[] source) throws IOException, EndOfOggStreamException, OggFormatException {
return create(source, false);
}
/**
* This method is called to
* create a new OggPage instance based on the specified byte array.
*
* @param source the source from which the ogg page is generated
* @param skipData if set to <code>true</code>, the actual page data is not read into memory
* @return an ogg page created by reading data from the specified source, starting at the current position
* @throws FormatException if the data read from the specified source is not matching the specification for an ogg page
* @throws EndOfStreamException if it is not possible to read an entire ogg page from the specified source
* @throws IOException if some other I/O error is detected when reading from the source
*
* @see #create(byte[])
*/
public static OggPage create(byte[] source, boolean skipData) throws IOException, EndOfOggStreamException, OggFormatException {
return create((Object)source, skipData);
}
private static OggPage create(Object source, boolean skipData) throws IOException, EndOfOggStreamException, OggFormatException {
try {
int sourceOffset=27;
byte[] header=new byte[27];
if(source instanceof RandomAccessFile) {
RandomAccessFile raf=(RandomAccessFile)source;
if(raf.getFilePointer()==raf.length()) {
return null;
}
raf.readFully(header);
}
else if(source instanceof InputStream) {
readFully((InputStream)source, header);
}
else if(source instanceof byte[]) {
System.arraycopy((byte[])source, 0, header, 0, 27);
}
BitInputStream bdSource=new ByteArrayBitInputStream(header);
int capture=bdSource.getInt(32);
if(capture!=0x5367674f) {
//throw new FormatException("Ogg page does not start with 'OggS' (0x4f676753)");
/*
** This condition is IMHO an error, but older Ogg files often contain
** pages with a different capture than OggS. I am not sure how to
** manage these pages, but the decoder seems to work properly, if
** the incorrect capture is simply ignored.
*/
String cs=Integer.toHexString(capture);
while(cs.length()<8) {
cs="0"+cs;
}
cs=cs.substring(6, 8)+cs.substring(4, 6)+cs.substring(2, 4)+cs.substring(0, 2);
char c1=(char)(Integer.valueOf(cs.substring(0, 2), 16).intValue());
char c2=(char)(Integer.valueOf(cs.substring(2, 4), 16).intValue());
char c3=(char)(Integer.valueOf(cs.substring(4, 6), 16).intValue());
char c4=(char)(Integer.valueOf(cs.substring(6, 8), 16).intValue());
System.out.println("Ogg packet header is 0x"+cs+" ("+c1+c2+c3+c4+"), should be 0x4f676753 (OggS)");
}
int version=bdSource.getInt(8);
byte tmp=(byte)bdSource.getInt(8);
boolean bf1=(tmp&1)!=0;
boolean bos=(tmp&2)!=0;
boolean eos=(tmp&4)!=0;
long absoluteGranulePosition=bdSource.getLong(64);
int streamSerialNumber=bdSource.getInt(32);
int pageSequenceNumber=bdSource.getInt(32);
int pageCheckSum=bdSource.getInt(32);
int pageSegments=bdSource.getInt(8);
//System.out.println("OggPage: "+streamSerialNumber+" / "+absoluteGranulePosition+" / "+pageSequenceNumber);
int[] segmentOffsets=new int[pageSegments];
int[] segmentLengths=new int[pageSegments];
int totalLength=0;
byte[] segmentTable=new byte[pageSegments];
byte[] tmpBuf=new byte[1];
for(int i=0; i<pageSegments; i++) {
int l=0;
if(source instanceof RandomAccessFile) {
l=((int)((RandomAccessFile)source).readByte()&0xff);
}
else if(source instanceof InputStream) {
l=(int)((InputStream)source).read();
}
else if(source instanceof byte[]) {
l=(int)((byte[])source)[sourceOffset++];
l&=255;
}
segmentTable[i]=(byte)l;
segmentLengths[i]=l;
segmentOffsets[i]=totalLength;
totalLength+=l;
}
byte[] data=null;
if(!skipData) {
//System.out.println("createPage: "+absoluteGranulePosition*1000/44100);
data=new byte[totalLength];
//source.read(data, 0, totalLength);
if(source instanceof RandomAccessFile) {
((RandomAccessFile)source).readFully(data);
}
else if(source instanceof InputStream) {
readFully((InputStream)source, data);
}
else if(source instanceof byte[]) {
System.arraycopy(source, sourceOffset, data, 0, totalLength);
}
}
return new OggPage(version, bf1, bos, eos, absoluteGranulePosition, streamSerialNumber, pageSequenceNumber, pageCheckSum, segmentOffsets, segmentLengths, totalLength, header, segmentTable, data);
}
catch(EOFException e) {
throw new EndOfOggStreamException();
}
}
private static void readFully(InputStream source, byte[] buffer) throws IOException {
int total=0;
while(total<buffer.length) {
int read=source.read(buffer, total, buffer.length-total);
if(read==-1) {
throw new EndOfOggStreamException();
}
total+=read;
}
}
/**
* Returns the absolute granule position of the last complete
* packet contained in this Ogg page, or -1 if the page contains a single
* packet, which is not completed on this page. For pages containing Vorbis
* data, this value is the sample index within the Vorbis stream. The Vorbis
* stream does not necessarily start with sample index 0.
*
* @return the absolute granule position of the last packet completed on
* this page
*/
public long getAbsoluteGranulePosition() {
return absoluteGranulePosition;
}
/**
* Returns the stream serial number of this ogg page.
*
* @return this page's serial number
*/
public int getStreamSerialNumber() {
return streamSerialNumber;
}
/**
* Return the sequnce number of this ogg page.
*
* @return this page's sequence number
*/
public int getPageSequenceNumber() {
return pageSequenceNumber;
}
/**
* Return the check sum of this ogg page.
*
* @return this page's check sum
*/
public int getPageCheckSum() {
return pageCheckSum;
}
/**
* @return the total number of bytes in the page data
*/
public int getTotalLength() {
if(data!=null) {
return 27+segmentTable.length+data.length;
}
else {
return totalLength;
}
}
/**
* @return a ByteBuffer containing the page data
*/
public byte[] getData() {
return data;
}
public byte[] getHeader() {
return header;
}
public byte[] getSegmentTable() {
return segmentTable;
}
public int[] getSegmentOffsets() {
return segmentOffsets;
}
public int[] getSegmentLengths() {
return segmentLengths;
}
/**
* @return <code>true</code> if this page begins with a continued packet
*/
public boolean isContinued() {
return continued;
}
/**
* @return <code>true</code> if this page begins with a fresh packet
*/
public boolean isFresh() {
return !continued;
}
/**
* @return <code>true</code> if this page is the beginning of a logical stream
*/
public boolean isBos() {
return bos;
}
/**
* @return <code>true</code> if this page is the end of a logical stream
*/
public boolean isEos() {
return eos;
}
}

View File

@ -1,121 +0,0 @@
/*
* $ProjectName$
* $ProjectRevision$
* -----------------------------------------------------------
* $Id: OnDemandUrlStream.java,v 1.1 2003/04/10 19:48:22 jarnbjo Exp $
* -----------------------------------------------------------
*
* $Author: jarnbjo $
*
* Description:
*
* Copyright 2002-2003 Tor-Einar Jarnbjo
* -----------------------------------------------------------
*
* Change History
* -----------------------------------------------------------
* $Log: OnDemandUrlStream.java,v $
* Revision 1.1 2003/04/10 19:48:22 jarnbjo
* no message
*
* Revision 1.1 2003/03/31 00:23:04 jarnbjo
* no message
*
*/
package de.jarnbjo.ogg;
import java.io.*;
import java.net.*;
import java.util.*;
/**
* Implementation of the <code>PhysicalOggStream</code> interface for reading
* an Ogg stream from a URL. This class performs
* no internal caching, and will not read data from the network before
* requested to do so. It is intended to be used in non-realtime applications
* like file download managers or similar.
*/
public class OnDemandUrlStream implements PhysicalOggStream {
private boolean closed=false;
private URLConnection source;
private InputStream sourceStream;
private Object drainLock=new Object();
private LinkedList pageCache=new LinkedList();
private long numberOfSamples=-1;
private int contentLength=0;
private int position=0;
private HashMap logicalStreams=new HashMap();
private OggPage firstPage;
private static final int PAGECACHE_SIZE = 20;
public OnDemandUrlStream(URL source) throws OggFormatException, IOException {
this.source=source.openConnection();
this.sourceStream=this.source.getInputStream();
contentLength=this.source.getContentLength();
firstPage=OggPage.create(sourceStream);
position+=firstPage.getTotalLength();
LogicalOggStreamImpl los=new LogicalOggStreamImpl(this, firstPage.getStreamSerialNumber());
logicalStreams.put(new Integer(firstPage.getStreamSerialNumber()), los);
los.checkFormat(firstPage);
}
public Collection getLogicalStreams() {
return logicalStreams.values();
}
public boolean isOpen() {
return !closed;
}
public void close() throws IOException {
closed=true;
sourceStream.close();
}
public int getContentLength() {
return contentLength;
}
public int getPosition() {
return position;
}
int pageNumber=2;
public OggPage getOggPage(int index) throws IOException {
if(firstPage!=null) {
OggPage tmp=firstPage;
firstPage=null;
return tmp;
}
else {
OggPage page=OggPage.create(sourceStream);
position+=page.getTotalLength();
return page;
}
}
private LogicalOggStream getLogicalStream(int serialNumber) {
return (LogicalOggStream)logicalStreams.get(new Integer(serialNumber));
}
public void setTime(long granulePosition) throws IOException {
throw new UnsupportedOperationException("Method not supported by this class");
}
/**
* @return always <code>false</code>
*/
public boolean isSeekable() {
return false;
}
}

View File

@ -1,118 +0,0 @@
/*
* $ProjectName$
* $ProjectRevision$
* -----------------------------------------------------------
* $Id: PhysicalOggStream.java,v 1.3 2003/04/10 19:48:22 jarnbjo Exp $
* -----------------------------------------------------------
*
* $Author: jarnbjo $
*
* Description:
*
* Copyright 2002-2003 Tor-Einar Jarnbjo
* -----------------------------------------------------------
*
* Change History
* -----------------------------------------------------------
* $Log: PhysicalOggStream.java,v $
* Revision 1.3 2003/04/10 19:48:22 jarnbjo
* no message
*
* Revision 1.2 2003/03/31 00:23:04 jarnbjo
* no message
*
* Revision 1.1 2003/03/03 21:02:20 jarnbjo
* no message
*
*/
package de.jarnbjo.ogg;
import java.io.IOException;
import java.util.Collection;
/**
* Interface providing access to a physical Ogg stream. Typically this is
* a file.
*/
public interface PhysicalOggStream {
/**
* Returns a collection of objects implementing <code>LogicalOggStream</code>
* for accessing the separate logical streams within this physical Ogg stream.
*
* @return a collection of objects implementing <code>LogicalOggStream</code>
* which are representing the logical streams contained within this
* physical stream
*
* @see LogicalOggStream
*/
public Collection getLogicalStreams();
/**
* Return the Ogg page with the absolute index <code>index</code>,
* independent from the logical structure of this stream or if the
* index parameter is -1, the next Ogg page is returned.
* This method should only be used by implementations of <code>LogicalOggStream</code>
* to access the raw pages.
*
* @param index the absolute index starting from 0 at the beginning of
* the file or stream or -1 to get the next page in a non-seekable
* stream
*
* @return the Ogg page with the physical absolute index <code>index</code>
*
* @throws OggFormatException if the ogg stream is corrupted
* @throws IOException if some other IO error occurs
*/
public OggPage getOggPage(int index) throws OggFormatException, IOException;
/**
* Checks if this stream is open for reading.
*
* @return <code>true</code> if this stream is open for reading,
* <code>false</code> otherwise
*/
public boolean isOpen();
/**
* Closes this stream. After invoking this method, no further access
* to the streams data is possible.
*
* @throws IOException
*/
public void close() throws IOException;
/**
* Sets this stream's (and its logical stream's) position to the granule
* position. The next packet read from any logical stream will be the
* first packet beginning on the first page with a granule position higher
* than the argument.<br><br>
*
* At the moment, this method only works correctly for Ogg files with
* a single logical Vorbis stream, and due to the different interpretations
* of the granule position, depending on mixed content, this method will
* never be able to work for mixed streams. Chained and interleaved streams are
* also not yet supported. Actually, this method is only a hack to support
* seeking from JMF, but may of course be abused otherwise too :)
*
* @param granulePosition
*
* @throws OggFormatException if the ogg stream is corrupted
* @throws IOException if some other IO error occurs
*/
public void setTime(long granulePosition) throws OggFormatException, IOException;
/**
* @return <code>true</code> if the stream is seekable, <code>false</code>
* otherwise
*/
public boolean isSeekable();
}

View File

@ -1,201 +0,0 @@
/*
* $ProjectName$
* $ProjectRevision$
* -----------------------------------------------------------
* $Id: UncachedUrlStream.java,v 1.1 2003/04/10 19:48:22 jarnbjo Exp $
* -----------------------------------------------------------
*
* $Author: jarnbjo $
*
* Description:
*
* Copyright 2002-2003 Tor-Einar Jarnbjo
* -----------------------------------------------------------
*
* Change History
* -----------------------------------------------------------
* $Log: UncachedUrlStream.java,v $
* Revision 1.1 2003/04/10 19:48:22 jarnbjo
* no message
*
*/
package de.jarnbjo.ogg;
import java.io.*;
import java.net.*;
import java.util.*;
/**
* Implementation of the <code>PhysicalOggStream</code> interface for reading
* an Ogg stream from a URL. This class performs only the necessary caching
* to provide continous playback. Seeking within the stream is not supported.
*/
public class UncachedUrlStream implements PhysicalOggStream {
private boolean closed=false;
private URLConnection source;
private InputStream sourceStream;
private Object drainLock=new Object();
private LinkedList pageCache=new LinkedList();
private long numberOfSamples=-1;
private HashMap logicalStreams=new HashMap();
private LoaderThread loaderThread;
private static final int PAGECACHE_SIZE = 10;
/** Creates an instance of the <code>PhysicalOggStream</code> interface
* suitable for reading an Ogg stream from a URL.
*/
public UncachedUrlStream(URL source) throws OggFormatException, IOException {
this.source=source.openConnection();
this.sourceStream=this.source.getInputStream();
loaderThread=new LoaderThread(sourceStream, pageCache);
new Thread(loaderThread).start();
while(!loaderThread.isBosDone() || pageCache.size()<PAGECACHE_SIZE) {
try {
Thread.sleep(200);
}
catch (InterruptedException ex) {
}
//System.out.print("caching "+pageCache.size()+"/"+PAGECACHE_SIZE+" pages\r");
}
//System.out.println();
}
public Collection getLogicalStreams() {
return logicalStreams.values();
}
public boolean isOpen() {
return !closed;
}
public void close() throws IOException {
closed=true;
sourceStream.close();
}
/*
public long getCacheLength() {
return cacheLength;
}
*/
/*
private OggPage getNextPage() throws EndOfOggStreamException, IOException, OggFormatException {
return getNextPage(false);
}
private OggPage getNextPage(boolean skipData) throws EndOfOggStreamException, IOException, OggFormatException {
return OggPage.create(sourceStream, skipData);
}
*/
public OggPage getOggPage(int index) throws IOException {
while(pageCache.size()==0) {
try {
Thread.sleep(100);
}
catch (InterruptedException ex) {
}
}
synchronized(drainLock) {
//OggPage page=(OggPage)pageCache.getFirst();
//pageCache.removeFirst();
//return page;
return (OggPage)pageCache.removeFirst();
}
}
private LogicalOggStream getLogicalStream(int serialNumber) {
return (LogicalOggStream)logicalStreams.get(new Integer(serialNumber));
}
public void setTime(long granulePosition) throws IOException {
throw new UnsupportedOperationException("Method not supported by this class");
}
public class LoaderThread implements Runnable {
private InputStream source;
private LinkedList pageCache;
private RandomAccessFile drain;
private byte[] memoryCache;
private boolean bosDone=false;
private int pageNumber;
public LoaderThread(InputStream source, LinkedList pageCache) {
this.source=source;
this.pageCache=pageCache;
}
public void run() {
try {
boolean eos=false;
byte[] buffer=new byte[8192];
while(!eos) {
OggPage op=OggPage.create(source);
synchronized (drainLock) {
pageCache.add(op);
}
if(!op.isBos()) {
bosDone=true;
}
if(op.isEos()) {
eos=true;
}
LogicalOggStreamImpl los=(LogicalOggStreamImpl)getLogicalStream(op.getStreamSerialNumber());
if(los==null) {
los=new LogicalOggStreamImpl(UncachedUrlStream.this, op.getStreamSerialNumber());
logicalStreams.put(new Integer(op.getStreamSerialNumber()), los);
los.checkFormat(op);
}
//los.addPageNumberMapping(pageNumber);
//los.addGranulePosition(op.getAbsoluteGranulePosition());
pageNumber++;
while(pageCache.size()>PAGECACHE_SIZE) {
try {
Thread.sleep(200);
}
catch (InterruptedException ex) {
}
}
}
}
catch(EndOfOggStreamException e) {
// ok
}
catch(IOException e) {
e.printStackTrace();
}
}
public boolean isBosDone() {
return bosDone;
}
}
/**
* @return always <code>false</code>
*/
public boolean isSeekable() {
return false;
}
}

View File

@ -1,62 +0,0 @@
package de.jarnbjo.util.audio;
import java.io.*;
import javax.sound.sampled.*;
public class FadeableAudioInputStream extends AudioInputStream {
private AudioInputStream stream;
private boolean fading=false;
private double phi=0.0;
public FadeableAudioInputStream(AudioInputStream stream) throws IOException {
super(stream, stream.getFormat(), -1L);
}
public void fadeOut() {
fading=true;
phi=0.0;
}
public int read(byte[] b) throws IOException {
return read(b, 0, b.length);
}
public int read(byte[] b, int offset, int length) throws IOException {
int read=super.read(b, offset, length);
//System.out.println("read "+read);
if(fading) {
int j=0, l=0, r=0;
double gain=0.0;
for(int i=offset; i<offset+read; i+=4) {
j=i;
l=((int)b[j++])&0xff;
l|=((int)b[j++])<<8;
r=((int)b[j++])&0xff;
r|=((int)b[j])<<8;
if(phi<Math.PI/2) {
phi+=0.000015;
}
gain=Math.cos(phi);
//System.out.println("gain "+gain);
l=(int)(l*gain);
r=(int)(r*gain);
j=i;
b[j++]=(byte)(l&0xff);
b[j++]=(byte)((l>>8)&0xff);
b[j++]=(byte)(r&0xff);
b[j++]=(byte)((r>>8)&0xff);
}
}
return read;
}
}

View File

@ -1,179 +0,0 @@
/*
* $ProjectName$
* $ProjectRevision$
* -----------------------------------------------------------
* $Id: BitInputStream.java,v 1.5 2003/04/10 19:48:31 jarnbjo Exp $
* -----------------------------------------------------------
*
* $Author: jarnbjo $
*
* Description:
*
* Copyright 2002-2003 Tor-Einar Jarnbjo
* -----------------------------------------------------------
*
* Change History
* -----------------------------------------------------------
* $Log: BitInputStream.java,v $
* Revision 1.5 2003/04/10 19:48:31 jarnbjo
* no message
*
* Revision 1.4 2003/03/16 20:57:06 jarnbjo
* no message
*
* Revision 1.3 2003/03/16 20:56:56 jarnbjo
* no message
*
* Revision 1.2 2003/03/16 01:11:39 jarnbjo
* no message
*
* Revision 1.1 2003/03/03 21:02:20 jarnbjo
* no message
*
*/
package de.jarnbjo.util.io;
import java.io.IOException;
/**
* An interface with methods allowing bit-wise reading from
* an input stream. All methods in this interface are optional
* and an implementation not support a method or a specific state
* (e.g. endian) will throw an UnspportedOperationException if
* such a method is being called. This should be speicified in
* the implementation documentation.
*/
public interface BitInputStream {
/**
* constant for setting this stream's mode to little endian
*
* @see #setEndian(int)
*/
public static final int LITTLE_ENDIAN = 0;
/**
* constant for setting this stream's mode to big endian
*
* @see #setEndian(int)
*/
public static final int BIG_ENDIAN = 1;
/**
* reads one bit (as a boolean) from the input stream
*
* @return <code>true</code> if the next bit is 1,
* <code>false</code> otherwise
*
* @throws IOException if an I/O error occurs
* @throws UnsupportedOperationException if the method is not supported by the implementation
*/
public boolean getBit() throws IOException;
/**
* reads <code>bits</code> number of bits from the input
* stream
*
* @return the unsigned integer value read from the stream
*
* @throws IOException if an I/O error occurs
* @throws UnsupportedOperationException if the method is not supported by the implementation
*/
public int getInt(int bits) throws IOException;
/**
* reads <code>bits</code> number of bits from the input
* stream
*
* @return the signed integer value read from the stream
*
* @throws IOException if an I/O error occurs
* @throws UnsupportedOperationException if the method is not supported by the implementation
*/
public int getSignedInt(int bits) throws IOException;
/**
* reads a huffman codeword based on the <code>root</code>
* parameter and returns the decoded value
*
* @param root the root of the Huffman tree used to decode the codeword
* @return the decoded unsigned integer value read from the stream
*
* @throws IOException if an I/O error occurs
* @throws UnsupportedOperationException if the method is not supported by the implementation
*/
public int getInt(HuffmanNode root) throws IOException;
/**
* reads an integer encoded as "signed rice" as described in
* the FLAC audio format specification
*
* @param order
* @return the decoded integer value read from the stream
*
* @throws IOException if an I/O error occurs
* @throws UnsupportedOperationException if the method is not supported by the implementation
*/
public int readSignedRice(int order) throws IOException;
/**
* fills the array from <code>offset</code> with <code>len</code>
* integers encoded as "signed rice" as described in
* the FLAC audio format specification
*
* @param order
* @param buffer
* @param offset
* @param len
* @return the decoded integer value read from the stream
*
* @throws IOException if an I/O error occurs
* @throws UnsupportedOperationException if the method is not supported by the implementation
*/
public void readSignedRice(int order, int[] buffer, int offset, int len) throws IOException;
/**
* reads <code>bits</code> number of bits from the input
* stream
*
* @return the unsigned long value read from the stream
*
* @throws IOException if an I/O error occurs
* @throws UnsupportedOperationException if the method is not supported by the implementation
*/
public long getLong(int bits) throws IOException;
/**
* causes the read pointer to be moved to the beginning
* of the next byte, remaining bits in the current byte
* are discarded
*
* @throws UnsupportedOperationException if the method is not supported by the implementation
*/
public void align();
/**
* changes the endian mode used when reading bit-wise from
* the stream, changing the mode mid-stream will cause the
* read cursor to move to the beginning of the next byte
* (as if calling the <code>allign</code> method
*
* @see #align()
*
* @throws UnsupportedOperationException if the method is not supported by the implementation
*/
public void setEndian(int endian);
}

View File

@ -1,346 +0,0 @@
/*
* $ProjectName$
* $ProjectRevision$
* -----------------------------------------------------------
* $Id: ByteArrayBitInputStream.java,v 1.3 2003/04/10 19:48:31 jarnbjo Exp $
* -----------------------------------------------------------
*
* $Author: jarnbjo $
*
* Description:
*
* Copyright 2002-2003 Tor-Einar Jarnbjo
* -----------------------------------------------------------
*
* Change History
* -----------------------------------------------------------
* $Log: ByteArrayBitInputStream.java,v $
* Revision 1.3 2003/04/10 19:48:31 jarnbjo
* no message
*
* Revision 1.2 2003/03/16 01:11:39 jarnbjo
* no message
*
* Revision 1.1 2003/03/03 21:02:20 jarnbjo
* no message
*
*/
package de.jarnbjo.util.io;
import java.io.IOException;
/**
* Implementation of the <code>BitInputStream</code> interface,
* using a byte array as data source.
*/
public class ByteArrayBitInputStream implements BitInputStream {
private byte[] source;
private byte currentByte;
private int endian;
private int byteIndex=0;
private int bitIndex=0;
public ByteArrayBitInputStream(byte[] source) {
this(source, LITTLE_ENDIAN);
}
public ByteArrayBitInputStream(byte[] source, int endian) {
this.endian=endian;
this.source=source;
currentByte=source[0];
bitIndex=(endian==LITTLE_ENDIAN)?0:7;
}
public boolean getBit() throws IOException {
if(endian==LITTLE_ENDIAN) {
if(bitIndex>7) {
bitIndex=0;
currentByte=source[++byteIndex];
}
return (currentByte&(1<<(bitIndex++)))!=0;
}
else {
if(bitIndex<0) {
bitIndex=7;
currentByte=source[++byteIndex];
}
return (currentByte&(1<<(bitIndex--)))!=0;
}
}
public int getInt(int bits) throws IOException {
if(bits>32) {
throw new IllegalArgumentException("Argument \"bits\" must be <= 32");
}
int res=0;
if(endian==LITTLE_ENDIAN) {
for(int i=0; i<bits; i++) {
if(getBit()) {
res|=(1<<i);
}
}
}
else {
if(bitIndex<0) {
bitIndex=7;
currentByte=source[++byteIndex];
}
if(bits<=bitIndex+1) {
int ci=((int)currentByte)&0xff;
int offset=1+bitIndex-bits;
int mask=((1<<bits)-1)<<offset;
res=(ci&mask)>>offset;
bitIndex-=bits;
}
else {
res=(((int)currentByte)&0xff&((1<<(bitIndex+1))-1))<<(bits-bitIndex-1);
bits-=bitIndex+1;
currentByte=source[++byteIndex];
while(bits>=8) {
bits-=8;
res|=(((int)source[byteIndex])&0xff)<<bits;
currentByte=source[++byteIndex];
}
if(bits>0) {
int ci=((int)source[byteIndex])&0xff;
res|=(ci>>(8-bits))&((1<<bits)-1);
bitIndex=7-bits;
}
else {
currentByte=source[--byteIndex];
bitIndex=-1;
}
}
}
return res;
}
public int getSignedInt(int bits) throws IOException {
int raw=getInt(bits);
if(raw>=1<<(bits-1)) {
raw-=1<<bits;
}
return raw;
}
public int getInt(HuffmanNode root) throws IOException {
while(root.value==null) {
if(bitIndex>7) {
bitIndex=0;
currentByte=source[++byteIndex];
}
root=(currentByte&(1<<(bitIndex++)))!=0?root.o1:root.o0;
}
return root.value.intValue();
}
public long getLong(int bits) throws IOException {
if(bits>64) {
throw new IllegalArgumentException("Argument \"bits\" must be <= 64");
}
long res=0;
if(endian==LITTLE_ENDIAN) {
for(int i=0; i<bits; i++) {
if(getBit()) {
res|=(1L<<i);
}
}
}
else {
for(int i=bits-1; i>=0; i--) {
if(getBit()) {
res|=(1L<<i);
}
}
}
return res;
}
/**
* <p>reads an integer encoded as "signed rice" as described in
* the FLAC audio format specification</p>
*
* <p><b>not supported for little endian</b></p>
*
* @param order
* @return the decoded integer value read from the stream
*
* @throws IOException if an I/O error occurs
* @throws UnsupportedOperationException if the method is not supported by the implementation
*/
public int readSignedRice(int order) throws IOException {
int msbs=-1, lsbs=0, res=0;
if(endian==LITTLE_ENDIAN) {
// little endian
throw new UnsupportedOperationException("ByteArrayBitInputStream.readSignedRice() is only supported in big endian mode");
}
else {
// big endian
byte cb=source[byteIndex];
do {
msbs++;
if(bitIndex<0) {
bitIndex=7;
byteIndex++;
cb=source[byteIndex];
}
} while((cb&(1<<bitIndex--))==0);
int bits=order;
if(bitIndex<0) {
bitIndex=7;
byteIndex++;
}
if(bits<=bitIndex+1) {
int ci=((int)source[byteIndex])&0xff;
int offset=1+bitIndex-bits;
int mask=((1<<bits)-1)<<offset;
lsbs=(ci&mask)>>offset;
bitIndex-=bits;
}
else {
lsbs=(((int)source[byteIndex])&0xff&((1<<(bitIndex+1))-1))<<(bits-bitIndex-1);
bits-=bitIndex+1;
byteIndex++;
while(bits>=8) {
bits-=8;
lsbs|=(((int)source[byteIndex])&0xff)<<bits;
byteIndex++;
}
if(bits>0) {
int ci=((int)source[byteIndex])&0xff;
lsbs|=(ci>>(8-bits))&((1<<bits)-1);
bitIndex=7-bits;
}
else {
byteIndex--;
bitIndex=-1;
}
}
res=(msbs<<order)|lsbs;
}
return (res&1)==1?-(res>>1)-1:(res>>1);
}
/**
* <p>fills the array from <code>offset</code> with <code>len</code>
* integers encoded as "signed rice" as described in
* the FLAC audio format specification</p>
*
* <p><b>not supported for little endian</b></p>
*
* @param order
* @param buffer
* @param offset
* @param len
* @return the decoded integer value read from the stream
*
* @throws IOException if an I/O error occurs
* @throws UnsupportedOperationException if the method is not supported by the implementation
*/
public void readSignedRice(int order, int[] buffer, int off, int len) throws IOException {
if(endian==LITTLE_ENDIAN) {
// little endian
throw new UnsupportedOperationException("ByteArrayBitInputStream.readSignedRice() is only supported in big endian mode");
}
else {
// big endian
for(int i=off; i<off+len; i++) {
int msbs=-1, lsbs=0;
byte cb=source[byteIndex];
do {
msbs++;
if(bitIndex<0) {
bitIndex=7;
byteIndex++;
cb=source[byteIndex];
}
} while((cb&(1<<bitIndex--))==0);
int bits=order;
if(bitIndex<0) {
bitIndex=7;
byteIndex++;
}
if(bits<=bitIndex+1) {
int ci=((int)source[byteIndex])&0xff;
int offset=1+bitIndex-bits;
int mask=((1<<bits)-1)<<offset;
lsbs=(ci&mask)>>offset;
bitIndex-=bits;
}
else {
lsbs=(((int)source[byteIndex])&0xff&((1<<(bitIndex+1))-1))<<(bits-bitIndex-1);
bits-=bitIndex+1;
byteIndex++;
while(bits>=8) {
bits-=8;
lsbs|=(((int)source[byteIndex])&0xff)<<bits;
byteIndex++;
}
if(bits>0) {
int ci=((int)source[byteIndex])&0xff;
lsbs|=(ci>>(8-bits))&((1<<bits)-1);
bitIndex=7-bits;
}
else {
byteIndex--;
bitIndex=-1;
}
}
int res=(msbs<<order)|lsbs;
buffer[i]=(res&1)==1?-(res>>1)-1:(res>>1);
}
}
}
public void align() {
if(endian==BIG_ENDIAN && bitIndex>=0) {
bitIndex=7;
byteIndex++;
}
else if(endian==LITTLE_ENDIAN && bitIndex<=7) {
bitIndex=0;
byteIndex++;
}
}
public void setEndian(int endian) {
if(this.endian==BIG_ENDIAN && endian==LITTLE_ENDIAN) {
bitIndex=0;
byteIndex++;
}
else if(this.endian==LITTLE_ENDIAN && endian==BIG_ENDIAN) {
bitIndex=7;
byteIndex++;
}
this.endian=endian;
}
/**
* @return the byte array used as a source for this instance
*/
public byte[] getSource() {
return source;
}
}

View File

@ -1,138 +0,0 @@
/*
* $ProjectName$
* $ProjectRevision$
* -----------------------------------------------------------
* $Id: HuffmanNode.java,v 1.2 2003/04/10 19:48:31 jarnbjo Exp $
* -----------------------------------------------------------
*
* $Author: jarnbjo $
*
* Description:
*
* Copyright 2002-2003 Tor-Einar Jarnbjo
* -----------------------------------------------------------
*
* Change History
* -----------------------------------------------------------
* $Log: HuffmanNode.java,v $
* Revision 1.2 2003/04/10 19:48:31 jarnbjo
* no message
*
*/
package de.jarnbjo.util.io;
import java.io.IOException;
import de.jarnbjo.util.io.BitInputStream;
/**
* Representation of a node in a Huffman tree, used to read
* Huffman compressed codewords from e.g. a Vorbis stream.
*/
final public class HuffmanNode {
private HuffmanNode parent;
private int depth=0;
protected HuffmanNode o0, o1;
protected Integer value;
private boolean full=false;
/**
* creates a new Huffman tree root node
*/
public HuffmanNode() {
this(null);
}
protected HuffmanNode(HuffmanNode parent) {
this.parent=parent;
if(parent!=null) {
depth=parent.getDepth()+1;
}
}
protected HuffmanNode(HuffmanNode parent, int value) {
this(parent);
this.value=new Integer(value);
full=true;
}
protected int read(BitInputStream bis) throws IOException {
HuffmanNode iter=this;
while(iter.value==null) {
iter=bis.getBit()?iter.o1:iter.o0;
}
return iter.value.intValue();
}
protected HuffmanNode get0() {
return o0==null?set0(new HuffmanNode(this)):o0;
}
protected HuffmanNode get1() {
return o1==null?set1(new HuffmanNode(this)):o1;
}
protected Integer getValue() {
return value;
}
private HuffmanNode getParent() {
return parent;
}
protected int getDepth() {
return depth;
}
private boolean isFull() {
return full?true:(full=o0!=null&&o0.isFull()&&o1!=null&&o1.isFull());
}
private HuffmanNode set0(HuffmanNode value) {
return o0=value;
}
private HuffmanNode set1(HuffmanNode value) {
return o1=value;
}
private void setValue(Integer value) {
full=true;
this.value=value;
}
/**
* creates a new tree node at the first free location at the given
* depth, and assigns the value to it
*
* @param depth the tree depth of the new node (codeword length in bits)
* @param value the node's new value
*/
public boolean setNewValue(int depth, int value) {
if(isFull()) {
return false;
}
if(depth==1) {
if(o0==null) {
set0(new HuffmanNode(this, value));
return true;
}
else if(o1==null) {
set1(new HuffmanNode(this, value));
return true;
}
else {
return false;
}
}
else {
return get0().setNewValue(depth-1, value)?
true:
get1().setNewValue(depth-1, value);
}
}
}

View File

@ -1,320 +0,0 @@
/*
* $ProjectName$
* $ProjectRevision$
* -----------------------------------------------------------
* $Id: AudioPacket.java,v 1.2 2003/03/16 01:11:12 jarnbjo Exp $
* -----------------------------------------------------------
*
* $Author: jarnbjo $
*
* Description:
*
* Copyright 2002-2003 Tor-Einar Jarnbjo
* -----------------------------------------------------------
*
* Change History
* -----------------------------------------------------------
* $Log: AudioPacket.java,v $
* Revision 1.2 2003/03/16 01:11:12 jarnbjo
* no message
*
*
*/
package de.jarnbjo.vorbis;
import java.io.IOException;
import java.util.*;
import de.jarnbjo.util.io.*;
class AudioPacket {
private int modeNumber;
private Mode mode;
private Mapping mapping;
private int n; // block size
private boolean blockFlag, previousWindowFlag, nextWindowFlag;
private int windowCenter, leftWindowStart, leftWindowEnd, leftN, rightWindowStart, rightWindowEnd, rightN;
private float[] window;
private float[][] pcm;
private int[][] pcmInt;
private Floor[] channelFloors;
private boolean[] noResidues;
private final static float[][] windows=new float[8][];
protected AudioPacket(final VorbisStream vorbis, final BitInputStream source) throws VorbisFormatException, IOException {
final SetupHeader sHeader=vorbis.getSetupHeader();
final IdentificationHeader iHeader=vorbis.getIdentificationHeader();
final Mode[] modes=sHeader.getModes();
final Mapping[] mappings=sHeader.getMappings();
final Residue[] residues=sHeader.getResidues();
final int channels=iHeader.getChannels();
if(source.getInt(1)!=0) {
throw new VorbisFormatException("Packet type mismatch when trying to create an audio packet.");
}
modeNumber=source.getInt(Util.ilog(modes.length-1));
try {
mode=modes[modeNumber];
}
catch(ArrayIndexOutOfBoundsException e) {
throw new VorbisFormatException("Reference to invalid mode in audio packet.");
}
mapping=mappings[mode.getMapping()];
final int[] magnitudes=mapping.getMagnitudes();
final int[] angles=mapping.getAngles();
blockFlag=mode.getBlockFlag();
final int blockSize0=iHeader.getBlockSize0();
final int blockSize1=iHeader.getBlockSize1();
n=blockFlag?blockSize1:blockSize0;
if(blockFlag) {
previousWindowFlag=source.getBit();
nextWindowFlag=source.getBit();
}
windowCenter=n/2;
if(blockFlag && !previousWindowFlag) {
leftWindowStart=n/4-blockSize0/4;
leftWindowEnd=n/4+blockSize0/4;
leftN=blockSize0/2;
}
else {
leftWindowStart=0;
leftWindowEnd=n/2;
leftN=windowCenter;
}
if(blockFlag && !nextWindowFlag) {
rightWindowStart=n*3/4-blockSize0/4;
rightWindowEnd=n*3/4+blockSize0/4;
rightN=blockSize0/2;
}
else {
rightWindowStart=windowCenter;
rightWindowEnd=n;
rightN=n/2;
}
window=getComputedWindow();//new double[n];
channelFloors=new Floor[channels];
noResidues=new boolean[channels];
pcm=new float[channels][n];
pcmInt=new int[channels][n];
boolean allFloorsEmpty=true;
for(int i=0; i<channels; i++) {
int submapNumber=mapping.getMux()[i];
int floorNumber=mapping.getSubmapFloors()[submapNumber];
Floor decodedFloor=sHeader.getFloors()[floorNumber].decodeFloor(vorbis, source);
channelFloors[i]=decodedFloor;
noResidues[i]=decodedFloor==null;
if(decodedFloor!=null) {
allFloorsEmpty=false;
}
}
if(allFloorsEmpty) {
return;
}
for(int i=0; i<magnitudes.length; i++) {
if(!noResidues[magnitudes[i]] ||
!noResidues[angles[i]]) {
noResidues[magnitudes[i]]=false;
noResidues[angles[i]]=false;
}
}
Residue[] decodedResidues=new Residue[mapping.getSubmaps()];
for(int i=0; i<mapping.getSubmaps(); i++) {
int ch=0;
boolean[] doNotDecodeFlags=new boolean[channels];
for(int j=0; j<channels; j++) {
if(mapping.getMux()[j]==i) {
doNotDecodeFlags[ch++]=noResidues[j];
}
}
int residueNumber=mapping.getSubmapResidues()[i];
Residue residue=residues[residueNumber];
residue.decodeResidue(vorbis, source, mode, ch, doNotDecodeFlags, pcm);
}
for(int i=mapping.getCouplingSteps()-1; i>=0; i--) {
double newA=0, newM=0;
final float[] magnitudeVector=pcm[magnitudes[i]];
final float[] angleVector=pcm[angles[i]];
for(int j=0; j<magnitudeVector.length; j++) {
float a=angleVector[j];
float m=magnitudeVector[j];
if(a>0) {
//magnitudeVector[j]=m;
angleVector[j]=m>0?m-a:m+a;
}
else {
magnitudeVector[j]=m>0?m+a:m-a;
angleVector[j]=m;
}
}
}
for(int i=0; i<channels; i++) {
if(channelFloors[i]!=null) {
channelFloors[i].computeFloor(pcm[i]);
}
}
// perform an inverse mdct to all channels
for(int i=0; i<channels; i++) {
MdctFloat mdct=blockFlag?iHeader.getMdct1():iHeader.getMdct0();
mdct.imdct(pcm[i], window, pcmInt[i]);
}
}
private float[] getComputedWindow() {
int ix=(blockFlag?4:0)+(previousWindowFlag?2:0)+(nextWindowFlag?1:0);
float[] w=windows[ix];
if(w==null) {
w=new float[n];
for(int i=0;i<leftN;i++){
float x=(float)((i+.5)/leftN*Math.PI/2.);
x=(float)Math.sin(x);
x*=x;
x*=(float)Math.PI/2.;
x=(float)Math.sin(x);
w[i+leftWindowStart]=x;
}
for(int i=leftWindowEnd; i<rightWindowStart; w[i++]=1.0f);
for(int i=0;i<rightN;i++){
float x=(float)((rightN-i-.5)/rightN*Math.PI/2.);
x=(float)Math.sin(x);
x*=x;
x*=(float)Math.PI/2.;
x=(float)Math.sin(x);
w[i+rightWindowStart]=x;
}
windows[ix]=w;
}
return w;
}
protected int getNumberOfSamples() {
return rightWindowStart-leftWindowStart;
}
protected int getPcm(final AudioPacket previousPacket, final int[][] buffer) {
int channels=pcm.length;
int val;
// copy left window flank and mix with right window flank from
// the previous audio packet
for(int i=0; i<channels; i++) {
int j1=0, j2=previousPacket.rightWindowStart;
final int[] ppcm=previousPacket.pcmInt[i];
final int[] tpcm=pcmInt[i];
final int[] target=buffer[i];
for(int j=leftWindowStart; j<leftWindowEnd; j++) {
val=ppcm[j2++]+tpcm[j];
if(val>32767) val=32767;
if(val<-32768) val=-32768;
target[j1++]=val;
}
}
// use System.arraycopy to copy the middle part (if any)
// of the window
if(leftWindowEnd+1<rightWindowStart) {
for(int i=0; i<channels; i++) {
System.arraycopy(pcmInt[i], leftWindowEnd, buffer[i], leftWindowEnd-leftWindowStart, rightWindowStart-leftWindowEnd);
}
}
return rightWindowStart-leftWindowStart;
}
protected void getPcm(final AudioPacket previousPacket, final byte[] buffer) {
int channels=pcm.length;
int val;
// copy left window flank and mix with right window flank from
// the previous audio packet
for(int i=0; i<channels; i++) {
int ix=0, j2=previousPacket.rightWindowStart;
final int[] ppcm=previousPacket.pcmInt[i];
final int[] tpcm=pcmInt[i];
for(int j=leftWindowStart; j<leftWindowEnd; j++) {
val=ppcm[j2++]+tpcm[j];
if(val>32767) val=32767;
if(val<-32768) val=-32768;
buffer[ix+(i*2)+1]=(byte)(val&0xff);
buffer[ix+(i*2)]=(byte)((val>>8)&0xff);
ix+=channels*2;
}
ix=(leftWindowEnd-leftWindowStart)*channels*2;
for(int j=leftWindowEnd; j<rightWindowStart; j++) {
val=tpcm[j];
if(val>32767) val=32767;
if(val<-32768) val=-32768;
buffer[ix+(i*2)+1]=(byte)(val&0xff);
buffer[ix+(i*2)]=(byte)((val>>8)&0xff);
ix+=channels*2;
}
}
}
protected float[] getWindow() {
return window;
}
protected int getLeftWindowStart() {
return leftWindowStart;
}
protected int getLeftWindowEnd() {
return leftWindowEnd;
}
protected int getRightWindowStart() {
return rightWindowStart;
}
protected int getRightWindowEnd() {
return rightWindowEnd;
}
public int[][] getPcm() {
return pcmInt;
}
public float[][] getFreqencyDomain() {
return pcm;
}
}

View File

@ -1,267 +0,0 @@
/*
* $ProjectName$
* $ProjectRevision$
* -----------------------------------------------------------
* $Id: CodeBook.java,v 1.3 2003/04/10 19:49:04 jarnbjo Exp $
* -----------------------------------------------------------
*
* $Author: jarnbjo $
*
* Description:
*
* Copyright 2002-2003 Tor-Einar Jarnbjo
* -----------------------------------------------------------
*
* Change History
* -----------------------------------------------------------
* $Log: CodeBook.java,v $
* Revision 1.3 2003/04/10 19:49:04 jarnbjo
* no message
*
* Revision 1.2 2003/03/16 01:11:12 jarnbjo
* no message
*
*
*/
package de.jarnbjo.vorbis;
import java.io.*;
import java.text.*;
import java.util.*;
import de.jarnbjo.util.io.*;
class CodeBook {
private HuffmanNode huffmanRoot;
private int dimensions, entries;
private int[] entryLengths;
private float[][] valueVector;
protected CodeBook(BitInputStream source) throws VorbisFormatException, IOException {
// check sync
if(source.getInt(24)!=0x564342) {
throw new VorbisFormatException("The code book sync pattern is not correct.");
}
dimensions=source.getInt(16);
entries=source.getInt(24);
entryLengths=new int[entries];
boolean ordered=source.getBit();
if(ordered) {
int cl=source.getInt(5)+1;
for(int i=0; i<entryLengths.length; ) {
int num=source.getInt(Util.ilog(entryLengths.length-i));
if(i+num>entryLengths.length) {
throw new VorbisFormatException("The codebook entry length list is longer than the actual number of entry lengths.");
}
Arrays.fill(entryLengths, i, i+num, cl);
cl++;
i+=num;
}
}
else {
// !ordered
boolean sparse=source.getBit();
if(sparse) {
for(int i=0; i<entryLengths.length; i++) {
if(source.getBit()) {
entryLengths[i]=source.getInt(5)+1;
}
else {
entryLengths[i]=-1;
}
}
}
else {
// !sparse
for(int i=0; i<entryLengths.length; i++) {
entryLengths[i]=source.getInt(5)+1;
}
}
}
if (!createHuffmanTree(entryLengths)) {
throw new VorbisFormatException("An exception was thrown when building the codebook Huffman tree.");
}
int codeBookLookupType=source.getInt(4);
switch(codeBookLookupType) {
case 0:
// codebook has no scalar vectors to be calculated
break;
case 1:
case 2:
float codeBookMinimumValue=Util.float32unpack(source.getInt(32));
float codeBookDeltaValue=Util.float32unpack(source.getInt(32));
int codeBookValueBits=source.getInt(4)+1;
boolean codeBookSequenceP=source.getBit();
int codeBookLookupValues=0;
if(codeBookLookupType==1) {
codeBookLookupValues=Util.lookup1Values(entries, dimensions);
}
else {
codeBookLookupValues=entries*dimensions;
}
int codeBookMultiplicands[]=new int[codeBookLookupValues];
for(int i=0; i<codeBookMultiplicands.length; i++) {
codeBookMultiplicands[i]=source.getInt(codeBookValueBits);
}
valueVector=new float[entries][dimensions];
if(codeBookLookupType==1) {
for(int i=0; i<entries; i++) {
float last=0;
int indexDivisor=1;
for(int j=0; j<dimensions; j++) {
int multiplicandOffset=
(i/indexDivisor)%codeBookLookupValues;
valueVector[i][j]=
codeBookMultiplicands[multiplicandOffset]*codeBookDeltaValue+codeBookMinimumValue+last;
if(codeBookSequenceP) {
last=valueVector[i][j];
}
indexDivisor*=codeBookLookupValues;
}
}
}
else {
throw new UnsupportedOperationException();
/** @todo implement */
}
break;
default:
throw new VorbisFormatException("Unsupported codebook lookup type: "+codeBookLookupType);
}
}
private static long totalTime=0;
private boolean createHuffmanTree(int[] entryLengths) {
huffmanRoot=new HuffmanNode();
for(int i=0; i<entryLengths.length; i++) {
int el=entryLengths[i];
if(el>0) {
if(!huffmanRoot.setNewValue(el, i)) {
return false;
}
}
}
return true;
}
protected int getDimensions() {
return dimensions;
}
protected int getEntries() {
return entries;
}
protected HuffmanNode getHuffmanRoot() {
return huffmanRoot;
}
//public float[] readVQ(ReadableBitChannel source) throws IOException {
// return valueVector[readInt(source)];
//}
protected int readInt(final BitInputStream source) throws IOException {
return source.getInt(huffmanRoot);
/*
HuffmanNode node;
for(node=huffmanRoot; node.value==null; node=source.getBit()?node.o1:node.o0);
return node.value.intValue();
*/
}
protected void readVvAdd(float[][] a, BitInputStream source, int offset, int length)
throws VorbisFormatException, IOException {
int i,j;//k;//entry;
int chptr=0;
int ch=a.length;
if(ch==0) {
return;
}
int lim=(offset+length)/ch;
for(i=offset/ch;i<lim;){
final float[] ve=valueVector[source.getInt(huffmanRoot)];
for(j=0;j<dimensions;j++){
a[chptr++][i]+=ve[j];
if(chptr==ch){
chptr=0;
i++;
}
}
}
}
/*
public void readVAdd(double[] a, ReadableBitChannel source, int offset, int length)
throws FormatException, IOException {
int i,j,entry;
int t;
if(dimensions>8){
for(i=0;i<length;){
entry = readInt(source);
//if(entry==-1)return(-1);
//t=entry*dimensions;
for(j=0;j<dimensions;){
a[offset+(i++)]+=valueVector[entry][j++];//valuelist[t+(j++)];
}
}
}
else{
for(i=0;i<length;){
entry=readInt(source);
//if(entry==-1)return(-1);
//t=entry*dim;
j=0;
switch(dimensions){
case 8:
a[offset+(i++)]+=valueVector[entry][j++];//valuelist[t+(j++)];
case 7:
a[offset+(i++)]+=valueVector[entry][j++];//valuelist[t+(j++)];
case 6:
a[offset+(i++)]+=valueVector[entry][j++];//valuelist[t+(j++)];
case 5:
a[offset+(i++)]+=valueVector[entry][j++];//valuelist[t+(j++)];
case 4:
a[offset+(i++)]+=valueVector[entry][j++];//valuelist[t+(j++)];
case 3:
a[offset+(i++)]+=valueVector[entry][j++];//valuelist[t+(j++)];
case 2:
a[offset+(i++)]+=valueVector[entry][j++];//valuelist[t+(j++)];
case 1:
a[offset+(i++)]+=valueVector[entry][j++];//valuelist[t+(j++)];
case 0:
break;
}
}
}
}
*/
}

View File

@ -1,237 +0,0 @@
/*
* $ProjectName$
* $ProjectRevision$
* -----------------------------------------------------------
* $Id: CommentHeader.java,v 1.2 2003/03/16 01:11:12 jarnbjo Exp $
* -----------------------------------------------------------
*
* $Author: jarnbjo $
*
* Description:
*
* Copyright 2002-2003 Tor-Einar Jarnbjo
* -----------------------------------------------------------
*
* Change History
* -----------------------------------------------------------
* $Log: CommentHeader.java,v $
* Revision 1.2 2003/03/16 01:11:12 jarnbjo
* no message
*
*
*/
package de.jarnbjo.vorbis;
import java.io.*;
import java.util.*;
import de.jarnbjo.util.io.BitInputStream;
/**
*/
public class CommentHeader {
public static final String TITLE = "TITLE";
public static final String ARTIST = "ARTIST";
public static final String ALBUM = "ALBUM";
public static final String TRACKNUMBER = "TRACKNUMBER";
public static final String VERSION = "VERSION";
public static final String PERFORMER = "PERFORMER";
public static final String COPYRIGHT = "COPYRIGHT";
public static final String LICENSE = "LICENSE";
public static final String ORGANIZATION = "ORGANIZATION";
public static final String DESCRIPTION = "DESCRIPTION";
public static final String GENRE = "GENRE";
public static final String DATE = "DATE";
public static final String LOCATION = "LOCATION";
public static final String CONTACT = "CONTACT";
public static final String ISRC = "ISRC";
private String vendor;
private HashMap comments=new HashMap();
private boolean framingBit;
private static final long HEADER = 0x736962726f76L; // 'vorbis'
public CommentHeader(BitInputStream source) throws VorbisFormatException, IOException {
if(source.getLong(48)!=HEADER) {
throw new VorbisFormatException("The identification header has an illegal leading.");
}
vendor=getString(source);
int ucLength=source.getInt(32);
for(int i=0; i<ucLength; i++) {
String comment=getString(source);
int ix=comment.indexOf('=');
String key=comment.substring(0, ix);
String value=comment.substring(ix+1);
//comments.put(key, value);
addComment(key, value);
}
framingBit=source.getInt(8)!=0;
}
private void addComment(String key, String value) {
ArrayList al=(ArrayList)comments.get(key);
if(al==null) {
al=new ArrayList();
comments.put(key, al);
}
al.add(value);
}
public String getVendor() {
return vendor;
}
public String getComment(String key) {
ArrayList al=(ArrayList)comments.get(key);
return al==null?(String)null:(String)al.get(0);
}
public String[] getComments(String key) {
ArrayList al=(ArrayList)comments.get(key);
return al==null?new String[0]:(String[])al.toArray(new String[al.size()]);
}
public String getTitle() {
return getComment(TITLE);
}
public String[] getTitles() {
return getComments(TITLE);
}
public String getVersion() {
return getComment(VERSION);
}
public String[] getVersions() {
return getComments(VERSION);
}
public String getAlbum() {
return getComment(ALBUM);
}
public String[] getAlbums() {
return getComments(ALBUM);
}
public String getTrackNumber() {
return getComment(TRACKNUMBER);
}
public String[] getTrackNumbers() {
return getComments(TRACKNUMBER);
}
public String getArtist() {
return getComment(ARTIST);
}
public String[] getArtists() {
return getComments(ARTIST);
}
public String getPerformer() {
return getComment(PERFORMER);
}
public String[] getPerformers() {
return getComments(PERFORMER);
}
public String getCopyright() {
return getComment(COPYRIGHT);
}
public String[] getCopyrights() {
return getComments(COPYRIGHT);
}
public String getLicense() {
return getComment(LICENSE);
}
public String[] getLicenses() {
return getComments(LICENSE);
}
public String getOrganization() {
return getComment(ORGANIZATION);
}
public String[] getOrganizations() {
return getComments(ORGANIZATION);
}
public String getDescription() {
return getComment(DESCRIPTION);
}
public String[] getDescriptions() {
return getComments(DESCRIPTION);
}
public String getGenre() {
return getComment(GENRE);
}
public String[] getGenres() {
return getComments(GENRE);
}
public String getDate() {
return getComment(DATE);
}
public String[] getDates() {
return getComments(DATE);
}
public String getLocation() {
return getComment(LOCATION);
}
public String[] getLocations() {
return getComments(LOCATION);
}
public String getContact() {
return getComment(CONTACT);
}
public String[] getContacts() {
return getComments(CONTACT);
}
public String getIsrc() {
return getComment(ISRC);
}
public String[] getIsrcs() {
return getComments(ISRC);
}
private String getString(BitInputStream source) throws IOException, VorbisFormatException {
int length=source.getInt(32);
byte[] strArray=new byte[length];
for(int i=0; i<length; i++) {
strArray[i]=(byte)source.getInt(8);
}
return new String(strArray, "UTF-8");
}
}

View File

@ -1,118 +0,0 @@
/*
* $ProjectName$
* $ProjectRevision$
* -----------------------------------------------------------
* $Id: Floor.java,v 1.3 2003/04/10 19:49:04 jarnbjo Exp $
* -----------------------------------------------------------
*
* $Author: jarnbjo $
*
* Description:
*
* Copyright 2002-2003 Tor-Einar Jarnbjo
* -----------------------------------------------------------
*
* Change History
* -----------------------------------------------------------
* $Log: Floor.java,v $
* Revision 1.3 2003/04/10 19:49:04 jarnbjo
* no message
*
* Revision 1.2 2003/03/16 01:11:12 jarnbjo
* no message
*
*
*/
package de.jarnbjo.vorbis;
import java.io.IOException;
import de.jarnbjo.util.io.BitInputStream;
public abstract class Floor {
public final static float[] DB_STATIC_TABLE={
1.0649863e-07f, 1.1341951e-07f, 1.2079015e-07f, 1.2863978e-07f,
1.3699951e-07f, 1.4590251e-07f, 1.5538408e-07f, 1.6548181e-07f,
1.7623575e-07f, 1.8768855e-07f, 1.9988561e-07f, 2.128753e-07f,
2.2670913e-07f, 2.4144197e-07f, 2.5713223e-07f, 2.7384213e-07f,
2.9163793e-07f, 3.1059021e-07f, 3.3077411e-07f, 3.5226968e-07f,
3.7516214e-07f, 3.9954229e-07f, 4.2550680e-07f, 4.5315863e-07f,
4.8260743e-07f, 5.1396998e-07f, 5.4737065e-07f, 5.8294187e-07f,
6.2082472e-07f, 6.6116941e-07f, 7.0413592e-07f, 7.4989464e-07f,
7.9862701e-07f, 8.5052630e-07f, 9.0579828e-07f, 9.6466216e-07f,
1.0273513e-06f, 1.0941144e-06f, 1.1652161e-06f, 1.2409384e-06f,
1.3215816e-06f, 1.4074654e-06f, 1.4989305e-06f, 1.5963394e-06f,
1.7000785e-06f, 1.8105592e-06f, 1.9282195e-06f, 2.0535261e-06f,
2.1869758e-06f, 2.3290978e-06f, 2.4804557e-06f, 2.6416497e-06f,
2.8133190e-06f, 2.9961443e-06f, 3.1908506e-06f, 3.3982101e-06f,
3.6190449e-06f, 3.8542308e-06f, 4.1047004e-06f, 4.3714470e-06f,
4.6555282e-06f, 4.9580707e-06f, 5.2802740e-06f, 5.6234160e-06f,
5.9888572e-06f, 6.3780469e-06f, 6.7925283e-06f, 7.2339451e-06f,
7.7040476e-06f, 8.2047000e-06f, 8.7378876e-06f, 9.3057248e-06f,
9.9104632e-06f, 1.0554501e-05f, 1.1240392e-05f, 1.1970856e-05f,
1.2748789e-05f, 1.3577278e-05f, 1.4459606e-05f, 1.5399272e-05f,
1.6400004e-05f, 1.7465768e-05f, 1.8600792e-05f, 1.9809576e-05f,
2.1096914e-05f, 2.2467911e-05f, 2.3928002e-05f, 2.5482978e-05f,
2.7139006e-05f, 2.8902651e-05f, 3.0780908e-05f, 3.2781225e-05f,
3.4911534e-05f, 3.7180282e-05f, 3.9596466e-05f, 4.2169667e-05f,
4.4910090e-05f, 4.7828601e-05f, 5.0936773e-05f, 5.4246931e-05f,
5.7772202e-05f, 6.1526565e-05f, 6.5524908e-05f, 6.9783085e-05f,
7.4317983e-05f, 7.9147585e-05f, 8.4291040e-05f, 8.9768747e-05f,
9.5602426e-05f, 0.00010181521f, 0.00010843174f, 0.00011547824f,
0.00012298267f, 0.00013097477f, 0.00013948625f, 0.00014855085f,
0.00015820453f, 0.00016848555f, 0.00017943469f, 0.00019109536f,
0.00020351382f, 0.00021673929f, 0.00023082423f, 0.00024582449f,
0.00026179955f, 0.00027881276f, 0.00029693158f, 0.00031622787f,
0.00033677814f, 0.00035866388f, 0.00038197188f, 0.00040679456f,
0.00043323036f, 0.00046138411f, 0.00049136745f, 0.00052329927f,
0.00055730621f, 0.00059352311f, 0.00063209358f, 0.00067317058f,
0.00071691700f, 0.00076350630f, 0.00081312324f, 0.00086596457f,
0.00092223983f, 0.00098217216f, 0.0010459992f, 0.0011139742f,
0.0011863665f, 0.0012634633f, 0.0013455702f, 0.0014330129f,
0.0015261382f, 0.0016253153f, 0.0017309374f, 0.0018434235f,
0.0019632195f, 0.0020908006f, 0.0022266726f, 0.0023713743f,
0.0025254795f, 0.0026895994f, 0.0028643847f, 0.0030505286f,
0.0032487691f, 0.0034598925f, 0.0036847358f, 0.0039241906f,
0.0041792066f, 0.0044507950f, 0.0047400328f, 0.0050480668f,
0.0053761186f, 0.0057254891f, 0.0060975636f, 0.0064938176f,
0.0069158225f, 0.0073652516f, 0.0078438871f, 0.0083536271f,
0.0088964928f, 0.009474637f, 0.010090352f, 0.010746080f,
0.011444421f, 0.012188144f, 0.012980198f, 0.013823725f,
0.014722068f, 0.015678791f, 0.016697687f, 0.017782797f,
0.018938423f, 0.020169149f, 0.021479854f, 0.022875735f,
0.024362330f, 0.025945531f, 0.027631618f, 0.029427276f,
0.031339626f, 0.033376252f, 0.035545228f, 0.037855157f,
0.040315199f, 0.042935108f, 0.045725273f, 0.048696758f,
0.051861348f, 0.055231591f, 0.058820850f, 0.062643361f,
0.066714279f, 0.071049749f, 0.075666962f, 0.080584227f,
0.085821044f, 0.091398179f, 0.097337747f, 0.10366330f,
0.11039993f, 0.11757434f, 0.12521498f, 0.13335215f,
0.14201813f, 0.15124727f, 0.16107617f, 0.17154380f,
0.18269168f, 0.19456402f, 0.20720788f, 0.22067342f,
0.23501402f, 0.25028656f, 0.26655159f, 0.28387361f,
0.30232132f, 0.32196786f, 0.34289114f, 0.36517414f,
0.38890521f, 0.41417847f, 0.44109412f, 0.46975890f,
0.50028648f, 0.53279791f, 0.56742212f, 0.60429640f,
0.64356699f, 0.68538959f, 0.72993007f, 0.77736504f,
0.82788260f, 0.88168307f, 0.9389798f, 1.0f};
static Floor createInstance(BitInputStream source, SetupHeader header) throws VorbisFormatException, IOException {
int type=source.getInt(16);
switch(type) {
case 0:
return new Floor0(source, header);
case 1:
return new Floor1(source, header);
default:
throw new VorbisFormatException("Floor type "+type+" is not supported.");
}
}
abstract int getType();
abstract Floor decodeFloor(VorbisStream vorbis, BitInputStream source) throws VorbisFormatException, IOException;
abstract void computeFloor(float[] vector);
}

View File

@ -1,68 +0,0 @@
/*
* $ProjectName$
* $ProjectRevision$
* -----------------------------------------------------------
* $Id: Floor0.java,v 1.2 2003/03/16 01:11:12 jarnbjo Exp $
* -----------------------------------------------------------
*
* $Author: jarnbjo $
*
* Description:
*
* Copyright 2002-2003 Tor-Einar Jarnbjo
* -----------------------------------------------------------
*
* Change History
* -----------------------------------------------------------
* $Log: Floor0.java,v $
* Revision 1.2 2003/03/16 01:11:12 jarnbjo
* no message
*
*
*/
package de.jarnbjo.vorbis;
import java.io.IOException;
import de.jarnbjo.util.io.BitInputStream;
class Floor0 extends Floor {
private int order, rate, barkMapSize, amplitudeBits, amplitudeOffset;
private int bookList[];
protected Floor0(BitInputStream source, SetupHeader header) throws VorbisFormatException, IOException {
order=source.getInt(8);
rate=source.getInt(16);
barkMapSize=source.getInt(16);
amplitudeBits=source.getInt(6);
amplitudeOffset=source.getInt(8);
int bookCount=source.getInt(4)+1;
bookList=new int[bookCount];
for(int i=0; i<bookList.length; i++) {
bookList[i]=source.getInt(8);
if(bookList[i]>header.getCodeBooks().length) {
throw new VorbisFormatException("A floor0_book_list entry is higher than the code book count.");
}
}
}
protected int getType() {
return 0;
}
protected Floor decodeFloor(VorbisStream vorbis, BitInputStream source) throws VorbisFormatException, IOException {
/** @todo implement */
throw new UnsupportedOperationException();
}
protected void computeFloor(float[] vector) {
/** @todo implement */
throw new UnsupportedOperationException();
}
}

View File

@ -1,318 +0,0 @@
/*
* $ProjectName$
* $ProjectRevision$
* -----------------------------------------------------------
* $Id: Floor1.java,v 1.2 2003/03/16 01:11:12 jarnbjo Exp $multip
* -----------------------------------------------------------
*
* $Author: jarnbjo $
*
* Description:
*
* Copyright 2002-2003 Tor-Einar Jarnbjo
* -----------------------------------------------------------
*
* Change History
* -----------------------------------------------------------
* $Log: Floor1.java,v $
* Revision 1.2 2003/03/16 01:11:12 jarnbjo
* no message
*
*
*/
package de.jarnbjo.vorbis;
import java.io.IOException;
import java.util.*;
import de.jarnbjo.util.io.BitInputStream;
class Floor1 extends Floor implements Cloneable {
private int[] partitionClassList;
private int maximumClass, multiplier, rangeBits;
private int[] classDimensions;
private int[] classSubclasses;
private int[] classMasterbooks;
private int[][] subclassBooks;
private int[] xList;
private int[] yList;
private int[] lowNeighbours, highNeighbours;
//private boolean[] step2Flags;
private static final int[] RANGES = {256, 128, 86, 64};
private Floor1() {
}
protected Floor1(BitInputStream source, SetupHeader header) throws VorbisFormatException, IOException {
maximumClass=-1;
int partitions=source.getInt(5);
partitionClassList=new int[partitions];
for(int i=0; i<partitionClassList.length; i++) {
partitionClassList[i]=source.getInt(4);
if(partitionClassList[i]>maximumClass) {
maximumClass=partitionClassList[i];
}
}
classDimensions=new int[maximumClass+1];
classSubclasses=new int[maximumClass+1];
classMasterbooks=new int[maximumClass+1];
subclassBooks=new int[maximumClass+1][];
int xListLength=2;
for(int i=0; i<=maximumClass; i++) {
classDimensions[i]=source.getInt(3)+1;
xListLength+=classDimensions[i];
classSubclasses[i]=source.getInt(2);
if(classDimensions[i] > header.getCodeBooks().length ||
classSubclasses[i] > header.getCodeBooks().length) {
throw new VorbisFormatException("There is a class dimension or class subclasses entry higher than the number of codebooks in the setup header.");
}
if(classSubclasses[i]!=0) {
classMasterbooks[i]=source.getInt(8);
}
subclassBooks[i]=new int[1<<classSubclasses[i]];
for(int j=0; j<subclassBooks[i].length; j++) {
subclassBooks[i][j]=source.getInt(8)-1;
}
}
multiplier=source.getInt(2)+1;
rangeBits=source.getInt(4);
//System.out.println("multiplier: "+multiplier);
//System.out.println("rangeBits: "+rangeBits);
//System.out.println("xListLength: "+xListLength);
int floorValues=0;
ArrayList alXList=new ArrayList();
alXList.add(new Integer(0));
alXList.add(new Integer(1<<rangeBits));
//System.out.println("partitions: "+partitions);
//System.out.println("classDimensions.length: "+classDimensions.length);
for(int i=0; i<partitions; i++) {
for(int j=0; j<classDimensions[partitionClassList[i]]; j++) {
alXList.add(new Integer(source.getInt(rangeBits)));
}
}
xList=new int[alXList.size()];
lowNeighbours=new int[xList.length];
highNeighbours=new int[xList.length];
Iterator iter=alXList.iterator();
for(int i=0; i<xList.length; i++) {
xList[i]=((Integer)iter.next()).intValue();
}
for(int i=0; i<xList.length; i++) {
lowNeighbours[i]=Util.lowNeighbour(xList, i);
highNeighbours[i]=Util.highNeighbour(xList, i);
}
}
protected int getType() {
return 1;
}
protected Floor decodeFloor(VorbisStream vorbis, BitInputStream source) throws VorbisFormatException, IOException {
//System.out.println("decodeFloor");
if(!source.getBit()) {
//System.out.println("null");
return null;
}
Floor1 clone=(Floor1)clone();
clone.yList=new int[xList.length];
int range=RANGES[multiplier-1];
clone.yList[0]=source.getInt(Util.ilog(range-1));
clone.yList[1]=source.getInt(Util.ilog(range-1));
int offset=2;
for(int i=0; i<partitionClassList.length; i++) {
int cls=partitionClassList[i];
int cdim=classDimensions[cls];
int cbits=classSubclasses[cls];
int csub=(1<<cbits)-1;
int cval=0;
if(cbits>0) {
cval=source.getInt(vorbis.getSetupHeader().getCodeBooks()[classMasterbooks[cls]].getHuffmanRoot());
//cval=vorbis.getSetupHeader().getCodeBooks()[classMasterbooks[cls]].readInt(source);
//System.out.println("cval: "+cval);
}
//System.out.println("0: "+cls+" "+cdim+" "+cbits+" "+csub+" "+cval);
for(int j=0; j<cdim; j++) {
//System.out.println("a: "+cls+" "+cval+" "+csub);
int book=subclassBooks[cls][cval&csub];
cval>>>=cbits;
if(book>=0) {
clone.yList[j+offset]=source.getInt(vorbis.getSetupHeader().getCodeBooks()[book].getHuffmanRoot());
//clone.yList[j+offset]=vorbis.getSetupHeader().getCodeBooks()[book].readInt(source);
//System.out.println("b: "+(j+offset)+" "+book+" "+clone.yList[j+offset]);
//System.out.println("");
}
else {
clone.yList[j+offset]=0;
}
}
offset+=cdim;
}
//System.out.println("");
//for(int i=0; i<clone.xList.length; i++) {
// System.out.println(i+" = "+clone.xList[i]);
//}
//System.out.println("");
//for(int i=0; i<clone.yList.length; i++) {
// System.out.println(i+" = "+clone.yList[i]);
//}
//System.out.println("offset: "+offset);
//System.out.println("yList.length: "+clone.yList.length);
//System.exit(0);
return clone;
}
protected void computeFloor(final float[] vector) {
int n=vector.length;
final int values=xList.length;
final boolean[] step2Flags=new boolean[values];
final int range=RANGES[multiplier-1];
for(int i=2; i<values; i++) {
final int lowNeighbourOffset=lowNeighbours[i];//Util.lowNeighbour(xList, i);
final int highNeighbourOffset=highNeighbours[i];//Util.highNeighbour(xList, i);
final int predicted=Util.renderPoint(
xList[lowNeighbourOffset], xList[highNeighbourOffset],
yList[lowNeighbourOffset], yList[highNeighbourOffset],
xList[i]);
final int val=yList[i];
final int highRoom=range-predicted;
final int lowRoom=predicted;
final int room=highRoom<lowRoom?highRoom*2:lowRoom*2;
if(val!=0) {
step2Flags[lowNeighbourOffset]=true;
step2Flags[highNeighbourOffset]=true;
step2Flags[i]=true;
if(val>=room) {
yList[i]=highRoom>lowRoom?
val-lowRoom+predicted:
-val+highRoom+predicted-1;
}
else {
yList[i]=(val&1)==1?
predicted-((val+1)>>1):
predicted+(val>>1);
}
}
else {
step2Flags[i]=false;
yList[i]=predicted;
}
}
final int[] xList2=new int[values];
System.arraycopy(xList, 0, xList2, 0, values);
sort(xList2, yList, step2Flags);
int hx=0, hy=0, lx=0, ly=yList[0]*multiplier;
float[] vector2=new float[vector.length];
float[] vector3=new float[vector.length];
Arrays.fill(vector2, 1.0f);
System.arraycopy(vector, 0, vector3, 0, vector.length);
for(int i=1; i<values; i++) {
if(step2Flags[i]) {
hy=yList[i]*multiplier;
hx=xList2[i];
Util.renderLine(lx, ly, hx, hy, vector);
Util.renderLine(lx, ly, hx, hy, vector2);
lx=hx;
ly=hy;
}
}
final float r=DB_STATIC_TABLE[hy];
for(; hx<n/2; vector[hx++]=r);
}
public Object clone() {
Floor1 clone=new Floor1();
clone.classDimensions=classDimensions;
clone.classMasterbooks=classMasterbooks;
clone.classSubclasses=classSubclasses;
clone.maximumClass=maximumClass;
clone.multiplier=multiplier;
clone.partitionClassList=partitionClassList;
clone.rangeBits=rangeBits;
clone.subclassBooks=subclassBooks;
clone.xList=xList;
clone.yList=yList;
clone.lowNeighbours=lowNeighbours;
clone.highNeighbours=highNeighbours;
return clone;
}
private final static void sort(int x[], int y[], boolean b[]) {
int off=0;
int len=x.length;
int lim=len+off;
int itmp;
boolean btmp;
// Insertion sort on smallest arrays
for (int i=off; i<lim; i++) {
for (int j=i; j>off && x[j-1]>x[j]; j--) {
itmp=x[j];
x[j]=x[j-1];
x[j-1]=itmp;
itmp=y[j];
y[j]=y[j-1];
y[j-1]=itmp;
btmp=b[j];
b[j]=b[j-1];
b[j-1]=btmp;
//swap(x, j, j-1);
//swap(y, j, j-1);
//swap(b, j, j-1);
}
}
}
private final static void swap(int x[], int a, int b) {
int t = x[a];
x[a] = x[b];
x[b] = t;
}
private final static void swap(boolean x[], int a, int b) {
boolean t = x[a];
x[a] = x[b];
x[b] = t;
}
}

View File

@ -1,318 +0,0 @@
/*
* $ProjectName$
* $ProjectRevision$
* -----------------------------------------------------------
* $Id: Floor1.java,v 1.2 2003/03/16 01:11:12 jarnbjo Exp $
* -----------------------------------------------------------
*
* $Author: jarnbjo $
*
* Description:
*
* Copyright 2002-2003 Tor-Einar Jarnbjo
* -----------------------------------------------------------
*
* Change History
* -----------------------------------------------------------
* $Log: Floor1.java,v $
* Revision 1.2 2003/03/16 01:11:12 jarnbjo
* no message
*
*
*/
package de.jarnbjo.vorbis;
import java.io.IOException;
import java.util.*;
import de.jarnbjo.util.io.BitInputStream;
class Floor1 extends Floor implements Cloneable {
private int[] partitionClassList;
private int maximumClass, multiplier, rangeBits;
private int[] classDimensions;
private int[] classSubclasses;
private int[] classMasterbooks;
private int[][] subclassBooks;
private int[] xList;
private int[] yList;
private int[] lowNeighbours, highNeighbours;
//private boolean[] step2Flags;
private static final int[] RANGES = {256, 128, 86, 64};
private Floor1() {
}
protected Floor1(BitInputStream source, SetupHeader header) throws VorbisFormatException, IOException {
maximumClass=-1;
int partitions=source.getInt(5);
partitionClassList=new int[partitions];
for(int i=0; i<partitionClassList.length; i++) {
partitionClassList[i]=source.getInt(4);
if(partitionClassList[i]>maximumClass) {
maximumClass=partitionClassList[i];
}
}
classDimensions=new int[maximumClass+1];
classSubclasses=new int[maximumClass+1];
classMasterbooks=new int[maximumClass+1];
subclassBooks=new int[maximumClass+1][];
int xListLength=2;
for(int i=0; i<=maximumClass; i++) {
classDimensions[i]=source.getInt(3)+1;
xListLength+=classDimensions[i];
classSubclasses[i]=source.getInt(2);
if(classDimensions[i] > header.getCodeBooks().length ||
classSubclasses[i] > header.getCodeBooks().length) {
throw new VorbisFormatException("There is a class dimension or class subclasses entry higher than the number of codebooks in the setup header.");
}
if(classSubclasses[i]!=0) {
classMasterbooks[i]=source.getInt(8);
}
subclassBooks[i]=new int[1<<classSubclasses[i]];
for(int j=0; j<subclassBooks[i].length; j++) {
subclassBooks[i][j]=source.getInt(8)-1;
}
}
multiplier=source.getInt(2)+1;
rangeBits=source.getInt(4);
//System.out.println("multiplier: "+multiplier);
//System.out.println("rangeBits: "+rangeBits);
//System.out.println("xListLength: "+xListLength);
int floorValues=0;
ArrayList alXList=new ArrayList();
alXList.add(new Integer(0));
alXList.add(new Integer(1<<rangeBits));
//System.out.println("partitions: "+partitions);
//System.out.println("classDimensions.length: "+classDimensions.length);
for(int i=0; i<partitions; i++) {
for(int j=0; j<classDimensions[partitionClassList[i]]; j++) {
alXList.add(new Integer(source.getInt(rangeBits)));
}
}
xList=new int[alXList.size()];
lowNeighbours=new int[xList.length];
highNeighbours=new int[xList.length];
Iterator iter=alXList.iterator();
for(int i=0; i<xList.length; i++) {
xList[i]=((Integer)iter.next()).intValue();
}
for(int i=0; i<xList.length; i++) {
lowNeighbours[i]=Util.lowNeighbour(xList, i);
highNeighbours[i]=Util.highNeighbour(xList, i);
}
}
protected int getType() {
return 1;
}
protected Floor decodeFloor(VorbisStream vorbis, BitInputStream source) throws VorbisFormatException, IOException {
//System.out.println("decodeFloor");
if(!source.getBit()) {
//System.out.println("null");
return null;
}
Floor1 clone=(Floor1)clone();
clone.yList=new int[xList.length];
int range=RANGES[multiplier-1];
clone.yList[0]=source.getInt(Util.ilog(range-1));
clone.yList[1]=source.getInt(Util.ilog(range-1));
int offset=2;
for(int i=0; i<partitionClassList.length; i++) {
int cls=partitionClassList[i];
int cdim=classDimensions[cls];
int cbits=classSubclasses[cls];
int csub=(1<<cbits)-1;
int cval=0;
if(cbits>0) {
cval=source.getInt(vorbis.getSetupHeader().getCodeBooks()[classMasterbooks[cls]].getHuffmanRoot());
//cval=vorbis.getSetupHeader().getCodeBooks()[classMasterbooks[cls]].readInt(source);
//System.out.println("cval: "+cval);
}
//System.out.println("0: "+cls+" "+cdim+" "+cbits+" "+csub+" "+cval);
for(int j=0; j<cdim; j++) {
//System.out.println("a: "+cls+" "+cval+" "+csub);
int book=subclassBooks[cls][cval&csub];
cval>>>=cbits;
if(book>=0) {
clone.yList[j+offset]=source.getInt(vorbis.getSetupHeader().getCodeBooks()[book].getHuffmanRoot());
//clone.yList[j+offset]=vorbis.getSetupHeader().getCodeBooks()[book].readInt(source);
//System.out.println("b: "+(j+offset)+" "+book+" "+clone.yList[j+offset]);
//System.out.println("");
}
else {
clone.yList[j+offset]=0;
}
}
offset+=cdim;
}
//System.out.println("");
//for(int i=0; i<clone.xList.length; i++) {
// System.out.println(i+" = "+clone.xList[i]);
//}
//System.out.println("");
//for(int i=0; i<clone.yList.length; i++) {
// System.out.println(i+" = "+clone.yList[i]);
//}
//System.out.println("offset: "+offset);
//System.out.println("yList.length: "+clone.yList.length);
//System.exit(0);
return clone;
}
protected void computeFloor(final float[] vector) {
int n=vector.length;
final int values=xList.length;
final boolean[] step2Flags=new boolean[values];
final int range=RANGES[multiplier-1];
for(int i=2; i<values; i++) {
final int lowNeighbourOffset=lowNeighbours[i];//Util.lowNeighbour(xList, i);
final int highNeighbourOffset=highNeighbours[i];//Util.highNeighbour(xList, i);
final int predicted=Util.renderPoint(
xList[lowNeighbourOffset], xList[highNeighbourOffset],
yList[lowNeighbourOffset], yList[highNeighbourOffset],
xList[i]);
final int val=yList[i];
final int highRoom=range-predicted;
final int lowRoom=predicted;
final int room=highRoom<lowRoom?highRoom*2:lowRoom*2;
if(val!=0) {
step2Flags[lowNeighbourOffset]=true;
step2Flags[highNeighbourOffset]=true;
step2Flags[i]=true;
if(val>=room) {
yList[i]=highRoom>lowRoom?
val-lowRoom+predicted:
-val+highRoom+predicted-1;
}
else {
yList[i]=(val&1)==1?
predicted-((val+1)>>1):
predicted+(val>>1);
}
}
else {
step2Flags[i]=false;
yList[i]=predicted;
}
}
final int[] xList2=new int[values];
System.arraycopy(xList, 0, xList2, 0, values);
sort(xList2, yList, step2Flags);
int hx=0, hy=0, lx=0, ly=yList[0]*multiplier;
float[] vector2=new float[vector.length];
float[] vector3=new float[vector.length];
Arrays.fill(vector2, 1.0f);
System.arraycopy(vector, 0, vector3, 0, vector.length);
for(int i=1; i<values; i++) {
if(step2Flags[i]) {
hy=yList[i]*multiplier;
hx=xList2[i];
Util.renderLine(lx, ly, hx, hy, vector);
Util.renderLine(lx, ly, hx, hy, vector2);
lx=hx;
ly=hy;
}
}
final float r=DB_STATIC_TABLE[hy];
for(; hx<n/2; vector[hx++]=r);
}
public Object clone() {
Floor1 clone=new Floor1();
clone.classDimensions=classDimensions;
clone.classMasterbooks=classMasterbooks;
clone.classSubclasses=classSubclasses;
clone.maximumClass=maximumClass;
clone.multiplier=multiplier;
clone.partitionClassList=partitionClassList;
clone.rangeBits=rangeBits;
clone.subclassBooks=subclassBooks;
clone.xList=xList;
clone.yList=yList;
clone.lowNeighbours=lowNeighbours;
clone.highNeighbours=highNeighbours;
return clone;
}
private final static void sort(int x[], int y[], boolean b[]) {
int off=0;
int len=x.length;
int lim=len+off;
int itmp;
boolean btmp;
// Insertion sort on smallest arrays
for (int i=off; i<lim; i++) {
for (int j=i; j>off && x[j-1]>x[j]; j--) {
itmp=x[j];
x[j]=x[j-1];
x[j-1]=itmp;
itmp=y[j];
y[j]=y[j-1];
y[j-1]=itmp;
btmp=b[j];
b[j]=b[j-1];
b[j-1]=btmp;
//swap(x, j, j-1);
//swap(y, j, j-1);
//swap(b, j, j-1);
}
}
}
private final static void swap(int x[], int a, int b) {
int t = x[a];
x[a] = x[b];
x[b] = t;
}
private final static void swap(boolean x[], int a, int b) {
boolean t = x[a];
x[a] = x[b];
x[b] = t;
}
}

View File

@ -1,116 +0,0 @@
/*
* $ProjectName$
* $ProjectRevision$
* -----------------------------------------------------------
* $Id: IdentificationHeader.java,v 1.3 2003/03/31 00:20:16 jarnbjo Exp $
* -----------------------------------------------------------
*
* $Author: jarnbjo $
*
* Description:
*
* Copyright 2002-2003 Tor-Einar Jarnbjo
* -----------------------------------------------------------
*
* Change History
* -----------------------------------------------------------
* $Log: IdentificationHeader.java,v $
* Revision 1.3 2003/03/31 00:20:16 jarnbjo
* no message
*
* Revision 1.2 2003/03/16 01:11:12 jarnbjo
* no message
*
*
*/
package de.jarnbjo.vorbis;
import java.io.*;
import de.jarnbjo.util.io.BitInputStream;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
/**
*/
public class IdentificationHeader {
private int version, channels, sampleRate, bitrateMaximum, bitrateNominal, bitrateMinimum, blockSize0, blockSize1;
private boolean framingFlag;
private MdctFloat[] mdct=new MdctFloat[2];
//private MdctLong[] mdctInt=new MdctLong[2];
private static final long HEADER = 0x736962726f76L; // 'vorbis'
public IdentificationHeader(BitInputStream source) throws VorbisFormatException, IOException {
//equalizer=new Equalizer();
//equalizer.pack();
//equalizer.show();
long leading=source.getLong(48);
if(leading!=HEADER) {
throw new VorbisFormatException("The identification header has an illegal leading.");
}
version=source.getInt(32);
channels=source.getInt(8);
sampleRate=source.getInt(32);
bitrateMaximum=source.getInt(32);
bitrateNominal=source.getInt(32);
bitrateMinimum=source.getInt(32);
int bs=source.getInt(8);
blockSize0=1<<(bs&0xf);
blockSize1=1<<(bs>>4);
mdct[0]=new MdctFloat(blockSize0);
mdct[1]=new MdctFloat(blockSize1);
//mdctInt[0]=new MdctLong(blockSize0);
//mdctInt[1]=new MdctLong(blockSize1);
framingFlag=source.getInt(8)!=0;
}
public int getSampleRate() {
return sampleRate;
}
public int getMaximumBitrate() {
return bitrateMaximum;
}
public int getNominalBitrate() {
return bitrateNominal;
}
public int getMinimumBitrate() {
return bitrateMinimum;
}
public int getChannels() {
return channels;
}
public int getBlockSize0() {
return blockSize0;
}
public int getBlockSize1() {
return blockSize1;
}
protected MdctFloat getMdct0() {
return mdct[0];
}
protected MdctFloat getMdct1() {
return mdct[1];
}
public int getVersion() {
return version;
}
}

View File

@ -1,53 +0,0 @@
/*
* $ProjectName$
* $ProjectRevision$
* -----------------------------------------------------------
* $Id: Mapping.java,v 1.2 2003/03/16 01:11:12 jarnbjo Exp $
* -----------------------------------------------------------
*
* $Author: jarnbjo $
*
* Description:
*
* Copyright 2002-2003 Tor-Einar Jarnbjo
* -----------------------------------------------------------
*
* Change History
* -----------------------------------------------------------
* $Log: Mapping.java,v $
* Revision 1.2 2003/03/16 01:11:12 jarnbjo
* no message
*
*
*/
package de.jarnbjo.vorbis;
import java.io.IOException;
import de.jarnbjo.util.io.BitInputStream;
abstract class Mapping {
protected static Mapping createInstance(VorbisStream vorbis, BitInputStream source, SetupHeader header) throws VorbisFormatException, IOException {
int type=source.getInt(16);
switch(type) {
case 0:
//System.out.println("mapping type 0");
return new Mapping0(vorbis, source, header);
default:
throw new VorbisFormatException("Mapping type "+type+" is not supported.");
}
}
protected abstract int getType();
protected abstract int[] getAngles();
protected abstract int[] getMagnitudes() ;
protected abstract int[] getMux();
protected abstract int[] getSubmapFloors();
protected abstract int[] getSubmapResidues();
protected abstract int getCouplingSteps();
protected abstract int getSubmaps();
}

View File

@ -1,140 +0,0 @@
/*
* $ProjectName$
* $ProjectRevision$
* -----------------------------------------------------------
* $Id: Mapping0.java,v 1.2 2003/03/16 01:11:12 jarnbjo Exp $
* -----------------------------------------------------------
*
* $Author: jarnbjo $
*
* Description:
*
* Copyright 2002-2003 Tor-Einar Jarnbjo
* -----------------------------------------------------------
*
* Change History
* -----------------------------------------------------------
* $Log: Mapping0.java,v $
* Revision 1.2 2003/03/16 01:11:12 jarnbjo
* no message
*
*
*/
package de.jarnbjo.vorbis;
import java.io.IOException;
import de.jarnbjo.util.io.BitInputStream;
class Mapping0 extends Mapping {
private int[] magnitudes, angles, mux, submapFloors, submapResidues;
protected Mapping0(VorbisStream vorbis, BitInputStream source, SetupHeader header) throws VorbisFormatException, IOException {
int submaps=1;
if(source.getBit()) {
submaps=source.getInt(4)+1;
}
//System.out.println("submaps: "+submaps);
int channels=vorbis.getIdentificationHeader().getChannels();
int ilogChannels=Util.ilog(channels-1);
//System.out.println("ilogChannels: "+ilogChannels);
if(source.getBit()) {
int couplingSteps=source.getInt(8)+1;
magnitudes=new int[couplingSteps];
angles=new int[couplingSteps];
for(int i=0; i<couplingSteps; i++) {
magnitudes[i]=source.getInt(ilogChannels);
angles[i]=source.getInt(ilogChannels);
if(magnitudes[i]==angles[i] || magnitudes[i]>=channels || angles[i]>=channels) {
System.err.println(magnitudes[i]);
System.err.println(angles[i]);
throw new VorbisFormatException("The channel magnitude and/or angle mismatch.");
}
}
}
else {
magnitudes=new int[0];
angles=new int[0];
}
if(source.getInt(2)!=0) {
throw new VorbisFormatException("A reserved mapping field has an invalid value.");
}
mux=new int[channels];
if(submaps>1) {
for(int i=0; i<channels; i++) {
mux[i]=source.getInt(4);
if(mux[i]>submaps) {
throw new VorbisFormatException("A mapping mux value is higher than the number of submaps");
}
}
}
else {
for(int i=0; i<channels; i++) {
mux[i]=0;
}
}
submapFloors=new int[submaps];
submapResidues=new int[submaps];
int floorCount=header.getFloors().length;
int residueCount=header.getResidues().length;
for(int i=0; i<submaps; i++) {
source.getInt(8); // discard time placeholder
submapFloors[i]=source.getInt(8);
submapResidues[i]=source.getInt(8);
if(submapFloors[i]>floorCount) {
throw new VorbisFormatException("A mapping floor value is higher than the number of floors.");
}
if(submapResidues[i]>residueCount) {
throw new VorbisFormatException("A mapping residue value is higher than the number of residues.");
}
}
}
protected int getType() {
return 0;
}
protected int[] getAngles() {
return angles;
}
protected int[] getMagnitudes() {
return magnitudes;
}
protected int[] getMux() {
return mux;
}
protected int[] getSubmapFloors() {
return submapFloors;
}
protected int[] getSubmapResidues() {
return submapResidues;
}
protected int getCouplingSteps() {
return angles.length;
}
protected int getSubmaps() {
return submapFloors.length;
}
}

View File

@ -1,312 +0,0 @@
/*
* $ProjectName$
* $ProjectRevision$
* -----------------------------------------------------------
* $Id: MdctFloat.java,v 1.3 2003/04/10 19:49:04 jarnbjo Exp $
* -----------------------------------------------------------
*
* $Author: jarnbjo $
*
* Description:
*
* Copyright 2002-2003 Tor-Einar Jarnbjo
* -----------------------------------------------------------
*
* Change History
* -----------------------------------------------------------
* $Log: MdctFloat.java,v $
* Revision 1.3 2003/04/10 19:49:04 jarnbjo
* no message
*
* Revision 1.2 2003/03/16 01:11:12 jarnbjo
* no message
*
*
*/
package de.jarnbjo.vorbis;
class MdctFloat {
static private final float cPI3_8=0.38268343236508977175f;
static private final float cPI2_8=0.70710678118654752441f;
static private final float cPI1_8=0.92387953251128675613f;
private int n;
private int log2n;
private float[] trig;
private int[] bitrev;
private float[] equalizer;
private float scale;
private int itmp1, itmp2, itmp3, itmp4, itmp5, itmp6, itmp7, itmp8, itmp9;
private float dtmp1, dtmp2, dtmp3, dtmp4, dtmp5, dtmp6, dtmp7, dtmp8, dtmp9;
protected MdctFloat(int n) {
bitrev=new int[n/4];
trig=new float[n+n/4];
int n2=n>>>1;
log2n=(int)Math.rint(Math.log(n)/Math.log(2));
this.n=n;
int AE=0;
int AO=1;
int BE=AE+n/2;
int BO=BE+1;
int CE=BE+n/2;
int CO=CE+1;
// trig lookups...
for(int i=0;i<n/4;i++){
trig[AE+i*2]=(float)Math.cos((Math.PI/n)*(4*i));
trig[AO+i*2]=(float)-Math.sin((Math.PI/n)*(4*i));
trig[BE+i*2]=(float)Math.cos((Math.PI/(2*n))*(2*i+1));
trig[BO+i*2]=(float)Math.sin((Math.PI/(2*n))*(2*i+1));
}
for(int i=0;i<n/8;i++){
trig[CE+i*2]=(float)Math.cos((Math.PI/n)*(4*i+2));
trig[CO+i*2]=(float)-Math.sin((Math.PI/n)*(4*i+2));
}
{
int mask=(1<<(log2n-1))-1;
int msb=1<<(log2n-2);
for(int i=0;i<n/8;i++){
int acc=0;
for(int j=0;msb>>>j!=0;j++)
if(((msb>>>j)&i)!=0)acc|=1<<j;
bitrev[i*2]=((~acc)&mask);
// bitrev[i*2]=((~acc)&mask)-1;
bitrev[i*2+1]=acc;
}
}
scale=4.f/n;
}
//void clear(){
//}
//void forward(float[] in, float[] out){
//}
private float[] _x=new float[1024];
private float[] _w=new float[1024];
protected void setEqualizer(float[] equalizer) {
this.equalizer=equalizer;
}
protected float[] getEqualizer() {
return equalizer;
}
protected synchronized void imdct(final float[] frq, final float[] window, final int[] pcm) {//, float[] out){
float[] in=frq;//, out=buf;
if(_x.length<n/2){_x=new float[n/2];}
if(_w.length<n/2){_w=new float[n/2];}
final float[] x=_x;
final float[] w=_w;
int n2=n>>1;
int n4=n>>2;
int n8=n>>3;
if(equalizer!=null) {
for(int i=0; i<n; i++) {
frq[i]*=equalizer[i];
}
}
// rotate + step 1
{
int inO=-1;
int xO=0;
int A=n2;
int i;
for(i=0;i<n8;i++) {
dtmp1=in[inO+=2];
dtmp2=in[inO+=2];
dtmp3=trig[--A];
dtmp4=trig[--A];
x[xO++]=-dtmp2*dtmp3 - dtmp1*dtmp4;
x[xO++]= dtmp1*dtmp3 - dtmp2*dtmp4;
//A-=2;
//x[xO++]=-in[inO+2]*trig[A+1] - in[inO]*trig[A];
//x[xO++]= in[inO]*trig[A+1] - in[inO+2]*trig[A];
//inO+=4;
}
inO=n2;//-4;
for(i=0;i<n8;i++) {
dtmp1=in[inO-=2];
dtmp2=in[inO-=2];
dtmp3=trig[--A];
dtmp4=trig[--A];
x[xO++]=dtmp2*dtmp3 + dtmp1*dtmp4;
x[xO++]=dtmp2*dtmp4 - dtmp1*dtmp3;
//A-=2;
//x[xO++]=in[inO]*trig[A+1] + in[inO+2]*trig[A];
//x[xO++]=in[inO]*trig[A] - in[inO+2]*trig[A+1];
//inO-=4;
}
}
float[] xxx=kernel(x,w,n,n2,n4,n8);
int xx=0;
// step 8
{
int B=n2;
int o1=n4,o2=o1-1;
int o3=n4+n2,o4=o3-1;
for(int i=0;i<n4;i++){
dtmp1=xxx[xx++];
dtmp2=xxx[xx++];
dtmp3=trig[B++];
dtmp4=trig[B++];
float temp1= (dtmp1* dtmp4 - dtmp2 * dtmp3);
float temp2=-(dtmp1 * dtmp3 + dtmp2 * dtmp4);
/*
float temp1= (xxx[xx] * trig[B+1] - xxx[xx+1] * trig[B]);//*32767.0f;
float temp2=-(xxx[xx] * trig[B] + xxx[xx+1] * trig[B+1]);//*32767.0f;
*/
//if(temp1>32767.0f) temp1=32767.0f;
//if(temp1<-32768.0f) temp1=-32768.0f;
//if(temp2>32767.0f) temp2=32767.0f;
//if(temp2<-32768.0f) temp2=-32768.0f;
pcm[o1]=(int)(-temp1*window[o1]);
pcm[o2]=(int)( temp1*window[o2]);
pcm[o3]=(int)( temp2*window[o3]);
pcm[o4]=(int)( temp2*window[o4]);
o1++;
o2--;
o3++;
o4--;
//xx+=2;
//B+=2;
}
}
}
private float[] kernel(float[] x, float[] w,
int n, int n2, int n4, int n8){
// step 2
int xA=n4;
int xB=0;
int w2=n4;
int A=n2;
for(int i=0;i<n4;){
float x0=x[xA] - x[xB];
float x1;
w[w2+i]=x[xA++]+x[xB++];
x1=x[xA]-x[xB];
A-=4;
w[i++]= x0 * trig[A] + x1 * trig[A+1];
w[i]= x1 * trig[A] - x0 * trig[A+1];
w[w2+i]=x[xA++]+x[xB++];
i++;
}
// step 3
{
for(int i=0;i<log2n-3;i++){
int k0=n>>>(i+2);
int k1=1<<(i+3);
int wbase=n2-2;
A=0;
float[] temp;
for(int r=0;r<(k0>>>2);r++){
int w1=wbase;
w2=w1-(k0>>1);
float AEv= trig[A],wA;
float AOv= trig[A+1],wB;
wbase-=2;
k0++;
for(int s=0;s<(2<<i);s++){
dtmp1=w[w1];
dtmp2=w[w2];
wB=dtmp1-dtmp2;
x[w1]=dtmp1+dtmp2;
dtmp1=w[++w1];
dtmp2=w[++w2];
wA=dtmp1-dtmp2;
x[w1]=dtmp1+dtmp2;
x[w2] =wA*AEv - wB*AOv;
x[w2-1]=wB*AEv + wA*AOv;
/*
wB =w[w1] -w[w2];
x[w1] =w[w1] +w[w2];
wA =w[++w1] -w[++w2];
x[w1] =w[w1] +w[w2];
x[w2] =wA*AEv - wB*AOv;
x[w2-1]=wB*AEv + wA*AOv;
*/
w1-=k0;
w2-=k0;
}
k0--;
A+=k1;
}
temp=w;
w=x;
x=temp;
}
}
// step 4, 5, 6, 7
{
int C=n;
int bit=0;
int x1=0;
int x2=n2-1;
for(int i=0;i<n8;i++) {
int t1=bitrev[bit++];
int t2=bitrev[bit++];
float wA=w[t1]-w[t2+1];
float wB=w[t1-1]+w[t2];
float wC=w[t1]+w[t2+1];
float wD=w[t1-1]-w[t2];
float wACE=wA* trig[C];
float wBCE=wB* trig[C++];
float wACO=wA* trig[C];
float wBCO=wB* trig[C++];
x[x1++]=( wC+wACO+wBCE)*16383.0f;
x[x2--]=(-wD+wBCO-wACE)*16383.0f;
x[x1++]=( wD+wBCO-wACE)*16383.0f;
x[x2--]=( wC-wACO-wBCE)*16383.0f;
}
}
return x;
}
}

View File

@ -1,69 +0,0 @@
/*
* $ProjectName$
* $ProjectRevision$
* -----------------------------------------------------------
* $Id: Mode.java,v 1.2 2003/03/16 01:11:12 jarnbjo Exp $
* -----------------------------------------------------------
*
* $Author: jarnbjo $
*
* Description:
*
* Copyright 2002-2003 Tor-Einar Jarnbjo
* -----------------------------------------------------------
*
* Change History
* -----------------------------------------------------------
* $Log: Mode.java,v $
* Revision 1.2 2003/03/16 01:11:12 jarnbjo
* no message
*
*
*/
package de.jarnbjo.vorbis;
import java.io.*;
import de.jarnbjo.util.io.*;
class Mode {
private boolean blockFlag;
private int windowType, transformType, mapping;
protected Mode(BitInputStream source, SetupHeader header) throws VorbisFormatException, IOException {
blockFlag=source.getBit();
windowType=source.getInt(16);
transformType=source.getInt(16);
mapping=source.getInt(8);
if(windowType!=0) {
throw new VorbisFormatException("Window type = "+windowType+", != 0");
}
if(transformType!=0) {
throw new VorbisFormatException("Transform type = "+transformType+", != 0");
}
if(mapping>header.getMappings().length) {
throw new VorbisFormatException("Mode mapping number is higher than total number of mappings.");
}
}
protected boolean getBlockFlag() {
return blockFlag;
}
protected int getWindowType() {
return windowType;
}
protected int getTransformType() {
return transformType;
}
protected int getMapping() {
return mapping;
}
}

View File

@ -1,254 +0,0 @@
/*
* $ProjectName$
* $ProjectRevision$
* -----------------------------------------------------------
* $Id: Residue.java,v 1.3 2003/04/04 08:33:02 jarnbjo Exp $
* -----------------------------------------------------------
*
* $Author: jarnbjo $
*
* Description:
*
* Copyright 2002-2003 Tor-Einar Jarnbjo
* -----------------------------------------------------------
*
* Change History
* -----------------------------------------------------------
* $Log: Residue.java,v $
* Revision 1.3 2003/04/04 08:33:02 jarnbjo
* no message
*
* Revision 1.2 2003/03/16 01:11:12 jarnbjo
* no message
*
*
*/
package de.jarnbjo.vorbis;
import java.io.IOException;
import java.util.HashMap;
import de.jarnbjo.util.io.*;
abstract class Residue {
protected int begin, end;
protected int partitionSize; // grouping
protected int classifications; // partitions
protected int classBook; // groupbook
protected int[] cascade; // secondstages
protected int[][] books;
protected HashMap looks=new HashMap();
protected Residue() {
}
protected Residue(BitInputStream source, SetupHeader header) throws VorbisFormatException, IOException {
begin=source.getInt(24);
end=source.getInt(24);
partitionSize=source.getInt(24)+1;
classifications=source.getInt(6)+1;
classBook=source.getInt(8);
cascade=new int[classifications];
int acc=0;
for(int i=0; i<classifications; i++) {
int highBits=0, lowBits=0;
lowBits=source.getInt(3);
if(source.getBit()) {
highBits=source.getInt(5);
}
cascade[i]=(highBits<<3)|lowBits;
acc+=Util.icount(cascade[i]);
}
books=new int[classifications][8];
for(int i=0; i<classifications; i++) {
for(int j=0; j<8; j++) {
if((cascade[i]&(1<<j))!=0) {
books[i][j]=source.getInt(8);
if(books[i][j]>header.getCodeBooks().length) {
throw new VorbisFormatException("Reference to invalid codebook entry in residue header.");
}
}
}
}
}
protected static Residue createInstance(BitInputStream source, SetupHeader header) throws VorbisFormatException, IOException {
int type=source.getInt(16);
switch(type) {
case 0:
//System.out.println("residue type 0");
return new Residue0(source, header);
case 1:
//System.out.println("residue type 1");
return new Residue2(source, header);
case 2:
//System.out.println("residue type 2");
return new Residue2(source, header);
default:
throw new VorbisFormatException("Residue type "+type+" is not supported.");
}
}
protected abstract int getType();
protected abstract void decodeResidue(VorbisStream vorbis, BitInputStream source, Mode mode, int ch, boolean[] doNotDecodeFlags, float[][] vectors) throws VorbisFormatException, IOException;
//public abstract double[][] getDecodedVectors();
protected int getBegin() {
return begin;
}
protected int getEnd() {
return end;
}
protected int getPartitionSize() {
return partitionSize;
}
protected int getClassifications() {
return classifications;
}
protected int getClassBook() {
return classBook;
}
protected int[] getCascade() {
return cascade;
}
protected int[][] getBooks() {
return books;
}
protected final void fill(Residue clone) {
clone.begin=begin;
clone.books=books;
clone.cascade=cascade;
clone.classBook=classBook;
clone.classifications=classifications;
clone.end=end;
clone.partitionSize=partitionSize;
}
protected Look getLook(VorbisStream source, Mode key) {
//return new Look(source, key);
Look look=(Look)looks.get(key);
if(look==null) {
look=new Look(source, key);
looks.put(key, look);
}
return look;
}
class Look {
int map;
int parts;
int stages;
CodeBook[] fullbooks;
CodeBook phrasebook;
int[][] partbooks;
int partvals;
int[][] decodemap;
int postbits;
int phrasebits;
int frames;
protected Look (VorbisStream source, Mode mode) {
int dim=0, acc=0, maxstage=0;
map=mode.getMapping();
parts=Residue.this.getClassifications();
fullbooks=source.getSetupHeader().getCodeBooks();
phrasebook=fullbooks[Residue.this.getClassBook()];
dim=phrasebook.getDimensions();
partbooks=new int[parts][];
for(int j=0;j<parts;j++) {
int stages=Util.ilog(Residue.this.getCascade()[j]);
if(stages!=0) {
if(stages>maxstage) {
maxstage=stages;
}
partbooks[j]=new int[stages];
for(int k=0; k<stages; k++){
if((Residue.this.getCascade()[j]&(1<<k))!=0){
partbooks[j][k]=Residue.this.getBooks()[j][k];
}
}
}
}
partvals=(int)Math.rint(Math.pow(parts, dim));
stages=maxstage;
decodemap=new int[partvals][];
for(int j=0;j<partvals;j++){
int val=j;
int mult=partvals/parts;
decodemap[j]=new int[dim];
for(int k=0;k<dim;k++){
int deco=val/mult;
val-=deco*mult;
mult/=parts;
decodemap[j][k]=deco;
}
}
}
protected int[][] getDecodeMap() {
return decodemap;
}
protected int getFrames() {
return frames;
}
protected int getMap() {
return map;
}
protected int[][] getPartBooks() {
return partbooks;
}
protected int getParts() {
return parts;
}
protected int getPartVals() {
return partvals;
}
protected int getPhraseBits() {
return phrasebits;
}
protected CodeBook getPhraseBook() {
return phrasebook;
}
protected int getPostBits() {
return postbits;
}
protected int getStages() {
return stages;
}
}
}

View File

@ -1,45 +0,0 @@
/*
* $ProjectName$
* $ProjectRevision$
* -----------------------------------------------------------
* $Id: Residue0.java,v 1.2 2003/03/16 01:11:12 jarnbjo Exp $
* -----------------------------------------------------------
*
* $Author: jarnbjo $
*
* Description:
*
* Copyright 2002-2003 Tor-Einar Jarnbjo
* -----------------------------------------------------------
*
* Change History
* -----------------------------------------------------------
* $Log: Residue0.java,v $
* Revision 1.2 2003/03/16 01:11:12 jarnbjo
* no message
*
*
*/
package de.jarnbjo.vorbis;
import java.io.IOException;
import java.util.*;
import de.jarnbjo.util.io.BitInputStream;
class Residue0 extends Residue {
protected Residue0(BitInputStream source, SetupHeader header) throws VorbisFormatException, IOException {
super(source, header);
}
protected int getType() {
return 0;
}
protected void decodeResidue(VorbisStream vorbis, BitInputStream source, Mode mode, int ch, boolean[] doNotDecodeFlags, float[][] vectors) throws VorbisFormatException, IOException {
/** @todo implement */
throw new UnsupportedOperationException();
}
}

View File

@ -1,47 +0,0 @@
/*
* $ProjectName$
* $ProjectRevision$
* -----------------------------------------------------------
* $Id: Residue1.java,v 1.2 2003/03/16 01:11:12 jarnbjo Exp $
* -----------------------------------------------------------
*
* $Author: jarnbjo $
*
* Description:
*
* Copyright 2002-2003 Tor-Einar Jarnbjo
* -----------------------------------------------------------
*
* Change History
* -----------------------------------------------------------
* $Log: Residue1.java,v $
* Revision 1.2 2003/03/16 01:11:12 jarnbjo
* no message
*
*
*/
package de.jarnbjo.vorbis;
import java.io.IOException;
import java.util.*;
import de.jarnbjo.util.io.BitInputStream;
class Residue1 extends Residue {
protected Residue1(BitInputStream source, SetupHeader header) throws VorbisFormatException, IOException {
super(source, header);
}
protected int getType() {
return 1;
}
protected void decodeResidue(VorbisStream vorbis, BitInputStream source, Mode mode, int ch, boolean[] doNotDecodeFlags, float[][] vectors) throws VorbisFormatException, IOException {
/** @todo implement */
throw new UnsupportedOperationException();
}
}

View File

@ -1,115 +0,0 @@
/*
* $ProjectName$
* $ProjectRevision$
* -----------------------------------------------------------
* $Id: Residue2.java,v 1.2 2003/03/16 01:11:12 jarnbjo Exp $
* -----------------------------------------------------------
*
* $Author: jarnbjo $
*
* Description:
*
* Copyright 2002-2003 Tor-Einar Jarnbjo
* -----------------------------------------------------------
*
* Change History
* -----------------------------------------------------------
* $Log: Residue2.java,v $
* Revision 1.2 2003/03/16 01:11:12 jarnbjo
* no message
*
*
*/
package de.jarnbjo.vorbis;
import java.io.IOException;
import java.util.*;
import de.jarnbjo.util.io.BitInputStream;
class Residue2 extends Residue {
private double[][] decodedVectors;
private Residue2() {
}
protected Residue2(BitInputStream source, SetupHeader header) throws VorbisFormatException, IOException {
super(source, header);
}
protected int getType() {
return 2;
}
protected void decodeResidue(VorbisStream vorbis, BitInputStream source, Mode mode, int ch, boolean[] doNotDecodeFlags, float[][] vectors) throws VorbisFormatException, IOException {
Look look=getLook(vorbis, mode);
CodeBook codeBook=vorbis.getSetupHeader().getCodeBooks()[getClassBook()];
int classvalsPerCodeword=codeBook.getDimensions();
int nToRead=getEnd()-getBegin();
int partitionsToRead=nToRead/getPartitionSize(); // partvals
int samplesPerPartition=getPartitionSize();
int partitionsPerWord=look.getPhraseBook().getDimensions();
int partWords=(partitionsToRead+partitionsPerWord-1)/partitionsPerWord;
int realCh=0;
for(int i=0; i<doNotDecodeFlags.length; i++) {
if(!doNotDecodeFlags[i]) {
realCh++;
}
}
float[][] realVectors=new float[realCh][];
realCh=0;
for(int i=0; i<doNotDecodeFlags.length; i++) {
if(!doNotDecodeFlags[i]) {
realVectors[realCh++]=vectors[i];
}
}
int[][] partword=new int[partWords][];
for(int s=0;s<look.getStages();s++){
for(int i=0,l=0;i<partitionsToRead;l++){
if(s==0){
//int temp=look.getPhraseBook().readInt(source);
int temp=source.getInt(look.getPhraseBook().getHuffmanRoot());
if(temp==-1){
throw new VorbisFormatException("");
}
partword[l]=look.getDecodeMap()[temp];
if(partword[l]==null){
throw new VorbisFormatException("");
}
}
for(int k=0;k<partitionsPerWord && i<partitionsToRead;k++,i++){
int offset=begin+i*samplesPerPartition;
if((cascade[partword[l][k]]&(1<<s))!=0){
CodeBook stagebook=vorbis.getSetupHeader().getCodeBooks()[look.getPartBooks()[partword[l][k]][s]];
if(stagebook!=null){
stagebook.readVvAdd(realVectors, source, offset, samplesPerPartition);
}
}
}
}
}
}
public Object clone() {
Residue2 clone=new Residue2();
fill(clone);
return clone;
}
protected double[][] getDecodedVectors() {
return decodedVectors;
}
}

View File

@ -1,125 +0,0 @@
/*
* $ProjectName$
* $ProjectRevision$
* -----------------------------------------------------------
* $Id: SetupHeader.java,v 1.2 2003/03/16 01:11:12 jarnbjo Exp $
* -----------------------------------------------------------
*
* $Author: jarnbjo $
*
* Description:
*
* Copyright 2002-2003 Tor-Einar Jarnbjo
* -----------------------------------------------------------
*
* Change History
* -----------------------------------------------------------
* $Log: SetupHeader.java,v $
* Revision 1.2 2003/03/16 01:11:12 jarnbjo
* no message
*
*
*/
package de.jarnbjo.vorbis;
import java.io.*;
import de.jarnbjo.util.io.*;
class SetupHeader {
private static final long HEADER = 0x736962726f76L; // 'vorbis'
private CodeBook[] codeBooks;
private Floor[] floors;
private Residue[] residues;
private Mapping[] mappings;
private Mode[] modes;
public SetupHeader(VorbisStream vorbis, BitInputStream source) throws VorbisFormatException, IOException {
if(source.getLong(48)!=HEADER) {
throw new VorbisFormatException("The setup header has an illegal leading.");
}
// read code books
int codeBookCount=source.getInt(8)+1;
codeBooks=new CodeBook[codeBookCount];
for(int i=0; i<codeBooks.length; i++) {
codeBooks[i]=new CodeBook(source);
}
// read the time domain transformations,
// these should all be 0
int timeCount=source.getInt(6)+1;
for(int i=0; i<timeCount; i++) {
if(source.getInt(16)!=0) {
throw new VorbisFormatException("Time domain transformation != 0");
}
}
// read floor entries
int floorCount=source.getInt(6)+1;
floors=new Floor[floorCount];
for(int i=0; i<floorCount; i++) {
floors[i]=Floor.createInstance(source, this);
}
// read residue entries
int residueCount=source.getInt(6)+1;
residues=new Residue[residueCount];
for(int i=0; i<residueCount; i++) {
residues[i]=Residue.createInstance(source, this);
}
// read mapping entries
int mappingCount=source.getInt(6)+1;
mappings=new Mapping[mappingCount];
for(int i=0; i<mappingCount; i++) {
mappings[i]=Mapping.createInstance(vorbis, source, this);
}
// read mode entries
int modeCount=source.getInt(6)+1;
modes=new Mode[modeCount];
for(int i=0; i<modeCount; i++) {
modes[i]=new Mode(source, this);
}
if(!source.getBit()) {
throw new VorbisFormatException("The setup header framing bit is incorrect.");
}
}
public CodeBook[] getCodeBooks() {
return codeBooks;
}
public Floor[] getFloors() {
return floors;
}
public Residue[] getResidues() {
return residues;
}
public Mapping[] getMappings() {
return mappings;
}
public Mode[] getModes() {
return modes;
}
}

View File

@ -1,121 +0,0 @@
/*
* $ProjectName$
* $ProjectRevision$
* -----------------------------------------------------------
* $Id: Util.java,v 1.3 2003/04/10 19:49:04 jarnbjo Exp $
* -----------------------------------------------------------
*
* $Author: jarnbjo $
*
* Description:
*
* Copyright 2002-2003 Tor-Einar Jarnbjo
* -----------------------------------------------------------
*
* Change History
* -----------------------------------------------------------
* $Log: Util.java,v $
* Revision 1.3 2003/04/10 19:49:04 jarnbjo
* no message
*
* Revision 1.2 2003/03/16 01:11:12 jarnbjo
* no message
*
*
*/
package de.jarnbjo.vorbis;
final public class Util {
public static final int ilog(int x) {
int res=0;
for(; x>0; x>>=1, res++);
return res;
}
public static final float float32unpack(int x) {
float mantissa=x&0x1fffff;
float e=(x&0x7fe00000)>>21;
if((x&0x80000000)!=0) {
mantissa=-mantissa;
}
return mantissa*(float)Math.pow(2.0, e-788.0);
}
public static final int lookup1Values(int a, int b) {
int res=(int)Math.pow(Math.E, Math.log(a)/b);
return intPow(res+1, b)<=a?res+1:res;
}
public static final int intPow(int base, int e) {
int res=1;
for(; e>0; e--, res*=base);
return res;
}
public static final boolean isBitSet(int value, int bit) {
return (value&(1<<bit))!=0;
}
public static final int icount(int value) {
int res=0;
while(value>0) {
res+=value&1;
value>>=1;
}
return res;
}
public static final int lowNeighbour(int[] v, int x) {
int max=-1, n=0;
for(int i=0; i<v.length && i<x; i++) {
if(v[i]>max && v[i]<v[x]) {
max=v[i];
n=i;
}
}
return n;
}
public static final int highNeighbour(int[] v, int x) {
int min=Integer.MAX_VALUE, n=0;
for(int i=0; i<v.length && i<x; i++) {
if(v[i]<min && v[i]>v[x]) {
min=v[i];
n=i;
}
}
return n;
}
public static final int renderPoint(int x0, int x1, int y0, int y1, int x) {
int dy=y1-y0;
int ady=dy<0?-dy:dy;
int off=(ady*(x-x0))/(x1-x0);
return dy<0?y0-off:y0+off;
}
public static final void renderLine(final int x0, final int y0, final int x1, final int y1, final float[] v) {
final int dy=y1-y0;
final int adx=x1-x0;
final int base=dy/adx;
final int sy=dy<0?base-1:base+1;
int x=x0;
int y=y0;
int err=0;
final int ady=(dy<0?-dy:dy)-(base>0?base*adx:-base*adx);
v[x]*=Floor.DB_STATIC_TABLE[y];
for(x=x0+1; x<x1; x++) {
err+=ady;
if(err>=adx) {
err-=adx;
v[x]*=Floor.DB_STATIC_TABLE[y+=sy];
}
else {
v[x]*=Floor.DB_STATIC_TABLE[y+=base];
}
}
}
}

View File

@ -1,196 +0,0 @@
package de.jarnbjo.vorbis;
/*
* $ProjectName$
* $ProjectRevision$
* -----------------------------------------------------------
* $Id: VorbisAudioFileReader.java,v 1.1 2003/08/08 19:48:22 jarnbjo Exp $
* -----------------------------------------------------------
*
* $Author: jarnbjo $
*
* Description:
*
* Copyright 2002-2003 Tor-Einar Jarnbjo
* -----------------------------------------------------------
*
* Change History
* -----------------------------------------------------------
* $Log: VorbisAudioFileReader.java,v $
*
*/
import java.io.*;
import java.net.*;
import java.util.*;
import de.jarnbjo.ogg.*;
import de.jarnbjo.vorbis.*;
import javax.sound.sampled.*;
import javax.sound.sampled.spi.AudioFileReader;
public class VorbisAudioFileReader extends AudioFileReader {
public VorbisAudioFileReader() {
}
public AudioFileFormat getAudioFileFormat(File file) throws IOException, UnsupportedAudioFileException {
try {
return getAudioFileFormat(new FileStream(new RandomAccessFile(file, "r")));
}
catch(OggFormatException e) {
throw new UnsupportedAudioFileException(e.getMessage());
}
}
public AudioFileFormat getAudioFileFormat(InputStream stream) throws IOException, UnsupportedAudioFileException {
try {
return getAudioFileFormat(new BasicStream(stream));
}
catch(OggFormatException e) {
throw new UnsupportedAudioFileException(e.getMessage());
}
}
public AudioFileFormat getAudioFileFormat(URL url) throws IOException, UnsupportedAudioFileException {
try {
return getAudioFileFormat(new UncachedUrlStream(url));
}
catch(OggFormatException e) {
throw new UnsupportedAudioFileException(e.getMessage());
}
}
private AudioFileFormat getAudioFileFormat(PhysicalOggStream oggStream) throws IOException, UnsupportedAudioFileException {
try {
Collection streams=oggStream.getLogicalStreams();
if(streams.size()!=1) {
throw new UnsupportedAudioFileException("Only Ogg files with one logical Vorbis stream are supported.");
}
LogicalOggStream los=(LogicalOggStream)streams.iterator().next();
if(los.getFormat()!=LogicalOggStream.FORMAT_VORBIS) {
throw new UnsupportedAudioFileException("Only Ogg files with one logical Vorbis stream are supported.");
}
VorbisStream vs=new VorbisStream(los);
AudioFormat audioFormat=new AudioFormat(
(float)vs.getIdentificationHeader().getSampleRate(),
16,
vs.getIdentificationHeader().getChannels(),
true, true);
return new AudioFileFormat(VorbisFormatType.getInstance(), audioFormat, AudioSystem.NOT_SPECIFIED);
}
catch(OggFormatException e) {
throw new UnsupportedAudioFileException(e.getMessage());
}
catch(VorbisFormatException e) {
throw new UnsupportedAudioFileException(e.getMessage());
}
}
public AudioInputStream getAudioInputStream(File file) throws IOException, UnsupportedAudioFileException {
try {
return getAudioInputStream(new FileStream(new RandomAccessFile(file, "r")));
}
catch(OggFormatException e) {
throw new UnsupportedAudioFileException(e.getMessage());
}
}
public AudioInputStream getAudioInputStream(InputStream stream) throws IOException, UnsupportedAudioFileException {
try {
return getAudioInputStream(new BasicStream(stream));
}
catch(OggFormatException e) {
throw new UnsupportedAudioFileException(e.getMessage());
}
}
public AudioInputStream getAudioInputStream(URL url) throws IOException, UnsupportedAudioFileException {
try {
return getAudioInputStream(new UncachedUrlStream(url));
}
catch(OggFormatException e) {
throw new UnsupportedAudioFileException(e.getMessage());
}
}
private AudioInputStream getAudioInputStream(PhysicalOggStream oggStream) throws IOException, UnsupportedAudioFileException {
try {
Collection streams=oggStream.getLogicalStreams();
if(streams.size()!=1) {
throw new UnsupportedAudioFileException("Only Ogg files with one logical Vorbis stream are supported.");
}
LogicalOggStream los=(LogicalOggStream)streams.iterator().next();
if(los.getFormat()!=LogicalOggStream.FORMAT_VORBIS) {
throw new UnsupportedAudioFileException("Only Ogg files with one logical Vorbis stream are supported.");
}
VorbisStream vs=new VorbisStream(los);
AudioFormat audioFormat=new AudioFormat(
(float)vs.getIdentificationHeader().getSampleRate(),
16,
vs.getIdentificationHeader().getChannels(),
true, true);
return new AudioInputStream(new VorbisInputStream(vs), audioFormat, -1);
}
catch(OggFormatException e) {
throw new UnsupportedAudioFileException(e.getMessage());
}
catch(VorbisFormatException e) {
throw new UnsupportedAudioFileException(e.getMessage());
}
}
public static class VorbisFormatType extends AudioFileFormat.Type {
private static final VorbisFormatType instance=new VorbisFormatType();
private VorbisFormatType() {
super("VORBIS", "ogg");
}
public static AudioFileFormat.Type getInstance() {
return instance;
}
}
public static class VorbisInputStream extends InputStream {
private VorbisStream source;
private byte[] buffer=new byte[8192];
public VorbisInputStream(VorbisStream source) {
this.source=source;
}
public int read() throws IOException {
return 0;
}
public int read(byte[] buffer) throws IOException {
return read(buffer, 0, buffer.length);
}
public int read(byte[] buffer, int offset, int length) throws IOException {
try {
return source.readPcm(buffer, offset, length);
}
catch(EndOfOggStreamException e) {
return -1;
}
}
}
}

View File

@ -1,41 +0,0 @@
/*
* $ProjectName$
* $ProjectRevision$
* -----------------------------------------------------------
* $Id: VorbisFormatException.java,v 1.2 2003/03/16 01:11:12 jarnbjo Exp $
* -----------------------------------------------------------
*
* $Author: jarnbjo $
*
* Description:
*
* Copyright 2002-2003 Tor-Einar Jarnbjo
* -----------------------------------------------------------
*
* Change History
* -----------------------------------------------------------
* $Log: VorbisFormatException.java,v $
* Revision 1.2 2003/03/16 01:11:12 jarnbjo
* no message
*
*
*/
package de.jarnbjo.vorbis;
import java.io.IOException;
/**
* Exception thrown when trying to read a corrupted Vorbis stream.
*/
public class VorbisFormatException extends IOException {
public VorbisFormatException() {
super();
}
public VorbisFormatException(String message) {
super(message);
}
}

View File

@ -1,241 +0,0 @@
/*
* $ProjectName$
* $ProjectRevision$
* -----------------------------------------------------------
* $Id: VorbisStream.java,v 1.4 2003/04/10 19:49:04 jarnbjo Exp $
* -----------------------------------------------------------
*
* $Author: jarnbjo $
*
* Description:
*
* Copyright 2002-2003 Tor-Einar Jarnbjo
* -----------------------------------------------------------
*
* Change History
* -----------------------------------------------------------
* $Log: VorbisStream.java,v $
* Revision 1.4 2003/04/10 19:49:04 jarnbjo
* no message
*
* Revision 1.3 2003/03/31 00:20:16 jarnbjo
* no message
*
* Revision 1.2 2003/03/16 01:11:12 jarnbjo
* no message
*
*
*/
package de.jarnbjo.vorbis;
import java.io.*;
import java.util.*;
import de.jarnbjo.ogg.*;
import de.jarnbjo.util.io.*;
/**
*/
public class VorbisStream {
private LogicalOggStream oggStream;
private IdentificationHeader identificationHeader;
private CommentHeader commentHeader;
private SetupHeader setupHeader;
private AudioPacket lastAudioPacket, nextAudioPacket;
private LinkedList audioPackets=new LinkedList();
private byte[] currentPcm;
private int currentPcmIndex;
private int currentPcmLimit;
private static final int IDENTIFICATION_HEADER = 1;
private static final int COMMENT_HEADER = 3;
private static final int SETUP_HEADER = 5;
private int bitIndex=0;
private byte lastByte=(byte)0;
private boolean initialized=false;
private Object streamLock=new Object();
private int pageCounter=0;
private int currentBitRate=0;
private long currentGranulePosition;
public static final int BIG_ENDIAN = 0;
public static final int LITTLE_ENDIAN = 1;
public VorbisStream() {
}
public VorbisStream(LogicalOggStream oggStream) throws VorbisFormatException, IOException {
this.oggStream=oggStream;
for(int i=0; i<3; i++) {
BitInputStream source=new ByteArrayBitInputStream(oggStream.getNextOggPacket());
int headerType=source.getInt(8);
switch(headerType) {
case IDENTIFICATION_HEADER:
identificationHeader=new IdentificationHeader(source);
break;
case COMMENT_HEADER:
commentHeader=new CommentHeader(source);
break;
case SETUP_HEADER:
setupHeader=new SetupHeader(this, source);
break;
}
}
if(identificationHeader==null) {
throw new VorbisFormatException("The file has no identification header.");
}
if(commentHeader==null) {
throw new VorbisFormatException("The file has no commentHeader.");
}
if(setupHeader==null) {
throw new VorbisFormatException("The file has no setup header.");
}
//currentPcm=new int[identificationHeader.getChannels()][16384];
currentPcm=new byte[identificationHeader.getChannels()*identificationHeader.getBlockSize1()*2];
//new BufferThread().start();
}
public IdentificationHeader getIdentificationHeader() {
return identificationHeader;
}
public CommentHeader getCommentHeader() {
return commentHeader;
}
protected SetupHeader getSetupHeader() {
return setupHeader;
}
public boolean isOpen() {
return oggStream.isOpen();
}
public void close() throws IOException {
oggStream.close();
}
public int readPcm(byte[] buffer, int offset, int length) throws IOException {
synchronized (streamLock) {
final int channels=identificationHeader.getChannels();
if(lastAudioPacket==null) {
lastAudioPacket=getNextAudioPacket();
}
if(currentPcm==null || currentPcmIndex>=currentPcmLimit) {
AudioPacket ap=getNextAudioPacket();
try {
ap.getPcm(lastAudioPacket, currentPcm);
currentPcmLimit=ap.getNumberOfSamples()*identificationHeader.getChannels()*2;
}
catch(ArrayIndexOutOfBoundsException e) {
return 0;
}
currentPcmIndex=0;
lastAudioPacket=ap;
}
int written=0;
int i=0;
int arrIx=0;
for(i=currentPcmIndex; i<currentPcmLimit && arrIx<length; i++) {
buffer[offset+arrIx++]=currentPcm[i];
written++;
}
currentPcmIndex=i;
return written;
}
}
private AudioPacket getNextAudioPacket() throws VorbisFormatException, IOException {
pageCounter++;
byte[] data=oggStream.getNextOggPacket();
AudioPacket res=null;
while(res==null) {
try {
res=new AudioPacket(this, new ByteArrayBitInputStream(data));
}
catch(ArrayIndexOutOfBoundsException e) {
// ignore and continue with next packet
}
}
currentGranulePosition+=res.getNumberOfSamples();
currentBitRate=data.length*8*identificationHeader.getSampleRate()/res.getNumberOfSamples();
return res;
}
public long getCurrentGranulePosition() {
return currentGranulePosition;
}
public int getCurrentBitRate() {
return currentBitRate;
}
public byte[] processPacket(byte[] packet) throws VorbisFormatException, IOException {
if(packet.length==0) {
throw new VorbisFormatException("Cannot decode a vorbis packet with length = 0");
}
if(((int)packet[0]&1)==1) {
// header packet
BitInputStream source=new ByteArrayBitInputStream(packet);
switch(source.getInt(8)) {
case IDENTIFICATION_HEADER:
identificationHeader=new IdentificationHeader(source);
break;
case COMMENT_HEADER:
commentHeader=new CommentHeader(source);
break;
case SETUP_HEADER:
setupHeader=new SetupHeader(this, source);
break;
}
return null;
}
else {
// audio packet
if(identificationHeader==null ||
commentHeader==null ||
setupHeader==null) {
throw new VorbisFormatException("Cannot decode audio packet before all three header packets have been decoded.");
}
AudioPacket ap=new AudioPacket(this, new ByteArrayBitInputStream(packet));
currentGranulePosition+=ap.getNumberOfSamples();
if(lastAudioPacket==null) {
lastAudioPacket=ap;
return null;
}
byte[] res=new byte[identificationHeader.getChannels()*ap.getNumberOfSamples()*2];
try {
ap.getPcm(lastAudioPacket, res);
}
catch(IndexOutOfBoundsException e) {
java.util.Arrays.fill(res, (byte)0);
}
lastAudioPacket=ap;
return res;
}
}
}

File diff suppressed because one or more lines are too long

View File

@ -67,7 +67,6 @@ import net.lax1dude.eaglercraft.AssetRepository;
import net.lax1dude.eaglercraft.Base64;
import net.lax1dude.eaglercraft.Client;
import net.lax1dude.eaglercraft.EaglerImage;
import net.lax1dude.eaglercraft.EarlyLoadScreen;
import net.lax1dude.eaglercraft.adapter.teavm.IndexedDBFilesystem;
import net.lax1dude.eaglercraft.adapter.teavm.IndexedDBFilesystem.OpenState;
import net.lax1dude.eaglercraft.adapter.teavm.WebGL2RenderingContext;