00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
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 
00043 
00044 #include "lsp_lookup.h"
00045 
00046 
00047 
00048 
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;                              
00054   long val=INVSQ_LOOKUP_I[i]-                                
00055     ((INVSQ_LOOKUP_IDel[i]*d)>>INVSQ_LOOKUP_I_SHIFT);        
00056   val*=ADJUST_SQRT2[e&1];
00057   e=(e>>1)+21;
00058   return(val>>e);
00059 }
00060 
00061 
00062 
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 
00072 
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 
00081 
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 
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   
00143 
00144   
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   
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     
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; 
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){ 
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];       
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]; 
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     
00228 
00229     if(m&1){
00230       
00231       
00232       qi=(qi>>shift)*labs(ilsp[j-1]-wi);
00233       pi=(pi>>shift)<<14;
00234       qexp+=shift;
00235           shift=MLOOP_1[(pi|qi)>>25]; 
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       
00258 
00259       
00260 
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     
00278 
00279 
00280 
00281     if(qi&0xffff0000){ 
00282       qi>>=1; qexp++; 
00283     }else
00284       while(qi && !(qi&0x8000)){ 
00285         qi<<=1; qexp--; 
00286       }
00287 
00288 #endif
00289 
00290     amp=vorbis_fromdBlook_i(ampi*                     
00291                             vorbis_invsqlook_i(qi,qexp)- 
00292                                                       
00293                             ampoffseti);              
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; 
00303 }
00304 
00305 
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 
00355 
00356 
00357 
00358 
00359 
00360 
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   
00375 
00376 
00377 
00378 
00379 
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; 
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){ 
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){ 
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; 
00435   if(memo){
00436     ogg_int32_t *lsp=(ogg_int32_t *)memo;
00437     ogg_int32_t amp=lsp[look->m];
00438 
00439     
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 
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