add another test case for ssjava:
[IRC.git] / Robust / src / Tests / ssJava / mp3decoder / Header.java
diff --git a/Robust/src/Tests/ssJava/mp3decoder/Header.java b/Robust/src/Tests/ssJava/mp3decoder/Header.java
new file mode 100644 (file)
index 0000000..a36572d
--- /dev/null
@@ -0,0 +1,762 @@
+/*\r
+ * 11/19/04 : 1.0 moved to LGPL.\r
+ *            VBRI header support added, E.B javalayer@javazoom.net\r
+ * \r
+ * 12/04/03 : VBR (XING) header support added, E.B javalayer@javazoom.net\r
+ *\r
+ * 02/13/99 : Java Conversion by JavaZOOM , E.B javalayer@javazoom.net\r
+ *\r
+ * Declarations for MPEG header class\r
+ * A few layer III, MPEG-2 LSF, and seeking modifications made by Jeff Tsay.\r
+ * Last modified : 04/19/97\r
+ *\r
+ *  @(#) header.h 1.7, last edit: 6/15/94 16:55:33\r
+ *  @(#) Copyright (C) 1993, 1994 Tobias Bading (bading@cs.tu-berlin.de)\r
+ *  @(#) Berlin University of Technology\r
+ *-----------------------------------------------------------------------\r
+ *   This program is free software; you can redistribute it and/or modify\r
+ *   it under the terms of the GNU Library General Public License as published\r
+ *   by the Free Software Foundation; either version 2 of the License, or\r
+ *   (at your option) any later version.\r
+ *\r
+ *   This program is distributed in the hope that it will be useful,\r
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *   GNU Library General Public License for more details.\r
+ *\r
+ *   You should have received a copy of the GNU Library General Public\r
+ *   License along with this program; if not, write to the Free Software\r
+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\r
+ *----------------------------------------------------------------------\r
+ */\r
+package javazoom.jl.decoder;\r
+\r
+/**\r
+ * Class for extracting information from a frame header.\r
+ */\r
+public final class Header\r
+{\r
+       public  static final int[][]    frequencies =\r
+                                               {{22050, 24000, 16000, 1},\r
+                                               {44100, 48000, 32000, 1},\r
+                                               {11025, 12000, 8000, 1}};       // SZD: MPEG25\r
+\r
+       /**\r
+        * Constant for MPEG-2 LSF version\r
+        */\r
+       public static final int         MPEG2_LSF = 0;\r
+       public static final int         MPEG25_LSF = 2; // SZD\r
+\r
+       /**\r
+        * Constant for MPEG-1 version\r
+        */\r
+       public static final int         MPEG1 = 1;\r
+\r
+       public static final int         STEREO = 0;\r
+       public static final int         JOINT_STEREO = 1;\r
+       public static final int         DUAL_CHANNEL = 2;\r
+       public static final int         SINGLE_CHANNEL = 3;\r
+       public static final int         FOURTYFOUR_POINT_ONE = 0;\r
+       public static final int         FOURTYEIGHT=1;\r
+       public static final int         THIRTYTWO=2;\r
+\r
+       private int                             h_layer, h_protection_bit, h_bitrate_index,\r
+                                                       h_padding_bit, h_mode_extension;\r
+       private int                             h_version;\r
+       private int                             h_mode;\r
+       private int                             h_sample_frequency;\r
+       private int                             h_number_of_subbands, h_intensity_stereo_bound;\r
+       private boolean                 h_copyright, h_original;\r
+       // VBR support added by E.B\r
+       private double[]                h_vbr_time_per_frame = {-1, 384, 1152, 1152};\r
+       private boolean                 h_vbr;\r
+       private int                             h_vbr_frames;\r
+       private int                             h_vbr_scale;\r
+       private int                             h_vbr_bytes;\r
+       private byte[]                  h_vbr_toc;\r
+       \r
+       private byte                    syncmode = Bitstream.INITIAL_SYNC;\r
+       private Crc16                   crc;\r
+\r
+       public short                    checksum;\r
+       public int                              framesize;\r
+       public int                              nSlots;\r
+\r
+       private int                             _headerstring = -1; // E.B\r
+\r
+       Header()\r
+       {\r
+       }\r
+       public String toString()\r
+       {\r
+               StringBuffer buffer = new StringBuffer(200);\r
+               buffer.append("Layer ");\r
+               buffer.append(layer_string());\r
+               buffer.append(" frame ");\r
+               buffer.append(mode_string());\r
+               buffer.append(' ');\r
+               buffer.append(version_string());\r
+               if (!checksums())\r
+                       buffer.append(" no");\r
+               buffer.append(" checksums");\r
+               buffer.append(' ');\r
+               buffer.append(sample_frequency_string());\r
+               buffer.append(',');\r
+               buffer.append(' ');\r
+               buffer.append(bitrate_string());\r
+\r
+               String s =  buffer.toString();\r
+               return s;\r
+       }\r
+\r
+       /**\r
+        * Read a 32-bit header from the bitstream.\r
+        */\r
+       void read_header(Bitstream stream, Crc16[] crcp) throws BitstreamException\r
+       {\r
+               int headerstring;\r
+               int channel_bitrate;\r
+               boolean sync = false;\r
+               do\r
+               {\r
+                       headerstring = stream.syncHeader(syncmode);\r
+                       _headerstring = headerstring; // E.B\r
+                       if (syncmode == Bitstream.INITIAL_SYNC)\r
+                       {\r
+                               h_version = ((headerstring >>> 19) & 1);\r
+                               if (((headerstring >>> 20) & 1) == 0) // SZD: MPEG2.5 detection\r
+                                       if (h_version == MPEG2_LSF)\r
+                                               h_version = MPEG25_LSF;\r
+                                       else\r
+                                               throw stream.newBitstreamException(Bitstream.UNKNOWN_ERROR);\r
+                               if ((h_sample_frequency = ((headerstring >>> 10) & 3)) == 3)\r
+                               {\r
+                                       throw stream.newBitstreamException(Bitstream.UNKNOWN_ERROR);\r
+                               }\r
+                       }\r
+                       h_layer = 4 - (headerstring >>> 17) & 3;\r
+                       h_protection_bit = (headerstring >>> 16) & 1;\r
+                       h_bitrate_index = (headerstring >>> 12) & 0xF;\r
+                       h_padding_bit = (headerstring >>> 9) & 1;\r
+                       h_mode = ((headerstring >>> 6) & 3);\r
+                       h_mode_extension = (headerstring >>> 4) & 3;\r
+                       if (h_mode == JOINT_STEREO)\r
+                               h_intensity_stereo_bound = (h_mode_extension << 2) + 4;\r
+                       else\r
+                               h_intensity_stereo_bound = 0; // should never be used\r
+                       if (((headerstring >>> 3) & 1) == 1)\r
+                               h_copyright = true;\r
+                       if (((headerstring >>> 2) & 1) == 1)\r
+                               h_original = true;\r
+                       // calculate number of subbands:\r
+                       if (h_layer == 1)\r
+                               h_number_of_subbands = 32;\r
+                       else\r
+                       {\r
+                               channel_bitrate = h_bitrate_index;\r
+                               // calculate bitrate per channel:\r
+                               if (h_mode != SINGLE_CHANNEL)\r
+                                       if (channel_bitrate == 4)\r
+                                               channel_bitrate = 1;\r
+                                       else\r
+                                               channel_bitrate -= 4;\r
+                               if ((channel_bitrate == 1) || (channel_bitrate == 2))\r
+                                       if (h_sample_frequency == THIRTYTWO)\r
+                                               h_number_of_subbands = 12;\r
+                                       else\r
+                                               h_number_of_subbands = 8;\r
+                               else if ((h_sample_frequency == FOURTYEIGHT) || ((channel_bitrate >= 3) && (channel_bitrate <= 5)))\r
+                                       h_number_of_subbands = 27;\r
+                               else\r
+                                       h_number_of_subbands = 30;\r
+                       }\r
+                       if (h_intensity_stereo_bound > h_number_of_subbands)\r
+                               h_intensity_stereo_bound = h_number_of_subbands;\r
+                       // calculate framesize and nSlots\r
+                       calculate_framesize();\r
+                       // read framedata:\r
+                       int framesizeloaded = stream.read_frame_data(framesize);\r
+                       if ((framesize >=0) && (framesizeloaded != framesize))\r
+                       {\r
+                               // Data loaded does not match to expected framesize,\r
+                               // it might be an ID3v1 TAG. (Fix 11/17/04).\r
+                               throw stream.newBitstreamException(Bitstream.INVALIDFRAME);\r
+                       }\r
+                       if (stream.isSyncCurrentPosition(syncmode))\r
+                       {\r
+                               if (syncmode == Bitstream.INITIAL_SYNC)\r
+                               {\r
+                                       syncmode = Bitstream.STRICT_SYNC;\r
+                                       stream.set_syncword(headerstring & 0xFFF80CC0);\r
+                               }\r
+                               sync = true;\r
+                       }\r
+                       else\r
+                       {\r
+                               stream.unreadFrame();\r
+                       }\r
+               }\r
+               while (!sync);\r
+               stream.parse_frame();\r
+               if (h_protection_bit == 0)\r
+               {\r
+                       // frame contains a crc checksum\r
+                       checksum = (short) stream.get_bits(16);\r
+                       if (crc == null)\r
+                               crc = new Crc16();\r
+                       crc.add_bits(headerstring, 16);\r
+                       crcp[0] = crc;\r
+               }\r
+               else\r
+                       crcp[0] = null;\r
+               if (h_sample_frequency == FOURTYFOUR_POINT_ONE)\r
+               {\r
+                       /*\r
+                               if (offset == null)\r
+                         {\r
+                                 int max = max_number_of_frames(stream);\r
+                                 offset = new int[max];\r
+                            for(int i=0; i<max; i++) offset[i] = 0;\r
+                         }\r
+                         // E.B : Investigate more\r
+                         int cf = stream.current_frame();\r
+                         int lf = stream.last_frame();\r
+                         if ((cf > 0) && (cf == lf))\r
+                         {\r
+                                  offset[cf] = offset[cf-1] + h_padding_bit;\r
+                         }\r
+                         else\r
+                         {\r
+                                      offset[0] = h_padding_bit;\r
+                         }\r
+                       */\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Parse frame to extract optionnal VBR frame.\r
+        * @param firstframe\r
+        * @author E.B (javalayer@javazoom.net)\r
+        */\r
+       void parseVBR(byte[] firstframe) throws BitstreamException\r
+       {\r
+               // Trying Xing header.\r
+               String xing = "Xing";\r
+               byte tmp[] = new byte[4];\r
+               int offset = 0;\r
+               // Compute "Xing" offset depending on MPEG version and channels.\r
+               if (h_version == MPEG1) \r
+               {\r
+                 if (h_mode == SINGLE_CHANNEL)  offset=21-4;\r
+                 else offset=36-4;\r
+               } \r
+               else \r
+               {\r
+                 if (h_mode == SINGLE_CHANNEL) offset=13-4;\r
+                 else offset = 21-4;             \r
+               }\r
+               try\r
+               {\r
+                       System.arraycopy(firstframe, offset, tmp, 0, 4);\r
+                       // Is "Xing" ?\r
+                       if (xing.equals(new String(tmp)))\r
+                       {\r
+                               //Yes.\r
+                               h_vbr = true;\r
+                               h_vbr_frames = -1;\r
+                               h_vbr_bytes = -1;\r
+                               h_vbr_scale = -1;\r
+                               h_vbr_toc = new byte[100];\r
+                                                               \r
+                               int length = 4;\r
+                               // Read flags.\r
+                               byte flags[] = new byte[4];\r
+                               System.arraycopy(firstframe, offset + length, flags, 0, flags.length);\r
+                               length += flags.length;\r
+                               // Read number of frames (if available).\r
+                               if ((flags[3] & (byte) (1 << 0)) != 0)\r
+                               {\r
+                                       System.arraycopy(firstframe, offset + length, tmp, 0, tmp.length);\r
+                                       h_vbr_frames = (tmp[0] << 24)&0xFF000000 | (tmp[1] << 16)&0x00FF0000 | (tmp[2] << 8)&0x0000FF00 | tmp[3]&0x000000FF;\r
+                                       length += 4;    \r
+                               }\r
+                               // Read size (if available).\r
+                               if ((flags[3] & (byte) (1 << 1)) != 0)\r
+                               {\r
+                                       System.arraycopy(firstframe, offset + length, tmp, 0, tmp.length);\r
+                                       h_vbr_bytes = (tmp[0] << 24)&0xFF000000 | (tmp[1] << 16)&0x00FF0000 | (tmp[2] << 8)&0x0000FF00 | tmp[3]&0x000000FF;\r
+                                       length += 4;    \r
+                               }\r
+                               // Read TOC (if available).\r
+                               if ((flags[3] & (byte) (1 << 2)) != 0)\r
+                               {\r
+                                       System.arraycopy(firstframe, offset + length, h_vbr_toc, 0, h_vbr_toc.length);\r
+                                       length += h_vbr_toc.length;     \r
+                               }\r
+                               // Read scale (if available).\r
+                               if ((flags[3] & (byte) (1 << 3)) != 0)\r
+                               {\r
+                                       System.arraycopy(firstframe, offset + length, tmp, 0, tmp.length);\r
+                                       h_vbr_scale = (tmp[0] << 24)&0xFF000000 | (tmp[1] << 16)&0x00FF0000 | (tmp[2] << 8)&0x0000FF00 | tmp[3]&0x000000FF;\r
+                                       length += 4;    \r
+                               }\r
+                               //System.out.println("VBR:"+xing+" Frames:"+ h_vbr_frames +" Size:"+h_vbr_bytes);                       \r
+                       }                               \r
+               }\r
+               catch (ArrayIndexOutOfBoundsException e)\r
+               {\r
+                       throw new BitstreamException("XingVBRHeader Corrupted",e);\r
+               }\r
+               \r
+               // Trying VBRI header.                  \r
+               String vbri = "VBRI";\r
+               offset = 36-4;\r
+               try\r
+               {\r
+                       System.arraycopy(firstframe, offset, tmp, 0, 4);\r
+                       // Is "VBRI" ?\r
+                       if (vbri.equals(new String(tmp)))\r
+                       {\r
+                               //Yes.\r
+                               h_vbr = true;\r
+                               h_vbr_frames = -1;\r
+                               h_vbr_bytes = -1;\r
+                               h_vbr_scale = -1;\r
+                               h_vbr_toc = new byte[100];\r
+                               // Bytes.                               \r
+                               int length = 4 + 6;\r
+                               System.arraycopy(firstframe, offset + length, tmp, 0, tmp.length);\r
+                               h_vbr_bytes = (tmp[0] << 24)&0xFF000000 | (tmp[1] << 16)&0x00FF0000 | (tmp[2] << 8)&0x0000FF00 | tmp[3]&0x000000FF;\r
+                               length += 4;    \r
+                               // Frames.      \r
+                               System.arraycopy(firstframe, offset + length, tmp, 0, tmp.length);\r
+                               h_vbr_frames = (tmp[0] << 24)&0xFF000000 | (tmp[1] << 16)&0x00FF0000 | (tmp[2] << 8)&0x0000FF00 | tmp[3]&0x000000FF;\r
+                               length += 4;    \r
+                               //System.out.println("VBR:"+vbri+" Frames:"+ h_vbr_frames +" Size:"+h_vbr_bytes);\r
+                               // TOC\r
+                               // TODO                         \r
+                       }\r
+               }\r
+               catch (ArrayIndexOutOfBoundsException e)\r
+               {\r
+                       throw new BitstreamException("VBRIVBRHeader Corrupted",e);\r
+               }\r
+       }\r
+       \r
+       // Functions to query header contents:\r
+       /**\r
+        * Returns version.\r
+        */\r
+       public int version() { return h_version; }\r
+\r
+       /**\r
+        * Returns Layer ID.\r
+        */\r
+       public int layer() { return h_layer; }\r
+\r
+       /**\r
+        * Returns bitrate index.\r
+        */\r
+       public int bitrate_index() { return h_bitrate_index; }\r
+\r
+       /**\r
+        * Returns Sample Frequency.\r
+        */\r
+       public int sample_frequency() { return h_sample_frequency; }\r
+\r
+       /**\r
+        * Returns Frequency.\r
+        */\r
+       public int frequency() {return frequencies[h_version][h_sample_frequency];}\r
+\r
+       /**\r
+        * Returns Mode.\r
+        */\r
+       public int mode() { return h_mode; }\r
+\r
+       /**\r
+        * Returns Protection bit.\r
+        */\r
+       public boolean checksums()\r
+       {\r
+               if (h_protection_bit == 0) return true;\r
+         else return false;\r
+       }\r
+\r
+       /**\r
+        * Returns Copyright.\r
+        */\r
+       public boolean copyright() { return h_copyright; }\r
+\r
+       /**\r
+        * Returns Original.\r
+        */\r
+       public boolean original() { return h_original; }\r
+\r
+       /**\r
+        * Return VBR.\r
+        * @return true if VBR header is found\r
+        */\r
+       public boolean vbr() { return h_vbr; }\r
+\r
+       /**\r
+        * Return VBR scale.\r
+        * @return scale of -1 if not available\r
+        */\r
+       public int vbr_scale() { return h_vbr_scale; }\r
+\r
+       /**\r
+        * Return VBR TOC.\r
+        * @return vbr toc ot null if not available\r
+        */\r
+       public byte[] vbr_toc() { return h_vbr_toc; }\r
+\r
+       /**\r
+        * Returns Checksum flag.\r
+        * Compares computed checksum with stream checksum.\r
+        */\r
+       public boolean checksum_ok () { return (checksum == crc.checksum()); }\r
+\r
+       // Seeking and layer III stuff\r
+       /**\r
+        * Returns Layer III Padding bit.\r
+        */\r
+       public boolean padding()\r
+       {\r
+               if (h_padding_bit == 0) return false;\r
+         else return true;\r
+       }\r
+\r
+       /**\r
+        * Returns Slots.\r
+        */\r
+       public int slots() { return nSlots; }\r
+\r
+       /**\r
+        * Returns Mode Extension.\r
+        */\r
+       public int mode_extension() { return h_mode_extension; }\r
+\r
+       // E.B -> private to public\r
+       public static final int bitrates[][][] = {\r
+               {{0 /*free format*/, 32000, 48000, 56000, 64000, 80000, 96000,\r
+         112000, 128000, 144000, 160000, 176000, 192000 ,224000, 256000, 0},\r
+               {0 /*free format*/, 8000, 16000, 24000, 32000, 40000, 48000,\r
+         56000, 64000, 80000, 96000, 112000, 128000, 144000, 160000, 0},\r
+               {0 /*free format*/, 8000, 16000, 24000, 32000, 40000, 48000,\r
+         56000, 64000, 80000, 96000, 112000, 128000, 144000, 160000, 0}},\r
+\r
+               {{0 /*free format*/, 32000, 64000, 96000, 128000, 160000, 192000,\r
+          224000, 256000, 288000, 320000, 352000, 384000, 416000, 448000, 0},\r
+         {0 /*free format*/, 32000, 48000, 56000, 64000, 80000, 96000,\r
+          112000, 128000, 160000, 192000, 224000, 256000, 320000, 384000, 0},\r
+         {0 /*free format*/, 32000, 40000, 48000, 56000, 64000, 80000,\r
+          96000, 112000, 128000, 160000, 192000, 224000, 256000, 320000, 0}},\r
+               // SZD: MPEG2.5\r
+               {{0 /*free format*/, 32000, 48000, 56000, 64000, 80000, 96000,\r
+         112000, 128000, 144000, 160000, 176000, 192000 ,224000, 256000, 0},\r
+               {0 /*free format*/, 8000, 16000, 24000, 32000, 40000, 48000,\r
+         56000, 64000, 80000, 96000, 112000, 128000, 144000, 160000, 0},\r
+               {0 /*free format*/, 8000, 16000, 24000, 32000, 40000, 48000,\r
+         56000, 64000, 80000, 96000, 112000, 128000, 144000, 160000, 0}},\r
+\r
+               };\r
+\r
+       // E.B -> private to public\r
+       /**\r
+        * Calculate Frame size.\r
+        * Calculates framesize in bytes excluding header size.\r
+        */\r
+       public int calculate_framesize()\r
+       {\r
+\r
+        if (h_layer == 1)\r
+        {\r
+          framesize = (12 * bitrates[h_version][0][h_bitrate_index]) /\r
+                      frequencies[h_version][h_sample_frequency];\r
+          if (h_padding_bit != 0 ) framesize++;\r
+          framesize <<= 2;             // one slot is 4 bytes long\r
+          nSlots = 0;\r
+        }\r
+        else\r
+        {\r
+          framesize = (144 * bitrates[h_version][h_layer - 1][h_bitrate_index]) /\r
+                      frequencies[h_version][h_sample_frequency];\r
+          if (h_version == MPEG2_LSF || h_version == MPEG25_LSF) framesize >>= 1;      // SZD\r
+          if (h_padding_bit != 0) framesize++;\r
+          // Layer III slots\r
+          if (h_layer == 3)\r
+          {\r
+            if (h_version == MPEG1)\r
+            {\r
+                        nSlots = framesize - ((h_mode == SINGLE_CHANNEL) ? 17 : 32) // side info size\r
+                                                                         -  ((h_protection_bit!=0) ? 0 : 2)                   // CRC size\r
+                                                                         - 4;                                                                       // header size\r
+            }\r
+            else\r
+                {  // MPEG-2 LSF, SZD: MPEG-2.5 LSF\r
+               nSlots = framesize - ((h_mode == SINGLE_CHANNEL) ?  9 : 17) // side info size\r
+                                                                 -  ((h_protection_bit!=0) ? 0 : 2)                   // CRC size\r
+                                                                         - 4;                                                                       // header size\r
+            }\r
+          }\r
+          else\r
+          {\r
+                nSlots = 0;\r
+          }\r
+        }\r
+        framesize -= 4;             // subtract header size\r
+        return framesize;\r
+       }\r
+\r
+       /**\r
+        * Returns the maximum number of frames in the stream.\r
+        * @param streamsize\r
+        * @return number of frames\r
+        */\r
+       public int max_number_of_frames(int streamsize)  // E.B\r
+       {\r
+               if (h_vbr == true) return h_vbr_frames;\r
+               else\r
+               {\r
+                       if ((framesize + 4 - h_padding_bit) == 0) return 0;\r
+                       else return(streamsize / (framesize + 4 - h_padding_bit));\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Returns the maximum number of frames in the stream.\r
+        * @param streamsize\r
+        * @return number of frames\r
+        */\r
+       public int min_number_of_frames(int streamsize) // E.B\r
+       {\r
+               if (h_vbr == true) return h_vbr_frames;\r
+               else\r
+               {\r
+                       if ((framesize + 5 - h_padding_bit) == 0) return 0;\r
+                       else return(streamsize / (framesize + 5 - h_padding_bit));\r
+               }\r
+       }\r
+\r
+\r
+       /**\r
+        * Returns ms/frame.\r
+        * @return milliseconds per frame\r
+        */\r
+       public float ms_per_frame() // E.B\r
+       {\r
+               if (h_vbr == true)\r
+               {                       \r
+                       double tpf = h_vbr_time_per_frame[layer()] / frequency();\r
+                       if ((h_version == MPEG2_LSF) || (h_version == MPEG25_LSF)) tpf /= 2;\r
+                       return ((float) (tpf * 1000));\r
+               }\r
+               else\r
+               {\r
+                       float ms_per_frame_array[][] = {{8.707483f,  8.0f, 12.0f},\r
+                                                                                       {26.12245f, 24.0f, 36.0f},\r
+                                                                                       {26.12245f, 24.0f, 36.0f}};\r
+                       return(ms_per_frame_array[h_layer-1][h_sample_frequency]);\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Returns total ms.\r
+        * @param streamsize\r
+        * @return total milliseconds\r
+        */\r
+       public float total_ms(int streamsize) // E.B\r
+       {\r
+               return(max_number_of_frames(streamsize) * ms_per_frame());\r
+       }\r
+\r
+       /**\r
+        * Returns synchronized header.\r
+        */\r
+       public int getSyncHeader() // E.B\r
+       {\r
+               return _headerstring;\r
+       }\r
+\r
+       // functions which return header informations as strings:\r
+       /**\r
+        * Return Layer version.\r
+        */\r
+       public String layer_string()\r
+       {\r
+               switch (h_layer)\r
+               {\r
+          case 1:\r
+               return "I";\r
+          case 2:\r
+               return "II";\r
+          case 3:\r
+               return "III";\r
+               }\r
+         return null;\r
+       }\r
+\r
+       // E.B -> private to public\r
+       public static final String bitrate_str[][][] = {\r
+               {{"free format", "32 kbit/s", "48 kbit/s", "56 kbit/s", "64 kbit/s",\r
+         "80 kbit/s", "96 kbit/s", "112 kbit/s", "128 kbit/s", "144 kbit/s",\r
+         "160 kbit/s", "176 kbit/s", "192 kbit/s", "224 kbit/s", "256 kbit/s",\r
+         "forbidden"},\r
+         {"free format", "8 kbit/s", "16 kbit/s", "24 kbit/s", "32 kbit/s",\r
+         "40 kbit/s", "48 kbit/s", "56 kbit/s", "64 kbit/s", "80 kbit/s",\r
+         "96 kbit/s", "112 kbit/s", "128 kbit/s", "144 kbit/s", "160 kbit/s",\r
+         "forbidden"},\r
+         {"free format", "8 kbit/s", "16 kbit/s", "24 kbit/s", "32 kbit/s",\r
+         "40 kbit/s", "48 kbit/s", "56 kbit/s", "64 kbit/s", "80 kbit/s",\r
+         "96 kbit/s", "112 kbit/s", "128 kbit/s", "144 kbit/s", "160 kbit/s",\r
+         "forbidden"}},\r
+\r
+         {{"free format", "32 kbit/s", "64 kbit/s", "96 kbit/s", "128 kbit/s",\r
+         "160 kbit/s", "192 kbit/s", "224 kbit/s", "256 kbit/s", "288 kbit/s",\r
+         "320 kbit/s", "352 kbit/s", "384 kbit/s", "416 kbit/s", "448 kbit/s",\r
+         "forbidden"},\r
+         {"free format", "32 kbit/s", "48 kbit/s", "56 kbit/s", "64 kbit/s",\r
+         "80 kbit/s", "96 kbit/s", "112 kbit/s", "128 kbit/s", "160 kbit/s",\r
+         "192 kbit/s", "224 kbit/s", "256 kbit/s", "320 kbit/s", "384 kbit/s",\r
+         "forbidden"},\r
+         {"free format", "32 kbit/s", "40 kbit/s", "48 kbit/s", "56 kbit/s",\r
+         "64 kbit/s", "80 kbit/s" , "96 kbit/s", "112 kbit/s", "128 kbit/s",\r
+         "160 kbit/s", "192 kbit/s", "224 kbit/s", "256 kbit/s", "320 kbit/s",\r
+         "forbidden"}},\r
+               // SZD: MPEG2.5\r
+               {{"free format", "32 kbit/s", "48 kbit/s", "56 kbit/s", "64 kbit/s",\r
+         "80 kbit/s", "96 kbit/s", "112 kbit/s", "128 kbit/s", "144 kbit/s",\r
+         "160 kbit/s", "176 kbit/s", "192 kbit/s", "224 kbit/s", "256 kbit/s",\r
+         "forbidden"},\r
+         {"free format", "8 kbit/s", "16 kbit/s", "24 kbit/s", "32 kbit/s",\r
+         "40 kbit/s", "48 kbit/s", "56 kbit/s", "64 kbit/s", "80 kbit/s",\r
+         "96 kbit/s", "112 kbit/s", "128 kbit/s", "144 kbit/s", "160 kbit/s",\r
+         "forbidden"},\r
+         {"free format", "8 kbit/s", "16 kbit/s", "24 kbit/s", "32 kbit/s",\r
+         "40 kbit/s", "48 kbit/s", "56 kbit/s", "64 kbit/s", "80 kbit/s",\r
+         "96 kbit/s", "112 kbit/s", "128 kbit/s", "144 kbit/s", "160 kbit/s",\r
+         "forbidden"}},\r
+         };\r
+\r
+       /**\r
+        * Return Bitrate.\r
+        * @return bitrate in bps\r
+        */\r
+       public String bitrate_string()\r
+       {\r
+               if (h_vbr == true)\r
+               {\r
+                       return Integer.toString(bitrate()/1000)+" kb/s";                \r
+               }\r
+         else return bitrate_str[h_version][h_layer - 1][h_bitrate_index];\r
+       }\r
+\r
+       /**\r
+        * Return Bitrate.\r
+        * @return bitrate in bps and average bitrate for VBR header\r
+        */\r
+       public int bitrate()\r
+       {\r
+               if (h_vbr == true)\r
+               {\r
+                       return ((int) ((h_vbr_bytes * 8) / (ms_per_frame() * h_vbr_frames)))*1000;              \r
+               }\r
+               else return bitrates[h_version][h_layer - 1][h_bitrate_index];\r
+       }\r
+\r
+       /**\r
+        * Return Instant Bitrate.\r
+        * Bitrate for VBR is not constant.\r
+        * @return bitrate in bps\r
+        */\r
+       public int bitrate_instant()\r
+       {\r
+               return bitrates[h_version][h_layer - 1][h_bitrate_index];\r
+       }\r
+\r
+       /**\r
+        * Returns Frequency\r
+        * @return frequency string in kHz\r
+        */\r
+       public String sample_frequency_string()\r
+       {\r
+               switch (h_sample_frequency)\r
+               {\r
+           case THIRTYTWO:\r
+               if (h_version == MPEG1)\r
+                       return "32 kHz";\r
+               else if (h_version == MPEG2_LSF)\r
+               return "16 kHz";\r
+           else        // SZD\r
+               return "8 kHz";\r
+           case FOURTYFOUR_POINT_ONE:\r
+               if (h_version == MPEG1)\r
+                       return "44.1 kHz";\r
+               else if (h_version == MPEG2_LSF)\r
+               return "22.05 kHz";\r
+               else    // SZD\r
+               return "11.025 kHz";\r
+           case FOURTYEIGHT:\r
+               if (h_version == MPEG1)\r
+                       return "48 kHz";\r
+               else if (h_version == MPEG2_LSF)\r
+               return "24 kHz";\r
+               else    // SZD\r
+                       return "12 kHz";\r
+         }\r
+         return(null);\r
+       }\r
+\r
+       /**\r
+        * Returns Mode.\r
+        */\r
+       public String mode_string()\r
+       {\r
+          switch (h_mode)\r
+          {\r
+            case STEREO:\r
+               return "Stereo";\r
+            case JOINT_STEREO:\r
+               return "Joint stereo";\r
+            case DUAL_CHANNEL:\r
+               return "Dual channel";\r
+            case SINGLE_CHANNEL:\r
+               return "Single channel";\r
+          }\r
+          return null;\r
+       }\r
+\r
+       /**\r
+        * Returns Version.\r
+        * @return MPEG-1 or MPEG-2 LSF or MPEG-2.5 LSF\r
+        */\r
+       public String version_string()\r
+       {\r
+         switch (h_version)\r
+         {\r
+           case MPEG1:\r
+             return "MPEG-1";\r
+           case MPEG2_LSF:\r
+             return "MPEG-2 LSF";\r
+           case MPEG25_LSF:    // SZD\r
+             return "MPEG-2.5 LSF";\r
+         }\r
+         return(null);\r
+       }\r
+\r
+       /**\r
+        * Returns the number of subbands in the current frame.\r
+        * @return number of subbands\r
+        */\r
+       public int number_of_subbands() {return h_number_of_subbands;}\r
+\r
+       /**\r
+        * Returns Intensity Stereo.\r
+        * (Layer II joint stereo only).\r
+        * Returns the number of subbands which are in stereo mode,\r
+        * subbands above that limit are in intensity stereo mode.\r
+        * @return intensity\r
+        */\r
+       public int intensity_stereo_bound() {return h_intensity_stereo_bound;}\r
+}\r