#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 "\"mdat\" atom data",sample_size,sample_count,decoding_parameters;
OUTPUT "a list of signed residual integers";
VAR sample_count "sample count";
VAR sample_size "sample size";
VAR decoding_parameters "decoding parameters";
VAR initial_history "initial history";
VAR maximum_K "maximum K";
VAR history_multiplier "history multiplier";
VAR history "history";
VAR zero_residuals "zero residuals count";
VAR sign_modifier "sign modifier";
VAR residual "residual";
FUNC read_residual "read residual" "alac:read_residual";
initial_history,history_multiplier,maximum_K <- decoding_parameters;
history <- initial_history;
sign_modifier <- 0;
for i <- 0 to sample_count {
    kappa <- floor(log 2 {(floor(history / 2 ^ 9) + 3)});
    if kappa > maximum_K {
        kappa <- maximum_K;
    }
    r[i] <- read_residual(kappa, sample_size);
    u[i] <- r[i] + sign_modifier;
    sign_modifier <- 0;
    if (u[i] % 2) == 0 /*apply sign bit*/ {
        residual[i] <- u[i] / 2;
    } else  {
        residual[i] <- -((u[i] + 1) / 2);
    }
    if u[i] <= 65535 /*update history*/ {
        history <- history +
                   (u[i] * history_multiplier) -
                   floor(frac(history * history_multiplier, 2 ^ 9));
        if history < 128 and (i + 1) < sample_count {
            /*generate run of 0 residuals if history gets too small*/;
            kappa <- 7 - floor(log 2 {history}) + floor((history + 16) / 64);
            if kappa > maximum_K {
                kappa <- maximum_K;
            }
            zero_residuals <- read_residual(kappa, 16);
            for j <- 0 to zero_residuals {
                residual[i + j + 1] <- 0;
            }
            i <- i + j;
            history <- 0;
            if zero_residuals <= 65535 {
                sign_modifier <- 1;
            }
        }
    } else {
        history <- 65535;
    }
}
return residual;
