Coverage Report

Created: 2026-01-16 07:48

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/vorbis/lib/floor0.c
Line
Count
Source
1
/********************************************************************
2
 *                                                                  *
3
 * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
4
 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
5
 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
6
 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
7
 *                                                                  *
8
 * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2015             *
9
 * by the Xiph.Org Foundation https://xiph.org/                     *
10
 *                                                                  *
11
 ********************************************************************
12
13
 function: floor backend 0 implementation
14
15
 ********************************************************************/
16
17
#include <stdlib.h>
18
#include <string.h>
19
#include <math.h>
20
#include <ogg/ogg.h>
21
#include "vorbis/codec.h"
22
#include "codec_internal.h"
23
#include "registry.h"
24
#include "lpc.h"
25
#include "lsp.h"
26
#include "codebook.h"
27
#include "scales.h"
28
#include "misc.h"
29
#include "os.h"
30
31
#include "misc.h"
32
#include <stdio.h>
33
34
typedef struct {
35
  int ln;
36
  int  m;
37
  int **linearmap;
38
  int  n[2];
39
40
  vorbis_info_floor0 *vi;
41
42
  long bits;
43
  long frames;
44
} vorbis_look_floor0;
45
46
47
/***********************************************/
48
49
410
static void floor0_free_info(vorbis_info_floor *i){
50
410
  vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
51
410
  if(info){
52
410
    memset(info,0,sizeof(*info));
53
410
    _ogg_free(info);
54
410
  }
55
410
}
56
57
293
static void floor0_free_look(vorbis_look_floor *i){
58
293
  vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
59
293
  if(look){
60
61
293
    if(look->linearmap){
62
63
293
      if(look->linearmap[0])_ogg_free(look->linearmap[0]);
64
293
      if(look->linearmap[1])_ogg_free(look->linearmap[1]);
65
66
293
      _ogg_free(look->linearmap);
67
293
    }
68
293
    memset(look,0,sizeof(*look));
69
293
    _ogg_free(look);
70
293
  }
71
293
}
72
73
410
static vorbis_info_floor *floor0_unpack (vorbis_info *vi,oggpack_buffer *opb){
74
410
  codec_setup_info     *ci=vi->codec_setup;
75
410
  int j;
76
77
410
  vorbis_info_floor0 *info=_ogg_malloc(sizeof(*info));
78
410
  info->order=oggpack_read(opb,8);
79
410
  info->rate=oggpack_read(opb,16);
80
410
  info->barkmap=oggpack_read(opb,16);
81
410
  info->ampbits=oggpack_read(opb,6);
82
410
  info->ampdB=oggpack_read(opb,8);
83
410
  info->numbooks=oggpack_read(opb,4)+1;
84
85
410
  if(info->order<1)goto err_out;
86
400
  if(info->rate<1)goto err_out;
87
397
  if(info->barkmap<1)goto err_out;
88
394
  if(info->numbooks<1)goto err_out;
89
90
3.57k
  for(j=0;j<info->numbooks;j++){
91
3.20k
    info->books[j]=oggpack_read(opb,8);
92
3.20k
    if(info->books[j]<0 || info->books[j]>=ci->books)goto err_out;
93
3.18k
    if(ci->book_param[info->books[j]]->maptype==0)goto err_out;
94
3.18k
    if(ci->book_param[info->books[j]]->dim<1)goto err_out;
95
3.18k
  }
96
371
  return(info);
97
98
39
 err_out:
99
39
  floor0_free_info(info);
100
39
  return(NULL);
101
390
}
102
103
/* initialize Bark scale and normalization lookups.  We could do this
104
   with static tables, but Vorbis allows a number of possible
105
   combinations, so it's best to do it computationally.
106
107
   The below is authoritative in terms of defining scale mapping.
108
   Note that the scale depends on the sampling rate as well as the
109
   linear block and mapping sizes */
110
111
static void floor0_map_lazy_init(vorbis_block      *vb,
112
                                 vorbis_info_floor *infoX,
113
751k
                                 vorbis_look_floor0 *look){
114
751k
  if(!look->linearmap[vb->W]){
115
288
    vorbis_dsp_state   *vd=vb->vd;
116
288
    vorbis_info        *vi=vd->vi;
117
288
    codec_setup_info   *ci=vi->codec_setup;
118
288
    vorbis_info_floor0 *info=(vorbis_info_floor0 *)infoX;
119
288
    int W=vb->W;
120
288
    int n=ci->blocksizes[W]/2,j;
121
122
    /* we choose a scaling constant so that:
123
       floor(bark(rate/2-1)*C)=mapped-1
124
     floor(bark(rate/2)*C)=mapped */
125
288
    float scale=look->ln/toBARK(info->rate/2.f);
126
127
    /* the mapping from a linear scale to a smaller bark scale is
128
       straightforward.  We do *not* make sure that the linear mapping
129
       does not skip bark-scale bins; the decoder simply skips them and
130
       the encoder may do what it wishes in filling them.  They're
131
       necessary in some mapping combinations to keep the scale spacing
132
       accurate */
133
288
    look->linearmap[W]=_ogg_malloc((n+1)*sizeof(**look->linearmap));
134
490k
    for(j=0;j<n;j++){
135
489k
      int val=floor( toBARK((info->rate/2.f)/n*j)
136
489k
                     *scale); /* bark numbers represent band edges */
137
489k
      if(val>=look->ln)val=look->ln-1; /* guard against the approximation */
138
489k
      look->linearmap[W][j]=val;
139
489k
    }
140
288
    look->linearmap[W][j]=-1;
141
288
    look->n[W]=n;
142
288
  }
143
751k
}
144
145
static vorbis_look_floor *floor0_look(vorbis_dsp_state *vd,
146
293
                                      vorbis_info_floor *i){
147
293
  vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
148
293
  vorbis_look_floor0 *look=_ogg_calloc(1,sizeof(*look));
149
150
293
  (void)vd;
151
152
293
  look->m=info->order;
153
293
  look->ln=info->barkmap;
154
293
  look->vi=info;
155
156
293
  look->linearmap=_ogg_calloc(2,sizeof(*look->linearmap));
157
158
293
  return look;
159
293
}
160
161
751k
static void *floor0_inverse1(vorbis_block *vb,vorbis_look_floor *i){
162
751k
  vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
163
751k
  vorbis_info_floor0 *info=look->vi;
164
751k
  int j,k;
165
166
751k
  int ampraw=oggpack_read(&vb->opb,info->ampbits);
167
751k
  if(ampraw>0){ /* also handles the -1 out of data case */
168
75.0k
    long maxval=(1<<info->ampbits)-1;
169
75.0k
    float amp=(float)ampraw/maxval*info->ampdB;
170
75.0k
    int booknum=oggpack_read(&vb->opb,ov_ilog(info->numbooks));
171
172
75.0k
    if(booknum!=-1 && booknum<info->numbooks){ /* be paranoid */
173
42.6k
      codec_setup_info  *ci=vb->vd->vi->codec_setup;
174
42.6k
      codebook *b=ci->fullbooks+info->books[booknum];
175
42.6k
      float last=0.f;
176
177
      /* the additional b->dim is a guard against any possible stack
178
         smash; b->dim is provably more than we can overflow the
179
         vector */
180
42.6k
      float *lsp=_vorbis_block_alloc(vb,sizeof(*lsp)*(look->m+b->dim+1));
181
182
42.6k
      if(vorbis_book_decodev_set(b,lsp,&vb->opb,look->m)==-1)goto eop;
183
106k
      for(j=0;j<look->m;){
184
777k
        for(k=0;j<look->m && k<b->dim;k++,j++)lsp[j]+=last;
185
64.2k
        last=lsp[j-1];
186
64.2k
      }
187
188
42.5k
      lsp[look->m]=amp;
189
42.5k
      return(lsp);
190
42.6k
    }
191
75.0k
  }
192
708k
 eop:
193
708k
  return(NULL);
194
751k
}
195
196
static int floor0_inverse2(vorbis_block *vb,vorbis_look_floor *i,
197
751k
                           void *memo,float *out){
198
751k
  vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
199
751k
  vorbis_info_floor0 *info=look->vi;
200
201
751k
  floor0_map_lazy_init(vb,info,look);
202
203
751k
  if(memo){
204
42.5k
    float *lsp=(float *)memo;
205
42.5k
    float amp=lsp[look->m];
206
207
    /* take the coefficients back to a spectral envelope curve */
208
42.5k
    vorbis_lsp_to_curve(out,
209
42.5k
                        look->linearmap[vb->W],
210
42.5k
                        look->n[vb->W],
211
42.5k
                        look->ln,
212
42.5k
                        lsp,look->m,amp,(float)info->ampdB);
213
42.5k
    return(1);
214
42.5k
  }
215
708k
  memset(out,0,sizeof(*out)*look->n[vb->W]);
216
708k
  return(0);
217
751k
}
218
219
/* export hooks */
220
const vorbis_func_floor floor0_exportbundle={
221
  NULL,&floor0_unpack,&floor0_look,&floor0_free_info,
222
  &floor0_free_look,&floor0_inverse1,&floor0_inverse2
223
};