mirror of
https://github.com/doublecmd/doublecmd.git
synced 2026-06-28 10:02:14 +00:00
99 lines
2.5 KiB
ObjectPascal
99 lines
2.5 KiB
ObjectPascal
unit URangeDecoder;
|
|
|
|
{$IFDEF FPC}
|
|
{$MODE Delphi}
|
|
{$ENDIF}
|
|
|
|
interface
|
|
|
|
uses Classes,ULZMACommon;
|
|
|
|
type TRangeDecoder=class
|
|
public
|
|
Range,Code:integer;
|
|
Stream:TStream;
|
|
procedure SetStream(const Stream:TStream);
|
|
procedure ReleaseStream;
|
|
procedure Init;
|
|
function DecodeDirectBits(const numTotalBits:integer):integer;
|
|
function DecodeBit(var probs: array of smallint;const index:integer):integer;
|
|
end;
|
|
|
|
procedure InitBitModels(var probs: array of smallint);
|
|
|
|
implementation
|
|
|
|
const kTopMask = not ((1 shl 24) - 1);
|
|
kNumBitModelTotalBits = 11;
|
|
kBitModelTotal = (1 shl kNumBitModelTotalBits);
|
|
kNumMoveBits = 5;
|
|
|
|
procedure TRangeDecoder.SetStream(const Stream:TStream);
|
|
begin
|
|
self.Stream:=Stream;
|
|
end;
|
|
|
|
procedure TRangeDecoder.ReleaseStream;
|
|
begin
|
|
stream:=nil;
|
|
end;
|
|
|
|
procedure TRangeDecoder.Init;
|
|
var i:integer;
|
|
begin
|
|
code:=0;
|
|
Range:=-1;
|
|
for i:=0 to 4 do begin
|
|
code:=(code shl 8) or byte(ReadByte(stream));
|
|
end;
|
|
end;
|
|
|
|
function TRangeDecoder.DecodeDirectBits(const numTotalBits:integer):integer;
|
|
var i,t:integer;
|
|
begin
|
|
result:=0;
|
|
for i := numTotalBits downto 1 do begin
|
|
range:=range shr 1;
|
|
t := (cardinal(Code - Range) shr 31);
|
|
Code := integer(Code - Range and (t - 1));
|
|
result := (result shl 1) or (1 - t);
|
|
if ((Range and kTopMask) = 0) then begin
|
|
Code := (Code shl 8) or ReadByte(stream);
|
|
Range := Range shl 8;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TRangeDecoder.DecodeBit(var probs: array of smallint;const index:integer):integer;
|
|
var prob,newbound:integer;
|
|
begin
|
|
prob:=probs[index];
|
|
newbound:= integer((Range shr kNumBitModelTotalBits) * prob);
|
|
if (integer((integer(Code) xor integer($80000000))) < integer((integer(newBound) xor integer($80000000)))) then begin
|
|
Range := newBound;
|
|
probs[index] := (prob + ((kBitModelTotal - prob) shr kNumMoveBits));
|
|
if ((Range and kTopMask) = 0) then begin
|
|
Code := (Code shl 8) or ReadByte(stream);
|
|
Range := Range shl 8;
|
|
end;
|
|
result:=0;
|
|
end else begin
|
|
Range := integer(Range - newBound);
|
|
Code := integer(Code - newBound);
|
|
probs[index] := (prob - ((prob) shr kNumMoveBits));
|
|
if ((Range and kTopMask) = 0) then begin
|
|
Code := (Code shl 8) or ReadByte(stream);
|
|
Range := Range shl 8;
|
|
end;
|
|
result:=1;
|
|
end;
|
|
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;
|
|
|
|
end.
|