--- 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
-};
-
-