Coverage Report

Created: 2026-02-14 06:59

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