size encoder_info (`mutagen.text`): encoder version """ channels = 0 length = 0 sample_rate = 0 bitrate = 0 encoder_info = "" @convert_error(IOError, TAKHeaderError) @convert_error(BitReaderError, TAKHeaderError) def __init__(self, fileobj): stream_id = fileobj.read(4) if len(stream_id) != 4 or not stream_id == b"tBaK": raise TAKHeaderError("not a TAK file") bitreader = _LSBBitReader(fileobj) found_stream_info = False while True: type = TAKMetadata(bitreader.bits(7)) bitreader.skip(1) # Unused size = struct.unpack(" 0: self.length = self.number_of_samples / float(self.sample_rate) def _parse_stream_info(self, bitreader, size): if size < STREAM_INFO_SIZE_MIN or size > STREAM_INFO_SIZE_MAX: raise TAKHeaderError("stream info has invalid length") # Encoder Info bitreader.skip(ENCODER_INFO_CODEC_BITS) bitreader.skip(ENCODER_INFO_PROFILE_BITS) # Size Info bitreader.skip(SIZE_INFO_FRAME_DURATION_BITS) self.number_of_samples = bitreader.bits(SIZE_INFO_SAMPLE_NUM_BITS) # Audio Format bitreader.skip(AUDIO_FORMAT_DATA_TYPE_BITS) self.sample_rate = (bitreader.bits(AUDIO_FORMAT_SAMPLE_RATE_BITS) + SAMPLE_RATE_MIN) self.bits_per_sample = (bitreader.bits(AUDIO_FORMAT_SAMPLE_BITS_BITS) + SAMPLE_BITS_MIN) self.channels = (bitreader.bits(AUDIO_FORMAT_CHANNEL_NUM_BITS) + CHANNEL_NUM_MIN) bitreader.skip(AUDIO_FORMAT_HAS_EXTENSION_BITS) def _parse_encoder_info(self, bitreader, size): patch = bitreader.bits(8) minor = bitreader.bits(8) major = bitreader.bits(8) self.encoder_info = "TAK %d.%d.%d" % (major, minor, patch) def pprint(self): return u"%s, %d Hz, %d bits, %.2f seconds, %d channel(s)" % ( self.encoder_info or "TAK", self.sample_rate, self.bits_per_sample, self.length, self.channels) class TAK(APEv2File): """TAK(filething) Arguments: filething (filething) Attributes: info (`TAKInfo`) """ _Info = TAKInfo _mimes = ["audio/x-tak"] @staticmethod def score(filename, fileobj, header): return header.startswith(b"tBaK") + endswith(filename.lower(), ".tak") Open = TAK