(二)用JAVA编写MP3解码器——帧头信息解码

51 篇文章 0 订阅

1.解析帧头   帧头共4字节,从高位到低位这32比特的含义如下:

比特数名称内容
11sync0x7FF
2version1=mpeg1.0, 0=mpeg2.0
2lay4-lay = layerI, II or III
1error protection0=yes, 1=no
4bitrate_index见下文
2sampling_freq见下文
1padding填充位
1extension见下文
2mode见下文
2mode_ext联合立体声(joint stereo)模式
1copyright0=no 1=yes
1original0=no 1=yes
2emphasis预加重

  Header.parseHeader(int)方法中的这几行依次解码上面的各个变量:

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. intVersionID = (h >> 19) & 3;  
  2. intLayer = 4 - (h >> 17) & 3;  
  3. intProtectionBit = (h >> 16) & 0x1;  
  4. intBitrateIndex = (h >> 12) & 0xF;  
  5. intSamplingFrequency = (h >> 10) & 3;  
  6. intPaddingBit = (h >> 9) & 0x1;  
  7. intMode = (h >> 6) & 3;  
  8. intModeExtension = (h >> 4) & 3;  


 

各变量的含义如下:

version  MPEG的版本,本程序支持MPEG 1.0/2.0/2.5,从MPEG 2.0开始支持32Kbps以下的低位率。

 

lay  MPEG Audio的压缩分为I、II、III共3层,Layer III的解码过程最为复杂。

 

error protection  设置为0表示有32位的循环冗余校检(CRC)。

 

bitrate_index   主数据的位率(单位KBits/s),例如对192Kbps的MP3,解码时每秒读取192*1024/8=24576字节的码流,如果你是从网络在线播放要确保每秒下载192/8=24KBytes以上才能流畅播放。

mpeg 1.0
Layer\值1234567891011121314
layer1326496128160192224256288320352384416448
layer2324856648096112128160192224256320384
layer332404856648096112128160192224256320

 

mpeg 2.0
Layer\值1234567891011121314
layer1324856648096112128144160176192224256
layer28162432404856648096112128144160
layer38162432404856648096112128144160


sampling_freq PCM样本的采样率,用它来初始化音频硬件以播放MP3。
mpeg1.0时其值0,1,2分别对应的采样是44100Hz,48000Hz,32000Hz
mpeg2.0时其值0,1,2分别对应的采样是22050Hz,24000Hz,16000Hz
mpeg2.5时其值0,1,2分别对应的采样是11025Hz,12000Hz,8000Hz


padding  设置为1表示有1字节的填充位,相应帧的长度增加1字节。

 

mode 声道模式,其值表示的含义:
0  立体声(stereo)
1  联合立体声(joint stereo)
2  双声道(dual channel)
3  单声道(single channel)


联合立体声(joint stereo) 采用联合立体声编码方式的两个声道具有关联性。例如MS_stereo将两个声道相加、相差后处理,相减后去掉了左右声道相同的成份,后续的压缩可得到更高的压缩率。


extension 其值表示采用哪种联合立体声方式

extensionintensity_stereoms_stereo
00offoff
01onof
10ofon
11onon


  帧头信息解码除解码上述信息外,还要进行帧同步、计算帧长、计算帧边信息长度等供后续解码。

  2. 帧同步   (1)帧头的4字节中高11位全部设置为1(11111111 111xxxxx xxxxxxxx xxxxxxxx),用它作为查找帧的重要依据。(2)考虑到MP3文件可能有的数据帧有损坏,帧同步时还要用version、lay、bitrate_index、sampling_freq的值是否合法去检验;(3)每一帧的 version、lay、sampling_freq保持不变,把已经解码的帧的这些变量保存起来,用以与下一帧这些变量的值比较; (4)根据当前帧的帧长,移到下一帧去解析下一帧的帧头来确定当前的4字节是否是有效的帧头。如源代码Header.syncFrame()方法中的这些行进行帧同步:

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. iraInput.read(b4, 0, 4);  
  2. h = makeInt32(b4, 0);  
  3. while(!bfind) {  
  4.     // 1.查找帧同步字  
  5.     while((h & intStandardMask) != intStandardMask  
  6.         || ((h >> 19) & 3) == 1       // version ID:  01 - reserved  
  7.         || ((h >> 17) & 3) == 0       // Layer index: 00 - reserved  
  8.         || ((h >> 12) & 0xf) == 0xf   // Bitrate Index: 1111 - reserved  
  9.         || ((h >> 12) & 0xf) == 0 // Bitrate Index: 0000 - free  
  10.         || ((h >> 10) & 3) == 3)  // Sampling Rate Index: 11 - reserved  
  11.     {  
  12.         //...  
  13.     }  
  14. //...  
  15.   
  16. // 2.与下一帧的同步头比较  
  17.     cur_mask = 0xffe00000;      //syncword  
  18.     cur_mask |= h & 0x180000;   //intVersionID  
  19.     cur_mask |= h & 0x60000;    //intLayer  
  20.     cur_mask |= h & 0x60000;    //intSamplingFrequency  
  21.   
  22.     if(iraInput.dump(intFrameSize-4, b4, 0, 4) < 4)  
  23.         return false;  
  24.     i = makeInt32(b4, 0);  
  25.     bfind = (i & cur_mask) == cur_mask && ((i >> 19) & 3) != 1  
  26.         && ((i >> 17) & 3) != 0 && ((i >> 12) & 15) != 15  
  27.         && ((i >> 12) & 0xf) != 0 && ((i >> 10) & 3) != 3;  
  28. //...  


3.计算帧长  一帧的长度应该用槽(slot)来描述,MPEG 1.0/2.0/2.5 对声音的3种压缩方式Layer1、Layer2和Layer3,每种压缩方式一帧的槽数是固定的,Layer1 一槽就是4个字节, Layer2和Layer3一槽就是一个字节,据此可以计算出帧的字节数;

 

  4.计算帧边信息长度  根据MP3帧头解码出的表示立体声编码模式(mode)、MPEG的版本(version)、压缩层(lay)套公式计算。

 

  5.解析VBR信息  见Header.parseVBR()方法,其中各个变量在其官方文档中有详细说明。如果你想了解细节,请查阅其官方文档。

 

Header.javar完整的源码如下:

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /*  
  2. * Header.java -- MPEG 1.0/2.0/2.5 Audio Layer I/II/III 帧同步和帧头信息解码  
  3. * Copyright (C) 2010  
  4. *  
  5. * This program is free software: you can redistribute it and/or modify  
  6. * it under the terms of the GNU General Public License as published by  
  7. * the Free Software Foundation, either version 3 of the License, or  
  8. * (at your option) any later version.  
  9. *  
  10. * This program is distributed in the hope that it will be useful,  
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of  
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the  
  13. * GNU General Public License for more details.  
  14. *  
  15. * You should have received a copy of the GNU General Public License  
  16. * along with this program.  If not, see <http://www.gnu.org/licenses/>.  
  17. *  
  18. * If you would like to negotiate alternate licensing terms, you may do  
  19. * so by contacting the author: <http://jmp123.sourceforge.net/>.  
  20. */  
  21.   
  22. package jmp123.decoder;  
  23.   
  24. import jmp123.instream.IRandomAccess;  
  25.   
  26. public final class Header {  
  27.     public static final int MPEG1 = 3;  
  28.     public static final int MPEG2 = 2;  
  29.     public static final int MPEG25 = 0;  
  30.     public static final int MAX_FRAMESIZE = 1732;   //MPEG 1.0/2.0/2.5, Lay 1/2/3  
  31.   
  32.     /*  
  33.      * intBitrateTable[intLSF][intLayer-1][intBitrateIndex]  
  34.      */  
  35.     private static final int[][][] intBitrateTable = {  
  36.         {  
  37.             //MPEG 1  
  38.             //Layer I  
  39.             {0,32,64,96,128,160,192,224,256,288,320,352,384,416,448},  
  40.             //Layer II  
  41.             {0,32,48,56, 64, 80, 96,112,128,160,192,224,256,320,384},  
  42.             //Layer III  
  43.             {0,32,40,48, 56, 64, 80, 96,112,128,160,192,224,256,320}  
  44.         },  
  45.         {  
  46.             //MPEG 2.0/2.5  
  47.             //Layer I  
  48.             {0,32,48,56,64,80,96,112,128,144,160,176,192,224,256},  
  49.             //Layer II  
  50.             {0,8,16,24,32,40,48,56,64,80,96,112,128,144,160},  
  51.             //Layer III  
  52.             {0,8,16,24,32,40,48,56,64,80,96,112,128,144,160}  
  53.         }  
  54.     };  
  55.     /*  
  56.      * intSamplingRateTable[intVersionID][intSamplingFrequency]  
  57.      */  
  58.     private static final int[][] intSamplingRateTable = {  
  59.         {11025 , 12000 , 8000,0},   //MPEG Version 2.5  
  60.         {0,0,0,0,},                 //reserved  
  61.         {22050, 24000, 16000 ,0},   //MPEG Version 2 (ISO/IEC 13818-3)  
  62.         {44100, 48000, 32000,0}     //MPEG Version 1 (ISO/IEC 11172-3)  
  63.     };  
  64.   
  65.     /*  
  66.      * intVersionID: 2 bits  
  67.      * "00"  MPEG Version 2.5 (unofficial extension of MPEG 2);  
  68.      * "01"  reserved;  
  69.      * "10"  MPEG Version 2 (ISO/IEC 13818-3);  
  70.      * "11"  MPEG Version 1 (ISO/IEC 11172-3).  
  71.      */  
  72.     private static int intVersionID;  
  73.   
  74.     /*  
  75.      * intLayer: 2 bits  
  76.      * "11"  Layer I  
  77.      * "10"  Layer II  
  78.      * "01"  Layer III  
  79.      * "00"  reserved  
  80.      * 已换算intLayer=4-intLayer: 1-Layer I; 2-Layer II; 3-Layer III; 4-reserved  
  81.      */  
  82.     private static int intLayer;  
  83.   
  84.     /*  
  85.      * intProtectionBit: 1 bit  
  86.      * "1"  no CRC;  
  87.      * "0"  protected by 16 bit CRC following header.  
  88.      */  
  89.     private static int intProtectionBit;  
  90.   
  91.     /*   
  92.      * intBitrateIndex: 4 bits  
  93.      */  
  94.     private static int intBitrateIndex;  
  95.   
  96.     /*  
  97.      * intSamplingFrequency: 2 bits  
  98.      * '00'  44.1kHz  
  99.      * '01'  48kHz  
  100.      * '10'  32kHz  
  101.      * '11'  reserved  
  102.      */  
  103.     private static int intSamplingFrequency;  
  104.   
  105.     private static int intPaddingBit;  
  106.   
  107.     /*  
  108.      * intMode: 2 bits  
  109.      * '00'  Stereo;  
  110.      * '01'  Joint Stereo (Stereo);  
  111.      * '10'  Dual channel (Two mono channels);  
  112.      * '11'  Single channel (Mono).  
  113.      */  
  114.     private static int intMode;  
  115.   
  116.     /*  
  117.      * intModeExtension: 2 bits  
  118.      *       intensity_stereo   boolMS_Stereo  
  119.      * '00'  off                off  
  120.      * '01'  on                 off  
  121.      * '10'  off                on  
  122.      * '11'  on                 on  
  123.      */  
  124.     private static int intModeExtension;  
  125.   
  126.     private static int intFrameSize;  
  127.     private static int intMainDataBytes;    //main_data length  
  128.     private static int intSideInfoSize;     //side_information length  
  129.     private static int intLSF;  
  130.     private static int intStandardMask = 0xffe00000;  
  131.     private static boolean boolMS_Stereo, boolIntensityStereo;  
  132.     private static IRandomAccess iraInput;  
  133.   
  134.     public Header(IRandomAccess in_rai) {  
  135.         iraInput = in_rai;  
  136.     }  
  137.   
  138.     private void parseHeader(int h) {  
  139.         intVersionID = (h >> 19) & 3;  
  140.         intLayer = 4 - (h >> 17) & 3;  
  141.         intProtectionBit = (h >> 16) & 0x1;  
  142.         intBitrateIndex = (h >> 12) & 0xF;  
  143.         intSamplingFrequency = (h >> 10) & 3;  
  144.         intPaddingBit = (h >> 9) & 0x1;  
  145.         intMode = (h >> 6) & 3;  
  146.         intModeExtension = (h >> 4) & 3;  
  147.   
  148.         boolMS_Stereo = intMode == 1 && (intModeExtension & 2) != 0;  
  149.         boolIntensityStereo = intMode == 1 && (intModeExtension & 0x1) != 0;  
  150.         intLSF = (intVersionID == MPEG1) ? 0 : 1;  
  151.   
  152.         switch (intLayer) {  
  153.         case 1:   
  154.             intFrameSize  = intBitrateTable[intLSF][0][intBitrateIndex] * 12000;  
  155.             intFrameSize /= intSamplingRateTable[intVersionID][intSamplingFrequency];  
  156.             intFrameSize  = ((intFrameSize+intPaddingBit)<<2);  
  157.             break;  
  158.         case 2:  
  159.             intFrameSize  = intBitrateTable[intLSF][1][intBitrateIndex] * 144000;  
  160.             intFrameSize /= intSamplingRateTable[intVersionID][intSamplingFrequency];  
  161.             intFrameSize += intPaddingBit;  
  162.             break;  
  163.         case 3:  
  164.             intFrameSize  = intBitrateTable[intLSF][2][intBitrateIndex] * 144000;  
  165.             intFrameSize /= intSamplingRateTable[intVersionID][intSamplingFrequency]<<(intLSF);  
  166.             intFrameSize += intPaddingBit;  
  167.             //计算帧边信息长度  
  168.             if(intVersionID == MPEG1)  
  169.                 intSideInfoSize = (intMode == 3) ? 17 : 32;  
  170.             else  
  171.                 intSideInfoSize = (intMode == 3) ? 9 : 17;  
  172.             break;  
  173.         }  
  174.   
  175.         //计算主数据长度  
  176.         intMainDataBytes = intFrameSize - 4 - intSideInfoSize;  
  177.         if(intProtectionBit == 0)  
  178.             intMainDataBytes -2;  
  179.     }  
  180.   
  181.     private static void headerCRC() throws Exception {  
  182.         if(iraInput.read() == -1 || iraInput.read() == -1)  
  183.             throw new Exception("crc() 文件读完");  
  184.     }  
  185.   
  186.     private static int makeInt32(byte[] b, int off) {  
  187.         int h = b[off] & 0xff;  
  188.         h <<= 8;  
  189.         h |= b[off + 1] & 0xff;  
  190.         h <<= 8;  
  191.         h |= b[off + 2] & 0xff;  
  192.         h <<= 8;  
  193.         h |= b[off + 3] & 0xff;  
  194.         return h;  
  195.     }  
  196.   
  197.     private static int intFrameCounter; //当前帧序号  
  198.     private static boolean boolSync;    //true:帧头的特征未改变  
  199.     private static final byte[] b4 = new byte[4];  
  200.     /*  
  201.      * 帧同步: 查找到帧同步字后与下一帧的intVersionID等比较,确定是否找到有效的同步字.  
  202.      */  
  203.     public boolean syncFrame()  throws Exception{  
  204.         int h, idx = 0, i, cur_mask = 0;  
  205.         iraInput.read(b4, 0, 4);  
  206.         h = (b4[0]<<24) | ((b4[1] & 0xff)<<16) | ((b4[2] & 0xff)<<8) | (b4[3] & 0xff);  
  207.         while(true) {  
  208.             // 1.查找帧同步字  
  209.             while((h & intStandardMask) != intStandardMask  
  210.                 || ((h >> 19) & 3) == 1       // version ID:  01 - reserved  
  211.                 || ((h >> 17) & 3) == 0       // Layer index: 00 - reserved  
  212.                 || ((h >> 12) & 0xf) == 0xf   // Bitrate Index: 1111 - reserved  
  213.                 || ((h >> 12) & 0xf) == 0 // Bitrate Index: 0000 - free  
  214.                 || ((h >> 10) & 3) == 3)  // Sampling Rate Index: 11 - reserved  
  215.             {  
  216.                 if((i = iraInput.read()) == -1)  
  217.                     return false;  
  218.                 idx++;  
  219.                 h = (h << 8) | i;  
  220.             }  
  221.             if (idx > 0)  
  222.                 boolSync = false;  
  223.   
  224.             // 2. 解析帧头  
  225.             parseHeader(h);  
  226.   
  227.             //若intVersionID等帧的特征未改变(boolSync=true),不用与下一帧的同步头比较.  
  228.             if(boolSync)  
  229.                 break;  
  230.             if(idx >= 0xffff) {  
  231.                 System.out.println("\n搜索 64K 未发现MP3帧后放弃。");  
  232.                 return false;  
  233.             }  
  234.   
  235.             // 3.与下一帧的同步头比较  
  236.             cur_mask = 0xffe00000;      //syncword  
  237.             cur_mask |= h & 0x180000;   //intVersionID  
  238.             cur_mask |= h & 0x60000;    //intLayer  
  239.             cur_mask |= h & 0x60000;    //intSamplingFrequency  
  240.             //cur_mask |= h & 0xC0;     //intMode  
  241.             //intMode,intModeExtension 不是始终不变.  
  242.   
  243.             if(iraInput.dump(intFrameSize-4, b4, 0, 4) < 4)  
  244.                 return false;  
  245.             i = makeInt32(b4, 0);  
  246.             if( (i & cur_mask) == cur_mask && ((i >> 19) & 3) != 1  
  247.                     && ((i >> 17) & 3) != 0 && ((i >> 12) & 15) != 15  
  248.                     && ((i >> 12) & 0xf) != 0 && ((i >> 10) & 3) != 3 )  
  249.                 break;  
  250.             idx++;  
  251.             h = (h << 8) | iraInput.read();  
  252.         }  
  253.         //if(idx > 0)  
  254.         //  System.out.println("frs="+intFrameCounter+",skip bytes:" + idx);  
  255.   
  256.         if(boolSync == false) {  
  257.             boolSync = true;  
  258.             if(intStandardMask == 0xffe00000) { //是第一帧...  
  259.                 longFrameOffset = iraInput.getFilePointer();  
  260.                 longAllFrameSize = iraInput.length() - longFrameOffset;  
  261.                 longFrames = longAllFrameSize / intFrameSize;  
  262.                 parseVBR();     //若有VBR tag以上3个变量将被改写  
  263.                 intStandardMask = cur_mask;  
  264.                 floatFrameDuration = 1152f / (getFrequency() << intLSF);  
  265.             }  
  266.         }  
  267.         if (intProtectionBit == 0)  
  268.             headerCRC();  
  269.         intFrameCounter++;  
  270.         return true;  
  271.     }  
  272.   
  273.     public boolean isMSStereo() {  
  274.         return boolMS_Stereo;  
  275.     }  
  276.   
  277.     public boolean isIStereo() {  
  278.         return boolIntensityStereo;  
  279.     }  
  280.   
  281.     public int getBitrate() {  
  282.         return intBitrateTable[intLSF][intLayer-1][intBitrateIndex];  
  283.     }  
  284.   
  285.     public int getBitrateIndex() {  
  286.         return intBitrateIndex;  
  287.     }  
  288.   
  289.     public int getChannels() {  
  290.         return intMode == 3 ? 1 : 2;  
  291.     }  
  292.   
  293.     public int getMode() {  
  294.         return intMode;  
  295.     }  
  296.   
  297.     public int getModeExtension() {  
  298.         return intModeExtension;  
  299.     }  
  300.   
  301.     public int getVersion() {  
  302.         return intVersionID;  
  303.     }  
  304.   
  305.     public int getLayer() {  
  306.         return intLayer;  
  307.     }  
  308.   
  309.     public int getSampleFrequency() {  
  310.         return intSamplingFrequency;  
  311.     }  
  312.   
  313.     public int getFrequency() {  
  314.         return intSamplingRateTable[intVersionID][intSamplingFrequency];  
  315.     }  
  316.   
  317.     public int getMainDataBytes() {  
  318.         return intMainDataBytes;  
  319.     }  
  320.   
  321.     public int getSideInfoSize() {  
  322.         return intSideInfoSize;  
  323.     }  
  324.   
  325.     public int getFrameSize() {  
  326.         return intFrameSize;  
  327.     }  
  328.   
  329.     public int getFrameCounter() {  
  330.         return intFrameCounter;  
  331.     }  
  332.   
  333.     // MP3 文件帧数等信息  
  334.     private static long longAllFrameSize;   //帧长度总和(文件长度减去ID3 tag, APE tag 等长度)  
  335.     private static long longFrameOffset;    //第一帧的偏移量  
  336.     private static long longFrames;         //帧数  
  337.     private static float floatFrameDuration;//一帧时长(秒)  
  338.     private static String strDuration;  
  339.   
  340.     public long getTrackFrames() {  
  341.         return longFrames;  
  342.     }  
  343.   
  344.     /*  
  345.      * 返回MP3文件时长(秒)  
  346.      */  
  347.     public float getDuration() {  
  348.         return floatFrameDuration * longFrames;  
  349.     }  
  350.   
  351.     /*  
  352.     * 解码存储在第一帧的VBR信息.若第一帧存储的是VBR信息,帧边信息被填充为零,不解  
  353.     * 码VBR tag而把这一帧作为音频帧不影响正常解码.  
  354.     */  
  355.     private boolean boolVBRtag;  
  356.     private byte[] byteVBRToc;  
  357.     private int intTocNumber, intTocPer, intTocFactor;  
  358.     private String strBitRate;  
  359.   
  360.     private boolean parseVBR() throws Exception {  
  361.         int iTagSize = intFrameSize - intSideInfoSize;  
  362.         if (iTagSize < 124)  
  363.             return false;  
  364.         byte[] b = new byte[iTagSize];  
  365.         iraInput.dump(0, b, 0, intSideInfoSize);  
  366.         for (int i = 2; i < intSideInfoSize; i++)    //前2字节可能是CRC_word  
  367.             if (b[i] != 0) {  
  368.                 b = null;  
  369.                 return false;  
  370.             }  
  371.         iraInput.dump(intSideInfoSize, b, 0, iTagSize);  
  372.   
  373.         //-------------------------------VBR tag------------------------------  
  374.         int iOff = 0;  
  375.         if ((b[0] == 'X' && b[1] == 'i' && b[2] == 'n' && b[3] == 'g') ||  
  376.                 (b[0] == 'I' && b[1] == 'n' && b[2] == 'f' && b[3] == 'o')) {  
  377.             //--------Xing/Info header--------  
  378.             boolVBRtag = true;  
  379.             longAllFrameSize -intFrameSize;  
  380.             longFrameOffset += intFrameSize;  
  381.             int xing_flags = makeInt32(b, 4);  
  382.             iOff = 8;  
  383.             if ((xing_flags & 1) == 1) {    // track frames  
  384.                 longFrames = makeInt32(b, iOff);  
  385.                 iOff += 4;  
  386.                 System.out.println("track frames: " + longFrames +  
  387.                         "  [" + new String(b,0,4) + "]");  
  388.             }  
  389.             if ((xing_flags & 0x2) != 0) { // track bytes  
  390.                 longAllFrameSize = makeInt32(b, iOff);  
  391.                 iOff += 4;  
  392.                 System.out.println(" track bytes: " + longAllFrameSize);  
  393.             }  
  394.             if ((xing_flags & 0x4) != 0) { // TOC: 100 bytes.  
  395.                 byteVBRToc = new byte[100];  
  396.                 System.arraycopy(b, iOff, byteVBRToc, 0, 100);  
  397.                 iOff += 100;  
  398.                 //System.out.println("         TOC: true");  
  399.             }  
  400.             if ((xing_flags & 0x8) != 0) { // VBR quality  
  401.                 int xing_quality = makeInt32(b, iOff);  
  402.                 iOff += 4;  
  403.                 System.out.println("     quality: " + xing_quality);  
  404.             }  
  405.             intTocNumber = 100; //TOC共100个表项  
  406.             intTocPer = 1;      //每个表项1字节  
  407.             intTocFactor = 1;  
  408.         } else if(b[0] == 'V' && b[1] == 'B' && b[2] == 'R' && b[3] == 'I') {  
  409.             //--------VBRI header--------  
  410.             //version ID: 2 bytes  
  411.             //Delay: 2 bytes  
  412.             int vbri_quality = (b[8] & 0xff) | (b[9] & 0xff);  
  413.             System.out.println("     quality: " + vbri_quality +  
  414.                     "  [" + new String(b,0,4) + "]");  
  415.             longAllFrameSize = makeInt32(b, 10);  
  416.             System.out.println(" track bytes: " + longAllFrameSize);  
  417.             longFrames = makeInt32(b, 14);  
  418.             System.out.println("track frames: " + longFrames);  
  419.             intTocNumber = (b[18] & 0xff) | (b[19] & 0xff);  
  420.             intTocFactor = (b[20] & 0xff) | (b[21] & 0xff);  
  421.             intTocPer = (b[22] & 0xff) | (b[23] & 0xff);  
  422.             //int toc_frames = (b[24] & 0xff) | (b[25] & 0xff); //每个TOC表项的帧数  
  423.             int toc_size = intTocNumber * intTocPer;  
  424.             iOff = 26 + toc_size;  
  425.             System.out.println("         TOC: " + intTocNumber + " * " +  
  426.                     intTocPer + " = " + toc_size + "factor=" + intTocFactor);  
  427.             if (intFrameSize - intSideInfoSize < iOff)  
  428.                 return false;  
  429.             byteVBRToc = new byte[toc_size];  
  430.             System.arraycopy(b, 26, byteVBRToc, 0, toc_size);  
  431.         } else {  
  432.             b = null;  
  433.             return false;  
  434.         }         
  435.   
  436.         //-------------------------------LAME tag------------------------------  
  437.         //9+1+1+8+1+1+3+1+1+2+4+2+2=36 bytes  
  438.         if(iTagSize - iOff < 36 || b[iOff] == 0) {  
  439.             strBitRate = "VBR";  
  440.             b = null;  
  441.             return true;  
  442.         }  
  443.         //Encoder Version: 9 bytes  
  444.         String strEncoder = new String(b, iOff, 9);  
  445.         iOff += 9;  
  446.         System.out.println("     encoder: " + strEncoder);  
  447.   
  448.         //'Info Tag' revision + VBR method: 1 byte  
  449.         //boolean isCBR=falseisABR=falseisVBR=false;  
  450.         int revi = (b[iOff] & 0xff) >> 4; //0:rev0; 1:rev1; 15:reserved  
  451.         int lame_vbr = b[iOff++] & 0xf;     //0:unknown  
  452.   
  453.         //Lowpass filter value(低通滤波上限值): 1 byte  
  454.         int lowpass = b[iOff++] & 0xff;  
  455.         System.out.println("     lowpass: " + (lowpass * 100) + "Hz" +"  [revi "+revi+"]");  
  456.   
  457.         //Replay Gain(回放增益):8 bytes  
  458.         float peak = Float.intBitsToFloat(makeInt32(b, iOff));  //Peak signal amplitude  
  459.         iOff += 4;  
  460.         int radio = ((b[iOff] & 0xff) << 8) | (b[iOff+1] & 0xff); //Radio Replay Gain  
  461.         /*  
  462.         * radio:  
  463.         * bits 0h-2h: NAME of Gain adjustment:  
  464.         *   000 = not set  
  465.         *   001 = radio  
  466.         *   010 = audiophile  
  467.         * bits 3h-5h: ORIGINATOR of Gain adjustment:  
  468.         *   000 = not set  
  469.         *   001 = set by artist  
  470.         *   010 = set by user  
  471.         *   011 = set by my model  
  472.         *   100 = set by simple RMS average  
  473.         * bit 6h: Sign bit  
  474.         * bits 7h-Fh: ABSOLUTE GAIN ADJUSTMENT.  
  475.         *  storing 10x the adjustment (to give the extra decimal place).  
  476.         */  
  477.         iOff += 2;  
  478.         int phile = ((b[iOff] & 0xff) << 8) | (b[iOff+1] & 0xff); //Audiophile Replay Gain  
  479.         /*  
  480.         * phile各位含义同上(radio)  
  481.         */  
  482.         iOff += 2;  
  483.           
  484.         //Encoding flags + ATH Type: 1 byte  
  485.         /*int enc_flag = (b[iOff] & 0xff) >> 4;  
  486.         int ath_type = b[iOff] & 0xf;  
  487.         //000?0000: LAME uses "--nspsytune" ?  
  488.         boolean nsp = ((enc_flag & 0x1) == 0) ? false : true;  
  489.         //00?00000: LAME uses "--nssafejoint" ?  
  490.         boolean nsj = ((enc_flag & 0x2) == 0) ? false : true;  
  491.         //0?000000: This track is --nogap continued in a next track ?  
  492.         //is true for all but the last track in a --nogap album   
  493.         boolean nogap_next = ((enc_flag & 0x4) == 0) ? false : true;  
  494.         //?0000000: This track is the --nogap continuation of an earlier one ?  
  495.         //is true for all but the first track in a --nogap album  
  496.         boolean nogap_cont = ((enc_flag & 0x8) == 0) ? false : true;*/  
  497.         iOff++;  
  498.   
  499.         // ABR/CBR位率或VBR的最小位率(0xFF表示位率为255Kbps以上): 1 byte  
  500.         int lame_bitrate = b[iOff++] & 0xff;  
  501.         switch (lame_vbr) {  
  502.         case 1:  
  503.         case 8: // CBR  
  504.             strBitRate = String.format("CBR %1$dK", getBitrate());  
  505.             break;  
  506.         case 2:  
  507.         case 9: // ABR  
  508.             if(lame_bitrate < 0xff)  
  509.                 strBitRate = String.format("ABR %1$dK", lame_bitrate);  
  510.             else  
  511.                 strBitRate = String.format("ABR %1$dK以上", lame_bitrate);  
  512.             break;  
  513.         default: // 0: unknown is VBR ?  
  514.             if(lame_bitrate == 0)   //unknown  
  515.                 strBitRate = "VBR";  
  516.             else  
  517.                 strBitRate = String.format("VBR %1$dK以上", lame_bitrate);  
  518.         }  
  519.   
  520.         //Encoder delays: 3 bytes  
  521.         iOff += 3;  
  522.   
  523.         //Misc: 1 byte  
  524.         iOff++;  
  525.   
  526.         //MP3 Gain: 1 byte.   
  527.         //任何MP3能无损放大2^(mp3_gain/4).以1.5dB为步进值改变'Replay Gain'的3个域:  
  528.         //  'Peak signal amplitude', 'Radio Replay Gain', 'Audiophile Replay Gain'  
  529.         //mp3_gain = -127..+127, 对应的:  
  530.         //  分贝值-190.5dB..+190.5dB; mp3_gain增加1, 增加1.5dB  
  531.         //  放大倍数0.000000000276883..3611622602.83833951  
  532.         int mp3_gain = b[iOff++];   //其缺省值为0  
  533.         if(mp3_gain != 0)  
  534.             System.out.println("    MP3 Gain: " + mp3_gain);  
  535.   
  536.         //Preset and surround info: 2 bytes  
  537.         int preset_surround = ((b[iOff] & 0xff) << 8) | (b[iOff+1] & 0xff);  
  538.         int surround_info = (preset_surround >> 11) & 0x7;  
  539.         switch(surround_info) {  
  540.         case 0:     //no surround info  
  541.             break;  
  542.         case 1:     //DPL encoding  
  543.             System.out.println("    surround: DPL");  
  544.             break;  
  545.         case 2:     //DPL2 encoding  
  546.             System.out.println("    surround: DPL2");  
  547.             break;  
  548.         case 3:     //Ambisonic encoding  
  549.             System.out.println("    surround: Ambisonic");  
  550.             break;  
  551.         case 7:     // reserved  
  552.             System.out.println("    surround: invalid data");  
  553.             break;  
  554.         }  
  555.         preset_surround &= 0x7ff;   //11 bits: 2047 presets  
  556.         if(preset_surround != 0)    //0: unknown / no preset used  
  557.             System.out.println("    surround: preset " + preset_surround);  
  558.         iOff += 2;  
  559.   
  560.         //MusicLength: 4 bytes  
  561.         //MP3文件原始的(即除去ID3 tag,APE tag等)'LAME Tag frame'和'音乐数据'的总字节数  
  562.         int music_len = makeInt32(b, iOff);  
  563.         iOff += 4;  
  564.         if(music_len != 0)  
  565.             longAllFrameSize = music_len;  
  566.   
  567.         //MusicCRC: 2 bytes  
  568.         iOff += 2;  
  569.   
  570.         //CRC-16 of Info Tag: 2 bytes  
  571.   
  572.         b = null;  
  573.         return true;  
  574.     }  
  575.   
  576.     // -------------------------------------------------------------------  
  577.     // 以下是辅助功能,删除掉源码及相关调用不影响正常播放  
  578.     // -------------------------------------------------------------------  
  579.     // 打印信息  
  580.     public void printHeaderInfo() {  
  581.         String[] sver = {"MPEG 2.5", "reserved", "MPEG 2.0", "MPEG 1.0"};  
  582.         String[] mode_str = {", Stereo",", Joint Stereo",", Dual channel",", Single channel(Mono)"};  
  583.         String[] exmode_str = {"","(I/S)","(M/S)","(I/S & M/S)"};  
  584.         if(strDuration == null) {  
  585.             float duration = getDuration();  
  586.             int m = (int)(duration / 60);  
  587.             strDuration = String.format("%1$02d:%2$02d", m, (int)(duration - m * 60 + 0.5));  
  588.             progress = new StringBuffer(">----------------------------------------");  
  589.         }  
  590.         if(!boolVBRtag)  
  591.             strBitRate = String.format("%1$dK", intBitrateTable[intLSF][intLayer-1][intBitrateIndex]);  
  592.         System.out.println("\r" + sver[intVersionID] + ", Layer " + intLayer +   
  593.             ", " + getFrequency()+"Hz, " +   
  594.             strBitRate +  
  595.             mode_str[intMode] +  
  596.             exmode_str[intModeExtension] + ", " +  
  597.             strDuration);  
  598.     }  
  599.   
  600.     private static StringBuffer progress;  
  601.     private static int progress_index = 1;  
  602.   
  603.     public void printState() {  
  604.         float t = intFrameCounter * floatFrameDuration;  
  605.         int m = (int)(t / 60);  
  606.         float s = t - 60 * m;  
  607.         float percent;  
  608.         if(boolVBRtag)  
  609.             percent = (float)intFrameCounter / longFrames * 100;  
  610.         else  
  611.             percent = (float)iraInput.getFilePointer() / iraInput.length() * 100;  
  612.         int i = ((int)(percent + 0.5) << 2) / 10;  
  613.         if(i == progress_index) {  
  614.             progress.replace(i-1, i+1, "=>");  
  615.             progress_index++;  
  616.         }  
  617.         System.out.printf("\r%1$02d:%2$04.1f [%3$-41s] %4$.1f%%", m, s, progress, percent);  
  618.     }  
  619. }  


 

【下载地址】http://jmp123.sourceforge.net/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值