Coverage Report

Created: 2025-11-16 06:17

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