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