1 /********************************************************************
2  *                                                                  *
3  * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
4  * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
5  * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
6  * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
7  *                                                                  *
8  * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009             *
9  * by the Xiph.Org Foundation http://www.xiph.org/                  *
10  *                                                                  *
11  ********************************************************************
12 
13  function: floor backend 0 implementation
14  last mod: $Id: floor0.c 17558 2010-10-22 00:24:41Z tterribe $
15 
16  ********************************************************************/
17 
18 
19 #include <stdlib.h>
20 #include <string.h>
21 #include <math.h>
22 #include "../../ogg.h"
23 #include "../../codec.h"
24 #include "codec_internal.h"
25 #include "registry.h"
26 #include "lpc.h"
27 #include "lsp.h"
28 #include "codebook.h"
29 #include "scales.h"
30 #include "misc.h"
31 #include "os.h"
32 
33 #include "misc.h"
34 #include <stdio.h>
35 
36 typedef struct {
37   int ln;
38   int  m;
39   int **linearmap;
40   int  n[2];
41 
42   vorbis_info_floor0 *vi;
43 
44   long bits;
45   long frames;
46 } vorbis_look_floor0;
47 
48 
49 /***********************************************/
50 
floor0_free_info(vorbis_info_floor * i)51 static void floor0_free_info(vorbis_info_floor *i){
52   vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
53   if(info){
54     memset(info,0,sizeof(*info));
55     _ogg_free(info);
56   }
57 }
58 
floor0_free_look(vorbis_look_floor * i)59 static void floor0_free_look(vorbis_look_floor *i){
60   vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
61   if(look){
62 
63     if(look->linearmap){
64 
65       if(look->linearmap[0])_ogg_free(look->linearmap[0]);
66       if(look->linearmap[1])_ogg_free(look->linearmap[1]);
67 
68       _ogg_free(look->linearmap);
69     }
70     memset(look,0,sizeof(*look));
71     _ogg_free(look);
72   }
73 }
74 
floor0_unpack(vorbis_info * vi,oggpack_buffer * opb)75 static vorbis_info_floor *floor0_unpack (vorbis_info *vi,oggpack_buffer *opb){
76   codec_setup_info     *ci=(codec_setup_info*)vi->codec_setup;
77   int j;
78 
79   vorbis_info_floor0 *info=(vorbis_info_floor0*)_ogg_malloc(sizeof(*info));
80   info->order=oggpack_read(opb,8);
81   info->rate=oggpack_read(opb,16);
82   info->barkmap=oggpack_read(opb,16);
83   info->ampbits=oggpack_read(opb,6);
84   info->ampdB=oggpack_read(opb,8);
85   info->numbooks=oggpack_read(opb,4)+1;
86 
87   if(info->order<1)goto err_out;
88   if(info->rate<1)goto err_out;
89   if(info->barkmap<1)goto err_out;
90   if(info->numbooks<1)goto err_out;
91 
92   for(j=0;j<info->numbooks;j++){
93     info->books[j]=oggpack_read(opb,8);
94     if(info->books[j]<0 || info->books[j]>=ci->books)goto err_out;
95     if(ci->book_param[info->books[j]]->maptype==0)goto err_out;
96     if(ci->book_param[info->books[j]]->dim<1)goto err_out;
97   }
98   return(info);
99 
100  err_out:
101   floor0_free_info(info);
102   return(NULL);
103 }
104 
105 /* initialize Bark scale and normalization lookups.  We could do this
106    with static tables, but Vorbis allows a number of possible
107    combinations, so it's best to do it computationally.
108 
109    The below is authoritative in terms of defining scale mapping.
110    Note that the scale depends on the sampling rate as well as the
111    linear block and mapping sizes */
112 
floor0_map_lazy_init(vorbis_block * vb,vorbis_info_floor * infoX,vorbis_look_floor0 * look)113 static void floor0_map_lazy_init(vorbis_block      *vb,
114                                  vorbis_info_floor *infoX,
115                                  vorbis_look_floor0 *look){
116   if(!look->linearmap[vb->W]){
117     vorbis_dsp_state   *vd=vb->vd;
118     vorbis_info        *vi=vd->vi;
119     codec_setup_info   *ci=(codec_setup_info*)vi->codec_setup;
120     vorbis_info_floor0 *info=(vorbis_info_floor0 *)infoX;
121     int W=vb->W;
122     int n=ci->blocksizes[W]/2,j;
123 
124     /* we choose a scaling constant so that:
125        floor(bark(rate/2-1)*C)=mapped-1
126      floor(bark(rate/2)*C)=mapped */
127     float scale=look->ln/toBARK(info->rate/2.f);
128 
129     /* the mapping from a linear scale to a smaller bark scale is
130        straightforward.  We do *not* make sure that the linear mapping
131        does not skip bark-scale bins; the decoder simply skips them and
132        the encoder may do what it wishes in filling them.  They're
133        necessary in some mapping combinations to keep the scale spacing
134        accurate */
135     look->linearmap[W]=(int*)_ogg_malloc((n+1)*sizeof(**look->linearmap));
136     for(j=0;j<n;j++){
137       int val=floor( toBARK((info->rate/2.f)/n*j)
138                      *scale); /* bark numbers represent band edges */
139       if(val>=look->ln)val=look->ln-1; /* guard against the approximation */
140       look->linearmap[W][j]=val;
141     }
142     look->linearmap[W][j]=-1;
143     look->n[W]=n;
144   }
145 }
146 
floor0_look(vorbis_dsp_state *,vorbis_info_floor * i)147 static vorbis_look_floor *floor0_look(vorbis_dsp_state* /* vd */,
148                                       vorbis_info_floor *i){
149   vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
150   vorbis_look_floor0 *look=(vorbis_look_floor0*)_ogg_calloc(1,sizeof(*look));
151   look->m=info->order;
152   look->ln=info->barkmap;
153   look->vi=info;
154 
155   look->linearmap=(int**)_ogg_calloc(2,sizeof(*look->linearmap));
156 
157   return look;
158 }
159 
floor0_inverse1(vorbis_block * vb,vorbis_look_floor * i)160 static void *floor0_inverse1(vorbis_block *vb,vorbis_look_floor *i){
161   vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
162   vorbis_info_floor0 *info=look->vi;
163   int j,k;
164 
165   int ampraw=oggpack_read(&vb->opb,info->ampbits);
166   if(ampraw>0){ /* also handles the -1 out of data case */
167     long maxval=(1<<info->ampbits)-1;
168     float amp=(float)ampraw/maxval*info->ampdB;
169     int booknum=oggpack_read(&vb->opb,_ilog(info->numbooks));
170 
171     if(booknum!=-1 && booknum<info->numbooks){ /* be paranoid */
172       codec_setup_info  *ci=(codec_setup_info *)vb->vd->vi->codec_setup;
173       codebook *b=ci->fullbooks+info->books[booknum];
174       float last=0.f;
175 
176       /* the additional b->dim is a guard against any possible stack
177          smash; b->dim is provably more than we can overflow the
178          vector */
179       float *lsp=(float*)_vorbis_block_alloc(vb,sizeof(*lsp)*(look->m+b->dim+1));
180 
181       for(j=0;j<look->m;j+=b->dim)
182         if(vorbis_book_decodev_set(b,lsp+j,&vb->opb,b->dim)==-1)goto eop;
183       for(j=0;j<look->m;){
184         for(k=0;k<b->dim;k++,j++)lsp[j]+=last;
185         last=lsp[j-1];
186       }
187 
188       lsp[look->m]=amp;
189       return(lsp);
190     }
191   }
192  eop:
193   return(NULL);
194 }
195 
floor0_inverse2(vorbis_block * vb,vorbis_look_floor * i,void * memo,float * out)196 static int floor0_inverse2(vorbis_block *vb,vorbis_look_floor *i,
197                            void *memo,float *out){
198   vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
199   vorbis_info_floor0 *info=look->vi;
200 
201   floor0_map_lazy_init(vb,info,look);
202 
203   if(memo){
204     float *lsp=(float *)memo;
205     float amp=lsp[look->m];
206 
207     /* take the coefficients back to a spectral envelope curve */
208     vorbis_lsp_to_curve(out,
209                         look->linearmap[vb->W],
210                         look->n[vb->W],
211                         look->ln,
212                         lsp,look->m,amp,(float)info->ampdB);
213     return(1);
214   }
215   memset(out,0,sizeof(*out)*look->n[vb->W]);
216   return(0);
217 }
218 
219 /* export hooks */
220 const vorbis_func_floor floor0_exportbundle={
221   NULL,&floor0_unpack,&floor0_look,&floor0_free_info,
222   &floor0_free_look,&floor0_inverse1,&floor0_inverse2
223 };
224