68 lines
1.7 KiB
Python
68 lines
1.7 KiB
Python
"""LSB-first bit reader/writer (Vorbis bit packing order)."""
|
|
|
|
|
|
class BitReader:
|
|
def __init__(self, data: bytes, bitpos: int = 0):
|
|
self.data = data
|
|
self.pos = bitpos
|
|
|
|
def get(self, n: int) -> int:
|
|
v = 0
|
|
for i in range(n):
|
|
byte = self.data[(self.pos >> 3)] if (self.pos >> 3) < len(self.data) else 0
|
|
v |= ((byte >> (self.pos & 7)) & 1) << i
|
|
self.pos += 1
|
|
return v
|
|
|
|
def bits_left(self) -> int:
|
|
return len(self.data) * 8 - self.pos
|
|
|
|
|
|
class BitWriter:
|
|
def __init__(self):
|
|
self.buf = bytearray()
|
|
self.pos = 0
|
|
|
|
def put(self, n: int, v: int):
|
|
for i in range(n):
|
|
if (self.pos >> 3) >= len(self.buf):
|
|
self.buf.append(0)
|
|
if (v >> i) & 1:
|
|
self.buf[self.pos >> 3] |= 1 << (self.pos & 7)
|
|
self.pos += 1
|
|
|
|
def put_bits_from(self, r: BitReader, n: int):
|
|
"""Copy n bits from a reader (fast path in 32-bit chunks)."""
|
|
while n > 0:
|
|
k = 32 if n >= 32 else n
|
|
self.put(k, r.get(k))
|
|
n -= k
|
|
|
|
def bytes(self) -> bytes:
|
|
return bytes(self.buf)
|
|
|
|
|
|
def ilog(v: int) -> int:
|
|
r = 0
|
|
while v:
|
|
r += 1
|
|
v >>= 1
|
|
return r
|
|
|
|
|
|
def book_maptype1_quantvals(entries: int, dims: int) -> int:
|
|
bits = ilog(entries)
|
|
vals = entries >> ((bits - 1) * (dims - 1) // dims)
|
|
while True:
|
|
acc = 1
|
|
acc1 = 1
|
|
for _ in range(dims):
|
|
acc *= vals
|
|
acc1 *= vals + 1
|
|
if acc <= entries < acc1:
|
|
return vals
|
|
if acc > entries:
|
|
vals -= 1
|
|
else:
|
|
vals += 1
|