Chinaunix首页 | 论坛 | 博客
  • 博客访问: 15531776
  • 博文数量: 2005
  • 博客积分: 11986
  • 博客等级: 上将
  • 技术积分: 22535
  • 用 户 组: 普通用户
  • 注册时间: 2007-05-17 13:56
文章分类

全部博文(2005)

文章存档

2014年(2)

2013年(2)

2012年(16)

2011年(66)

2010年(368)

2009年(743)

2008年(491)

2007年(317)

分类:

2009-07-13 20:43:40

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

1. L1帧解码 LayerIDecoder.java
   public void decodeFrame() {
     num_subbands = header.number_of_subbands();
     subbands = new Subband[32];                  // Layer I 有 32 个子带
     mode = header.mode();
     createSubbands();                            // 创建子带
     readAllocation();                            //
     readScaleFactorSelection();                  // L1 层没有比例系数选择

     if ((crc != null) || header.checksum_ok()) { //
       readScaleFactors();                        //
       readSampleData();                          // 读取解样数据
     }
   }

2. 读取分配 LayerIDecoder.java,
   protected void readAllocation() {              // 开始读取音频数据
     for (int i = 0; i < num_subbands; ++i)       // 对 32 个子带依次读取“分配”
       subbands[i].read_allocation(stream, header, crc);
   }
   class SubbandLayer1 {                          // L1 子带
     protect int allocation, samplelength;        // 注:Subband 类属性
     protected float factor, offset;
     ...
     public void read_allocation(Bitstream stream, Header header, Crc16 crc) {
       if ((allocation=stream.get_bits(4))==15);  // 警告:流中包含一个非法分配,MPEG 流已被破坏!
       if (crc!=null) crc.add_bits(allocation, 4);// 加入校验
       if (allocation != 0) {
         samplelength = allocation + 1;           // 计算采样长度
         factor = table_factor[allocation];       // 系数
         offset = table_offset[allocation];       // 偏移
       }
     }
   }

3. 校验和检查 Header class:
   // 比较计算的 checksum 和流 checksum,返回成功与否
   // 校验参与部分有:Header 和 32个4字节 Allocaltion
   public boolean checksum_ok () { return (checksum == crc.checksum()); }

4. 读取比例系数 LayerIDecoder class:
   protected void readScaleFactors() {
     for (int i=0; i       subbands[i].read_scalefactor(stream, header);
   }
   class SubbandLayer1 {                          // L1子带类的比例系数读取
     public void read_scalefactor(Bitstream stream, Header header) {
       if (allocation != 0) scalefactor =
         scalefactors[stream.get_bits(6)];        // 每个子带有 6bits 的比例系数位
     }
   }

5. 读取样本数据并写入解样数据 LayerIDecoder class:
   protected void readSampleData() {
     boolean read_ready = false;
     boolean write_ready = false;
     int  i, mode = header.mode();
     do {
       for (i = 0; i < num_subbands; ++i)         // 对 32 个子带依次读取“样本数据”
         read_ready = subbands[i].read_sampledata(stream);
       do {
         for (i = 0; i < num_subbands; ++i)       // 对 32 个子带解样数据依次写入样本缓冲
           write_ready = subbands[i].put_next_sample(which_channels, filter1, filter2);

         filter1.calculate_pcm_samples(buffer);   // 计算施加过滤器 1
         if ((which_channels==OutputChannels.BOTH_CHANNELS) && (mode!=Header.SINGLE_CHANNEL))
           filter2.calculate_pcm_samples(buffer); // 计算施加过滤器 2
       } while (!write_ready);
     } while (!read_ready);
   }

   class SubbandLayer1 {
     public boolean read_sampledata(Bitstream stream) {
       if (allocation != 0) sample = (float)
         (stream.get_bits(samplelength));         // 读取样本数据,长度=samplelength=allocation+1
       if (++samplenumber == 12) {                // 读取的样本数类计,超过 12 复位
         samplenumber = 0;
         return true;                             // 样本读取结束 32|12 = 96?
       }
       return false;
     }
     ...
   }

   class SynthesisFilter {                        // 计算 32 PCM 采样并放进输出缓冲区 Obuffer 对象
     public void calculate_pcm_samples(Obuffer buffer) {
       compute_new_v();
       compute_pcm_samples(buffer);

       actual_write_pos = (actual_write_pos + 1) & 0xf;
       actual_v = (actual_v == v1) ? v2 : v1;

       for (int p=0; p<32; p++) samples[p] = 0.0f;
     }

     // Compute new values via a fast cosine transform.
     private void compute_new_v() { ... }

     private void compute_pcm_samples(Obuffer buffer) {
       switch (actual_write_pos) {
       case 0:
         compute_pcm_samples0(buffer);
         break;
       case 1:
         ...
       }

       if (buffer!=null)
         buffer.appendSamples(channel, _tmpOut);

       // MDM: I was considering putting in quality control for
       // low-spec CPUs, but the performance gain (about 10-15%)
       // did not justify the considerable drop in audio quality.
       switch (inc) {
       case 16:
         buffer.appendSamples(channel, tmpOut);
         break;
       case 32:
         for (int i=0; i<16; i++) {
           buffer.append(channel, (short)tmpOut[i]);
           buffer.append(channel, (short)tmpOut[i]);
         }
         break;
       case 64:
         for (int i=0; i<8; i++) {
           buffer.append(channel, (short)tmpOut[i]);
           buffer.append(channel, (short)tmpOut[i]);
           buffer.append(channel, (short)tmpOut[i]);
           buffer.append(channel, (short)tmpOut[i]);
         }
         break;
       }
     }

     private void compute_pcm_samples0(Obuffer buffer) {
       final float[] vp = actual_v;
       // int inc = v_inc;
       final float[] tmpOut = _tmpOut;
       int dvp =0;

       // fat chance of having this loop unroll
       for ( int i=0; i<32; i++) {
         float pcm_sample;
         final float[] dp = d16[i];
         pcm_sample = (float)(
           ( (vp[0  + dvp] * dp[0]) + (vp[15 + dvp] * dp[1])
           + (vp[14 + dvp] * dp[2]) + (vp[13 + dvp] * dp[3])
           + (vp[12 + dvp] * dp[4]) + (vp[11 + dvp] * dp[5])
           + (vp[10 + dvp] * dp[6]) + (vp[ 9 + dvp] * dp[7])
           + (vp[ 8 + dvp] * dp[8]) + (vp[ 7 + dvp] * dp[9])
           + (vp[6 + dvp] * dp[10]) + (vp[5 + dvp] * dp[11])
           + (vp[4 + dvp] * dp[12]) + (vp[3 + dvp] * dp[13])
           + (vp[2 + dvp] * dp[14]) + (vp[1 + dvp] * dp[15])
           ) * scalefactor
         );

         tmpOut[i] = pcm_sample;
         dvp += 16;
       }
     }
   }


收藏到:Del.icio.us
阅读(774) | 评论(0) | 转发(3) |
给主人留下些什么吧!~~