#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 encoding_parameters, sample, sample_count, bits_per_sample;
OUTPUT "an LPC subframe, its length in bits and predictor order";
VAR encoding_parameters "encoding parameters";
VAR sample_count "sample count";
VAR sample "sample";
VAR bits_per_sample "bits-per-sample";
VAR LPC_order "LPC order";
VAR QLP_shift "QLP shift needed";
VAR QLP_precision "QLP precision";
VAR QLP_coeff "QLP coefficient";
VAR lpc_subframe "LPC subframe";
VAR lpc_subframe_length "LPC length";
VAR windowed "windowed";
VAR autocorrelated "autocorrelated";
VAR max_LPC_order "maximum LPC order";
VAR LP_coeff "LP coefficient";
VAR error "error";
VAR best_subframe_length "best LPC length";
VAR best_order "best LPC order";
VAR exhaustive_model_search "exhaustive model search";
FUNC calculate_qlp_precision "calculate QLP precision" "flac:calculate_qlp_precision";
FUNC window "window samples" "flac:window";
FUNC autocorrelate "autocorrelate samples" "flac:autocorrelate";
FUNC write_lpc_subframe "write LPC subframe" "flac:write_lpc_subframe";
FUNC compute_lp_coeffs "compute LP coefficients" "flac:compute_lp_coeffs";
FUNC estimate_best_order "estimate best order" "flac:estimate_best_order";
FUNC quantize_coeffs "quantize coefficients" "flac:quantize_lp_coeffs";
max_LPC_order,exhaustive_model_search <- encoding_parameters;
QLP_precision <- calculate_qlp_precision(sample_count);
windowed <- window(sample, sample_count);
autocorrelated <- autocorrelate(windowed, sample_count, max_LPC_order);
LP_coeff,error <- compute_lp_coeffs(autocorrelated, max_LPC_order);
if not exhaustive_model_search {
    LPC_order <- estimate_best_order(error,
                                     sample_count,
                                     QLP_precision,
                                     max_LPC_order);
    QLP_coeff,QLP_shift <- quantize_coeffs(LPC_order,
                                           LP_coeff,
                                           QLP_precision);
    lpc_subframe,lpc_subframe_length <-
    write_lpc_subframe(encoding_parameters,
                       sample,
                       sample_count,
                       bits_per_sample,
                       LPC_order,
                       QLP_precision,
                       QLP_shift,
                       QLP_coeff);
    return lpc_subframe,lpc_subframe_length,LPC_order;
} else {
    best_subframe_length <- infinity;
    for o <- 1 to max_LPC_order + 1 /*try all LPC orders*/ {
        QLP_coeff[o],QLP_shift[o] <- quantize_coeffs(o,
                                                     LP_coeff,
                                                     QLP_precision);
        lpc_subframe[o],lpc_subframe_length[o] <-
        write_lpc_subframe(encoding_parameters,
                           sample,
                           sample_count,
                           bits_per_sample,
                           o,
                           QLP_precision,
                           QLP_shift[o],
                           QLP_coeff[o]);
        if lpc_subframe_length[o] < best_subframe_length {
            best_order <- o;
            best_subframe_length <- lpc_subframe_length[o];
        }
    }
    return lpc_subframe[best_order],
           best_subframe_length,
           best_order;
}
