2 * 11/19/04 1.0 moved to LGPL.
4 * 11/17/04 Uncomplete frames discarded. E.B, javalayer@javazoom.net
6 * 12/05/03 ID3v2 tag returned. E.B, javalayer@javazoom.net
8 * 12/12/99 Based on Ibitstream. Exceptions thrown on errors,
9 * Temporary removed seek functionality. mdm@techie.com
11 * 02/12/99 : Java Conversion by E.B , javalayer@javazoom.net
13 * 04/14/97 : Added function prototypes for new syncing and seeking
14 * mechanisms. Also made this file portable. Changes made by Jeff Tsay
16 * @(#) ibitstream.h 1.5, last edit: 6/15/94 16:55:34
17 * @(#) Copyright (C) 1993, 1994 Tobias Bading (bading@cs.tu-berlin.de)
18 * @(#) Berlin University of Technology
19 *-----------------------------------------------------------------------
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU Library General Public License as published
22 * by the Free Software Foundation; either version 2 of the License, or
23 * (at your option) any later version.
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU Library General Public License for more details.
30 * You should have received a copy of the GNU Library General Public
31 * License along with this program; if not, write to the Free Software
32 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
33 *----------------------------------------------------------------------
37 * The <code>Bistream</code> class is responsible for parsing an MPEG audio
40 * <b>REVIEW:</b> much of the parsing currently occurs in the various decoders.
41 * This should be moved into this class and associated inner classes.
43 @LATTICE("FB<F,FF<F,WP<BI,FF*,WP*,BI*")
44 @METHODDEFAULT("OUT<THIS,THIS<VAR,VAR<IN,VAR*,THISLOC=THIS,GLOBALLOC=IN")
45 public final class Bitstream implements BitstreamErrors {
47 * Synchronization control constant for the initial synchronization to the
51 static byte INITIAL_SYNC = 0;
54 * Synchronization control constant for non-initial frame synchronizations.
58 static byte STRICT_SYNC = 1;
60 // max. 1730 bytes per frame: 144 * 384kbit/s / 32000 Hz + 2 Bytes CRC
62 * Maximum size of the frame buffer.
65 private static final int BUFFER_INT_SIZE = 433;
68 * The frame buffer that holds the data for the current frame.
71 private final int[] framebuffer = new int[BUFFER_INT_SIZE];
74 * Number of valid bytes in the frame buffer.
77 private int framesize;
80 * The bytes read from the stream.
83 private byte[] frame_bytes = new byte[BUFFER_INT_SIZE * 4];
86 * Index into <code>framebuffer</code> where the next bits are retrieved.
89 private int wordpointer;
92 * Number (0-31, from MSB to LSB) of next bit for get_bits()
98 * The current specified syncword
101 private int syncword;
104 * Audio header position in stream.
107 private int header_pos = 0;
113 private boolean single_ch_mode;
114 // private int current_frame_number;
115 // private int last_frame_number;
118 private final int bitmask[] = {
120 0x00000001, 0x00000003, 0x00000007, 0x0000000F, 0x0000001F, 0x0000003F, 0x0000007F,
121 0x000000FF, 0x000001FF, 0x000003FF, 0x000007FF, 0x00000FFF, 0x00001FFF, 0x00003FFF,
122 0x00007FFF, 0x0000FFFF, 0x0001FFFF };
125 private final PushbackInputStream source;
128 private final Header header = new Header();
131 private final byte syncbuf[] = new byte[4];
134 private Crc16[] crc = new Crc16[1];
137 private byte[] rawid3v2 = null;
140 private boolean firstframe = true;
142 private BitReserve br;
143 private int main_data_begin;
144 private int frame_start;
147 * Construct a IBitstream that reads data from a given InputStream.
150 * The InputStream to read from.
152 public Bitstream(InputStream in) {
154 throw new NullPointerException("in");
155 in = new BufferedInputStream(in);
158 // source = new PushbackInputStream(in, 1024);
159 source = new PushbackInputStream(in, BUFFER_INT_SIZE * 4);
162 // current_frame_number = -1;
163 // last_frame_number = -1;
165 br = new BitReserve();
170 * Return position of the first audio header.
172 * @return size of ID3v2 tag frames.
174 public int header_pos() {
185 private void loadID3v2(InputStream in) {
188 // Read ID3v2 header (10 bytes).
190 size = readID3v2Header(in);
192 } catch (IOException e) {
195 // Unread ID3v2 header (10 bytes).
197 } catch (IOException e) {
203 rawid3v2 = new byte[size];
204 in.read(rawid3v2, 0, rawid3v2.length);
206 } catch (IOException e) {
211 * Parse ID3v2 tag header to find out size of ID3v2 frames.
215 * @return size of ID3v2 frames + header
216 * @throws IOException
219 private int readID3v2Header(InputStream in) throws IOException {
220 byte[] id3header = new byte[4];
222 in.read(id3header, 0, 3);
224 if ((id3header[0] == 'I') && (id3header[1] == 'D') && (id3header[2] == '3')) {
225 in.read(id3header, 0, 3);
226 int majorVersion = id3header[0];
227 int revision = id3header[1];
228 in.read(id3header, 0, 4);
230 (int) (id3header[0] << 21) + (id3header[1] << 14) + (id3header[2] << 7) + (id3header[3]);
236 * Return raw ID3v2 frames + header.
238 * @return ID3v2 InputStream or null if ID3v2 frames are not available.
240 public InputStream getRawID3v2() {
241 if (rawid3v2 == null)
244 ByteArrayInputStream bain = new ByteArrayInputStream(rawid3v2);
250 * Close the Bitstream.
252 * @throws BitstreamException
254 public void close() throws BitstreamException {
257 } catch (IOException ex) {
258 throw newBitstreamException(STREAM_ERROR, ex);
263 * Reads and parses the next frame from the input source.
265 * @return the Header describing details of the frame read, or null if the end
266 * of the stream has been reached.
268 public Header readFrame() throws BitstreamException {
270 Header result = null;
272 result = readNextFrame();
273 if (result == null) {
276 // E.B, Parse VBR (if any) first frame.
277 if (firstframe == true) {
278 result.parseVBR(frame_bytes);
282 int channels = (header.mode() == Header.SINGLE_CHANNEL) ? 1 : 2;
284 result.setSideInfoBuf(getSideInfoBuffer(channels));
285 result.setBitReserve(getBitReserve(result.slots()));
289 } catch (BitstreamException ex) {
290 if ((ex.getErrorCode() == INVALIDFRAME)) {
291 // Try to skip this frame.
292 // System.out.println("INVALIDFRAME");
295 result = readNextFrame();
296 } catch (BitstreamException e) {
297 if ((e.getErrorCode() != STREAM_EOF)) {
298 // wrap original exception so stack trace is maintained.
299 throw newBitstreamException(e.getErrorCode(), e);
302 } else if ((ex.getErrorCode() != STREAM_EOF)) {
303 // wrap original exception so stack trace is maintained.
304 throw newBitstreamException(ex.getErrorCode(), ex);
312 * Read next MP3 frame.
314 * @return MP3 frame header.
315 * @throws BitstreamException
317 private Header readNextFrame() throws BitstreamException {
318 if (framesize == -1) {
319 if (nextFrame() == -1) {
327 * Read next MP3 frame.
329 * @throws BitstreamException
331 private int nextFrame() throws BitstreamException {
332 // entire frame is read by the header class.
333 // header.read_header(this, crc);
334 return header.read_header(this, crc);
338 * Unreads the bytes read from the frame.
340 * @throws BitstreamException
342 // REVIEW: add new error codes for this.
343 public void unreadFrame() throws BitstreamException {
344 if (wordpointer == -1 && bitindex == -1 && (framesize > 0)) {
346 source.unread(frame_bytes, 0, framesize);
347 } catch (IOException ex) {
348 throw newBitstreamException(STREAM_ERROR);
356 public void closeFrame() {
363 * Determines if the next 4 bytes of the stream represent a frame header.
365 public boolean isSyncCurrentPosition(int syncmode) throws BitstreamException {
366 int read = readBytes(syncbuf, 0, 4);
368 ((syncbuf[0] << 24) & 0xFF000000) | ((syncbuf[1] << 16) & 0x00FF0000)
369 | ((syncbuf[2] << 8) & 0x0000FF00) | ((syncbuf[3] << 0) & 0x000000FF);
372 source.unread(syncbuf, 0, read);
373 } catch (IOException ex) {
376 boolean sync = false;
382 sync = isSyncMark(headerstring, syncmode, syncword);
389 // REVIEW: this class should provide inner classes to
390 // parse the frame contents. Eventually, readBits will
392 public int readBits(int n) {
396 public int peek_bits(int number_of_bits) {
398 int peekbitindex = bitindex;
399 int peekPointer = wordpointer;
402 int sum = peekbitindex + number_of_bits;
404 if (peekPointer < 0) {
409 // all bits contained in *wordpointer
410 returnvalue = (framebuffer[peekPointer] >>> (32 - sum)) & bitmask[number_of_bits];
411 // returnvalue = (wordpointer[0] >> (32 - sum)) &
412 // bitmask[number_of_bits];
413 if ((peekbitindex += number_of_bits) == 32) {
415 peekPointer++; // added by me!
420 // E.B : Check that ?
421 // ((short[])&returnvalue)[0] = ((short[])wordpointer + 1)[0];
422 // wordpointer++; // Added by me!
423 // ((short[])&returnvalue + 1)[0] = ((short[])wordpointer)[0];
424 int Right = (framebuffer[peekPointer] & 0x0000FFFF);
426 int Left = (framebuffer[peekPointer] & 0xFFFF0000);
427 returnvalue = ((Right << 16) & 0xFFFF0000) | ((Left >>> 16) & 0x0000FFFF);
429 returnvalue >>>= 48 - sum; // returnvalue >>= 16 - (number_of_bits - (32
431 returnvalue &= bitmask[number_of_bits];
432 peekbitindex = sum - 32;
437 public int readCheckedBits(int n) {
438 // REVIEW: implement CRC check.
442 protected BitstreamException newBitstreamException(int errorcode) {
443 return new BitstreamException(errorcode, null);
446 protected BitstreamException newBitstreamException(int errorcode, Throwable throwable) {
447 return new BitstreamException(errorcode, throwable);
451 * Get next 32 bits from bitstream. They are stored in the headerstring.
452 * syncmod allows Synchro flag ID The returned value is False at the end of
456 int syncHeader(byte syncmode) throws BitstreamException {
459 // read additional 2 bytes
460 int bytesRead = readBytes(syncbuf, 0, 3);
463 throw newBitstreamException(STREAM_EOF, null);
466 ((syncbuf[0] << 16) & 0x00FF0000) | ((syncbuf[1] << 8) & 0x0000FF00)
467 | ((syncbuf[2] << 0) & 0x000000FF);
472 if (readBytes(syncbuf, 3, 1) != 1) {
473 // System.out.println("THROW NEW BITSTREAM EXCEPTION");
475 throw newBitstreamException(STREAM_EOF, null);
478 headerstring |= (syncbuf[3] & 0x000000FF);
480 sync = isSyncMark(headerstring, syncmode, syncword);
483 // current_frame_number++;
484 // if (last_frame_number < current_frame_number) last_frame_number =
485 // current_frame_number;
490 public boolean isSyncMark(int headerstring, int syncmode, int word) {
491 boolean sync = false;
493 if (syncmode == INITIAL_SYNC) {
494 // sync = ((headerstring & 0xFFF00000) == 0xFFF00000);
495 sync = ((headerstring & 0xFFE00000) == 0xFFE00000); // SZD: MPEG 2.5
498 ((headerstring & 0xFFF80C00) == word)
499 && (((headerstring & 0x000000C0) == 0x000000C0) == single_ch_mode);
502 // filter out invalid sample rate
504 sync = (((headerstring >>> 10) & 3) != 3);
505 // filter out invalid layer
507 sync = (((headerstring >>> 17) & 3) != 0);
508 // filter out invalid version
510 sync = (((headerstring >>> 19) & 3) != 1);
516 * Reads the data for the next frame. The frame is not parsed until parse
519 int read_frame_data(int bytesize) throws BitstreamException {
521 numread = readFully(frame_bytes, 0, bytesize);
522 framesize = bytesize;
529 * Parses the data previously read with read_frame_data().
531 @LATTICE("GLOBAL<B,B<BNUM,BNUM<K,K<BYTE,BYTE<THIS,B*,K*,THISLOC=THIS,GLOBALLOC=GLOBAL")
532 void parse_frame() throws BitstreamException {
533 // Convert Bytes read to int
535 @LOC("BYTE") byte[] byteread = frame_bytes;
536 @LOC("BYTE") int bytesize = framesize;
538 // Check ID3v1 TAG (True only if last frame).
539 // for (int t=0;t<(byteread.length)-2;t++)
541 // if ((byteread[t]=='T') && (byteread[t+1]=='A') && (byteread[t+2]=='G'))
543 // System.out.println("ID3v1 detected at offset "+t);
544 // throw newBitstreamException(INVALIDFRAME, null);
548 for (@LOC("K") int k = 0; k < bytesize; k = k + 4) {
549 @LOC("BYTE") int convert = 0;
550 @LOC("BNUM") byte b0 = 0;
551 @LOC("BNUM") byte b1 = 0;
552 @LOC("BNUM") byte b2 = 0;
553 @LOC("BNUM") byte b3 = 0;
555 if (k + 1 < bytesize)
556 b1 = byteread[k + 1];
557 if (k + 2 < bytesize)
558 b2 = byteread[k + 2];
559 if (k + 3 < bytesize)
560 b3 = byteread[k + 3];
562 ((b0 << 24) & 0xFF000000) | ((b1 << 16) & 0x00FF0000) | ((b2 << 8) & 0x0000FF00)
570 * Read bits from buffer into the lower bits of an unsigned int. The LSB
571 * contains the latest read bit of the stream. (1 <= number_of_bits <= 16)
573 @LATTICE("OUT<RL,RL<THIS,THIS<IN,OUT*,THISLOC=THIS,RETURNLOC=OUT")
574 public int get_bits(@LOC("IN") int number_of_bits) {
576 @LOC("OUT") int returnvalue = 0;
577 @LOC("THIS,Bitstream.BI") int sum = bitindex + number_of_bits;
580 // There is a problem here, wordpointer could be -1 ?!
586 // all bits contained in *wordpointer
587 returnvalue = (framebuffer[wordpointer] >>> (32 - sum)) & bitmask[number_of_bits];
588 // returnvalue = (wordpointer[0] >> (32 - sum)) & bitmask[number_of_bits];
589 if ((bitindex += number_of_bits) == 32) {
591 wordpointer++; // added by me!
596 // E.B : Check that ?
597 // ((short[])&returnvalue)[0] = ((short[])wordpointer + 1)[0];
598 // wordpointer++; // Added by me!
599 // ((short[])&returnvalue + 1)[0] = ((short[])wordpointer)[0];
600 @LOC("RL") int Right = (framebuffer[wordpointer] & 0x0000FFFF);
602 @LOC("RL") int Left = (framebuffer[wordpointer] & 0xFFFF0000);
603 returnvalue = ((Right << 16) & 0xFFFF0000) | ((Left >>> 16) & 0x0000FFFF);
605 returnvalue >>>= 48 - sum; // returnvalue >>= 16 - (number_of_bits - (32 -
607 returnvalue &= bitmask[number_of_bits];
613 * Set the word we want to sync the header to. In Big-Endian byte order
615 void set_syncword(@LOC("IN") int syncword0) {
616 syncword = syncword0 & 0xFFFFFF3F;
617 single_ch_mode = ((syncword0 & 0x000000C0) == 0x000000C0);
621 * Reads the exact number of bytes from the source input stream into a byte
625 * The byte array to read the specified number of bytes into.
627 * The index in the array where the first byte read should be stored.
629 * the number of bytes to read.
631 * @exception BitstreamException
632 * is thrown if the specified number of bytes could not be read
635 @LATTICE("OUT<VAR,VAR<THIS,THIS<IN,IN*,VAR*,THISLOC=THIS")
637 private int readFully(@LOC("OUT") byte[] b, @LOC("IN") int offs, @LOC("IN") int len)
638 throws BitstreamException {
639 @LOC("VAR") int nRead = 0;
642 @LOC("IN") int bytesread = source.read(b, offs, len);
643 if (bytesread == -1) {
648 // throw newBitstreamException(UNEXPECTED_EOF, new EOFException());
650 nRead = nRead + bytesread;
654 } catch (IOException ex) {
655 throw newBitstreamException(STREAM_ERROR, ex);
661 * Simlar to readFully, but doesn't throw exception when EOF is reached.
663 @LATTICE("OUT<VAR,VAR<THIS,THIS<IN,IN*,VAR*,THISLOC=THIS")
665 private int readBytes(@LOC("OUT") byte[] b, @LOC("IN") int offs, @LOC("IN") int len)
666 throws BitstreamException {
667 @LOC("VAR") int totalBytesRead = 0;
670 @LOC("IN") int bytesread = source.read(b, offs, len);
671 if (bytesread == -1) {
674 totalBytesRead += bytesread;
678 } catch (IOException ex) {
679 throw newBitstreamException(STREAM_ERROR, ex);
681 return totalBytesRead;
684 public SideInfoBuffer getSideInfoBuffer(int channelType) {
689 SideInfoBuffer sib = new SideInfoBuffer();
691 // first, store main_data_begin from the side inforamtion
692 main_data_begin = peek_bits(9);
695 if (channelType == 1) { // mono
696 max = wordpointer + 4;
698 max = wordpointer + 8;
702 for (; wordpointer < max; wordpointer++) {
703 sib.setBuffer(wordpointer, framebuffer[wordpointer]);
705 } catch (ArrayIndexOutOfBoundsException e) {
706 System.out.print("wordpointer=" + wordpointer);
707 System.out.println("framebuffer length=" + framebuffer.length);
713 public BitReserve getBitReserve(int nSlots) {
716 int bytes_to_discard;
719 for (i = 0; i < nSlots; i++)
720 br.hputbuf(get_bits(8));
722 int main_data_end = br.hsstell() >>> 3; // of previous frame
724 if ((flush_main = (br.hsstell() & 7)) != 0) {
725 br.hgetbits(8 - flush_main);
729 bytes_to_discard = frame_start - main_data_end - main_data_begin;
731 frame_start += nSlots;
733 if (bytes_to_discard < 0) {
737 if (main_data_end > 4096) {
739 br.rewindNbytes(4096);
742 for (; bytes_to_discard > 0; bytes_to_discard--)
745 // resynch index by trusted code
746 br.buf_byte_idx = br.totbit % br.BUFSIZE;