|
1 /******************************************************************** |
|
2 * * |
|
3 * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * |
|
4 * * |
|
5 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * |
|
6 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * |
|
7 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * |
|
8 * * |
|
9 * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * |
|
10 * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * |
|
11 * * |
|
12 ******************************************************************** |
|
13 |
|
14 function: residue backend 0, 1 and 2 implementation |
|
15 |
|
16 ********************************************************************/ |
|
17 |
|
18 #include <stdlib.h> |
|
19 #include <string.h> |
|
20 #include <math.h> |
|
21 #include <ogg/ogg.h> |
|
22 #include "ivorbiscodec.h" |
|
23 #include "codec_internal.h" |
|
24 #include "registry.h" |
|
25 #include "codebook.h" |
|
26 #include "misc.h" |
|
27 #include "os.h" |
|
28 #include "block.h" |
|
29 |
|
30 typedef struct { |
|
31 vorbis_info_residue0 *info; |
|
32 int map; |
|
33 |
|
34 int parts; |
|
35 int stages; |
|
36 codebook *fullbooks; |
|
37 codebook *phrasebook; |
|
38 codebook ***partbooks; |
|
39 |
|
40 int partvals; |
|
41 int **decodemap; |
|
42 |
|
43 } vorbis_look_residue0; |
|
44 |
|
45 void res0_free_info(vorbis_info_residue *i){ |
|
46 vorbis_info_residue0 *info=(vorbis_info_residue0 *)i; |
|
47 if(info){ |
|
48 memset(info,0,sizeof(*info)); |
|
49 _ogg_free(info); |
|
50 } |
|
51 } |
|
52 |
|
53 void res0_free_look(vorbis_look_residue *i){ |
|
54 int j; |
|
55 if(i){ |
|
56 |
|
57 vorbis_look_residue0 *look=(vorbis_look_residue0 *)i; |
|
58 |
|
59 for(j=0;j<look->parts;j++) |
|
60 if(look->partbooks[j])_ogg_free(look->partbooks[j]); |
|
61 _ogg_free(look->partbooks); |
|
62 for(j=0;j<look->partvals;j++) |
|
63 _ogg_free(look->decodemap[j]); |
|
64 _ogg_free(look->decodemap); |
|
65 |
|
66 memset(look,0,sizeof(*look)); |
|
67 _ogg_free(look); |
|
68 } |
|
69 } |
|
70 |
|
71 static int ilog(unsigned int v){ |
|
72 int ret=0; |
|
73 while(v){ |
|
74 ret++; |
|
75 v>>=1; |
|
76 } |
|
77 return(ret); |
|
78 } |
|
79 |
|
80 static int icount(unsigned int v){ |
|
81 int ret=0; |
|
82 while(v){ |
|
83 ret+=v&1; |
|
84 v>>=1; |
|
85 } |
|
86 return(ret); |
|
87 } |
|
88 |
|
89 /* vorbis_info is for range checking */ |
|
90 vorbis_info_residue *res0_unpack(vorbis_info *vi,oggpack_buffer *opb){ |
|
91 int j,acc=0; |
|
92 vorbis_info_residue0 *info=(vorbis_info_residue0 *)_ogg_calloc(1,sizeof(*info)); |
|
93 codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; |
|
94 |
|
95 info->begin=oggpack_read(opb,24); |
|
96 info->end=oggpack_read(opb,24); |
|
97 info->grouping=oggpack_read(opb,24)+1; |
|
98 info->partitions=oggpack_read(opb,6)+1; |
|
99 info->groupbook=oggpack_read(opb,8); |
|
100 |
|
101 /* check for premature EOP */ |
|
102 if(info->groupbook<0)goto errout; |
|
103 |
|
104 for(j=0;j<info->partitions;j++){ |
|
105 int cascade=oggpack_read(opb,3); |
|
106 int cflag=oggpack_read(opb,1); |
|
107 if(cflag<0) goto errout; |
|
108 if(cflag){ |
|
109 int c=oggpack_read(opb,5); |
|
110 if(c<0) goto errout; |
|
111 cascade|=(c<<3); |
|
112 } |
|
113 info->secondstages[j]=cascade; |
|
114 |
|
115 acc+=icount(cascade); |
|
116 } |
|
117 for(j=0;j<acc;j++){ |
|
118 int book=oggpack_read(opb,8); |
|
119 if(book<0) goto errout; |
|
120 info->booklist[j]=book; |
|
121 } |
|
122 |
|
123 if(info->groupbook>=ci->books)goto errout; |
|
124 for(j=0;j<acc;j++){ |
|
125 if(info->booklist[j]>=ci->books)goto errout; |
|
126 if(ci->book_param[info->booklist[j]]->maptype==0)goto errout; |
|
127 } |
|
128 |
|
129 /* verify the phrasebook is not specifying an impossible or |
|
130 inconsistent partitioning scheme. */ |
|
131 /* modify the phrasebook ranging check from r16327; an early beta |
|
132 encoder had a bug where it used an oversized phrasebook by |
|
133 accident. These files should continue to be playable, but don't |
|
134 allow an exploit */ |
|
135 { |
|
136 int entries = ci->book_param[info->groupbook]->entries; |
|
137 int dim = ci->book_param[info->groupbook]->dim; |
|
138 int partvals = 1; |
|
139 if (dim<1) goto errout; |
|
140 while(dim>0){ |
|
141 partvals *= info->partitions; |
|
142 if(partvals > entries) goto errout; |
|
143 dim--; |
|
144 } |
|
145 info->partvals = partvals; |
|
146 } |
|
147 |
|
148 return(info); |
|
149 errout: |
|
150 res0_free_info(info); |
|
151 return(NULL); |
|
152 } |
|
153 |
|
154 vorbis_look_residue *res0_look(vorbis_dsp_state *vd,vorbis_info_mode *vm, |
|
155 vorbis_info_residue *vr){ |
|
156 vorbis_info_residue0 *info=(vorbis_info_residue0 *)vr; |
|
157 vorbis_look_residue0 *look=(vorbis_look_residue0 *)_ogg_calloc(1,sizeof(*look)); |
|
158 codec_setup_info *ci=(codec_setup_info *)vd->vi->codec_setup; |
|
159 |
|
160 int j,k,acc=0; |
|
161 int dim; |
|
162 int maxstage=0; |
|
163 look->info=info; |
|
164 look->map=vm->mapping; |
|
165 |
|
166 look->parts=info->partitions; |
|
167 look->fullbooks=ci->fullbooks; |
|
168 look->phrasebook=ci->fullbooks+info->groupbook; |
|
169 dim=look->phrasebook->dim; |
|
170 |
|
171 look->partbooks=(codebook ***)_ogg_calloc(look->parts,sizeof(*look->partbooks)); |
|
172 |
|
173 for(j=0;j<look->parts;j++){ |
|
174 int stages=ilog(info->secondstages[j]); |
|
175 if(stages){ |
|
176 if(stages>maxstage)maxstage=stages; |
|
177 look->partbooks[j]=(codebook **)_ogg_calloc(stages,sizeof(*look->partbooks[j])); |
|
178 for(k=0;k<stages;k++) |
|
179 if(info->secondstages[j]&(1<<k)){ |
|
180 look->partbooks[j][k]=ci->fullbooks+info->booklist[acc++]; |
|
181 #ifdef TRAIN_RES |
|
182 look->training_data[k][j]=calloc(look->partbooks[j][k]->entries, |
|
183 sizeof(***look->training_data)); |
|
184 #endif |
|
185 } |
|
186 } |
|
187 } |
|
188 |
|
189 look->partvals=look->parts; |
|
190 for(j=1;j<dim;j++)look->partvals*=look->parts; |
|
191 look->stages=maxstage; |
|
192 look->decodemap=(int **)_ogg_malloc(look->partvals*sizeof(*look->decodemap)); |
|
193 for(j=0;j<look->partvals;j++){ |
|
194 long val=j; |
|
195 long mult=look->partvals/look->parts; |
|
196 look->decodemap[j]=(int *)_ogg_malloc(dim*sizeof(*look->decodemap[j])); |
|
197 for(k=0;k<dim;k++){ |
|
198 long deco=val/mult; |
|
199 val-=deco*mult; |
|
200 mult/=look->parts; |
|
201 look->decodemap[j][k]=deco; |
|
202 } |
|
203 } |
|
204 |
|
205 return(look); |
|
206 } |
|
207 |
|
208 |
|
209 /* a truncated packet here just means 'stop working'; it's not an error */ |
|
210 static int _01inverse(vorbis_block *vb,vorbis_look_residue *vl, |
|
211 ogg_int32_t **in,int ch, |
|
212 long (*decodepart)(codebook *, ogg_int32_t *, |
|
213 oggpack_buffer *,int,int)){ |
|
214 |
|
215 long i,j,k,l,s; |
|
216 vorbis_look_residue0 *look=(vorbis_look_residue0 *)vl; |
|
217 vorbis_info_residue0 *info=look->info; |
|
218 |
|
219 /* move all this setup out later */ |
|
220 int samples_per_partition=info->grouping; |
|
221 int partitions_per_word=look->phrasebook->dim; |
|
222 int max=vb->pcmend>>1; |
|
223 int end=(info->end<max?info->end:max); |
|
224 int n=end-info->begin; |
|
225 |
|
226 if(n>0){ |
|
227 int partvals=n/samples_per_partition; |
|
228 int partwords=(partvals+partitions_per_word-1)/partitions_per_word; |
|
229 int ***partword=(int ***)alloca(ch*sizeof(*partword)); |
|
230 |
|
231 for(j=0;j<ch;j++) |
|
232 partword[j]=(int **)_vorbis_block_alloc(vb,partwords*sizeof(*partword[j])); |
|
233 |
|
234 for(s=0;s<look->stages;s++){ |
|
235 |
|
236 /* each loop decodes on partition codeword containing |
|
237 partitions_pre_word partitions */ |
|
238 for(i=0,l=0;i<partvals;l++){ |
|
239 if(s==0){ |
|
240 /* fetch the partition word for each channel */ |
|
241 for(j=0;j<ch;j++){ |
|
242 int temp=vorbis_book_decode(look->phrasebook,&vb->opb); |
|
243 if(temp==-1 || temp>=info->partvals)goto eopbreak; |
|
244 partword[j][l]=look->decodemap[temp]; |
|
245 if(partword[j][l]==NULL)goto errout; |
|
246 } |
|
247 } |
|
248 |
|
249 /* now we decode residual values for the partitions */ |
|
250 for(k=0;k<partitions_per_word && i<partvals;k++,i++) |
|
251 for(j=0;j<ch;j++){ |
|
252 long offset=info->begin+i*samples_per_partition; |
|
253 if(info->secondstages[partword[j][l][k]]&(1<<s)){ |
|
254 codebook *stagebook=look->partbooks[partword[j][l][k]][s]; |
|
255 if(stagebook){ |
|
256 if(decodepart(stagebook,in[j]+offset,&vb->opb, |
|
257 samples_per_partition,-8)==-1)goto eopbreak; |
|
258 } |
|
259 } |
|
260 } |
|
261 } |
|
262 } |
|
263 } |
|
264 errout: |
|
265 eopbreak: |
|
266 return(0); |
|
267 } |
|
268 |
|
269 int res0_inverse(vorbis_block *vb,vorbis_look_residue *vl, |
|
270 ogg_int32_t **in,int *nonzero,int ch){ |
|
271 int i,used=0; |
|
272 for(i=0;i<ch;i++) |
|
273 if(nonzero[i]) |
|
274 in[used++]=in[i]; |
|
275 if(used) |
|
276 return(_01inverse(vb,vl,in,used,vorbis_book_decodevs_add)); |
|
277 else |
|
278 return(0); |
|
279 } |
|
280 |
|
281 int res1_inverse(vorbis_block *vb,vorbis_look_residue *vl, |
|
282 ogg_int32_t **in,int *nonzero,int ch){ |
|
283 int i,used=0; |
|
284 for(i=0;i<ch;i++) |
|
285 if(nonzero[i]) |
|
286 in[used++]=in[i]; |
|
287 if(used) |
|
288 return(_01inverse(vb,vl,in,used,vorbis_book_decodev_add)); |
|
289 else |
|
290 return(0); |
|
291 } |
|
292 |
|
293 /* duplicate code here as speed is somewhat more important */ |
|
294 int res2_inverse(vorbis_block *vb,vorbis_look_residue *vl, |
|
295 ogg_int32_t **in,int *nonzero,int ch){ |
|
296 long i,k,l,s; |
|
297 vorbis_look_residue0 *look=(vorbis_look_residue0 *)vl; |
|
298 vorbis_info_residue0 *info=look->info; |
|
299 |
|
300 /* move all this setup out later */ |
|
301 int samples_per_partition=info->grouping; |
|
302 int partitions_per_word=look->phrasebook->dim; |
|
303 int max=(vb->pcmend*ch)>>1; |
|
304 int end=(info->end<max?info->end:max); |
|
305 int n=end-info->begin; |
|
306 |
|
307 if(n>0){ |
|
308 |
|
309 int partvals=n/samples_per_partition; |
|
310 int partwords=(partvals+partitions_per_word-1)/partitions_per_word; |
|
311 int **partword=(int **)_vorbis_block_alloc(vb,partwords*sizeof(*partword)); |
|
312 int beginoff=info->begin/ch; |
|
313 |
|
314 for(i=0;i<ch;i++)if(nonzero[i])break; |
|
315 if(i==ch)return(0); /* no nonzero vectors */ |
|
316 |
|
317 samples_per_partition/=ch; |
|
318 |
|
319 for(s=0;s<look->stages;s++){ |
|
320 for(i=0,l=0;i<partvals;l++){ |
|
321 |
|
322 if(s==0){ |
|
323 /* fetch the partition word */ |
|
324 int temp=vorbis_book_decode(look->phrasebook,&vb->opb); |
|
325 if(temp==-1 || temp>=info->partvals)goto eopbreak; |
|
326 partword[l]=look->decodemap[temp]; |
|
327 if(partword[l]==NULL)goto errout; |
|
328 } |
|
329 |
|
330 /* now we decode residual values for the partitions */ |
|
331 for(k=0;k<partitions_per_word && i<partvals;k++,i++) |
|
332 if(info->secondstages[partword[l][k]]&(1<<s)){ |
|
333 codebook *stagebook=look->partbooks[partword[l][k]][s]; |
|
334 |
|
335 if(stagebook){ |
|
336 if(vorbis_book_decodevv_add(stagebook,in, |
|
337 i*samples_per_partition+beginoff,ch, |
|
338 &vb->opb, |
|
339 samples_per_partition,-8)==-1) |
|
340 goto eopbreak; |
|
341 } |
|
342 } |
|
343 } |
|
344 } |
|
345 } |
|
346 errout: |
|
347 eopbreak: |
|
348 return(0); |
|
349 } |
|
350 |
|
351 |
|
352 vorbis_func_residue residue0_exportbundle={ |
|
353 &res0_unpack, |
|
354 &res0_look, |
|
355 &res0_free_info, |
|
356 &res0_free_look, |
|
357 &res0_inverse |
|
358 }; |
|
359 |
|
360 vorbis_func_residue residue1_exportbundle={ |
|
361 &res0_unpack, |
|
362 &res0_look, |
|
363 &res0_free_info, |
|
364 &res0_free_look, |
|
365 &res1_inverse |
|
366 }; |
|
367 |
|
368 vorbis_func_residue residue2_exportbundle={ |
|
369 &res0_unpack, |
|
370 &res0_look, |
|
371 &res0_free_info, |
|
372 &res0_free_look, |
|
373 &res2_inverse |
|
374 }; |