Home | History | Annotate | Download | only in Compress
      1 // Compress/RangeCoderBit.h
      2 // 2013-01-10 : Igor Pavlov : Public domain
      3 
      4 #ifndef __COMPRESS_RANGE_CODER_BIT_H
      5 #define __COMPRESS_RANGE_CODER_BIT_H
      6 
      7 #include "RangeCoder.h"
      8 
      9 namespace NCompress {
     10 namespace NRangeCoder {
     11 
     12 const unsigned kNumBitModelTotalBits = 11;
     13 const UInt32 kBitModelTotal = (1 << kNumBitModelTotalBits);
     14 
     15 const unsigned kNumMoveReducingBits = 4;
     16 
     17 const unsigned kNumBitPriceShiftBits = 4;
     18 const UInt32 kBitPrice = 1 << kNumBitPriceShiftBits;
     19 
     20 extern UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits];
     21 
     22 template <unsigned numMoveBits>
     23 class CBitModel
     24 {
     25 public:
     26   UInt32 Prob;
     27   void UpdateModel(UInt32 symbol)
     28   {
     29     /*
     30     Prob -= (Prob + ((symbol - 1) & ((1 << numMoveBits) - 1))) >> numMoveBits;
     31     Prob += (1 - symbol) << (kNumBitModelTotalBits - numMoveBits);
     32     */
     33     if (symbol == 0)
     34       Prob += (kBitModelTotal - Prob) >> numMoveBits;
     35     else
     36       Prob -= (Prob) >> numMoveBits;
     37   }
     38 public:
     39   void Init() { Prob = kBitModelTotal / 2; }
     40 };
     41 
     42 template <unsigned numMoveBits>
     43 class CBitEncoder: public CBitModel<numMoveBits>
     44 {
     45 public:
     46   void Encode(CEncoder *encoder, UInt32 symbol)
     47   {
     48     /*
     49     encoder->EncodeBit(this->Prob, kNumBitModelTotalBits, symbol);
     50     this->UpdateModel(symbol);
     51     */
     52     UInt32 newBound = (encoder->Range >> kNumBitModelTotalBits) * this->Prob;
     53     if (symbol == 0)
     54     {
     55       encoder->Range = newBound;
     56       this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits;
     57     }
     58     else
     59     {
     60       encoder->Low += newBound;
     61       encoder->Range -= newBound;
     62       this->Prob -= (this->Prob) >> numMoveBits;
     63     }
     64     if (encoder->Range < kTopValue)
     65     {
     66       encoder->Range <<= 8;
     67       encoder->ShiftLow();
     68     }
     69   }
     70   UInt32 GetPrice(UInt32 symbol) const
     71   {
     72     return ProbPrices[(this->Prob ^ ((-(int)(Int32)symbol)) & (kBitModelTotal - 1)) >> kNumMoveReducingBits];
     73   }
     74   UInt32 GetPrice0() const { return ProbPrices[this->Prob >> kNumMoveReducingBits]; }
     75   UInt32 GetPrice1() const { return ProbPrices[(this->Prob ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]; }
     76 };
     77 
     78 
     79 template <unsigned numMoveBits>
     80 class CBitDecoder: public CBitModel<numMoveBits>
     81 {
     82 public:
     83   UInt32 Decode(CDecoder *decoder)
     84   {
     85     UInt32 newBound = (decoder->Range >> kNumBitModelTotalBits) * this->Prob;
     86     if (decoder->Code < newBound)
     87     {
     88       decoder->Range = newBound;
     89       this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits;
     90       if (decoder->Range < kTopValue)
     91       {
     92         decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte();
     93         decoder->Range <<= 8;
     94       }
     95       return 0;
     96     }
     97     else
     98     {
     99       decoder->Range -= newBound;
    100       decoder->Code -= newBound;
    101       this->Prob -= (this->Prob) >> numMoveBits;
    102       if (decoder->Range < kTopValue)
    103       {
    104         decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte();
    105         decoder->Range <<= 8;
    106       }
    107       return 1;
    108     }
    109   }
    110 };
    111 
    112 }}
    113 
    114 #endif
    115