#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 "MLP frame",restart_header,decoding_parameters;
OUTPUT shifted,restart_header,decoding_parameters;
VAR restart_header "restart header";
VAR decoding_parameters "decoding parameters";
VAR substream_count "substream count";
VAR checkdata_present "checkdata present";
VAR substream_end "substream end";
VAR parity "parity";
VAR crc8 "CRC-8";
VAR output "output";
VAR total_samples "total samples";
VAR max_matrix_channel "max matrix channel";
VAR noise_shift "noise shift";
VAR noise_gen_seed "noise gen seed";
VAR bypassed_lsbs "bypassed LSBs";
VAR quant_step_size "quant step size";
VAR matrix_count "matrix count";
VAR matrix_params "matrix parameters";
VAR shifted "shifted";
VAR output_shift "output shift";
VAR unified "unified";
FUNC read_major_sync "read major sync" "mlp:readmajorsync";
FUNC rematrix_channels "rematrix channels" "mlp:rematrixing";
FUNC read_substream_info "read substream info" "mlp:read_substream_info";
FUNC decode_substream "decode substream" "mlp:decode_substream";
FUNC apply_output_shifts "apply output shifts" "mlp:output_shifts";
FUNC verify_parity "verify parity" "mlp:verify_parity";
FUNC verify_crc "verify checksum" "mlp:verify_crc";
FUNC unify_substreams "unify substreams" "mlp:unify_substreams";
substream_count <- read_major_sync(substream_count);
assert 1 <= substream_count <= 2;
for s <- 0 to substream_count {
    checkdata_present[s],substream_end[s] <- read_substream_info();
}
output[0],total_samples[0],
bypassed_lsbs[0],restart_header[0],decoding_parameters[0] <-
    decode_substream(restart_header[0],decoding_parameters[0]);
if checkdata_present[0] == 1 {
    verify_parity(read 8 unsigned);
    verify_crc(read 8 unsigned);
}
if substream_count == 1 {
    max_matrix_channel[0],
    noise_shift[0],
    noise_gen_seed[0] <- restart_header[0];
    matrix_count[0],
    matrix_params[0],
    output_shift[0],
    quant_step_size[0] <- decoding_parameters[0];
    output[0],noise_gen_seed[0] <- rematrix_channels(
        total_samples[0],
        quant_step_size[0],
        noise_shift[0],
        noise_gen_seed[0],
        output[0],
        max_matrix_channel[0],
        matrix_count[0],
        matrix_params[0],
        bypassed_lsbs[0]);
    shifted <- apply_output_shifts(total_samples[0],
                                   max_matrix_channel[0],
                                   output_shift[0],
                                   output[0]);
} else {
    output[1],total_samples[1],
    bypassed_lsbs[1],restart_header[1],decoding_parameters[1] <-
        decode_substream(restart_header[1],decoding_parameters[1]);
    if checkdata_present[1] == 1 {
        verify_parity(read 8 unsigned);
        verify_crc(read 8 unsigned);
    }
    unified <- unify_substreams(restart_header[0],
                                output[0],
                                total_samples[0],
                                restart_header[1],
                                output[1],
                                total_samples[1]);
    max_matrix_channel[1],
    noise_shift[1],
    noise_gen_seed[1],
    max_matrix_channel[1] <- restart_header[1];
    matrix_count[1],
    matrix_params[1],
    output_shift[1],
    quant_step_size[1] <- decoding_parameters[1];
    unified,noise_gen_seed[1] <- rematrix_channels(
        total_samples[1],
        quant_step_size[1],
        noise_shift[1],
        noise_gen_seed[1],
        unified,
        max_matrix_channel[1],
        matrix_count[1],
        matrix_params[1],
        bypassed_lsbs[1]);
    shifted <- apply_output_shifts(total_samples[1],
                                   max_matrix_channel[1],
                                   output_shift[1],
                                   unified);
}
return shifted,restart_header,decoding_parameters;