コード例 #1
0
def encode_flac(filename, pcmreader,
                block_size=4096,
                max_lpc_order=8,
                adaptive_mid_side=False,
                mid_side=True,
                exhaustive_model_search=False,
                max_residual_partition_order=5):

    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 ** 32, 0,
                            pcmreader.sample_rate,
                            pcmreader.channels,
                            pcmreader.bits_per_sample,
                            0, md5())

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

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

    #walk through PCM reader's FrameLists
    frame_number = 0
    frame = pcmreader.read(block_size *
                           (pcmreader.bits_per_sample / 8) *
                           pcmreader.channels)

    flac_frame = BitstreamRecorder(0)

    while (len(frame) > 0):

        streaminfo.input_update(frame)

        flac_frame.reset()
        encode_flac_frame(flac_frame, pcmreader, options, frame_number, frame)

        streaminfo.output_update(flac_frame)

        flac_frame.copy(writer)

        frame_number += 1
        frame = pcmreader.read(block_size *
                               (pcmreader.bits_per_sample / 8) *
                               pcmreader.channels)

    #return to beginning of file and rewrite STREAMINFO block
    output_file.seek(8, 0)
    streaminfo.write(writer)
    writer.close()
コード例 #2
0
ファイル: ape.py プロジェクト: ryechus/python-audio-tools
    def build(self, writer):
        """outputs an APEv2 tag to writer"""

        from audiotools.bitstream import BitstreamRecorder

        tags = BitstreamRecorder(1)

        for tag in self.tags:
            tag.build(tags)

        if (self.contains_header):
            writer.build(ApeTag.HEADER_FORMAT,
                         ("APETAGEX",                # preamble
                          2000,                      # version
                          tags.bytes() + 32,         # tag size
                          len(self.tags),            # item count
                          0,                         # read only
                          0,                         # encoding
                          1,                         # is header
                          not self.contains_footer,  # no footer
                          self.contains_header))     # has header

        tags.copy(writer)
        if (self.contains_footer):
            writer.build(ApeTag.HEADER_FORMAT,
                         ("APETAGEX",                # preamble
                          2000,                      # version
                          tags.bytes() + 32,         # tag size
                          len(self.tags),            # item count
                          0,                         # read only
                          0,                         # encoding
                          0,                         # is header
                          not self.contains_footer,  # no footer
                          self.contains_header))     # has header
コード例 #3
0
def encode_frame(writer, pcmreader, options, channels):
    assert(len(channels) > 0)

    uncompressed_frame = BitstreamRecorder(0)
    compressed_frame = BitstreamRecorder(0)

    writer.write(3, len(channels) - 1)

    encode_uncompressed_frame(uncompressed_frame,
                              pcmreader,
                              options,
                              channels)

    if len(channels[0]) >= 10:
        try:
            encode_compressed_frame(compressed_frame,
                                    pcmreader,
                                    options,
                                    channels)

            if compressed_frame.bits() < uncompressed_frame.bits():
                compressed_frame.copy(writer)
            else:
                uncompressed_frame.copy(writer)
        except ResidualOverflow:
            uncompressed_frame.copy(writer)
    else:
        uncompressed_frame.copy(writer)
コード例 #4
0
def encode_subframe(writer, options, bits_per_sample, samples):
    def all_identical(l):
        if len(l) == 1:
            return True
        else:
            for i in l[1:]:
                if i != l[0]:
                    return False
            else:
                return True

    def wasted(s):
        w = 0
        while (s & 1) == 0:
            w += 1
            s >>= 1
        return w

    if all_identical(samples):
        encode_constant_subframe(writer, bits_per_sample, samples[0])
    else:
        # account for wasted BPS, if any
        wasted_bps = 2**32
        for sample in samples:
            if sample != 0:
                wasted_bps = min(wasted_bps, wasted(sample))
                if wasted_bps == 0:
                    break

        if wasted_bps == 2**32:
            # all samples are 0
            wasted_bps = 0
        elif wasted_bps > 0:
            samples = [s >> wasted_bps for s in samples]

        fixed_subframe = BitstreamRecorder(0)
        encode_fixed_subframe(fixed_subframe, options, wasted_bps,
                              bits_per_sample, samples)

        if options.max_lpc_order > 0:
            lpc_subframe = BitstreamRecorder(0)
            encode_lpc_subframe(lpc_subframe, options, wasted_bps,
                                bits_per_sample, samples)

            if (((bits_per_sample * len(samples)) < min(
                    fixed_subframe.bits(), lpc_subframe.bits()))):
                encode_verbatim_subframe(writer, wasted_bps, bits_per_sample,
                                         samples)
            elif fixed_subframe.bits() < lpc_subframe.bits():
                fixed_subframe.copy(writer)
            else:
                lpc_subframe.copy(writer)
        else:
            if (bits_per_sample * len(samples)) < fixed_subframe.bits():
                encode_verbatim_subframe(writer, wasted_bps, bits_per_sample,
                                         samples)
            else:
                fixed_subframe.copy(writer)
コード例 #5
0
ファイル: ape.py プロジェクト: ryechus/python-audio-tools
    def build(self, writer):
        """outputs an APEv2 tag to writer"""

        from audiotools.bitstream import BitstreamRecorder

        tags = BitstreamRecorder(1)

        for tag in self.tags:
            tag.build(tags)

        if (self.contains_header):
            writer.build(
                ApeTag.HEADER_FORMAT,
                (
                    "APETAGEX",  # preamble
                    2000,  # version
                    tags.bytes() + 32,  # tag size
                    len(self.tags),  # item count
                    0,  # read only
                    0,  # encoding
                    1,  # is header
                    not self.contains_footer,  # no footer
                    self.contains_header))  # has header

        tags.copy(writer)
        if (self.contains_footer):
            writer.build(
                ApeTag.HEADER_FORMAT,
                (
                    "APETAGEX",  # preamble
                    2000,  # version
                    tags.bytes() + 32,  # tag size
                    len(self.tags),  # item count
                    0,  # read only
                    0,  # encoding
                    0,  # is header
                    not self.contains_footer,  # no footer
                    self.contains_header))  # has header
コード例 #6
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,
                padding_size=4096):

    frame_sizes = []

    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 such as STREAMINFO and PADDING
    writer.write_bytes("fLaC")
    writer.build("1u 7u 24u", [0, 0, 34])
    streaminfo_start = writer.getpos()
    streaminfo.write(writer)

    writer.build("1u 7u 24u", [1, 1, padding_size])
    writer.write_bytes(b"\x00" * padding_size)

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

    flac_frame = BitstreamRecorder(0)

    while len(frame) > 0:
        streaminfo.input_update(frame)

        flac_frame.reset()
        encode_flac_frame(flac_frame, pcmreader, options, frame_number, frame)
        frame_sizes.append((flac_frame.bytes(), frame.frames))
        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.setpos(streaminfo_start)
    streaminfo.write(writer)
    writer.flush()
    writer.close()

    return frame_sizes
コード例 #7
0
def encode_lpc_subframe(writer, options, wasted_bps, bits_per_sample, samples):
    """computes the best LPC subframe from the given samples
    according to the options and writes it to the given BitstreamWriter"""

    # window signal
    windowed = [(sample * tukey)
                for (sample,
                     tukey) in zip(samples, tukey_window(len(samples), 0.5))]

    # compute autocorrelation values
    if len(samples) > (options.max_lpc_order + 1):
        autocorrelation_values = [
            sum(x * y for x, y in zip(windowed, windowed[lag:]))
            for lag in range(0, options.max_lpc_order + 1)
        ]
    else:
        # not enough samples, so build LPC with dummy coeffs
        write_lpc_subframe(writer=writer,
                           options=options,
                           wasted_bps=wasted_bps,
                           bits_per_sample=bits_per_sample,
                           order=1,
                           qlp_precision=options.qlp_precision,
                           qlp_shift_needed=0,
                           qlp_coefficients=[0],
                           samples=samples)
        return

    # compute LP coefficients from autocorrelation values
    if ((len(autocorrelation_values) > 1)
            and (set(autocorrelation_values) != {0.0})):
        (lp_coefficients, error) = \
            compute_lp_coefficients(autocorrelation_values)
    else:
        # all autocorrelation values are zero
        # so build LPC with dummy coeffs
        write_lpc_subframe(writer=writer,
                           options=options,
                           wasted_bps=wasted_bps,
                           bits_per_sample=bits_per_sample,
                           order=1,
                           qlp_precision=options.qlp_precision,
                           qlp_shift_needed=0,
                           qlp_coefficients=[0],
                           samples=samples)
        return

    if not options.exhaustive_model_search:
        # if not performaing an exhaustive model search
        # estimate which set of LP coefficients is best
        # and use those to build subframe

        order = estimate_best_lpc_order(options, len(samples), bits_per_sample,
                                        error)
        (qlp_coefficients, qlp_shift_needed) = \
            quantize_coefficients(options.qlp_precision,
                                  lp_coefficients,
                                  order)

        write_lpc_subframe(writer=writer,
                           options=options,
                           wasted_bps=wasted_bps,
                           bits_per_sample=bits_per_sample,
                           order=order,
                           qlp_precision=options.qlp_precision,
                           qlp_shift_needed=qlp_shift_needed,
                           qlp_coefficients=qlp_coefficients,
                           samples=samples)
    else:
        # otherwise, build all possible subframes
        # and return the one which is actually the smallest

        best_subframe_size = 2**32
        best_subframe = BitstreamRecorder(0)

        for order in range(1, options.max_lpc_order + 1):
            (qlp_coefficients, qlp_shift_needed) = \
                quantize_coefficients(options.qlp_precision,
                                      lp_coefficients,
                                      order)

            subframe = BitstreamRecorder(0)
            write_lpc_subframe(writer=subframe,
                               options=options,
                               wasted_bps=wasted_bps,
                               bits_per_sample=bits_per_sample,
                               order=order,
                               qlp_precision=options.qlp_precision,
                               qlp_shift_needed=qlp_shift_needed,
                               qlp_coefficients=qlp_coefficients,
                               samples=samples)
            if subframe.bits() < best_subframe_size:
                best_subframe = subframe
        else:
            best_subframe.copy(writer)
コード例 #8
0
def encode_flac_frame(writer, pcmreader, options, frame_number, frame):
    crc16 = CRC16()
    writer.add_callback(crc16.update)

    if ((pcmreader.channels == 2)
            and (options.adaptive_mid_side or options.mid_side)):
        # calculate average/difference
        average = [(c0 + c1) // 2
                   for c0, c1 in zip(frame.channel(0), frame.channel(1))]
        difference = [
            c0 - c1 for c0, c1 in zip(frame.channel(0), frame.channel(1))
        ]

        # try different subframes based on encoding options
        left_subframe = BitstreamRecorder(0)
        encode_subframe(left_subframe, options, pcmreader.bits_per_sample,
                        list(frame.channel(0)))

        right_subframe = BitstreamRecorder(0)
        encode_subframe(right_subframe, options, pcmreader.bits_per_sample,
                        list(frame.channel(1)))

        average_subframe = BitstreamRecorder(0)
        encode_subframe(average_subframe, options, pcmreader.bits_per_sample,
                        average)

        difference_subframe = BitstreamRecorder(0)
        encode_subframe(difference_subframe, options,
                        pcmreader.bits_per_sample + 1, difference)

        # write best header/subframes to disk
        if options.mid_side:
            if ((left_subframe.bits() + right_subframe.bits()) < min(
                    left_subframe.bits() + difference_subframe.bits(),
                    difference_subframe.bits() + right_subframe.bits(),
                    average_subframe.bits() + difference_subframe.bits())):
                write_frame_header(writer, pcmreader, frame_number, frame, 0x1)
                left_subframe.copy(writer)
                right_subframe.copy(writer)
            elif (left_subframe.bits() < min(right_subframe.bits(),
                                             difference_subframe.bits())):
                write_frame_header(writer, pcmreader, frame_number, frame, 0x8)
                left_subframe.copy(writer)
                difference_subframe.copy(writer)
            elif right_subframe.bits() < average_subframe.bits():
                write_frame_header(writer, pcmreader, frame_number, frame, 0x9)
                difference_subframe.copy(writer)
                right_subframe.copy(writer)
            else:
                write_frame_header(writer, pcmreader, frame_number, frame, 0xA)
                average_subframe.copy(writer)
                difference_subframe.copy(writer)
        else:
            if (((left_subframe.bits() + right_subframe.bits()) <
                 (average_subframe.bits() + difference_subframe.bits()))):
                write_frame_header(writer, pcmreader, frame_number, frame, 0x1)
                left_subframe.copy(writer)
                right_subframe.copy(writer)
            else:
                write_frame_header(writer, pcmreader, frame_number, frame, 0xA)
                average_subframe.copy(writer)
                difference_subframe.copy(writer)
    else:
        write_frame_header(writer, pcmreader, frame_number, frame,
                           pcmreader.channels - 1)

        for i in range(frame.channels):
            encode_subframe(writer, options, pcmreader.bits_per_sample,
                            list(frame.channel(i)))

    writer.byte_align()
    writer.pop_callback()
    writer.write(16, int(crc16))
コード例 #9
0
ファイル: wavpack.py プロジェクト: hzlf/python-audio-tools
def write_block(writer, context, channels, block_index, first_block, last_block, parameters):
    """writer is a BitstreamWriter-compatible object
    context is an EncoderContext object
    channels[c][s] is sample "s" in channel "c"
    block_index is an integer of the block's offset in PCM frames
    first_block and last_block are flags indicating the block's sequence
    parameters is an EncodingParameters object
    """

    assert (len(channels) == 1) or (len(channels) == 2)

    if (len(channels) == 1) or (channels[0] == channels[1]):
        # 1 channel block or equivalent
        if len(channels) == 1:
            false_stereo = 0
        else:
            false_stereo = 1

        # calculate maximum magnitude of channel_0
        magnitude = max(map(bits, channels[0]))

        # determine wasted bits
        wasted = min(map(wasted_bps, channels[0]))
        if wasted == INFINITY:
            # all samples are 0
            wasted = 0

        # if wasted bits, remove them from channel_0
        if (wasted > 0) and (wasted != INFINITY):
            shifted = [[s >> wasted for s in channels[0]]]
        else:
            shifted = [channels[0]]

        # calculate CRC of shifted_0
        crc = calculate_crc(shifted)
    else:
        # 2 channel block
        false_stereo = 0

        # calculate maximum magnitude of channel_0/channel_1
        magnitude = max(max(map(bits, channels[0])), max(map(bits, channels[1])))

        # determine wasted bits
        wasted = min(min(map(wasted_bps, channels[0])), min(map(wasted_bps, channels[1])))
        if wasted == INFINITY:
            # all samples are 0
            wasted = 0

        # if wasted bits, remove them from channel_0/channel_1
        if wasted > 0:
            shifted = [[s >> wasted for s in channels[0]], [s >> wasted for s in channels[1]]]
        else:
            shifted = channels

        # calculate CRC of shifted_0/shifted_1
        crc = calculate_crc(shifted)

        # joint stereo conversion of shifted_0/shifted_1 to mid/side channels
        mid_side = joint_stereo(shifted[0], shifted[1])

    sub_blocks = BitstreamRecorder(1)
    sub_block = BitstreamRecorder(1)

    # if first block in file, write Wave header
    if not context.first_block_written:
        sub_block.reset()
        if context.wave_header is None:
            if context.wave_footer is None:
                write_wave_header(sub_block, context.pcmreader, 0, 0)
            else:
                write_wave_header(sub_block, context.pcmreader, 0, len(context.wave_footer))
        else:
            sub_block.write_bytes(context.wave_header)
        write_sub_block(sub_blocks, WV_WAVE_HEADER, 1, sub_block)
        context.first_block_written = True

    # if correlation passes, write three sub blocks of pass data
    if parameters.correlation_passes > 0:
        sub_block.reset()
        write_correlation_terms(
            sub_block,
            [p.term for p in parameters.correlation_parameters(false_stereo)],
            [p.delta for p in parameters.correlation_parameters(false_stereo)],
        )
        write_sub_block(sub_blocks, WV_TERMS, 0, sub_block)

        sub_block.reset()
        write_correlation_weights(sub_block, [p.weights for p in parameters.correlation_parameters(false_stereo)])
        write_sub_block(sub_blocks, WV_WEIGHTS, 0, sub_block)

        sub_block.reset()
        write_correlation_samples(
            sub_block,
            [p.term for p in parameters.correlation_parameters(false_stereo)],
            [p.samples for p in parameters.correlation_parameters(false_stereo)],
            2 if ((len(channels) == 2) and (not false_stereo)) else 1,
        )
        write_sub_block(sub_blocks, WV_SAMPLES, 0, sub_block)

    # if wasted bits, write extended integers sub block
    if wasted > 0:
        sub_block.reset()
        write_extended_integers(sub_block, 0, wasted, 0, 0)
        write_sub_block(sub_blocks, WV_INT32_INFO, 0, sub_block)

    # if channel count > 2, write channel info sub block
    if context.pcmreader.channels > 2:
        sub_block.reset()
        sub_block.write(8, context.pcmreader.channels)
        sub_block.write(32, context.pcmreader.channel_mask)
        write_sub_block(sub_blocks, WV_CHANNEL_INFO, 0, sub_block)

    # if nonstandard sample rate, write sample rate sub block
    if context.pcmreader.sample_rate not in (
        6000,
        8000,
        9600,
        11025,
        12000,
        16000,
        22050,
        24000,
        32000,
        44100,
        48000,
        64000,
        88200,
        96000,
        192000,
    ):
        sub_block.reset()
        sub_block.write(32, context.pcmreader.sample_rate)
        write_sub_block(sub_blocks, WV_SAMPLE_RATE, 1, sub_block)

    if (len(channels) == 1) or (false_stereo):
        # 1 channel block

        # correlate shifted_0 with terms/deltas/weights/samples
        if parameters.correlation_passes > 0:
            assert len(shifted) == 1
            correlated = correlate_channels(shifted, parameters.correlation_parameters(false_stereo), 1)
        else:
            correlated = shifted
    else:
        # 2 channel block

        # correlate shifted_0/shifted_1 with terms/deltas/weights/samples
        if parameters.correlation_passes > 0:
            assert len(mid_side) == 2
            correlated = correlate_channels(mid_side, parameters.correlation_parameters(false_stereo), 2)
        else:
            correlated = mid_side

    # write entropy variables sub block
    sub_block.reset()
    write_entropy_variables(sub_block, correlated, parameters.entropy_variables)
    write_sub_block(sub_blocks, WV_ENTROPY, 0, sub_block)

    # write bitstream sub block
    sub_block.reset()
    write_bitstream(sub_block, correlated, parameters.entropy_variables)
    write_sub_block(sub_blocks, WV_BITSTREAM, 0, sub_block)

    # write block header with size of all sub blocks
    write_block_header(
        writer,
        sub_blocks.bytes(),
        block_index,
        len(channels[0]),
        context.pcmreader.bits_per_sample,
        len(channels),
        (len(channels) == 2) and (false_stereo == 0),
        len(set([-1, -2, -3]) & set([p.term for p in parameters.correlation_parameters(false_stereo)])) > 0,
        wasted,
        first_block,
        last_block,
        magnitude,
        context.pcmreader.sample_rate,
        false_stereo,
        crc,
    )

    # write sub block data to stream
    sub_blocks.copy(writer)

    # round-trip entropy variables
    parameters.entropy_variables = [
        [wv_exp2(wv_log2(p)) for p in parameters.entropy_variables[0]],
        [wv_exp2(wv_log2(p)) for p in parameters.entropy_variables[1]],
    ]
コード例 #10
0
ファイル: wavpack.py プロジェクト: hzlf/python-audio-tools
def encode_wavpack(filename, pcmreader, block_size, correlation_passes=0, wave_header=None, wave_footer=None):
    pcmreader = BufferedPCMReader(pcmreader)
    output_file = open(filename, "wb")
    writer = BitstreamWriter(output_file, 1)
    context = EncoderContext(
        pcmreader,
        block_parameters(pcmreader.channels, pcmreader.channel_mask, correlation_passes),
        wave_header,
        wave_footer,
    )

    block_index = 0

    # walk through PCM reader's FrameLists
    frame = pcmreader.read(block_size * (pcmreader.bits_per_sample / 8) * pcmreader.channels)
    while len(frame) > 0:
        context.total_frames += frame.frames
        context.md5sum.update(frame.to_bytes(False, pcmreader.bits_per_sample >= 16))

        c = 0
        for parameters in context.block_parameters:
            if parameters.channel_count == 1:
                channel_data = [list(frame.channel(c))]
            else:
                channel_data = [list(frame.channel(c)), list(frame.channel(c + 1))]

            first_block = parameters is context.block_parameters[0]
            last_block = parameters is context.block_parameters[-1]

            context.block_offsets.append(output_file.tell())
            write_block(writer, context, channel_data, block_index, first_block, last_block, parameters)

            c += parameters.channel_count

        block_index += frame.frames
        frame = pcmreader.read(block_size * (pcmreader.bits_per_sample / 8) * pcmreader.channels)

    # write MD5 sum and optional Wave footer in final block
    sub_blocks = BitstreamRecorder(1)
    sub_block = BitstreamRecorder(1)

    sub_block.reset()
    sub_block.write_bytes(context.md5sum.digest())
    write_sub_block(sub_blocks, WV_MD5, 1, sub_block)

    # write Wave footer in final block, if present
    if context.wave_footer is not None:
        sub_block.reset()
        sub_block.write_bytes(context.wave_footer)
        write_sub_block(sub_blocks, WV_WAVE_FOOTER, 1, sub_block)

    write_block_header(
        writer,
        sub_blocks.bytes(),
        0xFFFFFFFF,
        0,
        pcmreader.bits_per_sample,
        1,
        0,
        0,
        0,
        1,
        1,
        0,
        pcmreader.sample_rate,
        0,
        0xFFFFFFFF,
    )
    sub_blocks.copy(writer)

    # update Wave header's "data" chunk size, if generated
    if context.wave_header is None:
        output_file.seek(32 + 2)
        if context.wave_footer is None:
            write_wave_header(writer, context.pcmreader, context.total_frames, 0)
        else:
            write_wave_header(writer, context.pcmreader, context.total_frames, len(context.wave_footer))

    # go back and populate block headers with total samples
    for block_offset in context.block_offsets:
        output_file.seek(block_offset + 12, 0)
        writer.write(32, block_index)

    writer.close()
コード例 #11
0
ファイル: flac.py プロジェクト: brigittebigi/sppas
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,
                padding_size=4096):

    frame_sizes = []

    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 such as STREAMINFO and PADDING
    writer.write_bytes("fLaC")
    writer.build("1u 7u 24u", [0, 0, 34])
    streaminfo_start = writer.getpos()
    streaminfo.write(writer)

    writer.build("1u 7u 24u", [1, 1, padding_size])
    writer.write_bytes(b"\x00" * padding_size)

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

    flac_frame = BitstreamRecorder(0)

    while len(frame) > 0:
        streaminfo.input_update(frame)

        flac_frame.reset()
        encode_flac_frame(flac_frame, pcmreader, options, frame_number, frame)
        frame_sizes.append((flac_frame.bytes(), frame.frames))
        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.setpos(streaminfo_start)
    streaminfo.write(writer)
    writer.flush()
    writer.close()

    return frame_sizes
コード例 #12
0
ファイル: flac.py プロジェクト: brigittebigi/sppas
def encode_lpc_subframe(writer, options, wasted_bps, bits_per_sample,
                        samples):
    """computes the best LPC subframe from the given samples
    according to the options and writes it to the given BitstreamWriter"""

    # window signal
    windowed = [(sample * tukey) for (sample, tukey) in
                zip(samples, tukey_window(len(samples), 0.5))]

    # compute autocorrelation values
    if len(samples) > (options.max_lpc_order + 1):
        autocorrelation_values = [
            sum(x * y for x, y in zip(windowed, windowed[lag:]))
            for lag in range(0, options.max_lpc_order + 1)]
    else:
        # not enough samples, so build LPC with dummy coeffs
        write_lpc_subframe(writer=writer,
                           options=options,
                           wasted_bps=wasted_bps,
                           bits_per_sample=bits_per_sample,
                           order=1,
                           qlp_precision=options.qlp_precision,
                           qlp_shift_needed=0,
                           qlp_coefficients=[0],
                           samples=samples)
        return

    # compute LP coefficients from autocorrelation values
    if ((len(autocorrelation_values) > 1) and
        (set(autocorrelation_values) != {0.0})):
        (lp_coefficients, error) = \
            compute_lp_coefficients(autocorrelation_values)
    else:
        # all autocorrelation values are zero
        # so build LPC with dummy coeffs
        write_lpc_subframe(writer=writer,
                           options=options,
                           wasted_bps=wasted_bps,
                           bits_per_sample=bits_per_sample,
                           order=1,
                           qlp_precision=options.qlp_precision,
                           qlp_shift_needed=0,
                           qlp_coefficients=[0],
                           samples=samples)
        return

    if not options.exhaustive_model_search:
        # if not performaing an exhaustive model search
        # estimate which set of LP coefficients is best
        # and use those to build subframe

        order = estimate_best_lpc_order(options,
                                        len(samples),
                                        bits_per_sample,
                                        error)
        (qlp_coefficients, qlp_shift_needed) = \
            quantize_coefficients(options.qlp_precision,
                                  lp_coefficients,
                                  order)

        write_lpc_subframe(writer=writer,
                           options=options,
                           wasted_bps=wasted_bps,
                           bits_per_sample=bits_per_sample,
                           order=order,
                           qlp_precision=options.qlp_precision,
                           qlp_shift_needed=qlp_shift_needed,
                           qlp_coefficients=qlp_coefficients,
                           samples=samples)
    else:
        # otherwise, build all possible subframes
        # and return the one which is actually the smallest

        best_subframe_size = 2 ** 32
        best_subframe = BitstreamRecorder(0)

        for order in range(1, options.max_lpc_order + 1):
            (qlp_coefficients, qlp_shift_needed) = \
                quantize_coefficients(options.qlp_precision,
                                      lp_coefficients,
                                      order)

            subframe = BitstreamRecorder(0)
            write_lpc_subframe(writer=subframe,
                               options=options,
                               wasted_bps=wasted_bps,
                               bits_per_sample=bits_per_sample,
                               order=order,
                               qlp_precision=options.qlp_precision,
                               qlp_shift_needed=qlp_shift_needed,
                               qlp_coefficients=qlp_coefficients,
                               samples=samples)
            if subframe.bits() < best_subframe_size:
                best_subframe = subframe
        else:
            best_subframe.copy(writer)
コード例 #13
0
ファイル: flac.py プロジェクト: brigittebigi/sppas
def encode_subframe(writer, options, bits_per_sample, samples):
    def all_identical(l):
        if len(l) == 1:
            return True
        else:
            for i in l[1:]:
                if i != l[0]:
                    return False
            else:
                return True

    def wasted(s):
        w = 0
        while (s & 1) == 0:
            w += 1
            s >>= 1
        return w

    if all_identical(samples):
        encode_constant_subframe(writer, bits_per_sample, samples[0])
    else:
        # account for wasted BPS, if any
        wasted_bps = 2 ** 32
        for sample in samples:
            if sample != 0:
                wasted_bps = min(wasted_bps, wasted(sample))
                if wasted_bps == 0:
                    break

        if wasted_bps == 2 ** 32:
            # all samples are 0
            wasted_bps = 0
        elif wasted_bps > 0:
            samples = [s >> wasted_bps for s in samples]

        fixed_subframe = BitstreamRecorder(0)
        encode_fixed_subframe(fixed_subframe,
                              options,
                              wasted_bps,
                              bits_per_sample,
                              samples)

        if options.max_lpc_order > 0:
            lpc_subframe = BitstreamRecorder(0)
            encode_lpc_subframe(lpc_subframe,
                                options,
                                wasted_bps,
                                bits_per_sample,
                                samples)

            if (((bits_per_sample * len(samples)) <
                 min(fixed_subframe.bits(), lpc_subframe.bits()))):
                encode_verbatim_subframe(writer, wasted_bps,
                                         bits_per_sample, samples)
            elif fixed_subframe.bits() < lpc_subframe.bits():
                fixed_subframe.copy(writer)
            else:
                lpc_subframe.copy(writer)
        else:
            if (bits_per_sample * len(samples)) < fixed_subframe.bits():
                encode_verbatim_subframe(writer, wasted_bps,
                                         bits_per_sample, samples)
            else:
                fixed_subframe.copy(writer)
コード例 #14
0
ファイル: flac.py プロジェクト: brigittebigi/sppas
def encode_flac_frame(writer, pcmreader, options, frame_number, frame):
    crc16 = CRC16()
    writer.add_callback(crc16.update)

    if ((pcmreader.channels == 2) and (options.adaptive_mid_side or
                                       options.mid_side)):
        # calculate average/difference
        average = [(c0 + c1) // 2 for c0, c1 in zip(frame.channel(0),
                                                    frame.channel(1))]
        difference = [c0 - c1 for c0, c1 in zip(frame.channel(0),
                                                frame.channel(1))]

        # try different subframes based on encoding options
        left_subframe = BitstreamRecorder(0)
        encode_subframe(left_subframe, options,
                        pcmreader.bits_per_sample, list(frame.channel(0)))

        right_subframe = BitstreamRecorder(0)
        encode_subframe(right_subframe, options,
                        pcmreader.bits_per_sample, list(frame.channel(1)))

        average_subframe = BitstreamRecorder(0)
        encode_subframe(average_subframe, options,
                        pcmreader.bits_per_sample, average)

        difference_subframe = BitstreamRecorder(0)
        encode_subframe(difference_subframe, options,
                        pcmreader.bits_per_sample + 1, difference)

        # write best header/subframes to disk
        if options.mid_side:
            if ((left_subframe.bits() + right_subframe.bits()) <
                min(left_subframe.bits() + difference_subframe.bits(),
                    difference_subframe.bits() + right_subframe.bits(),
                    average_subframe.bits() + difference_subframe.bits())):
                write_frame_header(writer, pcmreader, frame_number, frame, 0x1)
                left_subframe.copy(writer)
                right_subframe.copy(writer)
            elif (left_subframe.bits() <
                  min(right_subframe.bits(), difference_subframe.bits())):
                write_frame_header(writer, pcmreader, frame_number, frame, 0x8)
                left_subframe.copy(writer)
                difference_subframe.copy(writer)
            elif right_subframe.bits() < average_subframe.bits():
                write_frame_header(writer, pcmreader, frame_number, frame, 0x9)
                difference_subframe.copy(writer)
                right_subframe.copy(writer)
            else:
                write_frame_header(writer, pcmreader, frame_number, frame, 0xA)
                average_subframe.copy(writer)
                difference_subframe.copy(writer)
        else:
            if (((left_subframe.bits() + right_subframe.bits()) <
                 (average_subframe.bits() + difference_subframe.bits()))):
                write_frame_header(writer, pcmreader, frame_number, frame, 0x1)
                left_subframe.copy(writer)
                right_subframe.copy(writer)
            else:
                write_frame_header(writer, pcmreader, frame_number, frame, 0xA)
                average_subframe.copy(writer)
                difference_subframe.copy(writer)
    else:
        write_frame_header(writer, pcmreader, frame_number, frame,
                           pcmreader.channels - 1)

        for i in range(frame.channels):
            encode_subframe(writer,
                            options,
                            pcmreader.bits_per_sample,
                            list(frame.channel(i)))

    writer.byte_align()
    writer.pop_callback()
    writer.write(16, int(crc16))
コード例 #15
0
ファイル: flac.py プロジェクト: wesclemens/python-audio-tools
def encode_subframe(writer, options, bits_per_sample, samples):
    def all_identical(l):
        if (len(l) == 1):
            return True
        else:
            for i in l[1:]:
                if (i != l[0]):
                    return False
            else:
                return True

    def wasted(s):
        w = 0
        while ((s & 1) == 0):
            w += 1
            s >>= 1
        return w

    if (all_identical(samples)):
        encode_constant_subframe(writer, bits_per_sample, samples[0])
    else:
        #account for wasted BPS, if any
        wasted_bps = 2 ** 32
        for sample in samples:
            if (sample != 0):
                wasted_bps = min(wasted_bps, wasted(sample))
                if (wasted_bps == 0):
                    break

        if (wasted_bps == 2 ** 32):
            #all samples are 0
            wasted_bps = 0
        elif (wasted_bps > 0):
            samples = [s >> wasted_bps for s in samples]

        fixed_subframe = BitstreamRecorder(0)
        encode_fixed_subframe(fixed_subframe,
                              options,
                              wasted_bps,
                              bits_per_sample,
                              samples)

        if (options.max_lpc_order > 0):
            (lpc_order,
             qlp_coeffs,
             qlp_shift_needed) = compute_lpc_coefficients(options,
                                                          wasted_bps,
                                                          bits_per_sample,
                                                          samples)

            lpc_subframe = BitstreamRecorder(0)
            encode_lpc_subframe(lpc_subframe,
                                options,
                                wasted_bps,
                                bits_per_sample,
                                lpc_order,
                                options.qlp_precision,
                                qlp_shift_needed,
                                qlp_coeffs,
                                samples)

            if (((bits_per_sample * len(samples)) <
                 min(fixed_subframe.bits(), lpc_subframe.bits()))):
                encode_verbatim_subframe(writer, wasted_bps,
                                         bits_per_sample, samples)
            elif (fixed_subframe.bits() < lpc_subframe.bits()):
                fixed_subframe.copy(writer)
            else:
                lpc_subframe.copy(writer)
        else:
            if ((bits_per_sample * len(samples)) < fixed_subframe.bits()):
                encode_verbatim_subframe(writer, wasted_bps,
                                         bits_per_sample, samples)
            else:
                fixed_subframe.copy(writer)
コード例 #16
0
def encode_subframe(writer, options, bits_per_sample, samples):
    def all_identical(l):
        if (len(l) == 1):
            return True
        else:
            for i in l[1:]:
                if (i != l[0]):
                    return False
            else:
                return True

    def wasted(s):
        w = 0
        while ((s & 1) == 0):
            w += 1
            s >>= 1
        return w

    if (all_identical(samples)):
        encode_constant_subframe(writer, bits_per_sample, samples[0])
    else:
        # account for wasted BPS, if any
        wasted_bps = 2 ** 32
        for sample in samples:
            if (sample != 0):
                wasted_bps = min(wasted_bps, wasted(sample))
                if (wasted_bps == 0):
                    break

        if (wasted_bps == 2 ** 32):
            # all samples are 0
            wasted_bps = 0
        elif (wasted_bps > 0):
            samples = [s >> wasted_bps for s in samples]

        fixed_subframe = BitstreamRecorder(0)
        encode_fixed_subframe(fixed_subframe,
                              options,
                              wasted_bps,
                              bits_per_sample,
                              samples)

        if (options.max_lpc_order > 0):
            (lpc_order,
             qlp_coeffs,
             qlp_shift_needed) = compute_lpc_coefficients(options,
                                                          wasted_bps,
                                                          bits_per_sample,
                                                          samples)

            lpc_subframe = BitstreamRecorder(0)
            encode_lpc_subframe(lpc_subframe,
                                options,
                                wasted_bps,
                                bits_per_sample,
                                lpc_order,
                                options.qlp_precision,
                                qlp_shift_needed,
                                qlp_coeffs,
                                samples)

            if (((bits_per_sample * len(samples)) <
                 min(fixed_subframe.bits(), lpc_subframe.bits()))):
                encode_verbatim_subframe(writer, wasted_bps,
                                         bits_per_sample, samples)
            elif (fixed_subframe.bits() < lpc_subframe.bits()):
                fixed_subframe.copy(writer)
            else:
                lpc_subframe.copy(writer)
        else:
            if ((bits_per_sample * len(samples)) < fixed_subframe.bits()):
                encode_verbatim_subframe(writer, wasted_bps,
                                         bits_per_sample, samples)
            else:
                fixed_subframe.copy(writer)