⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lsp.c

📁 fix point版本的Ogg Vorbis decoder
💻 C
字号:
/******************************************************************** *                                                                  * * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   * * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     * * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       * *                                                                  * * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001             * * by the XIPHOPHORUS Company http://www.xiph.org/                  * *                                                                  * ********************************************************************  function: LSP (also called LSF) conversion routines  last mod: $Id: lsp.c,v 1.20 2001/12/20 01:00:27 segher Exp $  The LSP generation code is taken (with minimal modification and a  few bugfixes) from "On the Computation of the LSP Frequencies" by  Joseph Rothweiler <rothwlr@altavista.net>, available at:    http://www2.xtdl.com/~rothwlr/lsfpaper/lsfpage.html  ********************************************************************//* Note that the lpc-lsp conversion finds the roots of polynomial with   an iterative root polisher (CACM algorithm 283).  It *is* possible   to confuse this algorithm into not converging; that should only   happen with absurdly closely spaced roots (very sharp peaks in the   LPC f response) which in turn should be impossible in our use of   the code.  If this *does* happen anyway, it's a bug in the floor   finder; find the cause of the confusion (probably a single bin   spike or accidental near-float-limit resolution problems) and   correct it. */#include <math.h>#include <string.h>#include <stdlib.h>#include "ogg_os_types.h"#include "lsp.h"#include "os.h"#include "misc.h"#include "scales.h"#define INT_LOOKUP#if defined(FIXED_POINT) || defined(INT_LOOKUP)#include "lookup.h"static int MLOOP_1[64]={   0,10,11,11, 12,12,12,12, 13,13,13,13, 13,13,13,13,  14,14,14,14, 14,14,14,14, 14,14,14,14, 14,14,14,14,  15,15,15,15, 15,15,15,15, 15,15,15,15, 15,15,15,15,  15,15,15,15, 15,15,15,15, 15,15,15,15, 15,15,15,15,};static int MLOOP_2[64]={  0,4,5,5, 6,6,6,6, 7,7,7,7, 7,7,7,7,  8,8,8,8, 8,8,8,8, 8,8,8,8, 8,8,8,8,  9,9,9,9, 9,9,9,9, 9,9,9,9, 9,9,9,9,  9,9,9,9, 9,9,9,9, 9,9,9,9, 9,9,9,9,};static int MLOOP_3[8]={0,1,2,2,3,3,3,3};/* side effect: changes *lsp to cosines of lsp */void vorbis_lsp_to_curve(FIXP *curve,int *map,int n,int ln,FIXP *lsp,int m,			    FIXP amp,FIXP ampoffset){  /* 0 <= m < 256 */  int i;#ifndef FIXED_POINT  int ampoffseti=rint(ampoffset*4096.f);  int ampi=rint(amp*16.f);  long *ilsp=alloca(m*sizeof(*ilsp));  for(i=0;i<m;i++)ilsp[i]=vorbis_coslook_i(lsp[i]/M_PI*65536.f+.5f);#else  int ampoffseti=ampoffset*4096;  int ampi=amp;  FIXP *ilsp=lsp;  for(i=0;i<m;i++)ilsp[i]=vorbis_coslook_i(MUL(16,lsp[i],(int)(65536.0/M_PI+.5)));#endif  i=0;  while(i<n){    int j,k=map[i];    unsigned long pi=46341; /* 2**-.5 in 0.16 */    unsigned long qi=46341;    int qexp=0,shift;    long wi=vorbis_coslook_i(k*65536/ln);    qi*=labs(ilsp[0]-wi);    pi*=labs(ilsp[1]-wi);    for(j=3;j<m;j+=2){      if(!(shift=MLOOP_1[(pi|qi)>>25]))	if(!(shift=MLOOP_2[(pi|qi)>>19]))	  shift=MLOOP_3[(pi|qi)>>16];      qi=(qi>>shift)*labs(ilsp[j-1]-wi);      pi=(pi>>shift)*labs(ilsp[j]-wi);      qexp+=shift;    }    if(!(shift=MLOOP_1[(pi|qi)>>25]))      if(!(shift=MLOOP_2[(pi|qi)>>19]))	shift=MLOOP_3[(pi|qi)>>16];    /* pi,qi normalized collectively, both tracked using qexp */    if(m&1){      /* odd order filter; slightly assymetric */      /* the last coefficient */      qi=(qi>>shift)*labs(ilsp[j-1]-wi);      pi=(pi>>shift)<<14;      qexp+=shift;      if(!(shift=MLOOP_1[(pi|qi)>>25]))	if(!(shift=MLOOP_2[(pi|qi)>>19]))	  shift=MLOOP_3[(pi|qi)>>16];            pi>>=shift;      qi>>=shift;      qexp+=shift-14*((m+1)>>1);      pi=((pi*pi)>>16);      qi=((qi*qi)>>16);      qexp=qexp*2+m;      pi*=(1<<14)-((wi*wi)>>14);      qi+=pi>>14;    }else{      /* even order filter; still symmetric */      /* p*=p(1-w), q*=q(1+w), let normalization drift because it isn't	 worth tracking step by step */            pi>>=shift;      qi>>=shift;      qexp+=shift-7*m;      pi=((pi*pi)>>16);      qi=((qi*qi)>>16);      qexp=qexp*2+m;            pi*=(1<<14)-wi;      qi*=(1<<14)+wi;      qi=(qi+pi)>>14;          }        /* we've let the normalization drift because it wasn't important;       however, for the lookup, things must be normalized again.  We       need at most one right shift or a number of left shifts */    if(qi&0xffff0000){ /* checks for 1.xxxxxxxxxxxxxxxx */      qi>>=1; qexp++;     }else      while(qi && !(qi&0x8000)){ /* checks for 0.0xxxxxxxxxxxxxxx or less*/	qi<<=1; qexp--;       }    amp=vorbis_fromdBlook_i(ampi*                     /*  n.4         */			    vorbis_invsqlook_i(qi,qexp)- 			                              /*  m.8, m+n<=8 */			    ampoffseti);              /*  8.12[0]     */    /*     * FIXP note: curve[] (x.16) * amp (x.30) = (x.46).     * We want to scale it back to FIXP_FRACBITS.     */    curve[i]=MUL(46-FIXP_FRACBITS,curve[i],amp);    while(map[++i]==k)curve[i]=MUL(46-FIXP_FRACBITS,curve[i],amp);  }}#else/* old, nonoptimized but simple version for any poor sap who needs to   figure out what the hell this code does, or wants the other   fraction of a dB precision *//* side effect: changes *lsp to cosines of lsp */void vorbis_lsp_to_curve(float *curve,int *map,int n,int ln,float *lsp,int m,			    float amp,float ampoffset){  int i;  float wdel=M_PI/ln;  for(i=0;i<m;i++)lsp[i]=2.f*cos(lsp[i]);  i=0;  while(i<n){    int j,k=map[i];    float p=.5f;    float q=.5f;    float w=2.f*cos(wdel*k);    for(j=1;j<m;j+=2){      q *= w-lsp[j-1];      p *= w-lsp[j];    }    if(j==m){      /* odd order filter; slightly assymetric */      /* the last coefficient */      q*=w-lsp[j-1];      p*=p*(4.f-w*w);      q*=q;    }else{      /* even order filter; still symmetric */      p*=p*(2.f-w);      q*=q*(2.f+w);    }    q=fromdB(amp/sqrt(p+q)-ampoffset);    curve[i]*=q;    while(map[++i]==k)curve[i]*=q;  }}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -