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