#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 channel, block_samples,decorrelation_term,decorrelation_delta,decorrelation_weight,decorrelation_samples;
OUTPUT correlated, decorrelation_weight,decorrelation_samples;
VAR channel "channel";
VAR block_samples "block samples";
VAR correlated "correlated";
VAR decorrelation_term "term";
VAR decorrelation_delta "delta";
VAR decorrelation_weight "weight";
VAR decorrelation_samples "samples";
VAR temp "temp";
FUNC invalid_term "invalid correlation term";
FUNC update_weight "update weight" "wavpack:update_weight";
if 17 <= decorrelation_term <= 18 {
    channel[-2] <- decorrelation_samples[1];
    channel[-1] <- decorrelation_samples[0];
    for i <- 0 to block_samples {
        if decorrelation_term == 18 {
            temp[i] <- floor((3 * channel[i - 1] - channel[i - 2]) / 2);
        } elif decorrelation_term == 17 {
            temp[i] <- 2 * channel[i - 1] - channel[i - 2];
        }
        correlated[i] <-
            channel[i] - floor((decorrelation_weight *
                                temp[i] + 2 ^ 9) / 2 ^ 10);
        decorrelation_weight <- update_weight(temp[i],
                                              correlated[i],
                                              decorrelation_weight,
                                              decorrelation_delta);
    }
    decorrelation_samples[0] <- channel[block_samples - 2];
    decorrelation_samples[1] <- channel[block_samples - 1];
} elif 1 <= decorrelation_term <= 8 {
    for i <- 0 to decorrelation_term {
        channel[i - decorrelation_term] <-
            decorrelation_samples[i];
    }
    for i <- 0 to block_samples {
        correlated[i] <-
            channel[i] - floor((decorrelation_weight *
                                channel[i - decorrelation_term] +
                                2 ^ 9) / 2 ^ 10);
        decorrelation_weight <- update_weight(channel[i - decorrelation_term],
                                              correlated[i],
                                              decorrelation_weight,
                                              decorrelation_delta);
    }
    for i <- 0 to decorrelation_term {
        decorrelation_samples[i] <-
            channel[block_samples - decorrelation_term + i];
    }
} else {
    invalid_term();
}
return correlated,decorrelation_weight,decorrelation_samples;
