66 lines
1.1 KiB
C++
Vendored
66 lines
1.1 KiB
C++
Vendored
/* Copyright (C) Teemu Suutari */
|
|
|
|
#include "RangeDecoder.hpp"
|
|
|
|
|
|
namespace ancient::internal
|
|
{
|
|
|
|
RangeDecoder::BitReader::BitReader()
|
|
{
|
|
// nothing needed
|
|
}
|
|
|
|
RangeDecoder::BitReader::~BitReader()
|
|
{
|
|
// nothing needed
|
|
}
|
|
|
|
RangeDecoder::RangeDecoder(BitReader &bitReader,uint16_t initialValue) :
|
|
_bitReader(bitReader),
|
|
_stream(initialValue)
|
|
{
|
|
// nothing needed
|
|
}
|
|
|
|
RangeDecoder::~RangeDecoder()
|
|
{
|
|
// nothing needed
|
|
}
|
|
|
|
uint16_t RangeDecoder::decode(uint16_t length)
|
|
{
|
|
return ((uint32_t(_stream-_low)+1)*length-1)/(uint32_t(_high-_low)+1);
|
|
}
|
|
|
|
void RangeDecoder::scale(uint16_t newLow,uint16_t newHigh,uint16_t newRange)
|
|
{
|
|
uint32_t range=uint32_t(_high-_low)+1;
|
|
_high=(range*newHigh)/newRange+_low-1;
|
|
_low=(range*newLow)/newRange+_low;
|
|
|
|
auto doubleContext=[&](uint16_t decr)
|
|
{
|
|
_low-=decr;
|
|
_high-=decr;
|
|
_stream-=decr;
|
|
_low<<=1;
|
|
_high=(_high<<1)|1U;
|
|
_stream=(_stream<<1)|_bitReader.readBit();
|
|
};
|
|
|
|
for (;;)
|
|
{
|
|
if (_high<0x8000U)
|
|
{
|
|
doubleContext(0U);
|
|
} else if (_low>=0x8000U) {
|
|
doubleContext(0x8000U);
|
|
} else if (_low>=0x4000U && _high<0xc000U) {
|
|
doubleContext(0x4000U);
|
|
} else break;
|
|
}
|
|
}
|
|
|
|
}
|