Пример #1
0
    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
Пример #2
0
    def read_metadata(self):
        from io import BytesIO

        command = self.unsigned(2)
        if command == 9:
            # got verbatim, so read data
            verbatim_bytes = ints_to_bytes([self.unsigned(8) & 0xFF
                                            for i in range(self.unsigned(5))])

            try:
                wave = BitstreamReader(BytesIO(verbatim_bytes), True)
                header = wave.read_bytes(12)
                if header.startswith(b"RIFF") and header.endswith(b"WAVE"):
                    # got RIFF/WAVE header, so parse wave blocks as needed
                    total_size = len(verbatim_bytes) - 12
                    while total_size > 0:
                        (chunk_id, chunk_size) = wave.parse("4b 32u")
                        total_size -= 8
                        if chunk_id == b'fmt ':
                            (channels,
                             self.sample_rate,
                             bits_per_sample,
                             channel_mask) = parse_fmt(
                                wave.substream(chunk_size))
                            self.channel_mask = int(channel_mask)
                            return
                        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
                    else:
                        # no fmt chunk, so use default metadata
                        pass
            except (IOError, ValueError):
                pass

            try:
                aiff = BitstreamReader(BytesIO(verbatim_bytes), False)
                header = aiff.read_bytes(12)
                if header.startswith(b"FORM") and header.endswith(b"AIFF"):
                    # got FORM/AIFF header, so parse aiff blocks as needed
                    total_size = len(verbatim_bytes) - 12
                    while total_size > 0:
                        (chunk_id, chunk_size) = aiff.parse("4b 32u")
                        total_size -= 8
                        if chunk_id == b'COMM':
                            (channels,
                             total_sample_frames,
                             bits_per_sample,
                             self.sample_rate,
                             channel_mask) = parse_comm(
                                aiff.substream(chunk_size))
                            self.channel_mask = int(channel_mask)
                            return
                        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
                    else:
                        # no COMM chunk, so use default metadata
                        pass
            except IOError:
                pass

        # got something else, so invent some PCM parameters
        self.sample_rate = 44100
        if self.channels == 1:
            self.channel_mask = 0x4
        elif self.channels == 2:
            self.channel_mask = 0x3
        else:
            self.channel_mask = 0
Пример #3
0
    def read_metadata(self):
        from io import BytesIO

        command = self.unsigned(2)
        if (command == 9):
            # got verbatim, so read data
            verbatim_bytes = ints_to_bytes(
                [self.unsigned(8) & 0xFF for i in range(self.unsigned(5))])

            try:
                wave = BitstreamReader(BytesIO(verbatim_bytes), True)
                header = wave.read_bytes(12)
                if (header.startswith(b"RIFF") and header.endswith(b"WAVE")):
                    # got RIFF/WAVE header, so parse wave blocks as needed
                    total_size = len(verbatim_bytes) - 12
                    while (total_size > 0):
                        (chunk_id, chunk_size) = wave.parse("4b 32u")
                        total_size -= 8
                        if (chunk_id == b'fmt '):
                            (channels, self.sample_rate, bits_per_sample,
                             channel_mask) = parse_fmt(
                                 wave.substream(chunk_size))
                            self.channel_mask = int(channel_mask)
                            return
                        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
                    else:
                        # no fmt chunk, so use default metadata
                        pass
            except (IOError, ValueError):
                pass

            try:
                aiff = BitstreamReader(BytesIO(verbatim_bytes), False)
                header = aiff.read_bytes(12)
                if (header.startswith(b"FORM") and header.endswith(b"AIFF")):
                    # got FORM/AIFF header, so parse aiff blocks as needed
                    total_size = len(verbatim_bytes) - 12
                    while (total_size > 0):
                        (chunk_id, chunk_size) = aiff.parse("4b 32u")
                        total_size -= 8
                        if (chunk_id == b'COMM'):
                            (channels, total_sample_frames, bits_per_sample,
                             self.sample_rate, channel_mask) = parse_comm(
                                 aiff.substream(chunk_size))
                            self.channel_mask = int(channel_mask)
                            return
                        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
                    else:
                        # no COMM chunk, so use default metadata
                        pass
            except IOError:
                pass

        # got something else, so invent some PCM parameters
        self.sample_rate = 44100
        if (self.channels == 1):
            self.channel_mask = 0x4
        elif (self.channels == 2):
            self.channel_mask = 0x3
        else:
            self.channel_mask = 0
Пример #4
0
    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
Пример #5
0
    def read_metadata(self):
        command = self.unsigned(2)
        if (command == 9):
            # got verbatim, so read data
            verbatim_bytes = "".join([chr(self.unsigned(8) & 0xFF)
                                      for i in range(self.unsigned(5))])

            try:
                wave = BitstreamReader(cStringIO.StringIO(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 > 0):
                        (chunk_id, chunk_size) = wave.parse("4b 32u")
                        total_size -= 8
                        if (chunk_id == 'fmt '):
                            (channels,
                             self.sample_rate,
                             bits_per_sample,
                             channel_mask) = parse_fmt(
                                wave.substream(chunk_size))
                            self.channel_mask = int(channel_mask)
                            return
                        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
                    else:
                        # no fmt chunk, so use default metadata
                        pass
            except (IOError, ValueError):
                pass

            try:
                aiff = BitstreamReader(cStringIO.StringIO(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 > 0):
                        (chunk_id, chunk_size) = aiff.parse("4b 32u")
                        total_size -= 8
                        if (chunk_id == 'COMM'):
                            (channels,
                             total_sample_frames,
                             bits_per_sample,
                             self.sample_rate,
                             channel_mask) = parse_comm(
                                aiff.substream(chunk_size))
                            self.channel_mask = int(channel_mask)
                            return
                        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
                    else:
                        # no COMM chunk, so use default metadata
                        pass
            except IOError:
                pass

        # got something else, so invent some PCM parameters
        self.sample_rate = 44100
        if (self.channels == 1):
            self.channel_mask = 0x4
        elif (self.channels == 2):
            self.channel_mask = 0x3
        else:
            self.channel_mask = 0