Exemple #1
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"""

        # Checking for a truncated Ogg stream typically involves
        # verifying that the "end of stream" flag is set on the last
        # Ogg page in the stream in the event that one or more whole
        # pages is lost.  But since the OpusFile decoder doesn't perform
        # this check and doesn't provide any access to its internal
        # Ogg decoder (unlike Vorbis), we'll perform that check externally.
        #
        # And since it's a fast check, we won't bother to update progress.

        from audiotools.ogg import PageReader
        import os.path

        try:
            reader = PageReader(open(self.filename, "rb"))
        except IOError as err:
            raise InvalidOpus(str(err))

        try:
            page = reader.read()
            while (not page.stream_end):
                page = reader.read()
            reader.close()
        except (IOError, ValueError) as err:
            raise InvalidOpus(str(err))

        return AudioFile.verify(self, progress)
Exemple #2
0
    def get_metadata(self):
        """returns a MetaData object, or None

        raises IOError if unable to read the file"""

        from cStringIO import StringIO
        from audiotools.bitstream import BitstreamReader
        from audiotools.ogg import PacketReader, PageReader
        from audiotools.vorbiscomment import VorbisComment

        reader = PacketReader(PageReader(open(self.filename, "rb")))

        identification = reader.read_packet()
        comment = BitstreamReader(StringIO(reader.read_packet()), True)

        (packet_type, packet_header) = comment.parse("8u 6b")
        if ((packet_type == 3) and (packet_header == 'vorbis')):
            vendor_string = \
                comment.read_bytes(comment.read(32)).decode('utf-8')
            comment_strings = [
                comment.read_bytes(comment.read(32)).decode('utf-8')
                for i in xrange(comment.read(32))]
            if (comment.read(1) == 1):   # framing bit
                return VorbisComment(comment_strings, vendor_string)
            else:
                return None
        else:
            return None
Exemple #3
0
    def get_metadata(self):
        """returns a MetaData object, or None

        raises IOError if unable to read the file"""

        from io import BytesIO
        from audiotools.bitstream import BitstreamReader
        from audiotools.ogg import PacketReader, PageReader

        reader = PacketReader(PageReader(open(self.filename, "rb")))

        identification = reader.read_packet()
        comment = BitstreamReader(BytesIO(reader.read_packet()), True)

        if (comment.read_bytes(8) == "OpusTags"):
            vendor_string = \
                comment.read_bytes(comment.read(32)).decode('utf-8')
            comment_strings = [
                comment.read_bytes(comment.read(32)).decode('utf-8')
                for i in range(comment.read(32))
            ]

            return VorbisComment(comment_strings, vendor_string)
        else:
            return None
    def total_frames(self):
        """returns the total PCM frames of the track as an integer"""

        from audiotools._ogg import PageReader

        try:
            reader = PageReader(file(self.filename, "rb"))
            page = reader.read()
            pcm_samples = page.granule_position

            while (not page.stream_end):
                page = reader.read()
                pcm_samples = max(pcm_samples, page.granule_position)

            reader.close()
            return pcm_samples
        except (IOError, ValueError):
            return 0
Exemple #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"""

        # Checking for a truncated Ogg stream typically involves
        # verifying that the "end of stream" flag is set on the last
        # Ogg page in the stream in the event that one or more whole
        # pages is lost.  But since the OpusFile decoder doesn't perform
        # this check and doesn't provide any access to its internal
        # Ogg decoder (unlike Vorbis), we'll perform that check externally.
        #
        # And since it's a fast check, we won't bother to update progress.

        from audiotools.ogg import PageReader
        import os.path

        try:
            reader = PageReader(open(self.filename, "rb"))
        except IOError as err:
            raise InvalidOpus(str(err))

        try:
            page = reader.read()
            while (not page.stream_end):
                page = reader.read()
            reader.close()
        except (IOError, ValueError) as err:
            raise InvalidOpus(str(err))

        return AudioFile.verify(self, progress)
Exemple #6
0
    def total_frames(self):
        """returns the total PCM frames of the track as an integer"""

        from audiotools._ogg import PageReader

        try:
            with PageReader(open(self.filename, "rb")) as reader:
                page = reader.read()
                pcm_samples = page.granule_position

                while not page.stream_end:
                    page = reader.read()
                    pcm_samples = max(pcm_samples, page.granule_position)

                return pcm_samples
        except (IOError, ValueError):
            return 0
Exemple #7
0
    def update_metadata(self, metadata):
        """takes this track's current MetaData object
        as returned by get_metadata() and sets this track's metadata
        with any fields updated in that object

        raises IOError if unable to write the file
        """

        import os
        from audiotools import TemporaryFile
        from audiotools.ogg import (PageReader,
                                    PacketReader,
                                    PageWriter,
                                    packet_to_pages,
                                    packets_to_pages)
        from audiotools.vorbiscomment import VorbisComment
        from audiotools.bitstream import BitstreamRecorder

        if (metadata is None):
            return
        elif (not isinstance(metadata, VorbisComment)):
            from .text import ERR_FOREIGN_METADATA
            raise ValueError(ERR_FOREIGN_METADATA)
        elif (not os.access(self.filename, os.W_OK)):
            raise IOError(self.filename)

        original_ogg = PacketReader(PageReader(file(self.filename, "rb")))
        new_ogg = PageWriter(TemporaryFile(self.filename))

        sequence_number = 0

        #transfer current file's identification packet in its own page
        identification_packet = original_ogg.read_packet()
        for (i, page) in enumerate(packet_to_pages(
                identification_packet,
                self.__serial_number__,
                starting_sequence_number=sequence_number)):
            page.stream_beginning = (i == 0)
            new_ogg.write(page)
            sequence_number += 1

        #discard the current file's comment packet
        comment_packet = original_ogg.read_packet()

        #generate new comment packet
        comment_writer = BitstreamRecorder(True)
        comment_writer.build("8u 6b", (3, "vorbis"))
        vendor_string = metadata.vendor_string.encode('utf-8')
        comment_writer.build("32u %db" % (len(vendor_string)),
                             (len(vendor_string), vendor_string))
        comment_writer.write(32, len(metadata.comment_strings))
        for comment_string in metadata.comment_strings:
            comment_string = comment_string.encode('utf-8')
            comment_writer.build("32u %db" % (len(comment_string)),
                                 (len(comment_string), comment_string))

        comment_writer.build("1u a", (1,))  # framing bit

        #transfer codebooks packet from original file to new file
        codebooks_packet = original_ogg.read_packet()

        for page in packets_to_pages(
                [comment_writer.data(), codebooks_packet],
                self.__serial_number__,
                starting_sequence_number=sequence_number):
            new_ogg.write(page)
            sequence_number += 1

        #transfer remaining pages after re-sequencing
        page = original_ogg.read_page()
        page.sequence_number = sequence_number
        sequence_number += 1
        new_ogg.write(page)
        while (not page.stream_end):
            page = original_ogg.read_page()
            page.sequence_number = sequence_number
            page.bitstream_serial_number = self.__serial_number__
            sequence_number += 1
            new_ogg.write(page)

        original_ogg.close()
        new_ogg.close()