Coverage Report

Created: 2024-07-27 06:11

/src/tremor/codebook.c
Line
Count
Source (jump to first uncovered line)
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 codebook pack/unpack/code/decode operations
15
16
 ********************************************************************/
17
18
#include <stdlib.h>
19
#include <string.h>
20
#include <math.h>
21
#include <ogg/ogg.h>
22
#include "ivorbiscodec.h"
23
#include "codebook.h"
24
#include "misc.h"
25
26
/* unpacks a codebook from the packet buffer into the codebook struct,
27
   readies the codebook auxiliary structures for decode *************/
28
16.6k
static_codebook *vorbis_staticbook_unpack(oggpack_buffer *opb){
29
16.6k
  long i,j;
30
16.6k
  static_codebook *s=_ogg_calloc(1,sizeof(*s));
31
32
  /* make sure alignment is correct */
33
16.6k
  if(oggpack_read(opb,24)!=0x564342)goto _eofout;
34
35
  /* first the basic parameters */
36
16.5k
  s->dim=oggpack_read(opb,16);
37
16.5k
  s->entries=oggpack_read(opb,24);
38
16.5k
  if(s->entries==-1)goto _eofout;
39
40
16.5k
  if(_ilog(s->dim)+_ilog(s->entries)>24)goto _eofout;
41
42
  /* codeword ordering.... length ordered or unordered? */
43
16.5k
  switch((int)oggpack_read(opb,1)){
44
13.9k
  case 0:{
45
13.9k
    long unused;
46
    /* allocated but unused entries? */
47
13.9k
    unused=oggpack_read(opb,1);
48
13.9k
    if((s->entries*(unused?1:5)+7)>>3>opb->storage-oggpack_bytes(opb))
49
50
      goto _eofout;
50
    /* unordered */
51
13.9k
    s->lengthlist=(long *)_ogg_malloc(sizeof(*s->lengthlist)*s->entries);
52
53
    /* allocated but unused entries? */
54
13.9k
    if(unused){
55
      /* yes, unused entries */
56
57
837k
      for(i=0;i<s->entries;i++){
58
826k
  if(oggpack_read(opb,1)){
59
323k
    long num=oggpack_read(opb,5);
60
323k
    if(num==-1)goto _eofout;
61
323k
    s->lengthlist[i]=num+1;
62
323k
  }else
63
502k
    s->lengthlist[i]=0;
64
826k
      }
65
11.8k
    }else{
66
      /* all entries used; no tagging */
67
334k
      for(i=0;i<s->entries;i++){
68
332k
  long num=oggpack_read(opb,5);
69
332k
  if(num==-1)goto _eofout;
70
332k
  s->lengthlist[i]=num+1;
71
332k
      }
72
2.10k
    }
73
    
74
13.8k
    break;
75
13.9k
  }
76
13.8k
  case 1:
77
    /* ordered */
78
2.54k
    {
79
2.54k
      long length=oggpack_read(opb,5)+1;
80
2.54k
      if(length==0)goto _eofout;
81
2.54k
      s->lengthlist=(long *)_ogg_malloc(sizeof(*s->lengthlist)*s->entries);
82
83
7.43k
      for(i=0;i<s->entries;){
84
4.99k
  long num=oggpack_read(opb,_ilog(s->entries-i));
85
4.99k
  if(num==-1)goto _eofout;
86
4.95k
  if(length>32 || num>s->entries-i ||
87
4.95k
     (num>0 && (num-1)>>(length>>1)>>((length+1)>>1))>0){
88
63
    goto _errout;
89
63
  }
90
138M
  for(j=0;j<num;j++,i++)
91
138M
    s->lengthlist[i]=length;
92
4.89k
  length++;
93
4.89k
      }
94
2.54k
    }
95
2.44k
    break;
96
2.44k
  default:
97
    /* EOF */
98
15
    goto _eofout;
99
16.5k
  }
100
  
101
  /* Do we have a mapping to unpack? */
102
16.3k
  switch((s->maptype=oggpack_read(opb,4))){
103
8.85k
  case 0:
104
    /* no mapping */
105
8.85k
    break;
106
7.45k
  case 1: case 2:
107
    /* implicitly populated value mapping */
108
    /* explicitly populated value mapping */
109
110
7.45k
    s->q_min=oggpack_read(opb,32);
111
7.45k
    s->q_delta=oggpack_read(opb,32);
112
7.45k
    s->q_quant=oggpack_read(opb,4)+1;
113
7.45k
    s->q_sequencep=oggpack_read(opb,1);
114
7.45k
    if(s->q_sequencep==-1)goto _eofout;
115
116
7.43k
    {
117
7.43k
      int quantvals=0;
118
7.43k
      switch(s->maptype){
119
5.16k
      case 1:
120
5.16k
  quantvals=(s->dim==0?0:_book_maptype1_quantvals(s));
121
5.16k
  break;
122
2.27k
      case 2:
123
2.27k
  quantvals=s->entries*s->dim;
124
2.27k
  break;
125
7.43k
      }
126
      
127
      /* quantized values */
128
7.43k
      if((quantvals*s->q_quant+7)>>3>opb->storage-oggpack_bytes(opb))
129
161
        goto _eofout;
130
7.27k
      s->quantlist=(long *)_ogg_malloc(sizeof(*s->quantlist)*quantvals);
131
112k
      for(i=0;i<quantvals;i++)
132
105k
  s->quantlist[i]=oggpack_read(opb,s->q_quant);
133
      
134
7.27k
      if(quantvals&&s->quantlist[quantvals-1]==-1)goto _eofout;
135
7.27k
    }
136
7.27k
    break;
137
7.27k
  default:
138
25
    goto _errout;
139
16.3k
  }
140
141
  /* all set */
142
16.1k
  return(s);
143
  
144
88
 _errout:
145
548
 _eofout:
146
548
  vorbis_staticbook_destroy(s);
147
548
  return(NULL); 
148
88
}
149
150
/* the 'eliminate the decode tree' optimization actually requires the
151
   codewords to be MSb first, not LSb.  This is an annoying inelegancy
152
   (and one of the first places where carefully thought out design
153
   turned out to be wrong; Vorbis II and future Ogg codecs should go
154
   to an MSb bitpacker), but not actually the huge hit it appears to
155
   be.  The first-stage decode table catches most words so that
156
   bitreverse is not in the main execution path. */
157
158
78.4k
static ogg_uint32_t bitreverse(ogg_uint32_t x){
159
78.4k
  x=    ((x>>16)&0x0000ffff) | ((x<<16)&0xffff0000);
160
78.4k
  x=    ((x>> 8)&0x00ff00ff) | ((x<< 8)&0xff00ff00);
161
78.4k
  x=    ((x>> 4)&0x0f0f0f0f) | ((x<< 4)&0xf0f0f0f0);
162
78.4k
  x=    ((x>> 2)&0x33333333) | ((x<< 2)&0xcccccccc);
163
78.4k
  return((x>> 1)&0x55555555) | ((x<< 1)&0xaaaaaaaa);
164
78.4k
}
165
166
STIN long decode_packed_entry_number(codebook *book, 
167
166k
                oggpack_buffer *b){
168
166k
  int  read=book->dec_maxlength;
169
166k
  long lo,hi;
170
166k
  long lok = oggpack_look(b,book->dec_firsttablen);
171
 
172
166k
  if (lok >= 0) {
173
154k
    long entry = book->dec_firsttable[lok];
174
154k
    if(entry&0x80000000UL){
175
70.2k
      lo=(entry>>15)&0x7fff;
176
70.2k
      hi=book->used_entries-(entry&0x7fff);
177
84.2k
    }else{
178
84.2k
      oggpack_adv(b, book->dec_codelengths[entry-1]);
179
84.2k
      return(entry-1);
180
84.2k
    }
181
154k
  }else{
182
12.2k
    lo=0;
183
12.2k
    hi=book->used_entries;
184
12.2k
  }
185
186
82.4k
  lok = oggpack_look(b, read);
187
188
101k
  while(lok<0 && read>1)
189
19.1k
    lok = oggpack_look(b, --read);
190
191
82.4k
  if(lok<0){
192
4.04k
    oggpack_adv(b,1); /* force eop */
193
4.04k
    return -1;
194
4.04k
  }
195
196
  /* bisect search for the codeword in the ordered list */
197
78.4k
  {
198
78.4k
    ogg_uint32_t testword=bitreverse((ogg_uint32_t)lok);
199
200
102k
    while(hi-lo>1){
201
23.5k
      long p=(hi-lo)>>1;
202
23.5k
      long test=book->codelist[lo+p]>testword;    
203
23.5k
      lo+=p&(test-1);
204
23.5k
      hi-=p&(-test);
205
23.5k
    }
206
207
78.4k
    if(book->dec_codelengths[lo]<=read){
208
77.2k
      oggpack_adv(b, book->dec_codelengths[lo]);
209
77.2k
      return(lo);
210
77.2k
    }
211
78.4k
  }
212
  
213
1.20k
  oggpack_adv(b, read+1);
214
1.20k
  return(-1);
215
78.4k
}
216
217
/* Decode side is specced and easier, because we don't need to find
218
   matches using different criteria; we simply read and map.  There are
219
   two things we need to do 'depending':
220
   
221
   We may need to support interleave.  We don't really, but it's
222
   convenient to do it here rather than rebuild the vector later.
223
224
   Cascades may be additive or multiplicitive; this is not inherent in
225
   the codebook, but set in the code using the codebook.  Like
226
   interleaving, it's easiest to do it here.  
227
   addmul==0 -> declarative (set the value)
228
   addmul==1 -> additive
229
   addmul==2 -> multiplicitive */
230
231
/* returns the [original, not compacted] entry number or -1 on eof *********/
232
60.6k
long vorbis_book_decode(codebook *book, oggpack_buffer *b){
233
60.6k
  if(book->used_entries>0){
234
60.3k
    long packed_entry=decode_packed_entry_number(book,b);
235
60.3k
    if(packed_entry>=0)
236
57.9k
      return(book->dec_index[packed_entry]);
237
60.3k
  }
238
239
  /* if there's no dec_index, the codebook unpacking isn't collapsed */
240
2.75k
  return(-1);
241
60.6k
}
242
243
/* returns 0 on OK or -1 on eof *************************************/
244
/* decode vector / dim granularity gaurding is done in the upper layer */
245
long vorbis_book_decodevs_add(codebook *book,ogg_int32_t *a,
246
50.1k
            oggpack_buffer *b,int n,int point){
247
50.1k
  if(book->used_entries>0){  
248
49.8k
    int step=n/book->dim;
249
49.8k
    long *entry = (long *)alloca(sizeof(*entry)*step);
250
49.8k
    ogg_int32_t **t = (ogg_int32_t **)alloca(sizeof(*t)*step);
251
49.8k
    int i,j,o;
252
49.8k
    int shift=point-book->binarypoint;
253
    
254
49.8k
    if(shift>=0){
255
32.7k
      for (i = 0; i < step; i++) {
256
12.5k
  entry[i]=decode_packed_entry_number(book,b);
257
12.5k
  if(entry[i]==-1)return(-1);
258
12.2k
  t[i] = book->valuelist+entry[i]*book->dim;
259
12.2k
      }
260
714M
      for(i=0,o=0;i<book->dim;i++,o+=step)
261
714M
  for (j=0;o+j<n && j<step;j++)
262
242k
    a[o+j]+=t[j][i]>>shift;
263
29.3k
    }else{
264
40.9k
      for (i = 0; i < step; i++) {
265
11.8k
  entry[i]=decode_packed_entry_number(book,b);
266
11.8k
  if(entry[i]==-1)return(-1);
267
11.5k
  t[i] = book->valuelist+entry[i]*book->dim;
268
11.5k
      }
269
760M
      for(i=0,o=0;i<book->dim;i++,o+=step)
270
760M
  for (j=0;o+j<n && j<step;j++)
271
46.3k
    a[o+j]+=t[j][i]<<-shift;
272
29.1k
    }
273
49.8k
  }
274
49.6k
  return(0);
275
50.1k
}
276
277
/* decode vector / dim granularity gaurding is done in the upper layer */
278
long vorbis_book_decodev_add(codebook *book,ogg_int32_t *a,
279
1.75k
           oggpack_buffer *b,int n,int point){
280
1.75k
  if(book->used_entries>0){
281
1.54k
    int i,j,entry;
282
1.54k
    ogg_int32_t *t;
283
1.54k
    int shift=point-book->binarypoint;
284
    
285
1.54k
    if(shift>=0){
286
3.89k
      for(i=0;i<n;){
287
3.32k
  entry = decode_packed_entry_number(book,b);
288
3.32k
  if(entry==-1)return(-1);
289
3.05k
  t     = book->valuelist+entry*book->dim;
290
102k
  for (j=0;i<n && j<book->dim;)
291
99.6k
    a[i++]+=t[j++]>>shift;
292
3.05k
      }
293
836
    }else{
294
2.79k
      for(i=0;i<n;){
295
2.34k
  entry = decode_packed_entry_number(book,b);
296
2.34k
  if(entry==-1)return(-1);
297
2.08k
  t     = book->valuelist+entry*book->dim;
298
108k
  for (j=0;i<n && j<book->dim;)
299
106k
    a[i++]+=t[j++]<<-shift;
300
2.08k
      }
301
711
    }
302
1.54k
  }
303
1.21k
  return(0);
304
1.75k
}
305
306
/* unlike the others, we guard against n not being an integer number
307
   of <dim> internally rather than in the upper layer (called only by
308
   floor0) */
309
long vorbis_book_decodev_set(codebook *book,ogg_int32_t *a,
310
9.65k
           oggpack_buffer *b,int n,int point){
311
9.65k
  if(book->used_entries>0){
312
8.85k
    int i,j,entry;
313
8.85k
    ogg_int32_t *t;
314
8.85k
    int shift=point-book->binarypoint;
315
    
316
8.85k
    if(shift>=0){
317
      
318
20.0k
      for(i=0;i<n;){
319
15.9k
  entry = decode_packed_entry_number(book,b);
320
15.9k
  if(entry==-1)return(-1);
321
15.2k
  t     = book->valuelist+entry*book->dim;
322
538k
  for (j=0;i<n && j<book->dim;){
323
523k
    a[i++]=t[j++]>>shift;
324
523k
  }
325
15.2k
      }
326
4.76k
    }else{
327
      
328
14.2k
      for(i=0;i<n;){
329
10.5k
  entry = decode_packed_entry_number(book,b);
330
10.5k
  if(entry==-1)return(-1);
331
10.1k
  t     = book->valuelist+entry*book->dim;
332
295k
  for (j=0;i<n && j<book->dim;){
333
285k
    a[i++]=t[j++]<<-shift;
334
285k
  }
335
10.1k
      }
336
4.08k
    }
337
8.85k
  }else{
338
339
807
    int i,j;
340
93.5k
    for(i=0;i<n;){
341
92.7k
      a[i++]=0;
342
92.7k
    }
343
807
  }
344
8.59k
  return(0);
345
9.65k
}
346
347
/* decode vector / dim granularity gaurding is done in the upper layer */
348
long vorbis_book_decodevv_add(codebook *book,ogg_int32_t **a,\
349
            long offset,int ch,
350
193k
            oggpack_buffer *b,int n,int point){
351
193k
  if(book->used_entries>0){
352
193k
    long i,j,entry;
353
193k
    int chptr=0;
354
193k
    int shift=point-book->binarypoint;
355
193k
    int m=offset+n;
356
193k
    if(shift>=0){
357
      
358
22.0k
      for(i=offset;i<m;){
359
10.7k
  entry = decode_packed_entry_number(book,b);
360
10.7k
  if(entry==-1)return(-1);
361
10.4k
  {
362
10.4k
    const ogg_int32_t *t = book->valuelist+entry*book->dim;
363
850k
    for (j=0;i<m && j<book->dim;j++){
364
840k
      a[chptr++][i]+=t[j]>>shift;
365
840k
      if(chptr==ch){
366
67.5k
        chptr=0;
367
67.5k
        i++;
368
67.5k
      }
369
840k
    }
370
10.4k
  }
371
10.4k
      }
372
181k
    }else{
373
      
374
220k
      for(i=offset;i<m;){
375
39.1k
  entry = decode_packed_entry_number(book,b);
376
39.1k
  if(entry==-1)return(-1);
377
38.7k
  {
378
38.7k
    const ogg_int32_t *t = book->valuelist+entry*book->dim;
379
1.36M
    for (j=0;i<m && j<book->dim;j++){
380
1.32M
      a[chptr++][i]+=t[j]<<-shift;
381
1.32M
      if(chptr==ch){
382
51.7k
        chptr=0;
383
51.7k
        i++;
384
51.7k
      }
385
1.32M
    }
386
38.7k
  }
387
38.7k
      }
388
181k
    }
389
193k
  }
390
192k
  return(0);
391
193k
}