コード例 #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
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
コード例 #3
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]],
    ]
コード例 #4
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()
コード例 #5
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