|
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 19031 2013-12-03 19:20:50Z tterribe $ |
|
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 |
|
151 (void)vd; |
|
152 |
|
153 look->m=info->order; |
|
154 look->ln=info->barkmap; |
|
155 look->vi=info; |
|
156 |
|
157 look->linearmap=_ogg_calloc(2,sizeof(*look->linearmap)); |
|
158 |
|
159 return look; |
|
160 } |
|
161 |
|
162 static void *floor0_inverse1(vorbis_block *vb,vorbis_look_floor *i){ |
|
163 vorbis_look_floor0 *look=(vorbis_look_floor0 *)i; |
|
164 vorbis_info_floor0 *info=look->vi; |
|
165 int j,k; |
|
166 |
|
167 int ampraw=oggpack_read(&vb->opb,info->ampbits); |
|
168 if(ampraw>0){ /* also handles the -1 out of data case */ |
|
169 long maxval=(1<<info->ampbits)-1; |
|
170 float amp=(float)ampraw/maxval*info->ampdB; |
|
171 int booknum=oggpack_read(&vb->opb,_ilog(info->numbooks)); |
|
172 |
|
173 if(booknum!=-1 && booknum<info->numbooks){ /* be paranoid */ |
|
174 codec_setup_info *ci=vb->vd->vi->codec_setup; |
|
175 codebook *b=ci->fullbooks+info->books[booknum]; |
|
176 float last=0.f; |
|
177 |
|
178 /* the additional b->dim is a guard against any possible stack |
|
179 smash; b->dim is provably more than we can overflow the |
|
180 vector */ |
|
181 float *lsp=_vorbis_block_alloc(vb,sizeof(*lsp)*(look->m+b->dim+1)); |
|
182 |
|
183 if(vorbis_book_decodev_set(b,lsp,&vb->opb,look->m)==-1)goto eop; |
|
184 for(j=0;j<look->m;){ |
|
185 for(k=0;j<look->m && k<b->dim;k++,j++)lsp[j]+=last; |
|
186 last=lsp[j-1]; |
|
187 } |
|
188 |
|
189 lsp[look->m]=amp; |
|
190 return(lsp); |
|
191 } |
|
192 } |
|
193 eop: |
|
194 return(NULL); |
|
195 } |
|
196 |
|
197 static int floor0_inverse2(vorbis_block *vb,vorbis_look_floor *i, |
|
198 void *memo,float *out){ |
|
199 vorbis_look_floor0 *look=(vorbis_look_floor0 *)i; |
|
200 vorbis_info_floor0 *info=look->vi; |
|
201 |
|
202 floor0_map_lazy_init(vb,info,look); |
|
203 |
|
204 if(memo){ |
|
205 float *lsp=(float *)memo; |
|
206 float amp=lsp[look->m]; |
|
207 |
|
208 /* take the coefficients back to a spectral envelope curve */ |
|
209 vorbis_lsp_to_curve(out, |
|
210 look->linearmap[vb->W], |
|
211 look->n[vb->W], |
|
212 look->ln, |
|
213 lsp,look->m,amp,(float)info->ampdB); |
|
214 return(1); |
|
215 } |
|
216 memset(out,0,sizeof(*out)*look->n[vb->W]); |
|
217 return(0); |
|
218 } |
|
219 |
|
220 /* export hooks */ |
|
221 const vorbis_func_floor floor0_exportbundle={ |
|
222 NULL,&floor0_unpack,&floor0_look,&floor0_free_info, |
|
223 &floor0_free_look,&floor0_inverse1,&floor0_inverse2 |
|
224 }; |