examples/SFExamples/oggvorbiscodec94/src/tremor/floor0.c

00001 /********************************************************************
00002  *                                                                  *
00003  * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE.   *
00004  *                                                                  *
00005  * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
00006  * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
00007  * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
00008  *                                                                  *
00009  * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002    *
00010  * BY THE Xiph.Org FOUNDATION http://www.xiph.org/                  *
00011  *                                                                  *
00012  ********************************************************************
00013 
00014  function: floor backend 0 implementation
00015 
00016  ********************************************************************/
00017 
00018 #include <stdlib.h>
00019 #include <string.h>
00020 #include <math.h>
00021 #include "ogg.h"
00022 #include "ivorbiscodec.h"
00023 #include "codec_internal.h"
00024 #include "registry.h"
00025 #include "codebook.h"
00026 #include "misc.h"
00027 #include "os.h"
00028 
00029 #define LSP_FRACBITS 14
00030 
00031 typedef struct {
00032   long n;
00033   int ln;
00034   int  m;
00035   int *linearmap;
00036 
00037   vorbis_info_floor0 *vi;
00038   ogg_int32_t *lsp_look;
00039 
00040 } vorbis_look_floor0;
00041 
00042 /*************** LSP decode ********************/
00043 
00044 #include "lsp_lookup.h"
00045 
00046 /* interpolated 1./sqrt(p) where .5 <= a < 1. (.100000... to .111111...) in
00047    16.16 format 
00048    returns in m.8 format */
00049 
00050 const static long ADJUST_SQRT2[2]={8192,5792};
00051 static ogg_int32_t vorbis_invsqlook_i(long a,long e){
00052   long i=(a&0x7fff)>>(INVSQ_LOOKUP_I_SHIFT-1); 
00053   long d=a&INVSQ_LOOKUP_I_MASK;                              /*  0.10 */
00054   long val=INVSQ_LOOKUP_I[i]-                                /*  1.16 */
00055     ((INVSQ_LOOKUP_IDel[i]*d)>>INVSQ_LOOKUP_I_SHIFT);        /* result 1.16 */
00056   val*=ADJUST_SQRT2[e&1];
00057   e=(e>>1)+21;
00058   return(val>>e);
00059 }
00060 
00061 /* interpolated lookup based fromdB function, domain -140dB to 0dB only */
00062 /* a is in n.12 format */
00063 static ogg_int32_t vorbis_fromdBlook_i(long a){
00064   int i=(-a)>>(12-FROMdB2_SHIFT);
00065   if(i<0) return 0x7fffffff;
00066   if(i>=(FROMdB_LOOKUP_SZ<<FROMdB_SHIFT))return 0;
00067   
00068   return FROMdB_LOOKUP[i>>FROMdB_SHIFT] * FROMdB2_LOOKUP[i&FROMdB2_MASK];
00069 }
00070 
00071 /* interpolated lookup based cos function, domain 0 to PI only */
00072 /* a is in 0.16 format, where 0==0, 2^^16-1==PI, return 0.14 */
00073 static ogg_int32_t vorbis_coslook_i(long a){
00074   int i=a>>COS_LOOKUP_I_SHIFT;
00075   int d=a&COS_LOOKUP_I_MASK;
00076   return COS_LOOKUP_I[i]- ((d*(COS_LOOKUP_I[i]-COS_LOOKUP_I[i+1]))>>
00077                            COS_LOOKUP_I_SHIFT);
00078 }
00079 
00080 /* interpolated lookup based cos function */
00081 /* a is in 0.16 format, where 0==0, 2^^16==PI, return .LSP_FRACBITS */
00082 static ogg_int32_t vorbis_coslook2_i(long a){
00083   a=a&0x1ffff;
00084 
00085   if(a>0x10000)a=0x20000-a;
00086   {               
00087     int i=a>>COS_LOOKUP_I_SHIFT;
00088     int d=a&COS_LOOKUP_I_MASK;
00089     a=((COS_LOOKUP_I[i]<<COS_LOOKUP_I_SHIFT)-
00090        d*(COS_LOOKUP_I[i]-COS_LOOKUP_I[i+1]))>>
00091       (COS_LOOKUP_I_SHIFT-LSP_FRACBITS+14);
00092   }
00093   
00094   return(a);
00095 }
00096 
00097 const static int barklook[28]={
00098   0,100,200,301,          405,516,635,766,
00099   912,1077,1263,1476,     1720,2003,2333,2721,
00100   3184,3742,4428,5285,    6376,7791,9662,12181,
00101   15624,20397,27087,36554
00102 };
00103 
00104 /* used in init only; interpolate the long way */
00105 static ogg_int32_t toBARK(int n){
00106   int i;
00107   for(i=0;i<27;i++) 
00108     if(n>=barklook[i] && n<barklook[i+1])break;
00109   
00110   if(i==27){
00111     return 27<<15;
00112   }else{
00113     int gap=barklook[i+1]-barklook[i];
00114     int del=n-barklook[i];
00115 
00116     return((i<<15)+((del<<15)/gap));
00117   }
00118 }
00119 
00120 static const unsigned char MLOOP_1[64]={
00121    0,10,11,11, 12,12,12,12, 13,13,13,13, 13,13,13,13,
00122   14,14,14,14, 14,14,14,14, 14,14,14,14, 14,14,14,14,
00123   15,15,15,15, 15,15,15,15, 15,15,15,15, 15,15,15,15,
00124   15,15,15,15, 15,15,15,15, 15,15,15,15, 15,15,15,15,
00125 };
00126 
00127 static const unsigned char MLOOP_2[64]={
00128   0,4,5,5, 6,6,6,6, 7,7,7,7, 7,7,7,7,
00129   8,8,8,8, 8,8,8,8, 8,8,8,8, 8,8,8,8,
00130   9,9,9,9, 9,9,9,9, 9,9,9,9, 9,9,9,9,
00131   9,9,9,9, 9,9,9,9, 9,9,9,9, 9,9,9,9,
00132 };
00133 
00134 static const unsigned char MLOOP_3[8]={0,1,2,2,3,3,3,3};
00135 
00136 void vorbis_lsp_to_curve(ogg_int32_t *curve,int *map,int n,int ln,
00137                          ogg_int32_t *lsp,int m,
00138                          ogg_int32_t amp,
00139                          ogg_int32_t ampoffset,
00140                          ogg_int32_t *icos){
00141 
00142   /* 0 <= m < 256 */
00143 
00144   /* set up for using all int later */
00145   int i;
00146   int ampoffseti=ampoffset*4096;
00147   int ampi=amp;
00148   ogg_int32_t *ilsp=(ogg_int32_t *)_ogg_malloc(m*sizeof(*ilsp));
00149   /* lsp is in 8.24, range 0 to PI; coslook wants it in .16 0 to 1*/
00150   for(i=0;i<m;i++){
00151 #ifndef _LOW_ACCURACY_
00152     ogg_int32_t val=MULT32(lsp[i],0x517cc2);
00153 #else
00154     ogg_int32_t val=((lsp[i]>>10)*0x517d)>>14;
00155 #endif
00156 
00157     /* safeguard against a malicious stream */
00158     if(val<0 || (val>>COS_LOOKUP_I_SHIFT)>=COS_LOOKUP_I_SZ){
00159       memset(curve,0,sizeof(*curve)*n);
00160       _ogg_free(ilsp);
00161       return;
00162     }
00163 
00164     ilsp[i]=vorbis_coslook_i(val);
00165   }
00166 
00167   i=0;
00168   while(i<n){
00169     int j,k=map[i];
00170     ogg_uint32_t pi=46341; /* 2**-.5 in 0.16 */
00171     ogg_uint32_t qi=46341;
00172     ogg_int32_t qexp=0,shift;
00173     ogg_int32_t wi=icos[k];
00174 
00175 #ifdef _V_LSP_MATH_ASM
00176     lsp_loop_asm(&qi,&pi,&qexp,ilsp,wi,m);
00177 
00178     pi=((pi*pi)>>16);
00179     qi=((qi*qi)>>16);
00180     
00181     if(m&1){
00182       qexp= qexp*2-28*((m+1)>>1)+m;          
00183       pi*=(1<<14)-((wi*wi)>>14);
00184       qi+=pi>>14;     
00185     }else{
00186       qexp= qexp*2-13*m;
00187       
00188       pi*=(1<<14)-wi;
00189       qi*=(1<<14)+wi;
00190       
00191       qi=(qi+pi)>>14;
00192     }
00193     
00194     if(qi&0xffff0000){ /* checks for 1.xxxxxxxxxxxxxxxx */
00195       qi>>=1; qexp++; 
00196     }else
00197       lsp_norm_asm(&qi,&qexp);
00198 
00199 #else
00200 
00201     qi*=labs(ilsp[0]-wi);
00202     pi*=labs(ilsp[1]-wi);
00203 
00204     for(j=3;j<m;j+=2){
00205       shift=MLOOP_1[(pi|qi)>>25];       //patch
00206       if(!shift){
00207         shift=MLOOP_2[(pi|qi)>>19];
00208         if(!shift){
00209                 shift=MLOOP_3[(pi|qi)>>16];             
00210         }
00211       }
00212          
00213       qi=(qi>>shift)*labs(ilsp[j-1]-wi);
00214       pi=(pi>>shift)*labs(ilsp[j]-wi);
00215       qexp+=shift;
00216     }
00217     
00218     shift=MLOOP_1[(pi|qi)>>25]; //patch
00219     if(!shift){
00220         shift=MLOOP_2[(pi|qi)>>19];
00221         if(!shift){
00222                 shift=MLOOP_3[(pi|qi)>>16];     
00223         }
00224     }
00225       
00226 
00227     /* pi,qi normalized collectively, both tracked using qexp */
00228 
00229     if(m&1){
00230       /* odd order filter; slightly assymetric */
00231       /* the last coefficient */
00232       qi=(qi>>shift)*labs(ilsp[j-1]-wi);
00233       pi=(pi>>shift)<<14;
00234       qexp+=shift;
00235           shift=MLOOP_1[(pi|qi)>>25]; //patch
00236       if(!shift){
00237           shift=MLOOP_2[(pi|qi)>>19];   
00238               if(!shift){
00239                         shift=MLOOP_3[(pi|qi)>>16];     
00240                   }     
00241       }
00242         
00243           
00244       
00245       pi>>=shift;
00246       qi>>=shift;
00247       qexp+=shift-14*((m+1)>>1);
00248 
00249       pi=((pi*pi)>>16);
00250       qi=((qi*qi)>>16);
00251       qexp=qexp*2+m;
00252 
00253       pi*=(1<<14)-((wi*wi)>>14);
00254       qi+=pi>>14;
00255 
00256     }else{
00257       /* even order filter; still symmetric */
00258 
00259       /* p*=p(1-w), q*=q(1+w), let normalization drift because it isn't
00260          worth tracking step by step */
00261       
00262       pi>>=shift;
00263       qi>>=shift;
00264       qexp+=shift-7*m;
00265 
00266       pi=((pi*pi)>>16);
00267       qi=((qi*qi)>>16);
00268       qexp=qexp*2+m;
00269       
00270       pi*=(1<<14)-wi;
00271       qi*=(1<<14)+wi;
00272       qi=(qi+pi)>>14;
00273       
00274     }
00275     
00276 
00277     /* we've let the normalization drift because it wasn't important;
00278        however, for the lookup, things must be normalized again.  We
00279        need at most one right shift or a number of left shifts */
00280 
00281     if(qi&0xffff0000){ /* checks for 1.xxxxxxxxxxxxxxxx */
00282       qi>>=1; qexp++; 
00283     }else
00284       while(qi && !(qi&0x8000)){ /* checks for 0.0xxxxxxxxxxxxxxx or less*/
00285         qi<<=1; qexp--; 
00286       }
00287 
00288 #endif
00289 
00290     amp=vorbis_fromdBlook_i(ampi*                     /*  n.4         */
00291                             vorbis_invsqlook_i(qi,qexp)- 
00292                                                       /*  m.8, m+n<=8 */
00293                             ampoffseti);              /*  8.12[0]     */
00294     
00295 #ifdef _LOW_ACCURACY_
00296     amp>>=9;
00297 #endif
00298     curve[i]= MULT31_SHIFT15(curve[i],amp);
00299     while(map[++i]==k) curve[i]= MULT31_SHIFT15(curve[i],amp);
00300   }
00301 _ogg_free(ilsp);
00302 ln = ln; //patch
00303 }
00304 
00305 /*************** vorbis decode glue ************/
00306 
00307 static void floor0_free_info(vorbis_info_floor *i){
00308   vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
00309   if(info){
00310     memset(info,0,sizeof(*info));
00311     _ogg_free(info);
00312   }
00313 }
00314 
00315 static void floor0_free_look(vorbis_look_floor *i){
00316   vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
00317   if(look){
00318 
00319     if(look->linearmap)_ogg_free(look->linearmap);
00320     if(look->lsp_look)_ogg_free(look->lsp_look);
00321     memset(look,0,sizeof(*look));
00322     _ogg_free(look);
00323   }
00324 }
00325 
00326 static vorbis_info_floor *floor0_unpack (vorbis_info *vi,oggpack_buffer *opb){
00327   codec_setup_info     *ci=(codec_setup_info *)vi->codec_setup;
00328   int j;
00329 
00330   vorbis_info_floor0 *info=(vorbis_info_floor0 *)_ogg_malloc(sizeof(*info));
00331   info->order=oggpack_read(opb,8);
00332   info->rate=oggpack_read(opb,16);
00333   info->barkmap=oggpack_read(opb,16);
00334   info->ampbits=oggpack_read(opb,6);
00335   info->ampdB=oggpack_read(opb,8);
00336   info->numbooks=oggpack_read(opb,4)+1;
00337   
00338   if(info->order<1)goto err_out;
00339   if(info->rate<1)goto err_out;
00340   if(info->barkmap<1)goto err_out;
00341   if(info->numbooks<1)goto err_out;
00342     
00343   for(j=0;j<info->numbooks;j++){
00344     info->books[j]=oggpack_read(opb,8);
00345     if(info->books[j]<0 || info->books[j]>=ci->books)goto err_out;
00346   }
00347   return(info);
00348 
00349  err_out:
00350   floor0_free_info(info);
00351   return(NULL);
00352 }
00353 
00354 /* initialize Bark scale and normalization lookups.  We could do this
00355    with static tables, but Vorbis allows a number of possible
00356    combinations, so it's best to do it computationally.
00357 
00358    The below is authoritative in terms of defining scale mapping.
00359    Note that the scale depends on the sampling rate as well as the
00360    linear block and mapping sizes */
00361 
00362 static vorbis_look_floor *floor0_look (vorbis_dsp_state *vd,vorbis_info_mode *mi,
00363                               vorbis_info_floor *i){
00364   int j;
00365   vorbis_info        *vi=vd->vi;
00366   codec_setup_info   *ci=(codec_setup_info *)vi->codec_setup;
00367   vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
00368   vorbis_look_floor0 *look=(vorbis_look_floor0 *)_ogg_calloc(1,sizeof(*look));
00369   look->m=info->order;
00370   look->n=ci->blocksizes[mi->blockflag]/2;
00371   look->ln=info->barkmap;
00372   look->vi=info;
00373 
00374   /* the mapping from a linear scale to a smaller bark scale is
00375      straightforward.  We do *not* make sure that the linear mapping
00376      does not skip bark-scale bins; the decoder simply skips them and
00377      the encoder may do what it wishes in filling them.  They're
00378      necessary in some mapping combinations to keep the scale spacing
00379      accurate */
00380   look->linearmap=(int *)_ogg_malloc((look->n+1)*sizeof(*look->linearmap));
00381   for(j=0;j<look->n;j++){
00382 
00383     int val=(look->ln*
00384              ((toBARK(info->rate/2*j/look->n)<<11)/toBARK(info->rate/2)))>>11;
00385 
00386     if(val>=look->ln)val=look->ln-1; /* guard against the approximation */
00387     look->linearmap[j]=val;
00388   }
00389   look->linearmap[j]=-1;
00390 
00391   look->lsp_look=(ogg_int32_t *)_ogg_malloc(look->ln*sizeof(*look->lsp_look));
00392   for(j=0;j<look->ln;j++)
00393     look->lsp_look[j]=vorbis_coslook2_i(0x10000*j/look->ln);
00394 
00395   return look;
00396 }
00397 void *_vorbis_block_alloc(vorbis_block *vb,long bytes);
00398 static void *floor0_inverse1(vorbis_block *vb,vorbis_look_floor *i){
00399   vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
00400   vorbis_info_floor0 *info=look->vi;
00401   int j,k;
00402   
00403   int ampraw=oggpack_read(&vb->opb,info->ampbits);
00404   if(ampraw>0){ /* also handles the -1 out of data case */
00405     long maxval=(1<<info->ampbits)-1;
00406     int amp=((ampraw*info->ampdB)<<4)/maxval;
00407     int booknum=oggpack_read(&vb->opb,_ilog(info->numbooks));
00408     
00409     if(booknum!=-1 && booknum<info->numbooks){ /* be paranoid */
00410       codec_setup_info  *ci=(codec_setup_info *)vb->vd->vi->codec_setup;
00411       codebook *b=ci->fullbooks+info->books[booknum];
00412       ogg_int32_t last=0;
00413       ogg_int32_t *lsp=(ogg_int32_t *)_vorbis_block_alloc(vb,sizeof(*lsp)*(look->m+1));
00414             
00415       for(j=0;j<look->m;j+=b->dim)
00416         if(vorbis_book_decodev_set(b,lsp+j,&vb->opb,b->dim,-24)==-1)goto eop;
00417       for(j=0;j<look->m;){
00418         for(k=0;k<b->dim;k++,j++)lsp[j]+=last;
00419         last=lsp[j-1];
00420       }
00421       
00422       lsp[look->m]=amp;
00423       return(lsp);
00424     }
00425   }
00426  eop:
00427   return(NULL);
00428 }
00429 
00430 static int floor0_inverse2(vorbis_block *vb,vorbis_look_floor *i,
00431                            void *memo,ogg_int32_t *out){
00432   vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
00433   vorbis_info_floor0 *info=look->vi;
00434   vb = vb; //patch
00435   if(memo){
00436     ogg_int32_t *lsp=(ogg_int32_t *)memo;
00437     ogg_int32_t amp=lsp[look->m];
00438 
00439     /* take the coefficients back to a spectral envelope curve */
00440     vorbis_lsp_to_curve(out,look->linearmap,look->n,look->ln,
00441                         lsp,look->m,amp,info->ampdB,look->lsp_look);
00442     return(1);
00443   }
00444   memset(out,0,sizeof(*out)*look->n);
00445   return(0);
00446 }
00447 
00448 /* export hooks */
00449 const vorbis_func_floor floor0_exportbundle={
00450   &floor0_unpack,&floor0_look,&floor0_free_info,
00451   &floor0_free_look,&floor0_inverse1,&floor0_inverse2
00452 };
00453 
00454 

Generated by  doxygen 1.6.2