src/libFLAC/lpc.c : Include <inttypes.h> so compiling debug version works.
[platform/upstream/flac.git] / src / libFLAC / lpc.c
index ed0e091..f5eaf22 100644 (file)
@@ -1,5 +1,5 @@
 /* libFLAC - Free Lossless Audio Codec library
- * Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007  Josh Coalson
+ * Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007,2008,2009  Josh Coalson
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 #endif
 
 #include <math.h>
+#include <inttypes.h>
 #include "FLAC/assert.h"
 #include "FLAC/format.h"
 #include "private/bitmath.h"
 #include "private/lpc.h"
+#include "private/macros.h"
 #if defined DEBUG || defined FLAC__OVERFLOW_DETECT || defined FLAC__OVERFLOW_DETECT_VERBOSE
 #include <stdio.h>
 #endif
 
+/* OPT: #undef'ing this may improve the speed on some architectures */
+#define FLAC__LPC_UNROLLED_FILTER_LOOPS
+
 #ifndef FLAC__INTEGER_ONLY_LIBRARY
 
 #ifndef M_LN2
 #define M_LN2 0.69314718055994530942
 #endif
 
-void FLAC__lpc_window_data(const FLAC__real in[], const FLAC__real window[], FLAC__real out[], unsigned data_len)
+#if !defined(HAVE_LROUND)
+#if defined(_MSC_VER)
+#include <float.h>
+#define copysign _copysign
+#elif defined(__GNUC__)
+#define copysign __builtin_copysign
+#endif
+static inline long int lround(double x) {
+    return (long)(x + copysign (0.5, x));
+}
+//If this fails, we are in the precence of a mid 90's compiler..move along...
+#endif
+
+void FLAC__lpc_window_data(const FLAC__int32 in[], const FLAC__real window[], FLAC__real out[], unsigned data_len)
 {
        unsigned i;
        for(i = 0; i < data_len; i++)
@@ -108,7 +126,7 @@ void FLAC__lpc_compute_autocorrelation(const FLAC__real data[], unsigned data_le
 void FLAC__lpc_compute_lp_coefficients(const FLAC__real autoc[], unsigned *max_order, FLAC__real lp_coeff[][FLAC__MAX_LPC_ORDER], FLAC__double error[])
 {
        unsigned i, j;
-       FLAC__double r, err, ref[FLAC__MAX_LPC_ORDER], lpc[FLAC__MAX_LPC_ORDER];
+       FLAC__double r, err, lpc[FLAC__MAX_LPC_ORDER];
 
        FLAC__ASSERT(0 != max_order);
        FLAC__ASSERT(0 < *max_order);
@@ -122,7 +140,6 @@ void FLAC__lpc_compute_lp_coefficients(const FLAC__real autoc[], unsigned *max_o
                r = -autoc[i+1];
                for(j = 0; j < i; j++)
                        r -= lpc[j] * autoc[i-j];
-               ref[i] = (r/=err);
 
                /* Update LPC coefficients and total error. */
                lpc[i]=r;
@@ -196,14 +213,8 @@ int FLAC__lpc_quantize_coefficients(const FLAC__real lp_coeff[], unsigned order,
                FLAC__int32 q;
                for(i = 0; i < order; i++) {
                        error += lp_coeff[i] * (1 << *shift);
-#if 1 /* unfortunately lround() is C99 */
-                       if(error >= 0.0)
-                               q = (FLAC__int32)(error + 0.5);
-                       else
-                               q = (FLAC__int32)(error - 0.5);
-#else
                        q = lround(error);
-#endif
+
 #ifdef FLAC__OVERFLOW_DETECT
                        if(q > qmax+1) /* we expect q==qmax+1 occasionally due to rounding */
                                fprintf(stderr,"FLAC__lpc_quantize_coefficients: quantizer overflow: q>qmax %d>%d shift=%d cmax=%f precision=%u lpc[%u]=%f\n",q,qmax,*shift,cmax,precision+1,i,lp_coeff[i]);
@@ -231,14 +242,7 @@ int FLAC__lpc_quantize_coefficients(const FLAC__real lp_coeff[], unsigned order,
 #endif
                for(i = 0; i < order; i++) {
                        error += lp_coeff[i] / (1 << nshift);
-#if 1 /* unfortunately lround() is C99 */
-                       if(error >= 0.0)
-                               q = (FLAC__int32)(error + 0.5);
-                       else
-                               q = (FLAC__int32)(error - 0.5);
-#else
                        q = lround(error);
-#endif
 #ifdef FLAC__OVERFLOW_DETECT
                        if(q > qmax+1) /* we expect q==qmax+1 occasionally due to rounding */
                                fprintf(stderr,"FLAC__lpc_quantize_coefficients: quantizer overflow: q>qmax %d>%d shift=%d cmax=%f precision=%u lpc[%u]=%f\n",q,qmax,*shift,cmax,precision+1,i,lp_coeff[i]);
@@ -259,10 +263,9 @@ int FLAC__lpc_quantize_coefficients(const FLAC__real lp_coeff[], unsigned order,
 }
 
 void FLAC__lpc_compute_residual_from_qlp_coefficients(const FLAC__int32 *data, unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[])
+#if defined(FLAC__OVERFLOW_DETECT) || !defined(FLAC__LPC_UNROLLED_FILTER_LOOPS)
 {
-#ifdef FLAC__OVERFLOW_DETECT
        FLAC__int64 sumo;
-#endif
        unsigned i, j;
        FLAC__int32 sum;
        const FLAC__int32 *history;
@@ -276,23 +279,13 @@ void FLAC__lpc_compute_residual_from_qlp_coefficients(const FLAC__int32 *data, u
        FLAC__ASSERT(order > 0);
 
        for(i = 0; i < data_len; i++) {
-#ifdef FLAC__OVERFLOW_DETECT
                sumo = 0;
-#endif
                sum = 0;
                history = data;
                for(j = 0; j < order; j++) {
                        sum += qlp_coeff[j] * (*(--history));
-#ifdef FLAC__OVERFLOW_DETECT
                        sumo += (FLAC__int64)qlp_coeff[j] * (FLAC__int64)(*history);
-#if defined _MSC_VER
-                       if(sumo > 2147483647I64 || sumo < -2147483648I64)
-                               fprintf(stderr,"FLAC__lpc_compute_residual_from_qlp_coefficients: OVERFLOW, i=%u, j=%u, c=%d, d=%d, sumo=%I64d\n",i,j,qlp_coeff[j],*history,sumo);
-#else
-                       if(sumo > 2147483647ll || sumo < -2147483648ll)
-                               fprintf(stderr,"FLAC__lpc_compute_residual_from_qlp_coefficients: OVERFLOW, i=%u, j=%u, c=%d, d=%d, sumo=%lld\n",i,j,qlp_coeff[j],*history,(long long)sumo);
-#endif
-#endif
+                               fprintf(stderr,"FLAC__lpc_compute_residual_from_qlp_coefficients: OVERFLOW, i=%u, j=%u, c=%d, d=%d, sumo=%" PRId64 "\n",i,j,qlp_coeff[j],*history,sumo);
                }
                *(residual++) = *(data++) - (sum >> lp_quantization);
        }
@@ -306,8 +299,231 @@ void FLAC__lpc_compute_residual_from_qlp_coefficients(const FLAC__int32 *data, u
        }
        */
 }
+#else /* fully unrolled version for normal use */
+{
+       int i;
+       FLAC__int32 sum;
+
+       FLAC__ASSERT(order > 0);
+       FLAC__ASSERT(order <= 32);
+
+       /*
+        * We do unique versions up to 12th order since that's the subset limit.
+        * Also they are roughly ordered to match frequency of occurrence to
+        * minimize branching.
+        */
+       if(order <= 12) {
+               if(order > 8) {
+                       if(order > 10) {
+                               if(order == 12) {
+                                       for(i = 0; i < (int)data_len; i++) {
+                                               sum = 0;
+                                               sum += qlp_coeff[11] * data[i-12];
+                                               sum += qlp_coeff[10] * data[i-11];
+                                               sum += qlp_coeff[9] * data[i-10];
+                                               sum += qlp_coeff[8] * data[i-9];
+                                               sum += qlp_coeff[7] * data[i-8];
+                                               sum += qlp_coeff[6] * data[i-7];
+                                               sum += qlp_coeff[5] * data[i-6];
+                                               sum += qlp_coeff[4] * data[i-5];
+                                               sum += qlp_coeff[3] * data[i-4];
+                                               sum += qlp_coeff[2] * data[i-3];
+                                               sum += qlp_coeff[1] * data[i-2];
+                                               sum += qlp_coeff[0] * data[i-1];
+                                               residual[i] = data[i] - (sum >> lp_quantization);
+                                       }
+                               }
+                               else { /* order == 11 */
+                                       for(i = 0; i < (int)data_len; i++) {
+                                               sum = 0;
+                                               sum += qlp_coeff[10] * data[i-11];
+                                               sum += qlp_coeff[9] * data[i-10];
+                                               sum += qlp_coeff[8] * data[i-9];
+                                               sum += qlp_coeff[7] * data[i-8];
+                                               sum += qlp_coeff[6] * data[i-7];
+                                               sum += qlp_coeff[5] * data[i-6];
+                                               sum += qlp_coeff[4] * data[i-5];
+                                               sum += qlp_coeff[3] * data[i-4];
+                                               sum += qlp_coeff[2] * data[i-3];
+                                               sum += qlp_coeff[1] * data[i-2];
+                                               sum += qlp_coeff[0] * data[i-1];
+                                               residual[i] = data[i] - (sum >> lp_quantization);
+                                       }
+                               }
+                       }
+                       else {
+                               if(order == 10) {
+                                       for(i = 0; i < (int)data_len; i++) {
+                                               sum = 0;
+                                               sum += qlp_coeff[9] * data[i-10];
+                                               sum += qlp_coeff[8] * data[i-9];
+                                               sum += qlp_coeff[7] * data[i-8];
+                                               sum += qlp_coeff[6] * data[i-7];
+                                               sum += qlp_coeff[5] * data[i-6];
+                                               sum += qlp_coeff[4] * data[i-5];
+                                               sum += qlp_coeff[3] * data[i-4];
+                                               sum += qlp_coeff[2] * data[i-3];
+                                               sum += qlp_coeff[1] * data[i-2];
+                                               sum += qlp_coeff[0] * data[i-1];
+                                               residual[i] = data[i] - (sum >> lp_quantization);
+                                       }
+                               }
+                               else { /* order == 9 */
+                                       for(i = 0; i < (int)data_len; i++) {
+                                               sum = 0;
+                                               sum += qlp_coeff[8] * data[i-9];
+                                               sum += qlp_coeff[7] * data[i-8];
+                                               sum += qlp_coeff[6] * data[i-7];
+                                               sum += qlp_coeff[5] * data[i-6];
+                                               sum += qlp_coeff[4] * data[i-5];
+                                               sum += qlp_coeff[3] * data[i-4];
+                                               sum += qlp_coeff[2] * data[i-3];
+                                               sum += qlp_coeff[1] * data[i-2];
+                                               sum += qlp_coeff[0] * data[i-1];
+                                               residual[i] = data[i] - (sum >> lp_quantization);
+                                       }
+                               }
+                       }
+               }
+               else if(order > 4) {
+                       if(order > 6) {
+                               if(order == 8) {
+                                       for(i = 0; i < (int)data_len; i++) {
+                                               sum = 0;
+                                               sum += qlp_coeff[7] * data[i-8];
+                                               sum += qlp_coeff[6] * data[i-7];
+                                               sum += qlp_coeff[5] * data[i-6];
+                                               sum += qlp_coeff[4] * data[i-5];
+                                               sum += qlp_coeff[3] * data[i-4];
+                                               sum += qlp_coeff[2] * data[i-3];
+                                               sum += qlp_coeff[1] * data[i-2];
+                                               sum += qlp_coeff[0] * data[i-1];
+                                               residual[i] = data[i] - (sum >> lp_quantization);
+                                       }
+                               }
+                               else { /* order == 7 */
+                                       for(i = 0; i < (int)data_len; i++) {
+                                               sum = 0;
+                                               sum += qlp_coeff[6] * data[i-7];
+                                               sum += qlp_coeff[5] * data[i-6];
+                                               sum += qlp_coeff[4] * data[i-5];
+                                               sum += qlp_coeff[3] * data[i-4];
+                                               sum += qlp_coeff[2] * data[i-3];
+                                               sum += qlp_coeff[1] * data[i-2];
+                                               sum += qlp_coeff[0] * data[i-1];
+                                               residual[i] = data[i] - (sum >> lp_quantization);
+                                       }
+                               }
+                       }
+                       else {
+                               if(order == 6) {
+                                       for(i = 0; i < (int)data_len; i++) {
+                                               sum = 0;
+                                               sum += qlp_coeff[5] * data[i-6];
+                                               sum += qlp_coeff[4] * data[i-5];
+                                               sum += qlp_coeff[3] * data[i-4];
+                                               sum += qlp_coeff[2] * data[i-3];
+                                               sum += qlp_coeff[1] * data[i-2];
+                                               sum += qlp_coeff[0] * data[i-1];
+                                               residual[i] = data[i] - (sum >> lp_quantization);
+                                       }
+                               }
+                               else { /* order == 5 */
+                                       for(i = 0; i < (int)data_len; i++) {
+                                               sum = 0;
+                                               sum += qlp_coeff[4] * data[i-5];
+                                               sum += qlp_coeff[3] * data[i-4];
+                                               sum += qlp_coeff[2] * data[i-3];
+                                               sum += qlp_coeff[1] * data[i-2];
+                                               sum += qlp_coeff[0] * data[i-1];
+                                               residual[i] = data[i] - (sum >> lp_quantization);
+                                       }
+                               }
+                       }
+               }
+               else {
+                       if(order > 2) {
+                               if(order == 4) {
+                                       for(i = 0; i < (int)data_len; i++) {
+                                               sum = 0;
+                                               sum += qlp_coeff[3] * data[i-4];
+                                               sum += qlp_coeff[2] * data[i-3];
+                                               sum += qlp_coeff[1] * data[i-2];
+                                               sum += qlp_coeff[0] * data[i-1];
+                                               residual[i] = data[i] - (sum >> lp_quantization);
+                                       }
+                               }
+                               else { /* order == 3 */
+                                       for(i = 0; i < (int)data_len; i++) {
+                                               sum = 0;
+                                               sum += qlp_coeff[2] * data[i-3];
+                                               sum += qlp_coeff[1] * data[i-2];
+                                               sum += qlp_coeff[0] * data[i-1];
+                                               residual[i] = data[i] - (sum >> lp_quantization);
+                                       }
+                               }
+                       }
+                       else {
+                               if(order == 2) {
+                                       for(i = 0; i < (int)data_len; i++) {
+                                               sum = 0;
+                                               sum += qlp_coeff[1] * data[i-2];
+                                               sum += qlp_coeff[0] * data[i-1];
+                                               residual[i] = data[i] - (sum >> lp_quantization);
+                                       }
+                               }
+                               else { /* order == 1 */
+                                       for(i = 0; i < (int)data_len; i++)
+                                               residual[i] = data[i] - ((qlp_coeff[0] * data[i-1]) >> lp_quantization);
+                               }
+                       }
+               }
+       }
+       else { /* order > 12 */
+               for(i = 0; i < (int)data_len; i++) {
+                       sum = 0;
+                       switch(order) {
+                               case 32: sum += qlp_coeff[31] * data[i-32];
+                               case 31: sum += qlp_coeff[30] * data[i-31];
+                               case 30: sum += qlp_coeff[29] * data[i-30];
+                               case 29: sum += qlp_coeff[28] * data[i-29];
+                               case 28: sum += qlp_coeff[27] * data[i-28];
+                               case 27: sum += qlp_coeff[26] * data[i-27];
+                               case 26: sum += qlp_coeff[25] * data[i-26];
+                               case 25: sum += qlp_coeff[24] * data[i-25];
+                               case 24: sum += qlp_coeff[23] * data[i-24];
+                               case 23: sum += qlp_coeff[22] * data[i-23];
+                               case 22: sum += qlp_coeff[21] * data[i-22];
+                               case 21: sum += qlp_coeff[20] * data[i-21];
+                               case 20: sum += qlp_coeff[19] * data[i-20];
+                               case 19: sum += qlp_coeff[18] * data[i-19];
+                               case 18: sum += qlp_coeff[17] * data[i-18];
+                               case 17: sum += qlp_coeff[16] * data[i-17];
+                               case 16: sum += qlp_coeff[15] * data[i-16];
+                               case 15: sum += qlp_coeff[14] * data[i-15];
+                               case 14: sum += qlp_coeff[13] * data[i-14];
+                               case 13: sum += qlp_coeff[12] * data[i-13];
+                                        sum += qlp_coeff[11] * data[i-12];
+                                        sum += qlp_coeff[10] * data[i-11];
+                                        sum += qlp_coeff[ 9] * data[i-10];
+                                        sum += qlp_coeff[ 8] * data[i- 9];
+                                        sum += qlp_coeff[ 7] * data[i- 8];
+                                        sum += qlp_coeff[ 6] * data[i- 7];
+                                        sum += qlp_coeff[ 5] * data[i- 6];
+                                        sum += qlp_coeff[ 4] * data[i- 5];
+                                        sum += qlp_coeff[ 3] * data[i- 4];
+                                        sum += qlp_coeff[ 2] * data[i- 3];
+                                        sum += qlp_coeff[ 1] * data[i- 2];
+                                        sum += qlp_coeff[ 0] * data[i- 1];
+                       }
+                       residual[i] = data[i] - (sum >> lp_quantization);
+               }
+       }
+}
+#endif
 
 void FLAC__lpc_compute_residual_from_qlp_coefficients_wide(const FLAC__int32 *data, unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[])
+#if defined(FLAC__OVERFLOW_DETECT) || !defined(FLAC__LPC_UNROLLED_FILTER_LOOPS)
 {
        unsigned i, j;
        FLAC__int64 sum;
@@ -326,35 +542,246 @@ void FLAC__lpc_compute_residual_from_qlp_coefficients_wide(const FLAC__int32 *da
                history = data;
                for(j = 0; j < order; j++)
                        sum += (FLAC__int64)qlp_coeff[j] * (FLAC__int64)(*(--history));
-#ifdef FLAC__OVERFLOW_DETECT
                if(FLAC__bitmath_silog2_wide(sum >> lp_quantization) > 32) {
-#if defined _MSC_VER
-                       fprintf(stderr,"FLAC__lpc_compute_residual_from_qlp_coefficients_wide: OVERFLOW, i=%u, sum=%I64d\n", i, sum >> lp_quantization);
-#else
-                       fprintf(stderr,"FLAC__lpc_compute_residual_from_qlp_coefficients_wide: OVERFLOW, i=%u, sum=%lld\n", i, (long long)(sum >> lp_quantization));
-#endif
+                       fprintf(stderr,"FLAC__lpc_compute_residual_from_qlp_coefficients_wide: OVERFLOW, i=%u, sum=%" PRId64 "\n", i, (sum >> lp_quantization));
                        break;
                }
                if(FLAC__bitmath_silog2_wide((FLAC__int64)(*data) - (sum >> lp_quantization)) > 32) {
-#if defined _MSC_VER
-                       fprintf(stderr,"FLAC__lpc_compute_residual_from_qlp_coefficients_wide: OVERFLOW, i=%u, data=%d, sum=%I64d, residual=%I64d\n", i, *data, sum >> lp_quantization, (FLAC__int64)(*data) - (sum >> lp_quantization));
-#else
-                       fprintf(stderr,"FLAC__lpc_compute_residual_from_qlp_coefficients_wide: OVERFLOW, i=%u, data=%d, sum=%lld, residual=%lld\n", i, *data, (long long)(sum >> lp_quantization), (long long)((FLAC__int64)(*data) - (sum >> lp_quantization)));
-#endif
+                       fprintf(stderr,"FLAC__lpc_compute_residual_from_qlp_coefficients_wide: OVERFLOW, i=%u, data=%d, sum=%" PRId64 ", residual=%" PRId64 "\n", i, *data, (long long)(sum >> lp_quantization), ((FLAC__int64)(*data) - (sum >> lp_quantization)));
                        break;
                }
-#endif
                *(residual++) = *(data++) - (FLAC__int32)(sum >> lp_quantization);
        }
 }
+#else /* fully unrolled version for normal use */
+{
+       int i;
+       FLAC__int64 sum;
+
+       FLAC__ASSERT(order > 0);
+       FLAC__ASSERT(order <= 32);
+
+       /*
+        * We do unique versions up to 12th order since that's the subset limit.
+        * Also they are roughly ordered to match frequency of occurrence to
+        * minimize branching.
+        */
+       if(order <= 12) {
+               if(order > 8) {
+                       if(order > 10) {
+                               if(order == 12) {
+                                       for(i = 0; i < (int)data_len; i++) {
+                                               sum = 0;
+                                               sum += qlp_coeff[11] * (FLAC__int64)data[i-12];
+                                               sum += qlp_coeff[10] * (FLAC__int64)data[i-11];
+                                               sum += qlp_coeff[9] * (FLAC__int64)data[i-10];
+                                               sum += qlp_coeff[8] * (FLAC__int64)data[i-9];
+                                               sum += qlp_coeff[7] * (FLAC__int64)data[i-8];
+                                               sum += qlp_coeff[6] * (FLAC__int64)data[i-7];
+                                               sum += qlp_coeff[5] * (FLAC__int64)data[i-6];
+                                               sum += qlp_coeff[4] * (FLAC__int64)data[i-5];
+                                               sum += qlp_coeff[3] * (FLAC__int64)data[i-4];
+                                               sum += qlp_coeff[2] * (FLAC__int64)data[i-3];
+                                               sum += qlp_coeff[1] * (FLAC__int64)data[i-2];
+                                               sum += qlp_coeff[0] * (FLAC__int64)data[i-1];
+                                               residual[i] = data[i] - (FLAC__int32)(sum >> lp_quantization);
+                                       }
+                               }
+                               else { /* order == 11 */
+                                       for(i = 0; i < (int)data_len; i++) {
+                                               sum = 0;
+                                               sum += qlp_coeff[10] * (FLAC__int64)data[i-11];
+                                               sum += qlp_coeff[9] * (FLAC__int64)data[i-10];
+                                               sum += qlp_coeff[8] * (FLAC__int64)data[i-9];
+                                               sum += qlp_coeff[7] * (FLAC__int64)data[i-8];
+                                               sum += qlp_coeff[6] * (FLAC__int64)data[i-7];
+                                               sum += qlp_coeff[5] * (FLAC__int64)data[i-6];
+                                               sum += qlp_coeff[4] * (FLAC__int64)data[i-5];
+                                               sum += qlp_coeff[3] * (FLAC__int64)data[i-4];
+                                               sum += qlp_coeff[2] * (FLAC__int64)data[i-3];
+                                               sum += qlp_coeff[1] * (FLAC__int64)data[i-2];
+                                               sum += qlp_coeff[0] * (FLAC__int64)data[i-1];
+                                               residual[i] = data[i] - (FLAC__int32)(sum >> lp_quantization);
+                                       }
+                               }
+                       }
+                       else {
+                               if(order == 10) {
+                                       for(i = 0; i < (int)data_len; i++) {
+                                               sum = 0;
+                                               sum += qlp_coeff[9] * (FLAC__int64)data[i-10];
+                                               sum += qlp_coeff[8] * (FLAC__int64)data[i-9];
+                                               sum += qlp_coeff[7] * (FLAC__int64)data[i-8];
+                                               sum += qlp_coeff[6] * (FLAC__int64)data[i-7];
+                                               sum += qlp_coeff[5] * (FLAC__int64)data[i-6];
+                                               sum += qlp_coeff[4] * (FLAC__int64)data[i-5];
+                                               sum += qlp_coeff[3] * (FLAC__int64)data[i-4];
+                                               sum += qlp_coeff[2] * (FLAC__int64)data[i-3];
+                                               sum += qlp_coeff[1] * (FLAC__int64)data[i-2];
+                                               sum += qlp_coeff[0] * (FLAC__int64)data[i-1];
+                                               residual[i] = data[i] - (FLAC__int32)(sum >> lp_quantization);
+                                       }
+                               }
+                               else { /* order == 9 */
+                                       for(i = 0; i < (int)data_len; i++) {
+                                               sum = 0;
+                                               sum += qlp_coeff[8] * (FLAC__int64)data[i-9];
+                                               sum += qlp_coeff[7] * (FLAC__int64)data[i-8];
+                                               sum += qlp_coeff[6] * (FLAC__int64)data[i-7];
+                                               sum += qlp_coeff[5] * (FLAC__int64)data[i-6];
+                                               sum += qlp_coeff[4] * (FLAC__int64)data[i-5];
+                                               sum += qlp_coeff[3] * (FLAC__int64)data[i-4];
+                                               sum += qlp_coeff[2] * (FLAC__int64)data[i-3];
+                                               sum += qlp_coeff[1] * (FLAC__int64)data[i-2];
+                                               sum += qlp_coeff[0] * (FLAC__int64)data[i-1];
+                                               residual[i] = data[i] - (FLAC__int32)(sum >> lp_quantization);
+                                       }
+                               }
+                       }
+               }
+               else if(order > 4) {
+                       if(order > 6) {
+                               if(order == 8) {
+                                       for(i = 0; i < (int)data_len; i++) {
+                                               sum = 0;
+                                               sum += qlp_coeff[7] * (FLAC__int64)data[i-8];
+                                               sum += qlp_coeff[6] * (FLAC__int64)data[i-7];
+                                               sum += qlp_coeff[5] * (FLAC__int64)data[i-6];
+                                               sum += qlp_coeff[4] * (FLAC__int64)data[i-5];
+                                               sum += qlp_coeff[3] * (FLAC__int64)data[i-4];
+                                               sum += qlp_coeff[2] * (FLAC__int64)data[i-3];
+                                               sum += qlp_coeff[1] * (FLAC__int64)data[i-2];
+                                               sum += qlp_coeff[0] * (FLAC__int64)data[i-1];
+                                               residual[i] = data[i] - (FLAC__int32)(sum >> lp_quantization);
+                                       }
+                               }
+                               else { /* order == 7 */
+                                       for(i = 0; i < (int)data_len; i++) {
+                                               sum = 0;
+                                               sum += qlp_coeff[6] * (FLAC__int64)data[i-7];
+                                               sum += qlp_coeff[5] * (FLAC__int64)data[i-6];
+                                               sum += qlp_coeff[4] * (FLAC__int64)data[i-5];
+                                               sum += qlp_coeff[3] * (FLAC__int64)data[i-4];
+                                               sum += qlp_coeff[2] * (FLAC__int64)data[i-3];
+                                               sum += qlp_coeff[1] * (FLAC__int64)data[i-2];
+                                               sum += qlp_coeff[0] * (FLAC__int64)data[i-1];
+                                               residual[i] = data[i] - (FLAC__int32)(sum >> lp_quantization);
+                                       }
+                               }
+                       }
+                       else {
+                               if(order == 6) {
+                                       for(i = 0; i < (int)data_len; i++) {
+                                               sum = 0;
+                                               sum += qlp_coeff[5] * (FLAC__int64)data[i-6];
+                                               sum += qlp_coeff[4] * (FLAC__int64)data[i-5];
+                                               sum += qlp_coeff[3] * (FLAC__int64)data[i-4];
+                                               sum += qlp_coeff[2] * (FLAC__int64)data[i-3];
+                                               sum += qlp_coeff[1] * (FLAC__int64)data[i-2];
+                                               sum += qlp_coeff[0] * (FLAC__int64)data[i-1];
+                                               residual[i] = data[i] - (FLAC__int32)(sum >> lp_quantization);
+                                       }
+                               }
+                               else { /* order == 5 */
+                                       for(i = 0; i < (int)data_len; i++) {
+                                               sum = 0;
+                                               sum += qlp_coeff[4] * (FLAC__int64)data[i-5];
+                                               sum += qlp_coeff[3] * (FLAC__int64)data[i-4];
+                                               sum += qlp_coeff[2] * (FLAC__int64)data[i-3];
+                                               sum += qlp_coeff[1] * (FLAC__int64)data[i-2];
+                                               sum += qlp_coeff[0] * (FLAC__int64)data[i-1];
+                                               residual[i] = data[i] - (FLAC__int32)(sum >> lp_quantization);
+                                       }
+                               }
+                       }
+               }
+               else {
+                       if(order > 2) {
+                               if(order == 4) {
+                                       for(i = 0; i < (int)data_len; i++) {
+                                               sum = 0;
+                                               sum += qlp_coeff[3] * (FLAC__int64)data[i-4];
+                                               sum += qlp_coeff[2] * (FLAC__int64)data[i-3];
+                                               sum += qlp_coeff[1] * (FLAC__int64)data[i-2];
+                                               sum += qlp_coeff[0] * (FLAC__int64)data[i-1];
+                                               residual[i] = data[i] - (FLAC__int32)(sum >> lp_quantization);
+                                       }
+                               }
+                               else { /* order == 3 */
+                                       for(i = 0; i < (int)data_len; i++) {
+                                               sum = 0;
+                                               sum += qlp_coeff[2] * (FLAC__int64)data[i-3];
+                                               sum += qlp_coeff[1] * (FLAC__int64)data[i-2];
+                                               sum += qlp_coeff[0] * (FLAC__int64)data[i-1];
+                                               residual[i] = data[i] - (FLAC__int32)(sum >> lp_quantization);
+                                       }
+                               }
+                       }
+                       else {
+                               if(order == 2) {
+                                       for(i = 0; i < (int)data_len; i++) {
+                                               sum = 0;
+                                               sum += qlp_coeff[1] * (FLAC__int64)data[i-2];
+                                               sum += qlp_coeff[0] * (FLAC__int64)data[i-1];
+                                               residual[i] = data[i] - (FLAC__int32)(sum >> lp_quantization);
+                                       }
+                               }
+                               else { /* order == 1 */
+                                       for(i = 0; i < (int)data_len; i++)
+                                               residual[i] = data[i] - (FLAC__int32)((qlp_coeff[0] * (FLAC__int64)data[i-1]) >> lp_quantization);
+                               }
+                       }
+               }
+       }
+       else { /* order > 12 */
+               for(i = 0; i < (int)data_len; i++) {
+                       sum = 0;
+                       switch(order) {
+                               case 32: sum += qlp_coeff[31] * (FLAC__int64)data[i-32];
+                               case 31: sum += qlp_coeff[30] * (FLAC__int64)data[i-31];
+                               case 30: sum += qlp_coeff[29] * (FLAC__int64)data[i-30];
+                               case 29: sum += qlp_coeff[28] * (FLAC__int64)data[i-29];
+                               case 28: sum += qlp_coeff[27] * (FLAC__int64)data[i-28];
+                               case 27: sum += qlp_coeff[26] * (FLAC__int64)data[i-27];
+                               case 26: sum += qlp_coeff[25] * (FLAC__int64)data[i-26];
+                               case 25: sum += qlp_coeff[24] * (FLAC__int64)data[i-25];
+                               case 24: sum += qlp_coeff[23] * (FLAC__int64)data[i-24];
+                               case 23: sum += qlp_coeff[22] * (FLAC__int64)data[i-23];
+                               case 22: sum += qlp_coeff[21] * (FLAC__int64)data[i-22];
+                               case 21: sum += qlp_coeff[20] * (FLAC__int64)data[i-21];
+                               case 20: sum += qlp_coeff[19] * (FLAC__int64)data[i-20];
+                               case 19: sum += qlp_coeff[18] * (FLAC__int64)data[i-19];
+                               case 18: sum += qlp_coeff[17] * (FLAC__int64)data[i-18];
+                               case 17: sum += qlp_coeff[16] * (FLAC__int64)data[i-17];
+                               case 16: sum += qlp_coeff[15] * (FLAC__int64)data[i-16];
+                               case 15: sum += qlp_coeff[14] * (FLAC__int64)data[i-15];
+                               case 14: sum += qlp_coeff[13] * (FLAC__int64)data[i-14];
+                               case 13: sum += qlp_coeff[12] * (FLAC__int64)data[i-13];
+                                        sum += qlp_coeff[11] * (FLAC__int64)data[i-12];
+                                        sum += qlp_coeff[10] * (FLAC__int64)data[i-11];
+                                        sum += qlp_coeff[ 9] * (FLAC__int64)data[i-10];
+                                        sum += qlp_coeff[ 8] * (FLAC__int64)data[i- 9];
+                                        sum += qlp_coeff[ 7] * (FLAC__int64)data[i- 8];
+                                        sum += qlp_coeff[ 6] * (FLAC__int64)data[i- 7];
+                                        sum += qlp_coeff[ 5] * (FLAC__int64)data[i- 6];
+                                        sum += qlp_coeff[ 4] * (FLAC__int64)data[i- 5];
+                                        sum += qlp_coeff[ 3] * (FLAC__int64)data[i- 4];
+                                        sum += qlp_coeff[ 2] * (FLAC__int64)data[i- 3];
+                                        sum += qlp_coeff[ 1] * (FLAC__int64)data[i- 2];
+                                        sum += qlp_coeff[ 0] * (FLAC__int64)data[i- 1];
+                       }
+                       residual[i] = data[i] - (FLAC__int32)(sum >> lp_quantization);
+               }
+       }
+}
+#endif
 
 #endif /* !defined FLAC__INTEGER_ONLY_LIBRARY */
 
 void FLAC__lpc_restore_signal(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[])
+#if defined(FLAC__OVERFLOW_DETECT) || !defined(FLAC__LPC_UNROLLED_FILTER_LOOPS)
 {
-#ifdef FLAC__OVERFLOW_DETECT
        FLAC__int64 sumo;
-#endif
        unsigned i, j;
        FLAC__int32 sum;
        const FLAC__int32 *r = residual, *history;
@@ -368,23 +795,14 @@ void FLAC__lpc_restore_signal(const FLAC__int32 residual[], unsigned data_len, c
        FLAC__ASSERT(order > 0);
 
        for(i = 0; i < data_len; i++) {
-#ifdef FLAC__OVERFLOW_DETECT
                sumo = 0;
-#endif
                sum = 0;
                history = data;
                for(j = 0; j < order; j++) {
                        sum += qlp_coeff[j] * (*(--history));
-#ifdef FLAC__OVERFLOW_DETECT
                        sumo += (FLAC__int64)qlp_coeff[j] * (FLAC__int64)(*history);
-#if defined _MSC_VER
-                       if(sumo > 2147483647I64 || sumo < -2147483648I64)
-                               fprintf(stderr,"FLAC__lpc_restore_signal: OVERFLOW, i=%u, j=%u, c=%d, d=%d, sumo=%I64d\n",i,j,qlp_coeff[j],*history,sumo);
-#else
                        if(sumo > 2147483647ll || sumo < -2147483648ll)
-                               fprintf(stderr,"FLAC__lpc_restore_signal: OVERFLOW, i=%u, j=%u, c=%d, d=%d, sumo=%lld\n",i,j,qlp_coeff[j],*history,(long long)sumo);
-#endif
-#endif
+                               fprintf(stderr,"FLAC__lpc_restore_signal: OVERFLOW, i=%u, j=%u, c=%d, d=%d, sumo=%" PRId64 "\n",i,j,qlp_coeff[j],*history,sumo);
                }
                *(data++) = *(r++) + (sum >> lp_quantization);
        }
@@ -398,8 +816,231 @@ void FLAC__lpc_restore_signal(const FLAC__int32 residual[], unsigned data_len, c
        }
        */
 }
+#else /* fully unrolled version for normal use */
+{
+       int i;
+       FLAC__int32 sum;
+
+       FLAC__ASSERT(order > 0);
+       FLAC__ASSERT(order <= 32);
+
+       /*
+        * We do unique versions up to 12th order since that's the subset limit.
+        * Also they are roughly ordered to match frequency of occurrence to
+        * minimize branching.
+        */
+       if(order <= 12) {
+               if(order > 8) {
+                       if(order > 10) {
+                               if(order == 12) {
+                                       for(i = 0; i < (int)data_len; i++) {
+                                               sum = 0;
+                                               sum += qlp_coeff[11] * data[i-12];
+                                               sum += qlp_coeff[10] * data[i-11];
+                                               sum += qlp_coeff[9] * data[i-10];
+                                               sum += qlp_coeff[8] * data[i-9];
+                                               sum += qlp_coeff[7] * data[i-8];
+                                               sum += qlp_coeff[6] * data[i-7];
+                                               sum += qlp_coeff[5] * data[i-6];
+                                               sum += qlp_coeff[4] * data[i-5];
+                                               sum += qlp_coeff[3] * data[i-4];
+                                               sum += qlp_coeff[2] * data[i-3];
+                                               sum += qlp_coeff[1] * data[i-2];
+                                               sum += qlp_coeff[0] * data[i-1];
+                                               data[i] = residual[i] + (sum >> lp_quantization);
+                                       }
+                               }
+                               else { /* order == 11 */
+                                       for(i = 0; i < (int)data_len; i++) {
+                                               sum = 0;
+                                               sum += qlp_coeff[10] * data[i-11];
+                                               sum += qlp_coeff[9] * data[i-10];
+                                               sum += qlp_coeff[8] * data[i-9];
+                                               sum += qlp_coeff[7] * data[i-8];
+                                               sum += qlp_coeff[6] * data[i-7];
+                                               sum += qlp_coeff[5] * data[i-6];
+                                               sum += qlp_coeff[4] * data[i-5];
+                                               sum += qlp_coeff[3] * data[i-4];
+                                               sum += qlp_coeff[2] * data[i-3];
+                                               sum += qlp_coeff[1] * data[i-2];
+                                               sum += qlp_coeff[0] * data[i-1];
+                                               data[i] = residual[i] + (sum >> lp_quantization);
+                                       }
+                               }
+                       }
+                       else {
+                               if(order == 10) {
+                                       for(i = 0; i < (int)data_len; i++) {
+                                               sum = 0;
+                                               sum += qlp_coeff[9] * data[i-10];
+                                               sum += qlp_coeff[8] * data[i-9];
+                                               sum += qlp_coeff[7] * data[i-8];
+                                               sum += qlp_coeff[6] * data[i-7];
+                                               sum += qlp_coeff[5] * data[i-6];
+                                               sum += qlp_coeff[4] * data[i-5];
+                                               sum += qlp_coeff[3] * data[i-4];
+                                               sum += qlp_coeff[2] * data[i-3];
+                                               sum += qlp_coeff[1] * data[i-2];
+                                               sum += qlp_coeff[0] * data[i-1];
+                                               data[i] = residual[i] + (sum >> lp_quantization);
+                                       }
+                               }
+                               else { /* order == 9 */
+                                       for(i = 0; i < (int)data_len; i++) {
+                                               sum = 0;
+                                               sum += qlp_coeff[8] * data[i-9];
+                                               sum += qlp_coeff[7] * data[i-8];
+                                               sum += qlp_coeff[6] * data[i-7];
+                                               sum += qlp_coeff[5] * data[i-6];
+                                               sum += qlp_coeff[4] * data[i-5];
+                                               sum += qlp_coeff[3] * data[i-4];
+                                               sum += qlp_coeff[2] * data[i-3];
+                                               sum += qlp_coeff[1] * data[i-2];
+                                               sum += qlp_coeff[0] * data[i-1];
+                                               data[i] = residual[i] + (sum >> lp_quantization);
+                                       }
+                               }
+                       }
+               }
+               else if(order > 4) {
+                       if(order > 6) {
+                               if(order == 8) {
+                                       for(i = 0; i < (int)data_len; i++) {
+                                               sum = 0;
+                                               sum += qlp_coeff[7] * data[i-8];
+                                               sum += qlp_coeff[6] * data[i-7];
+                                               sum += qlp_coeff[5] * data[i-6];
+                                               sum += qlp_coeff[4] * data[i-5];
+                                               sum += qlp_coeff[3] * data[i-4];
+                                               sum += qlp_coeff[2] * data[i-3];
+                                               sum += qlp_coeff[1] * data[i-2];
+                                               sum += qlp_coeff[0] * data[i-1];
+                                               data[i] = residual[i] + (sum >> lp_quantization);
+                                       }
+                               }
+                               else { /* order == 7 */
+                                       for(i = 0; i < (int)data_len; i++) {
+                                               sum = 0;
+                                               sum += qlp_coeff[6] * data[i-7];
+                                               sum += qlp_coeff[5] * data[i-6];
+                                               sum += qlp_coeff[4] * data[i-5];
+                                               sum += qlp_coeff[3] * data[i-4];
+                                               sum += qlp_coeff[2] * data[i-3];
+                                               sum += qlp_coeff[1] * data[i-2];
+                                               sum += qlp_coeff[0] * data[i-1];
+                                               data[i] = residual[i] + (sum >> lp_quantization);
+                                       }
+                               }
+                       }
+                       else {
+                               if(order == 6) {
+                                       for(i = 0; i < (int)data_len; i++) {
+                                               sum = 0;
+                                               sum += qlp_coeff[5] * data[i-6];
+                                               sum += qlp_coeff[4] * data[i-5];
+                                               sum += qlp_coeff[3] * data[i-4];
+                                               sum += qlp_coeff[2] * data[i-3];
+                                               sum += qlp_coeff[1] * data[i-2];
+                                               sum += qlp_coeff[0] * data[i-1];
+                                               data[i] = residual[i] + (sum >> lp_quantization);
+                                       }
+                               }
+                               else { /* order == 5 */
+                                       for(i = 0; i < (int)data_len; i++) {
+                                               sum = 0;
+                                               sum += qlp_coeff[4] * data[i-5];
+                                               sum += qlp_coeff[3] * data[i-4];
+                                               sum += qlp_coeff[2] * data[i-3];
+                                               sum += qlp_coeff[1] * data[i-2];
+                                               sum += qlp_coeff[0] * data[i-1];
+                                               data[i] = residual[i] + (sum >> lp_quantization);
+                                       }
+                               }
+                       }
+               }
+               else {
+                       if(order > 2) {
+                               if(order == 4) {
+                                       for(i = 0; i < (int)data_len; i++) {
+                                               sum = 0;
+                                               sum += qlp_coeff[3] * data[i-4];
+                                               sum += qlp_coeff[2] * data[i-3];
+                                               sum += qlp_coeff[1] * data[i-2];
+                                               sum += qlp_coeff[0] * data[i-1];
+                                               data[i] = residual[i] + (sum >> lp_quantization);
+                                       }
+                               }
+                               else { /* order == 3 */
+                                       for(i = 0; i < (int)data_len; i++) {
+                                               sum = 0;
+                                               sum += qlp_coeff[2] * data[i-3];
+                                               sum += qlp_coeff[1] * data[i-2];
+                                               sum += qlp_coeff[0] * data[i-1];
+                                               data[i] = residual[i] + (sum >> lp_quantization);
+                                       }
+                               }
+                       }
+                       else {
+                               if(order == 2) {
+                                       for(i = 0; i < (int)data_len; i++) {
+                                               sum = 0;
+                                               sum += qlp_coeff[1] * data[i-2];
+                                               sum += qlp_coeff[0] * data[i-1];
+                                               data[i] = residual[i] + (sum >> lp_quantization);
+                                       }
+                               }
+                               else { /* order == 1 */
+                                       for(i = 0; i < (int)data_len; i++)
+                                               data[i] = residual[i] + ((qlp_coeff[0] * data[i-1]) >> lp_quantization);
+                               }
+                       }
+               }
+       }
+       else { /* order > 12 */
+               for(i = 0; i < (int)data_len; i++) {
+                       sum = 0;
+                       switch(order) {
+                               case 32: sum += qlp_coeff[31] * data[i-32];
+                               case 31: sum += qlp_coeff[30] * data[i-31];
+                               case 30: sum += qlp_coeff[29] * data[i-30];
+                               case 29: sum += qlp_coeff[28] * data[i-29];
+                               case 28: sum += qlp_coeff[27] * data[i-28];
+                               case 27: sum += qlp_coeff[26] * data[i-27];
+                               case 26: sum += qlp_coeff[25] * data[i-26];
+                               case 25: sum += qlp_coeff[24] * data[i-25];
+                               case 24: sum += qlp_coeff[23] * data[i-24];
+                               case 23: sum += qlp_coeff[22] * data[i-23];
+                               case 22: sum += qlp_coeff[21] * data[i-22];
+                               case 21: sum += qlp_coeff[20] * data[i-21];
+                               case 20: sum += qlp_coeff[19] * data[i-20];
+                               case 19: sum += qlp_coeff[18] * data[i-19];
+                               case 18: sum += qlp_coeff[17] * data[i-18];
+                               case 17: sum += qlp_coeff[16] * data[i-17];
+                               case 16: sum += qlp_coeff[15] * data[i-16];
+                               case 15: sum += qlp_coeff[14] * data[i-15];
+                               case 14: sum += qlp_coeff[13] * data[i-14];
+                               case 13: sum += qlp_coeff[12] * data[i-13];
+                                        sum += qlp_coeff[11] * data[i-12];
+                                        sum += qlp_coeff[10] * data[i-11];
+                                        sum += qlp_coeff[ 9] * data[i-10];
+                                        sum += qlp_coeff[ 8] * data[i- 9];
+                                        sum += qlp_coeff[ 7] * data[i- 8];
+                                        sum += qlp_coeff[ 6] * data[i- 7];
+                                        sum += qlp_coeff[ 5] * data[i- 6];
+                                        sum += qlp_coeff[ 4] * data[i- 5];
+                                        sum += qlp_coeff[ 3] * data[i- 4];
+                                        sum += qlp_coeff[ 2] * data[i- 3];
+                                        sum += qlp_coeff[ 1] * data[i- 2];
+                                        sum += qlp_coeff[ 0] * data[i- 1];
+                       }
+                       data[i] = residual[i] + (sum >> lp_quantization);
+               }
+       }
+}
+#endif
 
 void FLAC__lpc_restore_signal_wide(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[])
+#if defined(FLAC__OVERFLOW_DETECT) || !defined(FLAC__LPC_UNROLLED_FILTER_LOOPS)
 {
        unsigned i, j;
        FLAC__int64 sum;
@@ -418,27 +1059,239 @@ void FLAC__lpc_restore_signal_wide(const FLAC__int32 residual[], unsigned data_l
                history = data;
                for(j = 0; j < order; j++)
                        sum += (FLAC__int64)qlp_coeff[j] * (FLAC__int64)(*(--history));
-#ifdef FLAC__OVERFLOW_DETECT
                if(FLAC__bitmath_silog2_wide(sum >> lp_quantization) > 32) {
-#ifdef _MSC_VER
-                       fprintf(stderr,"FLAC__lpc_restore_signal_wide: OVERFLOW, i=%u, sum=%I64d\n", i, sum >> lp_quantization);
-#else
-                       fprintf(stderr,"FLAC__lpc_restore_signal_wide: OVERFLOW, i=%u, sum=%lld\n", i, (long long)(sum >> lp_quantization));
-#endif
+                       fprintf(stderr,"FLAC__lpc_restore_signal_wide: OVERFLOW, i=%u, sum=%" PRId64 "\n", i, (sum >> lp_quantization));
                        break;
                }
                if(FLAC__bitmath_silog2_wide((FLAC__int64)(*r) + (sum >> lp_quantization)) > 32) {
-#ifdef _MSC_VER
-                       fprintf(stderr,"FLAC__lpc_restore_signal_wide: OVERFLOW, i=%u, residual=%d, sum=%I64d, data=%I64d\n", i, *r, sum >> lp_quantization, (FLAC__int64)(*r) + (sum >> lp_quantization));
-#else
-                       fprintf(stderr,"FLAC__lpc_restore_signal_wide: OVERFLOW, i=%u, residual=%d, sum=%lld, data=%lld\n", i, *r, (long long)(sum >> lp_quantization), (long long)((FLAC__int64)(*r) + (sum >> lp_quantization)));
-#endif
+                       fprintf(stderr,"FLAC__lpc_restore_signal_wide: OVERFLOW, i=%u, residual=%d, sum=%" PRId64 ", data=%" PRId64 "\n", i, *r, (sum >> lp_quantization), ((FLAC__int64)(*r) + (sum >> lp_quantization)));
                        break;
                }
-#endif
                *(data++) = *(r++) + (FLAC__int32)(sum >> lp_quantization);
        }
 }
+#else /* fully unrolled version for normal use */
+{
+       int i;
+       FLAC__int64 sum;
+
+       FLAC__ASSERT(order > 0);
+       FLAC__ASSERT(order <= 32);
+
+       /*
+        * We do unique versions up to 12th order since that's the subset limit.
+        * Also they are roughly ordered to match frequency of occurrence to
+        * minimize branching.
+        */
+       if(order <= 12) {
+               if(order > 8) {
+                       if(order > 10) {
+                               if(order == 12) {
+                                       for(i = 0; i < (int)data_len; i++) {
+                                               sum = 0;
+                                               sum += qlp_coeff[11] * (FLAC__int64)data[i-12];
+                                               sum += qlp_coeff[10] * (FLAC__int64)data[i-11];
+                                               sum += qlp_coeff[9] * (FLAC__int64)data[i-10];
+                                               sum += qlp_coeff[8] * (FLAC__int64)data[i-9];
+                                               sum += qlp_coeff[7] * (FLAC__int64)data[i-8];
+                                               sum += qlp_coeff[6] * (FLAC__int64)data[i-7];
+                                               sum += qlp_coeff[5] * (FLAC__int64)data[i-6];
+                                               sum += qlp_coeff[4] * (FLAC__int64)data[i-5];
+                                               sum += qlp_coeff[3] * (FLAC__int64)data[i-4];
+                                               sum += qlp_coeff[2] * (FLAC__int64)data[i-3];
+                                               sum += qlp_coeff[1] * (FLAC__int64)data[i-2];
+                                               sum += qlp_coeff[0] * (FLAC__int64)data[i-1];
+                                               data[i] = residual[i] + (FLAC__int32)(sum >> lp_quantization);
+                                       }
+                               }
+                               else { /* order == 11 */
+                                       for(i = 0; i < (int)data_len; i++) {
+                                               sum = 0;
+                                               sum += qlp_coeff[10] * (FLAC__int64)data[i-11];
+                                               sum += qlp_coeff[9] * (FLAC__int64)data[i-10];
+                                               sum += qlp_coeff[8] * (FLAC__int64)data[i-9];
+                                               sum += qlp_coeff[7] * (FLAC__int64)data[i-8];
+                                               sum += qlp_coeff[6] * (FLAC__int64)data[i-7];
+                                               sum += qlp_coeff[5] * (FLAC__int64)data[i-6];
+                                               sum += qlp_coeff[4] * (FLAC__int64)data[i-5];
+                                               sum += qlp_coeff[3] * (FLAC__int64)data[i-4];
+                                               sum += qlp_coeff[2] * (FLAC__int64)data[i-3];
+                                               sum += qlp_coeff[1] * (FLAC__int64)data[i-2];
+                                               sum += qlp_coeff[0] * (FLAC__int64)data[i-1];
+                                               data[i] = residual[i] + (FLAC__int32)(sum >> lp_quantization);
+                                       }
+                               }
+                       }
+                       else {
+                               if(order == 10) {
+                                       for(i = 0; i < (int)data_len; i++) {
+                                               sum = 0;
+                                               sum += qlp_coeff[9] * (FLAC__int64)data[i-10];
+                                               sum += qlp_coeff[8] * (FLAC__int64)data[i-9];
+                                               sum += qlp_coeff[7] * (FLAC__int64)data[i-8];
+                                               sum += qlp_coeff[6] * (FLAC__int64)data[i-7];
+                                               sum += qlp_coeff[5] * (FLAC__int64)data[i-6];
+                                               sum += qlp_coeff[4] * (FLAC__int64)data[i-5];
+                                               sum += qlp_coeff[3] * (FLAC__int64)data[i-4];
+                                               sum += qlp_coeff[2] * (FLAC__int64)data[i-3];
+                                               sum += qlp_coeff[1] * (FLAC__int64)data[i-2];
+                                               sum += qlp_coeff[0] * (FLAC__int64)data[i-1];
+                                               data[i] = residual[i] + (FLAC__int32)(sum >> lp_quantization);
+                                       }
+                               }
+                               else { /* order == 9 */
+                                       for(i = 0; i < (int)data_len; i++) {
+                                               sum = 0;
+                                               sum += qlp_coeff[8] * (FLAC__int64)data[i-9];
+                                               sum += qlp_coeff[7] * (FLAC__int64)data[i-8];
+                                               sum += qlp_coeff[6] * (FLAC__int64)data[i-7];
+                                               sum += qlp_coeff[5] * (FLAC__int64)data[i-6];
+                                               sum += qlp_coeff[4] * (FLAC__int64)data[i-5];
+                                               sum += qlp_coeff[3] * (FLAC__int64)data[i-4];
+                                               sum += qlp_coeff[2] * (FLAC__int64)data[i-3];
+                                               sum += qlp_coeff[1] * (FLAC__int64)data[i-2];
+                                               sum += qlp_coeff[0] * (FLAC__int64)data[i-1];
+                                               data[i] = residual[i] + (FLAC__int32)(sum >> lp_quantization);
+                                       }
+                               }
+                       }
+               }
+               else if(order > 4) {
+                       if(order > 6) {
+                               if(order == 8) {
+                                       for(i = 0; i < (int)data_len; i++) {
+                                               sum = 0;
+                                               sum += qlp_coeff[7] * (FLAC__int64)data[i-8];
+                                               sum += qlp_coeff[6] * (FLAC__int64)data[i-7];
+                                               sum += qlp_coeff[5] * (FLAC__int64)data[i-6];
+                                               sum += qlp_coeff[4] * (FLAC__int64)data[i-5];
+                                               sum += qlp_coeff[3] * (FLAC__int64)data[i-4];
+                                               sum += qlp_coeff[2] * (FLAC__int64)data[i-3];
+                                               sum += qlp_coeff[1] * (FLAC__int64)data[i-2];
+                                               sum += qlp_coeff[0] * (FLAC__int64)data[i-1];
+                                               data[i] = residual[i] + (FLAC__int32)(sum >> lp_quantization);
+                                       }
+                               }
+                               else { /* order == 7 */
+                                       for(i = 0; i < (int)data_len; i++) {
+                                               sum = 0;
+                                               sum += qlp_coeff[6] * (FLAC__int64)data[i-7];
+                                               sum += qlp_coeff[5] * (FLAC__int64)data[i-6];
+                                               sum += qlp_coeff[4] * (FLAC__int64)data[i-5];
+                                               sum += qlp_coeff[3] * (FLAC__int64)data[i-4];
+                                               sum += qlp_coeff[2] * (FLAC__int64)data[i-3];
+                                               sum += qlp_coeff[1] * (FLAC__int64)data[i-2];
+                                               sum += qlp_coeff[0] * (FLAC__int64)data[i-1];
+                                               data[i] = residual[i] + (FLAC__int32)(sum >> lp_quantization);
+                                       }
+                               }
+                       }
+                       else {
+                               if(order == 6) {
+                                       for(i = 0; i < (int)data_len; i++) {
+                                               sum = 0;
+                                               sum += qlp_coeff[5] * (FLAC__int64)data[i-6];
+                                               sum += qlp_coeff[4] * (FLAC__int64)data[i-5];
+                                               sum += qlp_coeff[3] * (FLAC__int64)data[i-4];
+                                               sum += qlp_coeff[2] * (FLAC__int64)data[i-3];
+                                               sum += qlp_coeff[1] * (FLAC__int64)data[i-2];
+                                               sum += qlp_coeff[0] * (FLAC__int64)data[i-1];
+                                               data[i] = residual[i] + (FLAC__int32)(sum >> lp_quantization);
+                                       }
+                               }
+                               else { /* order == 5 */
+                                       for(i = 0; i < (int)data_len; i++) {
+                                               sum = 0;
+                                               sum += qlp_coeff[4] * (FLAC__int64)data[i-5];
+                                               sum += qlp_coeff[3] * (FLAC__int64)data[i-4];
+                                               sum += qlp_coeff[2] * (FLAC__int64)data[i-3];
+                                               sum += qlp_coeff[1] * (FLAC__int64)data[i-2];
+                                               sum += qlp_coeff[0] * (FLAC__int64)data[i-1];
+                                               data[i] = residual[i] + (FLAC__int32)(sum >> lp_quantization);
+                                       }
+                               }
+                       }
+               }
+               else {
+                       if(order > 2) {
+                               if(order == 4) {
+                                       for(i = 0; i < (int)data_len; i++) {
+                                               sum = 0;
+                                               sum += qlp_coeff[3] * (FLAC__int64)data[i-4];
+                                               sum += qlp_coeff[2] * (FLAC__int64)data[i-3];
+                                               sum += qlp_coeff[1] * (FLAC__int64)data[i-2];
+                                               sum += qlp_coeff[0] * (FLAC__int64)data[i-1];
+                                               data[i] = residual[i] + (FLAC__int32)(sum >> lp_quantization);
+                                       }
+                               }
+                               else { /* order == 3 */
+                                       for(i = 0; i < (int)data_len; i++) {
+                                               sum = 0;
+                                               sum += qlp_coeff[2] * (FLAC__int64)data[i-3];
+                                               sum += qlp_coeff[1] * (FLAC__int64)data[i-2];
+                                               sum += qlp_coeff[0] * (FLAC__int64)data[i-1];
+                                               data[i] = residual[i] + (FLAC__int32)(sum >> lp_quantization);
+                                       }
+                               }
+                       }
+                       else {
+                               if(order == 2) {
+                                       for(i = 0; i < (int)data_len; i++) {
+                                               sum = 0;
+                                               sum += qlp_coeff[1] * (FLAC__int64)data[i-2];
+                                               sum += qlp_coeff[0] * (FLAC__int64)data[i-1];
+                                               data[i] = residual[i] + (FLAC__int32)(sum >> lp_quantization);
+                                       }
+                               }
+                               else { /* order == 1 */
+                                       for(i = 0; i < (int)data_len; i++)
+                                               data[i] = residual[i] + (FLAC__int32)((qlp_coeff[0] * (FLAC__int64)data[i-1]) >> lp_quantization);
+                               }
+                       }
+               }
+       }
+       else { /* order > 12 */
+               for(i = 0; i < (int)data_len; i++) {
+                       sum = 0;
+                       switch(order) {
+                               case 32: sum += qlp_coeff[31] * (FLAC__int64)data[i-32];
+                               case 31: sum += qlp_coeff[30] * (FLAC__int64)data[i-31];
+                               case 30: sum += qlp_coeff[29] * (FLAC__int64)data[i-30];
+                               case 29: sum += qlp_coeff[28] * (FLAC__int64)data[i-29];
+                               case 28: sum += qlp_coeff[27] * (FLAC__int64)data[i-28];
+                               case 27: sum += qlp_coeff[26] * (FLAC__int64)data[i-27];
+                               case 26: sum += qlp_coeff[25] * (FLAC__int64)data[i-26];
+                               case 25: sum += qlp_coeff[24] * (FLAC__int64)data[i-25];
+                               case 24: sum += qlp_coeff[23] * (FLAC__int64)data[i-24];
+                               case 23: sum += qlp_coeff[22] * (FLAC__int64)data[i-23];
+                               case 22: sum += qlp_coeff[21] * (FLAC__int64)data[i-22];
+                               case 21: sum += qlp_coeff[20] * (FLAC__int64)data[i-21];
+                               case 20: sum += qlp_coeff[19] * (FLAC__int64)data[i-20];
+                               case 19: sum += qlp_coeff[18] * (FLAC__int64)data[i-19];
+                               case 18: sum += qlp_coeff[17] * (FLAC__int64)data[i-18];
+                               case 17: sum += qlp_coeff[16] * (FLAC__int64)data[i-17];
+                               case 16: sum += qlp_coeff[15] * (FLAC__int64)data[i-16];
+                               case 15: sum += qlp_coeff[14] * (FLAC__int64)data[i-15];
+                               case 14: sum += qlp_coeff[13] * (FLAC__int64)data[i-14];
+                               case 13: sum += qlp_coeff[12] * (FLAC__int64)data[i-13];
+                                        sum += qlp_coeff[11] * (FLAC__int64)data[i-12];
+                                        sum += qlp_coeff[10] * (FLAC__int64)data[i-11];
+                                        sum += qlp_coeff[ 9] * (FLAC__int64)data[i-10];
+                                        sum += qlp_coeff[ 8] * (FLAC__int64)data[i- 9];
+                                        sum += qlp_coeff[ 7] * (FLAC__int64)data[i- 8];
+                                        sum += qlp_coeff[ 6] * (FLAC__int64)data[i- 7];
+                                        sum += qlp_coeff[ 5] * (FLAC__int64)data[i- 6];
+                                        sum += qlp_coeff[ 4] * (FLAC__int64)data[i- 5];
+                                        sum += qlp_coeff[ 3] * (FLAC__int64)data[i- 4];
+                                        sum += qlp_coeff[ 2] * (FLAC__int64)data[i- 3];
+                                        sum += qlp_coeff[ 1] * (FLAC__int64)data[i- 2];
+                                        sum += qlp_coeff[ 0] * (FLAC__int64)data[i- 1];
+                       }
+                       data[i] = residual[i] + (FLAC__int32)(sum >> lp_quantization);
+               }
+       }
+}
+#endif
 
 #ifndef FLAC__INTEGER_ONLY_LIBRARY