diff options
Diffstat (limited to 'libavcodec/lpc.c')
-rw-r--r-- | libavcodec/lpc.c | 68 |
1 files changed, 53 insertions, 15 deletions
diff --git a/libavcodec/lpc.c b/libavcodec/lpc.c index 1482e57..f8da1e1 100644 --- a/libavcodec/lpc.c +++ b/libavcodec/lpc.c @@ -2,20 +2,20 @@ * LPC utility code * Copyright (c) 2006 Justin Ruggles <justin.ruggles@gmail.com> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -24,6 +24,7 @@ #define LPC_USE_DOUBLE #include "lpc.h" +#include "libavutil/avassert.h" /** @@ -36,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. */ - assert(!(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++) { @@ -86,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; @@ -111,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--; } @@ -160,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 * @@ -171,7 +202,7 @@ 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] = { 0 }; @@ -179,8 +210,9 @@ int ff_lpc_calc_coefs(LPCContext *s, int i, j, pass = 0; int opt_order; - assert(max_order >= MIN_LPC_ORDER && max_order <= MAX_LPC_ORDER && + av_assert2(max_order >= MIN_LPC_ORDER && max_order <= MAX_LPC_ORDER && lpc_type > FF_LPC_TYPE_FIXED); + av_assert0(lpc_type == FF_LPC_TYPE_CHOLESKY || lpc_type == FF_LPC_TYPE_LEVINSON); /* reinit LPC context if parameters have changed */ if (blocksize != s->blocksize || max_order != s->max_order || @@ -189,6 +221,9 @@ int ff_lpc_calc_coefs(LPCContext *s, ff_lpc_init(s, blocksize, max_order, lpc_type); } + if(lpc_passes <= 0) + lpc_passes = 2; + if (lpc_type == FF_LPC_TYPE_LEVINSON || (lpc_type == FF_LPC_TYPE_CHOLESKY && lpc_passes > 1)) { s->lpc_apply_welch_window(samples, blocksize, s->windowed_samples); @@ -203,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)); @@ -244,15 +279,18 @@ int ff_lpc_calc_coefs(LPCContext *s, for(i=max_order-1; i>0; i--) ref[i] = ref[i-1] - ref[i]; } + opt_order = max_order; 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); } } |