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