Coverage Report

Created: 2025-07-23 06:18

/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
78.3M
#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.58M
STIN ogg_int32_t vorbis_invsqlook_i(long a,long e){
52
2.58M
  long i=(a&0x7fff)>>(INVSQ_LOOKUP_I_SHIFT-1); 
53
2.58M
  long d=a&INVSQ_LOOKUP_I_MASK;                              /*  0.10 */
54
2.58M
  long val=INVSQ_LOOKUP_I[i]-                                /*  1.16 */
55
2.58M
    ((INVSQ_LOOKUP_IDel[i]*d)>>INVSQ_LOOKUP_I_SHIFT);        /* result 1.16 */
56
2.58M
  val*=ADJUST_SQRT2[e&1];
57
2.58M
  e=(e>>1)+21;
58
2.58M
  return(val>>e);
59
2.58M
}
60
61
/* interpolated lookup based fromdB function, domain -140dB to 0dB only */
62
/* a is in n.12 format */
63
2.58M
STIN ogg_int32_t vorbis_fromdBlook_i(long a){
64
2.58M
  int i=(-a)>>(12-FROMdB2_SHIFT);
65
2.58M
  if(i<0) return 0x7fffffff;
66
1.94M
  if(i>=(FROMdB_LOOKUP_SZ<<FROMdB_SHIFT))return 0;
67
  
68
1.48M
  return FROMdB_LOOKUP[i>>FROMdB_SHIFT] * FROMdB2_LOOKUP[i&FROMdB2_MASK];
69
1.94M
}
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
314k
STIN ogg_int32_t vorbis_coslook_i(long a){
74
314k
  int i=a>>COS_LOOKUP_I_SHIFT;
75
314k
  int d=a&COS_LOOKUP_I_MASK;
76
314k
  return COS_LOOKUP_I[i]- ((d*(COS_LOOKUP_I[i]-COS_LOOKUP_I[i+1]))>>
77
314k
         COS_LOOKUP_I_SHIFT);
78
314k
}
79
80
/* interpolated lookup based cos function */
81
/* a is in 0.16 format, where 0==0, 2^^16==PI, return .LSP_FRACBITS */
82
78.3M
STIN ogg_int32_t vorbis_coslook2_i(long a){
83
78.3M
  a=a&0x1ffff;
84
85
78.3M
  if(a>0x10000)a=0x20000-a;
86
78.3M
  {               
87
78.3M
    int i=a>>COS_LOOKUP_I_SHIFT;
88
78.3M
    int d=a&COS_LOOKUP_I_MASK;
89
78.3M
    a=((COS_LOOKUP_I[i]<<COS_LOOKUP_I_SHIFT)-
90
78.3M
       d*(COS_LOOKUP_I[i]-COS_LOOKUP_I[i+1]))>>
91
78.3M
      (COS_LOOKUP_I_SHIFT-LSP_FRACBITS+14);
92
78.3M
  }
93
  
94
78.3M
  return(a);
95
78.3M
}
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
4.31M
STIN ogg_int32_t toBARK(int n){
106
4.31M
  int i;
107
82.1M
  for(i=0;i<27;i++) 
108
82.1M
    if(n>=barklook[i] && n<barklook[i+1])break;
109
  
110
4.31M
  if(i==27){
111
0
    return 27<<15;
112
4.31M
  }else{
113
4.31M
    int gap=barklook[i+1]-barklook[i];
114
4.31M
    int del=n-barklook[i];
115
116
4.31M
    return((i<<15)+((del<<15)/gap));
117
4.31M
  }
118
4.31M
}
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
8.50k
       ogg_int32_t *icos){
141
142
  /* 0 <= m < 256 */
143
144
  /* set up for using all int later */
145
8.50k
  int i;
146
8.50k
  int ampoffseti=ampoffset*4096;
147
8.50k
  int ampi=amp;
148
8.50k
  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
323k
  for(i=0;i<m;i++){
151
318k
#ifndef _LOW_ACCURACY_
152
318k
    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
318k
    if(val<0 || (val>>COS_LOOKUP_I_SHIFT)>=COS_LOOKUP_I_SZ){
159
4.38k
      memset(curve,0,sizeof(*curve)*n);
160
4.38k
      return;
161
4.38k
    }
162
163
314k
    ilsp[i]=vorbis_coslook_i(val);
164
314k
  }
165
166
4.11k
  i=0;
167
2.58M
  while(i<n){
168
2.58M
    int j,k=map[i];
169
2.58M
    ogg_uint32_t pi=46341; /* 2**-.5 in 0.16 */
170
2.58M
    ogg_uint32_t qi=46341;
171
2.58M
    ogg_int32_t qexp=0,shift;
172
2.58M
    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.58M
    j=1;
201
2.58M
    if(m>1){
202
2.50M
      qi*=labs(ilsp[0]-wi);
203
2.50M
      pi*=labs(ilsp[1]-wi);
204
205
123M
      for(j+=2;j<m;j+=2){
206
121M
        if(!(shift=MLOOP_1[(pi|qi)>>25]))
207
4.43M
          if(!(shift=MLOOP_2[(pi|qi)>>19]))
208
490k
            shift=MLOOP_3[(pi|qi)>>16];
209
121M
        qi=(qi>>shift)*labs(ilsp[j-1]-wi);
210
121M
        pi=(pi>>shift)*labs(ilsp[j]-wi);
211
121M
        qexp+=shift;
212
121M
      }
213
2.50M
    }
214
2.58M
    if(!(shift=MLOOP_1[(pi|qi)>>25]))
215
187k
      if(!(shift=MLOOP_2[(pi|qi)>>19]))
216
85.7k
  shift=MLOOP_3[(pi|qi)>>16];
217
218
    /* pi,qi normalized collectively, both tracked using qexp */
219
220
2.58M
    if(m&1){
221
      /* odd order filter; slightly assymetric */
222
      /* the last coefficient */
223
2.07M
      qi=(qi>>shift)*labs(ilsp[j-1]-wi);
224
2.07M
      pi=(pi>>shift)<<14;
225
2.07M
      qexp+=shift;
226
227
2.07M
      if(!(shift=MLOOP_1[(pi|qi)>>25]))
228
12.8k
  if(!(shift=MLOOP_2[(pi|qi)>>19]))
229
2.56k
    shift=MLOOP_3[(pi|qi)>>16];
230
      
231
2.07M
      pi>>=shift;
232
2.07M
      qi>>=shift;
233
2.07M
      qexp+=shift-14*((m+1)>>1);
234
235
2.07M
      pi=((pi*pi)>>16);
236
2.07M
      qi=((qi*qi)>>16);
237
2.07M
      qexp=qexp*2+m;
238
239
2.07M
      pi*=(1<<14)-((wi*wi)>>14);
240
2.07M
      qi+=pi>>14;
241
242
2.07M
    }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
507k
      pi>>=shift;
249
507k
      qi>>=shift;
250
507k
      qexp+=shift-7*m;
251
252
507k
      pi=((pi*pi)>>16);
253
507k
      qi=((qi*qi)>>16);
254
507k
      qexp=qexp*2+m;
255
      
256
507k
      pi*=(1<<14)-wi;
257
507k
      qi*=(1<<14)+wi;
258
507k
      qi=(qi+pi)>>14;
259
      
260
507k
    }
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.58M
    if(qi&0xffff0000){ /* checks for 1.xxxxxxxxxxxxxxxx */
268
483k
      qi>>=1; qexp++; 
269
483k
    }else
270
3.73M
      while(qi && !(qi&0x8000)){ /* checks for 0.0xxxxxxxxxxxxxxx or less*/
271
1.64M
  qi<<=1; qexp--; 
272
1.64M
      }
273
274
2.58M
#endif
275
276
2.58M
    amp=vorbis_fromdBlook_i(ampi*                     /*  n.4         */
277
2.58M
          vorbis_invsqlook_i(qi,qexp)- 
278
                                    /*  m.8, m+n<=8 */
279
2.58M
          ampoffseti);              /*  8.12[0]     */
280
    
281
#ifdef _LOW_ACCURACY_
282
    amp>>=9;
283
#endif
284
2.58M
    curve[i]= MULT31_SHIFT15(curve[i],amp);
285
6.13M
    while(map[++i]==k) curve[i]= MULT31_SHIFT15(curve[i],amp);
286
2.58M
  }
287
4.11k
}
288
289
/*************** vorbis decode glue ************/
290
291
1.95k
static void floor0_free_info(vorbis_info_floor *i){
292
1.95k
  vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
293
1.95k
  if(info){
294
1.95k
    memset(info,0,sizeof(*info));
295
1.95k
    _ogg_free(info);
296
1.95k
  }
297
1.95k
}
298
299
3.06k
static void floor0_free_look(vorbis_look_floor *i){
300
3.06k
  vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
301
3.06k
  if(look){
302
303
3.06k
    if(look->linearmap)_ogg_free(look->linearmap);
304
3.06k
    if(look->lsp_look)_ogg_free(look->lsp_look);
305
3.06k
    memset(look,0,sizeof(*look));
306
3.06k
    _ogg_free(look);
307
3.06k
  }
308
3.06k
}
309
310
1.95k
static vorbis_info_floor *floor0_unpack (vorbis_info *vi,oggpack_buffer *opb){
311
1.95k
  codec_setup_info     *ci=(codec_setup_info *)vi->codec_setup;
312
1.95k
  int j;
313
314
1.95k
  vorbis_info_floor0 *info=(vorbis_info_floor0 *)_ogg_malloc(sizeof(*info));
315
1.95k
  info->order=oggpack_read(opb,8);
316
1.95k
  info->rate=oggpack_read(opb,16);
317
1.95k
  info->barkmap=oggpack_read(opb,16);
318
1.95k
  info->ampbits=oggpack_read(opb,6);
319
1.95k
  info->ampdB=oggpack_read(opb,8);
320
1.95k
  info->numbooks=oggpack_read(opb,4)+1;
321
  
322
1.95k
  if(info->order<1)goto err_out;
323
1.94k
  if(info->rate<1)goto err_out;
324
1.94k
  if(info->barkmap<1)goto err_out;
325
1.93k
  if(info->numbooks<1)goto err_out;
326
    
327
4.69k
  for(j=0;j<info->numbooks;j++){
328
2.81k
    info->books[j]=oggpack_read(opb,8);
329
2.81k
    if(info->books[j]<0 || info->books[j]>=ci->books)goto err_out;
330
2.78k
    if(ci->book_param[info->books[j]]->maptype==0)goto err_out;
331
2.78k
    if(ci->book_param[info->books[j]]->dim<1)goto err_out;
332
2.78k
  }
333
1.87k
  return(info);
334
335
80
 err_out:
336
80
  floor0_free_info(info);
337
80
  return(NULL);
338
1.91k
}
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
3.06k
                              vorbis_info_floor *i){
350
3.06k
  int j;
351
3.06k
  vorbis_info        *vi=vd->vi;
352
3.06k
  codec_setup_info   *ci=(codec_setup_info *)vi->codec_setup;
353
3.06k
  vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
354
3.06k
  vorbis_look_floor0 *look=(vorbis_look_floor0 *)_ogg_calloc(1,sizeof(*look));
355
3.06k
  look->m=info->order;
356
3.06k
  look->n=ci->blocksizes[mi->blockflag]/2;
357
3.06k
  look->ln=info->barkmap;
358
3.06k
  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
3.06k
  look->linearmap=(int *)_ogg_malloc((look->n+1)*sizeof(*look->linearmap));
367
2.15M
  for(j=0;j<look->n;j++){
368
369
2.15M
    int val=(look->ln*
370
2.15M
       ((toBARK(info->rate/2*j/look->n)<<11)/toBARK(info->rate/2)))>>11;
371
372
2.15M
    if(val>=look->ln)val=look->ln-1; /* guard against the approximation */
373
2.15M
    look->linearmap[j]=val;
374
2.15M
  }
375
3.06k
  look->linearmap[j]=-1;
376
377
3.06k
  look->lsp_look=(ogg_int32_t *)_ogg_malloc(look->ln*sizeof(*look->lsp_look));
378
78.3M
  for(j=0;j<look->ln;j++)
379
78.3M
    look->lsp_look[j]=vorbis_coslook2_i(0x10000*j/look->ln);
380
381
3.06k
  return look;
382
3.06k
}
383
384
556k
static void *floor0_inverse1(vorbis_block *vb,vorbis_look_floor *i){
385
556k
  vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
386
556k
  vorbis_info_floor0 *info=look->vi;
387
556k
  int j,k;
388
  
389
556k
  int ampraw=oggpack_read(&vb->opb,info->ampbits);
390
556k
  if(ampraw>0){ /* also handles the -1 out of data case */
391
17.2k
    long maxval=(1<<info->ampbits)-1;
392
17.2k
    int amp=((ampraw*info->ampdB)<<4)/maxval;
393
17.2k
    int booknum=oggpack_read(&vb->opb,_ilog(info->numbooks));
394
    
395
17.2k
    if(booknum!=-1 && booknum<info->numbooks){ /* be paranoid */
396
9.55k
      codec_setup_info  *ci=(codec_setup_info *)vb->vd->vi->codec_setup;
397
9.55k
      codebook *b=ci->fullbooks+info->books[booknum];
398
9.55k
      ogg_int32_t last=0;
399
9.55k
      ogg_int32_t *lsp=(ogg_int32_t *)_vorbis_block_alloc(vb,sizeof(*lsp)*(look->m+1));
400
            
401
9.55k
      if(vorbis_book_decodev_set(b,lsp,&vb->opb,look->m,-24)==-1)goto eop;
402
126k
      for(j=0;j<look->m;){
403
798k
  for(k=0;j<look->m && k<b->dim;k++,j++)lsp[j]+=last;
404
118k
  last=lsp[j-1];
405
118k
      }
406
      
407
8.50k
      lsp[look->m]=amp;
408
8.50k
      return(lsp);
409
9.55k
    }
410
17.2k
  }
411
547k
 eop:
412
547k
  return(NULL);
413
556k
}
414
415
static int floor0_inverse2(vorbis_block *vb,vorbis_look_floor *i,
416
556k
         void *memo,ogg_int32_t *out){
417
556k
  vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
418
556k
  vorbis_info_floor0 *info=look->vi;
419
  
420
556k
  if(memo){
421
8.50k
    ogg_int32_t *lsp=(ogg_int32_t *)memo;
422
8.50k
    ogg_int32_t amp=lsp[look->m];
423
424
    /* take the coefficients back to a spectral envelope curve */
425
8.50k
    vorbis_lsp_to_curve(out,look->linearmap,look->n,look->ln,
426
8.50k
      lsp,look->m,amp,info->ampdB,look->lsp_look);
427
8.50k
    return(1);
428
8.50k
  }
429
547k
  memset(out,0,sizeof(*out)*look->n);
430
547k
  return(0);
431
556k
}
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