Coverage Report

Created: 2025-08-28 07:12

/src/vorbis/lib/floor1.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 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
1.02k
static void floor1_free_info(vorbis_info_floor *i){
54
1.02k
  vorbis_info_floor1 *info=(vorbis_info_floor1 *)i;
55
1.02k
  if(info){
56
1.02k
    memset(info,0,sizeof(*info));
57
1.02k
    _ogg_free(info);
58
1.02k
  }
59
1.02k
}
60
61
586
static void floor1_free_look(vorbis_look_floor *i){
62
586
  vorbis_look_floor1 *look=(vorbis_look_floor1 *)i;
63
586
  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
586
    memset(look,0,sizeof(*look));
70
586
    _ogg_free(look);
71
586
  }
72
586
}
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.75k
static int icomp(const void *a,const void *b){
113
2.75k
  return(**(int **)a-**(int **)b);
114
2.75k
}
115
116
1.02k
static vorbis_info_floor *floor1_unpack (vorbis_info *vi,oggpack_buffer *opb){
117
1.02k
  codec_setup_info     *ci=vi->codec_setup;
118
1.02k
  int j,k,count=0,maxclass=-1,rangebits;
119
120
1.02k
  vorbis_info_floor1 *info=_ogg_calloc(1,sizeof(*info));
121
  /* read partitions */
122
1.02k
  info->partitions=oggpack_read(opb,5); /* only 0 to 31 legal */
123
1.78k
  for(j=0;j<info->partitions;j++){
124
769
    info->partitionclass[j]=oggpack_read(opb,4); /* only 0 to 15 legal */
125
769
    if(info->partitionclass[j]<0)goto err_out;
126
765
    if(maxclass<info->partitionclass[j])maxclass=info->partitionclass[j];
127
765
  }
128
129
  /* read partition classes */
130
1.22k
  for(j=0;j<maxclass+1;j++){
131
246
    info->class_dim[j]=oggpack_read(opb,3)+1; /* 1 to 8 */
132
246
    info->class_subs[j]=oggpack_read(opb,2); /* 0,1,2,3 bits */
133
246
    if(info->class_subs[j]<0)
134
3
      goto err_out;
135
243
    if(info->class_subs[j])info->class_book[j]=oggpack_read(opb,8);
136
243
    if(info->class_book[j]<0 || info->class_book[j]>=ci->books)
137
19
      goto err_out;
138
460
    for(k=0;k<(1<<info->class_subs[j]);k++){
139
259
      info->class_subbook[j][k]=oggpack_read(opb,8)-1;
140
259
      if(info->class_subbook[j][k]<-1 || info->class_subbook[j][k]>=ci->books)
141
23
        goto err_out;
142
259
    }
143
224
  }
144
145
  /* read the post list */
146
974
  info->mult=oggpack_read(opb,2)+1;     /* only 1,2,3,4 legal now */
147
974
  rangebits=oggpack_read(opb,4);
148
974
  if(rangebits<0)goto err_out;
149
150
1.21k
  for(j=0,k=0;j<info->partitions;j++){
151
254
    count+=info->class_dim[info->partitionclass[j]];
152
254
    if(count>VIF_POSIT) goto err_out;
153
698
    for(;k<count;k++){
154
455
      int t=info->postlist[k+2]=oggpack_read(opb,rangebits);
155
455
      if(t<0 || t>=(1<<rangebits))
156
10
        goto err_out;
157
455
    }
158
253
  }
159
962
  info->postlist[0]=0;
160
962
  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
962
  {
165
962
    int *sortpointer[VIF_POSIT+2];
166
3.25k
    for(j=0;j<count+2;j++)sortpointer[j]=info->postlist+j;
167
962
    qsort(sortpointer,count+2,sizeof(*sortpointer),icomp);
168
169
1.95k
    for(j=1;j<count+2;j++)
170
1.01k
      if(*sortpointer[j-1]==*sortpointer[j])goto err_out;
171
962
  }
172
173
939
  return(info);
174
175
84
 err_out:
176
84
  floor1_free_info(info);
177
84
  return(NULL);
178
962
}
179
180
static vorbis_look_floor *floor1_look(vorbis_dsp_state *vd,
181
586
                                      vorbis_info_floor *in){
182
183
586
  int *sortpointer[VIF_POSIT+2];
184
586
  vorbis_info_floor1 *info=(vorbis_info_floor1 *)in;
185
586
  vorbis_look_floor1 *look=_ogg_calloc(1,sizeof(*look));
186
586
  int i,j,n=0;
187
188
586
  (void)vd;
189
190
586
  look->vi=info;
191
586
  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
586
  for(i=0;i<info->partitions;i++)n+=info->class_dim[info->partitionclass[i]];
201
586
  n+=2;
202
586
  look->posts=n;
203
204
  /* also store a sorted position index */
205
1.75k
  for(i=0;i<n;i++)sortpointer[i]=info->postlist+i;
206
586
  qsort(sortpointer,n,sizeof(*sortpointer),icomp);
207
208
  /* points from sort order back to range number */
209
1.75k
  for(i=0;i<n;i++)look->forward_index[i]=sortpointer[i]-info->postlist;
210
  /* points from range order to sorted position */
211
1.75k
  for(i=0;i<n;i++)look->reverse_index[look->forward_index[i]]=i;
212
  /* we actually need the post values too */
213
1.75k
  for(i=0;i<n;i++)look->sorted_index[i]=info->postlist[look->forward_index[i]];
214
215
  /* quantize values to multiplier spec */
216
586
  switch(info->mult){
217
53
  case 1: /* 1024 -> 256 */
218
53
    look->quant_q=256;
219
53
    break;
220
418
  case 2: /* 1024 -> 128 */
221
418
    look->quant_q=128;
222
418
    break;
223
34
  case 3: /* 1024 -> 86 */
224
34
    look->quant_q=86;
225
34
    break;
226
81
  case 4: /* 1024 -> 64 */
227
81
    look->quant_q=64;
228
81
    break;
229
586
  }
230
231
  /* discover our neighbors for decode where we don't use fit flags
232
     (that would push the neighbors outward) */
233
586
  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
586
  return(look);
255
586
}
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
179k
static void render_line(int n, int x0,int x1,int y0,int y1,float *d){
348
179k
  int dy=y1-y0;
349
179k
  int adx=x1-x0;
350
179k
  int ady=abs(dy);
351
179k
  int base=dy/adx;
352
179k
  int sy=(dy<0?base-1:base+1);
353
179k
  int x=x0;
354
179k
  int y=y0;
355
179k
  int err=0;
356
357
179k
  ady-=abs(base*adx);
358
359
179k
  if(n>x1)n=x1;
360
361
179k
  if(x<n)
362
179k
    d[x]*=FLOOR1_fromdB_LOOKUP[y];
363
364
9.88M
  while(++x<n){
365
9.70M
    err=err+ady;
366
9.70M
    if(err>=adx){
367
3.53M
      err-=adx;
368
3.53M
      y+=sy;
369
6.16M
    }else{
370
6.16M
      y+=base;
371
6.16M
    }
372
9.70M
    d[x]*=FLOOR1_fromdB_LOOKUP[y];
373
9.70M
  }
374
179k
}
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<<1);
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
3.64M
static void *floor1_inverse1(vorbis_block *vb,vorbis_look_floor *in){
956
3.64M
  vorbis_look_floor1 *look=(vorbis_look_floor1 *)in;
957
3.64M
  vorbis_info_floor1 *info=look->vi;
958
3.64M
  codec_setup_info   *ci=vb->vd->vi->codec_setup;
959
960
3.64M
  int i,j,k;
961
3.64M
  codebook *books=ci->fullbooks;
962
963
  /* unpack wrapped/predicted values from stream */
964
3.64M
  if(oggpack_read(&vb->opb,1)==1){
965
206k
    int *fit_value=_vorbis_block_alloc(vb,(look->posts)*sizeof(*fit_value));
966
967
206k
    fit_value[0]=oggpack_read(&vb->opb,ov_ilog(look->quant_q-1));
968
206k
    fit_value[1]=oggpack_read(&vb->opb,ov_ilog(look->quant_q-1));
969
970
    /* partition by partition */
971
206k
    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
206k
    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
206k
    return(fit_value);
1036
206k
  }
1037
3.43M
 eop:
1038
3.43M
  return(NULL);
1039
3.64M
}
1040
1041
static int floor1_inverse2(vorbis_block *vb,vorbis_look_floor *in,void *memo,
1042
3.64M
                          float *out){
1043
3.64M
  vorbis_look_floor1 *look=(vorbis_look_floor1 *)in;
1044
3.64M
  vorbis_info_floor1 *info=look->vi;
1045
1046
3.64M
  codec_setup_info   *ci=vb->vd->vi->codec_setup;
1047
3.64M
  int                  n=ci->blocksizes[vb->W]/2;
1048
3.64M
  int j;
1049
1050
3.64M
  if(memo){
1051
    /* render the lines */
1052
206k
    int *fit_value=(int *)memo;
1053
206k
    int hx=0;
1054
206k
    int lx=0;
1055
206k
    int ly=fit_value[0]*info->mult;
1056
    /* guard lookup against out-of-range values */
1057
206k
    ly=(ly<0?0:ly>255?255:ly);
1058
1059
412k
    for(j=1;j<look->posts;j++){
1060
206k
      int current=look->forward_index[j];
1061
206k
      int hy=fit_value[current]&0x7fff;
1062
206k
      if(hy==fit_value[current]){
1063
1064
179k
        hx=info->postlist[current];
1065
179k
        hy*=info->mult;
1066
        /* guard lookup against out-of-range values */
1067
179k
        hy=(hy<0?0:hy>255?255:hy);
1068
1069
179k
        render_line(n,lx,hx,ly,hy,out);
1070
1071
179k
        lx=hx;
1072
179k
        ly=hy;
1073
179k
      }
1074
206k
    }
1075
18.4M
    for(j=hx;j<n;j++)out[j]*=FLOOR1_fromdB_LOOKUP[ly]; /* be certain */
1076
206k
    return(1);
1077
206k
  }
1078
3.43M
  memset(out,0,sizeof(*out)*n);
1079
3.43M
  return(0);
1080
3.64M
}
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
};