Blame lib/lpc.c

Packit 06404a
/********************************************************************
Packit 06404a
 *                                                                  *
Packit 06404a
 * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
Packit 06404a
 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
Packit 06404a
 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
Packit 06404a
 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
Packit 06404a
 *                                                                  *
Packit 06404a
 * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009             *
Packit 06404a
 * by the Xiph.Org Foundation http://www.xiph.org/                  *
Packit 06404a
 *                                                                  *
Packit 06404a
 ********************************************************************
Packit 06404a
Packit 06404a
  function: LPC low level routines
Packit 06404a
  last mod: $Id: lpc.c 16227 2009-07-08 06:58:46Z xiphmont $
Packit 06404a
Packit 06404a
 ********************************************************************/
Packit 06404a
Packit 06404a
/* Some of these routines (autocorrelator, LPC coefficient estimator)
Packit 06404a
   are derived from code written by Jutta Degener and Carsten Bormann;
Packit 06404a
   thus we include their copyright below.  The entirety of this file
Packit 06404a
   is freely redistributable on the condition that both of these
Packit 06404a
   copyright notices are preserved without modification.  */
Packit 06404a
Packit 06404a
/* Preserved Copyright: *********************************************/
Packit 06404a
Packit 06404a
/* Copyright 1992, 1993, 1994 by Jutta Degener and Carsten Bormann,
Packit 06404a
Technische Universita"t Berlin
Packit 06404a
Packit 06404a
Any use of this software is permitted provided that this notice is not
Packit 06404a
removed and that neither the authors nor the Technische Universita"t
Packit 06404a
Berlin are deemed to have made any representations as to the
Packit 06404a
suitability of this software for any purpose nor are held responsible
Packit 06404a
for any defects of this software. THERE IS ABSOLUTELY NO WARRANTY FOR
Packit 06404a
THIS SOFTWARE.
Packit 06404a
Packit 06404a
As a matter of courtesy, the authors request to be informed about uses
Packit 06404a
this software has found, about bugs in this software, and about any
Packit 06404a
improvements that may be of general interest.
Packit 06404a
Packit 06404a
Berlin, 28.11.1994
Packit 06404a
Jutta Degener
Packit 06404a
Carsten Bormann
Packit 06404a
Packit 06404a
*********************************************************************/
Packit 06404a
Packit 06404a
#include <stdlib.h>
Packit 06404a
#include <string.h>
Packit 06404a
#include <math.h>
Packit 06404a
#include "os.h"
Packit 06404a
#include "smallft.h"
Packit 06404a
#include "lpc.h"
Packit 06404a
#include "scales.h"
Packit 06404a
#include "misc.h"
Packit 06404a
Packit 06404a
/* Autocorrelation LPC coeff generation algorithm invented by
Packit 06404a
   N. Levinson in 1947, modified by J. Durbin in 1959. */
Packit 06404a
Packit 06404a
/* Input : n elements of time doamin data
Packit 06404a
   Output: m lpc coefficients, excitation energy */
Packit 06404a
Packit 06404a
float vorbis_lpc_from_data(float *data,float *lpci,int n,int m){
Packit 06404a
  double *aut=alloca(sizeof(*aut)*(m+1));
Packit 06404a
  double *lpc=alloca(sizeof(*lpc)*(m));
Packit 06404a
  double error;
Packit 06404a
  double epsilon;
Packit 06404a
  int i,j;
Packit 06404a
Packit 06404a
  /* autocorrelation, p+1 lag coefficients */
Packit 06404a
  j=m+1;
Packit 06404a
  while(j--){
Packit 06404a
    double d=0; /* double needed for accumulator depth */
Packit 06404a
    for(i=j;i
Packit 06404a
    aut[j]=d;
Packit 06404a
  }
Packit 06404a
Packit 06404a
  /* Generate lpc coefficients from autocorr values */
Packit 06404a
Packit 06404a
  /* set our noise floor to about -100dB */
Packit 06404a
  error=aut[0] * (1. + 1e-10);
Packit 06404a
  epsilon=1e-9*aut[0]+1e-10;
Packit 06404a
Packit 06404a
  for(i=0;i
Packit 06404a
    double r= -aut[i+1];
Packit 06404a
Packit 06404a
    if(error
Packit 06404a
      memset(lpc+i,0,(m-i)*sizeof(*lpc));
Packit 06404a
      goto done;
Packit 06404a
    }
Packit 06404a
Packit 06404a
    /* Sum up this iteration's reflection coefficient; note that in
Packit 06404a
       Vorbis we don't save it.  If anyone wants to recycle this code
Packit 06404a
       and needs reflection coefficients, save the results of 'r' from
Packit 06404a
       each iteration. */
Packit 06404a
Packit 06404a
    for(j=0;j
Packit 06404a
    r/=error;
Packit 06404a
Packit 06404a
    /* Update LPC coefficients and total error */
Packit 06404a
Packit 06404a
    lpc[i]=r;
Packit 06404a
    for(j=0;j
Packit 06404a
      double tmp=lpc[j];
Packit 06404a
Packit 06404a
      lpc[j]+=r*lpc[i-1-j];
Packit 06404a
      lpc[i-1-j]+=r*tmp;
Packit 06404a
    }
Packit 06404a
    if(i&1)lpc[j]+=lpc[j]*r;
Packit 06404a
Packit 06404a
    error*=1.-r*r;
Packit 06404a
Packit 06404a
  }
Packit 06404a
Packit 06404a
 done:
Packit 06404a
Packit 06404a
  /* slightly damp the filter */
Packit 06404a
  {
Packit 06404a
    double g = .99;
Packit 06404a
    double damp = g;
Packit 06404a
    for(j=0;j
Packit 06404a
      lpc[j]*=damp;
Packit 06404a
      damp*=g;
Packit 06404a
    }
Packit 06404a
  }
Packit 06404a
Packit 06404a
  for(j=0;j
Packit 06404a
Packit 06404a
  /* we need the error value to know how big an impulse to hit the
Packit 06404a
     filter with later */
Packit 06404a
Packit 06404a
  return error;
Packit 06404a
}
Packit 06404a
Packit 06404a
void vorbis_lpc_predict(float *coeff,float *prime,int m,
Packit 06404a
                     float *data,long n){
Packit 06404a
Packit 06404a
  /* in: coeff[0...m-1] LPC coefficients
Packit 06404a
         prime[0...m-1] initial values (allocated size of n+m-1)
Packit 06404a
    out: data[0...n-1] data samples */
Packit 06404a
Packit 06404a
  long i,j,o,p;
Packit 06404a
  float y;
Packit 06404a
  float *work=alloca(sizeof(*work)*(m+n));
Packit 06404a
Packit 06404a
  if(!prime)
Packit 06404a
    for(i=0;i
Packit 06404a
      work[i]=0.f;
Packit 06404a
  else
Packit 06404a
    for(i=0;i
Packit 06404a
      work[i]=prime[i];
Packit 06404a
Packit 06404a
  for(i=0;i
Packit 06404a
    y=0;
Packit 06404a
    o=i;
Packit 06404a
    p=m;
Packit 06404a
    for(j=0;j
Packit 06404a
      y-=work[o++]*coeff[--p];
Packit 06404a
Packit 06404a
    data[i]=work[o]=y;
Packit 06404a
  }
Packit 06404a
}