git-svn-id: https://svn.code.sf.net/p/kolmck/code@67 91bb2d04-0c0c-4d2d-88a5-bbb6f4c1fa07
176 lines
4.4 KiB
ObjectPascal
176 lines
4.4 KiB
ObjectPascal
unit URangeEncoder;
|
|
|
|
{$IFDEF FPC}
|
|
{$MODE Delphi}
|
|
{$ENDIF}
|
|
|
|
interface
|
|
|
|
uses KOL,ULZMACommon;
|
|
|
|
const kNumBitPriceShiftBits = 6;
|
|
kTopMask = not ((1 shl 24) - 1);
|
|
kNumBitModelTotalBits = 11;
|
|
kBitModelTotal = (1 shl kNumBitModelTotalBits);
|
|
kNumMoveBits = 5;
|
|
kNumMoveReducingBits = 2;
|
|
|
|
type PRangeEncoder = ^TRangeEncoder;
|
|
TRangeEncoder=object(TObj)
|
|
private
|
|
ProbPrices: array [0..kBitModelTotal shr kNumMoveReducingBits-1] of integer;
|
|
public
|
|
Stream:PStream;
|
|
Low,Position:int64;
|
|
Range,cacheSize,cache:integer;
|
|
procedure SetStream(const Astream:PStream);
|
|
procedure ReleaseStream;
|
|
procedure _Init;
|
|
procedure FlushData;
|
|
procedure FlushStream;
|
|
procedure ShiftLow;
|
|
procedure EncodeDirectBits(const v,AnumTotalBits:integer);
|
|
function GetProcessedSizeAdd:int64;
|
|
procedure Encode(var Aprobs: array of smallint;const Aindex,Asymbol:integer);
|
|
constructor Create;
|
|
function GetPrice(const AProb,Asymbol:integer):integer;
|
|
function GetPrice0(const AProb:integer):integer;
|
|
function GetPrice1(const AProb:integer):integer;
|
|
end;
|
|
|
|
var RangeEncoder:PRangeEncoder;
|
|
|
|
procedure InitBitModels(var probs:array of smallint);
|
|
|
|
implementation
|
|
|
|
procedure TRangeEncoder.SetStream(const Astream:PStream);
|
|
begin
|
|
self.Stream:=AStream;
|
|
end;
|
|
|
|
procedure TRangeEncoder.ReleaseStream;
|
|
begin
|
|
stream:=nil;
|
|
end;
|
|
|
|
procedure TRangeEncoder._Init;
|
|
begin
|
|
position := 0;
|
|
Low := 0;
|
|
Range := -1;
|
|
cacheSize := 1;
|
|
cache := 0;
|
|
end;
|
|
|
|
procedure TRangeEncoder.FlushData;
|
|
var i:integer;
|
|
begin
|
|
for i:=0 to 4 do
|
|
ShiftLow();
|
|
end;
|
|
|
|
procedure TRangeEncoder.FlushStream;
|
|
begin
|
|
//stream.flush;
|
|
end;
|
|
|
|
procedure TRangeEncoder.ShiftLow;
|
|
var LowHi:integer;
|
|
temp:integer;
|
|
begin
|
|
LowHi := (Low shr 32);
|
|
if (LowHi <> 0) or (Low < int64($FF000000)) then begin
|
|
position := position + cacheSize;
|
|
temp := cache;
|
|
repeat
|
|
WriteByte(stream,temp + LowHi);
|
|
temp := $FF;
|
|
dec(cacheSize);
|
|
until(cacheSize = 0);
|
|
cache := (Low shr 24);
|
|
end;
|
|
inc(cacheSize);
|
|
Low := (Low and integer($FFFFFF)) shl 8;
|
|
end;
|
|
|
|
procedure TRangeEncoder.EncodeDirectBits(const v,AnumTotalBits:integer);
|
|
var i:integer;
|
|
begin
|
|
for i := AnumTotalBits - 1 downto 0 do begin
|
|
Range := Range shr 1;
|
|
if (((v shr i) and 1) = 1) then
|
|
Low := Low + Range;
|
|
if ((Range and kTopMask) = 0) then begin
|
|
Range := range shl 8;
|
|
ShiftLow;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TRangeEncoder.GetProcessedSizeAdd:int64;
|
|
begin
|
|
result:=cacheSize + position + 4;
|
|
end;
|
|
|
|
procedure InitBitModels(var probs:array of smallint);
|
|
var i:integer;
|
|
begin
|
|
for i := 0 to length(probs) -1 do
|
|
probs[i] := kBitModelTotal shr 1;
|
|
end;
|
|
|
|
procedure TRangeEncoder.Encode(var Aprobs: array of smallint;const Aindex,Asymbol:integer);
|
|
var prob,newbound:integer;
|
|
begin
|
|
prob := Aprobs[Aindex];
|
|
newBound := (Range shr kNumBitModelTotalBits) * prob;
|
|
if (Asymbol = 0) then begin
|
|
Range := newBound;
|
|
Aprobs[Aindex] := (prob + ((kBitModelTotal - prob) shr kNumMoveBits));
|
|
end else begin
|
|
Low := Low + (newBound and int64($FFFFFFFF));
|
|
Range := Range - newBound;
|
|
Aprobs[Aindex] := (prob - ((prob) shr kNumMoveBits));
|
|
end;
|
|
if ((Range and kTopMask) = 0) then begin
|
|
Range := Range shl 8;
|
|
ShiftLow;
|
|
end;
|
|
end;
|
|
|
|
constructor TRangeEncoder.Create;
|
|
var kNumBits:integer;
|
|
i,j,start,_end:integer;
|
|
begin
|
|
kNumBits := (kNumBitModelTotalBits - kNumMoveReducingBits);
|
|
for i := kNumBits - 1 downto 0 do begin
|
|
start := 1 shl (kNumBits - i - 1);
|
|
_end := 1 shl (kNumBits - i);
|
|
for j := start to _end -1 do
|
|
ProbPrices[j] := (i shl kNumBitPriceShiftBits) +
|
|
(((_end - j) shl kNumBitPriceShiftBits) shr (kNumBits - i - 1));
|
|
end;
|
|
end;
|
|
|
|
function TRangeEncoder.GetPrice(const AProb,Asymbol:integer):integer;
|
|
begin
|
|
result:=ProbPrices[(((AProb - Asymbol) xor ((-Asymbol))) and (kBitModelTotal - 1)) shr kNumMoveReducingBits];
|
|
end;
|
|
|
|
function TRangeEncoder.GetPrice0(const AProb:integer):integer;
|
|
begin
|
|
result:= ProbPrices[AProb shr kNumMoveReducingBits];
|
|
end;
|
|
|
|
function TRangeEncoder.GetPrice1(const AProb:integer):integer;
|
|
begin
|
|
result:= ProbPrices[(kBitModelTotal - AProb) shr kNumMoveReducingBits];
|
|
end;
|
|
|
|
initialization
|
|
New(RangeEncoder, Create);
|
|
finalization
|
|
RangeEncoder.Free;
|
|
end.
|