Coverage Report

Created: 2025-12-31 07:57

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
921
static void floor1_free_info(vorbis_info_floor *i){
54
921
  vorbis_info_floor1 *info=(vorbis_info_floor1 *)i;
55
921
  if(info){
56
921
    memset(info,0,sizeof(*info));
57
921
    _ogg_free(info);
58
921
  }
59
921
}
60
61
536
static void floor1_free_look(vorbis_look_floor *i){
62
536
  vorbis_look_floor1 *look=(vorbis_look_floor1 *)i;
63
536
  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
536
    memset(look,0,sizeof(*look));
70
536
    _ogg_free(look);
71
536
  }
72
536
}
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
2.58k
static int icomp(const void *a,const void *b){
113
2.58k
  return(**(int **)a-**(int **)b);
114
2.58k
}
115
116
921
static vorbis_info_floor *floor1_unpack (vorbis_info *vi,oggpack_buffer *opb){
117
921
  codec_setup_info     *ci=vi->codec_setup;
118
921
  int j,k,count=0,maxclass=-1,rangebits;
119
120
921
  vorbis_info_floor1 *info=_ogg_calloc(1,sizeof(*info));
121
  /* read partitions */
122
921
  info->partitions=oggpack_read(opb,5); /* only 0 to 31 legal */
123
1.61k
  for(j=0;j<info->partitions;j++){
124
702
    info->partitionclass[j]=oggpack_read(opb,4); /* only 0 to 15 legal */
125
702
    if(info->partitionclass[j]<0)goto err_out;
126
697
    if(maxclass<info->partitionclass[j])maxclass=info->partitionclass[j];
127
697
  }
128
129
  /* read partition classes */
130
1.09k
  for(j=0;j<maxclass+1;j++){
131
214
    info->class_dim[j]=oggpack_read(opb,3)+1; /* 1 to 8 */
132
214
    info->class_subs[j]=oggpack_read(opb,2); /* 0,1,2,3 bits */
133
214
    if(info->class_subs[j]<0)
134
4
      goto err_out;
135
210
    if(info->class_subs[j])info->class_book[j]=oggpack_read(opb,8);
136
210
    if(info->class_book[j]<0 || info->class_book[j]>=ci->books)
137
14
      goto err_out;
138
408
    for(k=0;k<(1<<info->class_subs[j]);k++){
139
232
      info->class_subbook[j][k]=oggpack_read(opb,8)-1;
140
232
      if(info->class_subbook[j][k]<-1 || info->class_subbook[j][k]>=ci->books)
141
20
        goto err_out;
142
232
    }
143
196
  }
144
145
  /* read the post list */
146
878
  info->mult=oggpack_read(opb,2)+1;     /* only 1,2,3,4 legal now */
147
878
  rangebits=oggpack_read(opb,4);
148
878
  if(rangebits<0)goto err_out;
149
150
1.09k
  for(j=0,k=0;j<info->partitions;j++){
151
229
    count+=info->class_dim[info->partitionclass[j]];
152
229
    if(count>VIF_POSIT) goto err_out;
153
662
    for(;k<count;k++){
154
444
      int t=info->postlist[k+2]=oggpack_read(opb,rangebits);
155
444
      if(t<0 || t>=(1<<rangebits))
156
10
        goto err_out;
157
444
    }
158
228
  }
159
866
  info->postlist[0]=0;
160
866
  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
866
  {
165
866
    int *sortpointer[VIF_POSIT+2];
166
2.95k
    for(j=0;j<count+2;j++)sortpointer[j]=info->postlist+j;
167
866
    qsort(sortpointer,count+2,sizeof(*sortpointer),icomp);
168
169
1.76k
    for(j=1;j<count+2;j++)
170
926
      if(*sortpointer[j-1]==*sortpointer[j])goto err_out;
171
866
  }
172
173
843
  return(info);
174
175
78
 err_out:
176
78
  floor1_free_info(info);
177
78
  return(NULL);
178
866
}
179
180
static vorbis_look_floor *floor1_look(vorbis_dsp_state *vd,
181
536
                                      vorbis_info_floor *in){
182
183
536
  int *sortpointer[VIF_POSIT+2];
184
536
  vorbis_info_floor1 *info=(vorbis_info_floor1 *)in;
185
536
  vorbis_look_floor1 *look=_ogg_calloc(1,sizeof(*look));
186
536
  int i,j,n=0;
187
188
536
  (void)vd;
189
190
536
  look->vi=info;
191
536
  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
536
  for(i=0;i<info->partitions;i++)n+=info->class_dim[info->partitionclass[i]];
201
536
  n+=2;
202
536
  look->posts=n;
203
204
  /* also store a sorted position index */
205
1.60k
  for(i=0;i<n;i++)sortpointer[i]=info->postlist+i;
206
536
  qsort(sortpointer,n,sizeof(*sortpointer),icomp);
207
208
  /* points from sort order back to range number */
209
1.60k
  for(i=0;i<n;i++)look->forward_index[i]=sortpointer[i]-info->postlist;
210
  /* points from range order to sorted position */
211
1.60k
  for(i=0;i<n;i++)look->reverse_index[look->forward_index[i]]=i;
212
  /* we actually need the post values too */
213
1.60k
  for(i=0;i<n;i++)look->sorted_index[i]=info->postlist[look->forward_index[i]];
214
215
  /* quantize values to multiplier spec */
216
536
  switch(info->mult){
217
25
  case 1: /* 1024 -> 256 */
218
25
    look->quant_q=256;
219
25
    break;
220
99
  case 2: /* 1024 -> 128 */
221
99
    look->quant_q=128;
222
99
    break;
223
114
  case 3: /* 1024 -> 86 */
224
114
    look->quant_q=86;
225
114
    break;
226
298
  case 4: /* 1024 -> 64 */
227
298
    look->quant_q=64;
228
298
    break;
229
536
  }
230
231
  /* discover our neighbors for decode where we don't use fit flags
232
     (that would push the neighbors outward) */
233
536
  for(i=0;i<n-2;i++){
234
0
    int lo=0;
235
0
    int hi=1;
236
0
    int lx=0;
237
0
    int hx=look->n;
238
0
    int currentx=info->postlist[i+2];
239
0
    for(j=0;j<i+2;j++){
240
0
      int x=info->postlist[j];
241
0
      if(x>lx && x<currentx){
242
0
        lo=j;
243
0
        lx=x;
244
0
      }
245
0
      if(x<hx && x>currentx){
246
0
        hi=j;
247
0
        hx=x;
248
0
      }
249
0
    }
250
0
    look->loneighbor[i]=lo;
251
0
    look->hineighbor[i]=hi;
252
0
  }
253
254
536
  return(look);
255
536
}
256
257
0
static int render_point(int x0,int x1,int y0,int y1,int x){
258
0
  y0&=0x7fff; /* mask off flag */
259
0
  y1&=0x7fff;
260
261
0
  {
262
0
    int dy=y1-y0;
263
0
    int adx=x1-x0;
264
0
    int ady=abs(dy);
265
0
    int err=ady*(x-x0);
266
267
0
    int off=err/adx;
268
0
    if(dy<0)return(y0-off);
269
0
    return(y0+off);
270
0
  }
271
0
}
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
97.1k
static void render_line(int n, int x0,int x1,int y0,int y1,float *d){
348
97.1k
  int dy=y1-y0;
349
97.1k
  int adx=x1-x0;
350
97.1k
  int ady=abs(dy);
351
97.1k
  int base=dy/adx;
352
97.1k
  int sy=(dy<0?base-1:base+1);
353
97.1k
  int x=x0;
354
97.1k
  int y=y0;
355
97.1k
  int err=0;
356
357
97.1k
  ady-=abs(base*adx);
358
359
97.1k
  if(n>x1)n=x1;
360
361
97.1k
  if(x<n)
362
97.1k
    d[x]*=FLOOR1_fromdB_LOOKUP[y];
363
364
4.41M
  while(++x<n){
365
4.31M
    err=err+ady;
366
4.31M
    if(err>=adx){
367
1.27M
      err-=adx;
368
1.27M
      y+=sy;
369
3.03M
    }else{
370
3.03M
      y+=base;
371
3.03M
    }
372
4.31M
    d[x]*=FLOOR1_fromdB_LOOKUP[y];
373
4.31M
  }
374
97.1k
}
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.09M
static void *floor1_inverse1(vorbis_block *vb,vorbis_look_floor *in){
956
2.09M
  vorbis_look_floor1 *look=(vorbis_look_floor1 *)in;
957
2.09M
  vorbis_info_floor1 *info=look->vi;
958
2.09M
  codec_setup_info   *ci=vb->vd->vi->codec_setup;
959
960
2.09M
  int i,j,k;
961
2.09M
  codebook *books=ci->fullbooks;
962
963
  /* unpack wrapped/predicted values from stream */
964
2.09M
  if(oggpack_read(&vb->opb,1)==1){
965
153k
    int *fit_value=_vorbis_block_alloc(vb,(look->posts)*sizeof(*fit_value));
966
967
153k
    fit_value[0]=oggpack_read(&vb->opb,ov_ilog(look->quant_q-1));
968
153k
    fit_value[1]=oggpack_read(&vb->opb,ov_ilog(look->quant_q-1));
969
970
    /* partition by partition */
971
153k
    for(i=0,j=2;i<info->partitions;i++){
972
0
      int class=info->partitionclass[i];
973
0
      int cdim=info->class_dim[class];
974
0
      int csubbits=info->class_subs[class];
975
0
      int csub=1<<csubbits;
976
0
      int cval=0;
977
978
      /* decode the partition's first stage cascade value */
979
0
      if(csubbits){
980
0
        cval=vorbis_book_decode(books+info->class_book[class],&vb->opb);
981
982
0
        if(cval==-1)goto eop;
983
0
      }
984
985
0
      for(k=0;k<cdim;k++){
986
0
        int book=info->class_subbook[class][cval&(csub-1)];
987
0
        cval>>=csubbits;
988
0
        if(book>=0){
989
0
          if((fit_value[j+k]=vorbis_book_decode(books+book,&vb->opb))==-1)
990
0
            goto eop;
991
0
        }else{
992
0
          fit_value[j+k]=0;
993
0
        }
994
0
      }
995
0
      j+=cdim;
996
0
    }
997
998
    /* unwrap positive values and reconsitute via linear interpolation */
999
153k
    for(i=2;i<look->posts;i++){
1000
0
      int predicted=render_point(info->postlist[look->loneighbor[i-2]],
1001
0
                                 info->postlist[look->hineighbor[i-2]],
1002
0
                                 fit_value[look->loneighbor[i-2]],
1003
0
                                 fit_value[look->hineighbor[i-2]],
1004
0
                                 info->postlist[i]);
1005
0
      int hiroom=look->quant_q-predicted;
1006
0
      int loroom=predicted;
1007
0
      int room=(hiroom<loroom?hiroom:loroom)<<1;
1008
0
      int val=fit_value[i];
1009
1010
0
      if(val){
1011
0
        if(val>=room){
1012
0
          if(hiroom>loroom){
1013
0
            val = val-loroom;
1014
0
          }else{
1015
0
            val = -1-(val-hiroom);
1016
0
          }
1017
0
        }else{
1018
0
          if(val&1){
1019
0
            val= -((val+1)>>1);
1020
0
          }else{
1021
0
            val>>=1;
1022
0
          }
1023
0
        }
1024
1025
0
        fit_value[i]=(val+predicted)&0x7fff;
1026
0
        fit_value[look->loneighbor[i-2]]&=0x7fff;
1027
0
        fit_value[look->hineighbor[i-2]]&=0x7fff;
1028
1029
0
      }else{
1030
0
        fit_value[i]=predicted|0x8000;
1031
0
      }
1032
1033
0
    }
1034
1035
153k
    return(fit_value);
1036
153k
  }
1037
1.94M
 eop:
1038
1.94M
  return(NULL);
1039
2.09M
}
1040
1041
static int floor1_inverse2(vorbis_block *vb,vorbis_look_floor *in,void *memo,
1042
2.09M
                          float *out){
1043
2.09M
  vorbis_look_floor1 *look=(vorbis_look_floor1 *)in;
1044
2.09M
  vorbis_info_floor1 *info=look->vi;
1045
1046
2.09M
  codec_setup_info   *ci=vb->vd->vi->codec_setup;
1047
2.09M
  int                  n=ci->blocksizes[vb->W]/2;
1048
2.09M
  int j;
1049
1050
2.09M
  if(memo){
1051
    /* render the lines */
1052
153k
    int *fit_value=(int *)memo;
1053
153k
    int hx=0;
1054
153k
    int lx=0;
1055
153k
    int ly=fit_value[0]*info->mult;
1056
    /* guard lookup against out-of-range values */
1057
153k
    ly=(ly<0?0:ly>255?255:ly);
1058
1059
306k
    for(j=1;j<look->posts;j++){
1060
153k
      int current=look->forward_index[j];
1061
153k
      int hy=fit_value[current]&0x7fff;
1062
153k
      if(hy==fit_value[current]){
1063
1064
97.1k
        hx=info->postlist[current];
1065
97.1k
        hy*=info->mult;
1066
        /* guard lookup against out-of-range values */
1067
97.1k
        hy=(hy<0?0:hy>255?255:hy);
1068
1069
97.1k
        render_line(n,lx,hx,ly,hy,out);
1070
1071
97.1k
        lx=hx;
1072
97.1k
        ly=hy;
1073
97.1k
      }
1074
153k
    }
1075
22.5M
    for(j=hx;j<n;j++)out[j]*=FLOOR1_fromdB_LOOKUP[ly]; /* be certain */
1076
153k
    return(1);
1077
153k
  }
1078
1.94M
  memset(out,0,sizeof(*out)*n);
1079
1.94M
  return(0);
1080
2.09M
}
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
};