Line | Count | Source |
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 | 4.19k | void res0_free_info(vorbis_info_residue *i){ |
46 | 4.19k | vorbis_info_residue0 *info=(vorbis_info_residue0 *)i; |
47 | 4.19k | if(info){ |
48 | 4.19k | memset(info,0,sizeof(*info)); |
49 | 4.19k | _ogg_free(info); |
50 | 4.19k | } |
51 | 4.19k | } |
52 | | |
53 | 7.09k | void res0_free_look(vorbis_look_residue *i){ |
54 | 7.09k | int j; |
55 | 7.09k | if(i){ |
56 | | |
57 | 7.09k | vorbis_look_residue0 *look=(vorbis_look_residue0 *)i; |
58 | | |
59 | 15.6k | for(j=0;j<look->parts;j++) |
60 | 8.59k | if(look->partbooks[j])_ogg_free(look->partbooks[j]); |
61 | 7.09k | _ogg_free(look->partbooks); |
62 | 36.5k | for(j=0;j<look->partvals;j++) |
63 | 29.4k | _ogg_free(look->decodemap[j]); |
64 | 7.09k | _ogg_free(look->decodemap); |
65 | | |
66 | 7.09k | memset(look,0,sizeof(*look)); |
67 | 7.09k | _ogg_free(look); |
68 | 7.09k | } |
69 | 7.09k | } |
70 | | |
71 | 8.59k | static int ilog(unsigned int v){ |
72 | 8.59k | int ret=0; |
73 | 18.0k | while(v){ |
74 | 9.47k | ret++; |
75 | 9.47k | v>>=1; |
76 | 9.47k | } |
77 | 8.59k | return(ret); |
78 | 8.59k | } |
79 | | |
80 | 6.54k | static int icount(unsigned int v){ |
81 | 6.54k | int ret=0; |
82 | 17.4k | while(v){ |
83 | 10.9k | ret+=v&1; |
84 | 10.9k | v>>=1; |
85 | 10.9k | } |
86 | 6.54k | return(ret); |
87 | 6.54k | } |
88 | | |
89 | | /* vorbis_info is for range checking */ |
90 | 4.19k | vorbis_info_residue *res0_unpack(vorbis_info *vi,oggpack_buffer *opb){ |
91 | 4.19k | int j,acc=0; |
92 | 4.19k | vorbis_info_residue0 *info=(vorbis_info_residue0 *)_ogg_calloc(1,sizeof(*info)); |
93 | 4.19k | codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; |
94 | | |
95 | 4.19k | info->begin=oggpack_read(opb,24); |
96 | 4.19k | info->end=oggpack_read(opb,24); |
97 | 4.19k | info->grouping=oggpack_read(opb,24)+1; |
98 | 4.19k | info->partitions=oggpack_read(opb,6)+1; |
99 | 4.19k | info->groupbook=oggpack_read(opb,8); |
100 | | |
101 | | /* check for premature EOP */ |
102 | 4.19k | if(info->groupbook<0)goto errout; |
103 | | |
104 | 10.7k | for(j=0;j<info->partitions;j++){ |
105 | 6.55k | int cascade=oggpack_read(opb,3); |
106 | 6.55k | int cflag=oggpack_read(opb,1); |
107 | 6.55k | if(cflag<0) goto errout; |
108 | 6.54k | if(cflag){ |
109 | 1.59k | int c=oggpack_read(opb,5); |
110 | 1.59k | if(c<0) goto errout; |
111 | 1.59k | cascade|=(c<<3); |
112 | 1.59k | } |
113 | 6.54k | info->secondstages[j]=cascade; |
114 | | |
115 | 6.54k | acc+=icount(cascade); |
116 | 6.54k | } |
117 | 8.51k | for(j=0;j<acc;j++){ |
118 | 4.34k | int book=oggpack_read(opb,8); |
119 | 4.34k | if(book<0) goto errout; |
120 | 4.33k | info->booklist[j]=book; |
121 | 4.33k | } |
122 | | |
123 | 4.17k | if(info->groupbook>=ci->books)goto errout; |
124 | 8.24k | for(j=0;j<acc;j++){ |
125 | 4.07k | if(info->booklist[j]>=ci->books)goto errout; |
126 | 4.07k | if(ci->book_param[info->booklist[j]]->maptype==0)goto errout; |
127 | 4.07k | } |
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 | 4.16k | { |
136 | 4.16k | int entries = ci->book_param[info->groupbook]->entries; |
137 | 4.16k | int dim = ci->book_param[info->groupbook]->dim; |
138 | 4.16k | int partvals = 1; |
139 | 4.16k | if (dim<1) goto errout; |
140 | 39.5M | while(dim>0){ |
141 | 39.5M | partvals *= info->partitions; |
142 | 39.5M | if(partvals > entries) goto errout; |
143 | 39.5M | dim--; |
144 | 39.5M | } |
145 | 4.15k | info->partvals = partvals; |
146 | 4.15k | } |
147 | | |
148 | 0 | return(info); |
149 | 33 | errout: |
150 | 33 | res0_free_info(info); |
151 | 33 | return(NULL); |
152 | 4.16k | } |
153 | | |
154 | | vorbis_look_residue *res0_look(vorbis_dsp_state *vd,vorbis_info_mode *vm, |
155 | 7.09k | vorbis_info_residue *vr){ |
156 | 7.09k | vorbis_info_residue0 *info=(vorbis_info_residue0 *)vr; |
157 | 7.09k | vorbis_look_residue0 *look=(vorbis_look_residue0 *)_ogg_calloc(1,sizeof(*look)); |
158 | 7.09k | codec_setup_info *ci=(codec_setup_info *)vd->vi->codec_setup; |
159 | | |
160 | 7.09k | int j,k,acc=0; |
161 | 7.09k | int dim; |
162 | 7.09k | int maxstage=0; |
163 | 7.09k | look->info=info; |
164 | 7.09k | look->map=vm->mapping; |
165 | | |
166 | 7.09k | look->parts=info->partitions; |
167 | 7.09k | look->fullbooks=ci->fullbooks; |
168 | 7.09k | look->phrasebook=ci->fullbooks+info->groupbook; |
169 | 7.09k | dim=look->phrasebook->dim; |
170 | | |
171 | 7.09k | look->partbooks=(codebook ***)_ogg_calloc(look->parts,sizeof(*look->partbooks)); |
172 | | |
173 | 15.6k | for(j=0;j<look->parts;j++){ |
174 | 8.59k | int stages=ilog(info->secondstages[j]); |
175 | 8.59k | if(stages){ |
176 | 2.61k | if(stages>maxstage)maxstage=stages; |
177 | 2.61k | look->partbooks[j]=(codebook **)_ogg_calloc(stages,sizeof(*look->partbooks[j])); |
178 | 12.0k | for(k=0;k<stages;k++) |
179 | 9.47k | if(info->secondstages[j]&(1<<k)){ |
180 | 3.75k | 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 | 3.75k | } |
186 | 2.61k | } |
187 | 8.59k | } |
188 | | |
189 | 7.09k | look->partvals=look->parts; |
190 | 105M | for(j=1;j<dim;j++)look->partvals*=look->parts; |
191 | 7.09k | look->stages=maxstage; |
192 | 7.09k | look->decodemap=(int **)_ogg_malloc(look->partvals*sizeof(*look->decodemap)); |
193 | 36.5k | for(j=0;j<look->partvals;j++){ |
194 | 29.4k | long val=j; |
195 | 29.4k | long mult=look->partvals/look->parts; |
196 | 29.4k | look->decodemap[j]=(int *)_ogg_malloc(dim*sizeof(*look->decodemap[j])); |
197 | 105M | for(k=0;k<dim;k++){ |
198 | 105M | long deco=val/mult; |
199 | 105M | val-=deco*mult; |
200 | 105M | mult/=look->parts; |
201 | 105M | look->decodemap[j][k]=deco; |
202 | 105M | } |
203 | 29.4k | } |
204 | | |
205 | 7.09k | return(look); |
206 | 7.09k | } |
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 | 7.96k | oggpack_buffer *,int,int)){ |
214 | | |
215 | 7.96k | long i,j,k,l,s; |
216 | 7.96k | vorbis_look_residue0 *look=(vorbis_look_residue0 *)vl; |
217 | 7.96k | vorbis_info_residue0 *info=look->info; |
218 | | |
219 | | /* move all this setup out later */ |
220 | 7.96k | int samples_per_partition=info->grouping; |
221 | 7.96k | int partitions_per_word=look->phrasebook->dim; |
222 | 7.96k | int max=vb->pcmend>>1; |
223 | 7.96k | int end=(info->end<max?info->end:max); |
224 | 7.96k | int n=end-info->begin; |
225 | | |
226 | 7.96k | if(n>0){ |
227 | 4.84k | int partvals=n/samples_per_partition; |
228 | 4.84k | int partwords=(partvals+partitions_per_word-1)/partitions_per_word; |
229 | 4.84k | int ***partword=(int ***)alloca(ch*sizeof(*partword)); |
230 | | |
231 | 13.3k | for(j=0;j<ch;j++) |
232 | 8.51k | partword[j]=(int **)_vorbis_block_alloc(vb,partwords*sizeof(*partword[j])); |
233 | | |
234 | 11.7k | for(s=0;s<look->stages;s++){ |
235 | | |
236 | | /* each loop decodes on partition codeword containing |
237 | | partitions_pre_word partitions */ |
238 | 15.7k | for(i=0,l=0;i<partvals;l++){ |
239 | 8.85k | if(s==0){ |
240 | | /* fetch the partition word for each channel */ |
241 | 8.97k | for(j=0;j<ch;j++){ |
242 | 6.04k | int temp=vorbis_book_decode(look->phrasebook,&vb->opb); |
243 | 6.04k | if(temp==-1 || temp>=info->partvals)goto eopbreak; |
244 | 4.97k | partword[j][l]=look->decodemap[temp]; |
245 | 4.97k | if(partword[j][l]==NULL)goto errout; |
246 | 4.97k | } |
247 | 4.00k | } |
248 | | |
249 | | /* now we decode residual values for the partitions */ |
250 | 113k | for(k=0;k<partitions_per_word && i<partvals;k++,i++) |
251 | 235k | for(j=0;j<ch;j++){ |
252 | 130k | long offset=info->begin+i*samples_per_partition; |
253 | 130k | if(info->secondstages[partword[j][l][k]]&(1<<s)){ |
254 | 20.6k | codebook *stagebook=look->partbooks[partword[j][l][k]][s]; |
255 | 20.6k | if(stagebook){ |
256 | 20.6k | if(decodepart(stagebook,in[j]+offset,&vb->opb, |
257 | 20.6k | samples_per_partition,-8)==-1)goto eopbreak; |
258 | 20.6k | } |
259 | 20.6k | } |
260 | 130k | } |
261 | 7.78k | } |
262 | 9.04k | } |
263 | 4.84k | } |
264 | 5.85k | errout: |
265 | 7.96k | eopbreak: |
266 | 7.96k | return(0); |
267 | 5.85k | } |
268 | | |
269 | | int res0_inverse(vorbis_block *vb,vorbis_look_residue *vl, |
270 | 9.86k | ogg_int32_t **in,int *nonzero,int ch){ |
271 | 9.86k | int i,used=0; |
272 | 914k | for(i=0;i<ch;i++) |
273 | 904k | if(nonzero[i]) |
274 | 19.1k | in[used++]=in[i]; |
275 | 9.86k | if(used) |
276 | 5.39k | return(_01inverse(vb,vl,in,used,vorbis_book_decodevs_add)); |
277 | 4.46k | else |
278 | 4.46k | return(0); |
279 | 9.86k | } |
280 | | |
281 | | int res1_inverse(vorbis_block *vb,vorbis_look_residue *vl, |
282 | 4.46k | ogg_int32_t **in,int *nonzero,int ch){ |
283 | 4.46k | int i,used=0; |
284 | 84.9k | for(i=0;i<ch;i++) |
285 | 80.4k | if(nonzero[i]) |
286 | 6.76k | in[used++]=in[i]; |
287 | 4.46k | if(used) |
288 | 2.56k | return(_01inverse(vb,vl,in,used,vorbis_book_decodev_add)); |
289 | 1.89k | else |
290 | 1.89k | return(0); |
291 | 4.46k | } |
292 | | |
293 | | /* duplicate code here as speed is somewhat more important */ |
294 | | int res2_inverse(vorbis_block *vb,vorbis_look_residue *vl, |
295 | 5.97k | ogg_int32_t **in,int *nonzero,int ch){ |
296 | 5.97k | long i,k,l,s; |
297 | 5.97k | vorbis_look_residue0 *look=(vorbis_look_residue0 *)vl; |
298 | 5.97k | vorbis_info_residue0 *info=look->info; |
299 | | |
300 | | /* move all this setup out later */ |
301 | 5.97k | int samples_per_partition=info->grouping; |
302 | 5.97k | int partitions_per_word=look->phrasebook->dim; |
303 | 5.97k | int max=(vb->pcmend*ch)>>1; |
304 | 5.97k | int end=(info->end<max?info->end:max); |
305 | 5.97k | int n=end-info->begin; |
306 | | |
307 | 5.97k | if(n>0){ |
308 | | |
309 | 3.79k | int partvals=n/samples_per_partition; |
310 | 3.79k | int partwords=(partvals+partitions_per_word-1)/partitions_per_word; |
311 | 3.79k | int **partword=(int **)_vorbis_block_alloc(vb,partwords*sizeof(*partword)); |
312 | 3.79k | int beginoff=info->begin/ch; |
313 | | |
314 | 101k | for(i=0;i<ch;i++)if(nonzero[i])break; |
315 | 3.79k | if(i==ch)return(0); /* no nonzero vectors */ |
316 | | |
317 | 2.75k | samples_per_partition/=ch; |
318 | | |
319 | 6.70k | for(s=0;s<look->stages;s++){ |
320 | 16.8k | for(i=0,l=0;i<partvals;l++){ |
321 | | |
322 | 12.9k | if(s==0){ |
323 | | /* fetch the partition word */ |
324 | 5.11k | int temp=vorbis_book_decode(look->phrasebook,&vb->opb); |
325 | 5.11k | if(temp==-1 || temp>=info->partvals)goto eopbreak; |
326 | 4.32k | partword[l]=look->decodemap[temp]; |
327 | 4.32k | if(partword[l]==NULL)goto errout; |
328 | 4.32k | } |
329 | | |
330 | | /* now we decode residual values for the partitions */ |
331 | 369k | for(k=0;k<partitions_per_word && i<partvals;k++,i++) |
332 | 357k | if(info->secondstages[partword[l][k]]&(1<<s)){ |
333 | 146k | codebook *stagebook=look->partbooks[partword[l][k]][s]; |
334 | | |
335 | 146k | if(stagebook){ |
336 | 146k | if(vorbis_book_decodevv_add(stagebook,in, |
337 | 146k | i*samples_per_partition+beginoff,ch, |
338 | 146k | &vb->opb, |
339 | 146k | samples_per_partition,-8)==-1) |
340 | 451 | goto eopbreak; |
341 | 146k | } |
342 | 146k | } |
343 | 12.1k | } |
344 | 5.19k | } |
345 | 2.75k | } |
346 | 3.69k | errout: |
347 | 4.93k | eopbreak: |
348 | 4.93k | return(0); |
349 | 3.69k | } |
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 | | }; |