⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bitstream.java

📁 java处理声音文件
💻 JAVA
字号:
/*
 * 12/12/99	 Based on Ibitstream. Exceptions thrown on errors, 
 *			 Tempoarily removed seek functionality. mdm@techie.com
 *
 * 02/12/99 : Java Conversion by E.B , ebsp@iname.com , JavaLayer
 *
 *----------------------------------------------------------------------
 *  @(#) 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 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 General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *  Changes made by Jeff Tsay :
 *  04/14/97 : Added function prototypes for new syncing and seeking
 *  mechanisms. Also made this file portable.
 *-----------------------------------------------------------------------
 */
 
package javazoom.jl.decoder;

import java.io.InputStream;
import java.io.IOException;
import java.io.EOFException;

/** 
 * 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
{	
	
	/**
	 * Syncrhronization control constant for the initial
	 * synchronization to the start of a frame.
	 */
	static byte		INITIAL_SYNC = 0;

	/**
	 * Syncrhronization control constant for non-iniital 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;		
	
	/**
	 * 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;
	
	/**
	 * 
	 */
	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 InputStream		source;		
	
	private final Header			header = new Header();
	
	private final byte				syncbuf[] = new byte[4];
	
	private Crc16[]					crc = new Crc16[1];
	
	/**
	 * 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");
		
		source = in;	
		
		closeFrame();
		//current_frame_number = -1;
		//last_frame_number = -1;	    
	}  
  	
	/**
	 * 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();
		}
		catch (BitstreamException ex)
		{			
			if (ex.getErrorCode()!=STREAM_EOF)
			{
				// wrap original exception so stack trace is maintained.
				throw newBitstreamException(ex.getErrorCode(), ex);				
			}
		}
		return result;
	}
  
	private Header readNextFrame() throws BitstreamException		
	{
		if (framesize == -1)
		{			
			nextFrame();
		}
		
		return header;
	}
	
	
	/**
	 * 
	 */
	private void nextFrame() throws BitstreamException
	{
		// entire frame is read by the header class. 
		header.read_header(this, crc);						   		
	}
	
	public void closeFrame()
	{
		framesize = -1;
		wordpointer = -1;
		bitindex = -1;		
	}

	
	// REVIEW: this class should provide inner classes to
	// parse the frame contents. Eventually, readBits will
	// be removed. 
	public int readBits(int n)
	{
		return get_bits(n);
	}
	
	public int readCheckedBits(int n)
	{
		// REVIEW: implement CRC check.
		return get_bits(n);
	}

	protected BitstreamException newBitstreamException(int errorcode)
	{
		return new BitstreamException(errorcode, null);
	}
	protected BitstreamException newBitstreamException(int errorcode, Throwable throwable)
	{
		return new BitstreamException(errorcode, throwable);
	}

	
  /**
   * Get next 32 bits from bitstream.
   * They are stored in the headerstring.
   * syncmod allows Synchro flag ID
   * The returned value is False at the end of stream.
   */
  		
	int syncHeader(byte syncmode) throws BitstreamException
	{
		boolean sync;
		int headerstring;
				
		// test for EOF
		int read;
		try
		{
			read = source.read();
			if (read==-1)
			{
				// System.out.println("hallo1");				throw newBitstreamException(STREAM_EOF, null);	
			}
		}
		catch (IOException ex)
		{
			// System.out.println("hallo2-");			throw newBitstreamException(STREAM_ERROR, ex);
		}
		
		syncbuf[0] = (byte)read;
		
		// read additinal 2 bytes
		readFully(syncbuf, 1, 2);
		
		headerstring = ((syncbuf[0] << 16) & 0x00FF0000) | ((syncbuf[1] << 8) & 0x0000FF00) | ((syncbuf[2] << 0) & 0x000000FF);
		
		do
		{						
			headerstring <<= 8;
			
			readFully(syncbuf, 3, 1);
			headerstring |= (syncbuf[3] & 0x000000FF);
			
			if (syncmode == INITIAL_SYNC)
			{
				sync =  ((headerstring & 0xFFF00000) == 0xFFF00000);
			}
			else
			{
				sync =  ((headerstring & 0xFFF80C00) == syncword) &&
				    (((headerstring & 0x000000C0) == 0x000000C0) == single_ch_mode);
			}		   						
		} 
		// System.out.println("hallo3");		while (!sync);
			
		//current_frame_number++;
		//if (last_frame_number < current_frame_number) last_frame_number = current_frame_number;		
		
		return headerstring;
	}

  /**
   * Fill buffer with data from bitstream.
   * Read bytesize bytes from the file.
   * The returned value is False at the end of stream.
   */
  void read_frame(int bytesize) throws BitstreamException 
  {
 	int		numread = 0;
    // read bytesize bytes from the file, placing the number of bytes
    // actually read in numread and setting result to true if
    // successful
  	boolean result = false;
	
	// REVIEW: optimize - reuse temporary buffer	
	byte[]	byteread = new byte[bytesize];
	readFully(byteread,0,bytesize);		
	
	// Convert Bytes read to int		
	int	b=0;
	
	for (int k=0;k<bytesize;k=k+4)
	{
		int convert = 0;
		byte b0 = 0;
		byte b1 = 0;
		byte b2 = 0;
		byte b3 = 0;
		b0 = byteread[k];
		if (k+1<bytesize) b1 = byteread[k+1];
		if (k+2<bytesize) b2 = byteread[k+2];
		if (k+3<bytesize) b3 = byteread[k+3];
		framebuffer[b++] = ((b0 << 24) &0xFF000000) | ((b1 << 16) & 0x00FF0000) | ((b2 << 8) & 0x0000FF00) | (b3 & 0x000000FF);
	}
	
	wordpointer = 0;
    bitindex = 0;
    framesize = bytesize;
	
  }
  
  /**
   * Read bits from buffer into the lower bits of an unsigned int. 
   * The LSB contains the latest read bit of the stream.
   * (1 <= number_of_bits <= 16)
   */  
  public int get_bits(int number_of_bits)
  {
  	
  	int				returnvalue = 0;
  	int 			sum = bitindex + number_of_bits;

  	if (sum <= 32)
  	{
	   // all bits contained in *wordpointer
	   returnvalue = (framebuffer[wordpointer] >>> (32 - sum)) & bitmask[number_of_bits];
	   // returnvalue = (wordpointer[0] >> (32 - sum)) & bitmask[number_of_bits];
	   if ((bitindex += number_of_bits) == 32)
	   {
		 bitindex = 0;
		 wordpointer++; // added by me!
	   }
	   return returnvalue;
    }

    // Magouille a Voir
    //((short[])&returnvalue)[0] = ((short[])wordpointer + 1)[0];
    //wordpointer++; // Added by me!
    //((short[])&returnvalue + 1)[0] = ((short[])wordpointer)[0];
	int Right = (framebuffer[wordpointer] & 0x0000FFFF);
	wordpointer++;
	int Left = (framebuffer[wordpointer] & 0xFFFF0000);
	returnvalue = ((Right << 16) & 0xFFFF0000) | ((Left >>> 16)& 0x0000FFFF);
	
    returnvalue >>>= 48 - sum;	// returnvalue >>= 16 - (number_of_bits - (32 - bitindex))
    returnvalue &= bitmask[number_of_bits];
    bitindex = sum - 32;
    return returnvalue;
}

	/**
	 * Set the word we want to sync the header to.
	 * In Big-Endian byte order
	 */
	void set_syncword(int syncword0)
	{
		syncword = syncword0 & 0xFFFFFF3F;
		single_ch_mode = ((syncword0 & 0x000000C0) == 0x000000C0);
	}
	/**
	 * Reads the exact number of bytes from the source
	 * input stream into a byte array.
	 * 
	 * @param b		The byte array to read the specified number
	 *				of bytes into.
	 * @param offs	The index in the array where the first byte
	 *				read should be stored.
	 * @param len	the number of bytes to read.
	 * 
	 * @exception BitstreamException is thrown if the specified
	 *		number of bytes could not be read from the stream.
	 */
	private void readFully(byte[] b, int offs, int len)
		throws BitstreamException
	{
		try
		{
			while (len > 0)
			{
				int bytesread = source.read(b, offs, len);
				if (bytesread == -1)
				{
					// System.out.println("hallo4");					// inserted MP19991217					throw newBitstreamException(STREAM_EOF, null);					// end insertion					// commented out MP19991217					// break;
					// end commented out					//throw newBitstreamException(UNEXPECTED_EOF, new EOFException());
				}
				
				offs += bytesread;
				len -= bytesread;
			}			
		}
		catch (IOException ex)
		{
			// System.out.println("hallo5");			throw newBitstreamException(STREAM_ERROR, ex);
		}
	}
  
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -