annotate ffmpeg/libavcodec/lpc.c @ 13:844d341cf643 tip

Back up before ISMIR
author Yading Song <yading.song@eecs.qmul.ac.uk>
date Thu, 31 Oct 2013 13:17:06 +0000
parents 6840f77b83aa
children
rev   line source
yading@10 1 /*
yading@10 2 * LPC utility code
yading@10 3 * Copyright (c) 2006 Justin Ruggles <justin.ruggles@gmail.com>
yading@10 4 *
yading@10 5 * This file is part of FFmpeg.
yading@10 6 *
yading@10 7 * FFmpeg is free software; you can redistribute it and/or
yading@10 8 * modify it under the terms of the GNU Lesser General Public
yading@10 9 * License as published by the Free Software Foundation; either
yading@10 10 * version 2.1 of the License, or (at your option) any later version.
yading@10 11 *
yading@10 12 * FFmpeg is distributed in the hope that it will be useful,
yading@10 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
yading@10 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
yading@10 15 * Lesser General Public License for more details.
yading@10 16 *
yading@10 17 * You should have received a copy of the GNU Lesser General Public
yading@10 18 * License along with FFmpeg; if not, write to the Free Software
yading@10 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
yading@10 20 */
yading@10 21
yading@10 22 #include "libavutil/common.h"
yading@10 23 #include "libavutil/lls.h"
yading@10 24
yading@10 25 #define LPC_USE_DOUBLE
yading@10 26 #include "lpc.h"
yading@10 27 #include "libavutil/avassert.h"
yading@10 28
yading@10 29
yading@10 30 /**
yading@10 31 * Apply Welch window function to audio block
yading@10 32 */
yading@10 33 static void lpc_apply_welch_window_c(const int32_t *data, int len,
yading@10 34 double *w_data)
yading@10 35 {
yading@10 36 int i, n2;
yading@10 37 double w;
yading@10 38 double c;
yading@10 39
yading@10 40 /* The optimization in commit fa4ed8c does not support odd len.
yading@10 41 * If someone wants odd len extend that change. */
yading@10 42 av_assert2(!(len & 1));
yading@10 43
yading@10 44 n2 = (len >> 1);
yading@10 45 c = 2.0 / (len - 1.0);
yading@10 46
yading@10 47 w_data+=n2;
yading@10 48 data+=n2;
yading@10 49 for(i=0; i<n2; i++) {
yading@10 50 w = c - n2 + i;
yading@10 51 w = 1.0 - (w * w);
yading@10 52 w_data[-i-1] = data[-i-1] * w;
yading@10 53 w_data[+i ] = data[+i ] * w;
yading@10 54 }
yading@10 55 }
yading@10 56
yading@10 57 /**
yading@10 58 * Calculate autocorrelation data from audio samples
yading@10 59 * A Welch window function is applied before calculation.
yading@10 60 */
yading@10 61 static void lpc_compute_autocorr_c(const double *data, int len, int lag,
yading@10 62 double *autoc)
yading@10 63 {
yading@10 64 int i, j;
yading@10 65
yading@10 66 for(j=0; j<lag; j+=2){
yading@10 67 double sum0 = 1.0, sum1 = 1.0;
yading@10 68 for(i=j; i<len; i++){
yading@10 69 sum0 += data[i] * data[i-j];
yading@10 70 sum1 += data[i] * data[i-j-1];
yading@10 71 }
yading@10 72 autoc[j ] = sum0;
yading@10 73 autoc[j+1] = sum1;
yading@10 74 }
yading@10 75
yading@10 76 if(j==lag){
yading@10 77 double sum = 1.0;
yading@10 78 for(i=j-1; i<len; i+=2){
yading@10 79 sum += data[i ] * data[i-j ]
yading@10 80 + data[i+1] * data[i-j+1];
yading@10 81 }
yading@10 82 autoc[j] = sum;
yading@10 83 }
yading@10 84 }
yading@10 85
yading@10 86 /**
yading@10 87 * Quantize LPC coefficients
yading@10 88 */
yading@10 89 static void quantize_lpc_coefs(double *lpc_in, int order, int precision,
yading@10 90 int32_t *lpc_out, int *shift, int max_shift, int zero_shift)
yading@10 91 {
yading@10 92 int i;
yading@10 93 double cmax, error;
yading@10 94 int32_t qmax;
yading@10 95 int sh;
yading@10 96
yading@10 97 /* define maximum levels */
yading@10 98 qmax = (1 << (precision - 1)) - 1;
yading@10 99
yading@10 100 /* find maximum coefficient value */
yading@10 101 cmax = 0.0;
yading@10 102 for(i=0; i<order; i++) {
yading@10 103 cmax= FFMAX(cmax, fabs(lpc_in[i]));
yading@10 104 }
yading@10 105
yading@10 106 /* if maximum value quantizes to zero, return all zeros */
yading@10 107 if(cmax * (1 << max_shift) < 1.0) {
yading@10 108 *shift = zero_shift;
yading@10 109 memset(lpc_out, 0, sizeof(int32_t) * order);
yading@10 110 return;
yading@10 111 }
yading@10 112
yading@10 113 /* calculate level shift which scales max coeff to available bits */
yading@10 114 sh = max_shift;
yading@10 115 while((cmax * (1 << sh) > qmax) && (sh > 0)) {
yading@10 116 sh--;
yading@10 117 }
yading@10 118
yading@10 119 /* since negative shift values are unsupported in decoder, scale down
yading@10 120 coefficients instead */
yading@10 121 if(sh == 0 && cmax > qmax) {
yading@10 122 double scale = ((double)qmax) / cmax;
yading@10 123 for(i=0; i<order; i++) {
yading@10 124 lpc_in[i] *= scale;
yading@10 125 }
yading@10 126 }
yading@10 127
yading@10 128 /* output quantized coefficients and level shift */
yading@10 129 error=0;
yading@10 130 for(i=0; i<order; i++) {
yading@10 131 error -= lpc_in[i] * (1 << sh);
yading@10 132 lpc_out[i] = av_clip(lrintf(error), -qmax, qmax);
yading@10 133 error -= lpc_out[i];
yading@10 134 }
yading@10 135 *shift = sh;
yading@10 136 }
yading@10 137
yading@10 138 static int estimate_best_order(double *ref, int min_order, int max_order)
yading@10 139 {
yading@10 140 int i, est;
yading@10 141
yading@10 142 est = min_order;
yading@10 143 for(i=max_order-1; i>=min_order-1; i--) {
yading@10 144 if(ref[i] > 0.10) {
yading@10 145 est = i+1;
yading@10 146 break;
yading@10 147 }
yading@10 148 }
yading@10 149 return est;
yading@10 150 }
yading@10 151
yading@10 152 int ff_lpc_calc_ref_coefs(LPCContext *s,
yading@10 153 const int32_t *samples, int order, double *ref)
yading@10 154 {
yading@10 155 double autoc[MAX_LPC_ORDER + 1];
yading@10 156
yading@10 157 s->lpc_apply_welch_window(samples, s->blocksize, s->windowed_samples);
yading@10 158 s->lpc_compute_autocorr(s->windowed_samples, s->blocksize, order, autoc);
yading@10 159 compute_ref_coefs(autoc, order, ref, NULL);
yading@10 160
yading@10 161 return order;
yading@10 162 }
yading@10 163
yading@10 164 /**
yading@10 165 * Calculate LPC coefficients for multiple orders
yading@10 166 *
yading@10 167 * @param lpc_type LPC method for determining coefficients,
yading@10 168 * see #FFLPCType for details
yading@10 169 */
yading@10 170 int ff_lpc_calc_coefs(LPCContext *s,
yading@10 171 const int32_t *samples, int blocksize, int min_order,
yading@10 172 int max_order, int precision,
yading@10 173 int32_t coefs[][MAX_LPC_ORDER], int *shift,
yading@10 174 enum FFLPCType lpc_type, int lpc_passes,
yading@10 175 int omethod, int max_shift, int zero_shift)
yading@10 176 {
yading@10 177 double autoc[MAX_LPC_ORDER+1];
yading@10 178 double ref[MAX_LPC_ORDER];
yading@10 179 double lpc[MAX_LPC_ORDER][MAX_LPC_ORDER];
yading@10 180 int i, j, pass;
yading@10 181 int opt_order;
yading@10 182
yading@10 183 av_assert2(max_order >= MIN_LPC_ORDER && max_order <= MAX_LPC_ORDER &&
yading@10 184 lpc_type > FF_LPC_TYPE_FIXED);
yading@10 185
yading@10 186 /* reinit LPC context if parameters have changed */
yading@10 187 if (blocksize != s->blocksize || max_order != s->max_order ||
yading@10 188 lpc_type != s->lpc_type) {
yading@10 189 ff_lpc_end(s);
yading@10 190 ff_lpc_init(s, blocksize, max_order, lpc_type);
yading@10 191 }
yading@10 192
yading@10 193 if (lpc_type == FF_LPC_TYPE_LEVINSON) {
yading@10 194 s->lpc_apply_welch_window(samples, blocksize, s->windowed_samples);
yading@10 195
yading@10 196 s->lpc_compute_autocorr(s->windowed_samples, blocksize, max_order, autoc);
yading@10 197
yading@10 198 compute_lpc_coefs(autoc, max_order, &lpc[0][0], MAX_LPC_ORDER, 0, 1);
yading@10 199
yading@10 200 for(i=0; i<max_order; i++)
yading@10 201 ref[i] = fabs(lpc[i][i]);
yading@10 202 } else if (lpc_type == FF_LPC_TYPE_CHOLESKY) {
yading@10 203 LLSModel m[2];
yading@10 204 double var[MAX_LPC_ORDER+1], av_uninit(weight);
yading@10 205
yading@10 206 if(lpc_passes <= 0)
yading@10 207 lpc_passes = 2;
yading@10 208
yading@10 209 for(pass=0; pass<lpc_passes; pass++){
yading@10 210 avpriv_init_lls(&m[pass&1], max_order);
yading@10 211
yading@10 212 weight=0;
yading@10 213 for(i=max_order; i<blocksize; i++){
yading@10 214 for(j=0; j<=max_order; j++)
yading@10 215 var[j]= samples[i-j];
yading@10 216
yading@10 217 if(pass){
yading@10 218 double eval, inv, rinv;
yading@10 219 eval= avpriv_evaluate_lls(&m[(pass-1)&1], var+1, max_order-1);
yading@10 220 eval= (512>>pass) + fabs(eval - var[0]);
yading@10 221 inv = 1/eval;
yading@10 222 rinv = sqrt(inv);
yading@10 223 for(j=0; j<=max_order; j++)
yading@10 224 var[j] *= rinv;
yading@10 225 weight += inv;
yading@10 226 }else
yading@10 227 weight++;
yading@10 228
yading@10 229 avpriv_update_lls(&m[pass&1], var, 1.0);
yading@10 230 }
yading@10 231 avpriv_solve_lls(&m[pass&1], 0.001, 0);
yading@10 232 }
yading@10 233
yading@10 234 for(i=0; i<max_order; i++){
yading@10 235 for(j=0; j<max_order; j++)
yading@10 236 lpc[i][j]=-m[(pass-1)&1].coeff[i][j];
yading@10 237 ref[i]= sqrt(m[(pass-1)&1].variance[i] / weight) * (blocksize - max_order) / 4000;
yading@10 238 }
yading@10 239 for(i=max_order-1; i>0; i--)
yading@10 240 ref[i] = ref[i-1] - ref[i];
yading@10 241 } else
yading@10 242 av_assert0(0);
yading@10 243 opt_order = max_order;
yading@10 244
yading@10 245 if(omethod == ORDER_METHOD_EST) {
yading@10 246 opt_order = estimate_best_order(ref, min_order, max_order);
yading@10 247 i = opt_order-1;
yading@10 248 quantize_lpc_coefs(lpc[i], i+1, precision, coefs[i], &shift[i], max_shift, zero_shift);
yading@10 249 } else {
yading@10 250 for(i=min_order-1; i<max_order; i++) {
yading@10 251 quantize_lpc_coefs(lpc[i], i+1, precision, coefs[i], &shift[i], max_shift, zero_shift);
yading@10 252 }
yading@10 253 }
yading@10 254
yading@10 255 return opt_order;
yading@10 256 }
yading@10 257
yading@10 258 av_cold int ff_lpc_init(LPCContext *s, int blocksize, int max_order,
yading@10 259 enum FFLPCType lpc_type)
yading@10 260 {
yading@10 261 s->blocksize = blocksize;
yading@10 262 s->max_order = max_order;
yading@10 263 s->lpc_type = lpc_type;
yading@10 264
yading@10 265 if (lpc_type == FF_LPC_TYPE_LEVINSON) {
yading@10 266 s->windowed_buffer = av_mallocz((blocksize + 2 + FFALIGN(max_order, 4)) *
yading@10 267 sizeof(*s->windowed_samples));
yading@10 268 if (!s->windowed_buffer)
yading@10 269 return AVERROR(ENOMEM);
yading@10 270 s->windowed_samples = s->windowed_buffer + FFALIGN(max_order, 4);
yading@10 271 } else {
yading@10 272 s->windowed_samples = NULL;
yading@10 273 }
yading@10 274
yading@10 275 s->lpc_apply_welch_window = lpc_apply_welch_window_c;
yading@10 276 s->lpc_compute_autocorr = lpc_compute_autocorr_c;
yading@10 277
yading@10 278 if (ARCH_X86)
yading@10 279 ff_lpc_init_x86(s);
yading@10 280
yading@10 281 return 0;
yading@10 282 }
yading@10 283
yading@10 284 av_cold void ff_lpc_end(LPCContext *s)
yading@10 285 {
yading@10 286 av_freep(&s->windowed_buffer);
yading@10 287 }