#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,
LPC_order,QLP_precision,QLP_shift,QLP_coeff;
OUTPUT "an LPC subframe, its length in bits";
VAR encoding_parameters "encoding parameters";
VAR sample_count "sample count";
VAR sample "sample";
VAR residual "residual";
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";
FUNC encode_residual "encode residual block" "flac:write_residual_block";
for i <- 0 to LPC_order /*write warm-up samples*/ {
    sample[i] -> write bits_per_sample signed;
}
(QLP_precision - 1) -> write 4 unsigned;
QLP_shift -> write 5 signed;
for i <- 0 to LPC_order {
    QLP_coeff[i] -> write QLP_precision signed;
}
for i <- 0 to sample_count - LPC_order /*calculate signed residuals*/ {
    residual[i] <- sample[i + LPC_order] -
        floor(frac(sum j <- 0 to LPC_order - 1
                   {QLP_coeff[j] * sample[i + LPC_order - j - 1]},
                   2 ^ QLP_shift));
}
encode_residual(encoding_parameters, sample_count, LPC_order, residual);
return lpc_subframe,lpc_subframe_length;
