examples/SFExamples/oggvorbiscodec94/src/tremor/floor1.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 1 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 
00028 #define floor1_rangedB 140 /* floor 1 fixed at -140dB to 0dB range */
00029 
00030 typedef struct {
00031   int forward_index[VIF_POSIT+2];
00032   
00033   int hineighbor[VIF_POSIT];
00034   int loneighbor[VIF_POSIT];
00035   int posts;
00036 
00037   int n;
00038   int quant_q;
00039   vorbis_info_floor1 *vi;
00040 
00041 } vorbis_look_floor1;
00042 
00043 /***********************************************/
00044  
00045 static void floor1_free_info(vorbis_info_floor *i){
00046   vorbis_info_floor1 *info=(vorbis_info_floor1 *)i;
00047   if(info){
00048     memset(info,0,sizeof(*info));
00049     _ogg_free(info);
00050   }
00051 }
00052 
00053 static void floor1_free_look(vorbis_look_floor *i){
00054   vorbis_look_floor1 *look=(vorbis_look_floor1 *)i;
00055   if(look){
00056     memset(look,0,sizeof(*look));
00057     _ogg_free(look);
00058   }
00059 }
00060 
00061 static int ilog(unsigned int v){
00062   int ret=0;
00063   while(v){
00064     ret++;
00065     v>>=1;
00066   }
00067   return(ret);
00068 }
00069 
00070 static vorbis_info_floor *floor1_unpack (vorbis_info *vi,oggpack_buffer *opb){
00071   codec_setup_info     *ci=(codec_setup_info *)vi->codec_setup;
00072   int j,k,count=0,maxclass=-1,rangebits;
00073 
00074   vorbis_info_floor1 *info=(vorbis_info_floor1 *)_ogg_calloc(1,sizeof(*info));
00075   /* read partitions */
00076   info->partitions=oggpack_read(opb,5); /* only 0 to 31 legal */
00077   for(j=0;j<info->partitions;j++){
00078     info->partitionclass[j]=oggpack_read(opb,4); /* only 0 to 15 legal */
00079     if(maxclass<info->partitionclass[j])maxclass=info->partitionclass[j];
00080   }
00081 
00082   /* read partition classes */
00083   for(j=0;j<maxclass+1;j++){
00084     info->class_dim[j]=oggpack_read(opb,3)+1; /* 1 to 8 */
00085     info->class_subs[j]=oggpack_read(opb,2); /* 0,1,2,3 bits */
00086     if(info->class_subs[j]<0)
00087       goto err_out;
00088     if(info->class_subs[j])info->class_book[j]=oggpack_read(opb,8);
00089     if(info->class_book[j]<0 || info->class_book[j]>=ci->books)
00090       goto err_out;
00091     for(k=0;k<(1<<info->class_subs[j]);k++){
00092       info->class_subbook[j][k]=oggpack_read(opb,8)-1;
00093       if(info->class_subbook[j][k]<-1 || info->class_subbook[j][k]>=ci->books)
00094         goto err_out;
00095     }
00096   }
00097 
00098   /* read the post list */
00099   info->mult=oggpack_read(opb,2)+1;     /* only 1,2,3,4 legal now */ 
00100   rangebits=oggpack_read(opb,4);
00101 
00102   for(j=0,k=0;j<info->partitions;j++){
00103     count+=info->class_dim[info->partitionclass[j]]; 
00104     for(;k<count;k++){
00105       int t=info->postlist[k+2]=oggpack_read(opb,rangebits);
00106       if(t<0 || t>=(1<<rangebits))
00107         goto err_out;
00108     }
00109   }
00110   info->postlist[0]=0;
00111   info->postlist[1]=1<<rangebits;
00112 
00113   return(info);
00114   
00115  err_out:
00116   floor1_free_info(info);
00117   return(NULL);
00118 }
00119 
00120 static int icomp(const void *a,const void *b){
00121   return(**(int **)a-**(int **)b);
00122 }
00123 
00124 static vorbis_look_floor *floor1_look(vorbis_dsp_state *vd,vorbis_info_mode *mi,
00125                               vorbis_info_floor *in){
00126 
00127   int *sortpointer[VIF_POSIT+2];
00128   vorbis_info_floor1 *info=(vorbis_info_floor1 *)in;
00129   vorbis_look_floor1 *look=(vorbis_look_floor1 *)_ogg_calloc(1,sizeof(*look));
00130   int i,j,n=0;
00131   mi = mi; //patch
00132   vd = vd; //patch
00133   
00134   look->vi=info;
00135   look->n=info->postlist[1];
00136  
00137   /* we drop each position value in-between already decoded values,
00138      and use linear interpolation to predict each new value past the
00139      edges.  The positions are read in the order of the position
00140      list... we precompute the bounding positions in the lookup.  Of
00141      course, the neighbors can change (if a position is declined), but
00142      this is an initial mapping */
00143 
00144   for(i=0;i<info->partitions;i++)n+=info->class_dim[info->partitionclass[i]];
00145   n+=2;
00146   look->posts=n;
00147 
00148   /* also store a sorted position index */
00149   for(i=0;i<n;i++)sortpointer[i]=info->postlist+i;
00150   qsort(sortpointer,n,sizeof(*sortpointer),icomp);
00151 
00152   /* points from sort order back to range number */
00153   for(i=0;i<n;i++)look->forward_index[i]=sortpointer[i]-info->postlist;
00154   
00155   /* quantize values to multiplier spec */
00156   switch(info->mult){
00157   case 1: /* 1024 -> 256 */
00158     look->quant_q=256;
00159     break;
00160   case 2: /* 1024 -> 128 */
00161     look->quant_q=128;
00162     break;
00163   case 3: /* 1024 -> 86 */
00164     look->quant_q=86;
00165     break;
00166   case 4: /* 1024 -> 64 */
00167     look->quant_q=64;
00168     break;
00169   }
00170 
00171   /* discover our neighbors for decode where we don't use fit flags
00172      (that would push the neighbors outward) */
00173   for(i=0;i<n-2;i++){
00174     int lo=0;
00175     int hi=1;
00176     int lx=0;
00177     int hx=look->n;
00178     int currentx=info->postlist[i+2];
00179     for(j=0;j<i+2;j++){
00180       int x=info->postlist[j];
00181       if(x>lx && x<currentx){
00182         lo=j;
00183         lx=x;
00184       }
00185       if(x<hx && x>currentx){
00186         hi=j;
00187         hx=x;
00188       }
00189     }
00190     look->loneighbor[i]=lo;
00191     look->hineighbor[i]=hi;
00192   }
00193 
00194   return(look);
00195 }
00196 
00197 static int render_point(int x0,int x1,int y0,int y1,int x){
00198   y0&=0x7fff; /* mask off flag */
00199   y1&=0x7fff;
00200     
00201   {
00202     int dy=y1-y0;
00203     int adx=x1-x0;
00204     int ady=abs(dy);
00205     int err=ady*(x-x0);
00206     
00207     int off=err/adx;
00208     if(dy<0)return(y0-off);
00209     return(y0+off);
00210   }
00211 }
00212 
00213 #ifdef _LOW_ACCURACY_
00214 #  define XdB(n) ((((n)>>8)+1)>>1)
00215 #else
00216 #  define XdB(n) (n)
00217 #endif
00218 
00219 static const ogg_int32_t FLOOR_fromdB_LOOKUP[256]={
00220   XdB(0x000000e5), XdB(0x000000f4), XdB(0x00000103), XdB(0x00000114),
00221   XdB(0x00000126), XdB(0x00000139), XdB(0x0000014e), XdB(0x00000163),
00222   XdB(0x0000017a), XdB(0x00000193), XdB(0x000001ad), XdB(0x000001c9),
00223   XdB(0x000001e7), XdB(0x00000206), XdB(0x00000228), XdB(0x0000024c),
00224   XdB(0x00000272), XdB(0x0000029b), XdB(0x000002c6), XdB(0x000002f4),
00225   XdB(0x00000326), XdB(0x0000035a), XdB(0x00000392), XdB(0x000003cd),
00226   XdB(0x0000040c), XdB(0x00000450), XdB(0x00000497), XdB(0x000004e4),
00227   XdB(0x00000535), XdB(0x0000058c), XdB(0x000005e8), XdB(0x0000064a),
00228   XdB(0x000006b3), XdB(0x00000722), XdB(0x00000799), XdB(0x00000818),
00229   XdB(0x0000089e), XdB(0x0000092e), XdB(0x000009c6), XdB(0x00000a69),
00230   XdB(0x00000b16), XdB(0x00000bcf), XdB(0x00000c93), XdB(0x00000d64),
00231   XdB(0x00000e43), XdB(0x00000f30), XdB(0x0000102d), XdB(0x0000113a),
00232   XdB(0x00001258), XdB(0x0000138a), XdB(0x000014cf), XdB(0x00001629),
00233   XdB(0x0000179a), XdB(0x00001922), XdB(0x00001ac4), XdB(0x00001c82),
00234   XdB(0x00001e5c), XdB(0x00002055), XdB(0x0000226f), XdB(0x000024ac),
00235   XdB(0x0000270e), XdB(0x00002997), XdB(0x00002c4b), XdB(0x00002f2c),
00236   XdB(0x0000323d), XdB(0x00003581), XdB(0x000038fb), XdB(0x00003caf),
00237   XdB(0x000040a0), XdB(0x000044d3), XdB(0x0000494c), XdB(0x00004e10),
00238   XdB(0x00005323), XdB(0x0000588a), XdB(0x00005e4b), XdB(0x0000646b),
00239   XdB(0x00006af2), XdB(0x000071e5), XdB(0x0000794c), XdB(0x0000812e),
00240   XdB(0x00008993), XdB(0x00009283), XdB(0x00009c09), XdB(0x0000a62d),
00241   XdB(0x0000b0f9), XdB(0x0000bc79), XdB(0x0000c8b9), XdB(0x0000d5c4),
00242   XdB(0x0000e3a9), XdB(0x0000f274), XdB(0x00010235), XdB(0x000112fd),
00243   XdB(0x000124dc), XdB(0x000137e4), XdB(0x00014c29), XdB(0x000161bf),
00244   XdB(0x000178bc), XdB(0x00019137), XdB(0x0001ab4a), XdB(0x0001c70e),
00245   XdB(0x0001e4a1), XdB(0x0002041f), XdB(0x000225aa), XdB(0x00024962),
00246   XdB(0x00026f6d), XdB(0x000297f0), XdB(0x0002c316), XdB(0x0002f109),
00247   XdB(0x000321f9), XdB(0x00035616), XdB(0x00038d97), XdB(0x0003c8b4),
00248   XdB(0x000407a7), XdB(0x00044ab2), XdB(0x00049218), XdB(0x0004de23),
00249   XdB(0x00052f1e), XdB(0x0005855c), XdB(0x0005e135), XdB(0x00064306),
00250   XdB(0x0006ab33), XdB(0x00071a24), XdB(0x0007904b), XdB(0x00080e20),
00251   XdB(0x00089422), XdB(0x000922da), XdB(0x0009bad8), XdB(0x000a5cb6),
00252   XdB(0x000b091a), XdB(0x000bc0b1), XdB(0x000c8436), XdB(0x000d5471),
00253   XdB(0x000e3233), XdB(0x000f1e5f), XdB(0x001019e4), XdB(0x001125c1),
00254   XdB(0x00124306), XdB(0x001372d5), XdB(0x0014b663), XdB(0x00160ef7),
00255   XdB(0x00177df0), XdB(0x001904c1), XdB(0x001aa4f9), XdB(0x001c603d),
00256   XdB(0x001e384f), XdB(0x00202f0f), XdB(0x0022467a), XdB(0x002480b1),
00257   XdB(0x0026dff7), XdB(0x002966b3), XdB(0x002c1776), XdB(0x002ef4fc),
00258   XdB(0x0032022d), XdB(0x00354222), XdB(0x0038b828), XdB(0x003c67c2),
00259   XdB(0x004054ae), XdB(0x004482e8), XdB(0x0048f6af), XdB(0x004db488),
00260   XdB(0x0052c142), XdB(0x005821ff), XdB(0x005ddc33), XdB(0x0063f5b0),
00261   XdB(0x006a74a7), XdB(0x00715faf), XdB(0x0078bdce), XdB(0x0080967f),
00262   XdB(0x0088f1ba), XdB(0x0091d7f9), XdB(0x009b5247), XdB(0x00a56a41),
00263   XdB(0x00b02a27), XdB(0x00bb9ce2), XdB(0x00c7ce12), XdB(0x00d4ca17),
00264   XdB(0x00e29e20), XdB(0x00f15835), XdB(0x0101074b), XdB(0x0111bb4e),
00265   XdB(0x01238531), XdB(0x01367704), XdB(0x014aa402), XdB(0x016020a7),
00266   XdB(0x017702c3), XdB(0x018f6190), XdB(0x01a955cb), XdB(0x01c4f9cf),
00267   XdB(0x01e269a8), XdB(0x0201c33b), XdB(0x0223265a), XdB(0x0246b4ea),
00268   XdB(0x026c9302), XdB(0x0294e716), XdB(0x02bfda13), XdB(0x02ed9793),
00269   XdB(0x031e4e09), XdB(0x03522ee4), XdB(0x03896ed0), XdB(0x03c445e2),
00270   XdB(0x0402efd6), XdB(0x0445ac4b), XdB(0x048cbefc), XdB(0x04d87013),
00271   XdB(0x05290c67), XdB(0x057ee5ca), XdB(0x05da5364), XdB(0x063bb204),
00272   XdB(0x06a36485), XdB(0x0711d42b), XdB(0x0787710e), XdB(0x0804b299),
00273   XdB(0x088a17ef), XdB(0x0918287e), XdB(0x09af747c), XdB(0x0a50957e),
00274   XdB(0x0afc2f19), XdB(0x0bb2ef7f), XdB(0x0c759034), XdB(0x0d44d6ca),
00275   XdB(0x0e2195bc), XdB(0x0f0cad0d), XdB(0x10070b62), XdB(0x1111aeea),
00276   XdB(0x122da66c), XdB(0x135c120f), XdB(0x149e24d9), XdB(0x15f525b1),
00277   XdB(0x176270e3), XdB(0x18e7794b), XdB(0x1a85c9ae), XdB(0x1c3f06d1),
00278   XdB(0x1e14f07d), XdB(0x200963d7), XdB(0x221e5ccd), XdB(0x2455f870),
00279   XdB(0x26b2770b), XdB(0x29363e2b), XdB(0x2be3db5c), XdB(0x2ebe06b6),
00280   XdB(0x31c7a55b), XdB(0x3503ccd4), XdB(0x3875c5aa), XdB(0x3c210f44),
00281   XdB(0x4009632b), XdB(0x4432b8cf), XdB(0x48a149bc), XdB(0x4d59959e),
00282   XdB(0x52606733), XdB(0x57bad899), XdB(0x5d6e593a), XdB(0x6380b298),
00283   XdB(0x69f80e9a), XdB(0x70dafda8), XdB(0x78307d76), XdB(0x7fffffff),
00284 };
00285   
00286 static void render_line(int x0,int x1,int y0,int y1,ogg_int32_t *d){
00287   int dy=y1-y0;
00288   int adx=x1-x0;
00289   int ady=abs(dy);
00290   int base=dy/adx;
00291   int sy=(dy<0?base-1:base+1);
00292   int x=x0;
00293   int y=y0;
00294   int err=0;
00295 
00296   ady-=abs(base*adx);
00297 
00298   d[x]= MULT31_SHIFT15(d[x],FLOOR_fromdB_LOOKUP[y]);
00299 
00300   while(++x<x1){
00301     err=err+ady;
00302     if(err>=adx){
00303       err-=adx;
00304       y+=sy;
00305     }else{
00306       y+=base;
00307     }
00308     d[x]= MULT31_SHIFT15(d[x],FLOOR_fromdB_LOOKUP[y]);
00309   }
00310 }
00311 
00312 void *_vorbis_block_alloc(vorbis_block *vb,long bytes); //patch
00313 static void *floor1_inverse1(vorbis_block *vb,vorbis_look_floor *in){
00314   vorbis_look_floor1 *look=(vorbis_look_floor1 *)in;
00315   vorbis_info_floor1 *info=look->vi;
00316   codec_setup_info   *ci=(codec_setup_info *)vb->vd->vi->codec_setup;
00317   
00318   int i,j,k;
00319   codebook *books=ci->fullbooks;   
00320   
00321   /* unpack wrapped/predicted values from stream */
00322   if(oggpack_read(&vb->opb,1)==1){
00323     int *fit_value=(int *)_vorbis_block_alloc(vb,(look->posts)*sizeof(*fit_value));
00324     
00325     fit_value[0]=oggpack_read(&vb->opb,ilog(look->quant_q-1));
00326     fit_value[1]=oggpack_read(&vb->opb,ilog(look->quant_q-1));
00327     
00328     /* partition by partition */
00329     /* partition by partition */
00330     for(i=0,j=2;i<info->partitions;i++){
00331       int classv=info->partitionclass[i];
00332       int cdim=info->class_dim[classv];
00333       int csubbits=info->class_subs[classv];
00334       int csub=1<<csubbits;
00335       int cval=0;
00336 
00337       /* decode the partition's first stage cascade value */
00338       if(csubbits){
00339         cval=vorbis_book_decode(books+info->class_book[classv],&vb->opb);
00340 
00341         if(cval==-1)goto eop;
00342       }
00343 
00344       for(k=0;k<cdim;k++){
00345         int book=info->class_subbook[classv][cval&(csub-1)];
00346         cval>>=csubbits;
00347         if(book>=0){
00348           if((fit_value[j+k]=vorbis_book_decode(books+book,&vb->opb))==-1)
00349             goto eop;
00350         }else{
00351           fit_value[j+k]=0;
00352         }
00353       }
00354       j+=cdim;
00355     }
00356 
00357     /* unwrap positive values and reconsitute via linear interpolation */
00358     for(i=2;i<look->posts;i++){
00359       int predicted=render_point(info->postlist[look->loneighbor[i-2]],
00360                                  info->postlist[look->hineighbor[i-2]],
00361                                  fit_value[look->loneighbor[i-2]],
00362                                  fit_value[look->hineighbor[i-2]],
00363                                  info->postlist[i]);
00364       int hiroom=look->quant_q-predicted;
00365       int loroom=predicted;
00366       int room=(hiroom<loroom?hiroom:loroom)<<1;
00367       int val=fit_value[i];
00368 
00369       if(val){
00370         if(val>=room){
00371           if(hiroom>loroom){
00372             val = val-loroom;
00373           }else{
00374           val = -1-(val-hiroom);
00375           }
00376         }else{
00377           if(val&1){
00378             val= -((val+1)>>1);
00379           }else{
00380             val>>=1;
00381           }
00382         }
00383 
00384         fit_value[i]=val+predicted;
00385         fit_value[look->loneighbor[i-2]]&=0x7fff;
00386         fit_value[look->hineighbor[i-2]]&=0x7fff;
00387 
00388       }else{
00389         fit_value[i]=predicted|0x8000;
00390       }
00391         
00392     }
00393 
00394     return(fit_value);
00395   }
00396  eop:
00397   return(NULL);
00398 }
00399 
00400 static int floor1_inverse2(vorbis_block *vb,vorbis_look_floor *in,void *memo,
00401                           ogg_int32_t *out){
00402   vorbis_look_floor1 *look=(vorbis_look_floor1 *)in;
00403   vorbis_info_floor1 *info=look->vi;
00404 
00405   codec_setup_info   *ci=(codec_setup_info *)vb->vd->vi->codec_setup;
00406   int                  n=ci->blocksizes[vb->W]/2;
00407   int j;
00408 
00409   if(memo){
00410     /* render the lines */
00411     int *fit_value=(int *)memo;
00412     int hx=0;
00413     int lx=0;
00414     int ly=fit_value[0]*info->mult;
00415     for(j=1;j<look->posts;j++){
00416       int current=look->forward_index[j];
00417       int hy=fit_value[current]&0x7fff;
00418       if(hy==fit_value[current]){
00419         
00420         hy*=info->mult;
00421         hx=info->postlist[current];
00422         
00423         render_line(lx,hx,ly,hy,out);
00424         
00425         lx=hx;
00426         ly=hy;
00427       }
00428     }
00429     for(j=hx;j<n;j++)out[j]*=ly; /* be certain */    
00430     return(1);
00431   }
00432   memset(out,0,sizeof(*out)*n);
00433   return(0);
00434 }
00435 
00436 /* export hooks */
00437 const vorbis_func_floor floor1_exportbundle={
00438   &floor1_unpack,&floor1_look,&floor1_free_info,
00439   &floor1_free_look,&floor1_inverse1,&floor1_inverse2
00440 };
00441 

Generated by  doxygen 1.6.2