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()
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
def encode_shn(filename, pcmreader, is_big_endian, signed_samples, header_data, footer_data="", block_size=256): """filename is a string to the output file's path pcmreader is a PCMReader object header_data and footer_data are binary strings block_size is the default size of each Shorten audio command """ pcmreader = BufferedPCMReader(pcmreader) output_file = open(filename, "wb") writer = BitstreamWriter(output_file, 0) left_shift = 0 wrapped_channels = [[] for c in xrange(pcmreader.channels)] # write magic number and version writer.build("4b 8u", ["ajkg", 2]) bytes_written = __Counter__() writer.add_callback(bytes_written.byte) # write header from PCMReader info and encoding options if pcmreader.bits_per_sample == 8: if signed_samples: write_long(writer, 1) # signed, 8-bit sign_adjustment = 0 else: write_long(writer, 2) # unsigned, 8-bit sign_adjustment = 1 << (pcmreader.bits_per_sample - 1) # 8-bit samples have no endianness elif pcmreader.bits_per_sample == 16: if signed_samples: if is_big_endian: write_long(writer, 3) # signed, 16-bit, big-endian else: write_long(writer, 5) # signed, 16-bit, little-endian sign_adjustment = 0 else: if is_big_endian: write_long(writer, 4) # unsigned, 16-bit, big-endian else: write_long(writer, 6) # unsigned, 16-bit, little-endian sign_adjustment = 1 << (pcmreader.bits_per_sample - 1) else: raise ValueError("unsupported bits_per_sample") write_long(writer, pcmreader.channels) write_long(writer, block_size) write_long(writer, 0) # max LPC write_long(writer, 0) # mean count write_long(writer, 0) # bytes to skip # write header as a VERBATIM block write_unsigned(writer, COMMAND_SIZE, FN_VERBATIM) write_unsigned(writer, VERBATIM_SIZE, len(header_data)) for b in header_data: write_unsigned(writer, VERBATIM_BYTE_SIZE, ord(b)) # split PCMReader into block_size chunks # and continue until the number of PCM frames is 0 frame = pcmreader.read(block_size) while len(frame) > 0: # if the chunk isn't block_size frames long, # issue a command to change it if frame.frames != block_size: block_size = frame.frames write_unsigned(writer, COMMAND_SIZE, FN_BLOCKSIZE) write_long(writer, block_size) # split chunk into individual channels for c in xrange(pcmreader.channels): # convert PCM data to unsigned, if necessary if signed_samples: channel = list(frame.channel(c)) else: channel = [s + sign_adjustment for s in frame.channel(c)] # if all samples are 0, issue a ZERO command if all_zeroes(channel): write_unsigned(writer, COMMAND_SIZE, FN_ZERO) # wrap zeroes around for next set of channels wrapped_channels[c] = channel else: # if channel's shifted bits have changed # from the previous channel's shift # issue a new BITSHIFT command wasted_bits = wasted_bps(channel) if wasted_bits != left_shift: write_unsigned(writer, COMMAND_SIZE, FN_BITSHIFT) write_unsigned(writer, BITSHIFT_SIZE, wasted_bits) left_shift = wasted_bits # and shift the channel's bits if the amount is still > 0 if left_shift > 0: shifted = [s >> left_shift for s in channel] else: shifted = channel # determine the best DIFF command and residuals # to issue for shifted channel data (diff, residuals) = best_diff(wrapped_channels[c], shifted) # determine the best energy size for DIFF's residuals energy = best_energy(residuals) # write DIFF command, energy size and residuals write_unsigned(writer, COMMAND_SIZE, {1: FN_DIFF1, 2: FN_DIFF2, 3: FN_DIFF3}[diff]) write_unsigned(writer, ENERGY_SIZE, energy) for residual in residuals: write_signed(writer, energy, residual) # wrap shifted channels around for next set of channels wrapped_channels[c] = shifted # and get another set of channels to encode frame = pcmreader.read(block_size) # once all PCM data has been sent # if there's any footer data, write it as another VERBATIM block if len(footer_data) > 0: write_unsigned(writer, COMMAND_SIZE, FN_VERBATIM) write_unsigned(writer, VERBATIM_SIZE, len(footer_data)) for b in footer_data: write_unsigned(writer, VERBATIM_BYTE_SIZE, ord(b)) # issue a QUIT command write_unsigned(writer, COMMAND_SIZE, FN_QUIT) # finally, due to Shorten's silly way of using bit buffers, # output (not counting the 5 bytes of magic + version) # must be padded to a multiple of 4 bytes # or its reference decoder explodes writer.byte_align() while (int(bytes_written) % 4) != 0: writer.write(8, 0)
def encode_shn(filename, pcmreader, is_big_endian, signed_samples, header_data, footer_data="", block_size=256): """filename is a string to the output file's path pcmreader is a PCMReader object header_data and footer_data are binary strings block_size is the default size of each Shorten audio command """ pcmreader = BufferedPCMReader(pcmreader) output_file = open(filename, "wb") writer = BitstreamWriter(output_file, 0) left_shift = 0 wrapped_channels = [[] for c in xrange(pcmreader.channels)] #write magic number and version writer.build("4b 8u", ["ajkg", 2]) bytes_written = __Counter__() writer.add_callback(bytes_written.byte) #write header from PCMReader info and encoding options if (pcmreader.bits_per_sample == 8): if (signed_samples): write_long(writer, 1) # signed, 8-bit sign_adjustment = 0 else: write_long(writer, 2) # unsigned, 8-bit sign_adjustment = 1 << (pcmreader.bits_per_sample - 1) #8-bit samples have no endianness elif (pcmreader.bits_per_sample == 16): if (signed_samples): if (is_big_endian): write_long(writer, 3) # signed, 16-bit, big-endian else: write_long(writer, 5) # signed, 16-bit, little-endian sign_adjustment = 0 else: if (is_big_endian): write_long(writer, 4) # unsigned, 16-bit, big-endian else: write_long(writer, 6) # unsigned, 16-bit, little-endian sign_adjustment = 1 << (pcmreader.bits_per_sample - 1) else: raise ValueError("unsupported bits_per_sample") write_long(writer, pcmreader.channels) write_long(writer, block_size) write_long(writer, 0) # max LPC write_long(writer, 0) # mean count write_long(writer, 0) # bytes to skip #write header as a VERBATIM block write_unsigned(writer, COMMAND_SIZE, FN_VERBATIM) write_unsigned(writer, VERBATIM_SIZE, len(header_data)) for b in header_data: write_unsigned(writer, VERBATIM_BYTE_SIZE, ord(b)) #split PCMReader into block_size chunks #and continue until the number of PCM frames is 0 frame = pcmreader.read(block_size) while (len(frame) > 0): #if the chunk isn't block_size frames long, #issue a command to change it if (frame.frames != block_size): block_size = frame.frames write_unsigned(writer, COMMAND_SIZE, FN_BLOCKSIZE) write_long(writer, block_size) #split chunk into individual channels for c in xrange(pcmreader.channels): #convert PCM data to unsigned, if necessary if (signed_samples): channel = list(frame.channel(c)) else: channel = [s + sign_adjustment for s in frame.channel(c)] #if all samples are 0, issue a ZERO command if (all_zeroes(channel)): write_unsigned(writer, COMMAND_SIZE, FN_ZERO) #wrap zeroes around for next set of channels wrapped_channels[c] = channel else: #if channel's shifted bits have changed #from the previous channel's shift #issue a new BITSHIFT command wasted_bits = wasted_bps(channel) if (wasted_bits != left_shift): write_unsigned(writer, COMMAND_SIZE, FN_BITSHIFT) write_unsigned(writer, BITSHIFT_SIZE, wasted_bits) left_shift = wasted_bits #and shift the channel's bits if the amount is still > 0 if (left_shift > 0): shifted = [s >> left_shift for s in channel] else: shifted = channel #determine the best DIFF command and residuals #to issue for shifted channel data (diff, residuals) = best_diff(wrapped_channels[c], shifted) #determine the best energy size for DIFF's residuals energy = best_energy(residuals) #write DIFF command, energy size and residuals write_unsigned(writer, COMMAND_SIZE, { 1: FN_DIFF1, 2: FN_DIFF2, 3: FN_DIFF3 }[diff]) write_unsigned(writer, ENERGY_SIZE, energy) for residual in residuals: write_signed(writer, energy, residual) #wrap shifted channels around for next set of channels wrapped_channels[c] = shifted #and get another set of channels to encode frame = pcmreader.read(block_size) #once all PCM data has been sent #if there's any footer data, write it as another VERBATIM block if (len(footer_data) > 0): write_unsigned(writer, COMMAND_SIZE, FN_VERBATIM) write_unsigned(writer, VERBATIM_SIZE, len(footer_data)) for b in footer_data: write_unsigned(writer, VERBATIM_BYTE_SIZE, ord(b)) #issue a QUIT command write_unsigned(writer, COMMAND_SIZE, FN_QUIT) #finally, due to Shorten's silly way of using bit buffers, #output (not counting the 5 bytes of magic + version) #must be padded to a multiple of 4 bytes #or its reference decoder explodes writer.byte_align() while ((int(bytes_written) % 4) != 0): writer.write(8, 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