/* * $ProjectName$ * $ProjectRevision$ * ----------------------------------------------------------- * $Id$ * ----------------------------------------------------------- * * $Author$ * * Description: * * Copyright 2002-2003 Tor-Einar Jarnbjo * ----------------------------------------------------------- * * Change History * ----------------------------------------------------------- * $Log$ * Revision 1.1 2005/07/11 15:42:36 hcl * Songdb java version, source. only 1.5 compatible * * Revision 1.1.1.1 2004/04/04 22:09:12 shred * First Import * * 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