local char, byte, floor, band, rshift = string.char, string.byte, math.floor, bit32.band, bit32.arshift local PREC = 10 local PREC_POW = 2 ^ PREC local PREC_POW_HALF = 2 ^ (PREC - 1) local STRENGTH_MIN = 2 ^ (PREC - 8 + 1) local function make_predictor() local charge, strength, previous_bit = 0, 0, false return function(current_bit) local target = current_bit and 127 or -128 local next_charge = charge + floor((strength * (target - charge) + PREC_POW_HALF) / PREC_POW) if next_charge == charge and next_charge ~= target then next_charge = next_charge + (current_bit and 1 or -1) end local z = current_bit == previous_bit and PREC_POW - 1 or 0 local next_strength = strength if next_strength ~= z then next_strength = next_strength + (current_bit == previous_bit and 1 or -1) end if next_strength < STRENGTH_MIN then next_strength = STRENGTH_MIN end charge, strength, previous_bit = next_charge, next_strength, current_bit return charge end end local function make_dec() local predictor = make_predictor() local low_pass_charge = 0 local previous_charge, previous_bit = 0, false return function (input) local output, output_n = {}, 0 for i = 1, #input do local input_byte = byte(input, i) for _ = 1, 8 do local current_bit = band(input_byte, 1) ~= 0 local charge = predictor(current_bit) local antijerk = charge if current_bit ~= previous_bit then antijerk = floor((charge + previous_charge + 1) / 2) end previous_charge, previous_bit = charge, current_bit low_pass_charge = low_pass_charge + floor(((antijerk - low_pass_charge) * 140 + 0x80) / 256) output_n = output_n + 1 output[output_n] = low_pass_charge input_byte = rshift(input_byte, 1) end end return output end end local function make_truebit_dec(max_amp) max_amp = max_amp or 127 return function (input) local output, output_n = {}, 0 for i = 1, #input do local input_byte = byte(input, i) for _ = 1, 8 do local bit_is_1 = band(input_byte, 1) ~= 0 output_n = output_n + 1 output[output_n] = bit_is_1 and max_amp or -max_amp input_byte = rshift(input_byte, 1) end end return output end end return { make_dec = make_dec, make_truebit_dec = make_truebit_dec }