📄 codebook.c
字号:
/******************************************************************** * * * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * * * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002 * * by the XIPHOPHORUS Company http://www.xiph.org/ * * * ******************************************************************** function: basic codebook pack/unpack/code/decode operations last mod: $Id: codebook.c 1942 2005-10-12 23:35:43Z baford $ ********************************************************************/#include <stdlib.h>#include <string.h>#include <math.h>#include <ogg/ogg.h>#include "vorbis/codec.h"#include "codebook.h"#include "scales.h"#include "misc.h"#include "os.h"/* packs the given codebook into the bitstream **************************/int vorbis_staticbook_pack(const static_codebook *c,oggpack_buffer *opb){ long i,j; int ordered=0; /* first the basic parameters */ oggpack_write(opb,0x564342,24); oggpack_write(opb,c->dim,16); oggpack_write(opb,c->entries,24); /* pack the codewords. There are two packings; length ordered and length random. Decide between the two now. */ for(i=1;i<c->entries;i++) if(c->lengthlist[i-1]==0 || c->lengthlist[i]<c->lengthlist[i-1])break; if(i==c->entries)ordered=1; if(ordered){ /* length ordered. We only need to say how many codewords of each length. The actual codewords are generated deterministically */ long count=0; oggpack_write(opb,1,1); /* ordered */ oggpack_write(opb,c->lengthlist[0]-1,5); /* 1 to 32 */ for(i=1;i<c->entries;i++){ long this=c->lengthlist[i]; long last=c->lengthlist[i-1]; if(this>last){ for(j=last;j<this;j++){ oggpack_write(opb,i-count,_ilog(c->entries-count)); count=i; } } } oggpack_write(opb,i-count,_ilog(c->entries-count)); }else{ /* length random. Again, we don't code the codeword itself, just the length. This time, though, we have to encode each length */ oggpack_write(opb,0,1); /* unordered */ /* algortihmic mapping has use for 'unused entries', which we tag here. The algorithmic mapping happens as usual, but the unused entry has no codeword. */ for(i=0;i<c->entries;i++) if(c->lengthlist[i]==0)break; if(i==c->entries){ oggpack_write(opb,0,1); /* no unused entries */ for(i=0;i<c->entries;i++) oggpack_write(opb,c->lengthlist[i]-1,5); }else{ oggpack_write(opb,1,1); /* we have unused entries; thus we tag */ for(i=0;i<c->entries;i++){ if(c->lengthlist[i]==0){ oggpack_write(opb,0,1); }else{ oggpack_write(opb,1,1); oggpack_write(opb,c->lengthlist[i]-1,5); } } } } /* is the entry number the desired return value, or do we have a mapping? If we have a mapping, what type? */ oggpack_write(opb,c->maptype,4); switch(c->maptype){ case 0: /* no mapping */ break; case 1:case 2: /* implicitly populated value mapping */ /* explicitly populated value mapping */ if(!c->quantlist){ /* no quantlist? error */ return(-1); } /* values that define the dequantization */ oggpack_write(opb,c->q_min,32); oggpack_write(opb,c->q_delta,32); oggpack_write(opb,c->q_quant-1,4); oggpack_write(opb,c->q_sequencep,1); { int quantvals; switch(c->maptype){ case 1: /* a single column of (c->entries/c->dim) quantized values for building a full value list algorithmically (square lattice) */ quantvals=_book_maptype1_quantvals(c); break; case 2: /* every value (c->entries*c->dim total) specified explicitly */ quantvals=c->entries*c->dim; break; default: /* NOT_REACHABLE */ quantvals=-1; } /* quantized values */ for(i=0;i<quantvals;i++) oggpack_write(opb,labs(c->quantlist[i]),c->q_quant); } break; default: /* error case; we don't have any other map types now */ return(-1); } return(0);}/* unpacks a codebook from the packet buffer into the codebook struct, readies the codebook auxiliary structures for decode *************/int vorbis_staticbook_unpack(oggpack_buffer *opb,static_codebook *s){ long i,j; memset(s,0,sizeof(*s)); s->allocedp=1; /* make sure alignment is correct */ if(oggpack_read(opb,24)!=0x564342)goto _eofout; /* first the basic parameters */ s->dim=oggpack_read(opb,16); s->entries=oggpack_read(opb,24); if(s->entries==-1)goto _eofout; /* codeword ordering.... length ordered or unordered? */ switch((int)oggpack_read(opb,1)){ case 0: /* unordered */ s->lengthlist=_ogg_malloc(sizeof(*s->lengthlist)*s->entries); /* allocated but unused entries? */ if(oggpack_read(opb,1)){ /* yes, unused entries */ for(i=0;i<s->entries;i++){ if(oggpack_read(opb,1)){ long num=oggpack_read(opb,5); if(num==-1)goto _eofout; s->lengthlist[i]=num+1; }else s->lengthlist[i]=0; } }else{ /* all entries used; no tagging */ for(i=0;i<s->entries;i++){ long num=oggpack_read(opb,5); if(num==-1)goto _eofout; s->lengthlist[i]=num+1; } } break; case 1: /* ordered */ { long length=oggpack_read(opb,5)+1; s->lengthlist=_ogg_malloc(sizeof(*s->lengthlist)*s->entries); for(i=0;i<s->entries;){ long num=oggpack_read(opb,_ilog(s->entries-i)); if(num==-1)goto _eofout; for(j=0;j<num && i<s->entries;j++,i++) s->lengthlist[i]=length; length++; } } break; default: /* EOF */ return(-1); } /* Do we have a mapping to unpack? */ switch((s->maptype=oggpack_read(opb,4))){ case 0: /* no mapping */ break; case 1: case 2: /* implicitly populated value mapping */ /* explicitly populated value mapping */ s->q_min=oggpack_read(opb,32); s->q_delta=oggpack_read(opb,32); s->q_quant=oggpack_read(opb,4)+1; s->q_sequencep=oggpack_read(opb,1); { int quantvals=0; switch(s->maptype){ case 1: quantvals=_book_maptype1_quantvals(s); break; case 2: quantvals=s->entries*s->dim; break; } /* quantized values */ s->quantlist=_ogg_malloc(sizeof(*s->quantlist)*quantvals); for(i=0;i<quantvals;i++) s->quantlist[i]=oggpack_read(opb,s->q_quant); if(quantvals&&s->quantlist[quantvals-1]==-1)goto _eofout; } break; default: goto _errout; } /* all set */ return(0); _errout: _eofout: vorbis_staticbook_clear(s); return(-1); }/* returns the number of bits ************************************************/int vorbis_book_encode(codebook *book, int a, oggpack_buffer *b){ oggpack_write(b,book->codelist[a],book->c->lengthlist[a]); return(book->c->lengthlist[a]);}/* One the encode side, our vector writers are each designed for aspecific purpose, and the encoder is not flexible without modification:The LSP vector coder uses a single stage nearest-match with nointerleave, so no step and no error return. This is specced by floor0and doesn't change.Residue0 encoding interleaves, uses multiple stages, and each stagepeels of a specific amount of resolution from a lattice (thus we wantto match by threshold, not nearest match). Residue doesn't *have* tobe encoded that way, but to change it, one will need to add moreinfrastructure on the encode side (decode side is specced and simpler) *//* floor0 LSP (single stage, non interleaved, nearest match) *//* returns entry number and *modifies a* to the quantization value *****/int vorbis_book_errorv(codebook *book,float *a){ int dim=book->dim,k; int best=_best(book,a,1); for(k=0;k<dim;k++) a[k]=(book->valuelist+best*dim)[k]; return(best);}/* returns the number of bits and *modifies a* to the quantization value *****/int vorbis_book_encodev(codebook *book,int best,float *a,oggpack_buffer *b){ int k,dim=book->dim; for(k=0;k<dim;k++) a[k]=(book->valuelist+best*dim)[k]; return(vorbis_book_encode(book,best,b));}#if 1 /* XXX vx32 hack */static unsigned long mask[]={0x00000000,0x00000001,0x00000003,0x00000007,0x0000000f, 0x0000001f,0x0000003f,0x0000007f,0x000000ff,0x000001ff, 0x000003ff,0x000007ff,0x00000fff,0x00001fff,0x00003fff, 0x00007fff,0x0000ffff,0x0001ffff,0x0003ffff,0x0007ffff, 0x000fffff,0x001fffff,0x003fffff,0x007fffff,0x00ffffff, 0x01ffffff,0x03ffffff,0x07ffffff,0x0fffffff,0x1fffffff, 0x3fffffff,0x7fffffff,0xffffffff };/* Read in bits without advancing the bitptr; bits <= 32 */static inline long st_oggpack_look(oggpack_buffer *b,int bits){ unsigned long ret; unsigned long m=mask[bits]; bits+=b->endbit; if(b->endbyte+4>=b->storage){ /* not the main path */ if(b->endbyte*8+bits>b->storage*8)return(-1); } ret=b->ptr[0]>>b->endbit; if(bits>8){ ret|=b->ptr[1]<<(8-b->endbit); if(bits>16){ ret|=b->ptr[2]<<(16-b->endbit); if(bits>24){ ret|=b->ptr[3]<<(24-b->endbit); if(bits>32 && b->endbit) ret|=b->ptr[4]<<(32-b->endbit); } } } return(m&ret);}#define oggpack_look st_oggpack_lookstatic inline void st_oggpack_adv(oggpack_buffer *b,int bits){ bits+=b->endbit;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -