00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <stdlib.h>
00019 #include <math.h>
00020 #include <string.h>
00021 #include "ogg/ogg.h"
00022 #include "os.h"
00023 #include "misc.h"
00024 #include "vorbis/codec.h"
00025 #include "codebook.h"
00026 #include "scales.h"
00027
00028
00029 int _ilog(unsigned int v){
00030 int ret=0;
00031 while(v){
00032 ret++;
00033 v>>=1;
00034 }
00035 return(ret);
00036 }
00037
00038
00039
00040
00041
00042 #define VQ_FEXP 10
00043 #define VQ_FMAN 21
00044 #define VQ_FEXP_BIAS 768
00045
00046
00047 long _float32_pack(float val){
00048 int sign=0;
00049 long exp;
00050 long mant;
00051 if(val<0){
00052 sign=0x80000000;
00053 val= -val;
00054 }
00055 exp= floor(log(val)/log(2.f));
00056 mant=rint(ldexp(val,(VQ_FMAN-1)-exp));
00057 exp=(exp+VQ_FEXP_BIAS)<<VQ_FMAN;
00058
00059 return(sign|exp|mant);
00060 }
00061
00062 float _float32_unpack(long val){
00063 double mant=val&0x1fffff;
00064 int sign=val&0x80000000;
00065 long exp =(val&0x7fe00000L)>>VQ_FMAN;
00066 if(sign)mant= -mant;
00067 return(ldexp(mant,exp-(VQ_FMAN-1)-VQ_FEXP_BIAS));
00068 }
00069
00070
00071
00072
00073 ogg_uint32_t *_make_words(long *l,long n,long sparsecount){
00074 long i,j,count=0;
00075 ogg_uint32_t marker[33];
00076 ogg_uint32_t *r=(ogg_uint32_t*)_ogg_malloc((sparsecount?sparsecount:n)*sizeof(*r));
00077 memset(marker,0,sizeof(marker));
00078
00079 for(i=0;i<n;i++){
00080 long length=l[i];
00081 if(length>0){
00082 ogg_uint32_t entry=marker[length];
00083
00084
00085
00086
00087
00088
00089
00090 if(length<32 && (entry>>length)){
00091
00092 _ogg_free(r);
00093 return(NULL);
00094 }
00095 r[count++]=entry;
00096
00097
00098
00099 {
00100 for(j=length;j>0;j--){
00101
00102 if(marker[j]&1){
00103
00104 if(j==1)
00105 marker[1]++;
00106 else
00107 marker[j]=marker[j-1]<<1;
00108 break;
00109
00110 }
00111 marker[j]++;
00112 }
00113 }
00114
00115
00116
00117
00118 for(j=length+1;j<33;j++)
00119 if((marker[j]>>1) == entry){
00120 entry=marker[j];
00121 marker[j]=marker[j-1]<<1;
00122 }else
00123 break;
00124 }else
00125 if(sparsecount==0)count++;
00126 }
00127
00128
00129
00130 for(i=0,count=0;i<n;i++){
00131 ogg_uint32_t temp=0;
00132 for(j=0;j<l[i];j++){
00133 temp<<=1;
00134 temp|=(r[count]>>j)&1;
00135 }
00136
00137 if(sparsecount){
00138 if(l[i])
00139 r[count++]=temp;
00140 }else
00141 r[count++]=temp;
00142 }
00143
00144 return(r);
00145 }
00146
00147
00148
00149
00150 long _book_maptype1_quantvals(const static_codebook *b){
00151 long vals=floor(pow((float)b->entries,1.f/b->dim));
00152
00153
00154
00155
00156
00157
00158 while(1){
00159 long acc=1;
00160 long acc1=1;
00161 int i;
00162 for(i=0;i<b->dim;i++){
00163 acc*=vals;
00164 acc1*=vals+1;
00165 }
00166 if(acc<=b->entries && acc1>b->entries){
00167 return(vals);
00168 }else{
00169 if(acc>b->entries){
00170 vals--;
00171 }else{
00172 vals++;
00173 }
00174 }
00175 }
00176 }
00177
00178
00179
00180
00181
00182
00183 float *_book_unquantize(const static_codebook *b,int n,int *sparsemap){
00184 long j,k,count=0;
00185 if(b->maptype==1 || b->maptype==2){
00186 int quantvals;
00187 float mindel=_float32_unpack(b->q_min);
00188 float delta=_float32_unpack(b->q_delta);
00189 float *r=(float*)_ogg_calloc(n*b->dim,sizeof(*r));
00190
00191
00192
00193 switch(b->maptype){
00194 case 1:
00195
00196
00197
00198
00199
00200
00201
00202 quantvals=_book_maptype1_quantvals(b);
00203 for(j=0;j<b->entries;j++){
00204 if((sparsemap && b->lengthlist[j]) || !sparsemap){
00205 float last=0.f;
00206 int indexdiv=1;
00207 for(k=0;k<b->dim;k++){
00208 int index= (j/indexdiv)%quantvals;
00209 float val=b->quantlist[index];
00210 val=fabs(val)*delta+mindel+last;
00211 if(b->q_sequencep)last=val;
00212 if(sparsemap)
00213 r[sparsemap[count]*b->dim+k]=val;
00214 else
00215 r[count*b->dim+k]=val;
00216 indexdiv*=quantvals;
00217 }
00218 count++;
00219 }
00220
00221 }
00222 break;
00223 case 2:
00224 for(j=0;j<b->entries;j++){
00225 if((sparsemap && b->lengthlist[j]) || !sparsemap){
00226 float last=0.f;
00227
00228 for(k=0;k<b->dim;k++){
00229 float val=b->quantlist[j*b->dim+k];
00230 val=fabs(val)*delta+mindel+last;
00231 if(b->q_sequencep)last=val;
00232 if(sparsemap)
00233 r[sparsemap[count]*b->dim+k]=val;
00234 else
00235 r[count*b->dim+k]=val;
00236 }
00237 count++;
00238 }
00239 }
00240 break;
00241 }
00242
00243 return(r);
00244 }
00245 return(NULL);
00246 }
00247
00248 void vorbis_staticbook_clear(static_codebook *b){
00249 if(b->allocedp){
00250 if(b->quantlist)_ogg_free(b->quantlist);
00251 if(b->lengthlist)_ogg_free(b->lengthlist);
00252 if(b->nearest_tree){
00253 _ogg_free(b->nearest_tree->ptr0);
00254 _ogg_free(b->nearest_tree->ptr1);
00255 _ogg_free(b->nearest_tree->p);
00256 _ogg_free(b->nearest_tree->q);
00257 memset(b->nearest_tree,0,sizeof(*b->nearest_tree));
00258 _ogg_free(b->nearest_tree);
00259 }
00260 if(b->thresh_tree){
00261 _ogg_free(b->thresh_tree->quantthresh);
00262 _ogg_free(b->thresh_tree->quantmap);
00263 memset(b->thresh_tree,0,sizeof(*b->thresh_tree));
00264 _ogg_free(b->thresh_tree);
00265 }
00266
00267 memset(b,0,sizeof(*b));
00268 }
00269 }
00270
00271 void vorbis_staticbook_destroy(static_codebook *b){
00272 if(b->allocedp){
00273 vorbis_staticbook_clear(b);
00274 _ogg_free(b);
00275 }
00276 }
00277
00278 void vorbis_book_clear(codebook *b){
00279
00280
00281 if(b->valuelist)_ogg_free(b->valuelist);
00282 if(b->codelist)_ogg_free(b->codelist);
00283
00284 if(b->dec_index)_ogg_free(b->dec_index);
00285 if(b->dec_codelengths)_ogg_free(b->dec_codelengths);
00286 if(b->dec_firsttable)_ogg_free(b->dec_firsttable);
00287
00288 memset(b,0,sizeof(*b));
00289 }
00290
00291 int vorbis_book_init_encode(codebook *c,const static_codebook *s){
00292
00293 memset(c,0,sizeof(*c));
00294 c->c=s;
00295 c->entries=s->entries;
00296 c->used_entries=s->entries;
00297 c->dim=s->dim;
00298 c->codelist=_make_words(s->lengthlist,s->entries,0);
00299 c->valuelist=_book_unquantize(s,s->entries,NULL);
00300
00301 return(0);
00302 }
00303
00304 static ogg_uint32_t bitreverse(ogg_uint32_t x){
00305 x= ((x>>16)&0x0000ffffUL) | ((x<<16)&0xffff0000UL);
00306 x= ((x>> 8)&0x00ff00ffUL) | ((x<< 8)&0xff00ff00UL);
00307 x= ((x>> 4)&0x0f0f0f0fUL) | ((x<< 4)&0xf0f0f0f0UL);
00308 x= ((x>> 2)&0x33333333UL) | ((x<< 2)&0xccccccccUL);
00309 return((x>> 1)&0x55555555UL) | ((x<< 1)&0xaaaaaaaaUL);
00310 }
00311
00312 static int sort32a(const void *a,const void *b){
00313 return ( **(ogg_uint32_t **)a>**(ogg_uint32_t **)b)-
00314 ( **(ogg_uint32_t **)a<**(ogg_uint32_t **)b);
00315 }
00316
00317
00318 int vorbis_book_init_decode(codebook *c,const static_codebook *s){
00319 int i,j,n=0,tabn;
00320 int *sortindex;
00321 int *sortindex_cpy = NULL;
00322 memset(c,0,sizeof(*c));
00323
00324
00325 for(i=0;i<s->entries;i++)
00326 if(s->lengthlist[i]>0)
00327 n++;
00328
00329 c->entries=s->entries;
00330 c->used_entries=n;
00331 c->dim=s->dim;
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343 {
00344
00345 ogg_uint32_t *codes=_make_words(s->lengthlist,s->entries,c->used_entries);
00346 ogg_uint32_t **codep= (ogg_uint32_t **)_ogg_malloc(sizeof(*codep)*n);
00347 ogg_uint32_t **codep_cpy = codep;
00348
00349 if(codes==NULL)goto err_out;
00350
00351 for(i=0;i<n;i++){
00352 codes[i]=bitreverse(codes[i]);
00353 codep[i]=codes+i;
00354 }
00355
00356 qsort(codep,n,sizeof(*codep),sort32a);
00357
00358 sortindex= (int*)_ogg_malloc(n*sizeof(*sortindex));
00359 sortindex_cpy =sortindex ;
00360
00361 c->codelist=(ogg_uint32_t*)_ogg_malloc(n*sizeof(*c->codelist));
00362
00363 for(i=0;i<n;i++){
00364 int position=codep[i]-codes;
00365 sortindex[position]=i;
00366 }
00367
00368 for(i=0;i<n;i++)
00369 c->codelist[sortindex[i]]=codes[i];
00370 _ogg_free(codes);
00371
00372 free(codep_cpy);
00373 }
00374
00375 c->valuelist=_book_unquantize(s,n,sortindex);
00376 c->dec_index=(int*)_ogg_malloc(n*sizeof(*c->dec_index));
00377
00378 for(n=0,i=0;i<s->entries;i++)
00379 if(s->lengthlist[i]>0)
00380 c->dec_index[sortindex[n++]]=i;
00381
00382 c->dec_codelengths=(char*)_ogg_malloc(n*sizeof(*c->dec_codelengths));
00383 for(n=0,i=0;i<s->entries;i++)
00384 if(s->lengthlist[i]>0)
00385 c->dec_codelengths[sortindex[n++]]=s->lengthlist[i];
00386
00387 c->dec_firsttablen=_ilog(c->used_entries)-4;
00388 if(c->dec_firsttablen<5)c->dec_firsttablen=5;
00389 if(c->dec_firsttablen>8)c->dec_firsttablen=8;
00390
00391 tabn=1<<c->dec_firsttablen;
00392 c->dec_firsttable=(ogg_uint32_t*)_ogg_calloc(tabn,sizeof(*c->dec_firsttable));
00393 c->dec_maxlength=0;
00394
00395 for(i=0;i<n;i++){
00396 if(c->dec_maxlength<c->dec_codelengths[i])
00397 c->dec_maxlength=c->dec_codelengths[i];
00398 if(c->dec_codelengths[i]<=c->dec_firsttablen){
00399 ogg_uint32_t orig=bitreverse(c->codelist[i]);
00400 for(j=0;j<(1<<(c->dec_firsttablen-c->dec_codelengths[i]));j++)
00401 c->dec_firsttable[orig|(j<<c->dec_codelengths[i])]=i+1;
00402 }
00403 }
00404
00405
00406
00407 {
00408 ogg_uint32_t mask=0xfffffffeUL<<(31-c->dec_firsttablen);
00409 long lo=0,hi=0;
00410
00411 for(i=0;i<tabn;i++){
00412 ogg_uint32_t word=i<<(32-c->dec_firsttablen);
00413 if(c->dec_firsttable[bitreverse(word)]==0){
00414 while((lo+1)<n && c->codelist[lo+1]<=word)lo++;
00415 while( hi<n && word>=(c->codelist[hi]&mask))hi++;
00416
00417
00418
00419
00420 {
00421 unsigned long loval=lo;
00422 unsigned long hival=n-hi;
00423
00424 if(loval>0x7fff)loval=0x7fff;
00425 if(hival>0x7fff)hival=0x7fff;
00426 c->dec_firsttable[bitreverse(word)]=
00427 0x80000000UL | (loval<<15) | hival;
00428 }
00429 }
00430 }
00431 }
00432
00433 free(sortindex_cpy);
00434 return(0);
00435 err_out:
00436 vorbis_book_clear(c);
00437
00438 free(sortindex_cpy);
00439 return(-1);
00440 }
00441
00442 static float _dist(int el,float *ref, float *b,int step){
00443 int i;
00444 float acc=0.f;
00445 for(i=0;i<el;i++){
00446 float val=(ref[i]-b[i*step]);
00447 acc+=val*val;
00448 }
00449 return(acc);
00450 }
00451
00452 int _best(codebook *book, float *a, int step){
00453 encode_aux_threshmatch *tt=book->c->thresh_tree;
00454
00455 #if 0
00456 encode_aux_nearestmatch *nt=book->c->nearest_tree;
00457 encode_aux_pigeonhole *pt=book->c->pigeon_tree;
00458 #endif
00459 int dim=book->dim;
00460 int k,o;
00461
00462
00463
00464
00465 if(tt){
00466 int index=0,i;
00467
00468 for(k=0,o=step*(dim-1);k<dim;k++,o-=step){
00469
00470 i=tt->threshvals>>1;
00471 if(a[o]<tt->quantthresh[i]){
00472
00473 for(;i>0;i--)
00474 if(a[o]>=tt->quantthresh[i-1])
00475 break;
00476
00477 }else{
00478
00479 for(i++;i<tt->threshvals-1;i++)
00480 if(a[o]<tt->quantthresh[i])break;
00481
00482 }
00483
00484 index=(index*tt->quantvals)+tt->quantmap[i];
00485 }
00486
00487 if(book->c->lengthlist[index]>0)
00488
00489
00490 return(index);
00491 }
00492
00493 #if 0
00494
00495 if(pt){
00496 const static_codebook *c=book->c;
00497 int i,besti=-1;
00498 float best=0.f;
00499 int entry=0;
00500
00501
00502 if(c->q_sequencep){
00503 int pv;
00504 long mul=1;
00505 float qlast=0;
00506 for(k=0,o=0;k<dim;k++,o+=step){
00507 pv=(int)((a[o]-qlast-pt->min)/pt->del);
00508 if(pv<0 || pv>=pt->mapentries)break;
00509 entry+=pt->pigeonmap[pv]*mul;
00510 mul*=pt->quantvals;
00511 qlast+=pv*pt->del+pt->min;
00512 }
00513 }else{
00514 for(k=0,o=step*(dim-1);k<dim;k++,o-=step){
00515 int pv=(int)((a[o]-pt->min)/pt->del);
00516 if(pv<0 || pv>=pt->mapentries)break;
00517 entry=entry*pt->quantvals+pt->pigeonmap[pv];
00518 }
00519 }
00520
00521
00522
00523 if(k==dim && pt->fitlength[entry]){
00524
00525 long *list=pt->fitlist+pt->fitmap[entry];
00526 for(i=0;i<pt->fitlength[entry];i++){
00527 float this=_dist(dim,book->valuelist+list[i]*dim,a,step);
00528 if(besti==-1 || this<best){
00529 best=this;
00530 besti=list[i];
00531 }
00532 }
00533
00534 return(besti);
00535 }
00536 }
00537
00538 if(nt){
00539
00540 while(1){
00541 float c=0.f;
00542 float *p=book->valuelist+nt->p[ptr];
00543 float *q=book->valuelist+nt->q[ptr];
00544
00545 for(k=0,o=0;k<dim;k++,o+=step)
00546 c+=(p[k]-q[k])*(a[o]-(p[k]+q[k])*.5);
00547
00548 if(c>0.f)
00549 ptr= -nt->ptr0[ptr];
00550 else
00551 ptr= -nt->ptr1[ptr];
00552 if(ptr<=0)break;
00553 }
00554 return(-ptr);
00555 }
00556 #endif
00557
00558
00559 {
00560 const static_codebook *c=book->c;
00561 int i,besti=-1;
00562 float best=0.f;
00563 float *e=book->valuelist;
00564 for(i=0;i<book->entries;i++){
00565 if(c->lengthlist[i]>0){
00566 float temp=_dist(dim,e,a,step);
00567 if(besti==-1 || temp<best){
00568 best=temp;
00569 besti=i;
00570 }
00571 }
00572 e+=dim;
00573 }
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589 return(besti);
00590 }
00591 }
00592
00593 long vorbis_book_codeword(codebook *book,int entry){
00594 if(book->c)
00595
00596 return book->codelist[entry];
00597 return -1;
00598 }
00599
00600 long vorbis_book_codelen(codebook *book,int entry){
00601 if(book->c)
00602
00603 return book->c->lengthlist[entry];
00604 return -1;
00605 }
00606
00607 #ifdef _V_SELFTEST
00608
00609
00610
00611
00612
00613 #include <stdio.h>
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625 static long full_quantlist1[]={0,1,2,3, 4,5,6,7, 8,3,6,1};
00626 static long partial_quantlist1[]={0,7,2};
00627
00628
00629 static_codebook test1={
00630 4,16,
00631 NULL,
00632 0,
00633 0,0,0,0,
00634 NULL,
00635 NULL,NULL
00636 };
00637 static float *test1_result=NULL;
00638
00639
00640 static_codebook test2={
00641 4,3,
00642 NULL,
00643 2,
00644 -533200896,1611661312,4,0,
00645 full_quantlist1,
00646 NULL,NULL
00647 };
00648 static float test2_result[]={-3,-2,-1,0, 1,2,3,4, 5,0,3,-2};
00649
00650
00651 static_codebook test3={
00652 4,3,
00653 NULL,
00654 2,
00655 -533200896,1611661312,4,1,
00656 full_quantlist1,
00657 NULL,NULL
00658 };
00659 static float test3_result[]={-3,-5,-6,-6, 1,3,6,10, 5,5,8,6};
00660
00661
00662 static_codebook test4={
00663 3,27,
00664 NULL,
00665 1,
00666 -533200896,1611661312,4,0,
00667 partial_quantlist1,
00668 NULL,NULL
00669 };
00670 static float test4_result[]={-3,-3,-3, 4,-3,-3, -1,-3,-3,
00671 -3, 4,-3, 4, 4,-3, -1, 4,-3,
00672 -3,-1,-3, 4,-1,-3, -1,-1,-3,
00673 -3,-3, 4, 4,-3, 4, -1,-3, 4,
00674 -3, 4, 4, 4, 4, 4, -1, 4, 4,
00675 -3,-1, 4, 4,-1, 4, -1,-1, 4,
00676 -3,-3,-1, 4,-3,-1, -1,-3,-1,
00677 -3, 4,-1, 4, 4,-1, -1, 4,-1,
00678 -3,-1,-1, 4,-1,-1, -1,-1,-1};
00679
00680
00681 static_codebook test5={
00682 3,27,
00683 NULL,
00684 1,
00685 -533200896,1611661312,4,1,
00686 partial_quantlist1,
00687 NULL,NULL
00688 };
00689 static float test5_result[]={-3,-6,-9, 4, 1,-2, -1,-4,-7,
00690 -3, 1,-2, 4, 8, 5, -1, 3, 0,
00691 -3,-4,-7, 4, 3, 0, -1,-2,-5,
00692 -3,-6,-2, 4, 1, 5, -1,-4, 0,
00693 -3, 1, 5, 4, 8,12, -1, 3, 7,
00694 -3,-4, 0, 4, 3, 7, -1,-2, 2,
00695 -3,-6,-7, 4, 1, 0, -1,-4,-5,
00696 -3, 1, 0, 4, 8, 7, -1, 3, 2,
00697 -3,-4,-5, 4, 3, 2, -1,-2,-3};
00698
00699 void run_test(static_codebook *b,float *comp){
00700 float *out=_book_unquantize(b,b->entries,NULL);
00701 int i;
00702
00703 if(comp){
00704 if(!out){
00705 fprintf(stderr,"_book_unquantize incorrectly returned NULL\n");
00706 exit(1);
00707 }
00708
00709 for(i=0;i<b->entries*b->dim;i++)
00710 if(fabs(out[i]-comp[i])>.0001){
00711 fprintf(stderr,"disagreement in unquantized and reference data:\n"
00712 "position %d, %g != %g\n",i,out[i],comp[i]);
00713 exit(1);
00714 }
00715
00716 }else{
00717 if(out){
00718 fprintf(stderr,"_book_unquantize returned a value array: \n"
00719 " correct result should have been NULL\n");
00720 exit(1);
00721 }
00722 }
00723 }
00724
00725 int main(){
00726
00727 fprintf(stderr,"Dequant test 1... ");
00728 run_test(&test1,test1_result);
00729 fprintf(stderr,"OK\nDequant test 2... ");
00730 run_test(&test2,test2_result);
00731 fprintf(stderr,"OK\nDequant test 3... ");
00732 run_test(&test3,test3_result);
00733 fprintf(stderr,"OK\nDequant test 4... ");
00734 run_test(&test4,test4_result);
00735 fprintf(stderr,"OK\nDequant test 5... ");
00736 run_test(&test5,test5_result);
00737 fprintf(stderr,"OK\n\n");
00738
00739 return(0);
00740 }
00741
00742 #endif