mirror of
https://github.com/ZDoom/Raze.git
synced 2024-12-25 03:30:53 +00:00
718112a8fe
Currently none of these is being used, but eventually they will, once more code gets ported over. So it's better to have them right away and avoid editing the project file too much, only to revert that later.
191 lines
4.6 KiB
C
191 lines
4.6 KiB
C
/* Ppmd7Dec.c -- PPMdH Decoder
|
|
2018-07-04 : Igor Pavlov : Public domain
|
|
This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
|
|
|
|
#include "Precomp.h"
|
|
|
|
#include "Ppmd7.h"
|
|
|
|
#define kTopValue (1 << 24)
|
|
|
|
BoolInt Ppmd7z_RangeDec_Init(CPpmd7z_RangeDec *p)
|
|
{
|
|
unsigned i;
|
|
p->Code = 0;
|
|
p->Range = 0xFFFFFFFF;
|
|
if (IByteIn_Read(p->Stream) != 0)
|
|
return False;
|
|
for (i = 0; i < 4; i++)
|
|
p->Code = (p->Code << 8) | IByteIn_Read(p->Stream);
|
|
return (p->Code < 0xFFFFFFFF);
|
|
}
|
|
|
|
#define GET_Ppmd7z_RangeDec CPpmd7z_RangeDec *p = CONTAINER_FROM_VTBL(pp, CPpmd7z_RangeDec, vt);
|
|
|
|
static UInt32 Range_GetThreshold(const IPpmd7_RangeDec *pp, UInt32 total)
|
|
{
|
|
GET_Ppmd7z_RangeDec
|
|
return p->Code / (p->Range /= total);
|
|
}
|
|
|
|
static void Range_Normalize(CPpmd7z_RangeDec *p)
|
|
{
|
|
if (p->Range < kTopValue)
|
|
{
|
|
p->Code = (p->Code << 8) | IByteIn_Read(p->Stream);
|
|
p->Range <<= 8;
|
|
if (p->Range < kTopValue)
|
|
{
|
|
p->Code = (p->Code << 8) | IByteIn_Read(p->Stream);
|
|
p->Range <<= 8;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void Range_Decode(const IPpmd7_RangeDec *pp, UInt32 start, UInt32 size)
|
|
{
|
|
GET_Ppmd7z_RangeDec
|
|
p->Code -= start * p->Range;
|
|
p->Range *= size;
|
|
Range_Normalize(p);
|
|
}
|
|
|
|
static UInt32 Range_DecodeBit(const IPpmd7_RangeDec *pp, UInt32 size0)
|
|
{
|
|
GET_Ppmd7z_RangeDec
|
|
UInt32 newBound = (p->Range >> 14) * size0;
|
|
UInt32 symbol;
|
|
if (p->Code < newBound)
|
|
{
|
|
symbol = 0;
|
|
p->Range = newBound;
|
|
}
|
|
else
|
|
{
|
|
symbol = 1;
|
|
p->Code -= newBound;
|
|
p->Range -= newBound;
|
|
}
|
|
Range_Normalize(p);
|
|
return symbol;
|
|
}
|
|
|
|
void Ppmd7z_RangeDec_CreateVTable(CPpmd7z_RangeDec *p)
|
|
{
|
|
p->vt.GetThreshold = Range_GetThreshold;
|
|
p->vt.Decode = Range_Decode;
|
|
p->vt.DecodeBit = Range_DecodeBit;
|
|
}
|
|
|
|
|
|
#define MASK(sym) ((signed char *)charMask)[sym]
|
|
|
|
int Ppmd7_DecodeSymbol(CPpmd7 *p, const IPpmd7_RangeDec *rc)
|
|
{
|
|
size_t charMask[256 / sizeof(size_t)];
|
|
if (p->MinContext->NumStats != 1)
|
|
{
|
|
CPpmd_State *s = Ppmd7_GetStats(p, p->MinContext);
|
|
unsigned i;
|
|
UInt32 count, hiCnt;
|
|
if ((count = rc->GetThreshold(rc, p->MinContext->SummFreq)) < (hiCnt = s->Freq))
|
|
{
|
|
Byte symbol;
|
|
rc->Decode(rc, 0, s->Freq);
|
|
p->FoundState = s;
|
|
symbol = s->Symbol;
|
|
Ppmd7_Update1_0(p);
|
|
return symbol;
|
|
}
|
|
p->PrevSuccess = 0;
|
|
i = p->MinContext->NumStats - 1;
|
|
do
|
|
{
|
|
if ((hiCnt += (++s)->Freq) > count)
|
|
{
|
|
Byte symbol;
|
|
rc->Decode(rc, hiCnt - s->Freq, s->Freq);
|
|
p->FoundState = s;
|
|
symbol = s->Symbol;
|
|
Ppmd7_Update1(p);
|
|
return symbol;
|
|
}
|
|
}
|
|
while (--i);
|
|
if (count >= p->MinContext->SummFreq)
|
|
return -2;
|
|
p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol];
|
|
rc->Decode(rc, hiCnt, p->MinContext->SummFreq - hiCnt);
|
|
PPMD_SetAllBitsIn256Bytes(charMask);
|
|
MASK(s->Symbol) = 0;
|
|
i = p->MinContext->NumStats - 1;
|
|
do { MASK((--s)->Symbol) = 0; } while (--i);
|
|
}
|
|
else
|
|
{
|
|
UInt16 *prob = Ppmd7_GetBinSumm(p);
|
|
if (rc->DecodeBit(rc, *prob) == 0)
|
|
{
|
|
Byte symbol;
|
|
*prob = (UInt16)PPMD_UPDATE_PROB_0(*prob);
|
|
symbol = (p->FoundState = Ppmd7Context_OneState(p->MinContext))->Symbol;
|
|
Ppmd7_UpdateBin(p);
|
|
return symbol;
|
|
}
|
|
*prob = (UInt16)PPMD_UPDATE_PROB_1(*prob);
|
|
p->InitEsc = PPMD7_kExpEscape[*prob >> 10];
|
|
PPMD_SetAllBitsIn256Bytes(charMask);
|
|
MASK(Ppmd7Context_OneState(p->MinContext)->Symbol) = 0;
|
|
p->PrevSuccess = 0;
|
|
}
|
|
for (;;)
|
|
{
|
|
CPpmd_State *ps[256], *s;
|
|
UInt32 freqSum, count, hiCnt;
|
|
CPpmd_See *see;
|
|
unsigned i, num, numMasked = p->MinContext->NumStats;
|
|
do
|
|
{
|
|
p->OrderFall++;
|
|
if (!p->MinContext->Suffix)
|
|
return -1;
|
|
p->MinContext = Ppmd7_GetContext(p, p->MinContext->Suffix);
|
|
}
|
|
while (p->MinContext->NumStats == numMasked);
|
|
hiCnt = 0;
|
|
s = Ppmd7_GetStats(p, p->MinContext);
|
|
i = 0;
|
|
num = p->MinContext->NumStats - numMasked;
|
|
do
|
|
{
|
|
int k = (int)(MASK(s->Symbol));
|
|
hiCnt += (s->Freq & k);
|
|
ps[i] = s++;
|
|
i -= k;
|
|
}
|
|
while (i != num);
|
|
|
|
see = Ppmd7_MakeEscFreq(p, numMasked, &freqSum);
|
|
freqSum += hiCnt;
|
|
count = rc->GetThreshold(rc, freqSum);
|
|
|
|
if (count < hiCnt)
|
|
{
|
|
Byte symbol;
|
|
CPpmd_State **pps = ps;
|
|
for (hiCnt = 0; (hiCnt += (*pps)->Freq) <= count; pps++);
|
|
s = *pps;
|
|
rc->Decode(rc, hiCnt - s->Freq, s->Freq);
|
|
Ppmd_See_Update(see);
|
|
p->FoundState = s;
|
|
symbol = s->Symbol;
|
|
Ppmd7_Update2(p);
|
|
return symbol;
|
|
}
|
|
if (count >= freqSum)
|
|
return -2;
|
|
rc->Decode(rc, hiCnt, freqSum - hiCnt);
|
|
see->Summ = (UInt16)(see->Summ + freqSum);
|
|
do { MASK(ps[--i]->Symbol) = 0; } while (i != 0);
|
|
}
|
|
}
|