Blame lib/floor0.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 0 implementation
Packit 06404a
 last mod: $Id: floor0.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 "lpc.h"
Packit 06404a
#include "lsp.h"
Packit 06404a
#include "codebook.h"
Packit 06404a
#include "scales.h"
Packit 06404a
#include "misc.h"
Packit 06404a
#include "os.h"
Packit 06404a
Packit 06404a
#include "misc.h"
Packit 06404a
#include <stdio.h>
Packit 06404a
Packit 06404a
typedef struct {
Packit 06404a
  int ln;
Packit 06404a
  int  m;
Packit 06404a
  int **linearmap;
Packit 06404a
  int  n[2];
Packit 06404a
Packit 06404a
  vorbis_info_floor0 *vi;
Packit 06404a
Packit 06404a
  long bits;
Packit 06404a
  long frames;
Packit 06404a
} vorbis_look_floor0;
Packit 06404a
Packit 06404a
Packit 06404a
/***********************************************/
Packit 06404a
Packit 06404a
static void floor0_free_info(vorbis_info_floor *i){
Packit 06404a
  vorbis_info_floor0 *info=(vorbis_info_floor0 *)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 floor0_free_look(vorbis_look_floor *i){
Packit 06404a
  vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
Packit 06404a
  if(look){
Packit 06404a
Packit 06404a
    if(look->linearmap){
Packit 06404a
Packit 06404a
      if(look->linearmap[0])_ogg_free(look->linearmap[0]);
Packit 06404a
      if(look->linearmap[1])_ogg_free(look->linearmap[1]);
Packit 06404a
Packit 06404a
      _ogg_free(look->linearmap);
Packit 06404a
    }
Packit 06404a
    memset(look,0,sizeof(*look));
Packit 06404a
    _ogg_free(look);
Packit 06404a
  }
Packit 06404a
}
Packit 06404a
Packit 06404a
static vorbis_info_floor *floor0_unpack (vorbis_info *vi,oggpack_buffer *opb){
Packit 06404a
  codec_setup_info     *ci=vi->codec_setup;
Packit 06404a
  int j;
Packit 06404a
Packit 06404a
  vorbis_info_floor0 *info=_ogg_malloc(sizeof(*info));
Packit 06404a
  info->order=oggpack_read(opb,8);
Packit 06404a
  info->rate=oggpack_read(opb,16);
Packit 06404a
  info->barkmap=oggpack_read(opb,16);
Packit 06404a
  info->ampbits=oggpack_read(opb,6);
Packit 06404a
  info->ampdB=oggpack_read(opb,8);
Packit 06404a
  info->numbooks=oggpack_read(opb,4)+1;
Packit 06404a
Packit 06404a
  if(info->order<1)goto err_out;
Packit 06404a
  if(info->rate<1)goto err_out;
Packit 06404a
  if(info->barkmap<1)goto err_out;
Packit 06404a
  if(info->numbooks<1)goto err_out;
Packit 06404a
Packit 06404a
  for(j=0;j<info->numbooks;j++){
Packit 06404a
    info->books[j]=oggpack_read(opb,8);
Packit 06404a
    if(info->books[j]<0 || info->books[j]>=ci->books)goto err_out;
Packit 06404a
    if(ci->book_param[info->books[j]]->maptype==0)goto err_out;
Packit 06404a
    if(ci->book_param[info->books[j]]->dim<1)goto err_out;
Packit 06404a
  }
Packit 06404a
  return(info);
Packit 06404a
Packit 06404a
 err_out:
Packit 06404a
  floor0_free_info(info);
Packit 06404a
  return(NULL);
Packit 06404a
}
Packit 06404a
Packit 06404a
/* initialize Bark scale and normalization lookups.  We could do this
Packit 06404a
   with static tables, but Vorbis allows a number of possible
Packit 06404a
   combinations, so it's best to do it computationally.
Packit 06404a
Packit 06404a
   The below is authoritative in terms of defining scale mapping.
Packit 06404a
   Note that the scale depends on the sampling rate as well as the
Packit 06404a
   linear block and mapping sizes */
Packit 06404a
Packit 06404a
static void floor0_map_lazy_init(vorbis_block      *vb,
Packit 06404a
                                 vorbis_info_floor *infoX,
Packit 06404a
                                 vorbis_look_floor0 *look){
Packit 06404a
  if(!look->linearmap[vb->W]){
Packit 06404a
    vorbis_dsp_state   *vd=vb->vd;
Packit 06404a
    vorbis_info        *vi=vd->vi;
Packit 06404a
    codec_setup_info   *ci=vi->codec_setup;
Packit 06404a
    vorbis_info_floor0 *info=(vorbis_info_floor0 *)infoX;
Packit 06404a
    int W=vb->W;
Packit 06404a
    int n=ci->blocksizes[W]/2,j;
Packit 06404a
Packit 06404a
    /* we choose a scaling constant so that:
Packit 06404a
       floor(bark(rate/2-1)*C)=mapped-1
Packit 06404a
     floor(bark(rate/2)*C)=mapped */
Packit 06404a
    float scale=look->ln/toBARK(info->rate/2.f);
Packit 06404a
Packit 06404a
    /* the mapping from a linear scale to a smaller bark scale is
Packit 06404a
       straightforward.  We do *not* make sure that the linear mapping
Packit 06404a
       does not skip bark-scale bins; the decoder simply skips them and
Packit 06404a
       the encoder may do what it wishes in filling them.  They're
Packit 06404a
       necessary in some mapping combinations to keep the scale spacing
Packit 06404a
       accurate */
Packit 06404a
    look->linearmap[W]=_ogg_malloc((n+1)*sizeof(**look->linearmap));
Packit 06404a
    for(j=0;j
Packit 06404a
      int val=floor( toBARK((info->rate/2.f)/n*j)
Packit 06404a
                     *scale); /* bark numbers represent band edges */
Packit 06404a
      if(val>=look->ln)val=look->ln-1; /* guard against the approximation */
Packit 06404a
      look->linearmap[W][j]=val;
Packit 06404a
    }
Packit 06404a
    look->linearmap[W][j]=-1;
Packit 06404a
    look->n[W]=n;
Packit 06404a
  }
Packit 06404a
}
Packit 06404a
Packit 06404a
static vorbis_look_floor *floor0_look(vorbis_dsp_state *vd,
Packit 06404a
                                      vorbis_info_floor *i){
Packit 06404a
  vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
Packit 06404a
  vorbis_look_floor0 *look=_ogg_calloc(1,sizeof(*look));
Packit 06404a
Packit 06404a
  (void)vd;
Packit 06404a
Packit 06404a
  look->m=info->order;
Packit 06404a
  look->ln=info->barkmap;
Packit 06404a
  look->vi=info;
Packit 06404a
Packit 06404a
  look->linearmap=_ogg_calloc(2,sizeof(*look->linearmap));
Packit 06404a
Packit 06404a
  return look;
Packit 06404a
}
Packit 06404a
Packit 06404a
static void *floor0_inverse1(vorbis_block *vb,vorbis_look_floor *i){
Packit 06404a
  vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
Packit 06404a
  vorbis_info_floor0 *info=look->vi;
Packit 06404a
  int j,k;
Packit 06404a
Packit 06404a
  int ampraw=oggpack_read(&vb->opb,info->ampbits);
Packit 06404a
  if(ampraw>0){ /* also handles the -1 out of data case */
Packit 06404a
    long maxval=(1<<info->ampbits)-1;
Packit 06404a
    float amp=(float)ampraw/maxval*info->ampdB;
Packit 06404a
    int booknum=oggpack_read(&vb->opb,ov_ilog(info->numbooks));
Packit 06404a
Packit 06404a
    if(booknum!=-1 && booknum<info->numbooks){ /* be paranoid */
Packit 06404a
      codec_setup_info  *ci=vb->vd->vi->codec_setup;
Packit 06404a
      codebook *b=ci->fullbooks+info->books[booknum];
Packit 06404a
      float last=0.f;
Packit 06404a
Packit 06404a
      /* the additional b->dim is a guard against any possible stack
Packit 06404a
         smash; b->dim is provably more than we can overflow the
Packit 06404a
         vector */
Packit 06404a
      float *lsp=_vorbis_block_alloc(vb,sizeof(*lsp)*(look->m+b->dim+1));
Packit 06404a
Packit 06404a
      if(vorbis_book_decodev_set(b,lsp,&vb->opb,look->m)==-1)goto eop;
Packit 06404a
      for(j=0;j<look->m;){
Packit 06404a
        for(k=0;j<look->m && k<b->dim;k++,j++)lsp[j]+=last;
Packit 06404a
        last=lsp[j-1];
Packit 06404a
      }
Packit 06404a
Packit 06404a
      lsp[look->m]=amp;
Packit 06404a
      return(lsp);
Packit 06404a
    }
Packit 06404a
  }
Packit 06404a
 eop:
Packit 06404a
  return(NULL);
Packit 06404a
}
Packit 06404a
Packit 06404a
static int floor0_inverse2(vorbis_block *vb,vorbis_look_floor *i,
Packit 06404a
                           void *memo,float *out){
Packit 06404a
  vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
Packit 06404a
  vorbis_info_floor0 *info=look->vi;
Packit 06404a
Packit 06404a
  floor0_map_lazy_init(vb,info,look);
Packit 06404a
Packit 06404a
  if(memo){
Packit 06404a
    float *lsp=(float *)memo;
Packit 06404a
    float amp=lsp[look->m];
Packit 06404a
Packit 06404a
    /* take the coefficients back to a spectral envelope curve */
Packit 06404a
    vorbis_lsp_to_curve(out,
Packit 06404a
                        look->linearmap[vb->W],
Packit 06404a
                        look->n[vb->W],
Packit 06404a
                        look->ln,
Packit 06404a
                        lsp,look->m,amp,(float)info->ampdB);
Packit 06404a
    return(1);
Packit 06404a
  }
Packit 06404a
  memset(out,0,sizeof(*out)*look->n[vb->W]);
Packit 06404a
  return(0);
Packit 06404a
}
Packit 06404a
Packit 06404a
/* export hooks */
Packit 06404a
const vorbis_func_floor floor0_exportbundle={
Packit 06404a
  NULL,&floor0_unpack,&floor0_look,&floor0_free_info,
Packit 06404a
  &floor0_free_look,&floor0_inverse1,&floor0_inverse2
Packit 06404a
};