123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448 |
- #include <stdlib.h>
- #include <string.h>
- #include <math.h>
- #include "ogg.h"
- #include "ivorbiscodec.h"
- #include "codec_internal.h"
- #include "codebook.h"
- #include "misc.h"
- #include "os.h"
- #define LSP_FRACBITS 14
- extern const ogg_int32_t FLOOR_fromdB_LOOKUP[];
- #include "lsp_lookup.h"
- static long ADJUST_SQRT2[2]={8192,5792};
- 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;
- long val=INVSQ_LOOKUP_I[i]-
- ((INVSQ_LOOKUP_IDel[i]*d)>>INVSQ_LOOKUP_I_SHIFT);
- val*=ADJUST_SQRT2[e&1];
- e=(e>>1)+21;
- return(val>>e);
- }
- #ifdef _LOW_ACCURACY_
- static inline ogg_int32_t vorbis_fromdBlook_i(long a){
- if(a>0) return 0x7fffffff;
- if(a<(int)(((unsigned)-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<(int)(((unsigned)-140)<<12)) return 0;
- return FLOOR_fromdB_LOOKUP[((a+(140<<12))*467)>>20];
- }
- #endif
- 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);
- }
- 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 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
- };
- static inline ogg_int32_t toBARK(int n){
- int i;
- for(i=0;i<54;i++)
- if(n>=barklook[i] && n<barklook[i+1])break;
- if(i==54){
- return 54<<14;
- }else{
- return (i<<14)+(((n-barklook[i])*
- ((1UL<<31)/(barklook[i+1]-barklook[i])))>>17);
- }
- }
- static const unsigned char MLOOP_1[64]={
- 0,10,11,11, 12,12,12,12, 13,13,13,13, 13,13,13,13,
- 14,14,14,14, 14,14,14,14, 14,14,14,14, 14,14,14,14,
- 15,15,15,15, 15,15,15,15, 15,15,15,15, 15,15,15,15,
- 15,15,15,15, 15,15,15,15, 15,15,15,15, 15,15,15,15,
- };
- static const unsigned char MLOOP_2[64]={
- 0,4,5,5, 6,6,6,6, 7,7,7,7, 7,7,7,7,
- 8,8,8,8, 8,8,8,8, 8,8,8,8, 8,8,8,8,
- 9,9,9,9, 9,9,9,9, 9,9,9,9, 9,9,9,9,
- 9,9,9,9, 9,9,9,9, 9,9,9,9, 9,9,9,9,
- };
- 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 n,int ln,
- ogg_int32_t *lsp,int m,
- ogg_int32_t amp,
- ogg_int32_t ampoffset,
- ogg_int32_t nyq){
-
-
- int i;
- 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;
-
- 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);
-
- for(i=0;i<m;i++){
- #ifndef _LOW_ACCURACY_
- ogg_int32_t val=MULT32(lsp[i],0x517cc2);
- #else
- ogg_int32_t val=((lsp[i]>>10)*0x517d)>>14;
- #endif
-
- if(val<0 || (val>>COS_LOOKUP_I_SHIFT)>=COS_LOOKUP_I_SZ){
- memset(curve,0,sizeof(*curve)*n);
- return;
- }
- ilsp[i]=vorbis_coslook_i(val);
- }
- i=0;
- while(i<n){
- int j;
- ogg_uint32_t pi=46341;
- ogg_uint32_t qi=46341;
- ogg_int32_t qexp=0,shift;
- 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);
- pi=((pi*pi)>>16);
- qi=((qi*qi)>>16);
- if(m&1){
- qexp= qexp*2-28*((m+1)>>1)+m;
- pi*=(1<<14)-((wi*wi)>>14);
- qi+=pi>>14;
- }else{
- qexp= qexp*2-13*m;
- pi*=(1<<14)-wi;
- qi*=(1<<14)+wi;
- qi=(qi+pi)>>14;
- }
- if(qi&0xffff0000){
- qi>>=1; qexp++;
- }else
- lsp_norm_asm(&qi,&qexp);
- #else
- qi*=labs(ilsp[0]-wi);
- pi*=labs(ilsp[1]-wi);
- 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];
- qi=(qi>>shift)*labs(ilsp[j-1]-wi);
- pi=(pi>>shift)*labs(ilsp[j]-wi);
- qexp+=shift;
- }
- if(!(shift=MLOOP_1[(pi|qi)>>25]))
- if(!(shift=MLOOP_2[(pi|qi)>>19]))
- shift=MLOOP_3[(pi|qi)>>16];
-
- if(m&1){
-
-
- qi=(qi>>shift)*labs(ilsp[j-1]-wi);
- pi=(pi>>shift)<<14;
- qexp+=shift;
- if(!(shift=MLOOP_1[(pi|qi)>>25]))
- if(!(shift=MLOOP_2[(pi|qi)>>19]))
- shift=MLOOP_3[(pi|qi)>>16];
- pi>>=shift;
- qi>>=shift;
- qexp+=shift-14*((m+1)>>1);
- pi=((pi*pi)>>16);
- qi=((qi*qi)>>16);
- qexp=qexp*2+m;
- pi*=(1<<14)-((wi*wi)>>14);
- qi+=pi>>14;
- }else{
-
-
- pi>>=shift;
- qi>>=shift;
- qexp+=shift-7*m;
- pi=((pi*pi)>>16);
- qi=((qi*qi)>>16);
- qexp=qexp*2+m;
- pi*=(1<<14)-wi;
- qi*=(1<<14)+wi;
- qi=(qi+pi)>>14;
- }
-
- if(qi&0xffff0000){
- qi>>=1; qexp++;
- }else
- while(qi && !(qi&0x8000)){
- qi<<=1; qexp--;
- }
- #endif
- amp=vorbis_fromdBlook_i(ampi*
- vorbis_invsqlook_i(qi,qexp)-
-
- ampoffseti);
- #ifdef _LOW_ACCURACY_
- amp>>=9;
- #endif
- curve[i]= MULT31_SHIFT15(curve[i],amp);
- while(++i<n){
-
- 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;
- nextf=9999999;
- }
- }
- }
- void floor0_free_info(vorbis_info_floor *i){
- vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
- if(info)_ogg_free(info);
- }
- vorbis_info_floor *floor0_info_unpack (vorbis_info *vi,oggpack_buffer *opb){
- codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
- int j;
- vorbis_info_floor0 *info=(vorbis_info_floor0 *)_ogg_malloc(sizeof(*info));
- info->order=oggpack_read(opb,8);
- info->rate=oggpack_read(opb,16);
- info->barkmap=oggpack_read(opb,16);
- info->ampbits=oggpack_read(opb,6);
- info->ampdB=oggpack_read(opb,8);
- info->numbooks=oggpack_read(opb,4)+1;
- if(info->order<1)goto err_out;
- if(info->rate<1)goto err_out;
- if(info->barkmap<1)goto err_out;
- for(j=0;j<info->numbooks;j++){
- info->books[j]=(char)oggpack_read(opb,8);
- if(info->books[j]>=ci->books)goto err_out;
- }
- if(oggpack_eop(opb))goto err_out;
- return(info);
- err_out:
- floor0_free_info(info);
- return(NULL);
- }
- int floor0_memosize(vorbis_info_floor *i){
- vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
- return info->order+1;
- }
- 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(&vd->opb,info->ampbits);
- if(ampraw>0){
- long maxval=(1<<info->ampbits)-1;
- int amp=((ampraw*info->ampdB)<<4)/maxval;
- int booknum=oggpack_read(&vd->opb,_ilog(info->numbooks));
- if(booknum!=-1 && booknum<info->numbooks){
- codec_setup_info *ci=(codec_setup_info *)vd->vi->codec_setup;
- codebook *b=ci->book_param+info->books[booknum];
- ogg_int32_t last=0;
- 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[info->order]=amp;
- return(lsp);
- }
- }
- eop:
- return(NULL);
- }
- 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(lsp){
- ogg_int32_t amp=lsp[info->order];
-
- 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)*ci->blocksizes[vd->W]/2);
- return(0);
- }
|