Coverage Report

Created: 2025-11-16 06:17

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