michael@0: // Compress/RangeCoder/RangeCoderBit.h michael@0: michael@0: #ifndef __COMPRESS_RANGECODER_BIT_H michael@0: #define __COMPRESS_RANGECODER_BIT_H michael@0: michael@0: #include "RangeCoder.h" michael@0: michael@0: namespace NCompress { michael@0: namespace NRangeCoder { michael@0: michael@0: const int kNumBitModelTotalBits = 11; michael@0: const UInt32 kBitModelTotal = (1 << kNumBitModelTotalBits); michael@0: michael@0: const int kNumMoveReducingBits = 2; michael@0: michael@0: const int kNumBitPriceShiftBits = 6; michael@0: const UInt32 kBitPrice = 1 << kNumBitPriceShiftBits; michael@0: michael@0: class CPriceTables michael@0: { michael@0: public: michael@0: static UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits]; michael@0: static void Init(); michael@0: CPriceTables(); michael@0: }; michael@0: michael@0: template michael@0: class CBitModel michael@0: { michael@0: public: michael@0: UInt32 Prob; michael@0: void UpdateModel(UInt32 symbol) michael@0: { michael@0: /* michael@0: Prob -= (Prob + ((symbol - 1) & ((1 << numMoveBits) - 1))) >> numMoveBits; michael@0: Prob += (1 - symbol) << (kNumBitModelTotalBits - numMoveBits); michael@0: */ michael@0: if (symbol == 0) michael@0: Prob += (kBitModelTotal - Prob) >> numMoveBits; michael@0: else michael@0: Prob -= (Prob) >> numMoveBits; michael@0: } michael@0: public: michael@0: void Init() { Prob = kBitModelTotal / 2; } michael@0: }; michael@0: michael@0: template michael@0: class CBitEncoder: public CBitModel michael@0: { michael@0: public: michael@0: void Encode(CEncoder *encoder, UInt32 symbol) michael@0: { michael@0: /* michael@0: encoder->EncodeBit(this->Prob, kNumBitModelTotalBits, symbol); michael@0: this->UpdateModel(symbol); michael@0: */ michael@0: UInt32 newBound = (encoder->Range >> kNumBitModelTotalBits) * this->Prob; michael@0: if (symbol == 0) michael@0: { michael@0: encoder->Range = newBound; michael@0: this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits; michael@0: } michael@0: else michael@0: { michael@0: encoder->Low += newBound; michael@0: encoder->Range -= newBound; michael@0: this->Prob -= (this->Prob) >> numMoveBits; michael@0: } michael@0: if (encoder->Range < kTopValue) michael@0: { michael@0: encoder->Range <<= 8; michael@0: encoder->ShiftLow(); michael@0: } michael@0: } michael@0: UInt32 GetPrice(UInt32 symbol) const michael@0: { michael@0: return CPriceTables::ProbPrices[ michael@0: (((this->Prob - symbol) ^ ((-(int)symbol))) & (kBitModelTotal - 1)) >> kNumMoveReducingBits]; michael@0: } michael@0: UInt32 GetPrice0() const { return CPriceTables::ProbPrices[this->Prob >> kNumMoveReducingBits]; } michael@0: UInt32 GetPrice1() const { return CPriceTables::ProbPrices[(kBitModelTotal - this->Prob) >> kNumMoveReducingBits]; } michael@0: }; michael@0: michael@0: michael@0: template michael@0: class CBitDecoder: public CBitModel michael@0: { michael@0: public: michael@0: UInt32 Decode(CDecoder *decoder) michael@0: { michael@0: UInt32 newBound = (decoder->Range >> kNumBitModelTotalBits) * this->Prob; michael@0: if (decoder->Code < newBound) michael@0: { michael@0: decoder->Range = newBound; michael@0: this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits; michael@0: if (decoder->Range < kTopValue) michael@0: { michael@0: decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte(); michael@0: decoder->Range <<= 8; michael@0: } michael@0: return 0; michael@0: } michael@0: else michael@0: { michael@0: decoder->Range -= newBound; michael@0: decoder->Code -= newBound; michael@0: this->Prob -= (this->Prob) >> numMoveBits; michael@0: if (decoder->Range < kTopValue) michael@0: { michael@0: decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte(); michael@0: decoder->Range <<= 8; michael@0: } michael@0: return 1; michael@0: } michael@0: } michael@0: }; michael@0: michael@0: }} michael@0: michael@0: #endif