Coverage Report

Created: 2026-05-23 07:06

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