-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathpacking.pas
222 lines (195 loc) · 8.02 KB
/
packing.pas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
{
publish with BSD Licence.
Copyright (c) Terry Lao
}
unit packing;
{$MODE Delphi}
interface
uses
iLBC_define,
constants,
helpfun,C2Delphi_header;
{----------------------------------------------------------------*
* splitting an integer into first most significant bits and
* remaining least significant bits
*---------------------------------------------------------------}
procedure packsplit(
index:pinteger; { (i) the value to split }
firstpart:pinteger; { (o) the value specified by most
significant bits }
rest:pinteger; { (o) the value specified by least
significant bits }
bitno_firstpart:integer; { (i) number of bits in most
significant part }
bitno_total:integer { (i) number of bits in full range
of value }
);
procedure packcombine(
index:pinteger; { (i/o) the msb value in the
combined value out }
rest:integer; { (i) the lsb value }
bitno_rest:integer { (i) the number of bits in the
lsb part }
);
procedure dopack(
bitstream :ppchar; { (i/o) on entrance pointer to
place in bitstream to pack
new data, on exit pointer
to place in bitstream to
pack future data }
index:integer; { (i) the value to pack }
bitno:integer; { (i) the number of bits that the
value will fit within }
pos:pinteger { (i/o) write position in the
current byte }
);
procedure unpack(
bitstream :ppchar; { (i/o) on entrance pointer to
place in bitstream to
unpack new data from, on
exit pointer to place in
bitstream to unpack future
data from }
index:pinteger; { (o) resulting value }
bitno:integer; { (i) number of bits used to
represent the value }
pos:pinteger { (i/o) read position in the
current byte }
);
implementation
procedure packsplit(
index:pinteger; { (i) the value to split }
firstpart:pinteger; { (o) the value specified by most
significant bits }
rest:pinteger; { (o) the value specified by least
significant bits }
bitno_firstpart:integer; { (i) number of bits in most
significant part }
bitno_total:integer { (i) number of bits in full range
of value }
);
var
bitno_rest:integer;
begin
bitno_rest := bitno_total-bitno_firstpart;
firstpart^ := index^ shr (bitno_rest);
rest^ := index^-(firstpart^ shl (bitno_rest));
end;
{----------------------------------------------------------------*
* combining a value corresponding to msb's with a value
* corresponding to lsb's
*---------------------------------------------------------------}
procedure packcombine(
index:pinteger; { (i/o) the msb value in the
combined value out }
rest:integer; { (i) the lsb value }
bitno_rest:integer { (i) the number of bits in the
lsb part }
);
begin
index^ := index^ shl bitno_rest;
index^ :=index^ + rest;
end;
{----------------------------------------------------------------*
* packing of bits into bitstream, i.e., vector of bytes
*---------------------------------------------------------------}
procedure dopack(
bitstream :ppchar; { (i/o) on entrance pointer to
place in bitstream to pack
new data, on exit pointer
to place in bitstream to
pack future data }
index:integer; { (i) the value to pack }
bitno:integer; { (i) the number of bits that the
value will fit within }
pos:pinteger { (i/o) write position in the
current byte }
);
var
posLeft:integer;
begin
{ Clear the bits before starting in a new byte }
if (pos^=0) then
begin
bitstream^^:=#0;
end;
while (bitno>0) do
begin
{ Jump to the next byte if end of this byte is reached}
if (pos^=8) then
begin
pos^:=0;
inc(bitstream^);//(*bitstream)++;
bitstream^^:=#0;
end;
posLeft:=8-(pos^);
{ Insert index into the bitstream }
if (bitno <= posLeft) then
begin
bitstream^^ := char(byte(bitstream^^) or (index shl (posLeft-bitno)));
pos^:=pos^+bitno;
bitno:=0;
end
else
begin
bitstream^^:=char(byte(bitstream^^) or (index shr (bitno-posLeft)));
pos^:=8;
index:=index-((index shr (bitno-posLeft)) shl (bitno-posLeft));
bitno:=bitno-posLeft;
end;
end;
end;
{----------------------------------------------------------------*
* unpacking of bits from bitstream, i.e., vector of bytes
*---------------------------------------------------------------}
procedure unpack(
bitstream :ppchar; { (i/o) on entrance pointer to
place in bitstream to
unpack new data from, on
exit pointer to place in
bitstream to unpack future
data from }
index:pinteger; { (o) resulting value }
bitno:integer; { (i) number of bits used to
represent the value }
pos:pinteger { (i/o) read position in the
current byte }
);
var
BitsLeft:integer;
begin
index^:=0;
while (bitno>0) do
begin
{ move forward in bitstream when the end of the
byte is reached }
if (pos^=8) then
begin
pos^:=0;
inc(bitstream^);//(*bitstream)++;
end;
BitsLeft:=8-(pos^);
{ Extract bits to index }
if (BitsLeft>=bitno) then
begin
index^:=index^+ (((byte(bitstream^^) shl (pos^)) and $FF) shr (8-bitno));
pos^:=pos^+bitno;
bitno:=0;
end
else
begin
if ((8-bitno)>0) then
begin
index^:=index^+(((byte(bitstream^^) shl (pos^)) and $FF) shr (8-bitno));
pos^:=8;
end
else
begin
index^:=index^+((((byte(bitstream^^) shl (pos^)) and $FF)) shl (bitno-8));
pos^:=8;
end;
bitno:=bitno-BitsLeft;
end;
end;
end;
end.