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