annotate src/libvorbis-1.3.3/lib/floor1.c @ 83:ae30d91d2ffe

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