Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

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