summaryrefslogtreecommitdiff
path: root/libavcodec/lpc.c
diff options
context:
space:
mode:
Diffstat (limited to 'libavcodec/lpc.c')
-rw-r--r--libavcodec/lpc.c52
1 files changed, 42 insertions, 10 deletions
diff --git a/libavcodec/lpc.c b/libavcodec/lpc.c
index 1482e57615..5cda7797e4 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++) {
@@ -160,6 +167,26 @@ 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 c = (len - 1)/2.0f;
+
+ /* Welch window */
+ for (i = 0; i < len; i++)
+ s->windowed_samples[i] = 1.0f - ((samples[i]-c)/c)*((samples[i]-c)/c);
+
+ 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
*
@@ -179,8 +206,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 +217,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 +234,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,6 +275,7 @@ 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) {