[Ffmpeg-cvslog] r5747 - trunk/libavcodec/flacenc.c

michael subversion
Fri Jul 14 20:48:38 CEST 2006


Author: michael
Date: Fri Jul 14 20:48:38 2006
New Revision: 5747

Modified:
   trunk/libavcodec/flacenc.c

Log:
optionally (use_lpc=2) support Cholesky factorization for finding the lpc coeficients
  this will find the coefficients which minimize the sum of the squared errors, 
  levinson-durbin recursion OTOH is only strictly correct if the autocorrelation matrix is a
  toeplitz matrix which it is only if the blocksize is infinite, this is also why applying
  a window (like the welch winodw we currently use) improves the lpc coefficients generated
  by levinson-durbin recursion ...

optionally (use_lpc>2) support iterative linear least abs() solver using cholesky 
  factorization with adjusted weights in each iteration

compression gain for both is small, and multiple passes are of course dead slow
	    


Modified: trunk/libavcodec/flacenc.c
==============================================================================
--- trunk/libavcodec/flacenc.c	(original)
+++ trunk/libavcodec/flacenc.c	Fri Jul 14 20:48:38 2006
@@ -21,6 +21,7 @@
 #include "bitstream.h"
 #include "crc.h"
 #include "golomb.h"
+#include "lls.h"
 
 #define FLAC_MAX_CH  8
 #define FLAC_MIN_BLOCKSIZE  16
@@ -236,10 +237,12 @@
 
     /* set compression option overrides from AVCodecContext */
     if(avctx->use_lpc >= 0) {
-        s->options.use_lpc = !!avctx->use_lpc;
+        s->options.use_lpc = clip(avctx->use_lpc, 0, 11);
     }
-    av_log(avctx, AV_LOG_DEBUG, " use lpc: %s\n",
-           s->options.use_lpc? "yes" : "no");
+    if(s->options.use_lpc == 1)
+        av_log(avctx, AV_LOG_DEBUG, " use lpc: Levinson-Durbin recursion with Welch window\n");
+    else if(s->options.use_lpc > 1)
+        av_log(avctx, AV_LOG_DEBUG, " use lpc: Cholesky factorization\n");
 
     if(avctx->min_prediction_order >= 0) {
         if(s->options.use_lpc) {
@@ -725,21 +728,49 @@
  */
 static int lpc_calc_coefs(const int32_t *samples, int blocksize, int max_order,
                           int precision, int32_t coefs[][MAX_LPC_ORDER],
-                          int *shift)
+                          int *shift, int use_lpc)
 {
     double autoc[MAX_LPC_ORDER+1];
     double ref[MAX_LPC_ORDER];
     double lpc[MAX_LPC_ORDER][MAX_LPC_ORDER];
-    int i;
+    int i, j, pass;
     int opt_order;
 
     assert(max_order >= MIN_LPC_ORDER && max_order <= MAX_LPC_ORDER);
 
-    compute_autocorr(samples, blocksize, max_order+1, autoc);
+    if(use_lpc == 1){
+        compute_autocorr(samples, blocksize, max_order+1, autoc);
+
+        compute_lpc_coefs(autoc, max_order, lpc, ref);
+
+        opt_order = estimate_best_order(ref, max_order);
+    }else{
+        LLSModel m[2];
+        double var[MAX_LPC_ORDER+1], eval;
+
+        for(pass=0; pass<use_lpc-1; pass++){
+            av_init_lls(&m[pass&1], max_order/*3*/);
 
-    compute_lpc_coefs(autoc, max_order, lpc, ref);
+            for(i=max_order; i<blocksize; i++){
+                for(j=0; j<=max_order; j++)
+                    var[j]= samples[i-j];
+
+                if(pass){
+                    eval= av_evaluate_lls(&m[(pass-1)&1], var+1);
+                    eval= (512>>pass) + fabs(eval - var[0]);
+                    for(j=0; j<=max_order; j++)
+                        var[j]= samples[i-j] / sqrt(eval);
+                }
 
-    opt_order = estimate_best_order(ref, max_order);
+                av_update_lls(&m[pass&1], var, 1.0);
+            }
+            av_solve_lls(&m[pass&1], 0.001);
+            opt_order= max_order; //FIXME
+        }
+
+        for(i=0; i<opt_order; i++)
+            lpc[opt_order-1][i]= m[(pass-1)&1].coeff[i];
+    }
 
     i = opt_order-1;
     quantize_lpc_coefs(lpc[i], i+1, precision, coefs[i], &shift[i]);
@@ -865,7 +896,7 @@
     }
 
     /* LPC */
-    sub->order = lpc_calc_coefs(smp, n, max_order, precision, coefs, shift);
+    sub->order = lpc_calc_coefs(smp, n, max_order, precision, coefs, shift, ctx->options.use_lpc);
     sub->type = FLAC_SUBFRAME_LPC;
     sub->type_code = sub->type | (sub->order-1);
     sub->shift = shift[sub->order-1];




More information about the ffmpeg-cvslog mailing list