Coverage Report

Created: 2024-09-06 07:53

/src/vorbis/lib/floor0.c
Line
Count
Source (jump to first uncovered line)
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
0
static void floor0_free_info(vorbis_info_floor *i){
50
0
  vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
51
0
  if(info){
52
0
    memset(info,0,sizeof(*info));
53
0
    _ogg_free(info);
54
0
  }
55
0
}
56
57
0
static void floor0_free_look(vorbis_look_floor *i){
58
0
  vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
59
0
  if(look){
60
61
0
    if(look->linearmap){
62
63
0
      if(look->linearmap[0])_ogg_free(look->linearmap[0]);
64
0
      if(look->linearmap[1])_ogg_free(look->linearmap[1]);
65
66
0
      _ogg_free(look->linearmap);
67
0
    }
68
0
    memset(look,0,sizeof(*look));
69
0
    _ogg_free(look);
70
0
  }
71
0
}
72
73
0
static vorbis_info_floor *floor0_unpack (vorbis_info *vi,oggpack_buffer *opb){
74
0
  codec_setup_info     *ci=vi->codec_setup;
75
0
  int j;
76
77
0
  vorbis_info_floor0 *info=_ogg_malloc(sizeof(*info));
78
0
  info->order=oggpack_read(opb,8);
79
0
  info->rate=oggpack_read(opb,16);
80
0
  info->barkmap=oggpack_read(opb,16);
81
0
  info->ampbits=oggpack_read(opb,6);
82
0
  info->ampdB=oggpack_read(opb,8);
83
0
  info->numbooks=oggpack_read(opb,4)+1;
84
85
0
  if(info->order<1)goto err_out;
86
0
  if(info->rate<1)goto err_out;
87
0
  if(info->barkmap<1)goto err_out;
88
0
  if(info->numbooks<1)goto err_out;
89
90
0
  for(j=0;j<info->numbooks;j++){
91
0
    info->books[j]=oggpack_read(opb,8);
92
0
    if(info->books[j]<0 || info->books[j]>=ci->books)goto err_out;
93
0
    if(ci->book_param[info->books[j]]->maptype==0)goto err_out;
94
0
    if(ci->book_param[info->books[j]]->dim<1)goto err_out;
95
0
  }
96
0
  return(info);
97
98
0
 err_out:
99
0
  floor0_free_info(info);
100
0
  return(NULL);
101
0
}
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
0
                                 vorbis_look_floor0 *look){
114
0
  if(!look->linearmap[vb->W]){
115
0
    vorbis_dsp_state   *vd=vb->vd;
116
0
    vorbis_info        *vi=vd->vi;
117
0
    codec_setup_info   *ci=vi->codec_setup;
118
0
    vorbis_info_floor0 *info=(vorbis_info_floor0 *)infoX;
119
0
    int W=vb->W;
120
0
    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
0
    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
0
    look->linearmap[W]=_ogg_malloc((n+1)*sizeof(**look->linearmap));
134
0
    for(j=0;j<n;j++){
135
0
      int val=floor( toBARK((info->rate/2.f)/n*j)
136
0
                     *scale); /* bark numbers represent band edges */
137
0
      if(val>=look->ln)val=look->ln-1; /* guard against the approximation */
138
0
      look->linearmap[W][j]=val;
139
0
    }
140
0
    look->linearmap[W][j]=-1;
141
0
    look->n[W]=n;
142
0
  }
143
0
}
144
145
static vorbis_look_floor *floor0_look(vorbis_dsp_state *vd,
146
0
                                      vorbis_info_floor *i){
147
0
  vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
148
0
  vorbis_look_floor0 *look=_ogg_calloc(1,sizeof(*look));
149
150
0
  (void)vd;
151
152
0
  look->m=info->order;
153
0
  look->ln=info->barkmap;
154
0
  look->vi=info;
155
156
0
  look->linearmap=_ogg_calloc(2,sizeof(*look->linearmap));
157
158
0
  return look;
159
0
}
160
161
0
static void *floor0_inverse1(vorbis_block *vb,vorbis_look_floor *i){
162
0
  vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
163
0
  vorbis_info_floor0 *info=look->vi;
164
0
  int j,k;
165
166
0
  int ampraw=oggpack_read(&vb->opb,info->ampbits);
167
0
  if(ampraw>0){ /* also handles the -1 out of data case */
168
0
    long maxval=(1<<info->ampbits)-1;
169
0
    float amp=(float)ampraw/maxval*info->ampdB;
170
0
    int booknum=oggpack_read(&vb->opb,ov_ilog(info->numbooks));
171
172
0
    if(booknum!=-1 && booknum<info->numbooks){ /* be paranoid */
173
0
      codec_setup_info  *ci=vb->vd->vi->codec_setup;
174
0
      codebook *b=ci->fullbooks+info->books[booknum];
175
0
      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
0
      float *lsp=_vorbis_block_alloc(vb,sizeof(*lsp)*(look->m+b->dim+1));
181
182
0
      if(vorbis_book_decodev_set(b,lsp,&vb->opb,look->m)==-1)goto eop;
183
0
      for(j=0;j<look->m;){
184
0
        for(k=0;j<look->m && k<b->dim;k++,j++)lsp[j]+=last;
185
0
        last=lsp[j-1];
186
0
      }
187
188
0
      lsp[look->m]=amp;
189
0
      return(lsp);
190
0
    }
191
0
  }
192
0
 eop:
193
0
  return(NULL);
194
0
}
195
196
static int floor0_inverse2(vorbis_block *vb,vorbis_look_floor *i,
197
0
                           void *memo,float *out){
198
0
  vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
199
0
  vorbis_info_floor0 *info=look->vi;
200
201
0
  floor0_map_lazy_init(vb,info,look);
202
203
0
  if(memo){
204
0
    float *lsp=(float *)memo;
205
0
    float amp=lsp[look->m];
206
207
    /* take the coefficients back to a spectral envelope curve */
208
0
    vorbis_lsp_to_curve(out,
209
0
                        look->linearmap[vb->W],
210
0
                        look->n[vb->W],
211
0
                        look->ln,
212
0
                        lsp,look->m,amp,(float)info->ampdB);
213
0
    return(1);
214
0
  }
215
0
  memset(out,0,sizeof(*out)*look->n[vb->W]);
216
0
  return(0);
217
0
}
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
};