Blame lib/lsp.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: LSP (also called LSF) conversion routines
Packit 06404a
  last mod: $Id: lsp.c 19453 2015-03-02 22:35:34Z xiphmont $
Packit 06404a
Packit 06404a
  The LSP generation code is taken (with minimal modification and a
Packit 06404a
  few bugfixes) from "On the Computation of the LSP Frequencies" by
Packit 06404a
  Joseph Rothweiler (see http://www.rothweiler.us for contact info).
Packit 06404a
  The paper is available at:
Packit 06404a
Packit 06404a
  http://www.myown1.com/joe/lsf
Packit 06404a
Packit 06404a
 ********************************************************************/
Packit 06404a
Packit 06404a
/* Note that the lpc-lsp conversion finds the roots of polynomial with
Packit 06404a
   an iterative root polisher (CACM algorithm 283).  It *is* possible
Packit 06404a
   to confuse this algorithm into not converging; that should only
Packit 06404a
   happen with absurdly closely spaced roots (very sharp peaks in the
Packit 06404a
   LPC f response) which in turn should be impossible in our use of
Packit 06404a
   the code.  If this *does* happen anyway, it's a bug in the floor
Packit 06404a
   finder; find the cause of the confusion (probably a single bin
Packit 06404a
   spike or accidental near-float-limit resolution problems) and
Packit 06404a
   correct it. */
Packit 06404a
Packit 06404a
#include <math.h>
Packit 06404a
#include <string.h>
Packit 06404a
#include <stdlib.h>
Packit 06404a
#include "lsp.h"
Packit 06404a
#include "os.h"
Packit 06404a
#include "misc.h"
Packit 06404a
#include "lookup.h"
Packit 06404a
#include "scales.h"
Packit 06404a
Packit 06404a
/* three possible LSP to f curve functions; the exact computation
Packit 06404a
   (float), a lookup based float implementation, and an integer
Packit 06404a
   implementation.  The float lookup is likely the optimal choice on
Packit 06404a
   any machine with an FPU.  The integer implementation is *not* fixed
Packit 06404a
   point (due to the need for a large dynamic range and thus a
Packit 06404a
   separately tracked exponent) and thus much more complex than the
Packit 06404a
   relatively simple float implementations. It's mostly for future
Packit 06404a
   work on a fully fixed point implementation for processors like the
Packit 06404a
   ARM family. */
Packit 06404a
Packit 06404a
/* define either of these (preferably FLOAT_LOOKUP) to have faster
Packit 06404a
   but less precise implementation. */
Packit 06404a
#undef FLOAT_LOOKUP
Packit 06404a
#undef INT_LOOKUP
Packit 06404a
Packit 06404a
#ifdef FLOAT_LOOKUP
Packit 06404a
#include "lookup.c" /* catch this in the build system; we #include for
Packit 06404a
                       compilers (like gcc) that can't inline across
Packit 06404a
                       modules */
Packit 06404a
Packit 06404a
/* side effect: changes *lsp to cosines of lsp */
Packit 06404a
void vorbis_lsp_to_curve(float *curve,int *map,int n,int ln,float *lsp,int m,
Packit 06404a
                            float amp,float ampoffset){
Packit 06404a
  int i;
Packit 06404a
  float wdel=M_PI/ln;
Packit 06404a
  vorbis_fpu_control fpu;
Packit 06404a
Packit 06404a
  vorbis_fpu_setround(&fpu;;
Packit 06404a
  for(i=0;i
Packit 06404a
Packit 06404a
  i=0;
Packit 06404a
  while(i
Packit 06404a
    int k=map[i];
Packit 06404a
    int qexp;
Packit 06404a
    float p=.7071067812f;
Packit 06404a
    float q=.7071067812f;
Packit 06404a
    float w=vorbis_coslook(wdel*k);
Packit 06404a
    float *ftmp=lsp;
Packit 06404a
    int c=m>>1;
Packit 06404a
Packit 06404a
    while(c--){
Packit 06404a
      q*=ftmp[0]-w;
Packit 06404a
      p*=ftmp[1]-w;
Packit 06404a
      ftmp+=2;
Packit 06404a
    }
Packit 06404a
Packit 06404a
    if(m&1){
Packit 06404a
      /* odd order filter; slightly assymetric */
Packit 06404a
      /* the last coefficient */
Packit 06404a
      q*=ftmp[0]-w;
Packit 06404a
      q*=q;
Packit 06404a
      p*=p*(1.f-w*w);
Packit 06404a
    }else{
Packit 06404a
      /* even order filter; still symmetric */
Packit 06404a
      q*=q*(1.f+w);
Packit 06404a
      p*=p*(1.f-w);
Packit 06404a
    }
Packit 06404a
Packit 06404a
    q=frexp(p+q,&qexp);
Packit 06404a
    q=vorbis_fromdBlook(amp*
Packit 06404a
                        vorbis_invsqlook(q)*
Packit 06404a
                        vorbis_invsq2explook(qexp+m)-
Packit 06404a
                        ampoffset);
Packit 06404a
Packit 06404a
    do{
Packit 06404a
      curve[i++]*=q;
Packit 06404a
    }while(map[i]==k);
Packit 06404a
  }
Packit 06404a
  vorbis_fpu_restore(fpu);
Packit 06404a
}
Packit 06404a
Packit 06404a
#else
Packit 06404a
Packit 06404a
#ifdef INT_LOOKUP
Packit 06404a
#include "lookup.c" /* catch this in the build system; we #include for
Packit 06404a
                       compilers (like gcc) that can't inline across
Packit 06404a
                       modules */
Packit 06404a
Packit 06404a
static const int MLOOP_1[64]={
Packit 06404a
   0,10,11,11, 12,12,12,12, 13,13,13,13, 13,13,13,13,
Packit 06404a
  14,14,14,14, 14,14,14,14, 14,14,14,14, 14,14,14,14,
Packit 06404a
  15,15,15,15, 15,15,15,15, 15,15,15,15, 15,15,15,15,
Packit 06404a
  15,15,15,15, 15,15,15,15, 15,15,15,15, 15,15,15,15,
Packit 06404a
};
Packit 06404a
Packit 06404a
static const int MLOOP_2[64]={
Packit 06404a
  0,4,5,5, 6,6,6,6, 7,7,7,7, 7,7,7,7,
Packit 06404a
  8,8,8,8, 8,8,8,8, 8,8,8,8, 8,8,8,8,
Packit 06404a
  9,9,9,9, 9,9,9,9, 9,9,9,9, 9,9,9,9,
Packit 06404a
  9,9,9,9, 9,9,9,9, 9,9,9,9, 9,9,9,9,
Packit 06404a
};
Packit 06404a
Packit 06404a
static const int MLOOP_3[8]={0,1,2,2,3,3,3,3};
Packit 06404a
Packit 06404a
Packit 06404a
/* side effect: changes *lsp to cosines of lsp */
Packit 06404a
void vorbis_lsp_to_curve(float *curve,int *map,int n,int ln,float *lsp,int m,
Packit 06404a
                            float amp,float ampoffset){
Packit 06404a
Packit 06404a
  /* 0 <= m < 256 */
Packit 06404a
Packit 06404a
  /* set up for using all int later */
Packit 06404a
  int i;
Packit 06404a
  int ampoffseti=rint(ampoffset*4096.f);
Packit 06404a
  int ampi=rint(amp*16.f);
Packit 06404a
  long *ilsp=alloca(m*sizeof(*ilsp));
Packit 06404a
  for(i=0;i
Packit 06404a
Packit 06404a
  i=0;
Packit 06404a
  while(i
Packit 06404a
    int j,k=map[i];
Packit 06404a
    unsigned long pi=46341; /* 2**-.5 in 0.16 */
Packit 06404a
    unsigned long qi=46341;
Packit 06404a
    int qexp=0,shift;
Packit 06404a
    long wi=vorbis_coslook_i(k*65536/ln);
Packit 06404a
Packit 06404a
    qi*=labs(ilsp[0]-wi);
Packit 06404a
    pi*=labs(ilsp[1]-wi);
Packit 06404a
Packit 06404a
    for(j=3;j
Packit 06404a
      if(!(shift=MLOOP_1[(pi|qi)>>25]))
Packit 06404a
        if(!(shift=MLOOP_2[(pi|qi)>>19]))
Packit 06404a
          shift=MLOOP_3[(pi|qi)>>16];
Packit 06404a
      qi=(qi>>shift)*labs(ilsp[j-1]-wi);
Packit 06404a
      pi=(pi>>shift)*labs(ilsp[j]-wi);
Packit 06404a
      qexp+=shift;
Packit 06404a
    }
Packit 06404a
    if(!(shift=MLOOP_1[(pi|qi)>>25]))
Packit 06404a
      if(!(shift=MLOOP_2[(pi|qi)>>19]))
Packit 06404a
        shift=MLOOP_3[(pi|qi)>>16];
Packit 06404a
Packit 06404a
    /* pi,qi normalized collectively, both tracked using qexp */
Packit 06404a
Packit 06404a
    if(m&1){
Packit 06404a
      /* odd order filter; slightly assymetric */
Packit 06404a
      /* the last coefficient */
Packit 06404a
      qi=(qi>>shift)*labs(ilsp[j-1]-wi);
Packit 06404a
      pi=(pi>>shift)<<14;
Packit 06404a
      qexp+=shift;
Packit 06404a
Packit 06404a
      if(!(shift=MLOOP_1[(pi|qi)>>25]))
Packit 06404a
        if(!(shift=MLOOP_2[(pi|qi)>>19]))
Packit 06404a
          shift=MLOOP_3[(pi|qi)>>16];
Packit 06404a
Packit 06404a
      pi>>=shift;
Packit 06404a
      qi>>=shift;
Packit 06404a
      qexp+=shift-14*((m+1)>>1);
Packit 06404a
Packit 06404a
      pi=((pi*pi)>>16);
Packit 06404a
      qi=((qi*qi)>>16);
Packit 06404a
      qexp=qexp*2+m;
Packit 06404a
Packit 06404a
      pi*=(1<<14)-((wi*wi)>>14);
Packit 06404a
      qi+=pi>>14;
Packit 06404a
Packit 06404a
    }else{
Packit 06404a
      /* even order filter; still symmetric */
Packit 06404a
Packit 06404a
      /* p*=p(1-w), q*=q(1+w), let normalization drift because it isn't
Packit 06404a
         worth tracking step by step */
Packit 06404a
Packit 06404a
      pi>>=shift;
Packit 06404a
      qi>>=shift;
Packit 06404a
      qexp+=shift-7*m;
Packit 06404a
Packit 06404a
      pi=((pi*pi)>>16);
Packit 06404a
      qi=((qi*qi)>>16);
Packit 06404a
      qexp=qexp*2+m;
Packit 06404a
Packit 06404a
      pi*=(1<<14)-wi;
Packit 06404a
      qi*=(1<<14)+wi;
Packit 06404a
      qi=(qi+pi)>>14;
Packit 06404a
Packit 06404a
    }
Packit 06404a
Packit 06404a
Packit 06404a
    /* we've let the normalization drift because it wasn't important;
Packit 06404a
       however, for the lookup, things must be normalized again.  We
Packit 06404a
       need at most one right shift or a number of left shifts */
Packit 06404a
Packit 06404a
    if(qi&0xffff0000){ /* checks for 1.xxxxxxxxxxxxxxxx */
Packit 06404a
      qi>>=1; qexp++;
Packit 06404a
    }else
Packit 06404a
      while(qi && !(qi&0x8000)){ /* checks for 0.0xxxxxxxxxxxxxxx or less*/
Packit 06404a
        qi<<=1; qexp--;
Packit 06404a
      }
Packit 06404a
Packit 06404a
    amp=vorbis_fromdBlook_i(ampi*                     /*  n.4         */
Packit 06404a
                            vorbis_invsqlook_i(qi,qexp)-
Packit 06404a
                                                      /*  m.8, m+n<=8 */
Packit 06404a
                            ampoffseti);              /*  8.12[0]     */
Packit 06404a
Packit 06404a
    curve[i]*=amp;
Packit 06404a
    while(map[++i]==k)curve[i]*=amp;
Packit 06404a
  }
Packit 06404a
}
Packit 06404a
Packit 06404a
#else
Packit 06404a
Packit 06404a
/* old, nonoptimized but simple version for any poor sap who needs to
Packit 06404a
   figure out what the hell this code does, or wants the other
Packit 06404a
   fraction of a dB precision */
Packit 06404a
Packit 06404a
/* side effect: changes *lsp to cosines of lsp */
Packit 06404a
void vorbis_lsp_to_curve(float *curve,int *map,int n,int ln,float *lsp,int m,
Packit 06404a
                            float amp,float ampoffset){
Packit 06404a
  int i;
Packit 06404a
  float wdel=M_PI/ln;
Packit 06404a
  for(i=0;i
Packit 06404a
Packit 06404a
  i=0;
Packit 06404a
  while(i
Packit 06404a
    int j,k=map[i];
Packit 06404a
    float p=.5f;
Packit 06404a
    float q=.5f;
Packit 06404a
    float w=2.f*cos(wdel*k);
Packit 06404a
    for(j=1;j
Packit 06404a
      q *= w-lsp[j-1];
Packit 06404a
      p *= w-lsp[j];
Packit 06404a
    }
Packit 06404a
    if(j==m){
Packit 06404a
      /* odd order filter; slightly assymetric */
Packit 06404a
      /* the last coefficient */
Packit 06404a
      q*=w-lsp[j-1];
Packit 06404a
      p*=p*(4.f-w*w);
Packit 06404a
      q*=q;
Packit 06404a
    }else{
Packit 06404a
      /* even order filter; still symmetric */
Packit 06404a
      p*=p*(2.f-w);
Packit 06404a
      q*=q*(2.f+w);
Packit 06404a
    }
Packit 06404a
Packit 06404a
    q=fromdB(amp/sqrt(p+q)-ampoffset);
Packit 06404a
Packit 06404a
    curve[i]*=q;
Packit 06404a
    while(map[++i]==k)curve[i]*=q;
Packit 06404a
  }
Packit 06404a
}
Packit 06404a
Packit 06404a
#endif
Packit 06404a
#endif
Packit 06404a
Packit 06404a
static void cheby(float *g, int ord) {
Packit 06404a
  int i, j;
Packit 06404a
Packit 06404a
  g[0] *= .5f;
Packit 06404a
  for(i=2; i<= ord; i++) {
Packit 06404a
    for(j=ord; j >= i; j--) {
Packit 06404a
      g[j-2] -= g[j];
Packit 06404a
      g[j] += g[j];
Packit 06404a
    }
Packit 06404a
  }
Packit 06404a
}
Packit 06404a
Packit 06404a
static int comp(const void *a,const void *b){
Packit 06404a
  return (*(float *)a<*(float *)b)-(*(float *)a>*(float *)b);
Packit 06404a
}
Packit 06404a
Packit 06404a
/* Newton-Raphson-Maehly actually functioned as a decent root finder,
Packit 06404a
   but there are root sets for which it gets into limit cycles
Packit 06404a
   (exacerbated by zero suppression) and fails.  We can't afford to
Packit 06404a
   fail, even if the failure is 1 in 100,000,000, so we now use
Packit 06404a
   Laguerre and later polish with Newton-Raphson (which can then
Packit 06404a
   afford to fail) */
Packit 06404a
Packit 06404a
#define EPSILON 10e-7
Packit 06404a
static int Laguerre_With_Deflation(float *a,int ord,float *r){
Packit 06404a
  int i,m;
Packit 06404a
  double *defl=alloca(sizeof(*defl)*(ord+1));
Packit 06404a
  for(i=0;i<=ord;i++)defl[i]=a[i];
Packit 06404a
Packit 06404a
  for(m=ord;m>0;m--){
Packit 06404a
    double new=0.f,delta;
Packit 06404a
Packit 06404a
    /* iterate a root */
Packit 06404a
    while(1){
Packit 06404a
      double p=defl[m],pp=0.f,ppp=0.f,denom;
Packit 06404a
Packit 06404a
      /* eval the polynomial and its first two derivatives */
Packit 06404a
      for(i=m;i>0;i--){
Packit 06404a
        ppp = new*ppp + pp;
Packit 06404a
        pp  = new*pp  + p;
Packit 06404a
        p   = new*p   + defl[i-1];
Packit 06404a
      }
Packit 06404a
Packit 06404a
      /* Laguerre's method */
Packit 06404a
      denom=(m-1) * ((m-1)*pp*pp - m*p*ppp);
Packit 06404a
      if(denom<0)
Packit 06404a
        return(-1);  /* complex root!  The LPC generator handed us a bad filter */
Packit 06404a
Packit 06404a
      if(pp>0){
Packit 06404a
        denom = pp + sqrt(denom);
Packit 06404a
        if(denom
Packit 06404a
      }else{
Packit 06404a
        denom = pp - sqrt(denom);
Packit 06404a
        if(denom>-(EPSILON))denom=-(EPSILON);
Packit 06404a
      }
Packit 06404a
Packit 06404a
      delta  = m*p/denom;
Packit 06404a
      new   -= delta;
Packit 06404a
Packit 06404a
      if(delta<0.f)delta*=-1;
Packit 06404a
Packit 06404a
      if(fabs(delta/new)<10e-12)break;
Packit 06404a
    }
Packit 06404a
Packit 06404a
    r[m-1]=new;
Packit 06404a
Packit 06404a
    /* forward deflation */
Packit 06404a
Packit 06404a
    for(i=m;i>0;i--)
Packit 06404a
      defl[i-1]+=new*defl[i];
Packit 06404a
    defl++;
Packit 06404a
Packit 06404a
  }
Packit 06404a
  return(0);
Packit 06404a
}
Packit 06404a
Packit 06404a
Packit 06404a
/* for spit-and-polish only */
Packit 06404a
static int Newton_Raphson(float *a,int ord,float *r){
Packit 06404a
  int i, k, count=0;
Packit 06404a
  double error=1.f;
Packit 06404a
  double *root=alloca(ord*sizeof(*root));
Packit 06404a
Packit 06404a
  for(i=0; i
Packit 06404a
Packit 06404a
  while(error>1e-20){
Packit 06404a
    error=0;
Packit 06404a
Packit 06404a
    for(i=0; i
Packit 06404a
      double pp=0.,delta;
Packit 06404a
      double rooti=root[i];
Packit 06404a
      double p=a[ord];
Packit 06404a
      for(k=ord-1; k>= 0; k--) {
Packit 06404a
Packit 06404a
        pp= pp* rooti + p;
Packit 06404a
        p = p * rooti + a[k];
Packit 06404a
      }
Packit 06404a
Packit 06404a
      delta = p/pp;
Packit 06404a
      root[i] -= delta;
Packit 06404a
      error+= delta*delta;
Packit 06404a
    }
Packit 06404a
Packit 06404a
    if(count>40)return(-1);
Packit 06404a
Packit 06404a
    count++;
Packit 06404a
  }
Packit 06404a
Packit 06404a
  /* Replaced the original bubble sort with a real sort.  With your
Packit 06404a
     help, we can eliminate the bubble sort in our lifetime. --Monty */
Packit 06404a
Packit 06404a
  for(i=0; i
Packit 06404a
  return(0);
Packit 06404a
}
Packit 06404a
Packit 06404a
Packit 06404a
/* Convert lpc coefficients to lsp coefficients */
Packit 06404a
int vorbis_lpc_to_lsp(float *lpc,float *lsp,int m){
Packit 06404a
  int order2=(m+1)>>1;
Packit 06404a
  int g1_order,g2_order;
Packit 06404a
  float *g1=alloca(sizeof(*g1)*(order2+1));
Packit 06404a
  float *g2=alloca(sizeof(*g2)*(order2+1));
Packit 06404a
  float *g1r=alloca(sizeof(*g1r)*(order2+1));
Packit 06404a
  float *g2r=alloca(sizeof(*g2r)*(order2+1));
Packit 06404a
  int i;
Packit 06404a
Packit 06404a
  /* even and odd are slightly different base cases */
Packit 06404a
  g1_order=(m+1)>>1;
Packit 06404a
  g2_order=(m)  >>1;
Packit 06404a
Packit 06404a
  /* Compute the lengths of the x polynomials. */
Packit 06404a
  /* Compute the first half of K & R F1 & F2 polynomials. */
Packit 06404a
  /* Compute half of the symmetric and antisymmetric polynomials. */
Packit 06404a
  /* Remove the roots at +1 and -1. */
Packit 06404a
Packit 06404a
  g1[g1_order] = 1.f;
Packit 06404a
  for(i=1;i<=g1_order;i++) g1[g1_order-i] = lpc[i-1]+lpc[m-i];
Packit 06404a
  g2[g2_order] = 1.f;
Packit 06404a
  for(i=1;i<=g2_order;i++) g2[g2_order-i] = lpc[i-1]-lpc[m-i];
Packit 06404a
Packit 06404a
  if(g1_order>g2_order){
Packit 06404a
    for(i=2; i<=g2_order;i++) g2[g2_order-i] += g2[g2_order-i+2];
Packit 06404a
  }else{
Packit 06404a
    for(i=1; i<=g1_order;i++) g1[g1_order-i] -= g1[g1_order-i+1];
Packit 06404a
    for(i=1; i<=g2_order;i++) g2[g2_order-i] += g2[g2_order-i+1];
Packit 06404a
  }
Packit 06404a
Packit 06404a
  /* Convert into polynomials in cos(alpha) */
Packit 06404a
  cheby(g1,g1_order);
Packit 06404a
  cheby(g2,g2_order);
Packit 06404a
Packit 06404a
  /* Find the roots of the 2 even polynomials.*/
Packit 06404a
  if(Laguerre_With_Deflation(g1,g1_order,g1r) ||
Packit 06404a
     Laguerre_With_Deflation(g2,g2_order,g2r))
Packit 06404a
    return(-1);
Packit 06404a
Packit 06404a
  Newton_Raphson(g1,g1_order,g1r); /* if it fails, it leaves g1r alone */
Packit 06404a
  Newton_Raphson(g2,g2_order,g2r); /* if it fails, it leaves g2r alone */
Packit 06404a
Packit 06404a
  qsort(g1r,g1_order,sizeof(*g1r),comp);
Packit 06404a
  qsort(g2r,g2_order,sizeof(*g2r),comp);
Packit 06404a
Packit 06404a
  for(i=0;i
Packit 06404a
    lsp[i*2] = acos(g1r[i]);
Packit 06404a
Packit 06404a
  for(i=0;i
Packit 06404a
    lsp[i*2+1] = acos(g2r[i]);
Packit 06404a
  return(0);
Packit 06404a
}