avfilter/vf_framerate: change blend factor precision
[ffmpeg.git] / libavcodec / lpc.c
index 1d52edf..f8da1e1 100644 (file)
@@ -37,13 +37,19 @@ static void lpc_apply_welch_window_c(const int32_t *data, int len,
     double w;
     double c;
 
-    /* The optimization in commit fa4ed8c does not support odd len.
-     * If someone wants odd len extend that change. */
-    av_assert2(!(len & 1));
-
     n2 = (len >> 1);
     c = 2.0 / (len - 1.0);
 
+    if (len & 1) {
+        for(i=0; i<n2; i++) {
+            w = c - i - 1.0;
+            w = 1.0 - (w * w);
+            w_data[i] = data[i] * w;
+            w_data[len-1-i] = data[len-1-i] * w;
+        }
+        return;
+    }
+
     w_data+=n2;
       data+=n2;
     for(i=0; i<n2; i++) {
@@ -87,7 +93,8 @@ static void lpc_compute_autocorr_c(const double *data, int len, int lag,
  * Quantize LPC coefficients
  */
 static void quantize_lpc_coefs(double *lpc_in, int order, int precision,
-                               int32_t *lpc_out, int *shift, int max_shift, int zero_shift)
+                               int32_t *lpc_out, int *shift, int min_shift,
+                               int max_shift, int zero_shift)
 {
     int i;
     double cmax, error;
@@ -112,7 +119,7 @@ static void quantize_lpc_coefs(double *lpc_in, int order, int precision,
 
     /* calculate level shift which scales max coeff to available bits */
     sh = max_shift;
-    while((cmax * (1 << sh) > qmax) && (sh > 0)) {
+    while((cmax * (1 << sh) > qmax) && (sh > min_shift)) {
         sh--;
     }
 
@@ -161,6 +168,29 @@ int ff_lpc_calc_ref_coefs(LPCContext *s,
     return order;
 }
 
+double ff_lpc_calc_ref_coefs_f(LPCContext *s, const float *samples, int len,
+                               int order, double *ref)
+{
+    int i;
+    double signal = 0.0f, avg_err = 0.0f;
+    double autoc[MAX_LPC_ORDER+1] = {0}, error[MAX_LPC_ORDER+1] = {0};
+    const double a = 0.5f, b = 1.0f - a;
+
+    /* Apply windowing */
+    for (i = 0; i <= len / 2; i++) {
+        double weight = a - b*cos((2*M_PI*i)/(len - 1));
+        s->windowed_samples[i] = weight*samples[i];
+        s->windowed_samples[len-1-i] = weight*samples[len-1-i];
+    }
+
+    s->lpc_compute_autocorr(s->windowed_samples, len, order, autoc);
+    signal = autoc[0];
+    compute_ref_coefs(autoc, order, ref, error);
+    for (i = 0; i < order; i++)
+        avg_err = (avg_err + error[i])/2.0f;
+    return signal/avg_err;
+}
+
 /**
  * Calculate LPC coefficients for multiple orders
  *
@@ -172,10 +202,10 @@ int ff_lpc_calc_coefs(LPCContext *s,
                       int max_order, int precision,
                       int32_t coefs[][MAX_LPC_ORDER], int *shift,
                       enum FFLPCType lpc_type, int lpc_passes,
-                      int omethod, int max_shift, int zero_shift)
+                      int omethod, int min_shift, int max_shift, int zero_shift)
 {
     double autoc[MAX_LPC_ORDER+1];
-    double ref[MAX_LPC_ORDER];
+    double ref[MAX_LPC_ORDER] = { 0 };
     double lpc[MAX_LPC_ORDER][MAX_LPC_ORDER];
     int i, j, pass = 0;
     int opt_order;
@@ -208,7 +238,7 @@ int ff_lpc_calc_coefs(LPCContext *s,
     }
 
     if (lpc_type == FF_LPC_TYPE_CHOLESKY) {
-        LLSModel m[2];
+        LLSModel *m = s->lls_models;
         LOCAL_ALIGNED(32, double, var, [FFALIGN(MAX_LPC_ORDER+1,4)]);
         double av_uninit(weight);
         memset(var, 0, FFALIGN(MAX_LPC_ORDER+1,4)*sizeof(*var));
@@ -255,10 +285,12 @@ int ff_lpc_calc_coefs(LPCContext *s,
     if(omethod == ORDER_METHOD_EST) {
         opt_order = estimate_best_order(ref, min_order, max_order);
         i = opt_order-1;
-        quantize_lpc_coefs(lpc[i], i+1, precision, coefs[i], &shift[i], max_shift, zero_shift);
+        quantize_lpc_coefs(lpc[i], i+1, precision, coefs[i], &shift[i],
+                           min_shift, max_shift, zero_shift);
     } else {
         for(i=min_order-1; i<max_order; i++) {
-            quantize_lpc_coefs(lpc[i], i+1, precision, coefs[i], &shift[i], max_shift, zero_shift);
+            quantize_lpc_coefs(lpc[i], i+1, precision, coefs[i], &shift[i],
+                               min_shift, max_shift, zero_shift);
         }
     }