Coverage Report

Created: 2026-01-13 06:21

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