misc/libtremor/tremor/floor0.c
changeset 7697 767d3c4153a1
parent 6045 9a7cc0f29430
child 7849 a12155461b34
--- a/misc/libtremor/tremor/floor0.c	Thu Sep 20 23:04:10 2012 +0200
+++ b/misc/libtremor/tremor/floor0.c	Fri Sep 21 00:50:04 2012 +0200
@@ -6,7 +6,7 @@
  * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
  * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
  *                                                                  *
- * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002    *
+ * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2003    *
  * BY THE Xiph.Org FOUNDATION http://www.xiph.org/                  *
  *                                                                  *
  ********************************************************************
@@ -21,23 +21,12 @@
 #include "ogg.h"
 #include "ivorbiscodec.h"
 #include "codec_internal.h"
-#include "registry.h"
 #include "codebook.h"
 #include "misc.h"
-#include "block.h"
+#include "os.h"
 
 #define LSP_FRACBITS 14
-
-typedef struct {
-  long n;
-  int ln;
-  int  m;
-  int *linearmap;
-
-  vorbis_info_floor0 *vi;
-  ogg_int32_t *lsp_look;
-
-} vorbis_look_floor0;
+extern const ogg_int32_t FLOOR_fromdB_LOOKUP[];
 
 /*************** LSP decode ********************/
 
@@ -48,7 +37,7 @@
    returns in m.8 format */
 
 static long ADJUST_SQRT2[2]={8192,5792};
-STIN ogg_int32_t vorbis_invsqlook_i(long a,long e){
+static inline ogg_int32_t vorbis_invsqlook_i(long a,long e){
   long i=(a&0x7fff)>>(INVSQ_LOOKUP_I_SHIFT-1); 
   long d=a&INVSQ_LOOKUP_I_MASK;                              /*  0.10 */
   long val=INVSQ_LOOKUP_I[i]-                                /*  1.16 */
@@ -60,60 +49,60 @@
 
 /* interpolated lookup based fromdB function, domain -140dB to 0dB only */
 /* a is in n.12 format */
-STIN ogg_int32_t vorbis_fromdBlook_i(long a){
-  int i=(-a)>>(12-FROMdB2_SHIFT);
-  if(i<0) return 0x7fffffff;
-  if(i>=(FROMdB_LOOKUP_SZ<<FROMdB_SHIFT))return 0;
-  
-  return FROMdB_LOOKUP[i>>FROMdB_SHIFT] * FROMdB2_LOOKUP[i&FROMdB2_MASK];
+#ifdef _LOW_ACCURACY_
+static inline ogg_int32_t vorbis_fromdBlook_i(long a){
+  if(a>0) return 0x7fffffff;
+  if(a<(-140<<12)) return 0;
+  return FLOOR_fromdB_LOOKUP[((a+140)*467)>>20]<<9;
 }
+#else
+static inline ogg_int32_t vorbis_fromdBlook_i(long a){
+  if(a>0) return 0x7fffffff;
+  if(a<(-140<<12)) return 0;
+  return FLOOR_fromdB_LOOKUP[((a+(140<<12))*467)>>20];
+}
+#endif
 
 /* interpolated lookup based cos function, domain 0 to PI only */
 /* a is in 0.16 format, where 0==0, 2^^16-1==PI, return 0.14 */
-STIN ogg_int32_t vorbis_coslook_i(long a){
+static inline ogg_int32_t vorbis_coslook_i(long a){
   int i=a>>COS_LOOKUP_I_SHIFT;
   int d=a&COS_LOOKUP_I_MASK;
   return COS_LOOKUP_I[i]- ((d*(COS_LOOKUP_I[i]-COS_LOOKUP_I[i+1]))>>
 			   COS_LOOKUP_I_SHIFT);
 }
 
-/* interpolated lookup based cos function */
+/* interpolated half-wave lookup based cos function */
 /* a is in 0.16 format, where 0==0, 2^^16==PI, return .LSP_FRACBITS */
-STIN ogg_int32_t vorbis_coslook2_i(long a){
-  a=a&0x1ffff;
-
-  if(a>0x10000)a=0x20000-a;
-  {               
-    int i=a>>COS_LOOKUP_I_SHIFT;
-    int d=a&COS_LOOKUP_I_MASK;
-    a=((COS_LOOKUP_I[i]<<COS_LOOKUP_I_SHIFT)-
-       d*(COS_LOOKUP_I[i]-COS_LOOKUP_I[i+1]))>>
-      (COS_LOOKUP_I_SHIFT-LSP_FRACBITS+14);
-  }
-  
-  return(a);
+static inline ogg_int32_t vorbis_coslook2_i(long a){
+  int i=a>>COS_LOOKUP_I_SHIFT;
+  int d=a&COS_LOOKUP_I_MASK;
+  return ((COS_LOOKUP_I[i]<<COS_LOOKUP_I_SHIFT)-
+	  d*(COS_LOOKUP_I[i]-COS_LOOKUP_I[i+1]))>>
+    (COS_LOOKUP_I_SHIFT-LSP_FRACBITS+14);
 }
 
-static const int barklook[28]={
-  0,100,200,301,          405,516,635,766,
-  912,1077,1263,1476,     1720,2003,2333,2721,
-  3184,3742,4428,5285,    6376,7791,9662,12181,
-  15624,20397,27087,36554
+static const ogg_uint16_t barklook[54]={
+  0,51,102,154,            206,258,311,365,
+  420,477,535,594,         656,719,785,854,
+  926,1002,1082,1166,      1256,1352,1454,1564,
+  1683,1812,1953,2107,     2276,2463,2670,2900,
+  3155,3440,3756,4106,     4493,4919,5387,5901,
+  6466,7094,7798,8599,     9528,10623,11935,13524,
+  15453,17775,20517,23667, 27183,31004
 };
 
 /* used in init only; interpolate the long way */
-STIN ogg_int32_t toBARK(int n){
+static inline ogg_int32_t toBARK(int n){
   int i;
-  for(i=0;i<27;i++) 
+  for(i=0;i<54;i++) 
     if(n>=barklook[i] && n<barklook[i+1])break;
   
-  if(i==27){
-    return 27<<15;
+  if(i==54){
+    return 54<<14;
   }else{
-    int gap=barklook[i+1]-barklook[i];
-    int del=n-barklook[i];
-
-    return((i<<15)+((del<<15)/gap));
+    return (i<<14)+(((n-barklook[i])*  
+		     ((1UL<<31)/(barklook[i+1]-barklook[i])))>>17);
   }
 }
 
@@ -133,11 +122,11 @@
 
 static const unsigned char MLOOP_3[8]={0,1,2,2,3,3,3,3};
 
-void vorbis_lsp_to_curve(ogg_int32_t *curve,int *map,int n,int ln,
+void vorbis_lsp_to_curve(ogg_int32_t *curve,int n,int ln,
 			 ogg_int32_t *lsp,int m,
 			 ogg_int32_t amp,
 			 ogg_int32_t ampoffset,
-			 ogg_int32_t *icos){
+			 ogg_int32_t nyq){
 
   /* 0 <= m < 256 */
 
@@ -146,6 +135,27 @@
   int ampoffseti=ampoffset*4096;
   int ampi=amp;
   ogg_int32_t *ilsp=(ogg_int32_t *)alloca(m*sizeof(*ilsp));
+
+  ogg_uint32_t inyq= (1UL<<31) / toBARK(nyq);
+  ogg_uint32_t imap= (1UL<<31) / ln;
+  ogg_uint32_t tBnyq1 = toBARK(nyq)<<1;
+
+  /* Besenham for frequency scale to avoid a division */
+  int f=0;
+  int fdx=n;
+  int fbase=nyq/fdx;
+  int ferr=0;
+  int fdy=nyq-fbase*fdx;
+  int map=0;
+
+#ifdef _LOW_ACCURACY_
+  ogg_uint32_t nextbark=((tBnyq1<<11)/ln)>>12;
+#else
+  ogg_uint32_t nextbark=MULT31(imap>>1,tBnyq1);
+#endif
+  int nextf=barklook[nextbark>>14]+(((nextbark&0x3fff)*
+	    (barklook[(nextbark>>14)+1]-barklook[nextbark>>14]))>>14);
+
   /* lsp is in 8.24, range 0 to PI; coslook wants it in .16 0 to 1*/
   for(i=0;i<m;i++){
 #ifndef _LOW_ACCURACY_
@@ -165,11 +175,14 @@
 
   i=0;
   while(i<n){
-    int j,k=map[i];
+    int j;
     ogg_uint32_t pi=46341; /* 2**-.5 in 0.16 */
     ogg_uint32_t qi=46341;
     ogg_int32_t qexp=0,shift;
-    ogg_int32_t wi=icos[k];
+    ogg_int32_t wi;
+
+    wi=vorbis_coslook2_i((map*imap)>>15);
+
 
 #ifdef _V_LSP_MATH_ASM
     lsp_loop_asm(&qi,&pi,&qexp,ilsp,wi,m);
@@ -202,8 +215,9 @@
 
     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];
+      	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;
@@ -211,7 +225,7 @@
     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){
@@ -279,32 +293,57 @@
     amp>>=9;
 #endif
     curve[i]= MULT31_SHIFT15(curve[i],amp);
-    while(map[++i]==k) curve[i]= MULT31_SHIFT15(curve[i],amp);
+
+    while(++i<n){
+	
+      /* line plot to get new f */
+      ferr+=fdy;
+      if(ferr>=fdx){
+	ferr-=fdx;
+	f++;
+      }
+      f+=fbase;
+      
+      if(f>=nextf)break;
+
+      curve[i]= MULT31_SHIFT15(curve[i],amp);
+    }
+
+    while(1){
+      map++;
+
+      if(map+1<ln){
+	
+#ifdef _LOW_ACCURACY_
+	nextbark=((tBnyq1<<11)/ln*(map+1))>>12;
+#else
+	nextbark=MULT31((map+1)*(imap>>1),tBnyq1);
+#endif
+	nextf=barklook[nextbark>>14]+
+	  (((nextbark&0x3fff)*
+	    (barklook[(nextbark>>14)+1]-barklook[nextbark>>14]))>>14);
+	if(f<=nextf)break;
+	
+      }else{
+	nextf=9999999;
+	break;
+      }
+    }
+    if(map>=ln){
+      map=ln-1; /* guard against the approximation */      
+      nextf=9999999;
+    }
   }
 }
 
 /*************** vorbis decode glue ************/
 
-static void floor0_free_info(vorbis_info_floor *i){
+void floor0_free_info(vorbis_info_floor *i){
   vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
-  if(info){
-    memset(info,0,sizeof(*info));
-    _ogg_free(info);
-  }
+  if(info)_ogg_free(info);
 }
 
-static void floor0_free_look(vorbis_look_floor *i){
-  vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
-  if(look){
-
-    if(look->linearmap)_ogg_free(look->linearmap);
-    if(look->lsp_look)_ogg_free(look->lsp_look);
-    memset(look,0,sizeof(*look));
-    _ogg_free(look);
-  }
-}
-
-static vorbis_info_floor *floor0_unpack (vorbis_info *vi,oggpack_buffer *opb){
+vorbis_info_floor *floor0_info_unpack (vorbis_info *vi,oggpack_buffer *opb){
   codec_setup_info     *ci=(codec_setup_info *)vi->codec_setup;
   int j;
 
@@ -319,12 +358,13 @@
   if(info->order<1)goto err_out;
   if(info->rate<1)goto err_out;
   if(info->barkmap<1)goto err_out;
-  if(info->numbooks<1)goto err_out;
     
   for(j=0;j<info->numbooks;j++){
     info->books[j]=oggpack_read(opb,8);
-    if(info->books[j]<0 || info->books[j]>=ci->books)goto err_out;
+    if(info->books[j]>=ci->books)goto err_out;
   }
+
+  if(oggpack_eop(opb))goto err_out;
   return(info);
 
  err_out:
@@ -332,75 +372,35 @@
   return(NULL);
 }
 
-/* initialize Bark scale and normalization lookups.  We could do this
-   with static tables, but Vorbis allows a number of possible
-   combinations, so it's best to do it computationally.
-
-   The below is authoritative in terms of defining scale mapping.
-   Note that the scale depends on the sampling rate as well as the
-   linear block and mapping sizes */
-
-static vorbis_look_floor *floor0_look (vorbis_dsp_state *vd,vorbis_info_mode *mi,
-                              vorbis_info_floor *i){
-  int j;
-  vorbis_info        *vi=vd->vi;
-  codec_setup_info   *ci=(codec_setup_info *)vi->codec_setup;
+int floor0_memosize(vorbis_info_floor *i){
   vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
-  vorbis_look_floor0 *look=(vorbis_look_floor0 *)_ogg_calloc(1,sizeof(*look));
-  look->m=info->order;
-  look->n=ci->blocksizes[mi->blockflag]/2;
-  look->ln=info->barkmap;
-  look->vi=info;
-
-  /* the mapping from a linear scale to a smaller bark scale is
-     straightforward.  We do *not* make sure that the linear mapping
-     does not skip bark-scale bins; the decoder simply skips them and
-     the encoder may do what it wishes in filling them.  They're
-     necessary in some mapping combinations to keep the scale spacing
-     accurate */
-  look->linearmap=(int *)_ogg_malloc((look->n+1)*sizeof(*look->linearmap));
-  for(j=0;j<look->n;j++){
-
-    int val=(look->ln*
-	     ((toBARK(info->rate/2*j/look->n)<<11)/toBARK(info->rate/2)))>>11;
-
-    if(val>=look->ln)val=look->ln-1; /* guard against the approximation */
-    look->linearmap[j]=val;
-  }
-  look->linearmap[j]=-1;
-
-  look->lsp_look=(ogg_int32_t *)_ogg_malloc(look->ln*sizeof(*look->lsp_look));
-  for(j=0;j<look->ln;j++)
-    look->lsp_look[j]=vorbis_coslook2_i(0x10000*j/look->ln);
-
-  return look;
+  return info->order+1;
 }
 
-static void *floor0_inverse1(vorbis_block *vb,vorbis_look_floor *i){
-  vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
-  vorbis_info_floor0 *info=look->vi;
+ogg_int32_t *floor0_inverse1(vorbis_dsp_state *vd,vorbis_info_floor *i,
+			     ogg_int32_t *lsp){
+  vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
   int j,k;
   
-  int ampraw=oggpack_read(&vb->opb,info->ampbits);
+  int ampraw=oggpack_read(&vd->opb,info->ampbits);
   if(ampraw>0){ /* also handles the -1 out of data case */
     long maxval=(1<<info->ampbits)-1;
     int amp=((ampraw*info->ampdB)<<4)/maxval;
-    int booknum=oggpack_read(&vb->opb,_ilog(info->numbooks));
+    int booknum=oggpack_read(&vd->opb,_ilog(info->numbooks));
     
     if(booknum!=-1 && booknum<info->numbooks){ /* be paranoid */
-      codec_setup_info  *ci=(codec_setup_info *)vb->vd->vi->codec_setup;
-      codebook *b=ci->fullbooks+info->books[booknum];
+      codec_setup_info  *ci=(codec_setup_info *)vd->vi->codec_setup;
+      codebook *b=ci->book_param+info->books[booknum];
       ogg_int32_t last=0;
-      ogg_int32_t *lsp=(ogg_int32_t *)_vorbis_block_alloc(vb,sizeof(*lsp)*(look->m+1));
             
-      for(j=0;j<look->m;j+=b->dim)
-	if(vorbis_book_decodev_set(b,lsp+j,&vb->opb,b->dim,-24)==-1)goto eop;
-      for(j=0;j<look->m;){
+      for(j=0;j<info->order;j+=b->dim)
+	if(vorbis_book_decodev_set(b,lsp+j,&vd->opb,b->dim,-24)==-1)goto eop;
+      for(j=0;j<info->order;){
 	for(k=0;k<b->dim;k++,j++)lsp[j]+=last;
 	last=lsp[j-1];
       }
       
-      lsp[look->m]=amp;
+      lsp[info->order]=amp;
       return(lsp);
     }
   }
@@ -408,28 +408,21 @@
   return(NULL);
 }
 
-static int floor0_inverse2(vorbis_block *vb,vorbis_look_floor *i,
-			   void *memo,ogg_int32_t *out){
-  vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
-  vorbis_info_floor0 *info=look->vi;
+int floor0_inverse2(vorbis_dsp_state *vd,vorbis_info_floor *i,
+			   ogg_int32_t *lsp,ogg_int32_t *out){
+  vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
+  codec_setup_info  *ci=(codec_setup_info *)vd->vi->codec_setup;
   
-  if(memo){
-    ogg_int32_t *lsp=(ogg_int32_t *)memo;
-    ogg_int32_t amp=lsp[look->m];
+  if(lsp){
+    ogg_int32_t amp=lsp[info->order];
 
     /* take the coefficients back to a spectral envelope curve */
-    vorbis_lsp_to_curve(out,look->linearmap,look->n,look->ln,
-			lsp,look->m,amp,info->ampdB,look->lsp_look);
+    vorbis_lsp_to_curve(out,ci->blocksizes[vd->W]/2,info->barkmap,
+			lsp,info->order,amp,info->ampdB,
+			info->rate>>1);
     return(1);
   }
-  memset(out,0,sizeof(*out)*look->n);
+  memset(out,0,sizeof(*out)*ci->blocksizes[vd->W]/2);
   return(0);
 }
 
-/* export hooks */
-vorbis_func_floor floor0_exportbundle={
-  &floor0_unpack,&floor0_look,&floor0_free_info,
-  &floor0_free_look,&floor0_inverse1,&floor0_inverse2
-};
-
-