Port r17545 from Tremor.
[platform/upstream/libvorbis.git] / lib / 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$
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   }
96   return(info);
97
98  err_out:
99   floor0_free_info(info);
100   return(NULL);
101 }
102
103 /* initialize Bark scale and normalization lookups.  We could do this
104    with static tables, but Vorbis allows a number of possible
105    combinations, so it's best to do it computationally.
106
107    The below is authoritative in terms of defining scale mapping.
108    Note that the scale depends on the sampling rate as well as the
109    linear block and mapping sizes */
110
111 static void floor0_map_lazy_init(vorbis_block      *vb,
112                                  vorbis_info_floor *infoX,
113                                  vorbis_look_floor0 *look){
114   if(!look->linearmap[vb->W]){
115     vorbis_dsp_state   *vd=vb->vd;
116     vorbis_info        *vi=vd->vi;
117     codec_setup_info   *ci=vi->codec_setup;
118     vorbis_info_floor0 *info=(vorbis_info_floor0 *)infoX;
119     int W=vb->W;
120     int n=ci->blocksizes[W]/2,j;
121
122     /* we choose a scaling constant so that:
123        floor(bark(rate/2-1)*C)=mapped-1
124      floor(bark(rate/2)*C)=mapped */
125     float scale=look->ln/toBARK(info->rate/2.f);
126
127     /* the mapping from a linear scale to a smaller bark scale is
128        straightforward.  We do *not* make sure that the linear mapping
129        does not skip bark-scale bins; the decoder simply skips them and
130        the encoder may do what it wishes in filling them.  They're
131        necessary in some mapping combinations to keep the scale spacing
132        accurate */
133     look->linearmap[W]=_ogg_malloc((n+1)*sizeof(**look->linearmap));
134     for(j=0;j<n;j++){
135       int val=floor( toBARK((info->rate/2.f)/n*j)
136                      *scale); /* bark numbers represent band edges */
137       if(val>=look->ln)val=look->ln-1; /* guard against the approximation */
138       look->linearmap[W][j]=val;
139     }
140     look->linearmap[W][j]=-1;
141     look->n[W]=n;
142   }
143 }
144
145 static vorbis_look_floor *floor0_look(vorbis_dsp_state *vd,
146                                       vorbis_info_floor *i){
147   vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
148   vorbis_look_floor0 *look=_ogg_calloc(1,sizeof(*look));
149   look->m=info->order;
150   look->ln=info->barkmap;
151   look->vi=info;
152
153   look->linearmap=_ogg_calloc(2,sizeof(*look->linearmap));
154
155   return look;
156 }
157
158 static void *floor0_inverse1(vorbis_block *vb,vorbis_look_floor *i){
159   vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
160   vorbis_info_floor0 *info=look->vi;
161   int j,k;
162
163   int ampraw=oggpack_read(&vb->opb,info->ampbits);
164   if(ampraw>0){ /* also handles the -1 out of data case */
165     long maxval=(1<<info->ampbits)-1;
166     float amp=(float)ampraw/maxval*info->ampdB;
167     int booknum=oggpack_read(&vb->opb,_ilog(info->numbooks));
168
169     if(booknum!=-1 && booknum<info->numbooks){ /* be paranoid */
170       codec_setup_info  *ci=vb->vd->vi->codec_setup;
171       codebook *b=ci->fullbooks+info->books[booknum];
172       float last=0.f;
173
174       /* the additional b->dim is a guard against any possible stack
175          smash; b->dim is provably more than we can overflow the
176          vector */
177       float *lsp=_vorbis_block_alloc(vb,sizeof(*lsp)*(look->m+b->dim+1));
178
179       for(j=0;j<look->m;j+=b->dim)
180         if(vorbis_book_decodev_set(b,lsp+j,&vb->opb,b->dim)==-1)goto eop;
181       for(j=0;j<look->m;){
182         for(k=0;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 };