📄 codebook.c
字号:
b->ptr+=bits/8; b->endbyte+=bits/8; b->endbit=bits&7;}#define oggpack_adv st_oggpack_adv#endif /* XXX end vx32 hack *//* the 'eliminate the decode tree' optimization actually requires the codewords to be MSb first, not LSb. This is an annoying inelegancy (and one of the first places where carefully thought out design turned out to be wrong; Vorbis II and future Ogg codecs should go to an MSb bitpacker), but not actually the huge hit it appears to be. The first-stage decode table catches most words so that bitreverse is not in the main execution path. */static ogg_uint32_t bitreverse(ogg_uint32_t x){ x= ((x>>16)&0x0000ffff) | ((x<<16)&0xffff0000); x= ((x>> 8)&0x00ff00ff) | ((x<< 8)&0xff00ff00); x= ((x>> 4)&0x0f0f0f0f) | ((x<< 4)&0xf0f0f0f0); x= ((x>> 2)&0x33333333) | ((x<< 2)&0xcccccccc); return((x>> 1)&0x55555555) | ((x<< 1)&0xaaaaaaaa);}static inline long decode_packed_entry_number(codebook *book, oggpack_buffer *b){ int read=book->dec_maxlength; long lo,hi; long lok = oggpack_look(b,book->dec_firsttablen); if (lok >= 0) { long entry = book->dec_firsttable[lok]; if(entry&0x80000000UL){ lo=(entry>>15)&0x7fff; hi=book->used_entries-(entry&0x7fff); }else{ oggpack_adv(b, book->dec_codelengths[entry-1]); return(entry-1); } }else{ lo=0; hi=book->used_entries; } lok = oggpack_look(b, read); while(lok<0 && read>1) lok = oggpack_look(b, --read); if(lok<0)return -1; /* bisect search for the codeword in the ordered list */ { ogg_uint32_t testword=bitreverse((ogg_uint32_t)lok); while(hi-lo>1){ long p=(hi-lo)>>1; long test=book->codelist[lo+p]>testword; lo+=p&(test-1); hi-=p&(-test); } if(book->dec_codelengths[lo]<=read){ oggpack_adv(b, book->dec_codelengths[lo]); return(lo); } } oggpack_adv(b, read); return(-1);}/* Decode side is specced and easier, because we don't need to find matches using different criteria; we simply read and map. There are two things we need to do 'depending': We may need to support interleave. We don't really, but it's convenient to do it here rather than rebuild the vector later. Cascades may be additive or multiplicitive; this is not inherent in the codebook, but set in the code using the codebook. Like interleaving, it's easiest to do it here. addmul==0 -> declarative (set the value) addmul==1 -> additive addmul==2 -> multiplicitive *//* returns the [original, not compacted] entry number or -1 on eof *********/long vorbis_book_decode(codebook *book, oggpack_buffer *b){ long packed_entry=decode_packed_entry_number(book,b); if(packed_entry>=0) return(book->dec_index[packed_entry]); /* if there's no dec_index, the codebook unpacking isn't collapsed */ return(packed_entry);}/* returns 0 on OK or -1 on eof *************************************/long vorbis_book_decodevs_add(codebook *book,float *a,oggpack_buffer *b,int n){ int step=n/book->dim; long *entry = alloca(sizeof(*entry)*step); float **t = alloca(sizeof(*t)*step); int i,j,o; for (i = 0; i < step; i++) { entry[i]=decode_packed_entry_number(book,b); if(entry[i]==-1)return(-1); t[i] = book->valuelist+entry[i]*book->dim; } for(i=0,o=0;i<book->dim;i++,o+=step) for (j=0;j<step;j++) a[o+j]+=t[j][i]; return(0);}long vorbis_book_decodev_add(codebook *book,float *a,oggpack_buffer *b,int n){ int i,j,entry; float *t; if(book->dim>8){ for(i=0;i<n;){ entry = decode_packed_entry_number(book,b); if(entry==-1)return(-1); t = book->valuelist+entry*book->dim; for (j=0;j<book->dim;) a[i++]+=t[j++]; } }else{ for(i=0;i<n;){ entry = decode_packed_entry_number(book,b); if(entry==-1)return(-1); t = book->valuelist+entry*book->dim; j=0; switch((int)book->dim){ case 8: a[i++]+=t[j++]; case 7: a[i++]+=t[j++]; case 6: a[i++]+=t[j++]; case 5: a[i++]+=t[j++]; case 4: a[i++]+=t[j++]; case 3: a[i++]+=t[j++]; case 2: a[i++]+=t[j++]; case 1: a[i++]+=t[j++]; case 0: break; } } } return(0);}long vorbis_book_decodev_set(codebook *book,float *a,oggpack_buffer *b,int n){ int i,j,entry; float *t; for(i=0;i<n;){ entry = decode_packed_entry_number(book,b); if(entry==-1)return(-1); t = book->valuelist+entry*book->dim; for (j=0;j<book->dim;) a[i++]=t[j++]; } return(0);}long vorbis_book_decodevv_add(codebook *book,float **a,long offset,int ch, oggpack_buffer *b,int n){ long i,j,entry; int chptr=0; for(i=offset/ch;i<(offset+n)/ch;){ entry = decode_packed_entry_number(book,b); if(entry==-1)return(-1); { const float *t = book->valuelist+entry*book->dim; for (j=0;j<book->dim;j++){ a[chptr++][i]+=t[j]; if(chptr==ch){ chptr=0; i++; } } } } return(0);}#ifdef _V_SELFTEST/* Simple enough; pack a few candidate codebooks, unpack them. Code a number of vectors through (keeping track of the quantized values), and decode using the unpacked book. quantized version of in should exactly equal out */#include <stdio.h>#include "vorbis/book/lsp20_0.vqh"#include "vorbis/book/res0a_13.vqh"#define TESTSIZE 40float test1[TESTSIZE]={ 0.105939f, 0.215373f, 0.429117f, 0.587974f, 0.181173f, 0.296583f, 0.515707f, 0.715261f, 0.162327f, 0.263834f, 0.342876f, 0.406025f, 0.103571f, 0.223561f, 0.368513f, 0.540313f, 0.136672f, 0.395882f, 0.587183f, 0.652476f, 0.114338f, 0.417300f, 0.525486f, 0.698679f, 0.147492f, 0.324481f, 0.643089f, 0.757582f, 0.139556f, 0.215795f, 0.324559f, 0.399387f, 0.120236f, 0.267420f, 0.446940f, 0.608760f, 0.115587f, 0.287234f, 0.571081f, 0.708603f,};float test3[TESTSIZE]={ 0,1,-2,3,4,-5,6,7,8,9, 8,-2,7,-1,4,6,8,3,1,-9, 10,11,12,13,14,15,26,17,18,19, 30,-25,-30,-1,-5,-32,4,3,-2,0};static_codebook *testlist[]={&_vq_book_lsp20_0, &_vq_book_res0a_13,NULL};float *testvec[]={test1,test3};int main(){ oggpack_buffer write; oggpack_buffer read; long ptr=0,i; oggpack_writeinit(&write); fprintf(stderr,"Testing codebook abstraction...:\n"); while(testlist[ptr]){ codebook c; static_codebook s; float *qv=alloca(sizeof(*qv)*TESTSIZE); float *iv=alloca(sizeof(*iv)*TESTSIZE); memcpy(qv,testvec[ptr],sizeof(*qv)*TESTSIZE); memset(iv,0,sizeof(*iv)*TESTSIZE); fprintf(stderr,"\tpacking/coding %ld... ",ptr); /* pack the codebook, write the testvector */ oggpack_reset(&write); vorbis_book_init_encode(&c,testlist[ptr]); /* get it into memory we can write */ vorbis_staticbook_pack(testlist[ptr],&write); fprintf(stderr,"Codebook size %ld bytes... ",oggpack_bytes(&write)); for(i=0;i<TESTSIZE;i+=c.dim){ int best=_best(&c,qv+i,1); vorbis_book_encodev(&c,best,qv+i,&write); } vorbis_book_clear(&c); fprintf(stderr,"OK.\n"); fprintf(stderr,"\tunpacking/decoding %ld... ",ptr); /* transfer the write data to a read buffer and unpack/read */ oggpack_readinit(&read,oggpack_get_buffer(&write),oggpack_bytes(&write)); if(vorbis_staticbook_unpack(&read,&s)){ fprintf(stderr,"Error unpacking codebook.\n"); exit(1); } if(vorbis_book_init_decode(&c,&s)){ fprintf(stderr,"Error initializing codebook.\n"); exit(1); } for(i=0;i<TESTSIZE;i+=c.dim) if(vorbis_book_decodev_set(&c,iv+i,&read,c.dim)==-1){ fprintf(stderr,"Error reading codebook test data (EOP).\n"); exit(1); } for(i=0;i<TESTSIZE;i++) if(fabs(qv[i]-iv[i])>.000001){ fprintf(stderr,"read (%g) != written (%g) at position (%ld)\n", iv[i],qv[i],i); exit(1); } fprintf(stderr,"OK\n"); ptr++; } /* The above is the trivial stuff; now try unquantizing a log scale codebook */ exit(0);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -