LPC filter generation (for pre- and post-extrapolation) requires
[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-2002             *
9  * by the XIPHOPHORUS Company http://www.xiph.org/                  *
10  *                                                                  *
11  ********************************************************************
12
13  function: floor backend 0 implementation
14  last mod: $Id: floor0.c,v 1.54 2003/03/07 09:13:30 xiphmont Exp $
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   }
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
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
144 static vorbis_look_floor *floor0_look(vorbis_dsp_state *vd,
145                                       vorbis_info_floor *i){
146   int j;
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 vorbis_func_floor floor0_exportbundle={
219   NULL,&floor0_unpack,&floor0_look,&floor0_free_info,
220   &floor0_free_look,&floor0_inverse1,&floor0_inverse2
221 };
222
223
224