Pack:
PUBLIC
PROC [dst: BitAddress, src:
LONG
POINTER
TO RawWords, bitsPerSample: BitsPerSample, nSamples:
CARDINAL] ~
UNCHECKED {
p: LONG POINTER TO ARRAY [0..0] OF WORD ¬ LOOPHOLE[dst.word];
h: WORD ¬ BITSHIFT[p[0], dst.bit-bpw];
g: [0..bpw] ¬ dst.bit; -- number of good bits at least-sig end of h
j: CARDINAL ¬ 0;
count: CARDINAL ¬ nSamples;
bps: [0..bpw) ~ bitsPerSample;
m: WORD ~ BITLSHIFT[1, bps]-1;
bitsPerSample2: CARDINAL ~ bitsPerSample+bitsPerSample;
bitsPerSample4: CARDINAL ~ bitsPerSample2+bitsPerSample2;
bitsPerSample8: CARDINAL ~ bitsPerSample4+bitsPerSample4;
Combine:
PROC [w:
WORD, s:
WORD]
RETURNS [
WORD] ~
INLINE {
RETURN [BITOR[BITLSHIFT[w, bps], BITAND[s, m]]]
};
WHILE count >= 8
DO
SELECT
CARDINAL[bpw-g]
FROM
>= bitsPerSample8 => {
h ¬ Combine[h, src[j]];
h ¬ Combine[h, src[j+1]];
h ¬ Combine[h, src[j+2]];
h ¬ Combine[h, src[j+3]];
h ¬ Combine[h, src[j+4]];
h ¬ Combine[h, src[j+5]];
h ¬ Combine[h, src[j+6]];
h ¬ Combine[h, src[j+7]];
count ¬ count - 8;
j ¬ j + 8;
g ¬ g + bitsPerSample8;
};
>= bitsPerSample4 => {
h ¬ Combine[h, src[j]];
h ¬ Combine[h, src[j+1]];
h ¬ Combine[h, src[j+2]];
h ¬ Combine[h, src[j+3]];
count ¬ count - 4;
j ¬ j + 4;
g ¬ g + bitsPerSample4;
};
>= bitsPerSample2 => {
h ¬ Combine[h, src[j]];
h ¬ Combine[h, src[j+1]];
count ¬ count - 2;
j ¬ j + 2;
g ¬ g + bitsPerSample2;
};
>= bps => {
h ¬ Combine[h, src[j]];
count ¬ count - 1;
j ¬ j + 1;
g ¬ g + bps;
};
ENDCASE => EXIT; -- Need to span a word, so drop through to the slower case below
IF g = bpw
THEN {
p[0] ¬ h;
p ¬ p + SIZE[WORD];
g ¬ 0;
};
ENDLOOP;
UNTIL j = nSamples
DO
SELECT bpw-g
FROM
>= bps => {
There is room for another whole sample in this output word
h ¬ Combine[h, src[j]];
g ¬ g + bps;
};
= 0 => {
The output word is full; store it and get the next sample
p[0] ¬ h;
p ¬ p + SIZE[WORD];
h ¬ src[j];
g ¬ bps;
};
ENDCASE => {
The sample goes partially in this word and partially in the next
k: WORD ~ BITAND[src[j], m];
p[0] ¬ BITLSHIFT[h, bpw-g] + BITRSHIFT[k, bps+g-bpw];
p ¬ p + SIZE[WORD];
h ¬ k;
g ¬ g + bps - bpw;
};
j ¬ j + 1;
ENDLOOP;
IF g # 0
THEN {
p[0] ¬ BITLSHIFT[h, bpw-g]+BITAND[p[0], BITLSHIFT[1, bpw-g]-1];
};
};
Unpack:
PUBLIC
PROC [dst:
LONG
POINTER
TO RawWords, src: BitAddress, bitsPerSample: BitsPerSample, nSamples:
CARDINAL] ~
UNCHECKED {
SELECT
TRUE
FROM
(nSamples = 0) => NULL;
(bitsPerSample = 1) => {
wordPointer: LONG POINTER TO WORD ¬ @(dst[0]);
srcp: LONG POINTER TO WORD ¬ src.word;
bit: CARDINAL ¬ src.bit;
word: WORD ¬ 0;
count: CARDINAL ¬ nSamples;
IF bit#0
THEN {
word ¬ BITLSHIFT[srcp, bit];
srcp ¬ srcp + SIZE[WORD];
WHILE count#0
AND bit#bpw
DO
Assert[word = BITSHIFT[(srcp-SIZE[WORD])^, bit]];
wordPointer ¬ BITRSHIFT[word, bpw-1];
count ¬ count-1;
bit ¬ bit+1;
word ¬ 2*word;
wordPointer ¬ wordPointer + SIZE[WORD];
ENDLOOP;
};
bit ¬ bpw;
WHILE count>=32
DO
a: LONG POINTER TO ARRAY [0..32) OF WORD ~ LOOPHOLE[wordPointer];
lp: LONG POINTER TO PACKED ARRAY [0..32) OF [0..1] ~ LOOPHOLE[srcp];
b: PACKED ARRAY [0..32) OF [0..1] ~ lp;
a[0] ¬ b[0]; a[1] ¬ b[1]; a[2] ¬ b[2]; a[3] ¬ b[3];
a[4] ¬ b[4]; a[5] ¬ b[5]; a[6] ¬ b[6]; a[7] ¬ b[7];
a[8] ¬ b[8]; a[9] ¬ b[9]; a[10] ¬ b[10]; a[11] ¬ b[11];
a[12] ¬ b[12]; a[13] ¬ b[13]; a[14] ¬ b[14]; a[15] ¬ b[15];
a[16] ¬ b[16]; a[17] ¬ b[17]; a[18] ¬ b[18]; a[19] ¬ b[19];
a[20] ¬ b[20]; a[21] ¬ b[21]; a[22] ¬ b[22]; a[23] ¬ b[23];
a[24] ¬ b[24]; a[25] ¬ b[25]; a[26] ¬ b[26]; a[27] ¬ b[27];
a[28] ¬ b[28]; a[29] ¬ b[29]; a[30] ¬ b[30]; a[31] ¬ b[31];
wordPointer ¬ wordPointer + SIZE[ARRAY [0..32) OF WORD];
count ¬ count - 32;
srcp ¬ srcp + SIZE[PACKED ARRAY [0..32) OF [0..1]];
ENDLOOP;
WHILE count#0
DO
Assert[word = BITSHIFT[(srcp-SIZE[WORD])^, bit]];
IF bit = bpw THEN {bit ¬ 0; word ¬ srcp; srcp ¬ srcp + SIZE[WORD]};
Assert[word = BITSHIFT[(srcp-SIZE[WORD])^, bit]];
wordPointer ¬ BITRSHIFT[word, bpw-1];
count ¬ count-1;
word ¬ 2*word;
wordPointer ¬ wordPointer + SIZE[WORD];
bit ¬ bit+1;
ENDLOOP;
};
((bitsPerSample = 8)
AND ((src.bit
MOD 8) = 0)) => {
wordPointer: LONG POINTER TO WORD ¬ @(dst[0]);
chunksize: CARDINAL ~ 8; -- to change this, also change assignments in the unrolled loop below. Must be a multiple of BYTES[WORD].
srcp: LONG POINTER TO PACKED ARRAY [0..chunksize) OF BYTE ¬ LOOPHOLE[src.word];
byte: CARDINAL ¬ src.bit/8;
count: CARDINAL ¬ nSamples;
IF byte#0
THEN {
WHILE count#0
AND byte#chunksize
DO
wordPointer ¬ srcp[byte];
wordPointer ¬ wordPointer + SIZE[WORD];
byte ¬ byte + 1;
count ¬ count-1;
ENDLOOP;
srcp ¬ srcp + SIZE[PACKED ARRAY [0..chunksize) OF BYTE];
byte ¬ 0;
};
WHILE count>=chunksize
DO
a: LONG POINTER TO ARRAY [0..chunksize) OF WORD ~ LOOPHOLE[wordPointer];
b: PACKED ARRAY [0..chunksize) OF BYTE ~ srcp;
a[0] ¬ b[0]; a[1] ¬ b[1]; a[2] ¬ b[2]; a[3] ¬ b[3];
a[4] ¬ b[4]; a[5] ¬ b[5]; a[6] ¬ b[6]; a[7] ¬ b[7];
wordPointer ¬ wordPointer + SIZE[ARRAY [0..chunksize) OF WORD];
count ¬ count - chunksize;
srcp ¬ srcp + SIZE[PACKED ARRAY [0..chunksize) OF BYTE];
ENDLOOP;
WHILE count#0
DO
wordPointer ¬ srcp[byte];
wordPointer ¬ wordPointer + SIZE[WORD];
byte ¬ byte + 1;
count ¬ count-1;
ENDLOOP;
};
ENDCASE => {
m: WORD ~ BITLSHIFT[1, bitsPerSample]-1;
p: LONG POINTER TO ARRAY [0..1] OF WORD ¬ LOOPHOLE[src.word];
h: WORD ¬ p[0];
g: INTEGER ¬ bpw-src.bit; -- number of good bits at least-sig end of h
FOR j:
CARDINAL
IN [0..nSamples)
DO
SELECT g
FROM
>= bitsPerSample => {
The whole sample is in this word
dst[j] ¬ BITAND[m, BITRSHIFT[h, g-bitsPerSample]];
g ¬ g - bitsPerSample;
};
0 => {
The word is totally exhausted; pull the next one
p ¬ p + SIZE[WORD];
h ¬ p[0];
dst[j] ¬ BITAND[m, BITRSHIFT[h, bpw-bitsPerSample]];
g ¬ bpw - bitsPerSample;
};
ENDCASE => {
The sample is partially in this word and partially in the next
k: WORD ~ p[1];
dst[j] ¬ BITAND[m, BITOR[BITLSHIFT[h, bitsPerSample-g], BITRSHIFT[k, g+bpw-bitsPerSample]]];
h ¬ k;
p ¬ p + SIZE[WORD];
g ¬ g + bpw - bitsPerSample;
};
ENDLOOP;
};
};