#This work is licensed under the
#Creative Commons Attribution-Share Alike 3.0 United States License.
#To view a copy of this license, visit
#http://creativecommons.org/licenses/by-sa/3.0/us/ or send a letter to
#Creative Commons,
#171 Second Street, Suite 300,
#San Francisco, California, 94105, USA.

#INPUT "list of signed residuals, number of residuals, effective bits-per-sample; maximum K, initial history, history multiplier from encoding defaults";
INPUT residual,residual_count,sample_size,encoding_parameters;
OUTPUT "block of residual data, size of residual data block in bits";
VAR encoding_parameters "encoding parameters";
VAR sample_size "sample size";
VAR residual "residual";
VAR unsigned_ "unsigned";
VAR residual_count "residual count";
VAR residual_block "residual block";
VAR residual_block_size "residual block size";
VAR maximum_K "maximum K";
VAR initial_history "initial history";
VAR history_multiplier "history multiplier";
VAR history "history";
VAR sign_modifier "sign modifier";
VAR zeroes "zero residuals count";
FUNC residual_overflow "raise residual overflow exception";
FUNC write_residual "write residual" "alac:write_residual";
initial_history,history_multiplier,maximum_K <- encoding_parameters;
history <- initial_history;
sign_modifier <- 0;
for i <- 0 to residual_count {
    if residual[i] >= 0 /*add sign bit*/ {
        unsigned_[i] <- residual[i] * 2;
    } else {
        unsigned_[i] <- (-residual[i] * 2) - 1;
    }
    if unsigned_[i] >= 2 ^ sample_size {
       residual_overflow();
    }
    kappa <- floor(log 2 {(floor(history / 2 ^ 9) + 3)});
    if kappa > maximum_K {
       kappa <- maximum_K;
    }
    write_residual(unsigned_[i] - sign_modifier, kappa, sample_size);
    sign_modifier <- 0;
    if unsigned_[i] <= 65535 {
        history <- history +
                   (unsigned_[i] * history_multiplier) -
                   floor(frac(history * history_multiplier, 2 ^ 9));
        if history < 128 and i < residual_count {
            kappa <- 7 - floor(log 2 {history}) + floor((history + 16) / 64);
            if kappa > maximum_K {
                kappa <- maximum_K;
            }
            zeroes <- 0;
            while i < residual_count and residual[i] == 0 {
                zeroes <- zeroes + 1;
                i <- i + 1;
            }
            write_residual(zeroes, kappa, 16);
            if zeroes < 65535 {
                sign_modifier <- 1;
            }
            history <- 0;
        }
    } else {
        history <- 65535;
    }
}
return residual_block,residual_block_size;
