Coverage Report

Created: 2026-05-24 07:02

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/tremor/sharedbook.c
Line
Count
Source
1
/********************************************************************
2
 *                                                                  *
3
 * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE.   *
4
 *                                                                  *
5
 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
6
 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
7
 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
8
 *                                                                  *
9
 * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002    *
10
 * BY THE Xiph.Org FOUNDATION http://www.xiph.org/                  *
11
 *                                                                  *
12
 ********************************************************************
13
14
 function: basic shared codebook operations
15
16
 ********************************************************************/
17
18
#include <stdlib.h>
19
#include <limits.h>
20
#include <math.h>
21
#include <string.h>
22
#include <ogg/ogg.h>
23
#include "misc.h"
24
#include "ivorbiscodec.h"
25
#include "codebook.h"
26
27
/**** pack/unpack helpers ******************************************/
28
39.2M
int _ilog(unsigned int v){
29
39.2M
  int ret=0;
30
76.1M
  while(v){
31
36.8M
    ret++;
32
36.8M
    v>>=1;
33
36.8M
  }
34
39.2M
  return(ret);
35
39.2M
}
36
37
/* 32 bit float (not IEEE; nonnormalized mantissa +
38
   biased exponent) : neeeeeee eeemmmmm mmmmmmmm mmmmmmmm 
39
   Why not IEEE?  It's just not that important here. */
40
41
#define VQ_FEXP 10
42
22.6k
#define VQ_FMAN 21
43
11.3k
#define VQ_FEXP_BIAS 768 /* bias toward values smaller than 1. */
44
45
11.3k
static ogg_int32_t _float32_unpack(long val,int *point){
46
11.3k
  long   mant=val&0x1fffff;
47
11.3k
  int    sign=val&0x80000000;
48
11.3k
  long   exp =(val&0x7fe00000L)>>VQ_FMAN;
49
50
11.3k
  exp-=(VQ_FMAN-1)+VQ_FEXP_BIAS;
51
52
11.3k
  if(mant){
53
139k
    while(!(mant&0x40000000)){
54
128k
      mant<<=1;
55
128k
      exp-=1;
56
128k
    }
57
58
10.0k
    if(sign)mant= -mant;
59
10.0k
  }else{
60
1.29k
    sign=0;
61
1.29k
    exp=-9999;
62
1.29k
  }
63
64
11.3k
  *point=exp;
65
11.3k
  return mant;
66
11.3k
}
67
68
/* given a list of word lengths, generate a list of codewords.  Works
69
   for length ordered or unordered, always assigns the lowest valued
70
   codewords first.  Extended to handle unused entries (length 0) */
71
11.2k
ogg_uint32_t *_make_words(long *l,long n,long sparsecount){
72
11.2k
  long i,j,count=0;
73
11.2k
  ogg_uint32_t marker[33];
74
11.2k
  ogg_uint32_t *r=(ogg_uint32_t *)_ogg_malloc((sparsecount?sparsecount:n)*sizeof(*r));
75
11.2k
  memset(marker,0,sizeof(marker));
76
77
2.05M
  for(i=0;i<n;i++){
78
2.04M
    long length=l[i];
79
2.04M
    if(length>0){
80
1.73M
      ogg_uint32_t entry=marker[length];
81
      
82
      /* when we claim a node for an entry, we also claim the nodes
83
   below it (pruning off the imagined tree that may have dangled
84
   from it) as well as blocking the use of any nodes directly
85
   above for leaves */
86
      
87
      /* update ourself */
88
1.73M
      if(length<32 && (entry>>length)){
89
  /* error condition; the lengths must specify an overpopulated tree */
90
24
  _ogg_free(r);
91
24
  return(NULL);
92
24
      }
93
1.73M
      r[count++]=entry;
94
    
95
      /* Look to see if the next shorter marker points to the node
96
   above. if so, update it and repeat.  */
97
1.73M
      {
98
3.51M
  for(j=length;j>0;j--){
99
    
100
3.50M
    if(marker[j]&1){
101
      /* have to jump branches */
102
1.71M
      if(j==1)
103
5.33k
        marker[1]++;
104
1.71M
      else
105
1.71M
        marker[j]=marker[j-1]<<1;
106
1.71M
      break; /* invariant says next upper marker would already
107
          have been moved if it was on the same path */
108
1.71M
    }
109
1.78M
    marker[j]++;
110
1.78M
  }
111
1.73M
      }
112
      
113
      /* prune the tree; the implicit invariant says all the longer
114
   markers were dangling from our just-taken node.  Dangle them
115
   from our *new* node. */
116
32.9M
      for(j=length+1;j<33;j++)
117
31.3M
  if((marker[j]>>1) == entry){
118
31.1M
    entry=marker[j];
119
31.1M
    marker[j]=marker[j-1]<<1;
120
31.1M
  }else
121
192k
    break;
122
1.73M
    }else
123
311k
      if(sparsecount==0)count++;
124
2.04M
  }
125
126
  /* sanity check the huffman tree; an underpopulated tree must be
127
     rejected. The only exception is the one-node pseudo-nil tree,
128
     which appears to be underpopulated because the tree doesn't
129
     really exist; there's only one possible 'codeword' or zero bits,
130
     but the above tree-gen code doesn't mark that. */
131
11.2k
  if(sparsecount != 1){
132
174k
    for(i=1;i<33;i++)
133
169k
      if(marker[i] & (0xffffffffUL>>(32-i))){
134
51
       _ogg_free(r);
135
51
       return(NULL);
136
51
      }
137
5.32k
  }
138
139
  /* bitreverse the words because our bitwise packer/unpacker is LSb
140
     endian */
141
2.03M
  for(i=0,count=0;i<n;i++){
142
2.02M
    ogg_uint32_t temp=0;
143
22.2M
    for(j=0;j<l[i];j++){
144
20.2M
      temp<<=1;
145
20.2M
      temp|=(r[count]>>j)&1;
146
20.2M
    }
147
148
2.02M
    if(sparsecount){
149
2.02M
      if(l[i])
150
1.71M
  r[count++]=temp;
151
2.02M
    }else
152
0
      r[count++]=temp;
153
2.02M
  }
154
155
11.1k
  return(r);
156
11.2k
}
157
158
/* there might be a straightforward one-line way to do the below
159
   that's portable and totally safe against roundoff, but I haven't
160
   thought of it.  Therefore, we opt on the side of caution */
161
8.36k
long _book_maptype1_quantvals(const static_codebook *b){
162
  /* get us a starting hint, we'll polish it below */
163
8.36k
  int bits=_ilog(b->entries);
164
8.36k
  int vals=b->entries>>((bits-1)*(b->dim-1)/b->dim);
165
8.36k
  if(b->entries<1){
166
326
    return(0);
167
326
  }
168
169
22.9k
  while(1){
170
22.9k
    long acc=1;
171
22.9k
    long acc1=1;
172
22.9k
    int i;
173
41.3M
    for(i=0;i<b->dim;i++){
174
41.3M
      if(b->entries/vals<acc)break;
175
41.3M
      acc*=vals;
176
41.3M
      if(LONG_MAX/(vals+1)<acc1)acc1=LONG_MAX;
177
197k
      else acc1*=vals+1;
178
41.3M
    }
179
22.9k
    if(i>=b->dim && acc<=b->entries && acc1>b->entries){
180
8.03k
      return(vals);
181
14.9k
    }else{
182
14.9k
      if(i<b->dim || acc>b->entries){
183
14.9k
        vals--;
184
14.9k
      }else{
185
0
        vals++;
186
0
      }
187
14.9k
    }
188
22.9k
  }
189
8.03k
}
190
191
/* different than what _book_unquantize does for mainline:
192
   we repack the book in a fixed point format that shares the same
193
   binary point.  Upon first use, we can shift point if needed */
194
195
/* we need to deal with two map types: in map type 1, the values are
196
   generated algorithmically (each column of the vector counts through
197
   the values in the quant vector). in map type 2, all the values came
198
   in in an explicit list.  Both value lists must be unpacked */
199
200
ogg_int32_t *_book_unquantize(const static_codebook *b,int n,int *sparsemap,
201
11.1k
            int *maxpoint){
202
11.1k
  long j,k,count=0;
203
11.1k
  if(b->maptype==1 || b->maptype==2){
204
5.66k
    int quantvals;
205
5.66k
    int minpoint,delpoint;
206
5.66k
    ogg_int32_t mindel=_float32_unpack(b->q_min,&minpoint);
207
5.66k
    ogg_int32_t delta=_float32_unpack(b->q_delta,&delpoint);
208
5.66k
    ogg_int32_t *r=(ogg_int32_t *)_ogg_calloc(n*b->dim,sizeof(*r));
209
5.66k
    int *rp=(int *)_ogg_calloc(n*b->dim,sizeof(*rp));
210
211
5.66k
    *maxpoint=minpoint;
212
213
    /* maptype 1 and 2 both use a quantized value vector, but
214
       different sizes */
215
5.66k
    switch(b->maptype){
216
3.62k
    case 1:
217
      /* most of the time, entries%dimensions == 0, but we need to be
218
   well defined.  We define that the possible vales at each
219
   scalar is values == entries/dim.  If entries%dim != 0, we'll
220
   have 'too few' values (values*dim<entries), which means that
221
   we'll have 'left over' entries; left over entries use zeroed
222
   values (and are wasted).  So don't generate codebooks like
223
   that */
224
3.62k
      quantvals=_book_maptype1_quantvals(b);
225
415k
      for(j=0;j<b->entries;j++){
226
411k
  if((sparsemap && b->lengthlist[j]) || !sparsemap){
227
224k
    ogg_int32_t last=0;
228
224k
    int lastpoint=0;
229
224k
    int indexdiv=1;
230
39.3M
    for(k=0;k<b->dim;k++){
231
39.1M
      int index= (j/indexdiv)%quantvals;
232
39.1M
      int point=0;
233
39.1M
      int val=VFLOAT_MULTI(delta,delpoint,
234
39.1M
         abs(b->quantlist[index]),&point);
235
236
39.1M
      val=VFLOAT_ADD(mindel,minpoint,val,point,&point);
237
39.1M
      val=VFLOAT_ADD(last,lastpoint,val,point,&point);
238
      
239
39.1M
      if(b->q_sequencep){
240
9.09M
        last=val;   
241
9.09M
        lastpoint=point;
242
9.09M
      }
243
      
244
39.1M
      if(sparsemap){
245
39.1M
        r[sparsemap[count]*b->dim+k]=val;
246
39.1M
        rp[sparsemap[count]*b->dim+k]=point;
247
39.1M
      }else{
248
0
        r[count*b->dim+k]=val;
249
0
        rp[count*b->dim+k]=point;
250
0
      }
251
39.1M
      if(*maxpoint<point)*maxpoint=point;
252
39.1M
      indexdiv*=quantvals;
253
39.1M
    }
254
224k
    count++;
255
224k
  }
256
257
411k
      }
258
3.62k
      break;
259
2.03k
    case 2:
260
25.9k
      for(j=0;j<b->entries;j++){
261
23.9k
  if((sparsemap && b->lengthlist[j]) || !sparsemap){
262
3.79k
    ogg_int32_t last=0;
263
3.79k
    int         lastpoint=0;
264
265
42.2k
    for(k=0;k<b->dim;k++){
266
38.4k
      int point=0;
267
38.4k
      int val=VFLOAT_MULTI(delta,delpoint,
268
38.4k
         abs(b->quantlist[j*b->dim+k]),&point);
269
270
38.4k
      val=VFLOAT_ADD(mindel,minpoint,val,point,&point);
271
38.4k
      val=VFLOAT_ADD(last,lastpoint,val,point,&point);
272
      
273
38.4k
      if(b->q_sequencep){
274
35.8k
        last=val;   
275
35.8k
        lastpoint=point;
276
35.8k
      }
277
278
38.4k
      if(sparsemap){
279
38.4k
        r[sparsemap[count]*b->dim+k]=val;
280
38.4k
        rp[sparsemap[count]*b->dim+k]=point;
281
38.4k
      }else{
282
0
        r[count*b->dim+k]=val;
283
0
        rp[count*b->dim+k]=point;
284
0
      }
285
38.4k
      if(*maxpoint<point)*maxpoint=point;
286
38.4k
    }
287
3.79k
    count++;
288
3.79k
  }
289
23.9k
      }
290
2.03k
      break;
291
5.66k
    }
292
293
39.1M
    for(j=0;j<n*b->dim;j++)
294
39.1M
      if(rp[j]<*maxpoint)
295
6.51M
  r[j]>>=*maxpoint-rp[j];
296
      
297
5.66k
    _ogg_free(rp);
298
5.66k
    return(r);
299
5.66k
  }
300
5.49k
  return(NULL);
301
11.1k
}
302
303
14.5k
void vorbis_staticbook_destroy(static_codebook *b){
304
14.5k
  if(b->quantlist)_ogg_free(b->quantlist);
305
14.5k
  if(b->lengthlist)_ogg_free(b->lengthlist);
306
14.5k
  memset(b,0,sizeof(*b));
307
14.5k
  _ogg_free(b);
308
14.5k
}
309
310
12.3k
void vorbis_book_clear(codebook *b){
311
  /* static book is not cleared; we're likely called on the lookup and
312
     the static codebook belongs to the info struct */
313
12.3k
  if(b->valuelist)_ogg_free(b->valuelist);
314
12.3k
  if(b->codelist)_ogg_free(b->codelist);
315
316
12.3k
  if(b->dec_index)_ogg_free(b->dec_index);
317
12.3k
  if(b->dec_codelengths)_ogg_free(b->dec_codelengths);
318
12.3k
  if(b->dec_firsttable)_ogg_free(b->dec_firsttable);
319
320
12.3k
  memset(b,0,sizeof(*b));
321
12.3k
}
322
323
2.48M
static ogg_uint32_t bitreverse(ogg_uint32_t x){
324
2.48M
  x=    ((x>>16)&0x0000ffffUL) | ((x<<16)&0xffff0000UL);
325
2.48M
  x=    ((x>> 8)&0x00ff00ffUL) | ((x<< 8)&0xff00ff00UL);
326
2.48M
  x=    ((x>> 4)&0x0f0f0f0fUL) | ((x<< 4)&0xf0f0f0f0UL);
327
2.48M
  x=    ((x>> 2)&0x33333333UL) | ((x<< 2)&0xccccccccUL);
328
2.48M
  return((x>> 1)&0x55555555UL) | ((x<< 1)&0xaaaaaaaaUL);
329
2.48M
}
330
331
9.75M
static int sort32a(const void *a,const void *b){
332
9.75M
  return (**(ogg_uint32_t **)a>**(ogg_uint32_t **)b)-
333
9.75M
    (**(ogg_uint32_t **)a<**(ogg_uint32_t **)b);
334
9.75M
}
335
336
/* decode codebook arrangement is more heavily optimized than encode */
337
11.6k
int vorbis_book_init_decode(codebook *c,const static_codebook *s){
338
11.6k
  int i,j,n=0,tabn;
339
11.6k
  int *sortindex;
340
11.6k
  memset(c,0,sizeof(*c));
341
  
342
  /* count actually used entries */
343
2.05M
  for(i=0;i<s->entries;i++)
344
2.04M
    if(s->lengthlist[i]>0)
345
1.73M
      n++;
346
347
11.6k
  c->entries=s->entries;
348
11.6k
  c->used_entries=n;
349
11.6k
  c->dim=s->dim;
350
351
11.6k
  if(n>0){
352
    /* two different remappings go on here.  
353
       
354
       First, we collapse the likely sparse codebook down only to
355
       actually represented values/words.  This collapsing needs to be
356
       indexed as map-valueless books are used to encode original entry
357
       positions as integers.
358
       
359
       Second, we reorder all vectors, including the entry index above,
360
       by sorted bitreversed codeword to allow treeless decode. */
361
    
362
    /* perform sort */
363
11.2k
    ogg_uint32_t *codes=_make_words(s->lengthlist,s->entries,c->used_entries);
364
11.2k
    ogg_uint32_t **codep=(ogg_uint32_t **)alloca(sizeof(*codep)*n);
365
    
366
11.2k
    if(codes==NULL)goto err_out;
367
368
1.73M
    for(i=0;i<n;i++){
369
1.71M
      codes[i]=bitreverse(codes[i]);
370
1.71M
      codep[i]=codes+i;
371
1.71M
    }
372
373
11.1k
    qsort(codep,n,sizeof(*codep),sort32a);
374
375
11.1k
    sortindex=(int *)alloca(n*sizeof(*sortindex));
376
11.1k
    c->codelist=(ogg_uint32_t *)_ogg_malloc(n*sizeof(*c->codelist));
377
    /* the index is a reverse index */
378
1.73M
    for(i=0;i<n;i++){
379
1.71M
      int position=codep[i]-codes;
380
1.71M
      sortindex[position]=i;
381
1.71M
    }
382
383
1.73M
    for(i=0;i<n;i++)
384
1.71M
      c->codelist[sortindex[i]]=codes[i];
385
11.1k
    _ogg_free(codes);
386
    
387
    
388
    
389
11.1k
    c->valuelist=_book_unquantize(s,n,sortindex,&c->binarypoint);
390
11.1k
    c->dec_index=(int *)_ogg_malloc(n*sizeof(*c->dec_index));
391
    
392
2.03M
    for(n=0,i=0;i<s->entries;i++)
393
2.02M
      if(s->lengthlist[i]>0)
394
1.71M
  c->dec_index[sortindex[n++]]=i;
395
    
396
11.1k
    c->dec_codelengths=(char *)_ogg_malloc(n*sizeof(*c->dec_codelengths));
397
2.03M
    for(n=0,i=0;i<s->entries;i++)
398
2.02M
      if(s->lengthlist[i]>0)
399
1.71M
  c->dec_codelengths[sortindex[n++]]=s->lengthlist[i];
400
    
401
11.1k
    c->dec_firsttablen=_ilog(c->used_entries)-4; /* this is magic */
402
11.1k
    if(c->dec_firsttablen<5)c->dec_firsttablen=5;
403
11.1k
    if(c->dec_firsttablen>8)c->dec_firsttablen=8;
404
    
405
11.1k
    tabn=1<<c->dec_firsttablen;
406
11.1k
    c->dec_firsttable=(ogg_uint32_t *)_ogg_calloc(tabn,sizeof(*c->dec_firsttable));
407
11.1k
    c->dec_maxlength=0;
408
    
409
1.73M
    for(i=0;i<n;i++){
410
1.71M
      if(c->dec_maxlength<c->dec_codelengths[i])
411
27.6k
  c->dec_maxlength=c->dec_codelengths[i];
412
1.71M
      if(c->dec_codelengths[i]<=c->dec_firsttablen){
413
48.5k
  ogg_uint32_t orig=bitreverse(c->codelist[i]);
414
241k
  for(j=0;j<(1<<(c->dec_firsttablen-c->dec_codelengths[i]));j++)
415
192k
    c->dec_firsttable[orig|(j<<c->dec_codelengths[i])]=i+1;
416
48.5k
      }
417
1.71M
    }
418
    
419
    /* now fill in 'unused' entries in the firsttable with hi/lo search
420
       hints for the non-direct-hits */
421
11.1k
    {
422
11.1k
      ogg_uint32_t mask=0xfffffffeUL<<(31-c->dec_firsttablen);
423
11.1k
      long lo=0,hi=0;
424
      
425
464k
      for(i=0;i<tabn;i++){
426
453k
  ogg_uint32_t word=((ogg_uint32_t)i<<(32-c->dec_firsttablen));
427
453k
  if(c->dec_firsttable[bitreverse(word)]==0){
428
1.89M
    while((lo+1)<n && c->codelist[lo+1]<=word)lo++;
429
1.96M
    while(    hi<n && word>=(c->codelist[hi]&mask))hi++;
430
    
431
    /* we only actually have 15 bits per hint to play with here.
432
       In order to overflow gracefully (nothing breaks, efficiency
433
       just drops), encode as the difference from the extremes. */
434
260k
    {
435
260k
      unsigned long loval=lo;
436
260k
      unsigned long hival=n-hi;
437
      
438
260k
      if(loval>0x7fff)loval=0x7fff;
439
260k
      if(hival>0x7fff)hival=0x7fff;
440
260k
      c->dec_firsttable[bitreverse(word)]=
441
260k
        0x80000000UL | (loval<<15) | hival;
442
260k
    }
443
260k
  }
444
453k
      }
445
11.1k
    }
446
11.1k
  }
447
448
11.5k
  return(0);
449
75
 err_out:
450
75
  vorbis_book_clear(c);
451
75
  return(-1);
452
11.6k
}
453