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