Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1433134
  • 博文数量: 1334
  • 博客积分: 645
  • 博客等级: 上士
  • 技术积分: 5762
  • 用 户 组: 普通用户
  • 注册时间: 2012-07-25 16:56
文章分类

全部博文(1334)

文章存档

2014年(108)

2013年(1059)

2012年(169)

分类:

2012-12-07 17:36:38

:转载时请以超链接形式标明文章原始出处和作者信息及本声明
http://kware.blogbus.com/logs/30741724.html

1. 读 32bit 的帧头,头处理的主处理流程
   Header.read_header(Bitstream, Crc16[] crcp) [javazoom.jl.decoder]
     int headerstring;                            // 帧头的32位对应的32位整数
     int channel_bitrate;                         // 比特率
     boolean sync = false;                        // 同步判断

     do {
       headerstring = stream.syncHeader(syncmode);// 同步并获取帧头的32位整数
       _headerstring = headerstring;

       if (syncmode==Bitstream.INITIAL_SYNC) {    // 如果是初始化同步
         h_version = ((headerstring >>> 19) & 1); // 求取第 19 位的版本号
         if (((headerstring >>> 20) & 1) == 0)    // 第 20 位为: MPEG2.5 detection
           if (h_version == MPEG2_LSF)
             h_version = MPEG25_LSF;
           else
             throw stream.newBitstreamException(Bitstream.UNKNOWN_ERROR);
                                                  // 第 10-11 位为采样率
         if ((h_sample_frequency = ((headerstring >>> 10) & 3)) == 3)
           throw stream.newBitstreamException(Bitstream.UNKNOWN_ERROR);
       }

       h_layer = 4 - (headerstring >>> 17) & 3;       // 第 17-18 位为层号 Layer I/II/III
       h_protection_bit = (headerstring >>> 16) & 1;  // 第 16 位为保护位 Protect
       h_bitrate_index = (headerstring >>> 12) & 0xF; // 第 12-15 位为比特率
       h_padding_bit = (headerstring >>> 9) & 1;      // 第 9 位为补齐位
       h_mode = ((headerstring >>> 6) & 3);           // 第 6-7 位为模式位
       h_mode_extension = (headerstring >>> 4) & 3;   // 第 4-5 位为模式扩展位
       if (h_mode==JOINT_STEREO) h_intensity_stereo_bound = (h_mode_extension << 2) + 4;
       else h_intensity_stereo_bound = 0;         // 用不到
       if (((headerstring >>> 3) & 1)==1) h_copyright = true; // 第 3 位版权等信息
       if (((headerstring >>> 2) & 1)==1) h_original = true;  // 第 2 位为 Home 信息

       if (h_layer==1) h_number_of_subbands = 32; // 计算子带数(subbands),Layer I 有 32 个子带
       else {
         channel_bitrate = h_bitrate_index;       // 计算每个信道的比特率
         if (h_mode != SINGLE_CHANNEL)
         if (channel_bitrate == 4) channel_bitrate = 1;
         else channel_bitrate -= 4;

         if ((channel_bitrate == 1) || (channel_bitrate == 2))
           if (h_sample_frequency == THIRTYTWO) h_number_of_subbands = 12;
           else h_number_of_subbands = 8;
         else
           if ((h_sample_frequency == FOURTYEIGHT) || ((channel_bitrate >= 3)
             && (channel_bitrate <= 5)))
             h_number_of_subbands = 27;
           else
             h_number_of_subbands = 30;
       }
       if (h_intensity_stereo_bound > h_number_of_subbands)
         h_intensity_stereo_bound = h_number_of_subbands;

       calculate_framesize();                     // 计算帧尺寸和槽数(framesize/nSlots)
       stream.read_frame_data(framesize);         // 读取帧数据(framedata):

       if(stream.isSyncCurrentPosition(syncmode)){// 当前位置同步
         if (syncmode==Bitstream.INITIAL_SYNC) {  // 如果是初始化同步
           syncmode = Bitstream.STRICT_SYNC;      // 设定为严格同步
           stream.set_syncword(headerstring & 0xFFF80CC0); // 设定同步字,0xFFF80CC0 为同步字掩码
         }
         sync = true;                             // 目前同步
       } else {
         stream.unreadFrame();                    // 当前不同步,把帧数据退回去缓冲区中
       }
     } while (!sync);                             // 如果未同步重读

     stream.parse_frame();                        // 分析帧

     if (h_protection_bit == 0) {                 // 帧中包含 16 位的 crc 校验和
       checksum = (short)stream.get_bits(16);     // 取出 16 位的 crc 校验和到 checksum
       if (crc == null)
         crc = new Crc16();
       crc.add_bits(headerstring, 16);            // ?把头 16 位加入校验
       crcp[0] = crc;                             // 把校验器返回 crcp[]
     } else
       crcp[0] = null;                            // 无校验
   }

2. 帧尺寸计算,计算帧尺寸(单位为字节),抛掉头尺寸。
   public int calculate_framesize() {
     if (h_layer == 1) {                          // 层 Layer I,公式:fs = 12 * br / sf
       framesize = (12 * bitrates[h_version][0][h_bitrate_index])
         / frequencies[h_version][h_sample_frequency];
       if (h_padding_bit != 0 ) framesize++;
       framesize <<= 2;                           // 每槽 4bytes
       nSlots = 0;
     } else {                                     // 层 Layer II/III,公式:fs = 144 * br / sf
       framesize = (144 * bitrates[h_version][h_layer - 1][h_bitrate_index])
         / frequencies[h_version][h_sample_frequency];
       if (h_version == MPEG2_LSF || h_version == MPEG25_LSF)
         framesize >>= 1;                         // 每槽 4bits
       if (h_padding_bit != 0)                    // 对齐位
         framesize++;
       if (h_layer == 3) {                        // 层 Layer III 槽调整
         if (h_version == MPEG1) {                // MPEG1
           nSlots = framesize
             - ((h_mode==SINGLE_CHANNEL) ? 17:32) // 减去 边(side)信息尺寸
             - ((h_protection_bit!=0) ? 0 : 2)    // 减去 CRC 尺寸
             - 4;                                 // 减去 头尺寸
         } else {                                 // MPEG-2 LSF, MPEG-2.5 LSF
           nSlots = framesize
             - ((h_mode==SINGLE_CHANNEL) ?  9:17) // 减去 边(side)信息尺寸
             - ((h_protection_bit!=0) ? 0 : 2)    // 减去 CRC 尺寸
             - 4;                                 // 减去 头尺寸
         }
       } else {                                   // 层 Layer II 槽为 0
         nSlots = 0;
       }
     }
     framesize -= 4;                              // 再扣去一遍头尺寸?
     return framesize;                            // 返回
   }

3. 帧头是否同步,即检查头32位整数的合法性
   public boolean isSyncMark(int headerstring, int syncmode, int syncword)  {
     boolean sync = false;                        // 同步变量

     if (syncmode==INITIAL_SYNC) {                // 初始化同步
       sync=((headerstring&0xFFE00000)==0xFFE00000); // MPEG 2.5
     } else {                                     // 否则要检查内部合法性
       sync=((headerstring&0xFFF80C00)==syncword) // 同步字相同,且:
         &&(((headerstring&0x000000C0)==0x000000C0)==single_ch_mode);
     }

     if (sync)                                    // 过滤掉非法采样率
       sync = (((headerstring >>> 10) & 3)!=3);
     if (sync)                                    // 过滤掉非法层
       sync = (((headerstring >>> 17) & 3)!=0);
     if (sync)                                    // 过滤掉非法版本
       sync = (((headerstring >>> 19) & 3)!=1);

     return sync;                                 // 返回是否同步
   }

4. 帧数据分析,转化读入的字节为每4个转化为一个32位整数。问题:为什么要这样做?
   void parse_frame() throws BitstreamException {
     int b=0;
     byte[] byteread = frame_bytes;               // 予处理:帧字节缓冲
     int bytesize = framesize;                    // 帧尺寸(单位字节)

     for (int k=0; k       byte b0=0, b1=0, b2=0, b3=0;
       b0 = byteread[k];
       if (k+1       if (k+2       if (k+3       framebuffer[b++] = (b0 << 24) | (b1 << 16) // 再合成32位整数:先读的 b0, b1 在高位,
                        | (b2 << 8)  | b3;        // 后读的 b2, b3 在低位
     }

     wordpointer = 0;                             // 后处理:字指针复位 0,范围:0 ~ 整数字个数-1
     bitindex = 0;                                // 位指针复位 0,范围:0 ~ 31
   }

5. 从缓冲区读入指定位数到一个无符号整数的低位部分 LSB(1~16)
   public int get_bits(int number_of_bits) {
     int returnvalue = 0;
     int sum = bitindex + number_of_bits;         // bitindex为当前字wordpointer下的当前位数指针

     if (wordpointer < 0) wordpointer = 0;        // 这儿有个问题,wordpointer 能是-1吗?!

     if (sum <= 32) {                             // 所有位包含在当前字中*wordpointer,没跨32位字
       returnvalue = (framebuffer[wordpointer] >>> (32 - sum))
         & bitmask[number_of_bits];               // bitmask[] = {0,1,3,7,15,31,63,127,...}
       if ((bitindex+=number_of_bits)==32) {      // 位指针前移 number_of_bits 位
         bitindex = 0;                            // bitindex==32, 即 bitindex = 0
         wordpointer++;                           // 字指针前移一个字
       }
     } else {                                     // 跨字处理
       int Right = (framebuffer[wordpointer] & 0x0000FFFF); // 上字后半部分
       wordpointer++;                             // 字指针前移一个字
       int Left = (framebuffer[wordpointer] & 0xFFFF0000); // 下子前半部分
       returnvalue = ((Right << 16) & 0xFFFF0000)
         | ((Left >>> 16)& 0x0000FFFF);           // 整字合并

       returnvalue >>>= 48 - sum;                 // 截尾便于掩码操作
       returnvalue &= bitmask[number_of_bits];    // 掩码出想读的位数字
       bitindex = sum - 32;                       // 位指针前移到位结束处
     }

     return returnvalue;                          // 返回想读的位数字
   }

6. 首个帧头处理初始化——Decoder.initialize(header)
   private void initialize(Header header) throws DecoderException {
     float scalefactor = 32700.0f;                // 评论:允许客户化缩放系数(Scale Factor)
     int mode = header.mode();
     int layer = header.layer();
     int channels = (mode==Header.SINGLE_CHANNEL ? 1 : 2);

     if (output==null)                            // 设置创建输出缓冲区,如果客户端未设置
       output = new SampleBuffer(header.frequency(), channels);

     float[] factors = equalizer.getBandFactors();// 均衡器在解码器创建时已创建,获取其各波段系数
     filter1 = new SynthesisFilter(0, scalefactor, factors); // 创建合成过滤器 1

     if (channels==2)                             // 评论:允许为立体声输出单声道
       filter2 = new SynthesisFilter(1, scalefactor, factors); // 创建合成过滤器 2

     outputChannels = channels;
     outputFrequency = header.frequency();

     initialized = true;                          // 初始化完成标志,以后不必再初始化。405
  }

阅读(668) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~