Exemplo n.º 1
0
def encode_mdat(file, pcmreader,
                block_size=4096,
                initial_history=10,
                history_multiplier=40,
                maximum_k=14,
                interlacing_shift=2,
                min_interlacing_leftweight=0,
                max_interlacing_leftweight=4):

    options = Encoding_Options(block_size,
                               initial_history,
                               history_multiplier,
                               maximum_k,
                               interlacing_shift,
                               min_interlacing_leftweight,
                               max_interlacing_leftweight)

    pcmreader = BufferedPCMReader(pcmreader)

    mdat = BitstreamWriter(file, False)
    total_pcm_frames = 0
    frame_byte_sizes = []

    # write placeholder mdat header
    mdat.mark()
    mdat.write(32, 0)
    mdat.write_bytes(b"mdat")

    # read FrameList objects until stream is empty
    frame = pcmreader.read(block_size)
    while (len(frame) > 0):
        total_pcm_frames += frame.frames
        frame_byte_size = Counter()
        mdat.add_callback(frame_byte_size.add)
        encode_frameset(mdat, pcmreader, options, frame)
        mdat.pop_callback()
        frame_byte_sizes.append(int(frame_byte_size))
        frame = pcmreader.read(block_size)

    # finally, return to start of mdat and write actual length
    mdat.rewind()
    mdat.write(32, sum(frame_byte_sizes) + 8)
    mdat.unmark()

    return (frame_byte_sizes, total_pcm_frames)
Exemplo n.º 2
0
def encode_mdat(file,
                pcmreader,
                block_size=4096,
                initial_history=10,
                history_multiplier=40,
                maximum_k=14,
                interlacing_shift=2,
                min_interlacing_leftweight=0,
                max_interlacing_leftweight=4):

    options = Encoding_Options(block_size, initial_history, history_multiplier,
                               maximum_k, interlacing_shift,
                               min_interlacing_leftweight,
                               max_interlacing_leftweight)

    pcmreader = BufferedPCMReader(pcmreader)

    mdat = BitstreamWriter(file, False)
    total_pcm_frames = 0
    frame_byte_sizes = []

    # write placeholder mdat header
    mdat.mark()
    mdat.write(32, 0)
    mdat.write_bytes(b"mdat")

    # read FrameList objects until stream is empty
    frame = pcmreader.read(block_size)
    while (len(frame) > 0):
        total_pcm_frames += frame.frames
        frame_byte_size = Counter()
        mdat.add_callback(frame_byte_size.add)
        encode_frameset(mdat, pcmreader, options, frame)
        mdat.pop_callback()
        frame_byte_sizes.append(int(frame_byte_size))
        frame = pcmreader.read(block_size)

    # finally, return to start of mdat and write actual length
    mdat.rewind()
    mdat.write(32, sum(frame_byte_sizes) + 8)
    mdat.unmark()

    return (frame_byte_sizes, total_pcm_frames)
Exemplo n.º 3
0
    def from_pcm(cls, filename, pcmreader,
                 compression=None,
                 total_pcm_frames=None,
                 encoding_function=None):
        """encodes a new file from PCM data

        takes a filename string, PCMReader object,
        optional compression level string and
        optional total_pcm_frames integer
        encodes a new audio file from pcmreader's data
        at the given filename with the specified compression level
        and returns a new AudioFile-compatible object

        may raise EncodingError if some problem occurs when
        encoding the input file.  This includes an error
        in the input stream, a problem writing the output file,
        or even an EncodingError subclass such as
        "UnsupportedBitsPerSample" if the input stream
        is formatted in a way this class is unable to support
        """

        from audiotools import (BufferedPCMReader,
                                CounterPCMReader,
                                transfer_data,
                                EncodingError)
        # from audiotools.py_encoders import encode_tta
        from audiotools.encoders import encode_tta
        from audiotools.bitstream import BitstreamWriter

        # open output file right away
        # so we can fail as soon as possible
        try:
            file = open(filename, "wb")
        except IOError as err:
            pcmreader.close()
            raise EncodingError(str(err))

        writer = BitstreamWriter(file, True)
        counter = CounterPCMReader(pcmreader)
        try:
            if (total_pcm_frames is not None):
                # write header to disk
                write_header(writer,
                             pcmreader.channels,
                             pcmreader.bits_per_sample,
                             pcmreader.sample_rate,
                             total_pcm_frames)

                block_size = (pcmreader.sample_rate * 256) // 245
                total_tta_frames = div_ceil(total_pcm_frames, block_size)

                # write temporary seektable to disk
                writer.mark()
                write_seektable(writer, [0] * total_tta_frames)
                writer.flush()

                # write frames to disk
                try:
                    frame_sizes = \
                        (encode_tta if encoding_function is None
                         else encoding_function)(file,
                                                 BufferedPCMReader(counter))
                except (IOError, ValueError) as err:
                    cls.__unlink__(filename)
                    raise EncodingError(str(err))

                # ensure written number of PCM frames
                # matches total_pcm_frames
                if (counter.frames_written != total_pcm_frames):
                    from audiotools.text import ERR_TOTAL_PCM_FRAMES_MISMATCH
                    cls.__unlink__(filename)
                    raise EncodingError(ERR_TOTAL_PCM_FRAMES_MISMATCH)

                assert(len(frame_sizes) == total_tta_frames)

                # go back and rewrite seektable with completed one
                writer.rewind()
                write_seektable(writer, frame_sizes)
                writer.unmark()
            else:
                import tempfile

                frames = tempfile.TemporaryFile()

                # encode TTA frames to temporary file
                try:
                    frame_sizes = \
                        (encode_tta if encoding_function is None
                         else encoding_function)(frames,
                                                 BufferedPCMReader(counter))
                except (IOError, ValueError) as err:
                    frames.close()
                    cls.__unlink__(filename)
                    raise EncodingError(str(err))

                # write header to disk
                write_header(writer,
                             pcmreader.channels,
                             pcmreader.bits_per_sample,
                             pcmreader.sample_rate,
                             counter.frames_written)

                # write seektable to disk
                write_seektable(writer, frame_sizes)

                # transfer TTA frames from temporary space to disk
                frames.seek(0, 0)
                transfer_data(frames.read, writer.write_bytes)
                frames.close()
        finally:
            counter.close()
            if (writer.has_mark()):
                writer.unmark()
            writer.close()

        return cls(filename)
Exemplo n.º 4
0
def encode_flac(filename,
                pcmreader,
                block_size=4096,
                max_lpc_order=8,
                min_residual_partition_order=0,
                max_residual_partition_order=5,
                mid_side=True,
                adaptive_mid_side=False,
                exhaustive_model_search=False,
                disable_verbatim_subframes=False,
                disable_constant_subframes=False,
                disable_fixed_subframes=False,
                disable_lpc_subframes=False):

    current_offset = 0
    frame_offsets = []

    options = Encoding_Options(block_size,
                               max_lpc_order,
                               adaptive_mid_side,
                               mid_side,
                               exhaustive_model_search,
                               max_residual_partition_order,
                               14 if pcmreader.bits_per_sample <= 16 else 30)

    streaminfo = STREAMINFO(block_size,
                            block_size,
                            (2 ** 24) - 1,
                            0,
                            pcmreader.sample_rate,
                            pcmreader.channels,
                            pcmreader.bits_per_sample,
                            0, md5())

    pcmreader = BufferedPCMReader(pcmreader)
    output_file = open(filename, "wb")
    writer = BitstreamWriter(output_file, False)

    # write placeholder metadata blocks
    writer.write_bytes("fLaC")
    writer.build("1u 7u 24u", [1, 0, 34])
    writer.mark(0)
    streaminfo.write(writer)

    # walk through PCM reader's FrameLists
    frame_number = 0
    frame = pcmreader.read(block_size)

    flac_frame = BitstreamRecorder(0)

    while (len(frame) > 0):
        frame_offsets.append((current_offset, frame.frames))
        streaminfo.input_update(frame)

        flac_frame.reset()
        encode_flac_frame(flac_frame, pcmreader, options, frame_number, frame)
        current_offset += flac_frame.bytes()
        streaminfo.output_update(flac_frame)

        flac_frame.copy(writer)

        frame_number += 1
        frame = pcmreader.read(block_size)

    # return to beginning of file and rewrite STREAMINFO block
    writer.rewind(0)
    streaminfo.write(writer)
    writer.unmark(0)
    writer.flush()
    writer.close()

    return frame_offsets
Exemplo n.º 5
0
    def from_pcm(cls,
                 filename,
                 pcmreader,
                 compression=None,
                 total_pcm_frames=None,
                 encoding_function=None):
        """encodes a new file from PCM data

        takes a filename string, PCMReader object,
        optional compression level string and
        optional total_pcm_frames integer
        encodes a new audio file from pcmreader's data
        at the given filename with the specified compression level
        and returns a new AudioFile-compatible object

        may raise EncodingError if some problem occurs when
        encoding the input file.  This includes an error
        in the input stream, a problem writing the output file,
        or even an EncodingError subclass such as
        "UnsupportedBitsPerSample" if the input stream
        is formatted in a way this class is unable to support
        """

        from audiotools import (BufferedPCMReader, CounterPCMReader,
                                transfer_data, EncodingError)
        # from audiotools.py_encoders import encode_tta
        from audiotools.encoders import encode_tta
        from audiotools.bitstream import BitstreamWriter

        # open output file right away
        # so we can fail as soon as possible
        try:
            file = open(filename, "wb")
        except IOError as err:
            pcmreader.close()
            raise EncodingError(str(err))

        writer = BitstreamWriter(file, True)
        counter = CounterPCMReader(pcmreader)
        try:
            if (total_pcm_frames is not None):
                # write header to disk
                write_header(writer, pcmreader.channels,
                             pcmreader.bits_per_sample, pcmreader.sample_rate,
                             total_pcm_frames)

                block_size = (pcmreader.sample_rate * 256) // 245
                total_tta_frames = div_ceil(total_pcm_frames, block_size)

                # write temporary seektable to disk
                writer.mark()
                write_seektable(writer, [0] * total_tta_frames)
                writer.flush()

                # write frames to disk
                try:
                    frame_sizes = \
                        (encode_tta if encoding_function is None
                         else encoding_function)(file,
                                                 BufferedPCMReader(counter))
                except (IOError, ValueError) as err:
                    cls.__unlink__(filename)
                    raise EncodingError(str(err))

                # ensure written number of PCM frames
                # matches total_pcm_frames
                if (counter.frames_written != total_pcm_frames):
                    from audiotools.text import ERR_TOTAL_PCM_FRAMES_MISMATCH
                    cls.__unlink__(filename)
                    raise EncodingError(ERR_TOTAL_PCM_FRAMES_MISMATCH)

                assert (len(frame_sizes) == total_tta_frames)

                # go back and rewrite seektable with completed one
                writer.rewind()
                write_seektable(writer, frame_sizes)
                writer.unmark()
            else:
                import tempfile

                frames = tempfile.TemporaryFile()

                # encode TTA frames to temporary file
                try:
                    frame_sizes = \
                        (encode_tta if encoding_function is None
                         else encoding_function)(frames,
                                                 BufferedPCMReader(counter))
                except (IOError, ValueError) as err:
                    frames.close()
                    cls.__unlink__(filename)
                    raise EncodingError(str(err))

                # write header to disk
                write_header(writer, pcmreader.channels,
                             pcmreader.bits_per_sample, pcmreader.sample_rate,
                             counter.frames_written)

                # write seektable to disk
                write_seektable(writer, frame_sizes)

                # transfer TTA frames from temporary space to disk
                frames.seek(0, 0)
                transfer_data(frames.read, writer.write_bytes)
                frames.close()
        finally:
            counter.close()
            if (writer.has_mark()):
                writer.unmark()
            writer.close()

        return cls(filename)