--- /dev/null
+/*\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