Пример #1
0
    def from_wave(cls, filename, wave_filename, compression=None,
                  progress=None):
        """Encodes a new AudioFile from an existing .wav file.

        Takes a filename string, wave_filename string
        of an existing WaveAudio file
        and an optional compression level string.
        Encodes a new audio file from the wave's data
        at the given filename with the specified compression level
        and returns a new WavPackAudio object."""

        from . import encoders

        if ((compression is None) or
            (compression not in cls.COMPRESSION_MODES)):
            compression = __default_quality__(cls.NAME)

        wave = WaveAudio(wave_filename)

        (head, tail) = wave.pcm_split()

        try:
            encoders.encode_wavpack(filename,
                                    to_pcm_progress(wave, progress),
                                    wave_header=head,
                                    wave_footer=tail,
                                    **cls.__options__[compression])

            return cls(filename)
        except (ValueError, IOError), msg:
            cls.__unlink__(filename)
            raise EncodingError(str(msg))
Пример #2
0
    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())
Пример #3
0
    def from_aiff(cls, filename, aiff_filename, compression=None, block_size=256, progress=None):
        """encodes a new AudioFile from an existing .aiff file

        takes a filename string, aiff_filename string
        of an existing WaveAudio file
        and an optional compression level string
        encodes a new audio file from the aiff's data
        at the given filename with the specified compression level
        and returns a new ShortenAudio object"""

        aiff = AiffAudio(aiff_filename)

        if aiff.bits_per_sample() not in (8, 16):
            raise UnsupportedBitsPerSample(filename, aiff.bits_per_sample())

        (head, tail) = aiff.pcm_split()

        from .encoders import encode_shn

        try:
            if len(tail) == 0:
                encode_shn(
                    filename=filename,
                    pcmreader=to_pcm_progress(aiff, progress),
                    is_big_endian=True,
                    signed_samples=True,
                    header_data=head,
                    block_size=block_size,
                )
            else:
                encode_shn(
                    filename=filename,
                    pcmreader=to_pcm_progress(aiff, progress),
                    is_big_endian=True,
                    signed_samples=True,
                    header_data=head,
                    footer_data=tail,
                    block_size=block_size,
                )

            return cls(filename)
        except IOError, err:
            cls.__unlink__(filename)
            raise EncodingError(str(err))
Пример #4
0
    def from_wave(cls, filename, wave_filename, compression=None,
                  block_size=256, progress=None):
        """Encodes a new AudioFile from an existing .wav file.

        Takes a filename string, wave_filename string
        of an existing WaveAudio file
        and an optional compression level string.
        Encodes a new audio file from the wave's data
        at the given filename with the specified compression level
        and returns a new ShortenAudio object."""

        wave = WaveAudio(wave_filename)

        if (wave.bits_per_sample() not in (8, 16)):
            raise UnsupportedBitsPerSample(filename, wave.bits_per_sample())

        (head, tail) = wave.pcm_split()

        from .encoders import encode_shn

        try:
            if (len(tail) == 0):
                encode_shn(filename=filename,
                           pcmreader=to_pcm_progress(wave, progress),
                           is_big_endian=False,
                           signed_samples=wave.bits_per_sample() == 16,
                           header_data=head,
                           block_size=block_size)
            else:
                encode_shn(filename=filename,
                           pcmreader=to_pcm_progress(wave, progress),
                           is_big_endian=False,
                           signed_samples=wave.bits_per_sample() == 16,
                           header_data=head,
                           footer_data=tail,
                           block_size=block_size)

            return cls(filename)
        except IOError, err:
            cls.__unlink__(filename)
            raise EncodingError(str(err))
Пример #5
0
    def verify(self, progress=None):
        """verifies the current file for correctness

        returns True if the file is okay
        raises an InvalidFile with an error message if there is
        some problem with the file"""

        from audiotools import CounterPCMReader
        from audiotools import transfer_framelist_data
        from audiotools import to_pcm_progress

        try:
            (header, footer) = self.wave_header_footer()
        except IOError as err:
            raise InvalidWave(err)
        except ValueError as err:
            raise InvalidWave(err)

        # ensure header is valid
        try:
            (total_size, data_size) = validate_header(header)
        except ValueError as err:
            raise InvalidWave(err)

        # ensure "data" chunk has all its data
        counter = CounterPCMReader(to_pcm_progress(self, progress))
        try:
            transfer_framelist_data(counter, lambda f: f)
        except (IOError, ValueError):
            from audiotools.text import ERR_WAV_TRUNCATED_DATA_CHUNK
            raise InvalidWave(ERR_WAV_TRUNCATED_DATA_CHUNK)

        data_bytes_written = counter.bytes_written()

        # ensure output data size matches the "data" chunk's size
        if data_size != data_bytes_written:
            from audiotools.text import ERR_WAV_TRUNCATED_DATA_CHUNK
            raise InvalidWave(ERR_WAV_TRUNCATED_DATA_CHUNK)

        # ensure footer validates correctly
        try:
            validate_footer(footer, data_bytes_written)
        except ValueError as err:
            from audiotools.text import ERR_WAV_INVALID_SIZE
            raise InvalidWave(ERR_WAV_INVALID_SIZE)

        # ensure total size is correct
        if (len(header) + data_size + len(footer)) != total_size:
            from audiotools.text import ERR_WAV_INVALID_SIZE
            raise InvalidWave(ERR_WAV_INVALID_SIZE)

        return True
Пример #6
0
    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
        metadata is not copied during conversion, but embedded
        RIFF chunks are (if any)
        may raise EncodingError if some problem occurs during encoding"""

        #Note that a Shorten file cannot contain
        #both RIFF chunks and AIFF chunks at the same time.

        import tempfile

        if (target_class == WaveAudio):
            self.to_wave(target_path, progress=progress)
            return WaveAudio(target_path)
        elif (target_class == AiffAudio):
            self.to_aiff(target_path, progress=progress)
            return AiffAudio(target_path)
        elif (self.has_foreign_riff_chunks() and
              hasattr(target_class, "from_wave")):
            temp_wave = tempfile.NamedTemporaryFile(suffix=".wav")
            try:
                #we'll only log the second leg of conversion,
                #since that's likely to be the slower portion
                self.to_wave(temp_wave.name)
                return target_class.from_wave(target_path,
                                              temp_wave.name,
                                              compression,
                                              progress=progress)
            finally:
                temp_wave.close()
        elif (self.has_foreign_aiff_chunks() and
              hasattr(target_class, "from_aiff")):
            temp_aiff = tempfile.NamedTemporaryFile(suffix=".aiff")
            try:
                self.to_aiff(temp_aiff.name)
                return target_class.from_aiff(target_path,
                                              temp_aiff.name,
                                              compression,
                                              progress=progress)
            finally:
                temp_aiff.close()
        else:
            return target_class.from_pcm(target_path,
                                         to_pcm_progress(self, progress),
                                         compression)
Пример #7
0
    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."""

        if (hasattr(target_class, "from_wave")):
            return target_class.from_wave(target_path,
                                          self.filename,
                                          compression=compression,
                                          progress=progress)
        else:
            return target_class.from_pcm(target_path,
                                         to_pcm_progress(self, progress),
                                         compression)
Пример #8
0
    def from_wave(cls, filename, wave_filename, compression=None, progress=None):
        """Encodes a new AudioFile from an existing .wav file.

        Takes a filename string, wave_filename string
        of an existing WaveAudio file
        and an optional compression level string.
        Encodes a new audio file from the wave's data
        at the given filename with the specified compression level
        and returns a new M4AAudio object."""

        if (compression is None) or (compression not in cls.COMPRESSION_MODES):
            compression = __default_quality__(cls.NAME)

        try:
            wave = WaveAudio(wave_filename)
            wave.verify()
        except InvalidFile:
            raise EncodingError(u"invalid wave file")

        if wave.sample_rate > 96000:
            # convert through PCMConverter if sample rate is too high
            import tempfile

            tempwavefile = tempfile.NamedTemporaryFile(suffix=".wav")
            try:
                tempwave = WaveAudio.from_pcm(
                    tempwavefile.name,
                    PCMConverter(
                        to_pcm_progress(wave, progress),
                        sample_rate=96000,
                        channels=wave.channels(),
                        channel_mask=wave.channel_mask(),
                        bits_per_sample=wave.bits_per_sample(),
                    ),
                )
                return cls.__from_wave__(filename, tempwave.filename, compression)
            finally:
                if os.path.isfile(tempwavefile.name):
                    tempwavefile.close()
                else:
                    tempwavefile.close_called = True
        else:
            return cls.__from_wave__(filename, wave_filename, compression)
Пример #9
0
    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())
Пример #10
0
    def from_aiff(cls, filename, aiff_filename, compression=None,
                  block_size=256, progress=None):
        """Encodes a new AudioFile from an existing .aiff file.

        Takes a filename string, aiff_filename string
        of an existing WaveAudio file
        and an optional compression level string.
        Encodes a new audio file from the aiff's data
        at the given filename with the specified compression level
        and returns a new ShortenAudio object."""

        aiff = AiffAudio(aiff_filename)

        if (aiff.bits_per_sample() not in (8, 16)):
            raise UnsupportedBitsPerSample(filename, aiff.bits_per_sample())

        (head, tail) = aiff.pcm_split()
        if (len(tail) > 0):
            blocks = [head, None, tail]
        else:
            blocks = [head, None]

        import audiotools.encoders

        try:
            audiotools.encoders.encode_shn(
                filename=filename,
                pcmreader=to_pcm_progress(aiff, progress),
                block_size=block_size,
                file_type={8: 1,  # 8-bit AIFF seems to be signed
                           16: 3}[aiff.bits_per_sample()],
                verbatim_chunks=blocks)

            return cls(filename)
        except IOError, err:
            cls.__unlink__(filename)
            raise EncodingError(str(err))
Пример #11
0
                current_frames = 0
                decoder = decoders.SHNDecoder(self.filename)
                frame = decoder.read(4096)
                while (len(frame) > 0):
                    f.write(frame.to_bytes(False, self.bits_per_sample() > 8))
                    current_frames += frame.frames
                    if (progress is not None):
                        progress(current_frames, total_frames)
                    frame = decoder.read(4096)
                f.write(tail)
                f.close()
            except IOError, msg:
                self.__unlink__(wave_filename)
                raise EncodingError(str(msg))
        else:
            WaveAudio.from_pcm(wave_filename, to_pcm_progress(self, progress))

    def to_aiff(self, aiff_filename, progress=None):
        """writes the contents of this file to the given .aiff filename string

        raises EncodingError if some error occurs during decoding"""

        from . import decoders

        try:
            (head, tail) = decoders.SHNDecoder(self.filename).pcm_split()
        except IOError:
            raise EncodingError(str(msg))

        if ((head[0:4] == 'FORM') and (head[8:12] == 'AIFF')):
            try: