Coverage Report

Created: 2025-07-12 06:03

/src/tremor/floor0.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: floor backend 0 implementation
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 "codec_internal.h"
24
#include "registry.h"
25
#include "codebook.h"
26
#include "misc.h"
27
#include "block.h"
28
29
82.8M
#define LSP_FRACBITS 14
30
31
typedef struct {
32
  long n;
33
  int ln;
34
  int  m;
35
  int *linearmap;
36
37
  vorbis_info_floor0 *vi;
38
  ogg_int32_t *lsp_look;
39
40
} vorbis_look_floor0;
41
42
/*************** LSP decode ********************/
43
44
#include "lsp_lookup.h"
45
46
/* interpolated 1./sqrt(p) where .5 <= a < 1. (.100000... to .111111...) in
47
   16.16 format 
48
   returns in m.8 format */
49
50
static long ADJUST_SQRT2[2]={8192,5792};
51
2.69M
STIN ogg_int32_t vorbis_invsqlook_i(long a,long e){
52
2.69M
  long i=(a&0x7fff)>>(INVSQ_LOOKUP_I_SHIFT-1); 
53
2.69M
  long d=a&INVSQ_LOOKUP_I_MASK;                              /*  0.10 */
54
2.69M
  long val=INVSQ_LOOKUP_I[i]-                                /*  1.16 */
55
2.69M
    ((INVSQ_LOOKUP_IDel[i]*d)>>INVSQ_LOOKUP_I_SHIFT);        /* result 1.16 */
56
2.69M
  val*=ADJUST_SQRT2[e&1];
57
2.69M
  e=(e>>1)+21;
58
2.69M
  return(val>>e);
59
2.69M
}
60
61
/* interpolated lookup based fromdB function, domain -140dB to 0dB only */
62
/* a is in n.12 format */
63
2.69M
STIN ogg_int32_t vorbis_fromdBlook_i(long a){
64
2.69M
  int i=(-a)>>(12-FROMdB2_SHIFT);
65
2.69M
  if(i<0) return 0x7fffffff;
66
2.12M
  if(i>=(FROMdB_LOOKUP_SZ<<FROMdB_SHIFT))return 0;
67
  
68
1.85M
  return FROMdB_LOOKUP[i>>FROMdB_SHIFT] * FROMdB2_LOOKUP[i&FROMdB2_MASK];
69
2.12M
}
70
71
/* interpolated lookup based cos function, domain 0 to PI only */
72
/* a is in 0.16 format, where 0==0, 2^^16-1==PI, return 0.14 */
73
584k
STIN ogg_int32_t vorbis_coslook_i(long a){
74
584k
  int i=a>>COS_LOOKUP_I_SHIFT;
75
584k
  int d=a&COS_LOOKUP_I_MASK;
76
584k
  return COS_LOOKUP_I[i]- ((d*(COS_LOOKUP_I[i]-COS_LOOKUP_I[i+1]))>>
77
584k
         COS_LOOKUP_I_SHIFT);
78
584k
}
79
80
/* interpolated lookup based cos function */
81
/* a is in 0.16 format, where 0==0, 2^^16==PI, return .LSP_FRACBITS */
82
82.8M
STIN ogg_int32_t vorbis_coslook2_i(long a){
83
82.8M
  a=a&0x1ffff;
84
85
82.8M
  if(a>0x10000)a=0x20000-a;
86
82.8M
  {               
87
82.8M
    int i=a>>COS_LOOKUP_I_SHIFT;
88
82.8M
    int d=a&COS_LOOKUP_I_MASK;
89
82.8M
    a=((COS_LOOKUP_I[i]<<COS_LOOKUP_I_SHIFT)-
90
82.8M
       d*(COS_LOOKUP_I[i]-COS_LOOKUP_I[i+1]))>>
91
82.8M
      (COS_LOOKUP_I_SHIFT-LSP_FRACBITS+14);
92
82.8M
  }
93
  
94
82.8M
  return(a);
95
82.8M
}
96
97
static const int barklook[28]={
98
  0,100,200,301,          405,516,635,766,
99
  912,1077,1263,1476,     1720,2003,2333,2721,
100
  3184,3742,4428,5285,    6376,7791,9662,12181,
101
  15624,20397,27087,36554
102
};
103
104
/* used in init only; interpolate the long way */
105
3.85M
STIN ogg_int32_t toBARK(int n){
106
3.85M
  int i;
107
75.8M
  for(i=0;i<27;i++) 
108
75.8M
    if(n>=barklook[i] && n<barklook[i+1])break;
109
  
110
3.85M
  if(i==27){
111
0
    return 27<<15;
112
3.85M
  }else{
113
3.85M
    int gap=barklook[i+1]-barklook[i];
114
3.85M
    int del=n-barklook[i];
115
116
3.85M
    return((i<<15)+((del<<15)/gap));
117
3.85M
  }
118
3.85M
}
119
120
static const unsigned char MLOOP_1[64]={
121
   0,10,11,11, 12,12,12,12, 13,13,13,13, 13,13,13,13,
122
  14,14,14,14, 14,14,14,14, 14,14,14,14, 14,14,14,14,
123
  15,15,15,15, 15,15,15,15, 15,15,15,15, 15,15,15,15,
124
  15,15,15,15, 15,15,15,15, 15,15,15,15, 15,15,15,15,
125
};
126
127
static const unsigned char MLOOP_2[64]={
128
  0,4,5,5, 6,6,6,6, 7,7,7,7, 7,7,7,7,
129
  8,8,8,8, 8,8,8,8, 8,8,8,8, 8,8,8,8,
130
  9,9,9,9, 9,9,9,9, 9,9,9,9, 9,9,9,9,
131
  9,9,9,9, 9,9,9,9, 9,9,9,9, 9,9,9,9,
132
};
133
134
static const unsigned char MLOOP_3[8]={0,1,2,2,3,3,3,3};
135
136
void vorbis_lsp_to_curve(ogg_int32_t *curve,int *map,int n,int ln,
137
       ogg_int32_t *lsp,int m,
138
       ogg_int32_t amp,
139
       ogg_int32_t ampoffset,
140
11.6k
       ogg_int32_t *icos){
141
142
  /* 0 <= m < 256 */
143
144
  /* set up for using all int later */
145
11.6k
  int i;
146
11.6k
  int ampoffseti=ampoffset*4096;
147
11.6k
  int ampi=amp;
148
11.6k
  ogg_int32_t *ilsp=(ogg_int32_t *)alloca(m*sizeof(*ilsp));
149
  /* lsp is in 8.24, range 0 to PI; coslook wants it in .16 0 to 1*/
150
596k
  for(i=0;i<m;i++){
151
590k
#ifndef _LOW_ACCURACY_
152
590k
    ogg_int32_t val=MULT32(lsp[i],0x517cc2);
153
#else
154
    ogg_int32_t val=((lsp[i]>>10)*0x517d)>>14;
155
#endif
156
157
    /* safeguard against a malicious stream */
158
590k
    if(val<0 || (val>>COS_LOOKUP_I_SHIFT)>=COS_LOOKUP_I_SZ){
159
5.24k
      memset(curve,0,sizeof(*curve)*n);
160
5.24k
      return;
161
5.24k
    }
162
163
584k
    ilsp[i]=vorbis_coslook_i(val);
164
584k
  }
165
166
6.45k
  i=0;
167
2.70M
  while(i<n){
168
2.69M
    int j,k=map[i];
169
2.69M
    ogg_uint32_t pi=46341; /* 2**-.5 in 0.16 */
170
2.69M
    ogg_uint32_t qi=46341;
171
2.69M
    ogg_int32_t qexp=0,shift;
172
2.69M
    ogg_int32_t wi=icos[k];
173
174
#ifdef _V_LSP_MATH_ASM
175
    lsp_loop_asm(&qi,&pi,&qexp,ilsp,wi,m);
176
177
    pi=((pi*pi)>>16);
178
    qi=((qi*qi)>>16);
179
    
180
    if(m&1){
181
      qexp= qexp*2-28*((m+1)>>1)+m;      
182
      pi*=(1<<14)-((wi*wi)>>14);
183
      qi+=pi>>14;     
184
    }else{
185
      qexp= qexp*2-13*m;
186
      
187
      pi*=(1<<14)-wi;
188
      qi*=(1<<14)+wi;
189
      
190
      qi=(qi+pi)>>14;
191
    }
192
    
193
    if(qi&0xffff0000){ /* checks for 1.xxxxxxxxxxxxxxxx */
194
      qi>>=1; qexp++; 
195
    }else
196
      lsp_norm_asm(&qi,&qexp);
197
198
#else
199
200
2.69M
    j=1;
201
2.69M
    if(m>1){
202
2.63M
      qi*=labs(ilsp[0]-wi);
203
2.63M
      pi*=labs(ilsp[1]-wi);
204
205
119M
      for(j+=2;j<m;j+=2){
206
116M
        if(!(shift=MLOOP_1[(pi|qi)>>25]))
207
4.63M
          if(!(shift=MLOOP_2[(pi|qi)>>19]))
208
576k
            shift=MLOOP_3[(pi|qi)>>16];
209
116M
        qi=(qi>>shift)*labs(ilsp[j-1]-wi);
210
116M
        pi=(pi>>shift)*labs(ilsp[j]-wi);
211
116M
        qexp+=shift;
212
116M
      }
213
2.63M
    }
214
2.69M
    if(!(shift=MLOOP_1[(pi|qi)>>25]))
215
163k
      if(!(shift=MLOOP_2[(pi|qi)>>19]))
216
72.9k
  shift=MLOOP_3[(pi|qi)>>16];
217
218
    /* pi,qi normalized collectively, both tracked using qexp */
219
220
2.69M
    if(m&1){
221
      /* odd order filter; slightly assymetric */
222
      /* the last coefficient */
223
2.18M
      qi=(qi>>shift)*labs(ilsp[j-1]-wi);
224
2.18M
      pi=(pi>>shift)<<14;
225
2.18M
      qexp+=shift;
226
227
2.18M
      if(!(shift=MLOOP_1[(pi|qi)>>25]))
228
7.73k
  if(!(shift=MLOOP_2[(pi|qi)>>19]))
229
2.26k
    shift=MLOOP_3[(pi|qi)>>16];
230
      
231
2.18M
      pi>>=shift;
232
2.18M
      qi>>=shift;
233
2.18M
      qexp+=shift-14*((m+1)>>1);
234
235
2.18M
      pi=((pi*pi)>>16);
236
2.18M
      qi=((qi*qi)>>16);
237
2.18M
      qexp=qexp*2+m;
238
239
2.18M
      pi*=(1<<14)-((wi*wi)>>14);
240
2.18M
      qi+=pi>>14;
241
242
2.18M
    }else{
243
      /* even order filter; still symmetric */
244
245
      /* p*=p(1-w), q*=q(1+w), let normalization drift because it isn't
246
   worth tracking step by step */
247
      
248
505k
      pi>>=shift;
249
505k
      qi>>=shift;
250
505k
      qexp+=shift-7*m;
251
252
505k
      pi=((pi*pi)>>16);
253
505k
      qi=((qi*qi)>>16);
254
505k
      qexp=qexp*2+m;
255
      
256
505k
      pi*=(1<<14)-wi;
257
505k
      qi*=(1<<14)+wi;
258
505k
      qi=(qi+pi)>>14;
259
      
260
505k
    }
261
    
262
263
    /* we've let the normalization drift because it wasn't important;
264
       however, for the lookup, things must be normalized again.  We
265
       need at most one right shift or a number of left shifts */
266
267
2.69M
    if(qi&0xffff0000){ /* checks for 1.xxxxxxxxxxxxxxxx */
268
506k
      qi>>=1; qexp++; 
269
506k
    }else
270
3.87M
      while(qi && !(qi&0x8000)){ /* checks for 0.0xxxxxxxxxxxxxxx or less*/
271
1.68M
  qi<<=1; qexp--; 
272
1.68M
      }
273
274
2.69M
#endif
275
276
2.69M
    amp=vorbis_fromdBlook_i(ampi*                     /*  n.4         */
277
2.69M
          vorbis_invsqlook_i(qi,qexp)- 
278
                                    /*  m.8, m+n<=8 */
279
2.69M
          ampoffseti);              /*  8.12[0]     */
280
    
281
#ifdef _LOW_ACCURACY_
282
    amp>>=9;
283
#endif
284
2.69M
    curve[i]= MULT31_SHIFT15(curve[i],amp);
285
6.57M
    while(map[++i]==k) curve[i]= MULT31_SHIFT15(curve[i],amp);
286
2.69M
  }
287
6.45k
}
288
289
/*************** vorbis decode glue ************/
290
291
1.79k
static void floor0_free_info(vorbis_info_floor *i){
292
1.79k
  vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
293
1.79k
  if(info){
294
1.79k
    memset(info,0,sizeof(*info));
295
1.79k
    _ogg_free(info);
296
1.79k
  }
297
1.79k
}
298
299
2.80k
static void floor0_free_look(vorbis_look_floor *i){
300
2.80k
  vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
301
2.80k
  if(look){
302
303
2.80k
    if(look->linearmap)_ogg_free(look->linearmap);
304
2.80k
    if(look->lsp_look)_ogg_free(look->lsp_look);
305
2.80k
    memset(look,0,sizeof(*look));
306
2.80k
    _ogg_free(look);
307
2.80k
  }
308
2.80k
}
309
310
1.79k
static vorbis_info_floor *floor0_unpack (vorbis_info *vi,oggpack_buffer *opb){
311
1.79k
  codec_setup_info     *ci=(codec_setup_info *)vi->codec_setup;
312
1.79k
  int j;
313
314
1.79k
  vorbis_info_floor0 *info=(vorbis_info_floor0 *)_ogg_malloc(sizeof(*info));
315
1.79k
  info->order=oggpack_read(opb,8);
316
1.79k
  info->rate=oggpack_read(opb,16);
317
1.79k
  info->barkmap=oggpack_read(opb,16);
318
1.79k
  info->ampbits=oggpack_read(opb,6);
319
1.79k
  info->ampdB=oggpack_read(opb,8);
320
1.79k
  info->numbooks=oggpack_read(opb,4)+1;
321
  
322
1.79k
  if(info->order<1)goto err_out;
323
1.78k
  if(info->rate<1)goto err_out;
324
1.78k
  if(info->barkmap<1)goto err_out;
325
1.77k
  if(info->numbooks<1)goto err_out;
326
    
327
4.34k
  for(j=0;j<info->numbooks;j++){
328
2.60k
    info->books[j]=oggpack_read(opb,8);
329
2.60k
    if(info->books[j]<0 || info->books[j]>=ci->books)goto err_out;
330
2.58k
    if(ci->book_param[info->books[j]]->maptype==0)goto err_out;
331
2.58k
    if(ci->book_param[info->books[j]]->dim<1)goto err_out;
332
2.58k
  }
333
1.73k
  return(info);
334
335
57
 err_out:
336
57
  floor0_free_info(info);
337
57
  return(NULL);
338
1.75k
}
339
340
/* initialize Bark scale and normalization lookups.  We could do this
341
   with static tables, but Vorbis allows a number of possible
342
   combinations, so it's best to do it computationally.
343
344
   The below is authoritative in terms of defining scale mapping.
345
   Note that the scale depends on the sampling rate as well as the
346
   linear block and mapping sizes */
347
348
static vorbis_look_floor *floor0_look (vorbis_dsp_state *vd,vorbis_info_mode *mi,
349
2.80k
                              vorbis_info_floor *i){
350
2.80k
  int j;
351
2.80k
  vorbis_info        *vi=vd->vi;
352
2.80k
  codec_setup_info   *ci=(codec_setup_info *)vi->codec_setup;
353
2.80k
  vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
354
2.80k
  vorbis_look_floor0 *look=(vorbis_look_floor0 *)_ogg_calloc(1,sizeof(*look));
355
2.80k
  look->m=info->order;
356
2.80k
  look->n=ci->blocksizes[mi->blockflag]/2;
357
2.80k
  look->ln=info->barkmap;
358
2.80k
  look->vi=info;
359
360
  /* the mapping from a linear scale to a smaller bark scale is
361
     straightforward.  We do *not* make sure that the linear mapping
362
     does not skip bark-scale bins; the decoder simply skips them and
363
     the encoder may do what it wishes in filling them.  They're
364
     necessary in some mapping combinations to keep the scale spacing
365
     accurate */
366
2.80k
  look->linearmap=(int *)_ogg_malloc((look->n+1)*sizeof(*look->linearmap));
367
1.93M
  for(j=0;j<look->n;j++){
368
369
1.92M
    int val=(look->ln*
370
1.92M
       ((toBARK(info->rate/2*j/look->n)<<11)/toBARK(info->rate/2)))>>11;
371
372
1.92M
    if(val>=look->ln)val=look->ln-1; /* guard against the approximation */
373
1.92M
    look->linearmap[j]=val;
374
1.92M
  }
375
2.80k
  look->linearmap[j]=-1;
376
377
2.80k
  look->lsp_look=(ogg_int32_t *)_ogg_malloc(look->ln*sizeof(*look->lsp_look));
378
82.8M
  for(j=0;j<look->ln;j++)
379
82.8M
    look->lsp_look[j]=vorbis_coslook2_i(0x10000*j/look->ln);
380
381
2.80k
  return look;
382
2.80k
}
383
384
708k
static void *floor0_inverse1(vorbis_block *vb,vorbis_look_floor *i){
385
708k
  vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
386
708k
  vorbis_info_floor0 *info=look->vi;
387
708k
  int j,k;
388
  
389
708k
  int ampraw=oggpack_read(&vb->opb,info->ampbits);
390
708k
  if(ampraw>0){ /* also handles the -1 out of data case */
391
25.8k
    long maxval=(1<<info->ampbits)-1;
392
25.8k
    int amp=((ampraw*info->ampdB)<<4)/maxval;
393
25.8k
    int booknum=oggpack_read(&vb->opb,_ilog(info->numbooks));
394
    
395
25.8k
    if(booknum!=-1 && booknum<info->numbooks){ /* be paranoid */
396
12.9k
      codec_setup_info  *ci=(codec_setup_info *)vb->vd->vi->codec_setup;
397
12.9k
      codebook *b=ci->fullbooks+info->books[booknum];
398
12.9k
      ogg_int32_t last=0;
399
12.9k
      ogg_int32_t *lsp=(ogg_int32_t *)_vorbis_block_alloc(vb,sizeof(*lsp)*(look->m+1));
400
            
401
12.9k
      if(vorbis_book_decodev_set(b,lsp,&vb->opb,look->m,-24)==-1)goto eop;
402
221k
      for(j=0;j<look->m;){
403
1.42M
  for(k=0;j<look->m && k<b->dim;k++,j++)lsp[j]+=last;
404
209k
  last=lsp[j-1];
405
209k
      }
406
      
407
11.6k
      lsp[look->m]=amp;
408
11.6k
      return(lsp);
409
12.9k
    }
410
25.8k
  }
411
696k
 eop:
412
696k
  return(NULL);
413
708k
}
414
415
static int floor0_inverse2(vorbis_block *vb,vorbis_look_floor *i,
416
708k
         void *memo,ogg_int32_t *out){
417
708k
  vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
418
708k
  vorbis_info_floor0 *info=look->vi;
419
  
420
708k
  if(memo){
421
11.6k
    ogg_int32_t *lsp=(ogg_int32_t *)memo;
422
11.6k
    ogg_int32_t amp=lsp[look->m];
423
424
    /* take the coefficients back to a spectral envelope curve */
425
11.6k
    vorbis_lsp_to_curve(out,look->linearmap,look->n,look->ln,
426
11.6k
      lsp,look->m,amp,info->ampdB,look->lsp_look);
427
11.6k
    return(1);
428
11.6k
  }
429
696k
  memset(out,0,sizeof(*out)*look->n);
430
696k
  return(0);
431
708k
}
432
433
/* export hooks */
434
vorbis_func_floor floor0_exportbundle={
435
  &floor0_unpack,&floor0_look,&floor0_free_info,
436
  &floor0_free_look,&floor0_inverse1,&floor0_inverse2
437
};
438
439