Home | History | Annotate | Download | only in RangeCoder
      1 using System;
      2 
      3 namespace SevenZip.Compression.RangeCoder
      4 {
      5 	struct BitEncoder
      6 	{
      7 		public const int kNumBitModelTotalBits = 11;
      8 		public const uint kBitModelTotal = (1 << kNumBitModelTotalBits);
      9 		const int kNumMoveBits = 5;
     10 		const int kNumMoveReducingBits = 2;
     11 		public const int kNumBitPriceShiftBits = 6;
     12 
     13 		uint Prob;
     14 
     15 		public void Init() { Prob = kBitModelTotal >> 1; }
     16 
     17 		public void UpdateModel(uint symbol)
     18 		{
     19 			if (symbol == 0)
     20 				Prob += (kBitModelTotal - Prob) >> kNumMoveBits;
     21 			else
     22 				Prob -= (Prob) >> kNumMoveBits;
     23 		}
     24 
     25 		public void Encode(Encoder encoder, uint symbol)
     26 		{
     27 			// encoder.EncodeBit(Prob, kNumBitModelTotalBits, symbol);
     28 			// UpdateModel(symbol);
     29 			uint newBound = (encoder.Range >> kNumBitModelTotalBits) * Prob;
     30 			if (symbol == 0)
     31 			{
     32 				encoder.Range = newBound;
     33 				Prob += (kBitModelTotal - Prob) >> kNumMoveBits;
     34 			}
     35 			else
     36 			{
     37 				encoder.Low += newBound;
     38 				encoder.Range -= newBound;
     39 				Prob -= (Prob) >> kNumMoveBits;
     40 			}
     41 			if (encoder.Range < Encoder.kTopValue)
     42 			{
     43 				encoder.Range <<= 8;
     44 				encoder.ShiftLow();
     45 			}
     46 		}
     47 
     48 		private static UInt32[] ProbPrices = new UInt32[kBitModelTotal >> kNumMoveReducingBits];
     49 
     50 		static BitEncoder()
     51 		{
     52 			const int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits);
     53 			for (int i = kNumBits - 1; i >= 0; i--)
     54 			{
     55 				UInt32 start = (UInt32)1 << (kNumBits - i - 1);
     56 				UInt32 end = (UInt32)1 << (kNumBits - i);
     57 				for (UInt32 j = start; j < end; j++)
     58 					ProbPrices[j] = ((UInt32)i << kNumBitPriceShiftBits) +
     59 						(((end - j) << kNumBitPriceShiftBits) >> (kNumBits - i - 1));
     60 			}
     61 		}
     62 
     63 		public uint GetPrice(uint symbol)
     64 		{
     65 			return ProbPrices[(((Prob - symbol) ^ ((-(int)symbol))) & (kBitModelTotal - 1)) >> kNumMoveReducingBits];
     66 		}
     67 	  public uint GetPrice0() { return ProbPrices[Prob >> kNumMoveReducingBits]; }
     68 		public uint GetPrice1() { return ProbPrices[(kBitModelTotal - Prob) >> kNumMoveReducingBits]; }
     69 	}
     70 
     71 	struct BitDecoder
     72 	{
     73 		public const int kNumBitModelTotalBits = 11;
     74 		public const uint kBitModelTotal = (1 << kNumBitModelTotalBits);
     75 		const int kNumMoveBits = 5;
     76 
     77 		uint Prob;
     78 
     79 		public void UpdateModel(int numMoveBits, uint symbol)
     80 		{
     81 			if (symbol == 0)
     82 				Prob += (kBitModelTotal - Prob) >> numMoveBits;
     83 			else
     84 				Prob -= (Prob) >> numMoveBits;
     85 		}
     86 
     87 		public void Init() { Prob = kBitModelTotal >> 1; }
     88 
     89 		public uint Decode(RangeCoder.Decoder rangeDecoder)
     90 		{
     91 			uint newBound = (uint)(rangeDecoder.Range >> kNumBitModelTotalBits) * (uint)Prob;
     92 			if (rangeDecoder.Code < newBound)
     93 			{
     94 				rangeDecoder.Range = newBound;
     95 				Prob += (kBitModelTotal - Prob) >> kNumMoveBits;
     96 				if (rangeDecoder.Range < Decoder.kTopValue)
     97 				{
     98 					rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte();
     99 					rangeDecoder.Range <<= 8;
    100 				}
    101 				return 0;
    102 			}
    103 			else
    104 			{
    105 				rangeDecoder.Range -= newBound;
    106 				rangeDecoder.Code -= newBound;
    107 				Prob -= (Prob) >> kNumMoveBits;
    108 				if (rangeDecoder.Range < Decoder.kTopValue)
    109 				{
    110 					rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte();
    111 					rangeDecoder.Range <<= 8;
    112 				}
    113 				return 1;
    114 			}
    115 		}
    116 	}
    117 }
    118