Coverage Report

Created: 2026-01-09 06:55

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/vorbis/lib/floor1.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 1 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 "codebook.h"
25
#include "misc.h"
26
#include "scales.h"
27
28
#include <stdio.h>
29
30
#define floor1_rangedB 140 /* floor 1 fixed at -140dB to 0dB range */
31
32
typedef struct lsfit_acc{
33
  int x0;
34
  int x1;
35
36
  int xa;
37
  int ya;
38
  int x2a;
39
  int y2a;
40
  int xya;
41
  int an;
42
43
  int xb;
44
  int yb;
45
  int x2b;
46
  int y2b;
47
  int xyb;
48
  int bn;
49
} lsfit_acc;
50
51
/***********************************************/
52
53
7.55k
static void floor1_free_info(vorbis_info_floor *i){
54
7.55k
  vorbis_info_floor1 *info=(vorbis_info_floor1 *)i;
55
7.55k
  if(info){
56
7.55k
    memset(info,0,sizeof(*info));
57
7.55k
    _ogg_free(info);
58
7.55k
  }
59
7.55k
}
60
61
6.90k
static void floor1_free_look(vorbis_look_floor *i){
62
6.90k
  vorbis_look_floor1 *look=(vorbis_look_floor1 *)i;
63
6.90k
  if(look){
64
    /*fprintf(stderr,"floor 1 bit usage %f:%f (%f total)\n",
65
            (float)look->phrasebits/look->frames,
66
            (float)look->postbits/look->frames,
67
            (float)(look->postbits+look->phrasebits)/look->frames);*/
68
69
6.90k
    memset(look,0,sizeof(*look));
70
6.90k
    _ogg_free(look);
71
6.90k
  }
72
6.90k
}
73
74
0
static void floor1_pack (vorbis_info_floor *i,oggpack_buffer *opb){
75
0
  vorbis_info_floor1 *info=(vorbis_info_floor1 *)i;
76
0
  int j,k;
77
0
  int count=0;
78
0
  int rangebits;
79
0
  int maxposit=info->postlist[1];
80
0
  int maxclass=-1;
81
82
  /* save out partitions */
83
0
  oggpack_write(opb,info->partitions,5); /* only 0 to 31 legal */
84
0
  for(j=0;j<info->partitions;j++){
85
0
    oggpack_write(opb,info->partitionclass[j],4); /* only 0 to 15 legal */
86
0
    if(maxclass<info->partitionclass[j])maxclass=info->partitionclass[j];
87
0
  }
88
89
  /* save out partition classes */
90
0
  for(j=0;j<maxclass+1;j++){
91
0
    oggpack_write(opb,info->class_dim[j]-1,3); /* 1 to 8 */
92
0
    oggpack_write(opb,info->class_subs[j],2); /* 0 to 3 */
93
0
    if(info->class_subs[j])oggpack_write(opb,info->class_book[j],8);
94
0
    for(k=0;k<(1<<info->class_subs[j]);k++)
95
0
      oggpack_write(opb,info->class_subbook[j][k]+1,8);
96
0
  }
97
98
  /* save out the post list */
99
0
  oggpack_write(opb,info->mult-1,2);     /* only 1,2,3,4 legal now */
100
  /* maxposit cannot legally be less than 1; this is encode-side, we
101
     can assume our setup is OK */
102
0
  oggpack_write(opb,ov_ilog(maxposit-1),4);
103
0
  rangebits=ov_ilog(maxposit-1);
104
105
0
  for(j=0,k=0;j<info->partitions;j++){
106
0
    count+=info->class_dim[info->partitionclass[j]];
107
0
    for(;k<count;k++)
108
0
      oggpack_write(opb,info->postlist[k+2],rangebits);
109
0
  }
110
0
}
111
112
155k
static int icomp(const void *a,const void *b){
113
155k
  return(**(int **)a-**(int **)b);
114
155k
}
115
116
7.55k
static vorbis_info_floor *floor1_unpack (vorbis_info *vi,oggpack_buffer *opb){
117
7.55k
  codec_setup_info     *ci=vi->codec_setup;
118
7.55k
  int j,k,count=0,maxclass=-1,rangebits;
119
120
7.55k
  vorbis_info_floor1 *info=_ogg_calloc(1,sizeof(*info));
121
  /* read partitions */
122
7.55k
  info->partitions=oggpack_read(opb,5); /* only 0 to 31 legal */
123
16.6k
  for(j=0;j<info->partitions;j++){
124
9.13k
    info->partitionclass[j]=oggpack_read(opb,4); /* only 0 to 15 legal */
125
9.13k
    if(info->partitionclass[j]<0)goto err_out;
126
9.12k
    if(maxclass<info->partitionclass[j])maxclass=info->partitionclass[j];
127
9.12k
  }
128
129
  /* read partition classes */
130
11.8k
  for(j=0;j<maxclass+1;j++){
131
4.32k
    info->class_dim[j]=oggpack_read(opb,3)+1; /* 1 to 8 */
132
4.32k
    info->class_subs[j]=oggpack_read(opb,2); /* 0,1,2,3 bits */
133
4.32k
    if(info->class_subs[j]<0)
134
7
      goto err_out;
135
4.32k
    if(info->class_subs[j])info->class_book[j]=oggpack_read(opb,8);
136
4.32k
    if(info->class_book[j]<0 || info->class_book[j]>=ci->books)
137
28
      goto err_out;
138
13.7k
    for(k=0;k<(1<<info->class_subs[j]);k++){
139
9.44k
      info->class_subbook[j][k]=oggpack_read(opb,8)-1;
140
9.44k
      if(info->class_subbook[j][k]<-1 || info->class_subbook[j][k]>=ci->books)
141
21
        goto err_out;
142
9.44k
    }
143
4.29k
  }
144
145
  /* read the post list */
146
7.48k
  info->mult=oggpack_read(opb,2)+1;     /* only 1,2,3,4 legal now */
147
7.48k
  rangebits=oggpack_read(opb,4);
148
7.48k
  if(rangebits<0)goto err_out;
149
150
16.0k
  for(j=0,k=0;j<info->partitions;j++){
151
8.61k
    count+=info->class_dim[info->partitionclass[j]];
152
8.61k
    if(count>VIF_POSIT) goto err_out;
153
30.6k
    for(;k<count;k++){
154
22.0k
      int t=info->postlist[k+2]=oggpack_read(opb,rangebits);
155
22.0k
      if(t<0 || t>=(1<<rangebits))
156
10
        goto err_out;
157
22.0k
    }
158
8.60k
  }
159
7.46k
  info->postlist[0]=0;
160
7.46k
  info->postlist[1]=1<<rangebits;
161
162
  /* don't allow repeated values in post list as they'd result in
163
     zero-length segments */
164
7.46k
  {
165
7.46k
    int *sortpointer[VIF_POSIT+2];
166
44.1k
    for(j=0;j<count+2;j++)sortpointer[j]=info->postlist+j;
167
7.46k
    qsort(sortpointer,count+2,sizeof(*sortpointer),icomp);
168
169
35.9k
    for(j=1;j<count+2;j++)
170
28.5k
      if(*sortpointer[j-1]==*sortpointer[j])goto err_out;
171
7.46k
  }
172
173
7.43k
  return(info);
174
175
115
 err_out:
176
115
  floor1_free_info(info);
177
115
  return(NULL);
178
7.46k
}
179
180
static vorbis_look_floor *floor1_look(vorbis_dsp_state *vd,
181
6.90k
                                      vorbis_info_floor *in){
182
183
6.90k
  int *sortpointer[VIF_POSIT+2];
184
6.90k
  vorbis_info_floor1 *info=(vorbis_info_floor1 *)in;
185
6.90k
  vorbis_look_floor1 *look=_ogg_calloc(1,sizeof(*look));
186
6.90k
  int i,j,n=0;
187
188
6.90k
  (void)vd;
189
190
6.90k
  look->vi=info;
191
6.90k
  look->n=info->postlist[1];
192
193
  /* we drop each position value in-between already decoded values,
194
     and use linear interpolation to predict each new value past the
195
     edges.  The positions are read in the order of the position
196
     list... we precompute the bounding positions in the lookup.  Of
197
     course, the neighbors can change (if a position is declined), but
198
     this is an initial mapping */
199
200
14.4k
  for(i=0;i<info->partitions;i++)n+=info->class_dim[info->partitionclass[i]];
201
6.90k
  n+=2;
202
6.90k
  look->posts=n;
203
204
  /* also store a sorted position index */
205
39.7k
  for(i=0;i<n;i++)sortpointer[i]=info->postlist+i;
206
6.90k
  qsort(sortpointer,n,sizeof(*sortpointer),icomp);
207
208
  /* points from sort order back to range number */
209
39.7k
  for(i=0;i<n;i++)look->forward_index[i]=sortpointer[i]-info->postlist;
210
  /* points from range order to sorted position */
211
39.7k
  for(i=0;i<n;i++)look->reverse_index[look->forward_index[i]]=i;
212
  /* we actually need the post values too */
213
39.7k
  for(i=0;i<n;i++)look->sorted_index[i]=info->postlist[look->forward_index[i]];
214
215
  /* quantize values to multiplier spec */
216
6.90k
  switch(info->mult){
217
2.00k
  case 1: /* 1024 -> 256 */
218
2.00k
    look->quant_q=256;
219
2.00k
    break;
220
680
  case 2: /* 1024 -> 128 */
221
680
    look->quant_q=128;
222
680
    break;
223
3.25k
  case 3: /* 1024 -> 86 */
224
3.25k
    look->quant_q=86;
225
3.25k
    break;
226
963
  case 4: /* 1024 -> 64 */
227
963
    look->quant_q=64;
228
963
    break;
229
6.90k
  }
230
231
  /* discover our neighbors for decode where we don't use fit flags
232
     (that would push the neighbors outward) */
233
25.9k
  for(i=0;i<n-2;i++){
234
19.0k
    int lo=0;
235
19.0k
    int hi=1;
236
19.0k
    int lx=0;
237
19.0k
    int hx=look->n;
238
19.0k
    int currentx=info->postlist[i+2];
239
265k
    for(j=0;j<i+2;j++){
240
246k
      int x=info->postlist[j];
241
246k
      if(x>lx && x<currentx){
242
36.4k
        lo=j;
243
36.4k
        lx=x;
244
36.4k
      }
245
246k
      if(x<hx && x>currentx){
246
31.2k
        hi=j;
247
31.2k
        hx=x;
248
31.2k
      }
249
246k
    }
250
19.0k
    look->loneighbor[i]=lo;
251
19.0k
    look->hineighbor[i]=hi;
252
19.0k
  }
253
254
6.90k
  return(look);
255
6.90k
}
256
257
21.4k
static int render_point(int x0,int x1,int y0,int y1,int x){
258
21.4k
  y0&=0x7fff; /* mask off flag */
259
21.4k
  y1&=0x7fff;
260
261
21.4k
  {
262
21.4k
    int dy=y1-y0;
263
21.4k
    int adx=x1-x0;
264
21.4k
    int ady=abs(dy);
265
21.4k
    int err=ady*(x-x0);
266
267
21.4k
    int off=err/adx;
268
21.4k
    if(dy<0)return(y0-off);
269
12.2k
    return(y0+off);
270
21.4k
  }
271
21.4k
}
272
273
0
static int vorbis_dBquant(const float *x){
274
0
  int i= *x*7.3142857f+1023.5f;
275
0
  if(i>1023)return(1023);
276
0
  if(i<0)return(0);
277
0
  return i;
278
0
}
279
280
static const float FLOOR1_fromdB_LOOKUP[256]={
281
  1.0649863e-07F, 1.1341951e-07F, 1.2079015e-07F, 1.2863978e-07F,
282
  1.3699951e-07F, 1.4590251e-07F, 1.5538408e-07F, 1.6548181e-07F,
283
  1.7623575e-07F, 1.8768855e-07F, 1.9988561e-07F, 2.128753e-07F,
284
  2.2670913e-07F, 2.4144197e-07F, 2.5713223e-07F, 2.7384213e-07F,
285
  2.9163793e-07F, 3.1059021e-07F, 3.3077411e-07F, 3.5226968e-07F,
286
  3.7516214e-07F, 3.9954229e-07F, 4.2550680e-07F, 4.5315863e-07F,
287
  4.8260743e-07F, 5.1396998e-07F, 5.4737065e-07F, 5.8294187e-07F,
288
  6.2082472e-07F, 6.6116941e-07F, 7.0413592e-07F, 7.4989464e-07F,
289
  7.9862701e-07F, 8.5052630e-07F, 9.0579828e-07F, 9.6466216e-07F,
290
  1.0273513e-06F, 1.0941144e-06F, 1.1652161e-06F, 1.2409384e-06F,
291
  1.3215816e-06F, 1.4074654e-06F, 1.4989305e-06F, 1.5963394e-06F,
292
  1.7000785e-06F, 1.8105592e-06F, 1.9282195e-06F, 2.0535261e-06F,
293
  2.1869758e-06F, 2.3290978e-06F, 2.4804557e-06F, 2.6416497e-06F,
294
  2.8133190e-06F, 2.9961443e-06F, 3.1908506e-06F, 3.3982101e-06F,
295
  3.6190449e-06F, 3.8542308e-06F, 4.1047004e-06F, 4.3714470e-06F,
296
  4.6555282e-06F, 4.9580707e-06F, 5.2802740e-06F, 5.6234160e-06F,
297
  5.9888572e-06F, 6.3780469e-06F, 6.7925283e-06F, 7.2339451e-06F,
298
  7.7040476e-06F, 8.2047000e-06F, 8.7378876e-06F, 9.3057248e-06F,
299
  9.9104632e-06F, 1.0554501e-05F, 1.1240392e-05F, 1.1970856e-05F,
300
  1.2748789e-05F, 1.3577278e-05F, 1.4459606e-05F, 1.5399272e-05F,
301
  1.6400004e-05F, 1.7465768e-05F, 1.8600792e-05F, 1.9809576e-05F,
302
  2.1096914e-05F, 2.2467911e-05F, 2.3928002e-05F, 2.5482978e-05F,
303
  2.7139006e-05F, 2.8902651e-05F, 3.0780908e-05F, 3.2781225e-05F,
304
  3.4911534e-05F, 3.7180282e-05F, 3.9596466e-05F, 4.2169667e-05F,
305
  4.4910090e-05F, 4.7828601e-05F, 5.0936773e-05F, 5.4246931e-05F,
306
  5.7772202e-05F, 6.1526565e-05F, 6.5524908e-05F, 6.9783085e-05F,
307
  7.4317983e-05F, 7.9147585e-05F, 8.4291040e-05F, 8.9768747e-05F,
308
  9.5602426e-05F, 0.00010181521F, 0.00010843174F, 0.00011547824F,
309
  0.00012298267F, 0.00013097477F, 0.00013948625F, 0.00014855085F,
310
  0.00015820453F, 0.00016848555F, 0.00017943469F, 0.00019109536F,
311
  0.00020351382F, 0.00021673929F, 0.00023082423F, 0.00024582449F,
312
  0.00026179955F, 0.00027881276F, 0.00029693158F, 0.00031622787F,
313
  0.00033677814F, 0.00035866388F, 0.00038197188F, 0.00040679456F,
314
  0.00043323036F, 0.00046138411F, 0.00049136745F, 0.00052329927F,
315
  0.00055730621F, 0.00059352311F, 0.00063209358F, 0.00067317058F,
316
  0.00071691700F, 0.00076350630F, 0.00081312324F, 0.00086596457F,
317
  0.00092223983F, 0.00098217216F, 0.0010459992F, 0.0011139742F,
318
  0.0011863665F, 0.0012634633F, 0.0013455702F, 0.0014330129F,
319
  0.0015261382F, 0.0016253153F, 0.0017309374F, 0.0018434235F,
320
  0.0019632195F, 0.0020908006F, 0.0022266726F, 0.0023713743F,
321
  0.0025254795F, 0.0026895994F, 0.0028643847F, 0.0030505286F,
322
  0.0032487691F, 0.0034598925F, 0.0036847358F, 0.0039241906F,
323
  0.0041792066F, 0.0044507950F, 0.0047400328F, 0.0050480668F,
324
  0.0053761186F, 0.0057254891F, 0.0060975636F, 0.0064938176F,
325
  0.0069158225F, 0.0073652516F, 0.0078438871F, 0.0083536271F,
326
  0.0088964928F, 0.009474637F, 0.010090352F, 0.010746080F,
327
  0.011444421F, 0.012188144F, 0.012980198F, 0.013823725F,
328
  0.014722068F, 0.015678791F, 0.016697687F, 0.017782797F,
329
  0.018938423F, 0.020169149F, 0.021479854F, 0.022875735F,
330
  0.024362330F, 0.025945531F, 0.027631618F, 0.029427276F,
331
  0.031339626F, 0.033376252F, 0.035545228F, 0.037855157F,
332
  0.040315199F, 0.042935108F, 0.045725273F, 0.048696758F,
333
  0.051861348F, 0.055231591F, 0.058820850F, 0.062643361F,
334
  0.066714279F, 0.071049749F, 0.075666962F, 0.080584227F,
335
  0.085821044F, 0.091398179F, 0.097337747F, 0.10366330F,
336
  0.11039993F, 0.11757434F, 0.12521498F, 0.13335215F,
337
  0.14201813F, 0.15124727F, 0.16107617F, 0.17154380F,
338
  0.18269168F, 0.19456402F, 0.20720788F, 0.22067342F,
339
  0.23501402F, 0.25028656F, 0.26655159F, 0.28387361F,
340
  0.30232132F, 0.32196786F, 0.34289114F, 0.36517414F,
341
  0.38890521F, 0.41417847F, 0.44109412F, 0.46975890F,
342
  0.50028648F, 0.53279791F, 0.56742212F, 0.60429640F,
343
  0.64356699F, 0.68538959F, 0.72993007F, 0.77736504F,
344
  0.82788260F, 0.88168307F, 0.9389798F, 1.F,
345
};
346
347
117k
static void render_line(int n, int x0,int x1,int y0,int y1,float *d){
348
117k
  int dy=y1-y0;
349
117k
  int adx=x1-x0;
350
117k
  int ady=abs(dy);
351
117k
  int base=dy/adx;
352
117k
  int sy=(dy<0?base-1:base+1);
353
117k
  int x=x0;
354
117k
  int y=y0;
355
117k
  int err=0;
356
357
117k
  ady-=abs(base*adx);
358
359
117k
  if(n>x1)n=x1;
360
361
117k
  if(x<n)
362
114k
    d[x]*=FLOOR1_fromdB_LOOKUP[y];
363
364
1.82M
  while(++x<n){
365
1.70M
    err=err+ady;
366
1.70M
    if(err>=adx){
367
357k
      err-=adx;
368
357k
      y+=sy;
369
1.34M
    }else{
370
1.34M
      y+=base;
371
1.34M
    }
372
1.70M
    d[x]*=FLOOR1_fromdB_LOOKUP[y];
373
1.70M
  }
374
117k
}
375
376
0
static void render_line0(int n, int x0,int x1,int y0,int y1,int *d){
377
0
  int dy=y1-y0;
378
0
  int adx=x1-x0;
379
0
  int ady=abs(dy);
380
0
  int base=dy/adx;
381
0
  int sy=(dy<0?base-1:base+1);
382
0
  int x=x0;
383
0
  int y=y0;
384
0
  int err=0;
385
386
0
  ady-=abs(base*adx);
387
388
0
  if(n>x1)n=x1;
389
390
0
  if(x<n)
391
0
    d[x]=y;
392
393
0
  while(++x<n){
394
0
    err=err+ady;
395
0
    if(err>=adx){
396
0
      err-=adx;
397
0
      y+=sy;
398
0
    }else{
399
0
      y+=base;
400
0
    }
401
0
    d[x]=y;
402
0
  }
403
0
}
404
405
/* the floor has already been filtered to only include relevant sections */
406
static int accumulate_fit(const float *flr,const float *mdct,
407
                          int x0, int x1,lsfit_acc *a,
408
0
                          int n,vorbis_info_floor1 *info){
409
0
  long i;
410
411
0
  int xa=0,ya=0,x2a=0,y2a=0,xya=0,na=0, xb=0,yb=0,x2b=0,y2b=0,xyb=0,nb=0;
412
413
0
  memset(a,0,sizeof(*a));
414
0
  a->x0=x0;
415
0
  a->x1=x1;
416
0
  if(x1>=n)x1=n-1;
417
418
0
  for(i=x0;i<=x1;i++){
419
0
    int quantized=vorbis_dBquant(flr+i);
420
0
    if(quantized){
421
0
      if(mdct[i]+info->twofitatten>=flr[i]){
422
0
        xa  += i;
423
0
        ya  += quantized;
424
0
        x2a += i*i;
425
0
        y2a += quantized*quantized;
426
0
        xya += i*quantized;
427
0
        na++;
428
0
      }else{
429
0
        xb  += i;
430
0
        yb  += quantized;
431
0
        x2b += i*i;
432
0
        y2b += quantized*quantized;
433
0
        xyb += i*quantized;
434
0
        nb++;
435
0
      }
436
0
    }
437
0
  }
438
439
0
  a->xa=xa;
440
0
  a->ya=ya;
441
0
  a->x2a=x2a;
442
0
  a->y2a=y2a;
443
0
  a->xya=xya;
444
0
  a->an=na;
445
446
0
  a->xb=xb;
447
0
  a->yb=yb;
448
0
  a->x2b=x2b;
449
0
  a->y2b=y2b;
450
0
  a->xyb=xyb;
451
0
  a->bn=nb;
452
453
0
  return(na);
454
0
}
455
456
static int fit_line(lsfit_acc *a,int fits,int *y0,int *y1,
457
0
                    vorbis_info_floor1 *info){
458
0
  double xb=0,yb=0,x2b=0,y2b=0,xyb=0,bn=0;
459
0
  int i;
460
0
  int x0=a[0].x0;
461
0
  int x1=a[fits-1].x1;
462
463
0
  for(i=0;i<fits;i++){
464
0
    double weight = (a[i].bn+a[i].an)*info->twofitweight/(a[i].an+1)+1.;
465
466
0
    xb+=a[i].xb + a[i].xa * weight;
467
0
    yb+=a[i].yb + a[i].ya * weight;
468
0
    x2b+=a[i].x2b + a[i].x2a * weight;
469
0
    y2b+=a[i].y2b + a[i].y2a * weight;
470
0
    xyb+=a[i].xyb + a[i].xya * weight;
471
0
    bn+=a[i].bn + a[i].an * weight;
472
0
  }
473
474
0
  if(*y0>=0){
475
0
    xb+=   x0;
476
0
    yb+=  *y0;
477
0
    x2b+=  x0 *  x0;
478
0
    y2b+= *y0 * *y0;
479
0
    xyb+= *y0 *  x0;
480
0
    bn++;
481
0
  }
482
483
0
  if(*y1>=0){
484
0
    xb+=   x1;
485
0
    yb+=  *y1;
486
0
    x2b+=  x1 *  x1;
487
0
    y2b+= *y1 * *y1;
488
0
    xyb+= *y1 *  x1;
489
0
    bn++;
490
0
  }
491
492
0
  {
493
0
    double denom=(bn*x2b-xb*xb);
494
495
0
    if(denom>0.){
496
0
      double a=(yb*x2b-xyb*xb)/denom;
497
0
      double b=(bn*xyb-xb*yb)/denom;
498
0
      *y0=rint(a+b*x0);
499
0
      *y1=rint(a+b*x1);
500
501
      /* limit to our range! */
502
0
      if(*y0>1023)*y0=1023;
503
0
      if(*y1>1023)*y1=1023;
504
0
      if(*y0<0)*y0=0;
505
0
      if(*y1<0)*y1=0;
506
507
0
      return 0;
508
0
    }else{
509
0
      *y0=0;
510
0
      *y1=0;
511
0
      return 1;
512
0
    }
513
0
  }
514
0
}
515
516
static int inspect_error(int x0,int x1,int y0,int y1,const float *mask,
517
                         const float *mdct,
518
0
                         vorbis_info_floor1 *info){
519
0
  int dy=y1-y0;
520
0
  int adx=x1-x0;
521
0
  int ady=abs(dy);
522
0
  int base=dy/adx;
523
0
  int sy=(dy<0?base-1:base+1);
524
0
  int x=x0;
525
0
  int y=y0;
526
0
  int err=0;
527
0
  int val=vorbis_dBquant(mask+x);
528
0
  int mse=0;
529
0
  int n=0;
530
531
0
  ady-=abs(base*adx);
532
533
0
  mse=(y-val);
534
0
  mse*=mse;
535
0
  n++;
536
0
  if(mdct[x]+info->twofitatten>=mask[x]){
537
0
    if(y+info->maxover<val)return(1);
538
0
    if(y-info->maxunder>val)return(1);
539
0
  }
540
541
0
  while(++x<x1){
542
0
    err=err+ady;
543
0
    if(err>=adx){
544
0
      err-=adx;
545
0
      y+=sy;
546
0
    }else{
547
0
      y+=base;
548
0
    }
549
550
0
    val=vorbis_dBquant(mask+x);
551
0
    mse+=((y-val)*(y-val));
552
0
    n++;
553
0
    if(mdct[x]+info->twofitatten>=mask[x]){
554
0
      if(val){
555
0
        if(y+info->maxover<val)return(1);
556
0
        if(y-info->maxunder>val)return(1);
557
0
      }
558
0
    }
559
0
  }
560
561
0
  if(info->maxover*info->maxover/n>info->maxerr)return(0);
562
0
  if(info->maxunder*info->maxunder/n>info->maxerr)return(0);
563
0
  if(mse/n>info->maxerr)return(1);
564
0
  return(0);
565
0
}
566
567
0
static int post_Y(int *A,int *B,int pos){
568
0
  if(A[pos]<0)
569
0
    return B[pos];
570
0
  if(B[pos]<0)
571
0
    return A[pos];
572
573
0
  return (A[pos]+B[pos])>>1;
574
0
}
575
576
int *floor1_fit(vorbis_block *vb,vorbis_look_floor1 *look,
577
                          const float *logmdct,   /* in */
578
0
                          const float *logmask){
579
0
  long i,j;
580
0
  vorbis_info_floor1 *info=look->vi;
581
0
  long n=look->n;
582
0
  long posts=look->posts;
583
0
  long nonzero=0;
584
0
  lsfit_acc fits[VIF_POSIT+1];
585
0
  int fit_valueA[VIF_POSIT+2]; /* index by range list position */
586
0
  int fit_valueB[VIF_POSIT+2]; /* index by range list position */
587
588
0
  int loneighbor[VIF_POSIT+2]; /* sorted index of range list position (+2) */
589
0
  int hineighbor[VIF_POSIT+2];
590
0
  int *output=NULL;
591
0
  int memo[VIF_POSIT+2];
592
593
0
  for(i=0;i<posts;i++)fit_valueA[i]=-200; /* mark all unused */
594
0
  for(i=0;i<posts;i++)fit_valueB[i]=-200; /* mark all unused */
595
0
  for(i=0;i<posts;i++)loneighbor[i]=0; /* 0 for the implicit 0 post */
596
0
  for(i=0;i<posts;i++)hineighbor[i]=1; /* 1 for the implicit post at n */
597
0
  for(i=0;i<posts;i++)memo[i]=-1;      /* no neighbor yet */
598
599
  /* quantize the relevant floor points and collect them into line fit
600
     structures (one per minimal division) at the same time */
601
0
  if(posts==0){
602
0
    nonzero+=accumulate_fit(logmask,logmdct,0,n,fits,n,info);
603
0
  }else{
604
0
    for(i=0;i<posts-1;i++)
605
0
      nonzero+=accumulate_fit(logmask,logmdct,look->sorted_index[i],
606
0
                              look->sorted_index[i+1],fits+i,
607
0
                              n,info);
608
0
  }
609
610
0
  if(nonzero){
611
    /* start by fitting the implicit base case.... */
612
0
    int y0=-200;
613
0
    int y1=-200;
614
0
    fit_line(fits,posts-1,&y0,&y1,info);
615
616
0
    fit_valueA[0]=y0;
617
0
    fit_valueB[0]=y0;
618
0
    fit_valueB[1]=y1;
619
0
    fit_valueA[1]=y1;
620
621
    /* Non degenerate case */
622
    /* start progressive splitting.  This is a greedy, non-optimal
623
       algorithm, but simple and close enough to the best
624
       answer. */
625
0
    for(i=2;i<posts;i++){
626
0
      int sortpos=look->reverse_index[i];
627
0
      int ln=loneighbor[sortpos];
628
0
      int hn=hineighbor[sortpos];
629
630
      /* eliminate repeat searches of a particular range with a memo */
631
0
      if(memo[ln]!=hn){
632
        /* haven't performed this error search yet */
633
0
        int lsortpos=look->reverse_index[ln];
634
0
        int hsortpos=look->reverse_index[hn];
635
0
        memo[ln]=hn;
636
637
0
        {
638
          /* A note: we want to bound/minimize *local*, not global, error */
639
0
          int lx=info->postlist[ln];
640
0
          int hx=info->postlist[hn];
641
0
          int ly=post_Y(fit_valueA,fit_valueB,ln);
642
0
          int hy=post_Y(fit_valueA,fit_valueB,hn);
643
644
0
          if(ly==-1 || hy==-1){
645
0
            exit(1);
646
0
          }
647
648
0
          if(inspect_error(lx,hx,ly,hy,logmask,logmdct,info)){
649
            /* outside error bounds/begin search area.  Split it. */
650
0
            int ly0=-200;
651
0
            int ly1=-200;
652
0
            int hy0=-200;
653
0
            int hy1=-200;
654
0
            int ret0=fit_line(fits+lsortpos,sortpos-lsortpos,&ly0,&ly1,info);
655
0
            int ret1=fit_line(fits+sortpos,hsortpos-sortpos,&hy0,&hy1,info);
656
657
0
            if(ret0){
658
0
              ly0=ly;
659
0
              ly1=hy0;
660
0
            }
661
0
            if(ret1){
662
0
              hy0=ly1;
663
0
              hy1=hy;
664
0
            }
665
666
0
            if(ret0 && ret1){
667
0
              fit_valueA[i]=-200;
668
0
              fit_valueB[i]=-200;
669
0
            }else{
670
              /* store new edge values */
671
0
              fit_valueB[ln]=ly0;
672
0
              if(ln==0)fit_valueA[ln]=ly0;
673
0
              fit_valueA[i]=ly1;
674
0
              fit_valueB[i]=hy0;
675
0
              fit_valueA[hn]=hy1;
676
0
              if(hn==1)fit_valueB[hn]=hy1;
677
678
0
              if(ly1>=0 || hy0>=0){
679
                /* store new neighbor values */
680
0
                for(j=sortpos-1;j>=0;j--)
681
0
                  if(hineighbor[j]==hn)
682
0
                    hineighbor[j]=i;
683
0
                  else
684
0
                    break;
685
0
                for(j=sortpos+1;j<posts;j++)
686
0
                  if(loneighbor[j]==ln)
687
0
                    loneighbor[j]=i;
688
0
                  else
689
0
                    break;
690
0
              }
691
0
            }
692
0
          }else{
693
0
            fit_valueA[i]=-200;
694
0
            fit_valueB[i]=-200;
695
0
          }
696
0
        }
697
0
      }
698
0
    }
699
700
0
    output=_vorbis_block_alloc(vb,sizeof(*output)*posts);
701
702
0
    output[0]=post_Y(fit_valueA,fit_valueB,0);
703
0
    output[1]=post_Y(fit_valueA,fit_valueB,1);
704
705
    /* fill in posts marked as not using a fit; we will zero
706
       back out to 'unused' when encoding them so long as curve
707
       interpolation doesn't force them into use */
708
0
    for(i=2;i<posts;i++){
709
0
      int ln=look->loneighbor[i-2];
710
0
      int hn=look->hineighbor[i-2];
711
0
      int x0=info->postlist[ln];
712
0
      int x1=info->postlist[hn];
713
0
      int y0=output[ln];
714
0
      int y1=output[hn];
715
716
0
      int predicted=render_point(x0,x1,y0,y1,info->postlist[i]);
717
0
      int vx=post_Y(fit_valueA,fit_valueB,i);
718
719
0
      if(vx>=0 && predicted!=vx){
720
0
        output[i]=vx;
721
0
      }else{
722
0
        output[i]= predicted|0x8000;
723
0
      }
724
0
    }
725
0
  }
726
727
0
  return(output);
728
729
0
}
730
731
int *floor1_interpolate_fit(vorbis_block *vb,vorbis_look_floor1 *look,
732
                          int *A,int *B,
733
0
                          int del){
734
735
0
  long i;
736
0
  long posts=look->posts;
737
0
  int *output=NULL;
738
739
0
  if(A && B){
740
0
    output=_vorbis_block_alloc(vb,sizeof(*output)*posts);
741
742
    /* overly simpleminded--- look again post 1.2 */
743
0
    for(i=0;i<posts;i++){
744
0
      output[i]=((65536-del)*(A[i]&0x7fff)+del*(B[i]&0x7fff)+32768)>>16;
745
0
      if(A[i]&0x8000 && B[i]&0x8000)output[i]|=0x8000;
746
0
    }
747
0
  }
748
749
0
  return(output);
750
0
}
751
752
753
int floor1_encode(oggpack_buffer *opb,vorbis_block *vb,
754
                  vorbis_look_floor1 *look,
755
0
                  int *post,int *ilogmask){
756
757
0
  long i,j;
758
0
  vorbis_info_floor1 *info=look->vi;
759
0
  long posts=look->posts;
760
0
  codec_setup_info *ci=vb->vd->vi->codec_setup;
761
0
  int out[VIF_POSIT+2];
762
0
  static_codebook **sbooks=ci->book_param;
763
0
  codebook *books=ci->fullbooks;
764
765
  /* quantize values to multiplier spec */
766
0
  if(post){
767
0
    for(i=0;i<posts;i++){
768
0
      int val=post[i]&0x7fff;
769
0
      switch(info->mult){
770
0
      case 1: /* 1024 -> 256 */
771
0
        val>>=2;
772
0
        break;
773
0
      case 2: /* 1024 -> 128 */
774
0
        val>>=3;
775
0
        break;
776
0
      case 3: /* 1024 -> 86 */
777
0
        val/=12;
778
0
        break;
779
0
      case 4: /* 1024 -> 64 */
780
0
        val>>=4;
781
0
        break;
782
0
      }
783
0
      post[i]=val | (post[i]&0x8000);
784
0
    }
785
786
0
    out[0]=post[0];
787
0
    out[1]=post[1];
788
789
    /* find prediction values for each post and subtract them */
790
0
    for(i=2;i<posts;i++){
791
0
      int ln=look->loneighbor[i-2];
792
0
      int hn=look->hineighbor[i-2];
793
0
      int x0=info->postlist[ln];
794
0
      int x1=info->postlist[hn];
795
0
      int y0=post[ln];
796
0
      int y1=post[hn];
797
798
0
      int predicted=render_point(x0,x1,y0,y1,info->postlist[i]);
799
800
0
      if((post[i]&0x8000) || (predicted==post[i])){
801
0
        post[i]=predicted|0x8000; /* in case there was roundoff jitter
802
                                     in interpolation */
803
0
        out[i]=0;
804
0
      }else{
805
0
        int headroom=(look->quant_q-predicted<predicted?
806
0
                      look->quant_q-predicted:predicted);
807
808
0
        int val=post[i]-predicted;
809
810
        /* at this point the 'deviation' value is in the range +/- max
811
           range, but the real, unique range can always be mapped to
812
           only [0-maxrange).  So we want to wrap the deviation into
813
           this limited range, but do it in the way that least screws
814
           an essentially gaussian probability distribution. */
815
816
0
        if(val<0)
817
0
          if(val<-headroom)
818
0
            val=headroom-val-1;
819
0
          else
820
0
            val=-1-(val*2);
821
0
        else
822
0
          if(val>=headroom)
823
0
            val= val+headroom;
824
0
          else
825
0
            val<<=1;
826
827
0
        out[i]=val;
828
0
        post[ln]&=0x7fff;
829
0
        post[hn]&=0x7fff;
830
0
      }
831
0
    }
832
833
    /* we have everything we need. pack it out */
834
    /* mark nontrivial floor */
835
0
    oggpack_write(opb,1,1);
836
837
    /* beginning/end post */
838
0
    look->frames++;
839
0
    look->postbits+=ov_ilog(look->quant_q-1)*2;
840
0
    oggpack_write(opb,out[0],ov_ilog(look->quant_q-1));
841
0
    oggpack_write(opb,out[1],ov_ilog(look->quant_q-1));
842
843
844
    /* partition by partition */
845
0
    for(i=0,j=2;i<info->partitions;i++){
846
0
      int class=info->partitionclass[i];
847
0
      int cdim=info->class_dim[class];
848
0
      int csubbits=info->class_subs[class];
849
0
      int csub=1<<csubbits;
850
0
      int bookas[8]={0,0,0,0,0,0,0,0};
851
0
      int cval=0;
852
0
      int cshift=0;
853
0
      int k,l;
854
855
      /* generate the partition's first stage cascade value */
856
0
      if(csubbits){
857
0
        int maxval[8]={0,0,0,0,0,0,0,0}; /* gcc's static analysis
858
                                            issues a warning without
859
                                            initialization */
860
0
        for(k=0;k<csub;k++){
861
0
          int booknum=info->class_subbook[class][k];
862
0
          if(booknum<0){
863
0
            maxval[k]=1;
864
0
          }else{
865
0
            maxval[k]=sbooks[info->class_subbook[class][k]]->entries;
866
0
          }
867
0
        }
868
0
        for(k=0;k<cdim;k++){
869
0
          for(l=0;l<csub;l++){
870
0
            int val=out[j+k];
871
0
            if(val<maxval[l]){
872
0
              bookas[k]=l;
873
0
              break;
874
0
            }
875
0
          }
876
0
          cval|= bookas[k]<<cshift;
877
0
          cshift+=csubbits;
878
0
        }
879
        /* write it */
880
0
        look->phrasebits+=
881
0
          vorbis_book_encode(books+info->class_book[class],cval,opb);
882
883
#ifdef TRAIN_FLOOR1
884
        {
885
          FILE *of;
886
          char buffer[80];
887
          sprintf(buffer,"line_%dx%ld_class%d.vqd",
888
                  vb->pcmend/2,posts-2,class);
889
          of=fopen(buffer,"a");
890
          fprintf(of,"%d\n",cval);
891
          fclose(of);
892
        }
893
#endif
894
0
      }
895
896
      /* write post values */
897
0
      for(k=0;k<cdim;k++){
898
0
        int book=info->class_subbook[class][bookas[k]];
899
0
        if(book>=0){
900
          /* hack to allow training with 'bad' books */
901
0
          if(out[j+k]<(books+book)->entries)
902
0
            look->postbits+=vorbis_book_encode(books+book,
903
0
                                               out[j+k],opb);
904
          /*else
905
            fprintf(stderr,"+!");*/
906
907
#ifdef TRAIN_FLOOR1
908
          {
909
            FILE *of;
910
            char buffer[80];
911
            sprintf(buffer,"line_%dx%ld_%dsub%d.vqd",
912
                    vb->pcmend/2,posts-2,class,bookas[k]);
913
            of=fopen(buffer,"a");
914
            fprintf(of,"%d\n",out[j+k]);
915
            fclose(of);
916
          }
917
#endif
918
0
        }
919
0
      }
920
0
      j+=cdim;
921
0
    }
922
923
0
    {
924
      /* generate quantized floor equivalent to what we'd unpack in decode */
925
      /* render the lines */
926
0
      int hx=0;
927
0
      int lx=0;
928
0
      int ly=post[0]*info->mult;
929
0
      int n=ci->blocksizes[vb->W]/2;
930
931
0
      for(j=1;j<look->posts;j++){
932
0
        int current=look->forward_index[j];
933
0
        int hy=post[current]&0x7fff;
934
0
        if(hy==post[current]){
935
936
0
          hy*=info->mult;
937
0
          hx=info->postlist[current];
938
939
0
          render_line0(n,lx,hx,ly,hy,ilogmask);
940
941
0
          lx=hx;
942
0
          ly=hy;
943
0
        }
944
0
      }
945
0
      for(j=hx;j<vb->pcmend/2;j++)ilogmask[j]=ly; /* be certain */
946
0
      return(1);
947
0
    }
948
0
  }else{
949
0
    oggpack_write(opb,0,1);
950
0
    memset(ilogmask,0,vb->pcmend/2*sizeof(*ilogmask));
951
0
    return(0);
952
0
  }
953
0
}
954
955
2.57M
static void *floor1_inverse1(vorbis_block *vb,vorbis_look_floor *in){
956
2.57M
  vorbis_look_floor1 *look=(vorbis_look_floor1 *)in;
957
2.57M
  vorbis_info_floor1 *info=look->vi;
958
2.57M
  codec_setup_info   *ci=vb->vd->vi->codec_setup;
959
960
2.57M
  int i,j,k;
961
2.57M
  codebook *books=ci->fullbooks;
962
963
  /* unpack wrapped/predicted values from stream */
964
2.57M
  if(oggpack_read(&vb->opb,1)==1){
965
122k
    int *fit_value=_vorbis_block_alloc(vb,(look->posts)*sizeof(*fit_value));
966
967
122k
    fit_value[0]=oggpack_read(&vb->opb,ov_ilog(look->quant_q-1));
968
122k
    fit_value[1]=oggpack_read(&vb->opb,ov_ilog(look->quant_q-1));
969
970
    /* partition by partition */
971
135k
    for(i=0,j=2;i<info->partitions;i++){
972
14.7k
      int class=info->partitionclass[i];
973
14.7k
      int cdim=info->class_dim[class];
974
14.7k
      int csubbits=info->class_subs[class];
975
14.7k
      int csub=1<<csubbits;
976
14.7k
      int cval=0;
977
978
      /* decode the partition's first stage cascade value */
979
14.7k
      if(csubbits){
980
6.34k
        cval=vorbis_book_decode(books+info->class_book[class],&vb->opb);
981
982
6.34k
        if(cval==-1)goto eop;
983
6.34k
      }
984
985
35.9k
      for(k=0;k<cdim;k++){
986
22.5k
        int book=info->class_subbook[class][cval&(csub-1)];
987
22.5k
        cval>>=csubbits;
988
22.5k
        if(book>=0){
989
15.2k
          if((fit_value[j+k]=vorbis_book_decode(books+book,&vb->opb))==-1)
990
785
            goto eop;
991
15.2k
        }else{
992
7.32k
          fit_value[j+k]=0;
993
7.32k
        }
994
22.5k
      }
995
13.3k
      j+=cdim;
996
13.3k
    }
997
998
    /* unwrap positive values and reconsitute via linear interpolation */
999
142k
    for(i=2;i<look->posts;i++){
1000
21.4k
      int predicted=render_point(info->postlist[look->loneighbor[i-2]],
1001
21.4k
                                 info->postlist[look->hineighbor[i-2]],
1002
21.4k
                                 fit_value[look->loneighbor[i-2]],
1003
21.4k
                                 fit_value[look->hineighbor[i-2]],
1004
21.4k
                                 info->postlist[i]);
1005
21.4k
      int hiroom=look->quant_q-predicted;
1006
21.4k
      int loroom=predicted;
1007
21.4k
      int room=(hiroom<loroom?hiroom:loroom)<<1;
1008
21.4k
      int val=fit_value[i];
1009
1010
21.4k
      if(val){
1011
10.0k
        if(val>=room){
1012
2.91k
          if(hiroom>loroom){
1013
1.00k
            val = val-loroom;
1014
1.91k
          }else{
1015
1.91k
            val = -1-(val-hiroom);
1016
1.91k
          }
1017
7.10k
        }else{
1018
7.10k
          if(val&1){
1019
4.54k
            val= -((val+1)>>1);
1020
4.54k
          }else{
1021
2.56k
            val>>=1;
1022
2.56k
          }
1023
7.10k
        }
1024
1025
10.0k
        fit_value[i]=(val+predicted)&0x7fff;
1026
10.0k
        fit_value[look->loneighbor[i-2]]&=0x7fff;
1027
10.0k
        fit_value[look->hineighbor[i-2]]&=0x7fff;
1028
1029
11.3k
      }else{
1030
11.3k
        fit_value[i]=predicted|0x8000;
1031
11.3k
      }
1032
1033
21.4k
    }
1034
1035
120k
    return(fit_value);
1036
122k
  }
1037
2.45M
 eop:
1038
2.45M
  return(NULL);
1039
2.57M
}
1040
1041
static int floor1_inverse2(vorbis_block *vb,vorbis_look_floor *in,void *memo,
1042
2.57M
                          float *out){
1043
2.57M
  vorbis_look_floor1 *look=(vorbis_look_floor1 *)in;
1044
2.57M
  vorbis_info_floor1 *info=look->vi;
1045
1046
2.57M
  codec_setup_info   *ci=vb->vd->vi->codec_setup;
1047
2.57M
  int                  n=ci->blocksizes[vb->W]/2;
1048
2.57M
  int j;
1049
1050
2.57M
  if(memo){
1051
    /* render the lines */
1052
120k
    int *fit_value=(int *)memo;
1053
120k
    int hx=0;
1054
120k
    int lx=0;
1055
120k
    int ly=fit_value[0]*info->mult;
1056
    /* guard lookup against out-of-range values */
1057
120k
    ly=(ly<0?0:ly>255?255:ly);
1058
1059
262k
    for(j=1;j<look->posts;j++){
1060
142k
      int current=look->forward_index[j];
1061
142k
      int hy=fit_value[current]&0x7fff;
1062
142k
      if(hy==fit_value[current]){
1063
1064
117k
        hx=info->postlist[current];
1065
117k
        hy*=info->mult;
1066
        /* guard lookup against out-of-range values */
1067
117k
        hy=(hy<0?0:hy>255?255:hy);
1068
1069
117k
        render_line(n,lx,hx,ly,hy,out);
1070
1071
117k
        lx=hx;
1072
117k
        ly=hy;
1073
117k
      }
1074
142k
    }
1075
85.2M
    for(j=hx;j<n;j++)out[j]*=FLOOR1_fromdB_LOOKUP[ly]; /* be certain */
1076
120k
    return(1);
1077
120k
  }
1078
2.45M
  memset(out,0,sizeof(*out)*n);
1079
2.45M
  return(0);
1080
2.57M
}
1081
1082
/* export hooks */
1083
const vorbis_func_floor floor1_exportbundle={
1084
  &floor1_pack,&floor1_unpack,&floor1_look,&floor1_free_info,
1085
  &floor1_free_look,&floor1_inverse1,&floor1_inverse2
1086
};