def channel_mask(self): """Returns a ChannelMask object of this track's channel layout.""" #this unusual arrangement is taken from the AIFF specification if (self.channels() <= 2): return ChannelMask.from_channels(self.channels()) elif (self.channels() == 3): return ChannelMask.from_fields( front_left=True, front_right=True, front_center=True) elif (self.channels() == 4): return ChannelMask.from_fields( front_left=True, front_right=True, back_left=True, back_right=True) elif (self.channels() == 6): return ChannelMask.from_fields( front_left=True, side_left=True, front_center=True, front_right=True, side_right=True, back_center=True) else: return ChannelMask(0)
def channel_mask(self): """Returns a ChannelMask object of this track's channel layout.""" # M4A seems to use the same channel assignment # as old-style RIFF WAVE/FLAC if self.channels() == 1: return ChannelMask.from_fields(front_center=True) elif self.channels() == 2: return ChannelMask.from_fields(front_left=True, front_right=True) elif self.channels() == 3: return ChannelMask.from_fields(front_left=True, front_right=True, front_center=True) elif self.channels() == 4: return ChannelMask.from_fields(front_left=True, front_right=True, back_left=True, back_right=True) elif self.channels() == 5: return ChannelMask.from_fields( front_left=True, front_right=True, front_center=True, back_left=True, back_right=True ) elif self.channels() == 6: return ChannelMask.from_fields( front_left=True, front_right=True, front_center=True, back_left=True, back_right=True, low_frequency=True, ) else: return ChannelMask(0)
def channel_mask(self): """returns a ChannelMask object of this track's channel layout""" from audiotools import ChannelMask # M4A seems to use the same channel assignment # as old-style RIFF WAVE/FLAC if self.channels() == 1: return ChannelMask.from_fields(front_center=True) elif self.channels() == 2: return ChannelMask.from_fields(front_left=True, front_right=True) elif self.channels() == 3: return ChannelMask.from_fields(front_left=True, front_right=True, front_center=True) elif self.channels() == 4: return ChannelMask.from_fields(front_left=True, front_right=True, back_left=True, back_right=True) elif self.channels() == 5: return ChannelMask.from_fields(front_left=True, front_right=True, front_center=True, back_left=True, back_right=True) elif self.channels() == 6: return ChannelMask.from_fields(front_left=True, front_right=True, front_center=True, back_left=True, back_right=True, low_frequency=True) else: return ChannelMask(0)
def channel_mask(self): #this unusual arrangement is taken from the AIFF specification if (self.channels() <= 2): return ChannelMask.from_channels(self.channels()) elif (self.channels() == 3): return ChannelMask.from_fields(front_left=True, front_right=True, front_center=True) elif (self.channels() == 4): return ChannelMask.from_fields(front_left=True, front_right=True, back_left=True, back_right=True) elif (self.channels() == 6): return ChannelMask.from_fields(front_left=True, side_left=True, front_center=True, front_right=True, side_right=True, back_center=True) else: return ChannelMask(0)
def channel_mask(self): """returns a ChannelMask object of this track's channel layout""" if self.channels() == 1: return ChannelMask.from_fields(front_center=True) elif self.channels() == 2: return ChannelMask.from_fields(front_left=True, front_right=True) elif self.channels() == 3: return ChannelMask.from_fields(front_left=True, front_right=True, front_center=True) elif self.channels() == 4: return ChannelMask.from_fields(front_left=True, front_right=True, back_left=True, back_right=True) elif self.channels() == 5: return ChannelMask.from_fields(front_left=True, front_right=True, front_center=True, back_left=True, back_right=True) elif self.channels() == 6: return ChannelMask.from_fields(front_left=True, front_right=True, front_center=True, back_left=True, back_right=True, low_frequency=True) elif self.channels() == 7: return ChannelMask.from_fields(front_left=True, front_right=True, front_center=True, side_left=True, side_right=True, back_center=True, low_frequency=True) elif self.channels() == 8: return ChannelMask.from_fields(front_left=True, front_right=True, side_left=True, side_right=True, back_left=True, back_right=True, front_center=True, low_frequency=True) else: return ChannelMask(0)
def channel_mask(self): """Returns a ChannelMask object of this track's channel layout.""" if (self.channels() == 1): return ChannelMask.from_fields(front_center=True) elif (self.channels() == 2): return ChannelMask.from_fields(front_left=True, front_right=True) elif (self.channels() == 3): return ChannelMask.from_fields(front_left=True, front_right=True, front_center=True) elif (self.channels() == 4): return ChannelMask.from_fields(front_left=True, front_right=True, back_left=True, back_right=True) elif (self.channels() == 5): return ChannelMask.from_fields(front_left=True, front_right=True, front_center=True, back_left=True, back_right=True) elif (self.channels() == 6): return ChannelMask.from_fields(front_left=True, front_right=True, front_center=True, back_left=True, back_right=True, low_frequency=True) elif (self.channels() == 7): return ChannelMask.from_fields(front_left=True, front_right=True, front_center=True, side_left=True, side_right=True, back_center=True, low_frequency=True) elif (self.channels() == 8): return ChannelMask.from_fields(front_left=True, front_right=True, side_left=True, side_right=True, back_left=True, back_right=True, front_center=True, low_frequency=True) else: return ChannelMask(0)
def channel_mask(self): """returns a ChannelMask object of this track's channel layout""" if self.channels() == 1: return ChannelMask.from_fields(front_center=True) elif self.channels() == 2: return ChannelMask.from_fields(front_left=True, front_right=True) elif self.channels() == 3: return ChannelMask.from_fields(front_left=True, front_right=True, front_center=True) elif self.channels() == 4: return ChannelMask.from_fields(front_left=True, front_right=True, back_left=True, back_right=True) elif self.channels() == 5: return ChannelMask.from_fields( front_left=True, front_right=True, front_center=True, back_left=True, back_right=True ) elif self.channels() == 6: return ChannelMask.from_fields( front_left=True, front_right=True, front_center=True, back_left=True, back_right=True, low_frequency=True, ) elif self.channels() == 7: return ChannelMask.from_fields( front_left=True, front_right=True, front_center=True, side_left=True, side_right=True, back_center=True, low_frequency=True, ) elif self.channels() == 8: return ChannelMask.from_fields( front_left=True, front_right=True, side_left=True, side_right=True, back_left=True, back_right=True, front_center=True, low_frequency=True, ) else: return ChannelMask(0)
def channel_mask(self): if (self.channels() == 1): return ChannelMask.from_fields(front_center=True) elif (self.channels() == 2): return ChannelMask.from_fields(front_left=True, front_right=True) elif (self.channels() == 3): return ChannelMask.from_fields(front_left=True, front_right=True, front_center=True) elif (self.channels() == 4): return ChannelMask.from_fields(front_left=True, front_right=True, back_left=True, back_right=True) elif (self.channels() == 5): return ChannelMask.from_fields(front_left=True, front_right=True, front_center=True, back_left=True, back_right=True) elif (self.channels() == 6): return ChannelMask.from_fields(front_left=True, front_right=True, front_center=True, back_left=True, back_right=True, low_frequency=True) elif (self.channels() == 7): return ChannelMask.from_fields(front_left=True, front_right=True, front_center=True, side_left=True, side_right=True, back_center=True, low_frequency=True) elif (self.channels() == 8): return ChannelMask.from_fields(front_left=True, front_right=True, side_left=True, side_right=True, back_left=True, back_right=True, front_center=True, low_frequency=True) else: return ChannelMask(0)
def channel_mask(self): """Returns a ChannelMask object of this track's channel layout.""" if (self.channels() == 1): return ChannelMask.from_fields( front_center=True) elif (self.channels() == 2): return ChannelMask.from_fields( front_left=True, front_right=True) elif (self.channels() == 3): return ChannelMask.from_fields( front_left=True, front_right=True, front_center=True) elif (self.channels() == 4): return ChannelMask.from_fields( front_left=True, front_right=True, back_left=True, back_right=True) elif (self.channels() == 5): return ChannelMask.from_fields( front_left=True, front_right=True, front_center=True, back_left=True, back_right=True) elif (self.channels() == 6): return ChannelMask.from_fields( front_left=True, front_right=True, front_center=True, back_left=True, back_right=True, low_frequency=True) elif (self.channels() == 7): return ChannelMask.from_fields( front_left=True, front_right=True, front_center=True, side_left=True, side_right=True, back_center=True, low_frequency=True) elif (self.channels() == 8): return ChannelMask.from_fields( front_left=True, front_right=True, side_left=True, side_right=True, back_left=True, back_right=True, front_center=True, low_frequency=True) else: return ChannelMask(0)
def channel_mask(self): """Returns a ChannelMask object of this track's channel layout.""" return { 1: ChannelMask.from_fields(front_center=True), 2: ChannelMask.from_fields(front_left=True, front_right=True), 3: ChannelMask.from_fields(front_center=True, front_left=True, front_right=True), 4: ChannelMask.from_fields(front_center=True, front_left=True, front_right=True, back_center=True), 5: ChannelMask.from_fields( front_center=True, front_left=True, front_right=True, back_left=True, back_right=True ), 6: ChannelMask.from_fields( front_center=True, front_left=True, front_right=True, back_left=True, back_right=True, low_frequency=True, ), 7: ChannelMask.from_fields( front_center=True, front_left=True, front_right=True, back_left=True, back_right=True, back_center=True, low_frequency=True, ), 8: ChannelMask.from_fields( front_center=True, front_left_of_center=True, front_right_of_center=True, front_left=True, front_right=True, back_left=True, back_right=True, low_frequency=True, ), }.get(self.channels(), ChannelMask(0))
def channel_mask(self): fmt_chunk = WaveAudio.FMT_CHUNK.parse(self.__fmt_chunk__()) if (fmt_chunk.compression != 0xFFFE): if (self.__channels__ == 1): return ChannelMask.from_fields(front_center=True) elif (self.__channels__ == 2): return ChannelMask.from_fields(front_left=True, front_right=True) #if we have a multi-channel WavPack file #that's not WAVEFORMATEXTENSIBLE, #assume the channels follow SMPTE/ITU-R recommendations #and hope for the best elif (self.__channels__ == 3): return ChannelMask.from_fields(front_left=True, front_right=True, front_center=True) elif (self.__channels__ == 4): return ChannelMask.from_fields(front_left=True, front_right=True, back_left=True, back_right=True) elif (self.__channels__ == 5): return ChannelMask.from_fields(front_left=True, front_right=True, back_left=True, back_right=True, front_center=True) elif (self.__channels__ == 6): return ChannelMask.from_fields(front_left=True, front_right=True, back_left=True, back_right=True, front_center=True, low_frequency=True) else: return ChannelMask(0) else: return WaveAudio.fmt_chunk_to_channel_mask(fmt_chunk.channel_mask)
def __read_info__(self): from audiotools.bitstream import BitstreamReader from audiotools import ChannelMask reader = BitstreamReader(open(self.filename, "rb"), 1) reader.mark() try: (block_id, total_samples, bits_per_sample, mono_output, initial_block, final_block, sample_rate) = reader.parse( "4b 64p 32u 64p 2u 1u 8p 1u 1u 5p 5p 4u 37p") if (block_id != b"wvpk"): from audiotools.text import ERR_WAVPACK_INVALID_HEADER raise InvalidWavPack(ERR_WAVPACK_INVALID_HEADER) if (sample_rate != 0xF): self.__samplerate__ = WavPackAudio.SAMPLING_RATE[sample_rate] else: # if unknown, pull from SAMPLE_RATE sub-block for (block_id, nondecoder, data_size, data) in self.sub_blocks(reader): if ((block_id == 0x7) and nondecoder): self.__samplerate__ = data.read(data_size * 8) break else: # no SAMPLE RATE sub-block found # so pull info from FMT chunk reader.rewind() (self.__samplerate__,) = self.fmt_chunk(reader).parse( "32p 32u") self.__bitspersample__ = [8, 16, 24, 32][bits_per_sample] self.__total_frames__ = total_samples if (initial_block and final_block): if (mono_output): self.__channels__ = 1 self.__channel_mask__ = ChannelMask(0x4) else: self.__channels__ = 2 self.__channel_mask__ = ChannelMask(0x3) else: # if not mono or stereo, pull from CHANNEL INFO sub-block reader.rewind() for (block_id, nondecoder, data_size, data) in self.sub_blocks(reader): if ((block_id == 0xD) and not nondecoder): self.__channels__ = data.read(8) self.__channel_mask__ = ChannelMask( data.read((data_size - 1) * 8)) break else: # no CHANNEL INFO sub-block found # so pull info from FMT chunk reader.rewind() fmt = self.fmt_chunk(reader) compression_code = fmt.read(16) self.__channels__ = fmt.read(16) if (compression_code == 1): # this is theoretically possible # with very old .wav files, # but shouldn't happen in practice self.__channel_mask__ = \ {1: ChannelMask.from_fields(front_center=True), 2: ChannelMask.from_fields(front_left=True, front_right=True), 3: ChannelMask.from_fields(front_left=True, front_right=True, front_center=True), 4: ChannelMask.from_fields(front_left=True, front_right=True, back_left=True, back_right=True), 5: ChannelMask.from_fields(front_left=True, front_right=True, back_left=True, back_right=True, front_center=True), 6: ChannelMask.from_fields(front_left=True, front_right=True, back_left=True, back_right=True, front_center=True, low_frequency=True) }.get(self.__channels__, ChannelMask(0)) elif (compression_code == 0xFFFE): fmt.skip(128) mask = fmt.read(32) self.__channel_mask__ = ChannelMask(mask) else: from audiotools.text import ERR_WAVPACK_UNSUPPORTED_FMT raise InvalidWavPack(ERR_WAVPACK_UNSUPPORTED_FMT) finally: reader.unmark() reader.close()
def __read_info__(self): from audiotools.bitstream import BitstreamReader from audiotools import ChannelMask reader = BitstreamReader(open(self.filename, "rb"), 1) reader.mark() try: (block_id, total_samples, bits_per_sample, mono_output, initial_block, final_block, sample_rate) = reader.parse( "4b 64p 32u 64p 2u 1u 8p 1u 1u 5p 5p 4u 37p") if (block_id != 'wvpk'): from audiotools.text import ERR_WAVPACK_INVALID_HEADER raise InvalidWavPack(ERR_WAVPACK_INVALID_HEADER) if (sample_rate != 0xF): self.__samplerate__ = WavPackAudio.SAMPLING_RATE[sample_rate] else: # if unknown, pull from SAMPLE_RATE sub-block for (block_id, nondecoder, data_size, data) in self.sub_blocks(reader): if ((block_id == 0x7) and nondecoder): self.__samplerate__ = data.read(data_size * 8) break else: # no SAMPLE RATE sub-block found # so pull info from FMT chunk reader.rewind() (self.__samplerate__,) = self.fmt_chunk(reader).parse( "32p 32u") self.__bitspersample__ = [8, 16, 24, 32][bits_per_sample] self.__total_frames__ = total_samples if (initial_block and final_block): if (mono_output): self.__channels__ = 1 self.__channel_mask__ = ChannelMask(0x4) else: self.__channels__ = 2 self.__channel_mask__ = ChannelMask(0x3) else: # if not mono or stereo, pull from CHANNEL INFO sub-block reader.rewind() for (block_id, nondecoder, data_size, data) in self.sub_blocks(reader): if ((block_id == 0xD) and not nondecoder): self.__channels__ = data.read(8) self.__channel_mask__ = ChannelMask( data.read((data_size - 1) * 8)) break else: # no CHANNEL INFO sub-block found # so pull info from FMT chunk reader.rewind() fmt = self.fmt_chunk(reader) compression_code = fmt.read(16) self.__channels__ = fmt.read(16) if (compression_code == 1): # this is theoretically possible # with very old .wav files, # but shouldn't happen in practice self.__channel_mask__ = \ {1: ChannelMask.from_fields(front_center=True), 2: ChannelMask.from_fields(front_left=True, front_right=True), 3: ChannelMask.from_fields(front_left=True, front_right=True, front_center=True), 4: ChannelMask.from_fields(front_left=True, front_right=True, back_left=True, back_right=True), 5: ChannelMask.from_fields(front_left=True, front_right=True, back_left=True, back_right=True, front_center=True), 6: ChannelMask.from_fields(front_left=True, front_right=True, back_left=True, back_right=True, front_center=True, low_frequency=True) }.get(self.__channels__, ChannelMask(0)) elif (compression_code == 0xFFFE): fmt.skip(128) mask = fmt.read(32) self.__channel_mask__ = ChannelMask(mask) else: from audiotools.text import ERR_WAVPACK_UNSUPPORTED_FMT raise InvalidWavPack(ERR_WAVPACK_UNSUPPORTED_FMT) finally: reader.unmark() reader.close()
def parse_fmt(fmt): """given a fmt block BitstreamReader (without the 8 byte header) returns (channels, sample_rate, bits_per_sample, channel_mask) where channel_mask is a ChannelMask object and the rest are ints may raise ValueError if the fmt chunk is invalid or IOError if an error occurs parsing the chunk""" from audiotools import ChannelMask (compression, channels, sample_rate, bytes_per_second, block_align, bits_per_sample) = fmt.parse("16u 16u 32u 32u 16u 16u") if compression == 1: # if we have a multi-channel WAVE file # that's not WAVEFORMATEXTENSIBLE, # assume the channels follow # SMPTE/ITU-R recommendations # and hope for the best if channels == 1: channel_mask = ChannelMask.from_fields( front_center=True) elif channels == 2: channel_mask = ChannelMask.from_fields( front_left=True, front_right=True) elif channels == 3: channel_mask = ChannelMask.from_fields( front_left=True, front_right=True, front_center=True) elif channels == 4: channel_mask = ChannelMask.from_fields( front_left=True, front_right=True, back_left=True, back_right=True) elif channels == 5: channel_mask = ChannelMask.from_fields( front_left=True, front_right=True, back_left=True, back_right=True, front_center=True) elif channels == 6: channel_mask = ChannelMask.from_fields( front_left=True, front_right=True, back_left=True, back_right=True, front_center=True, low_frequency=True) else: channel_mask = ChannelMask(0) return (channels, sample_rate, bits_per_sample, channel_mask) elif compression == 0xFFFE: (cb_size, valid_bits_per_sample, channel_mask, sub_format) = fmt.parse("16u 16u 32u 16b") if (sub_format != (b'\x01\x00\x00\x00\x00\x00\x10\x00' + b'\x80\x00\x00\xaa\x00\x38\x9b\x71')): # FIXME raise ValueError("invalid WAVE sub-format") else: channel_mask = ChannelMask(channel_mask) return (channels, sample_rate, bits_per_sample, channel_mask) else: # FIXME raise ValueError("unsupported WAVE compression")