?? bitstream.java
字號:
/*
* 11/19/04 1.0 moved to LGPL.
*
* 11/17/04 Uncomplete frames discarded. E.B, javalayer@javazoom.net
*
* 12/05/03 ID3v2 tag returned. E.B, javalayer@javazoom.net
*
* 12/12/99 Based on Ibitstream. Exceptions thrown on errors,
* Temporary removed seek functionality. mdm@techie.com
*
* 02/12/99 : Java Conversion by E.B , javalayer@javazoom.net
*
* 04/14/97 : Added function prototypes for new syncing and seeking
* mechanisms. Also made this file portable. Changes made by Jeff Tsay
*
* @(#) ibitstream.h 1.5, last edit: 6/15/94 16:55:34
* @(#) Copyright (C) 1993, 1994 Tobias Bading (bading@cs.tu-berlin.de)
* @(#) Berlin University of Technology
*-----------------------------------------------------------------------
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*----------------------------------------------------------------------
*/
package javazoom.jl.decoder;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PushbackInputStream;
/**
* The <code>Bistream</code> class is responsible for parsing
* an MPEG audio bitstream.
*
* <b>REVIEW:</b> much of the parsing currently occurs in the
* various decoders. This should be moved into this class and associated
* inner classes.
*/
public final class Bitstream implements BitstreamErrors
{
/**
* Synchronization control constant for the initial
* synchronization to the start of a frame.
*/
static byte INITIAL_SYNC = 0;
/**
* Synchronization control constant for non-initial frame
* synchronizations.
*/
static byte STRICT_SYNC = 1;
// max. 1730 bytes per frame: 144 * 384kbit/s / 32000 Hz + 2 Bytes CRC
/**
* Maximum size of the frame buffer.
*/
private static final int BUFFER_INT_SIZE = 433;
/**
* The frame buffer that holds the data for the current frame.
*/
private final int[] framebuffer = new int[BUFFER_INT_SIZE];
/**
* Number of valid bytes in the frame buffer.
*/
private int framesize;
/**
* The bytes read from the stream.
*/
private byte[] frame_bytes = new byte[BUFFER_INT_SIZE*4];
/**
* Index into <code>framebuffer</code> where the next bits are
* retrieved.
*/
private int wordpointer;
/**
* Number (0-31, from MSB to LSB) of next bit for get_bits()
*/
private int bitindex;
/**
* The current specified syncword
*/
private int syncword;
/**
* Audio header position in stream.
*/
private int header_pos = 0;
/**
*
*/
private boolean single_ch_mode;
//private int current_frame_number;
//private int last_frame_number;
private final int bitmask[] = {0, // dummy
0x00000001, 0x00000003, 0x00000007, 0x0000000F,
0x0000001F, 0x0000003F, 0x0000007F, 0x000000FF,
0x000001FF, 0x000003FF, 0x000007FF, 0x00000FFF,
0x00001FFF, 0x00003FFF, 0x00007FFF, 0x0000FFFF,
0x0001FFFF };
private final PushbackInputStream source;
private final Header header = new Header();
private final byte syncbuf[] = new byte[4];
private Crc16[] crc = new Crc16[1];
private byte[] rawid3v2 = null;
private boolean firstframe = true;
/**
* Construct a IBitstream that reads data from a
* given InputStream.
*
* @param in The InputStream to read from.
*/
public Bitstream(InputStream in)
{
if (in==null) throw new NullPointerException("in");
in = new BufferedInputStream(in);
loadID3v2(in);
firstframe = true;
//source = new PushbackInputStream(in, 1024);
source = new PushbackInputStream(in, BUFFER_INT_SIZE*4);
closeFrame();
//current_frame_number = -1;
//last_frame_number = -1;
}
/**
* Return position of the first audio header.
* @return size of ID3v2 tag frames.
*/
public int header_pos()
{
return header_pos;
}
/**
* Load ID3v2 frames.
* @param in MP3 InputStream.
* @author JavaZOOM
*/
private void loadID3v2(InputStream in)
{
int size = -1;
try
{
// Read ID3v2 header (10 bytes).
in.mark(10);
size = readID3v2Header(in);
header_pos = size;
}
catch (IOException e)
{}
finally
{
try
{
// Unread ID3v2 header (10 bytes).
in.reset();
}
catch (IOException e)
{}
}
// Load ID3v2 tags.
try
{
if (size > 0)
{
rawid3v2 = new byte[size];
in.read(rawid3v2,0,rawid3v2.length);
}
}
catch (IOException e)
{}
}
/**
* Parse ID3v2 tag header to find out size of ID3v2 frames.
* @param in MP3 InputStream
* @return size of ID3v2 frames + header
* @throws IOException
* @author JavaZOOM
*/
private int readID3v2Header(InputStream in) throws IOException
{
byte[] id3header = new byte[4];
int size = -10;
in.read(id3header,0,3);
// Look for ID3v2
if ( (id3header[0]=='I') && (id3header[1]=='D') && (id3header[2]=='3'))
{
in.read(id3header,0,3);
int majorVersion = id3header[0];
int revision = id3header[1];
in.read(id3header,0,4);
size = (int) (id3header[0] << 21) + (id3header[1] << 14) + (id3header[2] << 7) + (id3header[3]);
}
return (size+10);
}
/**
* Return raw ID3v2 frames + header.
* @return ID3v2 InputStream or null if ID3v2 frames are not available.
*/
public InputStream getRawID3v2()
{
if (rawid3v2 == null) return null;
else
{
ByteArrayInputStream bain = new ByteArrayInputStream(rawid3v2);
return bain;
}
}
/**
* Close the Bitstream.
* @throws BitstreamException
*/
public void close() throws BitstreamException
{
try
{
source.close();
}
catch (IOException ex)
{
throw newBitstreamException(STREAM_ERROR, ex);
}
}
/**
* Reads and parses the next frame from the input source.
* @return the Header describing details of the frame read,
* or null if the end of the stream has been reached.
*/
public Header readFrame() throws BitstreamException
{
Header result = null;
try
{
result = readNextFrame();
// E.B, Parse VBR (if any) first frame.
if (firstframe == true)
{
result.parseVBR(frame_bytes);
firstframe = false;
}
}
catch (BitstreamException ex)
{
if ((ex.getErrorCode()==INVALIDFRAME))
{
// Try to skip this frame.
//System.out.println("INVALIDFRAME");
try
{
closeFrame();
result = readNextFrame();
}
catch (BitstreamException e)
{
if ((e.getErrorCode()!=STREAM_EOF))
{
// wrap original exception so stack trace is maintained.
throw newBitstreamException(e.getErrorCode(), e);
}
}
}
else if ((ex.getErrorCode()!=STREAM_EOF))
{
// wrap original exception so stack trace is maintained.
throw newBitstreamException(ex.getErrorCode(), ex);
}
}
return result;
}
/**
* Read next MP3 frame.
* @return MP3 frame header.
* @throws BitstreamException
*/
private Header readNextFrame() throws BitstreamException
{
if (framesize == -1)
{
nextFrame();
}
return header;
}
/**
* Read next MP3 frame.
* @throws BitstreamException
*/
private void nextFrame() throws BitstreamException
{
// entire frame is read by the header class.
header.read_header(this, crc);
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -