Source code for eyed3.utils.binfuncs

################################################################################
#  Copyright (C) 2001  Ryan Finne <ryan@finnie.org>
#  Copyright (C) 2002-2011  Travis Shirk <travis@pobox.com>
#
#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 2 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, see <http://www.gnu.org/licenses/>.
#
################################################################################
import struct

MAX_INT16 = (2 ** 16) // 2
MIN_INT16 = -(MAX_INT16 - 1)


[docs]def bytes2bin(bites, sz=8): """Accepts a string of ``bytes`` (chars) and returns an array of bits representing the bytes in big endian byte order. An optional max ``sz`` for each byte (default 8 bits/byte) which can be used to mask out higher bits.""" if sz < 1 or sz > 8: raise ValueError(f"Invalid sz value: {sz}") retval = [] for b in [bytes([b]) for b in bites]: bits = [] b = ord(b) while b > 0: bits.append(b & 1) b >>= 1 if len(bits) < sz: bits.extend([0] * (sz - len(bits))) elif len(bits) > sz: bits = bits[:sz] # Big endian byte order. bits.reverse() retval.extend(bits) return retval
[docs]def bin2bytes(x): """Convert an array of bits (MSB first) into a string of characters.""" bits = [] bits.extend(x) bits.reverse() i = 0 out = b'' multi = 1 ttl = 0 for b in bits: i += 1 ttl += b * multi multi *= 2 if i == 8: i = 0 out += bytes([ttl]) multi = 1 ttl = 0 if multi > 1: out += bytes([ttl]) out = bytearray(out) out.reverse() out = bytes(out) return out
[docs]def bin2dec(x): """Convert ``x``, an array of "bits" (MSB first), to it's decimal value.""" bits = [] bits.extend(x) bits.reverse() # MSB multi = 1 value = 0 for b in bits: value += b * multi multi *= 2 return value
[docs]def bytes2dec(bites, sz=8): return bin2dec(bytes2bin(bites, sz))
[docs]def dec2bin(n, p=1): """Convert a decimal value ``n`` to an array of bits (MSB first). Optionally, pad the overall size to ``p`` bits.""" assert n >= 0 if type(n) is not int: n = int(n) retval = [] while n > 0: retval.append(n & 1) n >>= 1 if p > 0: retval.extend([0] * (p - len(retval))) retval.reverse() return retval
[docs]def dec2bytes(n, p=1): return bin2bytes(dec2bin(n, p))
[docs]def bin2synchsafe(x): """Convert ``x``, a list of bits (MSB first), to a synch safe list of bits. (section 6.2 of the ID3 2.4 spec).""" n = bin2dec(x) if len(x) > 32 or n > 268435456: # 2^28 raise ValueError("Invalid value: %s" % str(x)) elif len(x) < 8: return x bites = bytes([(n >> 21) & 0x7f, (n >> 14) & 0x7f, (n >> 7) & 0x7f, (n >> 0) & 0x7f, ]) bits = bytes2bin(bites) assert(len(bits) == 32) return bits
[docs]def bytes2signedInt16(bites: bytes): if len(bites) != 2: raise ValueError("Signed 16 bit integer MUST be 2 bytes.") i = struct.unpack(">h", bites) return i[0]
[docs]def signedInt162bytes(n: int): n = int(n) if MIN_INT16 <= n <= MAX_INT16: return struct.pack(">h", n) raise ValueError(f"Signed int16 out of range: {n}")