Coverage Report

Created: 2026-07-12 06:32

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