repack ubyte[] to use only 7 bits
Manolo via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Sat Dec 13 03:20:20 PST 2014
On Saturday, 13 December 2014 at 10:09:27 UTC, Charles Hixson via
Digitalmars-d-learn wrote:
> Is there a standard way to do this? The code below is
> untested, as I haven't yet written the x7to8 routine, and came
> up with a better way to do what this was to accomplish, but it
> feels as if this should be somewhere in the standard library,
> if I could only find it.
>
> /** Repack the data from an array of ubytes into an array of
> ubytes of
> * which only the last 7 are significant. The high bit will be
> set only
> * if the byte would otherwise be zero. */
> byte[] x8to7 (ubyte[] bin)
> {
> ubyte[] bout;
> // bit masks: 0 => 0xfe = 11111110, 0x00 = 00000000
> // 1 => 0x7f = 01111111, 0x00 = 00000000
> // 2 => 0x3f = 00111111, 0x80 = 10000000
> // 3 => 0x1f = 00011111, 0xc0 = 11000000
> // 4 => 0x0f = 00001111, 0xe0 = 11100000
> // 5 => 0x07 = 00000111, 0xf0 = 11110000
> // 6 => 0x03 = 00000011, 0xf8 = 11111000
> // 7 => 0x01 = 00000001, 0xfc = 11111100
> if (bin.length < 1) return bout;
> int fByte, fBit;
> while (fByte < bin.length)
> { if (fByte + 1 == bin.length && fBit > 1) break;
> ubyte b;
> switch (fBit)
> { case 0:
> b = bin[fByte] / 2;
> break;
> case 1:
> b = bin[fByte] & 0x7f;
> break;
> case 2:
> ubyte b1 = (bin[fByte] & 0x3f) << 1;
> ubyte b2 = (bin[fByte + 1] & 0x80) >>>
> 7;
> b ~= (b1 | b2);
> break;
> case 3:
> ubyte b1 = (bin[fByte] & 0x1f) << 2;
> ubyte b2 = (bin[fByte + 1] & 0xc0) >>>
> 6;
> b ~= (b1 | b2);
> break;
> case 4:
> ubyte b1 = (bin[fByte] & 0x0f) << 3;
> ubyte b2 = (bin[fByte + 1] & 0xe0) >>>
> 5;
> b ~= (b1 | b2);
> break;
> case 5:
> ubyte b1 = (bin[fByte] & 0x07) << 4;
> ubyte b2 = (bin[fByte + 1] & 0xf0) >>>
> 4;
> b ~= (b1 | b2);
> break;
> case 6:
> ubyte b1 = (bin[fByte] & 0x03) << 5;
> ubyte b2 = (bin[fByte + 1] & 0xf8) >>>
> 3;
> b ~= (b1 | b2);
> break;
> case 7:
> ubyte b1 = (bin[fByte] & 0x01) << 6;
> ubyte b2 = (bin[fByte + 1] & 0xfc) >>>
> 2;
> b ~= (b1 | b2);
> break;
> default:
> assert (false, "This path should never be
> taken");
> } // switch (fBit)
> if (b == 0) bout ~= 0x80;
> else bout ~= b;
> fBit = fBit + 7;
> if (fBit > 7)
> { fByte++;
> fBit -= 7;
> }
> }
> }
Are you trying to make a "kind-of" Variable-Length quantity
encoder ?
eg:
0b10101110: last bit not set, integrate 0b10101110 and stop
reading.
0b10011001: last bit set, integrate 0b10011000 and continue to
next byte.
http://en.wikipedia.org/wiki/Variable-length_quantity
except that this algo limits the length to 24 bits. It was used a
lot with
MIDI, at a time when hardware memory was costly (eg inside
hardware synthesizer or workstations).
More information about the Digitalmars-d-learn
mailing list