a97504588e6c1c384aef30f8a5bdef79a8906fde
[IRC.git] / Robust / src / Tests / ssJava / mp3decoder / Bitstream.java
1 /*
2  * 11/19/04  1.0 moved to LGPL.
3  * 
4  * 11/17/04      Uncomplete frames discarded. E.B, javalayer@javazoom.net 
5  *
6  * 12/05/03      ID3v2 tag returned. E.B, javalayer@javazoom.net 
7  *
8  * 12/12/99      Based on Ibitstream. Exceptions thrown on errors,
9  *                       Temporary removed seek functionality. mdm@techie.com
10  *
11  * 02/12/99 : Java Conversion by E.B , javalayer@javazoom.net
12  *
13  * 04/14/97 : Added function prototypes for new syncing and seeking
14  * mechanisms. Also made this file portable. Changes made by Jeff Tsay
15  *
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.
24  *
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.
29  *
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  *----------------------------------------------------------------------
34  */
35
36
37 /**
38  * The <code>Bistream</code> class is responsible for parsing
39  * an MPEG audio bitstream.
40  *
41  * <b>REVIEW:</b> much of the parsing currently occurs in the
42  * various decoders. This should be moved into this class and associated
43  * inner classes.
44  */
45 @LATTICE("FB<F,FF<F,WP<BI,FF*,WP*,BI*")
46 @METHODDEFAULT("OUT<THIS,THIS<VAR,VAR<IN,VAR*,THISLOC=THIS,GLOBALLOC=IN")
47 public final class Bitstream implements BitstreamErrors
48 {
49         /**
50          * Synchronization control constant for the initial
51          * synchronization to the start of a frame.
52          */
53         @LOC("F") static byte           INITIAL_SYNC = 0;
54
55         /**
56          * Synchronization control constant for non-initial frame
57          * synchronizations.
58          */
59
60         @LOC("F") static byte           STRICT_SYNC = 1;
61
62         // max. 1730 bytes per frame: 144 * 384kbit/s / 32000 Hz + 2 Bytes CRC
63         /**
64          * Maximum size of the frame buffer.
65          */
66         @LOC("F") private static final int      BUFFER_INT_SIZE = 433;
67
68         /**
69          * The frame buffer that holds the data for the current frame.
70          */
71         @LOC("FB") private final int[]          framebuffer = new int[BUFFER_INT_SIZE];
72
73         /**
74          * Number of valid bytes in the frame buffer.
75          */
76         @LOC("F") private int                           framesize;
77
78         /**
79          * The bytes read from the stream.
80          */
81         @LOC("FB") private byte[]                       frame_bytes = new byte[BUFFER_INT_SIZE*4];
82
83         /**
84          * Index into <code>framebuffer</code> where the next bits are
85          * retrieved.
86          */
87         @LOC("WP") private int                          wordpointer;
88
89         /**
90          * Number (0-31, from MSB to LSB) of next bit for get_bits()
91          */
92         @LOC("BI") private int                          bitindex;
93
94         /**
95          * The current specified syncword
96          */
97         @LOC("F") private int                           syncword;
98         
99         /**
100          * Audio header position in stream.
101          */
102         @LOC("F")private int                            header_pos = 0;
103
104         /**
105          *
106          */
107         @LOC("F") private boolean                       single_ch_mode;
108   //private int                         current_frame_number;
109   //private int                         last_frame_number;
110
111         @LOC("F") private final int             bitmask[] = {0, // dummy
112          0x00000001, 0x00000003, 0x00000007, 0x0000000F,
113          0x0000001F, 0x0000003F, 0x0000007F, 0x000000FF,
114          0x000001FF, 0x000003FF, 0x000007FF, 0x00000FFF,
115          0x00001FFF, 0x00003FFF, 0x00007FFF, 0x0000FFFF,
116      0x0001FFFF };
117
118         @LOC("F") private final PushbackInputStream     source;
119
120         @LOC("F") private final Header                  header = new Header();
121
122         @LOC("F") private final byte                            syncbuf[] = new byte[4];
123
124         @LOC("F") private Crc16[]                                       crc = new Crc16[1];
125
126         @LOC("F") private byte[]                                        rawid3v2 = null;
127
128         @LOC("FF") private boolean                                      firstframe = true;
129
130
131         /**
132          * Construct a IBitstream that reads data from a
133          * given InputStream.
134          *
135          * @param in    The InputStream to read from.
136          */
137         public Bitstream(InputStream in)
138         {
139                 if (in==null) throw new NullPointerException("in");
140                 in = new BufferedInputStream(in);               
141                 loadID3v2(in);
142                 firstframe = true;
143                 //source = new PushbackInputStream(in, 1024);
144                 source = new PushbackInputStream(in, BUFFER_INT_SIZE*4);
145                 
146                 closeFrame();
147                 //current_frame_number = -1;
148                 //last_frame_number = -1;
149         }
150
151         /**
152          * Return position of the first audio header.
153          * @return size of ID3v2 tag frames.
154          */
155         public int header_pos()
156         {
157                 return header_pos;
158         }
159         
160         /**
161          * Load ID3v2 frames.
162          * @param in MP3 InputStream.
163          * @author JavaZOOM
164          */
165         private void loadID3v2(InputStream in)
166         {               
167                 int size = -1;
168                 try
169                 {
170                         // Read ID3v2 header (10 bytes).
171                         in.mark(10);                    
172                         size = readID3v2Header(in);
173                         header_pos = size;                      
174                 }
175                 catch (IOException e)
176                 {}
177                 finally
178                 {
179                         try
180                         {
181                                 // Unread ID3v2 header (10 bytes).
182                                 in.reset();
183                         }
184                         catch (IOException e)
185                         {}
186                 }
187                 // Load ID3v2 tags.
188                 try
189                 {
190                         if (size > 0)
191                         {
192                                 rawid3v2 = new byte[size];
193                                 in.read(rawid3v2,0,rawid3v2.length);
194                         }                       
195                 }
196                 catch (IOException e)
197                 {}
198         }
199         
200         /**
201          * Parse ID3v2 tag header to find out size of ID3v2 frames. 
202          * @param in MP3 InputStream
203          * @return size of ID3v2 frames + header
204          * @throws IOException
205          * @author JavaZOOM
206          */
207         private int readID3v2Header(InputStream in) throws IOException
208         {               
209                 byte[] id3header = new byte[4];
210                 int size = -10;
211                 in.read(id3header,0,3);
212                 // Look for ID3v2
213                 if ( (id3header[0]=='I') && (id3header[1]=='D') && (id3header[2]=='3'))
214                 {
215                         in.read(id3header,0,3);
216                         int majorVersion = id3header[0];
217                         int revision = id3header[1];
218                         in.read(id3header,0,4);
219                         size = (int) (id3header[0] << 21) + (id3header[1] << 14) + (id3header[2] << 7) + (id3header[3]);
220                 }
221                 return (size+10);
222         }
223         
224         /**
225          * Return raw ID3v2 frames + header.
226          * @return ID3v2 InputStream or null if ID3v2 frames are not available.
227          */
228         public InputStream getRawID3v2()
229         {
230                 if (rawid3v2 == null) return null;
231                 else
232                 {
233                         ByteArrayInputStream bain = new ByteArrayInputStream(rawid3v2);         
234                         return bain;
235                 }
236         }
237
238         /**
239          * Close the Bitstream.
240          * @throws BitstreamException
241          */
242         public void close() throws BitstreamException
243         {
244                 try
245                 {
246                         source.close();
247                 }
248                 catch (IOException ex)
249                 {
250                         throw newBitstreamException(STREAM_ERROR, ex);
251                 }
252         }
253
254         /**
255          * Reads and parses the next frame from the input source.
256          * @return the Header describing details of the frame read,
257          *      or null if the end of the stream has been reached.
258          */
259         public Header readFrame() throws BitstreamException
260         {
261                 Header result = null;
262                 try
263                 {
264                         result = readNextFrame();
265                         // E.B, Parse VBR (if any) first frame.
266                         if (firstframe == true)
267                         {
268                                 result.parseVBR(frame_bytes);
269                                 firstframe = false;
270                         }                       
271                 }
272                 catch (BitstreamException ex)
273                 {
274                         if ((ex.getErrorCode()==INVALIDFRAME))
275                         {
276                                 // Try to skip this frame.
277                                 //System.out.println("INVALIDFRAME");
278                                 try
279                                 {
280                                         closeFrame();
281                                         result = readNextFrame();
282                                 }
283                                 catch (BitstreamException e)
284                                 {
285                                         if ((e.getErrorCode()!=STREAM_EOF))
286                                         {
287                                                 // wrap original exception so stack trace is maintained.
288                                                 throw newBitstreamException(e.getErrorCode(), e);
289                                         }
290                                 }
291                         }
292                         else if ((ex.getErrorCode()!=STREAM_EOF))
293                         {
294                                 // wrap original exception so stack trace is maintained.
295                                 throw newBitstreamException(ex.getErrorCode(), ex);
296                         }
297                 }
298                 return result;
299         }
300
301         /**
302          * Read next MP3 frame.
303          * @return MP3 frame header.
304          * @throws BitstreamException
305          */
306         private Header readNextFrame() throws BitstreamException
307         {
308                 if (framesize == -1)
309                 {
310                         nextFrame();
311                 }
312                 return header;
313         }
314
315
316         /**
317          * Read next MP3 frame.
318          * @throws BitstreamException
319          */
320         private void nextFrame() throws BitstreamException
321         {
322                 // entire frame is read by the header class.
323                 header.read_header(this, crc);
324         }
325
326         /**
327          * Unreads the bytes read from the frame.
328          * @throws BitstreamException
329          */
330         // REVIEW: add new error codes for this.
331         public void unreadFrame() throws BitstreamException
332         {
333                 if (wordpointer==-1 && bitindex==-1 && (framesize>0))
334                 {
335                         try
336                         {
337                                 source.unread(frame_bytes, 0, framesize);
338                         }
339                         catch (IOException ex)
340                         {
341                                 throw newBitstreamException(STREAM_ERROR);
342                         }
343                 }
344         }
345
346         /**
347          * Close MP3 frame.
348          */
349         public void closeFrame()
350         {
351                 framesize = -1;
352                 wordpointer = -1;
353                 bitindex = -1;
354         }
355
356         /**
357          * Determines if the next 4 bytes of the stream represent a
358          * frame header.
359          */
360         public boolean isSyncCurrentPosition(int syncmode) throws BitstreamException
361         {
362                 int read = readBytes(syncbuf, 0, 4);
363                 int headerstring = ((syncbuf[0] << 24) & 0xFF000000) | ((syncbuf[1] << 16) & 0x00FF0000) | ((syncbuf[2] << 8) & 0x0000FF00) | ((syncbuf[3] << 0) & 0x000000FF);
364
365                 try
366                 {
367                         source.unread(syncbuf, 0, read);
368                 }
369                 catch (IOException ex)
370                 {
371                 }
372
373                 boolean sync = false;
374                 switch (read)
375                 {
376                         case 0:
377                                 sync = true;
378                                 break;
379                         case 4:
380                                 sync = isSyncMark(headerstring, syncmode, syncword);
381                                 break;
382                 }
383
384                 return sync;
385         }
386
387
388         // REVIEW: this class should provide inner classes to
389         // parse the frame contents. Eventually, readBits will
390         // be removed.
391         public int readBits(int n)
392         {
393                 return get_bits(n);
394         }
395
396         public int readCheckedBits(int n)
397         {
398                 // REVIEW: implement CRC check.
399                 return get_bits(n);
400         }
401
402         protected BitstreamException newBitstreamException(int errorcode)
403         {
404                 return new BitstreamException(errorcode, null);
405         }
406         protected BitstreamException newBitstreamException(int errorcode, Throwable throwable)
407         {
408                 return new BitstreamException(errorcode, throwable);
409         }
410
411   /**
412    * Get next 32 bits from bitstream.
413    * They are stored in the headerstring.
414    * syncmod allows Synchro flag ID
415    * The returned value is False at the end of stream.
416    */
417
418         int syncHeader(byte syncmode) throws BitstreamException
419         {
420                 boolean sync;
421                 int headerstring;
422                 // read additional 2 bytes
423                 int bytesRead = readBytes(syncbuf, 0, 3);
424
425                 if (bytesRead!=3) throw newBitstreamException(STREAM_EOF, null);
426
427                 headerstring = ((syncbuf[0] << 16) & 0x00FF0000) | ((syncbuf[1] << 8) & 0x0000FF00) | ((syncbuf[2] << 0) & 0x000000FF);
428
429                 do
430                 {
431                         headerstring <<= 8;
432
433                         if (readBytes(syncbuf, 3, 1)!=1)
434                                 throw newBitstreamException(STREAM_EOF, null);
435
436                         headerstring |= (syncbuf[3] & 0x000000FF);
437
438                         sync = isSyncMark(headerstring, syncmode, syncword);
439                 }
440                 while (!sync);
441
442                 //current_frame_number++;
443                 //if (last_frame_number < current_frame_number) last_frame_number = current_frame_number;
444
445                 return headerstring;
446         }
447
448         public boolean isSyncMark(int headerstring, int syncmode, int word)
449         {
450                 boolean sync = false;
451
452                 if (syncmode == INITIAL_SYNC)
453                 {
454                         //sync =  ((headerstring & 0xFFF00000) == 0xFFF00000);
455                         sync =  ((headerstring & 0xFFE00000) == 0xFFE00000);    // SZD: MPEG 2.5
456                 }
457                 else
458                 {
459                         sync =  ((headerstring & 0xFFF80C00) == word) &&
460                             (((headerstring & 0x000000C0) == 0x000000C0) == single_ch_mode);
461                 }
462
463                 // filter out invalid sample rate
464                 if (sync)
465                         sync = (((headerstring >>> 10) & 3)!=3);
466                 // filter out invalid layer
467                 if (sync)
468                         sync = (((headerstring >>> 17) & 3)!=0);
469                 // filter out invalid version
470                 if (sync)
471                         sync = (((headerstring >>> 19) & 3)!=1);
472
473                 return sync;
474         }
475
476         /**
477          * Reads the data for the next frame. The frame is not parsed
478          * until parse frame is called.
479          */
480         int read_frame_data(int bytesize) throws BitstreamException
481         {
482                 int     numread = 0;
483                 numread = readFully(frame_bytes, 0, bytesize);
484                 framesize = bytesize;
485                 wordpointer = -1;
486             bitindex = -1;
487             return numread;
488         }
489
490   /**
491    * Parses the data previously read with read_frame_data().
492    */
493   @LATTICE("GLOBAL<B,B<BNUM,BNUM<K,K<BYTE,BYTE<THIS,B*,K*,THISLOC=THIS,GLOBALLOC=GLOBAL")
494   void parse_frame() throws BitstreamException
495   {
496         // Convert Bytes read to int
497         @LOC("B") int   b=0;
498         @LOC("BYTE") byte[] byteread = frame_bytes;
499         @LOC("BYTE") int bytesize = framesize;
500
501         // Check ID3v1 TAG (True only if last frame).
502         //for (int t=0;t<(byteread.length)-2;t++)
503         //{
504         //      if ((byteread[t]=='T') && (byteread[t+1]=='A') && (byteread[t+2]=='G'))
505         //      {
506         //              System.out.println("ID3v1 detected at offset "+t);
507         //              throw newBitstreamException(INVALIDFRAME, null);
508         //      }       
509         //}
510         
511         for (@LOC("K") int k=0;k<bytesize;k=k+4)
512         {
513                 @LOC("BYTE") int convert = 0;
514                 @LOC("BNUM") byte b0 = 0;
515                 @LOC("BNUM") byte b1 = 0;
516                 @LOC("BNUM") byte b2 = 0;
517                 @LOC("BNUM") byte b3 = 0;
518                 b0 = byteread[k];
519                 if (k+1<bytesize) b1 = byteread[k+1];
520                 if (k+2<bytesize) b2 = byteread[k+2];
521                 if (k+3<bytesize) b3 = byteread[k+3];
522                 framebuffer[b++] = ((b0 << 24) &0xFF000000) | ((b1 << 16) & 0x00FF0000) | ((b2 << 8) & 0x0000FF00) | (b3 & 0x000000FF);
523         }
524         wordpointer = 0;
525     bitindex = 0;
526   }
527
528   /**
529    * Read bits from buffer into the lower bits of an unsigned int.
530    * The LSB contains the latest read bit of the stream.
531    * (1 <= number_of_bits <= 16)
532    */
533   @LATTICE("OUT<RL,RL<THIS,THIS<IN,OUT*,THISLOC=THIS")
534   @RETURNLOC("OUT") 
535   public int get_bits(@LOC("IN")int number_of_bits)
536   {
537         @LOC("OUT") int                         returnvalue = 0;
538         @LOC("THIS,Bitstream.BI") int                   sum = bitindex + number_of_bits;
539
540         // E.B
541         // There is a problem here, wordpointer could be -1 ?!
542     if (wordpointer < 0) wordpointer = 0;
543     // E.B : End.
544
545         if (sum <= 32)
546         {
547            // all bits contained in *wordpointer
548            returnvalue = (framebuffer[wordpointer] >>> (32 - sum)) & bitmask[number_of_bits];
549            // returnvalue = (wordpointer[0] >> (32 - sum)) & bitmask[number_of_bits];
550            if ((bitindex += number_of_bits) == 32)
551            {
552                  bitindex = 0;
553                  wordpointer++; // added by me!
554            }
555            return returnvalue;
556     }
557
558     // E.B : Check that ?
559     //((short[])&returnvalue)[0] = ((short[])wordpointer + 1)[0];
560     //wordpointer++; // Added by me!
561     //((short[])&returnvalue + 1)[0] = ((short[])wordpointer)[0];
562         @LOC("RL") int Right = (framebuffer[wordpointer] & 0x0000FFFF);
563         wordpointer++;
564         @LOC("RL") int Left = (framebuffer[wordpointer] & 0xFFFF0000);
565         returnvalue = ((Right << 16) & 0xFFFF0000) | ((Left >>> 16)& 0x0000FFFF);
566
567     returnvalue >>>= 48 - sum;  // returnvalue >>= 16 - (number_of_bits - (32 - bitindex))
568     returnvalue &= bitmask[number_of_bits];
569     bitindex = sum - 32;
570     return returnvalue;
571 }
572
573         /**
574          * Set the word we want to sync the header to.
575          * In Big-Endian byte order
576          */
577         void set_syncword(@LOC("IN") int syncword0)
578         {
579                 syncword = syncword0 & 0xFFFFFF3F;
580                 single_ch_mode = ((syncword0 & 0x000000C0) == 0x000000C0);
581         }
582         /**
583          * Reads the exact number of bytes from the source
584          * input stream into a byte array.
585          *
586          * @param b             The byte array to read the specified number
587          *                              of bytes into.
588          * @param offs  The index in the array where the first byte
589          *                              read should be stored.
590          * @param len   the number of bytes to read.
591          *
592          * @exception BitstreamException is thrown if the specified
593          *              number of bytes could not be read from the stream.
594          */
595         @LATTICE("OUT<VAR,VAR<THIS,THIS<IN,IN*,VAR*,THISLOC=THIS")
596         @RETURNLOC("OUT") 
597         private int readFully(@LOC("OUT") byte[] b, @LOC("IN") int offs, @LOC("IN") int len)
598                 throws BitstreamException
599         {               
600                 @LOC("VAR") int nRead = 0;
601                 try
602                 {
603                         while (len > 0)
604                         {
605                                 @LOC("IN") int bytesread = source.read(b, offs, len);
606                                 if (bytesread == -1)
607                                 {
608                                         while (len-->0)
609                                         {
610                                                 b[offs++] = 0;
611                                         }
612                                         break;
613                                         //throw newBitstreamException(UNEXPECTED_EOF, new EOFException());
614                                 }
615                                 nRead = nRead + bytesread;
616                                 offs += bytesread;
617                                 len -= bytesread;
618                         }
619                 }
620                 catch (IOException ex)
621                 {
622                         throw newBitstreamException(STREAM_ERROR, ex);
623                 }
624                 return nRead;
625         }
626
627         /**
628          * Simlar to readFully, but doesn't throw exception when
629          * EOF is reached.
630          */
631         @LATTICE("OUT<VAR,VAR<THIS,THIS<IN,IN*,VAR*,THISLOC=THIS")
632         @RETURNLOC("OUT") 
633         private int readBytes(@LOC("OUT") byte[] b, @LOC("IN") int offs, @LOC("IN") int len)
634              throws BitstreamException
635         {
636             @LOC("VAR") int totalBytesRead = 0;
637                 try
638                 {
639                         while (len > 0)
640                         {
641                                 @LOC("IN") int bytesread = source.read(b, offs, len);
642                                 if (bytesread == -1)
643                                 {
644                                         break;
645                                 }
646                                 totalBytesRead += bytesread;
647                                 offs += bytesread;
648                                 len -= bytesread;
649                         }
650                 }
651                 catch (IOException ex)
652                 {
653                         throw newBitstreamException(STREAM_ERROR, ex);
654                 }
655                 return totalBytesRead;
656         }
657 }