examples/sfexamples/oggvorbiscodec/src/libvorbis/lib/floor0.c

00001 /********************************************************************
00002  *                                                                  *
00003  * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
00004  * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
00005  * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
00006  * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
00007  *                                                                  *
00008  * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002             *
00009  * by the XIPHOPHORUS Company http://www.xiph.org/                  *
00010  *                                                                  *
00011  ********************************************************************
00012 
00013  function: floor backend 0 implementation
00014  last mod: $Id: floor0.c 7187 2004-07-20 07:24:27Z xiphmont $
00015 
00016  ********************************************************************/
00017 
00018 #include <stdlib.h>
00019 #include <string.h>
00020 #include <math.h>
00021 #include "ogg/ogg.h"
00022 #include "vorbis/codec.h"
00023 #include "codec_internal.h"
00024 #include "registry.h"
00025 #include "lpc.h"
00026 #include "lsp.h"
00027 #include "codebook.h"
00028 #include "scales.h"
00029 #include "misc.h"
00030 #include "os.h"
00031 
00032 #include "misc.h"
00033 #include <stdio.h>
00034 
00035 typedef struct {
00036   int ln;
00037   int  m;
00038   int **linearmap;
00039   int  n[2];
00040 
00041   vorbis_info_floor0 *vi;
00042 
00043   long bits;
00044   long frames;
00045 } vorbis_look_floor0;
00046 
00047 
00048 /***********************************************/
00049 
00050 static void floor0_free_info(vorbis_info_floor *i){
00051   vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
00052   if(info){
00053     memset(info,0,sizeof(*info));
00054     _ogg_free(info);
00055   }
00056 }
00057 
00058 static void floor0_free_look(vorbis_look_floor *i){
00059   vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
00060   if(look){
00061 
00062     if(look->linearmap){
00063 
00064       if(look->linearmap[0])_ogg_free(look->linearmap[0]);
00065       if(look->linearmap[1])_ogg_free(look->linearmap[1]);
00066 
00067       _ogg_free(look->linearmap);
00068     }
00069     memset(look,0,sizeof(*look));
00070     _ogg_free(look);
00071   }
00072 }
00073 
00074 static vorbis_info_floor *floor0_unpack (vorbis_info *vi,oggpack_buffer *opb){
00075   codec_setup_info     *ci=(codec_setup_info*)vi->codec_setup;
00076   int j;
00077 
00078   vorbis_info_floor0 *info=(vorbis_info_floor0*)_ogg_malloc(sizeof(*info));
00079   info->order=oggpack_read(opb,8);
00080   info->rate=oggpack_read(opb,16);
00081   info->barkmap=oggpack_read(opb,16);
00082   info->ampbits=oggpack_read(opb,6);
00083   info->ampdB=oggpack_read(opb,8);
00084   info->numbooks=oggpack_read(opb,4)+1;
00085   
00086   if(info->order<1)goto err_out;
00087   if(info->rate<1)goto err_out;
00088   if(info->barkmap<1)goto err_out;
00089   if(info->numbooks<1)goto err_out;
00090     
00091   for(j=0;j<info->numbooks;j++){
00092     info->books[j]=oggpack_read(opb,8);
00093     if(info->books[j]<0 || info->books[j]>=ci->books)goto err_out;
00094   }
00095   return(info);
00096 
00097  err_out:
00098   floor0_free_info(info);
00099   return(NULL);
00100 }
00101 
00102 /* initialize Bark scale and normalization lookups.  We could do this
00103    with static tables, but Vorbis allows a number of possible
00104    combinations, so it's best to do it computationally.
00105 
00106    The below is authoritative in terms of defining scale mapping.
00107    Note that the scale depends on the sampling rate as well as the
00108    linear block and mapping sizes */
00109 
00110 static void floor0_map_lazy_init(vorbis_block      *vb,
00111                                  vorbis_info_floor *infoX,
00112                                  vorbis_look_floor0 *look){
00113   if(!look->linearmap[vb->W]){
00114     vorbis_dsp_state   *vd=vb->vd;
00115     vorbis_info        *vi=vd->vi;
00116     codec_setup_info   *ci=(codec_setup_info*)vi->codec_setup;
00117     vorbis_info_floor0 *info=(vorbis_info_floor0 *)infoX;
00118     int W=vb->W;
00119     int n=ci->blocksizes[W]/2,j;
00120 
00121     /* we choose a scaling constant so that:
00122        floor(bark(rate/2-1)*C)=mapped-1
00123      floor(bark(rate/2)*C)=mapped */
00124     float scale=look->ln/toBARK(info->rate/2.f);
00125     
00126     /* the mapping from a linear scale to a smaller bark scale is
00127        straightforward.  We do *not* make sure that the linear mapping
00128        does not skip bark-scale bins; the decoder simply skips them and
00129        the encoder may do what it wishes in filling them.  They're
00130        necessary in some mapping combinations to keep the scale spacing
00131        accurate */
00132     look->linearmap[W]=(int*)_ogg_malloc((n+1)*sizeof(**look->linearmap));
00133     for(j=0;j<n;j++){
00134       int val=floor( toBARK((info->rate/2.f)/n*j) 
00135                      *scale); /* bark numbers represent band edges */
00136       if(val>=look->ln)val=look->ln-1; /* guard against the approximation */
00137       look->linearmap[W][j]=val;
00138     }
00139     look->linearmap[W][j]=-1;
00140     look->n[W]=n;
00141   }
00142 }
00143 
00144 static vorbis_look_floor *floor0_look(vorbis_dsp_state *vd,
00145                                       vorbis_info_floor *i){
00146   vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
00147   vorbis_look_floor0 *look=(vorbis_look_floor0*)_ogg_calloc(1,sizeof(*look));
00148   look->m=info->order;
00149   look->ln=info->barkmap;
00150   look->vi=info;
00151   vd = vd; //warning    
00152   look->linearmap=(int**)_ogg_calloc(2,sizeof(*look->linearmap));
00153 
00154   return look;
00155 }
00156 
00157 static void *floor0_inverse1(vorbis_block *vb,vorbis_look_floor *i){
00158   vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
00159   vorbis_info_floor0 *info=look->vi;
00160   int j,k;
00161 
00162   int ampraw=oggpack_read(&vb->opb,info->ampbits);
00163   if(ampraw>0){ /* also handles the -1 out of data case */
00164     long maxval=(1<<info->ampbits)-1;
00165     float amp=(float)ampraw/maxval*info->ampdB;
00166     int booknum=oggpack_read(&vb->opb,_ilog(info->numbooks));
00167     
00168     if(booknum!=-1 && booknum<info->numbooks){ /* be paranoid */
00169       codec_setup_info  *ci=(codec_setup_info*)vb->vd->vi->codec_setup;
00170       codebook *b=ci->fullbooks+info->books[booknum];
00171       float last=0.f;
00172 
00173       /* the additional b->dim is a guard against any possible stack
00174          smash; b->dim is provably more than we can overflow the
00175          vector */
00176       float *lsp=(float*)_vorbis_block_alloc(vb,sizeof(*lsp)*(look->m+b->dim+1));
00177             
00178       for(j=0;j<look->m;j+=b->dim)
00179         if(vorbis_book_decodev_set(b,lsp+j,&vb->opb,b->dim)==-1)goto eop;
00180       for(j=0;j<look->m;){
00181         for(k=0;k<b->dim;k++,j++)lsp[j]+=last;
00182         last=lsp[j-1];
00183       }
00184       
00185       lsp[look->m]=amp;
00186       return(lsp);
00187     }
00188   }
00189  eop:
00190   return(NULL);
00191 }
00192 
00193 static int floor0_inverse2(vorbis_block *vb,vorbis_look_floor *i,
00194                            void *memo,float *out){
00195   vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
00196   vorbis_info_floor0 *info=look->vi;
00197   
00198   floor0_map_lazy_init(vb,info,look);
00199 
00200   if(memo){
00201     float *lsp=(float *)memo;
00202     float amp=lsp[look->m];
00203 
00204     /* take the coefficients back to a spectral envelope curve */
00205     vorbis_lsp_to_curve(out,
00206                         look->linearmap[vb->W],
00207                         look->n[vb->W],
00208                         look->ln,
00209                         lsp,look->m,amp,(float)info->ampdB);
00210     return(1);
00211   }
00212   memset(out,0,sizeof(*out)*look->n[vb->W]);
00213   return(0);
00214 }
00215 
00216 /* export hooks */
00217 vorbis_func_floor floor0_exportbundle={
00218   NULL,&floor0_unpack,&floor0_look,&floor0_free_info,
00219   &floor0_free_look,&floor0_inverse1,&floor0_inverse2
00220 };
00221 
00222 
00223 

Generated by  doxygen 1.6.2