2024-09-24 14:54:57 +02:00

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;
}
}
}