Line | Count | Source (jump to first uncovered line) |
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-2010 * |
9 | | * by the Xiph.Org Foundation https://xiph.org/ * |
10 | | * * |
11 | | ******************************************************************** |
12 | | |
13 | | function: residue backend 0, 1 and 2 implementation |
14 | | |
15 | | ********************************************************************/ |
16 | | |
17 | | /* Slow, slow, slow, simpleminded and did I mention it was slow? The |
18 | | encode/decode loops are coded for clarity and performance is not |
19 | | yet even a nagging little idea lurking in the shadows. Oh and BTW, |
20 | | it's slow. */ |
21 | | |
22 | | #include <stdlib.h> |
23 | | #include <string.h> |
24 | | #include <math.h> |
25 | | #include <ogg/ogg.h> |
26 | | #include "vorbis/codec.h" |
27 | | #include "codec_internal.h" |
28 | | #include "registry.h" |
29 | | #include "codebook.h" |
30 | | #include "misc.h" |
31 | | #include "os.h" |
32 | | |
33 | | #if defined(TRAIN_RES) || defined (TRAIN_RESAUX) |
34 | | #include <stdio.h> |
35 | | #endif |
36 | | |
37 | | typedef struct { |
38 | | vorbis_info_residue0 *info; |
39 | | |
40 | | int parts; |
41 | | int stages; |
42 | | codebook *fullbooks; |
43 | | codebook *phrasebook; |
44 | | codebook ***partbooks; |
45 | | |
46 | | int partvals; |
47 | | int **decodemap; |
48 | | |
49 | | long postbits; |
50 | | long phrasebits; |
51 | | long frames; |
52 | | |
53 | | #if defined(TRAIN_RES) || defined(TRAIN_RESAUX) |
54 | | int train_seq; |
55 | | long *training_data[8][64]; |
56 | | float training_max[8][64]; |
57 | | float training_min[8][64]; |
58 | | float tmin; |
59 | | float tmax; |
60 | | int submap; |
61 | | #endif |
62 | | |
63 | | } vorbis_look_residue0; |
64 | | |
65 | 0 | void res0_free_info(vorbis_info_residue *i){ |
66 | 0 | vorbis_info_residue0 *info=(vorbis_info_residue0 *)i; |
67 | 0 | if(info){ |
68 | 0 | memset(info,0,sizeof(*info)); |
69 | 0 | _ogg_free(info); |
70 | 0 | } |
71 | 0 | } |
72 | | |
73 | 0 | void res0_free_look(vorbis_look_residue *i){ |
74 | 0 | int j; |
75 | 0 | if(i){ |
76 | |
|
77 | 0 | vorbis_look_residue0 *look=(vorbis_look_residue0 *)i; |
78 | |
|
79 | | #ifdef TRAIN_RES |
80 | | { |
81 | | int j,k,l; |
82 | | for(j=0;j<look->parts;j++){ |
83 | | /*fprintf(stderr,"partition %d: ",j);*/ |
84 | | for(k=0;k<8;k++) |
85 | | if(look->training_data[k][j]){ |
86 | | char buffer[80]; |
87 | | FILE *of; |
88 | | codebook *statebook=look->partbooks[j][k]; |
89 | | |
90 | | /* long and short into the same bucket by current convention */ |
91 | | sprintf(buffer,"res_sub%d_part%d_pass%d.vqd",look->submap,j,k); |
92 | | of=fopen(buffer,"a"); |
93 | | |
94 | | for(l=0;l<statebook->entries;l++) |
95 | | fprintf(of,"%d:%ld\n",l,look->training_data[k][j][l]); |
96 | | |
97 | | fclose(of); |
98 | | |
99 | | /*fprintf(stderr,"%d(%.2f|%.2f) ",k, |
100 | | look->training_min[k][j],look->training_max[k][j]);*/ |
101 | | |
102 | | _ogg_free(look->training_data[k][j]); |
103 | | look->training_data[k][j]=NULL; |
104 | | } |
105 | | /*fprintf(stderr,"\n");*/ |
106 | | } |
107 | | } |
108 | | fprintf(stderr,"min/max residue: %g::%g\n",look->tmin,look->tmax); |
109 | | |
110 | | /*fprintf(stderr,"residue bit usage %f:%f (%f total)\n", |
111 | | (float)look->phrasebits/look->frames, |
112 | | (float)look->postbits/look->frames, |
113 | | (float)(look->postbits+look->phrasebits)/look->frames);*/ |
114 | | #endif |
115 | | |
116 | | |
117 | | /*vorbis_info_residue0 *info=look->info; |
118 | | |
119 | | fprintf(stderr, |
120 | | "%ld frames encoded in %ld phrasebits and %ld residue bits " |
121 | | "(%g/frame) \n",look->frames,look->phrasebits, |
122 | | look->resbitsflat, |
123 | | (look->phrasebits+look->resbitsflat)/(float)look->frames); |
124 | | |
125 | | for(j=0;j<look->parts;j++){ |
126 | | long acc=0; |
127 | | fprintf(stderr,"\t[%d] == ",j); |
128 | | for(k=0;k<look->stages;k++) |
129 | | if((info->secondstages[j]>>k)&1){ |
130 | | fprintf(stderr,"%ld,",look->resbits[j][k]); |
131 | | acc+=look->resbits[j][k]; |
132 | | } |
133 | | |
134 | | fprintf(stderr,":: (%ld vals) %1.2fbits/sample\n",look->resvals[j], |
135 | | acc?(float)acc/(look->resvals[j]*info->grouping):0); |
136 | | } |
137 | | fprintf(stderr,"\n");*/ |
138 | |
|
139 | 0 | for(j=0;j<look->parts;j++) |
140 | 0 | if(look->partbooks[j])_ogg_free(look->partbooks[j]); |
141 | 0 | _ogg_free(look->partbooks); |
142 | 0 | for(j=0;j<look->partvals;j++) |
143 | 0 | _ogg_free(look->decodemap[j]); |
144 | 0 | _ogg_free(look->decodemap); |
145 | |
|
146 | 0 | memset(look,0,sizeof(*look)); |
147 | 0 | _ogg_free(look); |
148 | 0 | } |
149 | 0 | } |
150 | | |
151 | 0 | static int icount(unsigned int v){ |
152 | 0 | int ret=0; |
153 | 0 | while(v){ |
154 | 0 | ret+=v&1; |
155 | 0 | v>>=1; |
156 | 0 | } |
157 | 0 | return(ret); |
158 | 0 | } |
159 | | |
160 | | |
161 | 0 | void res0_pack(vorbis_info_residue *vr,oggpack_buffer *opb){ |
162 | 0 | vorbis_info_residue0 *info=(vorbis_info_residue0 *)vr; |
163 | 0 | int j,acc=0; |
164 | 0 | oggpack_write(opb,info->begin,24); |
165 | 0 | oggpack_write(opb,info->end,24); |
166 | |
|
167 | 0 | oggpack_write(opb,info->grouping-1,24); /* residue vectors to group and |
168 | | code with a partitioned book */ |
169 | 0 | oggpack_write(opb,info->partitions-1,6); /* possible partition choices */ |
170 | 0 | oggpack_write(opb,info->groupbook,8); /* group huffman book */ |
171 | | |
172 | | /* secondstages is a bitmask; as encoding progresses pass by pass, a |
173 | | bitmask of one indicates this partition class has bits to write |
174 | | this pass */ |
175 | 0 | for(j=0;j<info->partitions;j++){ |
176 | 0 | if(ov_ilog(info->secondstages[j])>3){ |
177 | | /* yes, this is a minor hack due to not thinking ahead */ |
178 | 0 | oggpack_write(opb,info->secondstages[j],3); |
179 | 0 | oggpack_write(opb,1,1); |
180 | 0 | oggpack_write(opb,info->secondstages[j]>>3,5); |
181 | 0 | }else |
182 | 0 | oggpack_write(opb,info->secondstages[j],4); /* trailing zero */ |
183 | 0 | acc+=icount(info->secondstages[j]); |
184 | 0 | } |
185 | 0 | for(j=0;j<acc;j++) |
186 | 0 | oggpack_write(opb,info->booklist[j],8); |
187 | |
|
188 | 0 | } |
189 | | |
190 | | /* vorbis_info is for range checking */ |
191 | 0 | vorbis_info_residue *res0_unpack(vorbis_info *vi,oggpack_buffer *opb){ |
192 | 0 | int j,acc=0; |
193 | 0 | vorbis_info_residue0 *info=_ogg_calloc(1,sizeof(*info)); |
194 | 0 | codec_setup_info *ci=vi->codec_setup; |
195 | |
|
196 | 0 | info->begin=oggpack_read(opb,24); |
197 | 0 | info->end=oggpack_read(opb,24); |
198 | 0 | info->grouping=oggpack_read(opb,24)+1; |
199 | 0 | info->partitions=oggpack_read(opb,6)+1; |
200 | 0 | info->groupbook=oggpack_read(opb,8); |
201 | | |
202 | | /* check for premature EOP */ |
203 | 0 | if(info->groupbook<0)goto errout; |
204 | | |
205 | 0 | for(j=0;j<info->partitions;j++){ |
206 | 0 | int cascade=oggpack_read(opb,3); |
207 | 0 | int cflag=oggpack_read(opb,1); |
208 | 0 | if(cflag<0) goto errout; |
209 | 0 | if(cflag){ |
210 | 0 | int c=oggpack_read(opb,5); |
211 | 0 | if(c<0) goto errout; |
212 | 0 | cascade|=(c<<3); |
213 | 0 | } |
214 | 0 | info->secondstages[j]=cascade; |
215 | |
|
216 | 0 | acc+=icount(cascade); |
217 | 0 | } |
218 | 0 | for(j=0;j<acc;j++){ |
219 | 0 | int book=oggpack_read(opb,8); |
220 | 0 | if(book<0) goto errout; |
221 | 0 | info->booklist[j]=book; |
222 | 0 | } |
223 | | |
224 | 0 | if(info->groupbook>=ci->books)goto errout; |
225 | 0 | for(j=0;j<acc;j++){ |
226 | 0 | if(info->booklist[j]>=ci->books)goto errout; |
227 | 0 | if(ci->book_param[info->booklist[j]]->maptype==0)goto errout; |
228 | 0 | } |
229 | | |
230 | | /* verify the phrasebook is not specifying an impossible or |
231 | | inconsistent partitioning scheme. */ |
232 | | /* modify the phrasebook ranging check from r16327; an early beta |
233 | | encoder had a bug where it used an oversized phrasebook by |
234 | | accident. These files should continue to be playable, but don't |
235 | | allow an exploit */ |
236 | 0 | { |
237 | 0 | int entries = ci->book_param[info->groupbook]->entries; |
238 | 0 | int dim = ci->book_param[info->groupbook]->dim; |
239 | 0 | int partvals = 1; |
240 | 0 | if (dim<1) goto errout; |
241 | 0 | while(dim>0){ |
242 | 0 | partvals *= info->partitions; |
243 | 0 | if(partvals > entries) goto errout; |
244 | 0 | dim--; |
245 | 0 | } |
246 | 0 | info->partvals = partvals; |
247 | 0 | } |
248 | | |
249 | 0 | return(info); |
250 | 0 | errout: |
251 | 0 | res0_free_info(info); |
252 | 0 | return(NULL); |
253 | 0 | } |
254 | | |
255 | | vorbis_look_residue *res0_look(vorbis_dsp_state *vd, |
256 | 0 | vorbis_info_residue *vr){ |
257 | 0 | vorbis_info_residue0 *info=(vorbis_info_residue0 *)vr; |
258 | 0 | vorbis_look_residue0 *look=_ogg_calloc(1,sizeof(*look)); |
259 | 0 | codec_setup_info *ci=vd->vi->codec_setup; |
260 | |
|
261 | 0 | int j,k,acc=0; |
262 | 0 | int dim; |
263 | 0 | int maxstage=0; |
264 | 0 | look->info=info; |
265 | |
|
266 | 0 | look->parts=info->partitions; |
267 | 0 | look->fullbooks=ci->fullbooks; |
268 | 0 | look->phrasebook=ci->fullbooks+info->groupbook; |
269 | 0 | dim=look->phrasebook->dim; |
270 | |
|
271 | 0 | look->partbooks=_ogg_calloc(look->parts,sizeof(*look->partbooks)); |
272 | |
|
273 | 0 | for(j=0;j<look->parts;j++){ |
274 | 0 | int stages=ov_ilog(info->secondstages[j]); |
275 | 0 | if(stages){ |
276 | 0 | if(stages>maxstage)maxstage=stages; |
277 | 0 | look->partbooks[j]=_ogg_calloc(stages,sizeof(*look->partbooks[j])); |
278 | 0 | for(k=0;k<stages;k++) |
279 | 0 | if(info->secondstages[j]&(1<<k)){ |
280 | 0 | look->partbooks[j][k]=ci->fullbooks+info->booklist[acc++]; |
281 | | #ifdef TRAIN_RES |
282 | | look->training_data[k][j]=_ogg_calloc(look->partbooks[j][k]->entries, |
283 | | sizeof(***look->training_data)); |
284 | | #endif |
285 | 0 | } |
286 | 0 | } |
287 | 0 | } |
288 | |
|
289 | 0 | look->partvals=1; |
290 | 0 | for(j=0;j<dim;j++) |
291 | 0 | look->partvals*=look->parts; |
292 | |
|
293 | 0 | look->stages=maxstage; |
294 | 0 | look->decodemap=_ogg_malloc(look->partvals*sizeof(*look->decodemap)); |
295 | 0 | for(j=0;j<look->partvals;j++){ |
296 | 0 | long val=j; |
297 | 0 | long mult=look->partvals/look->parts; |
298 | 0 | look->decodemap[j]=_ogg_malloc(dim*sizeof(*look->decodemap[j])); |
299 | 0 | for(k=0;k<dim;k++){ |
300 | 0 | long deco=val/mult; |
301 | 0 | val-=deco*mult; |
302 | 0 | mult/=look->parts; |
303 | 0 | look->decodemap[j][k]=deco; |
304 | 0 | } |
305 | 0 | } |
306 | | #if defined(TRAIN_RES) || defined (TRAIN_RESAUX) |
307 | | { |
308 | | static int train_seq=0; |
309 | | look->train_seq=train_seq++; |
310 | | } |
311 | | #endif |
312 | 0 | return(look); |
313 | 0 | } |
314 | | |
315 | | /* break an abstraction and copy some code for performance purposes */ |
316 | 0 | static int local_book_besterror(codebook *book,int *a){ |
317 | 0 | int dim=book->dim; |
318 | 0 | int i,j,o; |
319 | 0 | int minval=book->minval; |
320 | 0 | int del=book->delta; |
321 | 0 | int qv=book->quantvals; |
322 | 0 | int ze=(qv>>1); |
323 | 0 | int index=0; |
324 | | /* assumes integer/centered encoder codebook maptype 1 no more than dim 8 */ |
325 | 0 | int p[8]={0,0,0,0,0,0,0,0}; |
326 | |
|
327 | 0 | if(del!=1){ |
328 | 0 | for(i=0,o=dim;i<dim;i++){ |
329 | 0 | int v = (a[--o]-minval+(del>>1))/del; |
330 | 0 | int m = (v<ze ? ((ze-v)<<1)-1 : ((v-ze)<<1)); |
331 | 0 | index = index*qv+ (m<0?0:(m>=qv?qv-1:m)); |
332 | 0 | p[o]=v*del+minval; |
333 | 0 | } |
334 | 0 | }else{ |
335 | 0 | for(i=0,o=dim;i<dim;i++){ |
336 | 0 | int v = a[--o]-minval; |
337 | 0 | int m = (v<ze ? ((ze-v)<<1)-1 : ((v-ze)<<1)); |
338 | 0 | index = index*qv+ (m<0?0:(m>=qv?qv-1:m)); |
339 | 0 | p[o]=v*del+minval; |
340 | 0 | } |
341 | 0 | } |
342 | |
|
343 | 0 | if(book->c->lengthlist[index]<=0){ |
344 | 0 | const static_codebook *c=book->c; |
345 | 0 | int best=-1; |
346 | | /* assumes integer/centered encoder codebook maptype 1 no more than dim 8 */ |
347 | 0 | int e[8]={0,0,0,0,0,0,0,0}; |
348 | 0 | int maxval = book->minval + book->delta*(book->quantvals-1); |
349 | 0 | for(i=0;i<book->entries;i++){ |
350 | 0 | if(c->lengthlist[i]>0){ |
351 | 0 | int this=0; |
352 | 0 | for(j=0;j<dim;j++){ |
353 | 0 | int val=(e[j]-a[j]); |
354 | 0 | this+=val*val; |
355 | 0 | } |
356 | 0 | if(best==-1 || this<best){ |
357 | 0 | memcpy(p,e,sizeof(p)); |
358 | 0 | best=this; |
359 | 0 | index=i; |
360 | 0 | } |
361 | 0 | } |
362 | | /* assumes the value patterning created by the tools in vq/ */ |
363 | 0 | j=0; |
364 | 0 | while(e[j]>=maxval) |
365 | 0 | e[j++]=0; |
366 | 0 | if(e[j]>=0) |
367 | 0 | e[j]+=book->delta; |
368 | 0 | e[j]= -e[j]; |
369 | 0 | } |
370 | 0 | } |
371 | |
|
372 | 0 | if(index>-1){ |
373 | 0 | for(i=0;i<dim;i++) |
374 | 0 | *a++ -= p[i]; |
375 | 0 | } |
376 | |
|
377 | 0 | return(index); |
378 | 0 | } |
379 | | |
380 | | #ifdef TRAIN_RES |
381 | | static int _encodepart(oggpack_buffer *opb,int *vec, int n, |
382 | | codebook *book,long *acc){ |
383 | | #else |
384 | | static int _encodepart(oggpack_buffer *opb,int *vec, int n, |
385 | 0 | codebook *book){ |
386 | 0 | #endif |
387 | 0 | int i,bits=0; |
388 | 0 | int dim=book->dim; |
389 | 0 | int step=n/dim; |
390 | |
|
391 | 0 | for(i=0;i<step;i++){ |
392 | 0 | int entry=local_book_besterror(book,vec+i*dim); |
393 | |
|
394 | | #ifdef TRAIN_RES |
395 | | if(entry>=0) |
396 | | acc[entry]++; |
397 | | #endif |
398 | |
|
399 | 0 | bits+=vorbis_book_encode(book,entry,opb); |
400 | |
|
401 | 0 | } |
402 | |
|
403 | 0 | return(bits); |
404 | 0 | } |
405 | | |
406 | | static long **_01class(vorbis_block *vb,vorbis_look_residue *vl, |
407 | 0 | int **in,int ch){ |
408 | 0 | long i,j,k; |
409 | 0 | vorbis_look_residue0 *look=(vorbis_look_residue0 *)vl; |
410 | 0 | vorbis_info_residue0 *info=look->info; |
411 | | |
412 | | /* move all this setup out later */ |
413 | 0 | int samples_per_partition=info->grouping; |
414 | 0 | int possible_partitions=info->partitions; |
415 | 0 | int n=info->end-info->begin; |
416 | |
|
417 | 0 | int partvals=n/samples_per_partition; |
418 | 0 | long **partword=_vorbis_block_alloc(vb,ch*sizeof(*partword)); |
419 | 0 | float scale=100./samples_per_partition; |
420 | | |
421 | | /* we find the partition type for each partition of each |
422 | | channel. We'll go back and do the interleaved encoding in a |
423 | | bit. For now, clarity */ |
424 | |
|
425 | 0 | for(i=0;i<ch;i++){ |
426 | 0 | partword[i]=_vorbis_block_alloc(vb,n/samples_per_partition*sizeof(*partword[i])); |
427 | 0 | memset(partword[i],0,n/samples_per_partition*sizeof(*partword[i])); |
428 | 0 | } |
429 | |
|
430 | 0 | for(i=0;i<partvals;i++){ |
431 | 0 | int offset=i*samples_per_partition+info->begin; |
432 | 0 | for(j=0;j<ch;j++){ |
433 | 0 | int max=0; |
434 | 0 | int ent=0; |
435 | 0 | for(k=0;k<samples_per_partition;k++){ |
436 | 0 | if(abs(in[j][offset+k])>max)max=abs(in[j][offset+k]); |
437 | 0 | ent+=abs(in[j][offset+k]); |
438 | 0 | } |
439 | 0 | ent*=scale; |
440 | |
|
441 | 0 | for(k=0;k<possible_partitions-1;k++) |
442 | 0 | if(max<=info->classmetric1[k] && |
443 | 0 | (info->classmetric2[k]<0 || ent<info->classmetric2[k])) |
444 | 0 | break; |
445 | |
|
446 | 0 | partword[j][i]=k; |
447 | 0 | } |
448 | 0 | } |
449 | |
|
450 | | #ifdef TRAIN_RESAUX |
451 | | { |
452 | | FILE *of; |
453 | | char buffer[80]; |
454 | | |
455 | | for(i=0;i<ch;i++){ |
456 | | sprintf(buffer,"resaux_%d.vqd",look->train_seq); |
457 | | of=fopen(buffer,"a"); |
458 | | for(j=0;j<partvals;j++) |
459 | | fprintf(of,"%ld, ",partword[i][j]); |
460 | | fprintf(of,"\n"); |
461 | | fclose(of); |
462 | | } |
463 | | } |
464 | | #endif |
465 | 0 | look->frames++; |
466 | |
|
467 | 0 | return(partword); |
468 | 0 | } |
469 | | |
470 | | /* designed for stereo or other modes where the partition size is an |
471 | | integer multiple of the number of channels encoded in the current |
472 | | submap */ |
473 | | static long **_2class(vorbis_block *vb,vorbis_look_residue *vl,int **in, |
474 | 0 | int ch){ |
475 | 0 | long i,j,k,l; |
476 | 0 | vorbis_look_residue0 *look=(vorbis_look_residue0 *)vl; |
477 | 0 | vorbis_info_residue0 *info=look->info; |
478 | | |
479 | | /* move all this setup out later */ |
480 | 0 | int samples_per_partition=info->grouping; |
481 | 0 | int possible_partitions=info->partitions; |
482 | 0 | int n=info->end-info->begin; |
483 | |
|
484 | 0 | int partvals=n/samples_per_partition; |
485 | 0 | long **partword=_vorbis_block_alloc(vb,sizeof(*partword)); |
486 | |
|
487 | | #if defined(TRAIN_RES) || defined (TRAIN_RESAUX) |
488 | | FILE *of; |
489 | | char buffer[80]; |
490 | | #endif |
491 | |
|
492 | 0 | partword[0]=_vorbis_block_alloc(vb,partvals*sizeof(*partword[0])); |
493 | 0 | memset(partword[0],0,partvals*sizeof(*partword[0])); |
494 | |
|
495 | 0 | for(i=0,l=info->begin/ch;i<partvals;i++){ |
496 | 0 | int magmax=0; |
497 | 0 | int angmax=0; |
498 | 0 | for(j=0;j<samples_per_partition;j+=ch){ |
499 | 0 | if(abs(in[0][l])>magmax)magmax=abs(in[0][l]); |
500 | 0 | for(k=1;k<ch;k++) |
501 | 0 | if(abs(in[k][l])>angmax)angmax=abs(in[k][l]); |
502 | 0 | l++; |
503 | 0 | } |
504 | |
|
505 | 0 | for(j=0;j<possible_partitions-1;j++) |
506 | 0 | if(magmax<=info->classmetric1[j] && |
507 | 0 | angmax<=info->classmetric2[j]) |
508 | 0 | break; |
509 | |
|
510 | 0 | partword[0][i]=j; |
511 | |
|
512 | 0 | } |
513 | |
|
514 | | #ifdef TRAIN_RESAUX |
515 | | sprintf(buffer,"resaux_%d.vqd",look->train_seq); |
516 | | of=fopen(buffer,"a"); |
517 | | for(i=0;i<partvals;i++) |
518 | | fprintf(of,"%ld, ",partword[0][i]); |
519 | | fprintf(of,"\n"); |
520 | | fclose(of); |
521 | | #endif |
522 | |
|
523 | 0 | look->frames++; |
524 | |
|
525 | 0 | return(partword); |
526 | 0 | } |
527 | | |
528 | | static int _01forward(oggpack_buffer *opb, |
529 | | vorbis_look_residue *vl, |
530 | | int **in,int ch, |
531 | | long **partword, |
532 | | #ifdef TRAIN_RES |
533 | | int (*encode)(oggpack_buffer *,int *,int, |
534 | | codebook *,long *), |
535 | | int submap |
536 | | #else |
537 | | int (*encode)(oggpack_buffer *,int *,int, |
538 | | codebook *) |
539 | | #endif |
540 | 0 | ){ |
541 | 0 | long i,j,k,s; |
542 | 0 | vorbis_look_residue0 *look=(vorbis_look_residue0 *)vl; |
543 | 0 | vorbis_info_residue0 *info=look->info; |
544 | |
|
545 | | #ifdef TRAIN_RES |
546 | | look->submap=submap; |
547 | | #endif |
548 | | |
549 | | /* move all this setup out later */ |
550 | 0 | int samples_per_partition=info->grouping; |
551 | 0 | int possible_partitions=info->partitions; |
552 | 0 | int partitions_per_word=look->phrasebook->dim; |
553 | 0 | int n=info->end-info->begin; |
554 | |
|
555 | 0 | int partvals=n/samples_per_partition; |
556 | 0 | long resbits[128]; |
557 | 0 | long resvals[128]; |
558 | |
|
559 | | #ifdef TRAIN_RES |
560 | | for(i=0;i<ch;i++) |
561 | | for(j=info->begin;j<info->end;j++){ |
562 | | if(in[i][j]>look->tmax)look->tmax=in[i][j]; |
563 | | if(in[i][j]<look->tmin)look->tmin=in[i][j]; |
564 | | } |
565 | | #endif |
566 | |
|
567 | 0 | memset(resbits,0,sizeof(resbits)); |
568 | 0 | memset(resvals,0,sizeof(resvals)); |
569 | | |
570 | | /* we code the partition words for each channel, then the residual |
571 | | words for a partition per channel until we've written all the |
572 | | residual words for that partition word. Then write the next |
573 | | partition channel words... */ |
574 | |
|
575 | 0 | for(s=0;s<look->stages;s++){ |
576 | |
|
577 | 0 | for(i=0;i<partvals;){ |
578 | | |
579 | | /* first we encode a partition codeword for each channel */ |
580 | 0 | if(s==0){ |
581 | 0 | for(j=0;j<ch;j++){ |
582 | 0 | long val=partword[j][i]; |
583 | 0 | for(k=1;k<partitions_per_word;k++){ |
584 | 0 | val*=possible_partitions; |
585 | 0 | if(i+k<partvals) |
586 | 0 | val+=partword[j][i+k]; |
587 | 0 | } |
588 | | |
589 | | /* training hack */ |
590 | 0 | if(val<look->phrasebook->entries) |
591 | 0 | look->phrasebits+=vorbis_book_encode(look->phrasebook,val,opb); |
592 | | #if 0 /*def TRAIN_RES*/ |
593 | | else |
594 | | fprintf(stderr,"!"); |
595 | | #endif |
596 | |
|
597 | 0 | } |
598 | 0 | } |
599 | | |
600 | | /* now we encode interleaved residual values for the partitions */ |
601 | 0 | for(k=0;k<partitions_per_word && i<partvals;k++,i++){ |
602 | 0 | long offset=i*samples_per_partition+info->begin; |
603 | |
|
604 | 0 | for(j=0;j<ch;j++){ |
605 | 0 | if(s==0)resvals[partword[j][i]]+=samples_per_partition; |
606 | 0 | if(info->secondstages[partword[j][i]]&(1<<s)){ |
607 | 0 | codebook *statebook=look->partbooks[partword[j][i]][s]; |
608 | 0 | if(statebook){ |
609 | 0 | int ret; |
610 | | #ifdef TRAIN_RES |
611 | | long *accumulator=NULL; |
612 | | accumulator=look->training_data[s][partword[j][i]]; |
613 | | { |
614 | | int l; |
615 | | int *samples=in[j]+offset; |
616 | | for(l=0;l<samples_per_partition;l++){ |
617 | | if(samples[l]<look->training_min[s][partword[j][i]]) |
618 | | look->training_min[s][partword[j][i]]=samples[l]; |
619 | | if(samples[l]>look->training_max[s][partword[j][i]]) |
620 | | look->training_max[s][partword[j][i]]=samples[l]; |
621 | | } |
622 | | } |
623 | | ret=encode(opb,in[j]+offset,samples_per_partition, |
624 | | statebook,accumulator); |
625 | | #else |
626 | 0 | ret=encode(opb,in[j]+offset,samples_per_partition, |
627 | 0 | statebook); |
628 | 0 | #endif |
629 | |
|
630 | 0 | look->postbits+=ret; |
631 | 0 | resbits[partword[j][i]]+=ret; |
632 | 0 | } |
633 | 0 | } |
634 | 0 | } |
635 | 0 | } |
636 | 0 | } |
637 | 0 | } |
638 | |
|
639 | 0 | return(0); |
640 | 0 | } |
641 | | |
642 | | /* a truncated packet here just means 'stop working'; it's not an error */ |
643 | | static int _01inverse(vorbis_block *vb,vorbis_look_residue *vl, |
644 | | float **in,int ch, |
645 | | long (*decodepart)(codebook *, float *, |
646 | 0 | oggpack_buffer *,int)){ |
647 | |
|
648 | 0 | long i,j,k,l,s; |
649 | 0 | vorbis_look_residue0 *look=(vorbis_look_residue0 *)vl; |
650 | 0 | vorbis_info_residue0 *info=look->info; |
651 | | |
652 | | /* move all this setup out later */ |
653 | 0 | int samples_per_partition=info->grouping; |
654 | 0 | int partitions_per_word=look->phrasebook->dim; |
655 | 0 | int max=vb->pcmend>>1; |
656 | 0 | int end=(info->end<max?info->end:max); |
657 | 0 | int n=end-info->begin; |
658 | |
|
659 | 0 | if(n>0){ |
660 | 0 | int partvals=n/samples_per_partition; |
661 | 0 | int partwords=(partvals+partitions_per_word-1)/partitions_per_word; |
662 | 0 | int ***partword=alloca(ch*sizeof(*partword)); |
663 | |
|
664 | 0 | for(j=0;j<ch;j++) |
665 | 0 | partword[j]=_vorbis_block_alloc(vb,partwords*sizeof(*partword[j])); |
666 | |
|
667 | 0 | for(s=0;s<look->stages;s++){ |
668 | | |
669 | | /* each loop decodes on partition codeword containing |
670 | | partitions_per_word partitions */ |
671 | 0 | for(i=0,l=0;i<partvals;l++){ |
672 | 0 | if(s==0){ |
673 | | /* fetch the partition word for each channel */ |
674 | 0 | for(j=0;j<ch;j++){ |
675 | 0 | int temp=vorbis_book_decode(look->phrasebook,&vb->opb); |
676 | |
|
677 | 0 | if(temp==-1 || temp>=info->partvals)goto eopbreak; |
678 | 0 | partword[j][l]=look->decodemap[temp]; |
679 | 0 | if(partword[j][l]==NULL)goto errout; |
680 | 0 | } |
681 | 0 | } |
682 | | |
683 | | /* now we decode residual values for the partitions */ |
684 | 0 | for(k=0;k<partitions_per_word && i<partvals;k++,i++) |
685 | 0 | for(j=0;j<ch;j++){ |
686 | 0 | long offset=info->begin+i*samples_per_partition; |
687 | 0 | if(info->secondstages[partword[j][l][k]]&(1<<s)){ |
688 | 0 | codebook *stagebook=look->partbooks[partword[j][l][k]][s]; |
689 | 0 | if(stagebook){ |
690 | 0 | if(decodepart(stagebook,in[j]+offset,&vb->opb, |
691 | 0 | samples_per_partition)==-1)goto eopbreak; |
692 | 0 | } |
693 | 0 | } |
694 | 0 | } |
695 | 0 | } |
696 | 0 | } |
697 | 0 | } |
698 | 0 | errout: |
699 | 0 | eopbreak: |
700 | 0 | return(0); |
701 | 0 | } |
702 | | |
703 | | int res0_inverse(vorbis_block *vb,vorbis_look_residue *vl, |
704 | 0 | float **in,int *nonzero,int ch){ |
705 | 0 | int i,used=0; |
706 | 0 | for(i=0;i<ch;i++) |
707 | 0 | if(nonzero[i]) |
708 | 0 | in[used++]=in[i]; |
709 | 0 | if(used) |
710 | 0 | return(_01inverse(vb,vl,in,used,vorbis_book_decodevs_add)); |
711 | 0 | else |
712 | 0 | return(0); |
713 | 0 | } |
714 | | |
715 | | int res1_forward(oggpack_buffer *opb,vorbis_block *vb,vorbis_look_residue *vl, |
716 | 0 | int **in,int *nonzero,int ch, long **partword, int submap){ |
717 | 0 | int i,used=0; |
718 | 0 | (void)vb; |
719 | 0 | for(i=0;i<ch;i++) |
720 | 0 | if(nonzero[i]) |
721 | 0 | in[used++]=in[i]; |
722 | |
|
723 | 0 | if(used){ |
724 | | #ifdef TRAIN_RES |
725 | | return _01forward(opb,vl,in,used,partword,_encodepart,submap); |
726 | | #else |
727 | 0 | (void)submap; |
728 | 0 | return _01forward(opb,vl,in,used,partword,_encodepart); |
729 | 0 | #endif |
730 | 0 | }else{ |
731 | 0 | return(0); |
732 | 0 | } |
733 | 0 | } |
734 | | |
735 | | long **res1_class(vorbis_block *vb,vorbis_look_residue *vl, |
736 | 0 | int **in,int *nonzero,int ch){ |
737 | 0 | int i,used=0; |
738 | 0 | for(i=0;i<ch;i++) |
739 | 0 | if(nonzero[i]) |
740 | 0 | in[used++]=in[i]; |
741 | 0 | if(used) |
742 | 0 | return(_01class(vb,vl,in,used)); |
743 | 0 | else |
744 | 0 | return(0); |
745 | 0 | } |
746 | | |
747 | | int res1_inverse(vorbis_block *vb,vorbis_look_residue *vl, |
748 | 0 | float **in,int *nonzero,int ch){ |
749 | 0 | int i,used=0; |
750 | 0 | for(i=0;i<ch;i++) |
751 | 0 | if(nonzero[i]) |
752 | 0 | in[used++]=in[i]; |
753 | 0 | if(used) |
754 | 0 | return(_01inverse(vb,vl,in,used,vorbis_book_decodev_add)); |
755 | 0 | else |
756 | 0 | return(0); |
757 | 0 | } |
758 | | |
759 | | long **res2_class(vorbis_block *vb,vorbis_look_residue *vl, |
760 | 0 | int **in,int *nonzero,int ch){ |
761 | 0 | int i,used=0; |
762 | 0 | for(i=0;i<ch;i++) |
763 | 0 | if(nonzero[i])used++; |
764 | 0 | if(used) |
765 | 0 | return(_2class(vb,vl,in,ch)); |
766 | 0 | else |
767 | 0 | return(0); |
768 | 0 | } |
769 | | |
770 | | /* res2 is slightly more different; all the channels are interleaved |
771 | | into a single vector and encoded. */ |
772 | | |
773 | | int res2_forward(oggpack_buffer *opb, |
774 | | vorbis_block *vb,vorbis_look_residue *vl, |
775 | 0 | int **in,int *nonzero,int ch, long **partword,int submap){ |
776 | 0 | long i,j,k,n=vb->pcmend/2,used=0; |
777 | | |
778 | | /* don't duplicate the code; use a working vector hack for now and |
779 | | reshape ourselves into a single channel res1 */ |
780 | | /* ugly; reallocs for each coupling pass :-( */ |
781 | 0 | int *work=_vorbis_block_alloc(vb,ch*n*sizeof(*work)); |
782 | 0 | for(i=0;i<ch;i++){ |
783 | 0 | int *pcm=in[i]; |
784 | 0 | if(nonzero[i])used++; |
785 | 0 | for(j=0,k=i;j<n;j++,k+=ch) |
786 | 0 | work[k]=pcm[j]; |
787 | 0 | } |
788 | |
|
789 | 0 | if(used){ |
790 | | #ifdef TRAIN_RES |
791 | | return _01forward(opb,vl,&work,1,partword,_encodepart,submap); |
792 | | #else |
793 | 0 | (void)submap; |
794 | 0 | return _01forward(opb,vl,&work,1,partword,_encodepart); |
795 | 0 | #endif |
796 | 0 | }else{ |
797 | 0 | return(0); |
798 | 0 | } |
799 | 0 | } |
800 | | |
801 | | /* duplicate code here as speed is somewhat more important */ |
802 | | int res2_inverse(vorbis_block *vb,vorbis_look_residue *vl, |
803 | 0 | float **in,int *nonzero,int ch){ |
804 | 0 | long i,k,l,s; |
805 | 0 | vorbis_look_residue0 *look=(vorbis_look_residue0 *)vl; |
806 | 0 | vorbis_info_residue0 *info=look->info; |
807 | | |
808 | | /* move all this setup out later */ |
809 | 0 | int samples_per_partition=info->grouping; |
810 | 0 | int partitions_per_word=look->phrasebook->dim; |
811 | 0 | int max=(vb->pcmend*ch)>>1; |
812 | 0 | int end=(info->end<max?info->end:max); |
813 | 0 | int n=end-info->begin; |
814 | |
|
815 | 0 | if(n>0){ |
816 | 0 | int partvals=n/samples_per_partition; |
817 | 0 | int partwords=(partvals+partitions_per_word-1)/partitions_per_word; |
818 | 0 | int **partword=_vorbis_block_alloc(vb,partwords*sizeof(*partword)); |
819 | |
|
820 | 0 | for(i=0;i<ch;i++)if(nonzero[i])break; |
821 | 0 | if(i==ch)return(0); /* no nonzero vectors */ |
822 | | |
823 | 0 | for(s=0;s<look->stages;s++){ |
824 | 0 | for(i=0,l=0;i<partvals;l++){ |
825 | |
|
826 | 0 | if(s==0){ |
827 | | /* fetch the partition word */ |
828 | 0 | int temp=vorbis_book_decode(look->phrasebook,&vb->opb); |
829 | 0 | if(temp==-1 || temp>=info->partvals)goto eopbreak; |
830 | 0 | partword[l]=look->decodemap[temp]; |
831 | 0 | if(partword[l]==NULL)goto errout; |
832 | 0 | } |
833 | | |
834 | | /* now we decode residual values for the partitions */ |
835 | 0 | for(k=0;k<partitions_per_word && i<partvals;k++,i++) |
836 | 0 | if(info->secondstages[partword[l][k]]&(1<<s)){ |
837 | 0 | codebook *stagebook=look->partbooks[partword[l][k]][s]; |
838 | |
|
839 | 0 | if(stagebook){ |
840 | 0 | if(vorbis_book_decodevv_add(stagebook,in, |
841 | 0 | i*samples_per_partition+info->begin,ch, |
842 | 0 | &vb->opb,samples_per_partition)==-1) |
843 | 0 | goto eopbreak; |
844 | 0 | } |
845 | 0 | } |
846 | 0 | } |
847 | 0 | } |
848 | 0 | } |
849 | 0 | errout: |
850 | 0 | eopbreak: |
851 | 0 | return(0); |
852 | 0 | } |
853 | | |
854 | | |
855 | | const vorbis_func_residue residue0_exportbundle={ |
856 | | NULL, |
857 | | &res0_unpack, |
858 | | &res0_look, |
859 | | &res0_free_info, |
860 | | &res0_free_look, |
861 | | NULL, |
862 | | NULL, |
863 | | &res0_inverse |
864 | | }; |
865 | | |
866 | | const vorbis_func_residue residue1_exportbundle={ |
867 | | &res0_pack, |
868 | | &res0_unpack, |
869 | | &res0_look, |
870 | | &res0_free_info, |
871 | | &res0_free_look, |
872 | | &res1_class, |
873 | | &res1_forward, |
874 | | &res1_inverse |
875 | | }; |
876 | | |
877 | | const vorbis_func_residue residue2_exportbundle={ |
878 | | &res0_pack, |
879 | | &res0_unpack, |
880 | | &res0_look, |
881 | | &res0_free_info, |
882 | | &res0_free_look, |
883 | | &res2_class, |
884 | | &res2_forward, |
885 | | &res2_inverse |
886 | | }; |