added ogg/vorbis source code for ease of building on msvc
[laserbrain_demo] / libs / vorbis / floor0.c
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 18184 2012-02-03 20:55:12Z 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
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
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
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     if(ci->book_param[info->books[j]]->maptype==0)goto err_out;
95     if(ci->book_param[info->books[j]]->dim<1)goto err_out;
96   }
97   return(info);
98
99  err_out:
100   floor0_free_info(info);
101   return(NULL);
102 }
103
104 /* initialize Bark scale and normalization lookups.  We could do this
105    with static tables, but Vorbis allows a number of possible
106    combinations, so it's best to do it computationally.
107
108    The below is authoritative in terms of defining scale mapping.
109    Note that the scale depends on the sampling rate as well as the
110    linear block and mapping sizes */
111
112 static void floor0_map_lazy_init(vorbis_block      *vb,
113                                  vorbis_info_floor *infoX,
114                                  vorbis_look_floor0 *look){
115   if(!look->linearmap[vb->W]){
116     vorbis_dsp_state   *vd=vb->vd;
117     vorbis_info        *vi=vd->vi;
118     codec_setup_info   *ci=vi->codec_setup;
119     vorbis_info_floor0 *info=(vorbis_info_floor0 *)infoX;
120     int W=vb->W;
121     int n=ci->blocksizes[W]/2,j;
122
123     /* we choose a scaling constant so that:
124        floor(bark(rate/2-1)*C)=mapped-1
125      floor(bark(rate/2)*C)=mapped */
126     float scale=look->ln/toBARK(info->rate/2.f);
127
128     /* the mapping from a linear scale to a smaller bark scale is
129        straightforward.  We do *not* make sure that the linear mapping
130        does not skip bark-scale bins; the decoder simply skips them and
131        the encoder may do what it wishes in filling them.  They're
132        necessary in some mapping combinations to keep the scale spacing
133        accurate */
134     look->linearmap[W]=_ogg_malloc((n+1)*sizeof(**look->linearmap));
135     for(j=0;j<n;j++){
136       int val=floor( toBARK((info->rate/2.f)/n*j)
137                      *scale); /* bark numbers represent band edges */
138       if(val>=look->ln)val=look->ln-1; /* guard against the approximation */
139       look->linearmap[W][j]=val;
140     }
141     look->linearmap[W][j]=-1;
142     look->n[W]=n;
143   }
144 }
145
146 static vorbis_look_floor *floor0_look(vorbis_dsp_state *vd,
147                                       vorbis_info_floor *i){
148   vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
149   vorbis_look_floor0 *look=_ogg_calloc(1,sizeof(*look));
150   look->m=info->order;
151   look->ln=info->barkmap;
152   look->vi=info;
153
154   look->linearmap=_ogg_calloc(2,sizeof(*look->linearmap));
155
156   return look;
157 }
158
159 static void *floor0_inverse1(vorbis_block *vb,vorbis_look_floor *i){
160   vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
161   vorbis_info_floor0 *info=look->vi;
162   int j,k;
163
164   int ampraw=oggpack_read(&vb->opb,info->ampbits);
165   if(ampraw>0){ /* also handles the -1 out of data case */
166     long maxval=(1<<info->ampbits)-1;
167     float amp=(float)ampraw/maxval*info->ampdB;
168     int booknum=oggpack_read(&vb->opb,_ilog(info->numbooks));
169
170     if(booknum!=-1 && booknum<info->numbooks){ /* be paranoid */
171       codec_setup_info  *ci=vb->vd->vi->codec_setup;
172       codebook *b=ci->fullbooks+info->books[booknum];
173       float last=0.f;
174
175       /* the additional b->dim is a guard against any possible stack
176          smash; b->dim is provably more than we can overflow the
177          vector */
178       float *lsp=_vorbis_block_alloc(vb,sizeof(*lsp)*(look->m+b->dim+1));
179
180       if(vorbis_book_decodev_set(b,lsp,&vb->opb,look->m)==-1)goto eop;
181       for(j=0;j<look->m;){
182         for(k=0;j<look->m && k<b->dim;k++,j++)lsp[j]+=last;
183         last=lsp[j-1];
184       }
185
186       lsp[look->m]=amp;
187       return(lsp);
188     }
189   }
190  eop:
191   return(NULL);
192 }
193
194 static int floor0_inverse2(vorbis_block *vb,vorbis_look_floor *i,
195                            void *memo,float *out){
196   vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
197   vorbis_info_floor0 *info=look->vi;
198
199   floor0_map_lazy_init(vb,info,look);
200
201   if(memo){
202     float *lsp=(float *)memo;
203     float amp=lsp[look->m];
204
205     /* take the coefficients back to a spectral envelope curve */
206     vorbis_lsp_to_curve(out,
207                         look->linearmap[vb->W],
208                         look->n[vb->W],
209                         look->ln,
210                         lsp,look->m,amp,(float)info->ampdB);
211     return(1);
212   }
213   memset(out,0,sizeof(*out)*look->n[vb->W]);
214   return(0);
215 }
216
217 /* export hooks */
218 const vorbis_func_floor floor0_exportbundle={
219   NULL,&floor0_unpack,&floor0_look,&floor0_free_info,
220   &floor0_free_look,&floor0_inverse1,&floor0_inverse2
221 };