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)
def calculate_lpc_coefficients(pcmreader, options, sample_size, channel): windowed = [s * t for s, t in zip(channel, tukey_window(len(channel), 0.5))] autocorrelated = [sum([s1 * s2 for s1, s2 in zip(windowed, windowed[lag:])]) for lag in range(0, 9)] assert len(autocorrelated) == 9 if autocorrelated[0] != 0.0: lp_coefficients = compute_lp_coefficients(autocorrelated) assert len(lp_coefficients) == 8 qlp_coefficients4 = quantize_coefficients(lp_coefficients, 4) qlp_coefficients8 = quantize_coefficients(lp_coefficients, 8) residuals4 = compute_residuals(sample_size, qlp_coefficients4[:], channel) residuals8 = compute_residuals(sample_size, qlp_coefficients8[:], channel) residual_block4 = BitstreamRecorder(0) residual_block8 = BitstreamRecorder(0) encode_residuals(residual_block4, options, sample_size, residuals4) encode_residuals(residual_block8, options, sample_size, residuals8) if residual_block4.bits() < residual_block8.bits(): return (qlp_coefficients4, residual_block4) else: return (qlp_coefficients8, residual_block8) else: qlp_coefficients = [0, 0, 0, 0] residuals = compute_residuals(sample_size, qlp_coefficients[:], channel) residual_block = BitstreamRecorder(0) encode_residuals(residual_block, options, sample_size, residuals) return (qlp_coefficients, residual_block)
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)
def calculate_lpc_coefficients(pcmreader, options, sample_size, channel): windowed = [ s * t for s, t in zip(channel, tukey_window(len(channel), 0.5)) ] autocorrelated = [ sum([s1 * s2 for s1, s2 in zip(windowed, windowed[lag:])]) for lag in range(0, 9) ] assert (len(autocorrelated) == 9) if (autocorrelated[0] != 0.0): lp_coefficients = compute_lp_coefficients(autocorrelated) assert (len(lp_coefficients) == 8) qlp_coefficients4 = quantize_coefficients(lp_coefficients, 4) qlp_coefficients8 = quantize_coefficients(lp_coefficients, 8) residuals4 = compute_residuals(sample_size, qlp_coefficients4[:], channel) residuals8 = compute_residuals(sample_size, qlp_coefficients8[:], channel) residual_block4 = BitstreamRecorder(0) residual_block8 = BitstreamRecorder(0) encode_residuals(residual_block4, options, sample_size, residuals4) encode_residuals(residual_block8, options, sample_size, residuals8) if (residual_block4.bits() < residual_block8.bits()): return (qlp_coefficients4, residual_block4) else: return (qlp_coefficients8, residual_block8) else: qlp_coefficients = [0, 0, 0, 0] residuals = compute_residuals(sample_size, qlp_coefficients[:], channel) residual_block = BitstreamRecorder(0) encode_residuals(residual_block, options, sample_size, residuals) return (qlp_coefficients, residual_block)
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)
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))
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)
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)
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))
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)
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)