1
0
Fork 0
forked from len0rd/rockbox

Vorbis: Apply various bugfixes from upstream Tremor.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@13756 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Magnus Holmgren 2007-07-01 17:58:49 +00:00
parent 9af4289770
commit 932b20ec62
6 changed files with 290 additions and 260 deletions

View file

@ -148,7 +148,7 @@ static inline ogg_uint32_t bitreverse(register ogg_uint32_t x){
return((x>> 1)&0x55555555) | ((x<< 1)&0xaaaaaaaa);
}
static inline long decode_packed_entry_number(codebook *book,
STIN long decode_packed_entry_number(codebook *book,
oggpack_buffer *b){
int read=book->dec_maxlength;
long lo,hi;
@ -172,7 +172,11 @@ static inline long decode_packed_entry_number(codebook *book,
while(lok<0 && read>1)
lok = oggpack_look(b, --read);
if(lok<0)return -1;
if(lok<0){
oggpack_adv(b,1); /* force eop */
return -1;
}
/* bisect search for the codeword in the ordered list */
{
@ -191,7 +195,7 @@ static inline long decode_packed_entry_number(codebook *book,
}
}
oggpack_adv(b, read);
oggpack_adv(b, read+1);
return(-1);
}
@ -283,67 +287,73 @@ static inline long decode_packed_block(codebook *book, oggpack_buffer *b,
/* 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(book->used_entries>0){
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);
return(-1);
}
/* returns 0 on OK or -1 on eof *************************************/
long vorbis_book_decodevs_add(codebook *book,ogg_int32_t *a,
oggpack_buffer *b,int n,int point){
int step=n/book->dim;
long *entry = (long *)alloca(sizeof(*entry)*step);
ogg_int32_t **t = (ogg_int32_t **)alloca(sizeof(*t)*step);
int i,j,o;
int shift=point-book->binarypoint;
if(shift>=0){
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;
if(book->used_entries>0){
int step=n/book->dim;
long *entry = (long *)alloca(sizeof(*entry)*step);
ogg_int32_t **t = (ogg_int32_t **)alloca(sizeof(*t)*step);
int i,j,o;
int shift=point-book->binarypoint;
if(shift>=0){
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]>>shift;
}else{
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]<<-shift;
}
for(i=0,o=0;i<book->dim;i++,o+=step)
for (j=0;j<step;j++)
a[o+j]+=t[j][i]>>shift;
}else{
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]<<-shift;
}
return(0);
}
long vorbis_book_decodev_add(codebook *book,ogg_int32_t *a,
oggpack_buffer *b,int n,int point){
int i,j,entry;
ogg_int32_t *t;
int shift=point-book->binarypoint;
if(shift>=0){
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++]>>shift;
}
}else{
shift = -shift;
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++]<<shift;
if(book->used_entries>0){
int i,j,entry;
ogg_int32_t *t;
int shift=point-book->binarypoint;
if(shift>=0){
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++]>>shift;
}
}else{
shift = -shift;
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++]<<shift;
}
}
}
return(0);
@ -351,28 +361,38 @@ long vorbis_book_decodev_add(codebook *book,ogg_int32_t *a,
long vorbis_book_decodev_set(codebook *book,ogg_int32_t *a,
oggpack_buffer *b,int n,int point){
int i,j,entry;
ogg_int32_t *t;
int shift=point-book->binarypoint;
if(shift>=0){
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++]>>shift;
if(book->used_entries>0){
int i,j,entry;
ogg_int32_t *t;
int shift=point-book->binarypoint;
if(shift>=0){
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++]>>shift;
}
}
}else{
shift = -shift;
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++]<<shift;
}
}
}
}else{
shift = -shift;
int i,j;
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++]<<shift;
a[i++]=0;
}
}
}
@ -382,48 +402,50 @@ long vorbis_book_decodev_set(codebook *book,ogg_int32_t *a,
long vorbis_book_decodevv_add(codebook *book,ogg_int32_t **a,
long offset,int ch,
oggpack_buffer *b,int n,int point){
long i,j,k,chunk,read;
int chptr=0;
int shift=point-book->binarypoint;
long entries[32];
if(book->used_entries>0){
long i,j,k,chunk,read;
int chptr=0;
int shift=point-book->binarypoint;
long entries[32];
if(shift>=0){
if(shift>=0){
for(i=offset;i<offset+n;){
chunk=32;
if (chunk*book->dim>(offset+n-i)*ch)
chunk=((offset+n-i)*ch+book->dim-1)/book->dim;
read = decode_packed_block(book,b,entries,chunk);
for(k=0;k<read;k++){
const ogg_int32_t *t = book->valuelist+entries[k]*book->dim;
for (j=0;j<book->dim;j++){
a[chptr++][i]+=t[j]>>shift;
if(chptr==ch){
chptr=0;
i++;
for(i=offset;i<offset+n;){
chunk=32;
if (chunk*book->dim>(offset+n-i)*ch)
chunk=((offset+n-i)*ch+book->dim-1)/book->dim;
read = decode_packed_block(book,b,entries,chunk);
for(k=0;k<read;k++){
const ogg_int32_t *t = book->valuelist+entries[k]*book->dim;
for (j=0;j<book->dim;j++){
a[chptr++][i]+=t[j]>>shift;
if(chptr==ch){
chptr=0;
i++;
}
}
}
}
if (read<chunk)return-1;
}
if (read<chunk)return-1;
}
}else{
shift = -shift;
for(i=offset;i<offset+n;){
chunk=32;
if (chunk*book->dim>(offset+n-i)*ch)
chunk=((offset+n-i)*ch+book->dim-1)/book->dim;
read = decode_packed_block(book,b,entries,chunk);
for(k=0;k<read;k++){
const ogg_int32_t *t = book->valuelist+entries[k]*book->dim;
for (j=0;j<book->dim;j++){
a[chptr++][i]+=t[j]<<shift;
if(chptr==ch){
chptr=0;
i++;
}else{
shift = -shift;
for(i=offset;i<offset+n;){
chunk=32;
if (chunk*book->dim>(offset+n-i)*ch)
chunk=((offset+n-i)*ch+book->dim-1)/book->dim;
read = decode_packed_block(book,b,entries,chunk);
for(k=0;k<read;k++){
const ogg_int32_t *t = book->valuelist+entries[k]*book->dim;
for (j=0;j<book->dim;j++){
a[chptr++][i]+=t[j]<<shift;
if(chptr==ch){
chptr=0;
i++;
}
}
}
}
if (read<chunk)return-1;
}
if (read<chunk)return-1;
}
}
return(0);

View file

@ -286,7 +286,7 @@ static const ogg_int32_t FLOOR_fromdB_LOOKUP[256] ICONST_ATTR = {
XdB(0x69f80e9a), XdB(0x70dafda8), XdB(0x78307d76), XdB(0x7fffffff),
};
static void render_line(int x0,register int x1,int y0,int y1,ogg_int32_t *d){
static void render_line(int n, int x0,register int x1,int y0,int y1,ogg_int32_t *d){
int dy=y1-y0;
register int x=x0;
register int y=y0;
@ -296,11 +296,13 @@ static void render_line(int x0,register int x1,int y0,int y1,ogg_int32_t *d){
register int sy=(dy<0?base-1:base+1);
int err=0;
if(n>x1)n=x1;
ady-=abs(base*adx);
d[x]= MULT31_SHIFT15(d[x],FLOOR_fromdB_LOOKUP[y]);
if(x<n)
d[x]= MULT31_SHIFT15(d[x],FLOOR_fromdB_LOOKUP[y]);
while(++x<x1){
while(++x<n){
err=err+ady;
if(err>=adx){
err-=adx;
@ -424,7 +426,7 @@ static int floor1_inverse2(vorbis_block *vb,vorbis_look_floor *in,void *memo,
hy*=info->mult;
hx=info->postlist[current];
render_line(lx,hx,ly,hy,out);
render_line(n,lx,hx,ly,hy,out);
lx=hx;
ly=hy;

View file

@ -53,11 +53,6 @@ static void _ogg_buffer_destroy(ogg_buffer_state *bs){
bt=bs->unused_buffers;
rt=bs->unused_references;
if(!bs->outstanding){
_ogg_free(bs);
return;
}
while(bt){
ogg_buffer *b=bt;
bt=b->ptr.next;
@ -71,6 +66,10 @@ static void _ogg_buffer_destroy(ogg_buffer_state *bs){
_ogg_free(r);
}
bs->unused_references=0;
if(!bs->outstanding)
_ogg_free(bs);
}
}
@ -836,6 +835,7 @@ int ogg_stream_destroy(ogg_stream_state *os){
ogg_buffer_release(os->header_tail);
ogg_buffer_release(os->body_tail);
memset(os,0,sizeof(*os));
_ogg_free(os);
}
return OGG_SUCCESS;
}

View file

@ -97,8 +97,8 @@ void vorbis_comment_clear(vorbis_comment *vc){
if(vc->user_comments)_ogg_free(vc->user_comments);
if(vc->comment_lengths)_ogg_free(vc->comment_lengths);
if(vc->vendor)_ogg_free(vc->vendor);
memset(vc,0,sizeof(*vc));
}
memset(vc,0,sizeof(*vc));
}
/* blocksize 0 is guaranteed to be short, 1 is guarantted to be long.
@ -124,13 +124,16 @@ void vorbis_info_clear(vorbis_info *vi){
if(ci->mode_param[i])_ogg_free(ci->mode_param[i]);
for(i=0;i<ci->maps;i++) /* unpack does the range checking */
_mapping_P[ci->map_type[i]]->free_info(ci->map_param[i]);
if(ci->map_param[i])
_mapping_P[ci->map_type[i]]->free_info(ci->map_param[i]);
for(i=0;i<ci->floors;i++) /* unpack does the range checking */
_floor_P[ci->floor_type[i]]->free_info(ci->floor_param[i]);
if(ci->floor_param[i])
_floor_P[ci->floor_type[i]]->free_info(ci->floor_param[i]);
for(i=0;i<ci->residues;i++) /* unpack does the range checking */
_residue_P[ci->residue_type[i]]->free_info(ci->residue_param[i]);
if(ci->residue_param[i])
_residue_P[ci->residue_type[i]]->free_info(ci->residue_param[i]);
for(i=0;i<ci->books;i++){
if(ci->book_param[i]){

View file

@ -187,45 +187,48 @@ static int _01inverse(vorbis_block *vb,vorbis_look_residue *vl,
/* move all this setup out later */
int samples_per_partition=info->grouping;
int partitions_per_word=look->phrasebook->dim;
int n=info->end-info->begin;
int max=vb->pcmend>>1;
int end=(info->end<max?info->end:max);
int n=end-info->begin;
if(n>0){
int partvals=n/samples_per_partition;
int partwords=(partvals+partitions_per_word-1)/partitions_per_word;
int ***partword=(int ***)alloca(ch*sizeof(*partword));
int partvals=n/samples_per_partition;
int partwords=(partvals+partitions_per_word-1)/partitions_per_word;
int ***partword=(int ***)alloca(ch*sizeof(*partword));
for(j=0;j<ch;j++)
partword[j]=(int **)_vorbis_block_alloc(vb,partwords*sizeof(*partword[j]));
for(s=0;s<look->stages;s++){
/* each loop decodes on partition codeword containing
partitions_pre_word partitions */
for(i=0,l=0;i<partvals;l++){
if(s==0){
/* fetch the partition word for each channel */
for(j=0;j<ch;j++){
int temp=vorbis_book_decode(look->phrasebook,&vb->opb);
if(temp==-1)goto eopbreak;
partword[j][l]=look->decodemap[temp];
if(partword[j][l]==NULL)goto errout;
}
}
/* now we decode residual values for the partitions */
for(k=0;k<partitions_per_word && i<partvals;k++,i++)
for(j=0;j<ch;j++){
long offset=info->begin+i*samples_per_partition;
if(info->secondstages[partword[j][l][k]]&(1<<s)){
codebook *stagebook=look->partbooks[partword[j][l][k]][s];
if(stagebook){
if(decodepart(stagebook,in[j]+offset,&vb->opb,
samples_per_partition,-8)==-1)goto eopbreak;
}
for(j=0;j<ch;j++)
partword[j]=(int **)_vorbis_block_alloc(vb,partwords*sizeof(*partword[j]));
for(s=0;s<look->stages;s++){
/* each loop decodes on partition codeword containing
partitions_pre_word partitions */
for(i=0,l=0;i<partvals;l++){
if(s==0){
/* fetch the partition word for each channel */
for(j=0;j<ch;j++){
int temp=vorbis_book_decode(look->phrasebook,&vb->opb);
if(temp==-1)goto eopbreak;
partword[j][l]=look->decodemap[temp];
if(partword[j][l]==NULL)goto errout;
}
}
/* now we decode residual values for the partitions */
for(k=0;k<partitions_per_word && i<partvals;k++,i++)
for(j=0;j<ch;j++){
long offset=info->begin+i*samples_per_partition;
if(info->secondstages[partword[j][l][k]]&(1<<s)){
codebook *stagebook=look->partbooks[partword[j][l][k]][s];
if(stagebook){
if(decodepart(stagebook,in[j]+offset,&vb->opb,
samples_per_partition,-8)==-1)goto eopbreak;
}
}
}
}
}
}
errout:
eopbreak:
return(0);
@ -255,8 +258,6 @@ int res1_inverse(vorbis_block *vb,vorbis_look_residue *vl,
return(0);
}
/* duplicate code here as speed is somewhat more important */
int res2_inverse(vorbis_block *vb,vorbis_look_residue *vl,
ogg_int32_t **in,int *nonzero,int ch)
@ -270,44 +271,48 @@ int res2_inverse(vorbis_block *vb,vorbis_look_residue *vl,
/* move all this setup out later */
int samples_per_partition=info->grouping;
int partitions_per_word=look->phrasebook->dim;
int n=info->end-info->begin;
int max=(vb->pcmend*ch)>>1;
int end=(info->end<max?info->end:max);
int n=end-info->begin;
int partvals=n/samples_per_partition;
int partwords=(partvals+partitions_per_word-1)/partitions_per_word;
int **partword=(int **)_vorbis_block_alloc(vb,partwords*sizeof(*partword));
int beginoff=info->begin/ch;
for(i=0;i<ch;i++)if(nonzero[i])break;
if(i==ch)return(0); /* no nonzero vectors */
samples_per_partition/=ch;
for(s=0;s<look->stages;s++){
for(i=0,l=0;i<partvals;l++){
if(s==0){
/* fetch the partition word */
int temp=vorbis_book_decode(look->phrasebook,&vb->opb);
if(temp==-1)goto eopbreak;
partword[l]=look->decodemap[temp];
if(partword[l]==NULL)goto errout;
}
/* now we decode residual values for the partitions */
for(k=0;k<partitions_per_word && i<partvals;k++,i++)
if(info->secondstages[partword[l][k]]&(1<<s)){
codebook *stagebook=look->partbooks[partword[l][k]][s];
if(stagebook){
if(vorbis_book_decodevv_add(stagebook,in,
i*samples_per_partition+beginoff,ch,
&vb->opb,
samples_per_partition,-8)==-1)
goto eopbreak;
}
}
}
}
if(n>0){
int partvals=n/samples_per_partition;
int partwords=(partvals+partitions_per_word-1)/partitions_per_word;
int **partword=(int **)_vorbis_block_alloc(vb,partwords*sizeof(*partword));
int beginoff=info->begin/ch;
for(i=0;i<ch;i++)if(nonzero[i])break;
if(i==ch)return(0); /* no nonzero vectors */
samples_per_partition/=ch;
for(s=0;s<look->stages;s++){
for(i=0,l=0;i<partvals;l++){
if(s==0){
/* fetch the partition word */
int temp=vorbis_book_decode(look->phrasebook,&vb->opb);
if(temp==-1)goto eopbreak;
partword[l]=look->decodemap[temp];
if(partword[l]==NULL)goto errout;
}
/* now we decode residual values for the partitions */
for(k=0;k<partitions_per_word && i<partvals;k++,i++)
if(info->secondstages[partword[l][k]]&(1<<s)){
codebook *stagebook=look->partbooks[partword[l][k]][s];
if(stagebook){
if(vorbis_book_decodevv_add(stagebook,in,
i*samples_per_partition+beginoff,ch,
&vb->opb,
samples_per_partition,-8)==-1)
goto eopbreak;
}
}
}
}
}
errout:
eopbreak:
return(0);

View file

@ -337,24 +337,21 @@ int vorbis_book_init_decode(codebook *c,const static_codebook *s){
c->used_entries=n;
c->dim=s->dim;
c->q_min=s->q_min;
c->q_delta=s->q_delta;
/* two different remappings go on here.
First, we collapse the likely sparse codebook down only to
actually represented values/words. This collapsing needs to be
indexed as map-valueless books are used to encode original entry
positions as integers.
Second, we reorder all vectors, including the entry index above,
by sorted bitreversed codeword to allow treeless decode. */
{
if(n>0){
/* two different remappings go on here.
First, we collapse the likely sparse codebook down only to
actually represented values/words. This collapsing needs to be
indexed as map-valueless books are used to encode original entry
positions as integers.
Second, we reorder all vectors, including the entry index above,
by sorted bitreversed codeword to allow treeless decode. */
/* perform sort */
ogg_uint32_t *codes=_make_words(s->lengthlist,s->entries,c->used_entries);
ogg_uint32_t **codep=(ogg_uint32_t **)ogg_tmpmalloc(sizeof(*codep)*n);
if(codes==NULL||codep==NULL)goto err_out;
for(i=0;i<n;i++){
@ -375,67 +372,68 @@ int vorbis_book_init_decode(codebook *c,const static_codebook *s){
for(i=0;i<n;i++)
c->codelist[sortindex[i]]=codes[i];
/* _ogg_free(codes); */
}
c->valuelist=_book_unquantize(s,n,sortindex,&c->binarypoint);
c->dec_index=(int *)_ogg_malloc(n*sizeof(*c->dec_index));
for(n=0,i=0;i<s->entries;i++)
if(s->lengthlist[i]>0)
c->dec_index[sortindex[n++]]=i;
c->dec_codelengths=(char *)_ogg_malloc(n*sizeof(*c->dec_codelengths));
for(n=0,i=0;i<s->entries;i++)
if(s->lengthlist[i]>0)
c->dec_codelengths[sortindex[n++]]=s->lengthlist[i];
c->dec_firsttablen=_ilog(c->used_entries)-4; /* this is magic */
if(c->dec_firsttablen<5)c->dec_firsttablen=5;
if(c->dec_firsttablen>8)c->dec_firsttablen=8;
tabn=1<<c->dec_firsttablen;
c->dec_firsttable=(ogg_uint32_t *)_ogg_calloc(tabn,sizeof(*c->dec_firsttable));
c->dec_maxlength=0;
for(i=0;i<n;i++){
if(c->dec_maxlength<c->dec_codelengths[i])
c->dec_maxlength=c->dec_codelengths[i];
if(c->dec_codelengths[i]<=c->dec_firsttablen){
ogg_uint32_t orig=bitreverse(c->codelist[i]);
for(j=0;j<(1<<(c->dec_firsttablen-c->dec_codelengths[i]));j++)
c->dec_firsttable[orig|(j<<c->dec_codelengths[i])]=i+1;
c->valuelist=_book_unquantize(s,n,sortindex,&c->binarypoint);
c->dec_index=(int *)_ogg_malloc(n*sizeof(*c->dec_index));
for(n=0,i=0;i<s->entries;i++)
if(s->lengthlist[i]>0)
c->dec_index[sortindex[n++]]=i;
c->dec_codelengths=(char *)_ogg_malloc(n*sizeof(*c->dec_codelengths));
for(n=0,i=0;i<s->entries;i++)
if(s->lengthlist[i]>0)
c->dec_codelengths[sortindex[n++]]=s->lengthlist[i];
c->dec_firsttablen=_ilog(c->used_entries)-4; /* this is magic */
if(c->dec_firsttablen<5)c->dec_firsttablen=5;
if(c->dec_firsttablen>8)c->dec_firsttablen=8;
tabn=1<<c->dec_firsttablen;
c->dec_firsttable=(ogg_uint32_t *)_ogg_calloc(tabn,sizeof(*c->dec_firsttable));
c->dec_maxlength=0;
for(i=0;i<n;i++){
if(c->dec_maxlength<c->dec_codelengths[i])
c->dec_maxlength=c->dec_codelengths[i];
if(c->dec_codelengths[i]<=c->dec_firsttablen){
ogg_uint32_t orig=bitreverse(c->codelist[i]);
for(j=0;j<(1<<(c->dec_firsttablen-c->dec_codelengths[i]));j++)
c->dec_firsttable[orig|(j<<c->dec_codelengths[i])]=i+1;
}
}
}
/* now fill in 'unused' entries in the firsttable with hi/lo search
hints for the non-direct-hits */
{
ogg_uint32_t mask=0xfffffffeUL<<(31-c->dec_firsttablen);
long lo=0,hi=0;
for(i=0;i<tabn;i++){
ogg_uint32_t word=i<<(32-c->dec_firsttablen);
if(c->dec_firsttable[bitreverse(word)]==0){
while((lo+1)<n && c->codelist[lo+1]<=word)lo++;
while( hi<n && word>=(c->codelist[hi]&mask))hi++;
/* we only actually have 15 bits per hint to play with here.
In order to overflow gracefully (nothing breaks, efficiency
just drops), encode as the difference from the extremes. */
{
unsigned long loval=lo;
unsigned long hival=n-hi;
if(loval>0x7fff)loval=0x7fff;
if(hival>0x7fff)hival=0x7fff;
c->dec_firsttable[bitreverse(word)]=
0x80000000UL | (loval<<15) | hival;
/* now fill in 'unused' entries in the firsttable with hi/lo search
hints for the non-direct-hits */
{
ogg_uint32_t mask=0xfffffffeUL<<(31-c->dec_firsttablen);
long lo=0,hi=0;
for(i=0;i<tabn;i++){
ogg_uint32_t word=i<<(32-c->dec_firsttablen);
if(c->dec_firsttable[bitreverse(word)]==0){
while((lo+1)<n && c->codelist[lo+1]<=word)lo++;
while( hi<n && word>=(c->codelist[hi]&mask))hi++;
/* we only actually have 15 bits per hint to play with here.
In order to overflow gracefully (nothing breaks, efficiency
just drops), encode as the difference from the extremes. */
{
unsigned long loval=lo;
unsigned long hival=n-hi;
if(loval>0x7fff)loval=0x7fff;
if(hival>0x7fff)hival=0x7fff;
c->dec_firsttable[bitreverse(word)]=
0x80000000UL | (loval<<15) | hival;
}
}
}
}
}
ogg_tmpmalloc_free(pos);
return(0);
err_out: