def __init__(self, filename): """filename is a plain string""" WaveContainer.__init__(self, filename) self.__samplerate__ = 0 self.__channels__ = 0 self.__bitspersample__ = 0 self.__total_frames__ = 0 try: self.__read_info__() except IOError as msg: raise InvalidWavPack(str(msg))
def convert(self, target_path, target_class, compression=None, progress=None): """encodes a new AudioFile from existing AudioFile take a filename string, target class and optional compression string encodes a new AudioFile in the target class and returns the resulting object may raise EncodingError if some problem occurs during encoding""" # A Shorten file cannot contain both RIFF and AIFF chunks # at the same time. from audiotools import WaveAudio from audiotools import AiffAudio from audiotools import to_pcm_progress if ((self.has_foreign_wave_chunks() and hasattr(target_class, "from_wave") and callable(target_class.from_wave))): return WaveContainer.convert(self, target_path, target_class, compression, progress) elif (self.has_foreign_aiff_chunks() and hasattr(target_class, "from_aiff") and callable(target_class.from_aiff)): return AiffContainer.convert(self, target_path, target_class, compression, progress) else: return target_class.from_pcm(target_path, to_pcm_progress(self, progress), compression, total_pcm_frames=self.total_frames())
def __init__(self, filename): """filename is a plain string""" from audiotools import ChannelMask WaveContainer.__init__(self, filename) self.__channels__ = 0 self.__sample_rate__ = 0 self.__bits_per_sample__ = 0 self.__data_size__ = 0 self.__channel_mask__ = ChannelMask(0) from audiotools.bitstream import BitstreamReader fmt_read = data_read = False try: for chunk in self.chunks(): if (chunk.id == "fmt "): try: (self.__channels__, self.__sample_rate__, self.__bits_per_sample__, self.__channel_mask__) = parse_fmt( BitstreamReader(chunk.data(), 1)) fmt_read = True if (fmt_read and data_read): break except IOError: continue except ValueError as err: raise InvalidWave(str(err)) elif (chunk.id == "data"): self.__data_size__ = chunk.size() data_read = True if (fmt_read and data_read): break except IOError: # FIXME raise InvalidWave("I/O error reading wave")
def __init__(self, filename): """filename is a plain string""" from audiotools import ChannelMask WaveContainer.__init__(self, filename) self.__channels__ = 0 self.__sample_rate__ = 0 self.__bits_per_sample__ = 0 self.__data_size__ = 0 self.__channel_mask__ = ChannelMask(0) from audiotools.bitstream import BitstreamReader fmt_read = data_read = False try: for chunk in self.chunks(): if chunk.id == b"fmt ": try: (self.__channels__, self.__sample_rate__, self.__bits_per_sample__, self.__channel_mask__) = parse_fmt( BitstreamReader(chunk.data(), True)) fmt_read = True if fmt_read and data_read: break except IOError: continue except ValueError as err: raise InvalidWave(str(err)) elif chunk.id == b"data": self.__data_size__ = chunk.size() data_read = True if fmt_read and data_read: break except IOError: raise InvalidWave("I/O error reading wave")
def convert(self, target_path, target_class, compression=None, progress=None): """encodes a new AudioFile from existing AudioFile take a filename string, target class and optional compression string encodes a new AudioFile in the target class and returns the resulting object may raise EncodingError if some problem occurs during encoding""" #A Shorten file cannot contain both RIFF and AIFF chunks #at the same time. import tempfile from . import WaveAudio from . import AiffAudio from . import to_pcm_progress if ((self.has_foreign_wave_chunks() and hasattr(target_class, "from_wave") and callable(target_class.from_wave))): return WaveContainer.convert(self, target_path, target_class, compression, progress) elif (self.has_foreign_aiff_chunks() and hasattr(target_class, "from_aiff") and callable(target_class.from_aiff)): return AiffContainer.convert(self, target_path, target_class, compression, progress) else: return target_class.from_pcm( target_path, to_pcm_progress(self, progress), compression, total_pcm_frames=self.total_frames())
def __init__(self, filename): """filename is a plain string""" from audiotools.bitstream import BitstreamReader from audiotools import ChannelMask from io import BytesIO WaveContainer.__init__(self, filename) try: f = open(filename, 'rb') except IOError as msg: raise InvalidShorten(str(msg)) reader = BitstreamReader(f, 0) try: if (reader.parse("4b 8u") != ["ajkg", 2]): raise InvalidShorten("invalid Shorten header") except IOError: raise InvalidShorten("invalid Shorten header") def read_unsigned(r, c): MSB = r.unary(1) LSB = r.read(c) return MSB * 2 ** c + LSB def read_long(r): return read_unsigned(r, read_unsigned(r, 2)) # populate channels and bits_per_sample from Shorten header (file_type, self.__channels__, block_length, max_LPC, number_of_means, bytes_to_skip) = [read_long(reader) for i in range(6)] if ((1 <= file_type) and (file_type <= 2)): self.__bits_per_sample__ = 8 elif ((3 <= file_type) and (file_type <= 6)): self.__bits_per_sample__ = 16 else: # FIXME raise InvalidShorten("unsupported Shorten file type") # setup some default dummy metadata self.__sample_rate__ = 44100 if (self.__channels__ == 1): self.__channel_mask__ = ChannelMask(0x4) elif (self.__channels__ == 2): self.__channel_mask__ = ChannelMask(0x3) else: self.__channel_mask__ = ChannelMask(0) self.__total_frames__ = 0 # populate sample_rate and total_frames from first VERBATIM command command = read_unsigned(reader, 2) if (command == 9): verbatim_bytes = "".join([chr(read_unsigned(reader, 8) & 0xFF) for i in range(read_unsigned(reader, 5))]) try: wave = BitstreamReader(BytesIO(verbatim_bytes), 1) header = wave.read_bytes(12) if (header.startswith("RIFF") and header.endswith("WAVE")): # got RIFF/WAVE header, so parse wave blocks as needed total_size = len(verbatim_bytes) - 12 while (total_size >= 8): (chunk_id, chunk_size) = wave.parse("4b 32u") total_size -= 8 if (chunk_id == 'fmt '): from audiotools.wav import parse_fmt (channels, self.__sample_rate__, bits_per_sample, self.__channel_mask__) = parse_fmt( wave.substream(chunk_size)) elif (chunk_id == 'data'): self.__total_frames__ = \ (chunk_size // (self.__channels__ * (self.__bits_per_sample__ // 8))) else: if (chunk_size % 2): wave.read_bytes(chunk_size + 1) total_size -= (chunk_size + 1) else: wave.read_bytes(chunk_size) total_size -= chunk_size except (IOError, ValueError): pass try: aiff = BitstreamReader(BytesIO(verbatim_bytes), 0) header = aiff.read_bytes(12) if (header.startswith("FORM") and header.endswith("AIFF")): # got FORM/AIFF header, so parse aiff blocks as needed total_size = len(verbatim_bytes) - 12 while (total_size >= 8): (chunk_id, chunk_size) = aiff.parse("4b 32u") total_size -= 8 if (chunk_id == 'COMM'): from audiotools.aiff import parse_comm (channels, total_sample_frames, bits_per_sample, self.__sample_rate__, self.__channel_mask__) = parse_comm( aiff.substream(chunk_size)) elif (chunk_id == 'SSND'): # subtract 8 bytes for "offset" and "block size" self.__total_frames__ = \ ((chunk_size - 8) // (self.__channels__ * (self.__bits_per_sample__ // 8))) else: if (chunk_size % 2): aiff.read_bytes(chunk_size + 1) total_size -= (chunk_size + 1) else: aiff.read_bytes(chunk_size) total_size -= chunk_size except IOError: pass
def __init__(self, filename): """filename is a plain string""" from audiotools.bitstream import BitstreamReader from audiotools import ChannelMask from io import BytesIO WaveContainer.__init__(self, filename) try: f = open(filename, 'rb') except IOError as msg: raise InvalidShorten(str(msg)) reader = BitstreamReader(f, 0) try: if (reader.parse("4b 8u") != ["ajkg", 2]): raise InvalidShorten("invalid Shorten header") except IOError: raise InvalidShorten("invalid Shorten header") def read_unsigned(r, c): MSB = r.unary(1) LSB = r.read(c) return MSB * 2**c + LSB def read_long(r): return read_unsigned(r, read_unsigned(r, 2)) # populate channels and bits_per_sample from Shorten header (file_type, self.__channels__, block_length, max_LPC, number_of_means, bytes_to_skip) = [read_long(reader) for i in range(6)] if ((1 <= file_type) and (file_type <= 2)): self.__bits_per_sample__ = 8 elif ((3 <= file_type) and (file_type <= 6)): self.__bits_per_sample__ = 16 else: # FIXME raise InvalidShorten("unsupported Shorten file type") # setup some default dummy metadata self.__sample_rate__ = 44100 if (self.__channels__ == 1): self.__channel_mask__ = ChannelMask(0x4) elif (self.__channels__ == 2): self.__channel_mask__ = ChannelMask(0x3) else: self.__channel_mask__ = ChannelMask(0) self.__total_frames__ = 0 # populate sample_rate and total_frames from first VERBATIM command command = read_unsigned(reader, 2) if (command == 9): verbatim_bytes = "".join([ chr(read_unsigned(reader, 8) & 0xFF) for i in range(read_unsigned(reader, 5)) ]) try: wave = BitstreamReader(BytesIO(verbatim_bytes), 1) header = wave.read_bytes(12) if (header.startswith("RIFF") and header.endswith("WAVE")): # got RIFF/WAVE header, so parse wave blocks as needed total_size = len(verbatim_bytes) - 12 while (total_size >= 8): (chunk_id, chunk_size) = wave.parse("4b 32u") total_size -= 8 if (chunk_id == 'fmt '): from audiotools.wav import parse_fmt (channels, self.__sample_rate__, bits_per_sample, self.__channel_mask__) = parse_fmt( wave.substream(chunk_size)) elif (chunk_id == 'data'): self.__total_frames__ = \ (chunk_size // (self.__channels__ * (self.__bits_per_sample__ // 8))) else: if (chunk_size % 2): wave.read_bytes(chunk_size + 1) total_size -= (chunk_size + 1) else: wave.read_bytes(chunk_size) total_size -= chunk_size except (IOError, ValueError): pass try: aiff = BitstreamReader(BytesIO(verbatim_bytes), 0) header = aiff.read_bytes(12) if (header.startswith("FORM") and header.endswith("AIFF")): # got FORM/AIFF header, so parse aiff blocks as needed total_size = len(verbatim_bytes) - 12 while (total_size >= 8): (chunk_id, chunk_size) = aiff.parse("4b 32u") total_size -= 8 if (chunk_id == 'COMM'): from audiotools.aiff import parse_comm (channels, total_sample_frames, bits_per_sample, self.__sample_rate__, self.__channel_mask__) = parse_comm( aiff.substream(chunk_size)) elif (chunk_id == 'SSND'): # subtract 8 bytes for "offset" and "block size" self.__total_frames__ = \ ((chunk_size - 8) // (self.__channels__ * (self.__bits_per_sample__ // 8))) else: if (chunk_size % 2): aiff.read_bytes(chunk_size + 1) total_size -= (chunk_size + 1) else: aiff.read_bytes(chunk_size) total_size -= chunk_size except IOError: pass