Coverage Report

Created: 2026-08-13 06:25

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
44.1M
int _ilog(unsigned int v){
29
44.1M
  int ret=0;
30
94.5M
  while(v){
31
50.3M
    ret++;
32
50.3M
    v>>=1;
33
50.3M
  }
34
44.1M
  return(ret);
35
44.1M
}
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
23.0k
#define VQ_FMAN 21
43
11.5k
#define VQ_FEXP_BIAS 768 /* bias toward values smaller than 1. */
44
45
11.5k
static ogg_int32_t _float32_unpack(long val,int *point){
46
11.5k
  long   mant=val&0x1fffff;
47
11.5k
  int    sign=val&0x80000000;
48
11.5k
  long   exp =(val&0x7fe00000L)>>VQ_FMAN;
49
50
11.5k
  exp-=(VQ_FMAN-1)+VQ_FEXP_BIAS;
51
52
11.5k
  if(mant){
53
140k
    while(!(mant&0x40000000)){
54
130k
      mant<<=1;
55
130k
      exp-=1;
56
130k
    }
57
58
10.1k
    if(sign)mant= -mant;
59
10.1k
  }else{
60
1.34k
    sign=0;
61
1.34k
    exp=-9999;
62
1.34k
  }
63
64
11.5k
  *point=exp;
65
11.5k
  return mant;
66
11.5k
}
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
12.0k
ogg_uint32_t *_make_words(long *l,long n,long sparsecount){
72
12.0k
  long i,j,count=0;
73
12.0k
  ogg_uint32_t marker[33];
74
12.0k
  ogg_uint32_t *r=(ogg_uint32_t *)_ogg_malloc((sparsecount?sparsecount:n)*sizeof(*r));
75
12.0k
  memset(marker,0,sizeof(marker));
76
77
1.96M
  for(i=0;i<n;i++){
78
1.95M
    long length=l[i];
79
1.95M
    if(length>0){
80
1.60M
      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.60M
      if(length<32 && (entry>>length)){
89
  /* error condition; the lengths must specify an overpopulated tree */
90
31
  _ogg_free(r);
91
31
  return(NULL);
92
31
      }
93
1.60M
      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.60M
      {
98
3.28M
  for(j=length;j>0;j--){
99
    
100
3.27M
    if(marker[j]&1){
101
      /* have to jump branches */
102
1.59M
      if(j==1)
103
5.33k
        marker[1]++;
104
1.59M
      else
105
1.59M
        marker[j]=marker[j-1]<<1;
106
1.59M
      break; /* invariant says next upper marker would already
107
          have been moved if it was on the same path */
108
1.59M
    }
109
1.67M
    marker[j]++;
110
1.67M
  }
111
1.60M
      }
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
29.5M
      for(j=length+1;j<33;j++)
117
28.2M
  if((marker[j]>>1) == entry){
118
27.9M
    entry=marker[j];
119
27.9M
    marker[j]=marker[j-1]<<1;
120
27.9M
  }else
121
232k
    break;
122
1.60M
    }else
123
345k
      if(sparsecount==0)count++;
124
1.95M
  }
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.9k
  if(sparsecount != 1){
132
173k
    for(i=1;i<33;i++)
133
168k
      if(marker[i] & (0xffffffffUL>>(32-i))){
134
78
       _ogg_free(r);
135
78
       return(NULL);
136
78
      }
137
5.32k
  }
138
139
  /* bitreverse the words because our bitwise packer/unpacker is LSb
140
     endian */
141
1.94M
  for(i=0,count=0;i<n;i++){
142
1.93M
    ogg_uint32_t temp=0;
143
20.6M
    for(j=0;j<l[i];j++){
144
18.6M
      temp<<=1;
145
18.6M
      temp|=(r[count]>>j)&1;
146
18.6M
    }
147
148
1.93M
    if(sparsecount){
149
1.93M
      if(l[i])
150
1.59M
  r[count++]=temp;
151
1.93M
    }else
152
0
      r[count++]=temp;
153
1.93M
  }
154
155
11.9k
  return(r);
156
11.9k
}
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.97k
long _book_maptype1_quantvals(const static_codebook *b){
162
  /* get us a starting hint, we'll polish it below */
163
8.97k
  int bits=_ilog(b->entries);
164
8.97k
  int vals=b->entries>>((bits-1)*(b->dim-1)/b->dim);
165
8.97k
  if(b->entries<1){
166
270
    return(0);
167
270
  }
168
169
25.4k
  while(1){
170
25.4k
    long acc=1;
171
25.4k
    long acc1=1;
172
25.4k
    int i;
173
51.8M
    for(i=0;i<b->dim;i++){
174
51.8M
      if(b->entries/vals<acc)break;
175
51.8M
      acc*=vals;
176
51.8M
      if(LONG_MAX/(vals+1)<acc1)acc1=LONG_MAX;
177
218k
      else acc1*=vals+1;
178
51.8M
    }
179
25.4k
    if(i>=b->dim && acc<=b->entries && acc1>b->entries){
180
8.70k
      return(vals);
181
16.7k
    }else{
182
16.7k
      if(i<b->dim || acc>b->entries){
183
16.7k
        vals--;
184
16.7k
      }else{
185
0
        vals++;
186
0
      }
187
16.7k
    }
188
25.4k
  }
189
8.70k
}
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.9k
            int *maxpoint){
202
11.9k
  long j,k,count=0;
203
11.9k
  if(b->maptype==1 || b->maptype==2){
204
5.76k
    int quantvals;
205
5.76k
    int minpoint,delpoint;
206
5.76k
    ogg_int32_t mindel=_float32_unpack(b->q_min,&minpoint);
207
5.76k
    ogg_int32_t delta=_float32_unpack(b->q_delta,&delpoint);
208
5.76k
    ogg_int32_t *r=(ogg_int32_t *)_ogg_calloc(n*b->dim,sizeof(*r));
209
5.76k
    int *rp=(int *)_ogg_calloc(n*b->dim,sizeof(*rp));
210
211
5.76k
    *maxpoint=minpoint;
212
213
    /* maptype 1 and 2 both use a quantized value vector, but
214
       different sizes */
215
5.76k
    switch(b->maptype){
216
3.88k
    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.88k
      quantvals=_book_maptype1_quantvals(b);
225
489k
      for(j=0;j<b->entries;j++){
226
485k
  if((sparsemap && b->lengthlist[j]) || !sparsemap){
227
269k
    ogg_int32_t last=0;
228
269k
    int lastpoint=0;
229
269k
    int indexdiv=1;
230
44.3M
    for(k=0;k<b->dim;k++){
231
44.0M
      int index= (j/indexdiv)%quantvals;
232
44.0M
      int point=0;
233
44.0M
      int val=VFLOAT_MULTI(delta,delpoint,
234
44.0M
         abs(b->quantlist[index]),&point);
235
236
44.0M
      val=VFLOAT_ADD(mindel,minpoint,val,point,&point);
237
44.0M
      val=VFLOAT_ADD(last,lastpoint,val,point,&point);
238
      
239
44.0M
      if(b->q_sequencep){
240
12.7M
        last=val;   
241
12.7M
        lastpoint=point;
242
12.7M
      }
243
      
244
44.0M
      if(sparsemap){
245
44.0M
        r[sparsemap[count]*b->dim+k]=val;
246
44.0M
        rp[sparsemap[count]*b->dim+k]=point;
247
44.0M
      }else{
248
0
        r[count*b->dim+k]=val;
249
0
        rp[count*b->dim+k]=point;
250
0
      }
251
44.0M
      if(*maxpoint<point)*maxpoint=point;
252
44.0M
      indexdiv*=quantvals;
253
44.0M
    }
254
269k
    count++;
255
269k
  }
256
257
485k
      }
258
3.88k
      break;
259
1.87k
    case 2:
260
26.5k
      for(j=0;j<b->entries;j++){
261
24.6k
  if((sparsemap && b->lengthlist[j]) || !sparsemap){
262
3.42k
    ogg_int32_t last=0;
263
3.42k
    int         lastpoint=0;
264
265
30.3k
    for(k=0;k<b->dim;k++){
266
26.9k
      int point=0;
267
26.9k
      int val=VFLOAT_MULTI(delta,delpoint,
268
26.9k
         abs(b->quantlist[j*b->dim+k]),&point);
269
270
26.9k
      val=VFLOAT_ADD(mindel,minpoint,val,point,&point);
271
26.9k
      val=VFLOAT_ADD(last,lastpoint,val,point,&point);
272
      
273
26.9k
      if(b->q_sequencep){
274
23.6k
        last=val;   
275
23.6k
        lastpoint=point;
276
23.6k
      }
277
278
26.9k
      if(sparsemap){
279
26.9k
        r[sparsemap[count]*b->dim+k]=val;
280
26.9k
        rp[sparsemap[count]*b->dim+k]=point;
281
26.9k
      }else{
282
0
        r[count*b->dim+k]=val;
283
0
        rp[count*b->dim+k]=point;
284
0
      }
285
26.9k
      if(*maxpoint<point)*maxpoint=point;
286
26.9k
    }
287
3.42k
    count++;
288
3.42k
  }
289
24.6k
      }
290
1.87k
      break;
291
5.76k
    }
292
293
44.1M
    for(j=0;j<n*b->dim;j++)
294
44.1M
      if(rp[j]<*maxpoint)
295
9.28M
  r[j]>>=*maxpoint-rp[j];
296
      
297
5.76k
    _ogg_free(rp);
298
5.76k
    return(r);
299
5.76k
  }
300
6.14k
  return(NULL);
301
11.9k
}
302
303
15.5k
void vorbis_staticbook_destroy(static_codebook *b){
304
15.5k
  if(b->quantlist)_ogg_free(b->quantlist);
305
15.5k
  if(b->lengthlist)_ogg_free(b->lengthlist);
306
15.5k
  memset(b,0,sizeof(*b));
307
15.5k
  _ogg_free(b);
308
15.5k
}
309
310
13.4k
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
13.4k
  if(b->valuelist)_ogg_free(b->valuelist);
314
13.4k
  if(b->codelist)_ogg_free(b->codelist);
315
316
13.4k
  if(b->dec_index)_ogg_free(b->dec_index);
317
13.4k
  if(b->dec_codelengths)_ogg_free(b->dec_codelengths);
318
13.4k
  if(b->dec_firsttable)_ogg_free(b->dec_firsttable);
319
320
13.4k
  memset(b,0,sizeof(*b));
321
13.4k
}
322
323
2.39M
static ogg_uint32_t bitreverse(ogg_uint32_t x){
324
2.39M
  x=    ((x>>16)&0x0000ffffUL) | ((x<<16)&0xffff0000UL);
325
2.39M
  x=    ((x>> 8)&0x00ff00ffUL) | ((x<< 8)&0xff00ff00UL);
326
2.39M
  x=    ((x>> 4)&0x0f0f0f0fUL) | ((x<< 4)&0xf0f0f0f0UL);
327
2.39M
  x=    ((x>> 2)&0x33333333UL) | ((x<< 2)&0xccccccccUL);
328
2.39M
  return((x>> 1)&0x55555555UL) | ((x<< 1)&0xaaaaaaaaUL);
329
2.39M
}
330
331
8.93M
static int sort32a(const void *a,const void *b){
332
8.93M
  return (**(ogg_uint32_t **)a>**(ogg_uint32_t **)b)-
333
8.93M
    (**(ogg_uint32_t **)a<**(ogg_uint32_t **)b);
334
8.93M
}
335
336
/* decode codebook arrangement is more heavily optimized than encode */
337
12.4k
int vorbis_book_init_decode(codebook *c,const static_codebook *s){
338
12.4k
  int i,j,n=0,tabn;
339
12.4k
  int *sortindex;
340
12.4k
  memset(c,0,sizeof(*c));
341
  
342
  /* count actually used entries */
343
1.97M
  for(i=0;i<s->entries;i++)
344
1.96M
    if(s->lengthlist[i]>0)
345
1.61M
      n++;
346
347
12.4k
  c->entries=s->entries;
348
12.4k
  c->used_entries=n;
349
12.4k
  c->dim=s->dim;
350
351
12.4k
  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
12.0k
    ogg_uint32_t *codes=_make_words(s->lengthlist,s->entries,c->used_entries);
364
12.0k
    ogg_uint32_t **codep=(ogg_uint32_t **)alloca(sizeof(*codep)*n);
365
    
366
12.0k
    if(codes==NULL)goto err_out;
367
368
1.60M
    for(i=0;i<n;i++){
369
1.59M
      codes[i]=bitreverse(codes[i]);
370
1.59M
      codep[i]=codes+i;
371
1.59M
    }
372
373
11.9k
    qsort(codep,n,sizeof(*codep),sort32a);
374
375
11.9k
    sortindex=(int *)alloca(n*sizeof(*sortindex));
376
11.9k
    c->codelist=(ogg_uint32_t *)_ogg_malloc(n*sizeof(*c->codelist));
377
    /* the index is a reverse index */
378
1.60M
    for(i=0;i<n;i++){
379
1.59M
      int position=codep[i]-codes;
380
1.59M
      sortindex[position]=i;
381
1.59M
    }
382
383
1.60M
    for(i=0;i<n;i++)
384
1.59M
      c->codelist[sortindex[i]]=codes[i];
385
11.9k
    _ogg_free(codes);
386
    
387
    
388
    
389
11.9k
    c->valuelist=_book_unquantize(s,n,sortindex,&c->binarypoint);
390
11.9k
    c->dec_index=(int *)_ogg_malloc(n*sizeof(*c->dec_index));
391
    
392
1.94M
    for(n=0,i=0;i<s->entries;i++)
393
1.93M
      if(s->lengthlist[i]>0)
394
1.59M
  c->dec_index[sortindex[n++]]=i;
395
    
396
11.9k
    c->dec_codelengths=(char *)_ogg_malloc(n*sizeof(*c->dec_codelengths));
397
1.94M
    for(n=0,i=0;i<s->entries;i++)
398
1.93M
      if(s->lengthlist[i]>0)
399
1.59M
  c->dec_codelengths[sortindex[n++]]=s->lengthlist[i];
400
    
401
11.9k
    c->dec_firsttablen=_ilog(c->used_entries)-4; /* this is magic */
402
11.9k
    if(c->dec_firsttablen<5)c->dec_firsttablen=5;
403
11.9k
    if(c->dec_firsttablen>8)c->dec_firsttablen=8;
404
    
405
11.9k
    tabn=1<<c->dec_firsttablen;
406
11.9k
    c->dec_firsttable=(ogg_uint32_t *)_ogg_calloc(tabn,sizeof(*c->dec_firsttable));
407
11.9k
    c->dec_maxlength=0;
408
    
409
1.60M
    for(i=0;i<n;i++){
410
1.59M
      if(c->dec_maxlength<c->dec_codelengths[i])
411
28.9k
  c->dec_maxlength=c->dec_codelengths[i];
412
1.59M
      if(c->dec_codelengths[i]<=c->dec_firsttablen){
413
50.5k
  ogg_uint32_t orig=bitreverse(c->codelist[i]);
414
246k
  for(j=0;j<(1<<(c->dec_firsttablen-c->dec_codelengths[i]));j++)
415
195k
    c->dec_firsttable[orig|(j<<c->dec_codelengths[i])]=i+1;
416
50.5k
      }
417
1.59M
    }
418
    
419
    /* now fill in 'unused' entries in the firsttable with hi/lo search
420
       hints for the non-direct-hits */
421
11.9k
    {
422
11.9k
      ogg_uint32_t mask=0xfffffffeUL<<(31-c->dec_firsttablen);
423
11.9k
      long lo=0,hi=0;
424
      
425
485k
      for(i=0;i<tabn;i++){
426
473k
  ogg_uint32_t word=((ogg_uint32_t)i<<(32-c->dec_firsttablen));
427
473k
  if(c->dec_firsttable[bitreverse(word)]==0){
428
1.78M
    while((lo+1)<n && c->codelist[lo+1]<=word)lo++;
429
1.85M
    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
277k
    {
435
277k
      unsigned long loval=lo;
436
277k
      unsigned long hival=n-hi;
437
      
438
277k
      if(loval>0x7fff)loval=0x7fff;
439
277k
      if(hival>0x7fff)hival=0x7fff;
440
277k
      c->dec_firsttable[bitreverse(word)]=
441
277k
        0x80000000UL | (loval<<15) | hival;
442
277k
    }
443
277k
  }
444
473k
      }
445
11.9k
    }
446
11.9k
  }
447
448
12.3k
  return(0);
449
109
 err_out:
450
109
  vorbis_book_clear(c);
451
109
  return(-1);
452
12.4k
}
453