module.exports = class RangeCoder {
constructor(src) {
this.low = 0;
this.range = 0xffffffff;
this.code = 0;
this.FFnum = 0;
this.carry = 0;
this.cache = 0;
}
RangeStartDecode(src) {
for (var i = 0; i < 5; i++)
this.code = (this.code << 8) + src.ReadByte();
this.code &= 0xffffffff;
this.code >>>= 0; }
RangeGetFrequency(tot_freq) {
this.range = Math.floor(this.range / tot_freq);
return Math.floor(this.code / this.range);
}
RangeDecode(src, sym_low, sym_freq, tot_freq) {
this.code -= sym_low * this.range;
this.range *= sym_freq;
while (this.range < (1<<24)) {
this.range *= 256;
this.code = (this.code*256 + src.ReadByte());
}
}
RangeShiftLow(dst) {
if (this.low < 0xff000000 | this.carry) {
dst.WriteByte(this.cache + this.carry);
while (this.FFnum) {
dst.WriteByte(this.carry-1);
this.FFnum--;
}
this.cache = this.low >>> 24;
this.carry = 0;
} else {
this.FFnum++; }
this.low <<= 8;
this.low >>>= 0; }
RangeEncode(dst, sym_low, sym_freq, tot_freq) {
var old_low = this.low
this.range = Math.floor(this.range / tot_freq)
this.low += sym_low * this.range;
this.low >>>= 0; this.range *= sym_freq;
if (this.low < old_low) {
if (this.carry != 0) console.log("ERROR: Multiple carry")
this.carry = 1
}
while (this.range < (1<<24)) {
this.range *= 256;
this.RangeShiftLow(dst);
}
}
RangeFinishEncode(dst) {
for (var i = 0; i < 5; i++)
this.RangeShiftLow(dst)
}
};