Blame lib/floor1.c

Packit 06404a
/********************************************************************
Packit 06404a
 *                                                                  *
Packit 06404a
 * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
Packit 06404a
 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
Packit 06404a
 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
Packit 06404a
 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
Packit 06404a
 *                                                                  *
Packit 06404a
 * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2015             *
Packit 06404a
 * by the Xiph.Org Foundation http://www.xiph.org/                  *
Packit 06404a
 *                                                                  *
Packit 06404a
 ********************************************************************
Packit 06404a
Packit 06404a
 function: floor backend 1 implementation
Packit 06404a
 last mod: $Id: floor1.c 19457 2015-03-03 00:15:29Z giles $
Packit 06404a
Packit 06404a
 ********************************************************************/
Packit 06404a
Packit 06404a
#include <stdlib.h>
Packit 06404a
#include <string.h>
Packit 06404a
#include <math.h>
Packit 06404a
#include <ogg/ogg.h>
Packit 06404a
#include "vorbis/codec.h"
Packit 06404a
#include "codec_internal.h"
Packit 06404a
#include "registry.h"
Packit 06404a
#include "codebook.h"
Packit 06404a
#include "misc.h"
Packit 06404a
#include "scales.h"
Packit 06404a
Packit 06404a
#include <stdio.h>
Packit 06404a
Packit 06404a
#define floor1_rangedB 140 /* floor 1 fixed at -140dB to 0dB range */
Packit 06404a
Packit 06404a
typedef struct lsfit_acc{
Packit 06404a
  int x0;
Packit 06404a
  int x1;
Packit 06404a
Packit 06404a
  int xa;
Packit 06404a
  int ya;
Packit 06404a
  int x2a;
Packit 06404a
  int y2a;
Packit 06404a
  int xya;
Packit 06404a
  int an;
Packit 06404a
Packit 06404a
  int xb;
Packit 06404a
  int yb;
Packit 06404a
  int x2b;
Packit 06404a
  int y2b;
Packit 06404a
  int xyb;
Packit 06404a
  int bn;
Packit 06404a
} lsfit_acc;
Packit 06404a
Packit 06404a
/***********************************************/
Packit 06404a
Packit 06404a
static void floor1_free_info(vorbis_info_floor *i){
Packit 06404a
  vorbis_info_floor1 *info=(vorbis_info_floor1 *)i;
Packit 06404a
  if(info){
Packit 06404a
    memset(info,0,sizeof(*info));
Packit 06404a
    _ogg_free(info);
Packit 06404a
  }
Packit 06404a
}
Packit 06404a
Packit 06404a
static void floor1_free_look(vorbis_look_floor *i){
Packit 06404a
  vorbis_look_floor1 *look=(vorbis_look_floor1 *)i;
Packit 06404a
  if(look){
Packit 06404a
    /*fprintf(stderr,"floor 1 bit usage %f:%f (%f total)\n",
Packit 06404a
            (float)look->phrasebits/look->frames,
Packit 06404a
            (float)look->postbits/look->frames,
Packit 06404a
            (float)(look->postbits+look->phrasebits)/look->frames);*/
Packit 06404a
Packit 06404a
    memset(look,0,sizeof(*look));
Packit 06404a
    _ogg_free(look);
Packit 06404a
  }
Packit 06404a
}
Packit 06404a
Packit 06404a
static void floor1_pack (vorbis_info_floor *i,oggpack_buffer *opb){
Packit 06404a
  vorbis_info_floor1 *info=(vorbis_info_floor1 *)i;
Packit 06404a
  int j,k;
Packit 06404a
  int count=0;
Packit 06404a
  int rangebits;
Packit 06404a
  int maxposit=info->postlist[1];
Packit 06404a
  int maxclass=-1;
Packit 06404a
Packit 06404a
  /* save out partitions */
Packit 06404a
  oggpack_write(opb,info->partitions,5); /* only 0 to 31 legal */
Packit 06404a
  for(j=0;j<info->partitions;j++){
Packit 06404a
    oggpack_write(opb,info->partitionclass[j],4); /* only 0 to 15 legal */
Packit 06404a
    if(maxclass<info->partitionclass[j])maxclass=info->partitionclass[j];
Packit 06404a
  }
Packit 06404a
Packit 06404a
  /* save out partition classes */
Packit 06404a
  for(j=0;j
Packit 06404a
    oggpack_write(opb,info->class_dim[j]-1,3); /* 1 to 8 */
Packit 06404a
    oggpack_write(opb,info->class_subs[j],2); /* 0 to 3 */
Packit 06404a
    if(info->class_subs[j])oggpack_write(opb,info->class_book[j],8);
Packit 06404a
    for(k=0;k<(1<<info->class_subs[j]);k++)
Packit 06404a
      oggpack_write(opb,info->class_subbook[j][k]+1,8);
Packit 06404a
  }
Packit 06404a
Packit 06404a
  /* save out the post list */
Packit 06404a
  oggpack_write(opb,info->mult-1,2);     /* only 1,2,3,4 legal now */
Packit 06404a
  /* maxposit cannot legally be less than 1; this is encode-side, we
Packit 06404a
     can assume our setup is OK */
Packit 06404a
  oggpack_write(opb,ov_ilog(maxposit-1),4);
Packit 06404a
  rangebits=ov_ilog(maxposit-1);
Packit 06404a
Packit 06404a
  for(j=0,k=0;j<info->partitions;j++){
Packit 06404a
    count+=info->class_dim[info->partitionclass[j]];
Packit 06404a
    for(;k
Packit 06404a
      oggpack_write(opb,info->postlist[k+2],rangebits);
Packit 06404a
  }
Packit 06404a
}
Packit 06404a
Packit 06404a
static int icomp(const void *a,const void *b){
Packit 06404a
  return(**(int **)a-**(int **)b);
Packit 06404a
}
Packit 06404a
Packit 06404a
static vorbis_info_floor *floor1_unpack (vorbis_info *vi,oggpack_buffer *opb){
Packit 06404a
  codec_setup_info     *ci=vi->codec_setup;
Packit 06404a
  int j,k,count=0,maxclass=-1,rangebits;
Packit 06404a
Packit 06404a
  vorbis_info_floor1 *info=_ogg_calloc(1,sizeof(*info));
Packit 06404a
  /* read partitions */
Packit 06404a
  info->partitions=oggpack_read(opb,5); /* only 0 to 31 legal */
Packit 06404a
  for(j=0;j<info->partitions;j++){
Packit 06404a
    info->partitionclass[j]=oggpack_read(opb,4); /* only 0 to 15 legal */
Packit 06404a
    if(info->partitionclass[j]<0)goto err_out;
Packit 06404a
    if(maxclass<info->partitionclass[j])maxclass=info->partitionclass[j];
Packit 06404a
  }
Packit 06404a
Packit 06404a
  /* read partition classes */
Packit 06404a
  for(j=0;j
Packit 06404a
    info->class_dim[j]=oggpack_read(opb,3)+1; /* 1 to 8 */
Packit 06404a
    info->class_subs[j]=oggpack_read(opb,2); /* 0,1,2,3 bits */
Packit 06404a
    if(info->class_subs[j]<0)
Packit 06404a
      goto err_out;
Packit 06404a
    if(info->class_subs[j])info->class_book[j]=oggpack_read(opb,8);
Packit 06404a
    if(info->class_book[j]<0 || info->class_book[j]>=ci->books)
Packit 06404a
      goto err_out;
Packit 06404a
    for(k=0;k<(1<<info->class_subs[j]);k++){
Packit 06404a
      info->class_subbook[j][k]=oggpack_read(opb,8)-1;
Packit 06404a
      if(info->class_subbook[j][k]<-1 || info->class_subbook[j][k]>=ci->books)
Packit 06404a
        goto err_out;
Packit 06404a
    }
Packit 06404a
  }
Packit 06404a
Packit 06404a
  /* read the post list */
Packit 06404a
  info->mult=oggpack_read(opb,2)+1;     /* only 1,2,3,4 legal now */
Packit 06404a
  rangebits=oggpack_read(opb,4);
Packit 06404a
  if(rangebits<0)goto err_out;
Packit 06404a
Packit 06404a
  for(j=0,k=0;j<info->partitions;j++){
Packit 06404a
    count+=info->class_dim[info->partitionclass[j]];
Packit 06404a
    if(count>VIF_POSIT) goto err_out;
Packit 06404a
    for(;k
Packit 06404a
      int t=info->postlist[k+2]=oggpack_read(opb,rangebits);
Packit 06404a
      if(t<0 || t>=(1<
Packit 06404a
        goto err_out;
Packit 06404a
    }
Packit 06404a
  }
Packit 06404a
  info->postlist[0]=0;
Packit 06404a
  info->postlist[1]=1<
Packit 06404a
Packit 06404a
  /* don't allow repeated values in post list as they'd result in
Packit 06404a
     zero-length segments */
Packit 06404a
  {
Packit 06404a
    int *sortpointer[VIF_POSIT+2];
Packit 06404a
    for(j=0;j<count+2;j++)sortpointer[j]=info->postlist+j;
Packit 06404a
    qsort(sortpointer,count+2,sizeof(*sortpointer),icomp);
Packit 06404a
Packit 06404a
    for(j=1;j
Packit 06404a
      if(*sortpointer[j-1]==*sortpointer[j])goto err_out;
Packit 06404a
  }
Packit 06404a
Packit 06404a
  return(info);
Packit 06404a
Packit 06404a
 err_out:
Packit 06404a
  floor1_free_info(info);
Packit 06404a
  return(NULL);
Packit 06404a
}
Packit 06404a
Packit 06404a
static vorbis_look_floor *floor1_look(vorbis_dsp_state *vd,
Packit 06404a
                                      vorbis_info_floor *in){
Packit 06404a
Packit 06404a
  int *sortpointer[VIF_POSIT+2];
Packit 06404a
  vorbis_info_floor1 *info=(vorbis_info_floor1 *)in;
Packit 06404a
  vorbis_look_floor1 *look=_ogg_calloc(1,sizeof(*look));
Packit 06404a
  int i,j,n=0;
Packit 06404a
Packit 06404a
  (void)vd;
Packit 06404a
Packit 06404a
  look->vi=info;
Packit 06404a
  look->n=info->postlist[1];
Packit 06404a
Packit 06404a
  /* we drop each position value in-between already decoded values,
Packit 06404a
     and use linear interpolation to predict each new value past the
Packit 06404a
     edges.  The positions are read in the order of the position
Packit 06404a
     list... we precompute the bounding positions in the lookup.  Of
Packit 06404a
     course, the neighbors can change (if a position is declined), but
Packit 06404a
     this is an initial mapping */
Packit 06404a
Packit 06404a
  for(i=0;i<info->partitions;i++)n+=info->class_dim[info->partitionclass[i]];
Packit 06404a
  n+=2;
Packit 06404a
  look->posts=n;
Packit 06404a
Packit 06404a
  /* also store a sorted position index */
Packit 06404a
  for(i=0;i<n;i++)sortpointer[i]=info->postlist+i;
Packit 06404a
  qsort(sortpointer,n,sizeof(*sortpointer),icomp);
Packit 06404a
Packit 06404a
  /* points from sort order back to range number */
Packit 06404a
  for(i=0;i<n;i++)look->forward_index[i]=sortpointer[i]-info->postlist;
Packit 06404a
  /* points from range order to sorted position */
Packit 06404a
  for(i=0;i<n;i++)look->reverse_index[look->forward_index[i]]=i;
Packit 06404a
  /* we actually need the post values too */
Packit 06404a
  for(i=0;i<n;i++)look->sorted_index[i]=info->postlist[look->forward_index[i]];
Packit 06404a
Packit 06404a
  /* quantize values to multiplier spec */
Packit 06404a
  switch(info->mult){
Packit 06404a
  case 1: /* 1024 -> 256 */
Packit 06404a
    look->quant_q=256;
Packit 06404a
    break;
Packit 06404a
  case 2: /* 1024 -> 128 */
Packit 06404a
    look->quant_q=128;
Packit 06404a
    break;
Packit 06404a
  case 3: /* 1024 -> 86 */
Packit 06404a
    look->quant_q=86;
Packit 06404a
    break;
Packit 06404a
  case 4: /* 1024 -> 64 */
Packit 06404a
    look->quant_q=64;
Packit 06404a
    break;
Packit 06404a
  }
Packit 06404a
Packit 06404a
  /* discover our neighbors for decode where we don't use fit flags
Packit 06404a
     (that would push the neighbors outward) */
Packit 06404a
  for(i=0;i
Packit 06404a
    int lo=0;
Packit 06404a
    int hi=1;
Packit 06404a
    int lx=0;
Packit 06404a
    int hx=look->n;
Packit 06404a
    int currentx=info->postlist[i+2];
Packit 06404a
    for(j=0;j
Packit 06404a
      int x=info->postlist[j];
Packit 06404a
      if(x>lx && x
Packit 06404a
        lo=j;
Packit 06404a
        lx=x;
Packit 06404a
      }
Packit 06404a
      if(x<hx && x>currentx){
Packit 06404a
        hi=j;
Packit 06404a
        hx=x;
Packit 06404a
      }
Packit 06404a
    }
Packit 06404a
    look->loneighbor[i]=lo;
Packit 06404a
    look->hineighbor[i]=hi;
Packit 06404a
  }
Packit 06404a
Packit 06404a
  return(look);
Packit 06404a
}
Packit 06404a
Packit 06404a
static int render_point(int x0,int x1,int y0,int y1,int x){
Packit 06404a
  y0&=0x7fff; /* mask off flag */
Packit 06404a
  y1&=0x7fff;
Packit 06404a
Packit 06404a
  {
Packit 06404a
    int dy=y1-y0;
Packit 06404a
    int adx=x1-x0;
Packit 06404a
    int ady=abs(dy);
Packit 06404a
    int err=ady*(x-x0);
Packit 06404a
Packit 06404a
    int off=err/adx;
Packit 06404a
    if(dy<0)return(y0-off);
Packit 06404a
    return(y0+off);
Packit 06404a
  }
Packit 06404a
}
Packit 06404a
Packit 06404a
static int vorbis_dBquant(const float *x){
Packit 06404a
  int i= *x*7.3142857f+1023.5f;
Packit 06404a
  if(i>1023)return(1023);
Packit 06404a
  if(i<0)return(0);
Packit 06404a
  return i;
Packit 06404a
}
Packit 06404a
Packit 06404a
static const float FLOOR1_fromdB_LOOKUP[256]={
Packit 06404a
  1.0649863e-07F, 1.1341951e-07F, 1.2079015e-07F, 1.2863978e-07F,
Packit 06404a
  1.3699951e-07F, 1.4590251e-07F, 1.5538408e-07F, 1.6548181e-07F,
Packit 06404a
  1.7623575e-07F, 1.8768855e-07F, 1.9988561e-07F, 2.128753e-07F,
Packit 06404a
  2.2670913e-07F, 2.4144197e-07F, 2.5713223e-07F, 2.7384213e-07F,
Packit 06404a
  2.9163793e-07F, 3.1059021e-07F, 3.3077411e-07F, 3.5226968e-07F,
Packit 06404a
  3.7516214e-07F, 3.9954229e-07F, 4.2550680e-07F, 4.5315863e-07F,
Packit 06404a
  4.8260743e-07F, 5.1396998e-07F, 5.4737065e-07F, 5.8294187e-07F,
Packit 06404a
  6.2082472e-07F, 6.6116941e-07F, 7.0413592e-07F, 7.4989464e-07F,
Packit 06404a
  7.9862701e-07F, 8.5052630e-07F, 9.0579828e-07F, 9.6466216e-07F,
Packit 06404a
  1.0273513e-06F, 1.0941144e-06F, 1.1652161e-06F, 1.2409384e-06F,
Packit 06404a
  1.3215816e-06F, 1.4074654e-06F, 1.4989305e-06F, 1.5963394e-06F,
Packit 06404a
  1.7000785e-06F, 1.8105592e-06F, 1.9282195e-06F, 2.0535261e-06F,
Packit 06404a
  2.1869758e-06F, 2.3290978e-06F, 2.4804557e-06F, 2.6416497e-06F,
Packit 06404a
  2.8133190e-06F, 2.9961443e-06F, 3.1908506e-06F, 3.3982101e-06F,
Packit 06404a
  3.6190449e-06F, 3.8542308e-06F, 4.1047004e-06F, 4.3714470e-06F,
Packit 06404a
  4.6555282e-06F, 4.9580707e-06F, 5.2802740e-06F, 5.6234160e-06F,
Packit 06404a
  5.9888572e-06F, 6.3780469e-06F, 6.7925283e-06F, 7.2339451e-06F,
Packit 06404a
  7.7040476e-06F, 8.2047000e-06F, 8.7378876e-06F, 9.3057248e-06F,
Packit 06404a
  9.9104632e-06F, 1.0554501e-05F, 1.1240392e-05F, 1.1970856e-05F,
Packit 06404a
  1.2748789e-05F, 1.3577278e-05F, 1.4459606e-05F, 1.5399272e-05F,
Packit 06404a
  1.6400004e-05F, 1.7465768e-05F, 1.8600792e-05F, 1.9809576e-05F,
Packit 06404a
  2.1096914e-05F, 2.2467911e-05F, 2.3928002e-05F, 2.5482978e-05F,
Packit 06404a
  2.7139006e-05F, 2.8902651e-05F, 3.0780908e-05F, 3.2781225e-05F,
Packit 06404a
  3.4911534e-05F, 3.7180282e-05F, 3.9596466e-05F, 4.2169667e-05F,
Packit 06404a
  4.4910090e-05F, 4.7828601e-05F, 5.0936773e-05F, 5.4246931e-05F,
Packit 06404a
  5.7772202e-05F, 6.1526565e-05F, 6.5524908e-05F, 6.9783085e-05F,
Packit 06404a
  7.4317983e-05F, 7.9147585e-05F, 8.4291040e-05F, 8.9768747e-05F,
Packit 06404a
  9.5602426e-05F, 0.00010181521F, 0.00010843174F, 0.00011547824F,
Packit 06404a
  0.00012298267F, 0.00013097477F, 0.00013948625F, 0.00014855085F,
Packit 06404a
  0.00015820453F, 0.00016848555F, 0.00017943469F, 0.00019109536F,
Packit 06404a
  0.00020351382F, 0.00021673929F, 0.00023082423F, 0.00024582449F,
Packit 06404a
  0.00026179955F, 0.00027881276F, 0.00029693158F, 0.00031622787F,
Packit 06404a
  0.00033677814F, 0.00035866388F, 0.00038197188F, 0.00040679456F,
Packit 06404a
  0.00043323036F, 0.00046138411F, 0.00049136745F, 0.00052329927F,
Packit 06404a
  0.00055730621F, 0.00059352311F, 0.00063209358F, 0.00067317058F,
Packit 06404a
  0.00071691700F, 0.00076350630F, 0.00081312324F, 0.00086596457F,
Packit 06404a
  0.00092223983F, 0.00098217216F, 0.0010459992F, 0.0011139742F,
Packit 06404a
  0.0011863665F, 0.0012634633F, 0.0013455702F, 0.0014330129F,
Packit 06404a
  0.0015261382F, 0.0016253153F, 0.0017309374F, 0.0018434235F,
Packit 06404a
  0.0019632195F, 0.0020908006F, 0.0022266726F, 0.0023713743F,
Packit 06404a
  0.0025254795F, 0.0026895994F, 0.0028643847F, 0.0030505286F,
Packit 06404a
  0.0032487691F, 0.0034598925F, 0.0036847358F, 0.0039241906F,
Packit 06404a
  0.0041792066F, 0.0044507950F, 0.0047400328F, 0.0050480668F,
Packit 06404a
  0.0053761186F, 0.0057254891F, 0.0060975636F, 0.0064938176F,
Packit 06404a
  0.0069158225F, 0.0073652516F, 0.0078438871F, 0.0083536271F,
Packit 06404a
  0.0088964928F, 0.009474637F, 0.010090352F, 0.010746080F,
Packit 06404a
  0.011444421F, 0.012188144F, 0.012980198F, 0.013823725F,
Packit 06404a
  0.014722068F, 0.015678791F, 0.016697687F, 0.017782797F,
Packit 06404a
  0.018938423F, 0.020169149F, 0.021479854F, 0.022875735F,
Packit 06404a
  0.024362330F, 0.025945531F, 0.027631618F, 0.029427276F,
Packit 06404a
  0.031339626F, 0.033376252F, 0.035545228F, 0.037855157F,
Packit 06404a
  0.040315199F, 0.042935108F, 0.045725273F, 0.048696758F,
Packit 06404a
  0.051861348F, 0.055231591F, 0.058820850F, 0.062643361F,
Packit 06404a
  0.066714279F, 0.071049749F, 0.075666962F, 0.080584227F,
Packit 06404a
  0.085821044F, 0.091398179F, 0.097337747F, 0.10366330F,
Packit 06404a
  0.11039993F, 0.11757434F, 0.12521498F, 0.13335215F,
Packit 06404a
  0.14201813F, 0.15124727F, 0.16107617F, 0.17154380F,
Packit 06404a
  0.18269168F, 0.19456402F, 0.20720788F, 0.22067342F,
Packit 06404a
  0.23501402F, 0.25028656F, 0.26655159F, 0.28387361F,
Packit 06404a
  0.30232132F, 0.32196786F, 0.34289114F, 0.36517414F,
Packit 06404a
  0.38890521F, 0.41417847F, 0.44109412F, 0.46975890F,
Packit 06404a
  0.50028648F, 0.53279791F, 0.56742212F, 0.60429640F,
Packit 06404a
  0.64356699F, 0.68538959F, 0.72993007F, 0.77736504F,
Packit 06404a
  0.82788260F, 0.88168307F, 0.9389798F, 1.F,
Packit 06404a
};
Packit 06404a
Packit 06404a
static void render_line(int n, int x0,int x1,int y0,int y1,float *d){
Packit 06404a
  int dy=y1-y0;
Packit 06404a
  int adx=x1-x0;
Packit 06404a
  int ady=abs(dy);
Packit 06404a
  int base=dy/adx;
Packit 06404a
  int sy=(dy<0?base-1:base+1);
Packit 06404a
  int x=x0;
Packit 06404a
  int y=y0;
Packit 06404a
  int err=0;
Packit 06404a
Packit 06404a
  ady-=abs(base*adx);
Packit 06404a
Packit 06404a
  if(n>x1)n=x1;
Packit 06404a
Packit 06404a
  if(x
Packit 06404a
    d[x]*=FLOOR1_fromdB_LOOKUP[y];
Packit 06404a
Packit 06404a
  while(++x
Packit 06404a
    err=err+ady;
Packit 06404a
    if(err>=adx){
Packit 06404a
      err-=adx;
Packit 06404a
      y+=sy;
Packit 06404a
    }else{
Packit 06404a
      y+=base;
Packit 06404a
    }
Packit 06404a
    d[x]*=FLOOR1_fromdB_LOOKUP[y];
Packit 06404a
  }
Packit 06404a
}
Packit 06404a
Packit 06404a
static void render_line0(int n, int x0,int x1,int y0,int y1,int *d){
Packit 06404a
  int dy=y1-y0;
Packit 06404a
  int adx=x1-x0;
Packit 06404a
  int ady=abs(dy);
Packit 06404a
  int base=dy/adx;
Packit 06404a
  int sy=(dy<0?base-1:base+1);
Packit 06404a
  int x=x0;
Packit 06404a
  int y=y0;
Packit 06404a
  int err=0;
Packit 06404a
Packit 06404a
  ady-=abs(base*adx);
Packit 06404a
Packit 06404a
  if(n>x1)n=x1;
Packit 06404a
Packit 06404a
  if(x
Packit 06404a
    d[x]=y;
Packit 06404a
Packit 06404a
  while(++x
Packit 06404a
    err=err+ady;
Packit 06404a
    if(err>=adx){
Packit 06404a
      err-=adx;
Packit 06404a
      y+=sy;
Packit 06404a
    }else{
Packit 06404a
      y+=base;
Packit 06404a
    }
Packit 06404a
    d[x]=y;
Packit 06404a
  }
Packit 06404a
}
Packit 06404a
Packit 06404a
/* the floor has already been filtered to only include relevant sections */
Packit 06404a
static int accumulate_fit(const float *flr,const float *mdct,
Packit 06404a
                          int x0, int x1,lsfit_acc *a,
Packit 06404a
                          int n,vorbis_info_floor1 *info){
Packit 06404a
  long i;
Packit 06404a
Packit 06404a
  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;
Packit 06404a
Packit 06404a
  memset(a,0,sizeof(*a));
Packit 06404a
  a->x0=x0;
Packit 06404a
  a->x1=x1;
Packit 06404a
  if(x1>=n)x1=n-1;
Packit 06404a
Packit 06404a
  for(i=x0;i<=x1;i++){
Packit 06404a
    int quantized=vorbis_dBquant(flr+i);
Packit 06404a
    if(quantized){
Packit 06404a
      if(mdct[i]+info->twofitatten>=flr[i]){
Packit 06404a
        xa  += i;
Packit 06404a
        ya  += quantized;
Packit 06404a
        x2a += i*i;
Packit 06404a
        y2a += quantized*quantized;
Packit 06404a
        xya += i*quantized;
Packit 06404a
        na++;
Packit 06404a
      }else{
Packit 06404a
        xb  += i;
Packit 06404a
        yb  += quantized;
Packit 06404a
        x2b += i*i;
Packit 06404a
        y2b += quantized*quantized;
Packit 06404a
        xyb += i*quantized;
Packit 06404a
        nb++;
Packit 06404a
      }
Packit 06404a
    }
Packit 06404a
  }
Packit 06404a
Packit 06404a
  a->xa=xa;
Packit 06404a
  a->ya=ya;
Packit 06404a
  a->x2a=x2a;
Packit 06404a
  a->y2a=y2a;
Packit 06404a
  a->xya=xya;
Packit 06404a
  a->an=na;
Packit 06404a
Packit 06404a
  a->xb=xb;
Packit 06404a
  a->yb=yb;
Packit 06404a
  a->x2b=x2b;
Packit 06404a
  a->y2b=y2b;
Packit 06404a
  a->xyb=xyb;
Packit 06404a
  a->bn=nb;
Packit 06404a
Packit 06404a
  return(na);
Packit 06404a
}
Packit 06404a
Packit 06404a
static int fit_line(lsfit_acc *a,int fits,int *y0,int *y1,
Packit 06404a
                    vorbis_info_floor1 *info){
Packit 06404a
  double xb=0,yb=0,x2b=0,y2b=0,xyb=0,bn=0;
Packit 06404a
  int i;
Packit 06404a
  int x0=a[0].x0;
Packit 06404a
  int x1=a[fits-1].x1;
Packit 06404a
Packit 06404a
  for(i=0;i
Packit 06404a
    double weight = (a[i].bn+a[i].an)*info->twofitweight/(a[i].an+1)+1.;
Packit 06404a
Packit 06404a
    xb+=a[i].xb + a[i].xa * weight;
Packit 06404a
    yb+=a[i].yb + a[i].ya * weight;
Packit 06404a
    x2b+=a[i].x2b + a[i].x2a * weight;
Packit 06404a
    y2b+=a[i].y2b + a[i].y2a * weight;
Packit 06404a
    xyb+=a[i].xyb + a[i].xya * weight;
Packit 06404a
    bn+=a[i].bn + a[i].an * weight;
Packit 06404a
  }
Packit 06404a
Packit 06404a
  if(*y0>=0){
Packit 06404a
    xb+=   x0;
Packit 06404a
    yb+=  *y0;
Packit 06404a
    x2b+=  x0 *  x0;
Packit 06404a
    y2b+= *y0 * *y0;
Packit 06404a
    xyb+= *y0 *  x0;
Packit 06404a
    bn++;
Packit 06404a
  }
Packit 06404a
Packit 06404a
  if(*y1>=0){
Packit 06404a
    xb+=   x1;
Packit 06404a
    yb+=  *y1;
Packit 06404a
    x2b+=  x1 *  x1;
Packit 06404a
    y2b+= *y1 * *y1;
Packit 06404a
    xyb+= *y1 *  x1;
Packit 06404a
    bn++;
Packit 06404a
  }
Packit 06404a
Packit 06404a
  {
Packit 06404a
    double denom=(bn*x2b-xb*xb);
Packit 06404a
Packit 06404a
    if(denom>0.){
Packit 06404a
      double a=(yb*x2b-xyb*xb)/denom;
Packit 06404a
      double b=(bn*xyb-xb*yb)/denom;
Packit 06404a
      *y0=rint(a+b*x0);
Packit 06404a
      *y1=rint(a+b*x1);
Packit 06404a
Packit 06404a
      /* limit to our range! */
Packit 06404a
      if(*y0>1023)*y0=1023;
Packit 06404a
      if(*y1>1023)*y1=1023;
Packit 06404a
      if(*y0<0)*y0=0;
Packit 06404a
      if(*y1<0)*y1=0;
Packit 06404a
Packit 06404a
      return 0;
Packit 06404a
    }else{
Packit 06404a
      *y0=0;
Packit 06404a
      *y1=0;
Packit 06404a
      return 1;
Packit 06404a
    }
Packit 06404a
  }
Packit 06404a
}
Packit 06404a
Packit 06404a
static int inspect_error(int x0,int x1,int y0,int y1,const float *mask,
Packit 06404a
                         const float *mdct,
Packit 06404a
                         vorbis_info_floor1 *info){
Packit 06404a
  int dy=y1-y0;
Packit 06404a
  int adx=x1-x0;
Packit 06404a
  int ady=abs(dy);
Packit 06404a
  int base=dy/adx;
Packit 06404a
  int sy=(dy<0?base-1:base+1);
Packit 06404a
  int x=x0;
Packit 06404a
  int y=y0;
Packit 06404a
  int err=0;
Packit 06404a
  int val=vorbis_dBquant(mask+x);
Packit 06404a
  int mse=0;
Packit 06404a
  int n=0;
Packit 06404a
Packit 06404a
  ady-=abs(base*adx);
Packit 06404a
Packit 06404a
  mse=(y-val);
Packit 06404a
  mse*=mse;
Packit 06404a
  n++;
Packit 06404a
  if(mdct[x]+info->twofitatten>=mask[x]){
Packit 06404a
    if(y+info->maxover
Packit 06404a
    if(y-info->maxunder>val)return(1);
Packit 06404a
  }
Packit 06404a
Packit 06404a
  while(++x
Packit 06404a
    err=err+ady;
Packit 06404a
    if(err>=adx){
Packit 06404a
      err-=adx;
Packit 06404a
      y+=sy;
Packit 06404a
    }else{
Packit 06404a
      y+=base;
Packit 06404a
    }
Packit 06404a
Packit 06404a
    val=vorbis_dBquant(mask+x);
Packit 06404a
    mse+=((y-val)*(y-val));
Packit 06404a
    n++;
Packit 06404a
    if(mdct[x]+info->twofitatten>=mask[x]){
Packit 06404a
      if(val){
Packit 06404a
        if(y+info->maxover
Packit 06404a
        if(y-info->maxunder>val)return(1);
Packit 06404a
      }
Packit 06404a
    }
Packit 06404a
  }
Packit 06404a
Packit 06404a
  if(info->maxover*info->maxover/n>info->maxerr)return(0);
Packit 06404a
  if(info->maxunder*info->maxunder/n>info->maxerr)return(0);
Packit 06404a
  if(mse/n>info->maxerr)return(1);
Packit 06404a
  return(0);
Packit 06404a
}
Packit 06404a
Packit 06404a
static int post_Y(int *A,int *B,int pos){
Packit 06404a
  if(A[pos]<0)
Packit 06404a
    return B[pos];
Packit 06404a
  if(B[pos]<0)
Packit 06404a
    return A[pos];
Packit 06404a
Packit 06404a
  return (A[pos]+B[pos])>>1;
Packit 06404a
}
Packit 06404a
Packit 06404a
int *floor1_fit(vorbis_block *vb,vorbis_look_floor1 *look,
Packit 06404a
                          const float *logmdct,   /* in */
Packit 06404a
                          const float *logmask){
Packit 06404a
  long i,j;
Packit 06404a
  vorbis_info_floor1 *info=look->vi;
Packit 06404a
  long n=look->n;
Packit 06404a
  long posts=look->posts;
Packit 06404a
  long nonzero=0;
Packit 06404a
  lsfit_acc fits[VIF_POSIT+1];
Packit 06404a
  int fit_valueA[VIF_POSIT+2]; /* index by range list position */
Packit 06404a
  int fit_valueB[VIF_POSIT+2]; /* index by range list position */
Packit 06404a
Packit 06404a
  int loneighbor[VIF_POSIT+2]; /* sorted index of range list position (+2) */
Packit 06404a
  int hineighbor[VIF_POSIT+2];
Packit 06404a
  int *output=NULL;
Packit 06404a
  int memo[VIF_POSIT+2];
Packit 06404a
Packit 06404a
  for(i=0;i
Packit 06404a
  for(i=0;i
Packit 06404a
  for(i=0;i
Packit 06404a
  for(i=0;i
Packit 06404a
  for(i=0;i
Packit 06404a
Packit 06404a
  /* quantize the relevant floor points and collect them into line fit
Packit 06404a
     structures (one per minimal division) at the same time */
Packit 06404a
  if(posts==0){
Packit 06404a
    nonzero+=accumulate_fit(logmask,logmdct,0,n,fits,n,info);
Packit 06404a
  }else{
Packit 06404a
    for(i=0;i
Packit 06404a
      nonzero+=accumulate_fit(logmask,logmdct,look->sorted_index[i],
Packit 06404a
                              look->sorted_index[i+1],fits+i,
Packit 06404a
                              n,info);
Packit 06404a
  }
Packit 06404a
Packit 06404a
  if(nonzero){
Packit 06404a
    /* start by fitting the implicit base case.... */
Packit 06404a
    int y0=-200;
Packit 06404a
    int y1=-200;
Packit 06404a
    fit_line(fits,posts-1,&y0,&y1,info);
Packit 06404a
Packit 06404a
    fit_valueA[0]=y0;
Packit 06404a
    fit_valueB[0]=y0;
Packit 06404a
    fit_valueB[1]=y1;
Packit 06404a
    fit_valueA[1]=y1;
Packit 06404a
Packit 06404a
    /* Non degenerate case */
Packit 06404a
    /* start progressive splitting.  This is a greedy, non-optimal
Packit 06404a
       algorithm, but simple and close enough to the best
Packit 06404a
       answer. */
Packit 06404a
    for(i=2;i
Packit 06404a
      int sortpos=look->reverse_index[i];
Packit 06404a
      int ln=loneighbor[sortpos];
Packit 06404a
      int hn=hineighbor[sortpos];
Packit 06404a
Packit 06404a
      /* eliminate repeat searches of a particular range with a memo */
Packit 06404a
      if(memo[ln]!=hn){
Packit 06404a
        /* haven't performed this error search yet */
Packit 06404a
        int lsortpos=look->reverse_index[ln];
Packit 06404a
        int hsortpos=look->reverse_index[hn];
Packit 06404a
        memo[ln]=hn;
Packit 06404a
Packit 06404a
        {
Packit 06404a
          /* A note: we want to bound/minimize *local*, not global, error */
Packit 06404a
          int lx=info->postlist[ln];
Packit 06404a
          int hx=info->postlist[hn];
Packit 06404a
          int ly=post_Y(fit_valueA,fit_valueB,ln);
Packit 06404a
          int hy=post_Y(fit_valueA,fit_valueB,hn);
Packit 06404a
Packit 06404a
          if(ly==-1 || hy==-1){
Packit 06404a
            exit(1);
Packit 06404a
          }
Packit 06404a
Packit 06404a
          if(inspect_error(lx,hx,ly,hy,logmask,logmdct,info)){
Packit 06404a
            /* outside error bounds/begin search area.  Split it. */
Packit 06404a
            int ly0=-200;
Packit 06404a
            int ly1=-200;
Packit 06404a
            int hy0=-200;
Packit 06404a
            int hy1=-200;
Packit 06404a
            int ret0=fit_line(fits+lsortpos,sortpos-lsortpos,&ly0,&ly1,info);
Packit 06404a
            int ret1=fit_line(fits+sortpos,hsortpos-sortpos,&hy0,&hy1,info);
Packit 06404a
Packit 06404a
            if(ret0){
Packit 06404a
              ly0=ly;
Packit 06404a
              ly1=hy0;
Packit 06404a
            }
Packit 06404a
            if(ret1){
Packit 06404a
              hy0=ly1;
Packit 06404a
              hy1=hy;
Packit 06404a
            }
Packit 06404a
Packit 06404a
            if(ret0 && ret1){
Packit 06404a
              fit_valueA[i]=-200;
Packit 06404a
              fit_valueB[i]=-200;
Packit 06404a
            }else{
Packit 06404a
              /* store new edge values */
Packit 06404a
              fit_valueB[ln]=ly0;
Packit 06404a
              if(ln==0)fit_valueA[ln]=ly0;
Packit 06404a
              fit_valueA[i]=ly1;
Packit 06404a
              fit_valueB[i]=hy0;
Packit 06404a
              fit_valueA[hn]=hy1;
Packit 06404a
              if(hn==1)fit_valueB[hn]=hy1;
Packit 06404a
Packit 06404a
              if(ly1>=0 || hy0>=0){
Packit 06404a
                /* store new neighbor values */
Packit 06404a
                for(j=sortpos-1;j>=0;j--)
Packit 06404a
                  if(hineighbor[j]==hn)
Packit 06404a
                    hineighbor[j]=i;
Packit 06404a
                  else
Packit 06404a
                    break;
Packit 06404a
                for(j=sortpos+1;j
Packit 06404a
                  if(loneighbor[j]==ln)
Packit 06404a
                    loneighbor[j]=i;
Packit 06404a
                  else
Packit 06404a
                    break;
Packit 06404a
              }
Packit 06404a
            }
Packit 06404a
          }else{
Packit 06404a
            fit_valueA[i]=-200;
Packit 06404a
            fit_valueB[i]=-200;
Packit 06404a
          }
Packit 06404a
        }
Packit 06404a
      }
Packit 06404a
    }
Packit 06404a
Packit 06404a
    output=_vorbis_block_alloc(vb,sizeof(*output)*posts);
Packit 06404a
Packit 06404a
    output[0]=post_Y(fit_valueA,fit_valueB,0);
Packit 06404a
    output[1]=post_Y(fit_valueA,fit_valueB,1);
Packit 06404a
Packit 06404a
    /* fill in posts marked as not using a fit; we will zero
Packit 06404a
       back out to 'unused' when encoding them so long as curve
Packit 06404a
       interpolation doesn't force them into use */
Packit 06404a
    for(i=2;i
Packit 06404a
      int ln=look->loneighbor[i-2];
Packit 06404a
      int hn=look->hineighbor[i-2];
Packit 06404a
      int x0=info->postlist[ln];
Packit 06404a
      int x1=info->postlist[hn];
Packit 06404a
      int y0=output[ln];
Packit 06404a
      int y1=output[hn];
Packit 06404a
Packit 06404a
      int predicted=render_point(x0,x1,y0,y1,info->postlist[i]);
Packit 06404a
      int vx=post_Y(fit_valueA,fit_valueB,i);
Packit 06404a
Packit 06404a
      if(vx>=0 && predicted!=vx){
Packit 06404a
        output[i]=vx;
Packit 06404a
      }else{
Packit 06404a
        output[i]= predicted|0x8000;
Packit 06404a
      }
Packit 06404a
    }
Packit 06404a
  }
Packit 06404a
Packit 06404a
  return(output);
Packit 06404a
Packit 06404a
}
Packit 06404a
Packit 06404a
int *floor1_interpolate_fit(vorbis_block *vb,vorbis_look_floor1 *look,
Packit 06404a
                          int *A,int *B,
Packit 06404a
                          int del){
Packit 06404a
Packit 06404a
  long i;
Packit 06404a
  long posts=look->posts;
Packit 06404a
  int *output=NULL;
Packit 06404a
Packit 06404a
  if(A && B){
Packit 06404a
    output=_vorbis_block_alloc(vb,sizeof(*output)*posts);
Packit 06404a
Packit 06404a
    /* overly simpleminded--- look again post 1.2 */
Packit 06404a
    for(i=0;i
Packit 06404a
      output[i]=((65536-del)*(A[i]&0x7fff)+del*(B[i]&0x7fff)+32768)>>16;
Packit 06404a
      if(A[i]&0x8000 && B[i]&0x8000)output[i]|=0x8000;
Packit 06404a
    }
Packit 06404a
  }
Packit 06404a
Packit 06404a
  return(output);
Packit 06404a
}
Packit 06404a
Packit 06404a
Packit 06404a
int floor1_encode(oggpack_buffer *opb,vorbis_block *vb,
Packit 06404a
                  vorbis_look_floor1 *look,
Packit 06404a
                  int *post,int *ilogmask){
Packit 06404a
Packit 06404a
  long i,j;
Packit 06404a
  vorbis_info_floor1 *info=look->vi;
Packit 06404a
  long posts=look->posts;
Packit 06404a
  codec_setup_info *ci=vb->vd->vi->codec_setup;
Packit 06404a
  int out[VIF_POSIT+2];
Packit 06404a
  static_codebook **sbooks=ci->book_param;
Packit 06404a
  codebook *books=ci->fullbooks;
Packit 06404a
Packit 06404a
  /* quantize values to multiplier spec */
Packit 06404a
  if(post){
Packit 06404a
    for(i=0;i
Packit 06404a
      int val=post[i]&0x7fff;
Packit 06404a
      switch(info->mult){
Packit 06404a
      case 1: /* 1024 -> 256 */
Packit 06404a
        val>>=2;
Packit 06404a
        break;
Packit 06404a
      case 2: /* 1024 -> 128 */
Packit 06404a
        val>>=3;
Packit 06404a
        break;
Packit 06404a
      case 3: /* 1024 -> 86 */
Packit 06404a
        val/=12;
Packit 06404a
        break;
Packit 06404a
      case 4: /* 1024 -> 64 */
Packit 06404a
        val>>=4;
Packit 06404a
        break;
Packit 06404a
      }
Packit 06404a
      post[i]=val | (post[i]&0x8000);
Packit 06404a
    }
Packit 06404a
Packit 06404a
    out[0]=post[0];
Packit 06404a
    out[1]=post[1];
Packit 06404a
Packit 06404a
    /* find prediction values for each post and subtract them */
Packit 06404a
    for(i=2;i
Packit 06404a
      int ln=look->loneighbor[i-2];
Packit 06404a
      int hn=look->hineighbor[i-2];
Packit 06404a
      int x0=info->postlist[ln];
Packit 06404a
      int x1=info->postlist[hn];
Packit 06404a
      int y0=post[ln];
Packit 06404a
      int y1=post[hn];
Packit 06404a
Packit 06404a
      int predicted=render_point(x0,x1,y0,y1,info->postlist[i]);
Packit 06404a
Packit 06404a
      if((post[i]&0x8000) || (predicted==post[i])){
Packit 06404a
        post[i]=predicted|0x8000; /* in case there was roundoff jitter
Packit 06404a
                                     in interpolation */
Packit 06404a
        out[i]=0;
Packit 06404a
      }else{
Packit 06404a
        int headroom=(look->quant_q-predicted
Packit 06404a
                      look->quant_q-predicted:predicted);
Packit 06404a
Packit 06404a
        int val=post[i]-predicted;
Packit 06404a
Packit 06404a
        /* at this point the 'deviation' value is in the range +/- max
Packit 06404a
           range, but the real, unique range can always be mapped to
Packit 06404a
           only [0-maxrange).  So we want to wrap the deviation into
Packit 06404a
           this limited range, but do it in the way that least screws
Packit 06404a
           an essentially gaussian probability distribution. */
Packit 06404a
Packit 06404a
        if(val<0)
Packit 06404a
          if(val<-headroom)
Packit 06404a
            val=headroom-val-1;
Packit 06404a
          else
Packit 06404a
            val=-1-(val<<1);
Packit 06404a
        else
Packit 06404a
          if(val>=headroom)
Packit 06404a
            val= val+headroom;
Packit 06404a
          else
Packit 06404a
            val<<=1;
Packit 06404a
Packit 06404a
        out[i]=val;
Packit 06404a
        post[ln]&=0x7fff;
Packit 06404a
        post[hn]&=0x7fff;
Packit 06404a
      }
Packit 06404a
    }
Packit 06404a
Packit 06404a
    /* we have everything we need. pack it out */
Packit 06404a
    /* mark nontrivial floor */
Packit 06404a
    oggpack_write(opb,1,1);
Packit 06404a
Packit 06404a
    /* beginning/end post */
Packit 06404a
    look->frames++;
Packit 06404a
    look->postbits+=ov_ilog(look->quant_q-1)*2;
Packit 06404a
    oggpack_write(opb,out[0],ov_ilog(look->quant_q-1));
Packit 06404a
    oggpack_write(opb,out[1],ov_ilog(look->quant_q-1));
Packit 06404a
Packit 06404a
Packit 06404a
    /* partition by partition */
Packit 06404a
    for(i=0,j=2;i<info->partitions;i++){
Packit 06404a
      int class=info->partitionclass[i];
Packit 06404a
      int cdim=info->class_dim[class];
Packit 06404a
      int csubbits=info->class_subs[class];
Packit 06404a
      int csub=1<
Packit 06404a
      int bookas[8]={0,0,0,0,0,0,0,0};
Packit 06404a
      int cval=0;
Packit 06404a
      int cshift=0;
Packit 06404a
      int k,l;
Packit 06404a
Packit 06404a
      /* generate the partition's first stage cascade value */
Packit 06404a
      if(csubbits){
Packit 06404a
        int maxval[8]={0,0,0,0,0,0,0,0}; /* gcc's static analysis
Packit 06404a
                                            issues a warning without
Packit 06404a
                                            initialization */
Packit 06404a
        for(k=0;k
Packit 06404a
          int booknum=info->class_subbook[class][k];
Packit 06404a
          if(booknum<0){
Packit 06404a
            maxval[k]=1;
Packit 06404a
          }else{
Packit 06404a
            maxval[k]=sbooks[info->class_subbook[class][k]]->entries;
Packit 06404a
          }
Packit 06404a
        }
Packit 06404a
        for(k=0;k
Packit 06404a
          for(l=0;l
Packit 06404a
            int val=out[j+k];
Packit 06404a
            if(val
Packit 06404a
              bookas[k]=l;
Packit 06404a
              break;
Packit 06404a
            }
Packit 06404a
          }
Packit 06404a
          cval|= bookas[k]<
Packit 06404a
          cshift+=csubbits;
Packit 06404a
        }
Packit 06404a
        /* write it */
Packit 06404a
        look->phrasebits+=
Packit 06404a
          vorbis_book_encode(books+info->class_book[class],cval,opb);
Packit 06404a
Packit 06404a
#ifdef TRAIN_FLOOR1
Packit 06404a
        {
Packit 06404a
          FILE *of;
Packit 06404a
          char buffer[80];
Packit 06404a
          sprintf(buffer,"line_%dx%ld_class%d.vqd",
Packit 06404a
                  vb->pcmend/2,posts-2,class);
Packit 06404a
          of=fopen(buffer,"a");
Packit 06404a
          fprintf(of,"%d\n",cval);
Packit 06404a
          fclose(of);
Packit 06404a
        }
Packit 06404a
#endif
Packit 06404a
      }
Packit 06404a
Packit 06404a
      /* write post values */
Packit 06404a
      for(k=0;k
Packit 06404a
        int book=info->class_subbook[class][bookas[k]];
Packit 06404a
        if(book>=0){
Packit 06404a
          /* hack to allow training with 'bad' books */
Packit 06404a
          if(out[j+k]<(books+book)->entries)
Packit 06404a
            look->postbits+=vorbis_book_encode(books+book,
Packit 06404a
                                               out[j+k],opb);
Packit 06404a
          /*else
Packit 06404a
            fprintf(stderr,"+!");*/
Packit 06404a
Packit 06404a
#ifdef TRAIN_FLOOR1
Packit 06404a
          {
Packit 06404a
            FILE *of;
Packit 06404a
            char buffer[80];
Packit 06404a
            sprintf(buffer,"line_%dx%ld_%dsub%d.vqd",
Packit 06404a
                    vb->pcmend/2,posts-2,class,bookas[k]);
Packit 06404a
            of=fopen(buffer,"a");
Packit 06404a
            fprintf(of,"%d\n",out[j+k]);
Packit 06404a
            fclose(of);
Packit 06404a
          }
Packit 06404a
#endif
Packit 06404a
        }
Packit 06404a
      }
Packit 06404a
      j+=cdim;
Packit 06404a
    }
Packit 06404a
Packit 06404a
    {
Packit 06404a
      /* generate quantized floor equivalent to what we'd unpack in decode */
Packit 06404a
      /* render the lines */
Packit 06404a
      int hx=0;
Packit 06404a
      int lx=0;
Packit 06404a
      int ly=post[0]*info->mult;
Packit 06404a
      int n=ci->blocksizes[vb->W]/2;
Packit 06404a
Packit 06404a
      for(j=1;j<look->posts;j++){
Packit 06404a
        int current=look->forward_index[j];
Packit 06404a
        int hy=post[current]&0x7fff;
Packit 06404a
        if(hy==post[current]){
Packit 06404a
Packit 06404a
          hy*=info->mult;
Packit 06404a
          hx=info->postlist[current];
Packit 06404a
Packit 06404a
          render_line0(n,lx,hx,ly,hy,ilogmask);
Packit 06404a
Packit 06404a
          lx=hx;
Packit 06404a
          ly=hy;
Packit 06404a
        }
Packit 06404a
      }
Packit 06404a
      for(j=hx;j<vb->pcmend/2;j++)ilogmask[j]=ly; /* be certain */
Packit 06404a
      return(1);
Packit 06404a
    }
Packit 06404a
  }else{
Packit 06404a
    oggpack_write(opb,0,1);
Packit 06404a
    memset(ilogmask,0,vb->pcmend/2*sizeof(*ilogmask));
Packit 06404a
    return(0);
Packit 06404a
  }
Packit 06404a
}
Packit 06404a
Packit 06404a
static void *floor1_inverse1(vorbis_block *vb,vorbis_look_floor *in){
Packit 06404a
  vorbis_look_floor1 *look=(vorbis_look_floor1 *)in;
Packit 06404a
  vorbis_info_floor1 *info=look->vi;
Packit 06404a
  codec_setup_info   *ci=vb->vd->vi->codec_setup;
Packit 06404a
Packit 06404a
  int i,j,k;
Packit 06404a
  codebook *books=ci->fullbooks;
Packit 06404a
Packit 06404a
  /* unpack wrapped/predicted values from stream */
Packit 06404a
  if(oggpack_read(&vb->opb,1)==1){
Packit 06404a
    int *fit_value=_vorbis_block_alloc(vb,(look->posts)*sizeof(*fit_value));
Packit 06404a
Packit 06404a
    fit_value[0]=oggpack_read(&vb->opb,ov_ilog(look->quant_q-1));
Packit 06404a
    fit_value[1]=oggpack_read(&vb->opb,ov_ilog(look->quant_q-1));
Packit 06404a
Packit 06404a
    /* partition by partition */
Packit 06404a
    for(i=0,j=2;i<info->partitions;i++){
Packit 06404a
      int class=info->partitionclass[i];
Packit 06404a
      int cdim=info->class_dim[class];
Packit 06404a
      int csubbits=info->class_subs[class];
Packit 06404a
      int csub=1<
Packit 06404a
      int cval=0;
Packit 06404a
Packit 06404a
      /* decode the partition's first stage cascade value */
Packit 06404a
      if(csubbits){
Packit 06404a
        cval=vorbis_book_decode(books+info->class_book[class],&vb->opb);
Packit 06404a
Packit 06404a
        if(cval==-1)goto eop;
Packit 06404a
      }
Packit 06404a
Packit 06404a
      for(k=0;k
Packit 06404a
        int book=info->class_subbook[class][cval&(csub-1)];
Packit 06404a
        cval>>=csubbits;
Packit 06404a
        if(book>=0){
Packit 06404a
          if((fit_value[j+k]=vorbis_book_decode(books+book,&vb->opb))==-1)
Packit 06404a
            goto eop;
Packit 06404a
        }else{
Packit 06404a
          fit_value[j+k]=0;
Packit 06404a
        }
Packit 06404a
      }
Packit 06404a
      j+=cdim;
Packit 06404a
    }
Packit 06404a
Packit 06404a
    /* unwrap positive values and reconsitute via linear interpolation */
Packit 06404a
    for(i=2;i<look->posts;i++){
Packit 06404a
      int predicted=render_point(info->postlist[look->loneighbor[i-2]],
Packit 06404a
                                 info->postlist[look->hineighbor[i-2]],
Packit 06404a
                                 fit_value[look->loneighbor[i-2]],
Packit 06404a
                                 fit_value[look->hineighbor[i-2]],
Packit 06404a
                                 info->postlist[i]);
Packit 06404a
      int hiroom=look->quant_q-predicted;
Packit 06404a
      int loroom=predicted;
Packit 06404a
      int room=(hiroom
Packit 06404a
      int val=fit_value[i];
Packit 06404a
Packit 06404a
      if(val){
Packit 06404a
        if(val>=room){
Packit 06404a
          if(hiroom>loroom){
Packit 06404a
            val = val-loroom;
Packit 06404a
          }else{
Packit 06404a
            val = -1-(val-hiroom);
Packit 06404a
          }
Packit 06404a
        }else{
Packit 06404a
          if(val&1){
Packit 06404a
            val= -((val+1)>>1);
Packit 06404a
          }else{
Packit 06404a
            val>>=1;
Packit 06404a
          }
Packit 06404a
        }
Packit 06404a
Packit 06404a
        fit_value[i]=(val+predicted)&0x7fff;
Packit 06404a
        fit_value[look->loneighbor[i-2]]&=0x7fff;
Packit 06404a
        fit_value[look->hineighbor[i-2]]&=0x7fff;
Packit 06404a
Packit 06404a
      }else{
Packit 06404a
        fit_value[i]=predicted|0x8000;
Packit 06404a
      }
Packit 06404a
Packit 06404a
    }
Packit 06404a
Packit 06404a
    return(fit_value);
Packit 06404a
  }
Packit 06404a
 eop:
Packit 06404a
  return(NULL);
Packit 06404a
}
Packit 06404a
Packit 06404a
static int floor1_inverse2(vorbis_block *vb,vorbis_look_floor *in,void *memo,
Packit 06404a
                          float *out){
Packit 06404a
  vorbis_look_floor1 *look=(vorbis_look_floor1 *)in;
Packit 06404a
  vorbis_info_floor1 *info=look->vi;
Packit 06404a
Packit 06404a
  codec_setup_info   *ci=vb->vd->vi->codec_setup;
Packit 06404a
  int                  n=ci->blocksizes[vb->W]/2;
Packit 06404a
  int j;
Packit 06404a
Packit 06404a
  if(memo){
Packit 06404a
    /* render the lines */
Packit 06404a
    int *fit_value=(int *)memo;
Packit 06404a
    int hx=0;
Packit 06404a
    int lx=0;
Packit 06404a
    int ly=fit_value[0]*info->mult;
Packit 06404a
    /* guard lookup against out-of-range values */
Packit 06404a
    ly=(ly<0?0:ly>255?255:ly);
Packit 06404a
Packit 06404a
    for(j=1;j<look->posts;j++){
Packit 06404a
      int current=look->forward_index[j];
Packit 06404a
      int hy=fit_value[current]&0x7fff;
Packit 06404a
      if(hy==fit_value[current]){
Packit 06404a
Packit 06404a
        hx=info->postlist[current];
Packit 06404a
        hy*=info->mult;
Packit 06404a
        /* guard lookup against out-of-range values */
Packit 06404a
        hy=(hy<0?0:hy>255?255:hy);
Packit 06404a
Packit 06404a
        render_line(n,lx,hx,ly,hy,out);
Packit 06404a
Packit 06404a
        lx=hx;
Packit 06404a
        ly=hy;
Packit 06404a
      }
Packit 06404a
    }
Packit 06404a
    for(j=hx;j
Packit 06404a
    return(1);
Packit 06404a
  }
Packit 06404a
  memset(out,0,sizeof(*out)*n);
Packit 06404a
  return(0);
Packit 06404a
}
Packit 06404a
Packit 06404a
/* export hooks */
Packit 06404a
const vorbis_func_floor floor1_exportbundle={
Packit 06404a
  &floor1_pack,&floor1_unpack,&floor1_look,&floor1_free_info,
Packit 06404a
  &floor1_free_look,&floor1_inverse1,&floor1_inverse2
Packit 06404a
};