// PpmdDecode.h // 2009-05-30 : Igor Pavlov : Public domain // This code is based on Dmitry Shkarin's PPMdH code (public domain) #ifndef __COMPRESS_PPMD_DECODE_H #define __COMPRESS_PPMD_DECODE_H #include "PpmdContext.h" namespace NCompress { namespace NPpmd { class CRangeDecoderVirt { public: virtual ~CRangeDecoderVirt() {} virtual UInt32 GetThreshold(UInt32 total) = 0; virtual void Decode(UInt32 start, UInt32 size) = 0; virtual UInt32 DecodeBit(UInt32 size0, UInt32 numTotalBits) = 0; }; typedef NRangeCoder::CDecoder CRangeDecoderMy; class CRangeDecoder:public CRangeDecoderVirt, public CRangeDecoderMy { UInt32 GetThreshold(UInt32 total) { return CRangeDecoderMy::GetThreshold(total); } void Decode(UInt32 start, UInt32 size) { CRangeDecoderMy::Decode(start, size); } UInt32 DecodeBit(UInt32 size0, UInt32 numTotalBits) { return CRangeDecoderMy::DecodeBit(size0, numTotalBits); } }; struct CDecodeInfo: public CInfo { void DecodeBinSymbol(CRangeDecoderVirt *rangeDecoder) { PPM_CONTEXT::STATE& rs = MinContext->oneState(); UInt16& bs = GetBinSumm(rs, GetContextNoCheck(MinContext->Suffix)->NumStats); if (rangeDecoder->DecodeBit(bs, TOT_BITS) == 0) { FoundState = &rs; rs.Freq = (Byte)(rs.Freq + (rs.Freq < 128 ? 1: 0)); bs = (UInt16)(bs + INTERVAL - GET_MEAN(bs, PERIOD_BITS, 2)); PrevSuccess = 1; RunLength++; } else { bs = (UInt16)(bs - GET_MEAN(bs, PERIOD_BITS, 2)); InitEsc = ExpEscape[bs >> 10]; NumMasked = 1; CharMask[rs.Symbol] = EscCount; PrevSuccess = 0; FoundState = NULL; } } void DecodeSymbol1(CRangeDecoderVirt *rangeDecoder) { PPM_CONTEXT::STATE* p = GetStateNoCheck(MinContext->Stats); int i, count, hiCnt; if ((count = rangeDecoder->GetThreshold(MinContext->SummFreq)) < (hiCnt = p->Freq)) { PrevSuccess = (2 * hiCnt > MinContext->SummFreq); RunLength += PrevSuccess; rangeDecoder->Decode(0, p->Freq); // MinContext->SummFreq); (FoundState = p)->Freq = (Byte)(hiCnt += 4); MinContext->SummFreq += 4; if (hiCnt > MAX_FREQ) rescale(); return; } PrevSuccess = 0; i = MinContext->NumStats - 1; while ((hiCnt += (++p)->Freq) <= count) if (--i == 0) { HiBitsFlag = HB2Flag[FoundState->Symbol]; rangeDecoder->Decode(hiCnt, MinContext->SummFreq - hiCnt); // , MinContext->SummFreq); CharMask[p->Symbol] = EscCount; i = (NumMasked = MinContext->NumStats)-1; FoundState = NULL; do { CharMask[(--p)->Symbol] = EscCount; } while ( --i ); return; } rangeDecoder->Decode(hiCnt - p->Freq, p->Freq); // , MinContext->SummFreq); update1(p); } void DecodeSymbol2(CRangeDecoderVirt *rangeDecoder) { int count, hiCnt, i = MinContext->NumStats - NumMasked; UInt32 freqSum; SEE2_CONTEXT* psee2c = makeEscFreq2(i, freqSum); PPM_CONTEXT::STATE* ps[256], ** pps = ps, * p = GetStateNoCheck(MinContext->Stats)-1; hiCnt = 0; do { do { p++; } while (CharMask[p->Symbol] == EscCount); hiCnt += p->Freq; *pps++ = p; } while ( --i ); freqSum += hiCnt; count = rangeDecoder->GetThreshold(freqSum); p = *(pps = ps); if (count < hiCnt) { hiCnt = 0; while ((hiCnt += p->Freq) <= count) p=*++pps; rangeDecoder->Decode(hiCnt - p->Freq, p->Freq); // , freqSum); psee2c->update(); update2(p); } else { rangeDecoder->Decode(hiCnt, freqSum - hiCnt); // , freqSum); i = MinContext->NumStats - NumMasked; pps--; do { CharMask[(*++pps)->Symbol] = EscCount; } while ( --i ); psee2c->Summ = (UInt16)(psee2c->Summ + freqSum); NumMasked = MinContext->NumStats; } } int DecodeSymbol(CRangeDecoderVirt *rangeDecoder) { if (MinContext->NumStats != 1) DecodeSymbol1(rangeDecoder); else DecodeBinSymbol(rangeDecoder); while ( !FoundState ) { do { OrderFall++; MinContext = GetContext(MinContext->Suffix); if (MinContext == 0) return -1; } while (MinContext->NumStats == NumMasked); DecodeSymbol2(rangeDecoder); } Byte symbol = FoundState->Symbol; NextContext(); return symbol; } }; }} #endif