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 | void res0_free_info(vorbis_info_residue *i){ |
66 | vorbis_info_residue0 *info=(vorbis_info_residue0 *)i; |
67 | if(info){ |
68 | memset(info,0,sizeof(*info)); |
69 | _ogg_free(info); |
70 | } |
71 | } |
72 | |
73 | void res0_free_look(vorbis_look_residue *i){ |
74 | int j; |
75 | if(i){ |
76 | |
77 | 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 | for(j=0;j<look->parts;j++) |
140 | if(look->partbooks[j])_ogg_free(look->partbooks[j]); |
141 | _ogg_free(look->partbooks); |
142 | for(j=0;j<look->partvals;j++) |
143 | _ogg_free(look->decodemap[j]); |
144 | _ogg_free(look->decodemap); |
145 | |
146 | memset(look,0,sizeof(*look)); |
147 | _ogg_free(look); |
148 | } |
149 | } |
150 | |
151 | static int icount(unsigned int v){ |
152 | int ret=0; |
153 | while(v){ |
154 | ret+=v&1; |
155 | v>>=1; |
156 | } |
157 | return(ret); |
158 | } |
159 | |
160 | |
161 | void res0_pack(vorbis_info_residue *vr,oggpack_buffer *opb){ |
162 | vorbis_info_residue0 *info=(vorbis_info_residue0 *)vr; |
163 | int j,acc=0; |
164 | oggpack_write(opb,info->begin,24); |
165 | oggpack_write(opb,info->end,24); |
166 | |
167 | oggpack_write(opb,info->grouping-1,24); /* residue vectors to group and |
168 | code with a partitioned book */ |
169 | oggpack_write(opb,info->partitions-1,6); /* possible partition choices */ |
170 | 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 | for(j=0;j<info->partitions;j++){ |
176 | if(ov_ilog(info->secondstages[j])>3){ |
177 | /* yes, this is a minor hack due to not thinking ahead */ |
178 | oggpack_write(opb,info->secondstages[j],3); |
179 | oggpack_write(opb,1,1); |
180 | oggpack_write(opb,info->secondstages[j]>>3,5); |
181 | }else |
182 | oggpack_write(opb,info->secondstages[j],4); /* trailing zero */ |
183 | acc+=icount(info->secondstages[j]); |
184 | } |
185 | for(j=0;j<acc;j++) |
186 | oggpack_write(opb,info->booklist[j],8); |
187 | |
188 | } |
189 | |
190 | /* vorbis_info is for range checking */ |
191 | vorbis_info_residue *res0_unpack(vorbis_info *vi,oggpack_buffer *opb){ |
192 | int j,acc=0; |
193 | vorbis_info_residue0 *info=_ogg_calloc(1,sizeof(*info)); |
194 | codec_setup_info *ci=vi->codec_setup; |
195 | |
196 | info->begin=oggpack_read(opb,24); |
197 | info->end=oggpack_read(opb,24); |
198 | info->grouping=oggpack_read(opb,24)+1; |
199 | info->partitions=oggpack_read(opb,6)+1; |
200 | info->groupbook=oggpack_read(opb,8); |
201 | |
202 | /* check for premature EOP */ |
203 | if(info->groupbook<0)goto errout; |
204 | |
205 | for(j=0;j<info->partitions;j++){ |
206 | int cascade=oggpack_read(opb,3); |
207 | int cflag=oggpack_read(opb,1); |
208 | if(cflag<0) goto errout; |
209 | if(cflag){ |
210 | int c=oggpack_read(opb,5); |
211 | if(c<0) goto errout; |
212 | cascade|=(c<<3); |
213 | } |
214 | info->secondstages[j]=cascade; |
215 | |
216 | acc+=icount(cascade); |
217 | } |
218 | for(j=0;j<acc;j++){ |
219 | int book=oggpack_read(opb,8); |
220 | if(book<0) goto errout; |
221 | info->booklist[j]=book; |
222 | } |
223 | |
224 | if(info->groupbook>=ci->books)goto errout; |
225 | for(j=0;j<acc;j++){ |
226 | if(info->booklist[j]>=ci->books)goto errout; |
227 | if(ci->book_param[info->booklist[j]]->maptype==0)goto errout; |
228 | } |
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 | { |
237 | int entries = ci->book_param[info->groupbook]->entries; |
238 | int dim = ci->book_param[info->groupbook]->dim; |
239 | int partvals = 1; |
240 | if (dim<1) goto errout; |
241 | while(dim>0){ |
242 | partvals *= info->partitions; |
243 | if(partvals > entries) goto errout; |
244 | dim--; |
245 | } |
246 | info->partvals = partvals; |
247 | } |
248 | |
249 | return(info); |
250 | errout: |
251 | res0_free_info(info); |
252 | return(NULL); |
253 | } |
254 | |
255 | vorbis_look_residue *res0_look(vorbis_dsp_state *vd, |
256 | vorbis_info_residue *vr){ |
257 | vorbis_info_residue0 *info=(vorbis_info_residue0 *)vr; |
258 | vorbis_look_residue0 *look=_ogg_calloc(1,sizeof(*look)); |
259 | codec_setup_info *ci=vd->vi->codec_setup; |
260 | |
261 | int j,k,acc=0; |
262 | int dim; |
263 | int maxstage=0; |
264 | look->info=info; |
265 | |
266 | look->parts=info->partitions; |
267 | look->fullbooks=ci->fullbooks; |
268 | look->phrasebook=ci->fullbooks+info->groupbook; |
269 | dim=look->phrasebook->dim; |
270 | |
271 | look->partbooks=_ogg_calloc(look->parts,sizeof(*look->partbooks)); |
272 | |
273 | for(j=0;j<look->parts;j++){ |
274 | int stages=ov_ilog(info->secondstages[j]); |
275 | if(stages){ |
276 | if(stages>maxstage)maxstage=stages; |
277 | look->partbooks[j]=_ogg_calloc(stages,sizeof(*look->partbooks[j])); |
278 | for(k=0;k<stages;k++) |
279 | if(info->secondstages[j]&(1<<k)){ |
280 | 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 | } |
286 | } |
287 | } |
288 | |
289 | look->partvals=1; |
290 | for(j=0;j<dim;j++) |
291 | look->partvals*=look->parts; |
292 | |
293 | look->stages=maxstage; |
294 | look->decodemap=_ogg_malloc(look->partvals*sizeof(*look->decodemap)); |
295 | for(j=0;j<look->partvals;j++){ |
296 | long val=j; |
297 | long mult=look->partvals/look->parts; |
298 | look->decodemap[j]=_ogg_malloc(dim*sizeof(*look->decodemap[j])); |
299 | for(k=0;k<dim;k++){ |
300 | long deco=val/mult; |
301 | val-=deco*mult; |
302 | mult/=look->parts; |
303 | look->decodemap[j][k]=deco; |
304 | } |
305 | } |
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 | return(look); |
313 | } |
314 | |
315 | /* break an abstraction and copy some code for performance purposes */ |
316 | static int local_book_besterror(codebook *book,int *a){ |
317 | int dim=book->dim; |
318 | int i,j,o; |
319 | int minval=book->minval; |
320 | int del=book->delta; |
321 | int qv=book->quantvals; |
322 | int ze=(qv>>1); |
323 | int index=0; |
324 | /* assumes integer/centered encoder codebook maptype 1 no more than dim 8 */ |
325 | int p[8]={0,0,0,0,0,0,0,0}; |
326 | |
327 | if(del!=1){ |
328 | for(i=0,o=dim;i<dim;i++){ |
329 | int v = (a[--o]-minval+(del>>1))/del; |
330 | int m = (v<ze ? ((ze-v)<<1)-1 : ((v-ze)<<1)); |
331 | index = index*qv+ (m<0?0:(m>=qv?qv-1:m)); |
332 | p[o]=v*del+minval; |
333 | } |
334 | }else{ |
335 | for(i=0,o=dim;i<dim;i++){ |
336 | int v = a[--o]-minval; |
337 | int m = (v<ze ? ((ze-v)<<1)-1 : ((v-ze)<<1)); |
338 | index = index*qv+ (m<0?0:(m>=qv?qv-1:m)); |
339 | p[o]=v*del+minval; |
340 | } |
341 | } |
342 | |
343 | if(book->c->lengthlist[index]<=0){ |
344 | const static_codebook *c=book->c; |
345 | int best=-1; |
346 | /* assumes integer/centered encoder codebook maptype 1 no more than dim 8 */ |
347 | int e[8]={0,0,0,0,0,0,0,0}; |
348 | int maxval = book->minval + book->delta*(book->quantvals-1); |
349 | for(i=0;i<book->entries;i++){ |
350 | if(c->lengthlist[i]>0){ |
351 | int this=0; |
352 | for(j=0;j<dim;j++){ |
353 | int val=(e[j]-a[j]); |
354 | this+=val*val; |
355 | } |
356 | if(best==-1 || this<best){ |
357 | memcpy(p,e,sizeof(p)); |
358 | best=this; |
359 | index=i; |
360 | } |
361 | } |
362 | /* assumes the value patterning created by the tools in vq/ */ |
363 | j=0; |
364 | while(e[j]>=maxval) |
365 | e[j++]=0; |
366 | if(e[j]>=0) |
367 | e[j]+=book->delta; |
368 | e[j]= -e[j]; |
369 | } |
370 | } |
371 | |
372 | if(index>-1){ |
373 | for(i=0;i<dim;i++) |
374 | *a++ -= p[i]; |
375 | } |
376 | |
377 | return(index); |
378 | } |
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 | codebook *book){ |
386 | #endif |
387 | int i,bits=0; |
388 | int dim=book->dim; |
389 | int step=n/dim; |
390 | |
391 | for(i=0;i<step;i++){ |
392 | 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 | bits+=vorbis_book_encode(book,entry,opb); |
400 | |
401 | } |
402 | |
403 | return(bits); |
404 | } |
405 | |
406 | static long **_01class(vorbis_block *vb,vorbis_look_residue *vl, |
407 | int **in,int ch){ |
408 | long i,j,k; |
409 | vorbis_look_residue0 *look=(vorbis_look_residue0 *)vl; |
410 | vorbis_info_residue0 *info=look->info; |
411 | |
412 | /* move all this setup out later */ |
413 | int samples_per_partition=info->grouping; |
414 | int possible_partitions=info->partitions; |
415 | int n=info->end-info->begin; |
416 | |
417 | int partvals=n/samples_per_partition; |
418 | long **partword=_vorbis_block_alloc(vb,ch*sizeof(*partword)); |
419 | 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 | for(i=0;i<ch;i++){ |
426 | partword[i]=_vorbis_block_alloc(vb,n/samples_per_partition*sizeof(*partword[i])); |
427 | memset(partword[i],0,n/samples_per_partition*sizeof(*partword[i])); |
428 | } |
429 | |
430 | for(i=0;i<partvals;i++){ |
431 | int offset=i*samples_per_partition+info->begin; |
432 | for(j=0;j<ch;j++){ |
433 | int max=0; |
434 | int ent=0; |
435 | for(k=0;k<samples_per_partition;k++){ |
436 | if(abs(in[j][offset+k])>max)max=abs(in[j][offset+k]); |
437 | ent+=abs(in[j][offset+k]); |
438 | } |
439 | ent*=scale; |
440 | |
441 | for(k=0;k<possible_partitions-1;k++) |
442 | if(max<=info->classmetric1[k] && |
443 | (info->classmetric2[k]<0 || ent<info->classmetric2[k])) |
444 | break; |
445 | |
446 | partword[j][i]=k; |
447 | } |
448 | } |
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 | look->frames++; |
466 | |
467 | return(partword); |
468 | } |
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 | int ch){ |
475 | long i,j,k,l; |
476 | vorbis_look_residue0 *look=(vorbis_look_residue0 *)vl; |
477 | vorbis_info_residue0 *info=look->info; |
478 | |
479 | /* move all this setup out later */ |
480 | int samples_per_partition=info->grouping; |
481 | int possible_partitions=info->partitions; |
482 | int n=info->end-info->begin; |
483 | |
484 | int partvals=n/samples_per_partition; |
485 | 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 | partword[0]=_vorbis_block_alloc(vb,partvals*sizeof(*partword[0])); |
493 | memset(partword[0],0,partvals*sizeof(*partword[0])); |
494 | |
495 | for(i=0,l=info->begin/ch;i<partvals;i++){ |
496 | int magmax=0; |
497 | int angmax=0; |
498 | for(j=0;j<samples_per_partition;j+=ch){ |
499 | if(abs(in[0][l])>magmax)magmax=abs(in[0][l]); |
500 | for(k=1;k<ch;k++) |
501 | if(abs(in[k][l])>angmax)angmax=abs(in[k][l]); |
502 | l++; |
503 | } |
504 | |
505 | for(j=0;j<possible_partitions-1;j++) |
506 | if(magmax<=info->classmetric1[j] && |
507 | angmax<=info->classmetric2[j]) |
508 | break; |
509 | |
510 | partword[0][i]=j; |
511 | |
512 | } |
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 | look->frames++; |
524 | |
525 | return(partword); |
526 | } |
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 | ){ |
541 | long i,j,k,s; |
542 | vorbis_look_residue0 *look=(vorbis_look_residue0 *)vl; |
543 | 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 | int samples_per_partition=info->grouping; |
551 | int possible_partitions=info->partitions; |
552 | int partitions_per_word=look->phrasebook->dim; |
553 | int n=info->end-info->begin; |
554 | |
555 | int partvals=n/samples_per_partition; |
556 | long resbits[128]; |
557 | 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 | memset(resbits,0,sizeof(resbits)); |
568 | 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 | for(s=0;s<look->stages;s++){ |
576 | |
577 | for(i=0;i<partvals;){ |
578 | |
579 | /* first we encode a partition codeword for each channel */ |
580 | if(s==0){ |
581 | for(j=0;j<ch;j++){ |
582 | long val=partword[j][i]; |
583 | for(k=1;k<partitions_per_word;k++){ |
584 | val*=possible_partitions; |
585 | if(i+k<partvals) |
586 | val+=partword[j][i+k]; |
587 | } |
588 | |
589 | /* training hack */ |
590 | if(val<look->phrasebook->entries) |
591 | look->phrasebits+=vorbis_book_encode(look->phrasebook,val,opb); |
592 | #if 0 /*def TRAIN_RES*/ |
593 | else |
594 | fprintf(stderr,"!" ); |
595 | #endif |
596 | |
597 | } |
598 | } |
599 | |
600 | /* now we encode interleaved residual values for the partitions */ |
601 | for(k=0;k<partitions_per_word && i<partvals;k++,i++){ |
602 | long offset=i*samples_per_partition+info->begin; |
603 | |
604 | for(j=0;j<ch;j++){ |
605 | if(s==0)resvals[partword[j][i]]+=samples_per_partition; |
606 | if(info->secondstages[partword[j][i]]&(1<<s)){ |
607 | codebook *statebook=look->partbooks[partword[j][i]][s]; |
608 | if(statebook){ |
609 | 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 | ret=encode(opb,in[j]+offset,samples_per_partition, |
627 | statebook); |
628 | #endif |
629 | |
630 | look->postbits+=ret; |
631 | resbits[partword[j][i]]+=ret; |
632 | } |
633 | } |
634 | } |
635 | } |
636 | } |
637 | } |
638 | |
639 | return(0); |
640 | } |
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 | oggpack_buffer *,int)){ |
647 | |
648 | long i,j,k,l,s; |
649 | vorbis_look_residue0 *look=(vorbis_look_residue0 *)vl; |
650 | vorbis_info_residue0 *info=look->info; |
651 | |
652 | /* move all this setup out later */ |
653 | int samples_per_partition=info->grouping; |
654 | int partitions_per_word=look->phrasebook->dim; |
655 | int max=vb->pcmend>>1; |
656 | int end=(info->end<max?info->end:max); |
657 | int n=end-info->begin; |
658 | |
659 | if(n>0){ |
660 | int partvals=n/samples_per_partition; |
661 | int partwords=(partvals+partitions_per_word-1)/partitions_per_word; |
662 | int ***partword=alloca(ch*sizeof(*partword)); |
663 | |
664 | for(j=0;j<ch;j++) |
665 | partword[j]=_vorbis_block_alloc(vb,partwords*sizeof(*partword[j])); |
666 | |
667 | for(s=0;s<look->stages;s++){ |
668 | |
669 | /* each loop decodes on partition codeword containing |
670 | partitions_per_word partitions */ |
671 | for(i=0,l=0;i<partvals;l++){ |
672 | if(s==0){ |
673 | /* fetch the partition word for each channel */ |
674 | for(j=0;j<ch;j++){ |
675 | int temp=vorbis_book_decode(look->phrasebook,&vb->opb); |
676 | |
677 | if(temp==-1 || temp>=info->partvals)goto eopbreak; |
678 | partword[j][l]=look->decodemap[temp]; |
679 | if(partword[j][l]==NULL)goto errout; |
680 | } |
681 | } |
682 | |
683 | /* now we decode residual values for the partitions */ |
684 | for(k=0;k<partitions_per_word && i<partvals;k++,i++) |
685 | for(j=0;j<ch;j++){ |
686 | long offset=info->begin+i*samples_per_partition; |
687 | if(info->secondstages[partword[j][l][k]]&(1<<s)){ |
688 | codebook *stagebook=look->partbooks[partword[j][l][k]][s]; |
689 | if(stagebook){ |
690 | if(decodepart(stagebook,in[j]+offset,&vb->opb, |
691 | samples_per_partition)==-1)goto eopbreak; |
692 | } |
693 | } |
694 | } |
695 | } |
696 | } |
697 | } |
698 | errout: |
699 | eopbreak: |
700 | return(0); |
701 | } |
702 | |
703 | int res0_inverse(vorbis_block *vb,vorbis_look_residue *vl, |
704 | float **in,int *nonzero,int ch){ |
705 | int i,used=0; |
706 | for(i=0;i<ch;i++) |
707 | if(nonzero[i]) |
708 | in[used++]=in[i]; |
709 | if(used) |
710 | return(_01inverse(vb,vl,in,used,vorbis_book_decodevs_add)); |
711 | else |
712 | return(0); |
713 | } |
714 | |
715 | int res1_forward(oggpack_buffer *opb,vorbis_block *vb,vorbis_look_residue *vl, |
716 | int **in,int *nonzero,int ch, long **partword, int submap){ |
717 | int i,used=0; |
718 | (void)vb; |
719 | for(i=0;i<ch;i++) |
720 | if(nonzero[i]) |
721 | in[used++]=in[i]; |
722 | |
723 | if(used){ |
724 | #ifdef TRAIN_RES |
725 | return _01forward(opb,vl,in,used,partword,_encodepart,submap); |
726 | #else |
727 | (void)submap; |
728 | return _01forward(opb,vl,in,used,partword,_encodepart); |
729 | #endif |
730 | }else{ |
731 | return(0); |
732 | } |
733 | } |
734 | |
735 | long **res1_class(vorbis_block *vb,vorbis_look_residue *vl, |
736 | int **in,int *nonzero,int ch){ |
737 | int i,used=0; |
738 | for(i=0;i<ch;i++) |
739 | if(nonzero[i]) |
740 | in[used++]=in[i]; |
741 | if(used) |
742 | return(_01class(vb,vl,in,used)); |
743 | else |
744 | return(0); |
745 | } |
746 | |
747 | int res1_inverse(vorbis_block *vb,vorbis_look_residue *vl, |
748 | float **in,int *nonzero,int ch){ |
749 | int i,used=0; |
750 | for(i=0;i<ch;i++) |
751 | if(nonzero[i]) |
752 | in[used++]=in[i]; |
753 | if(used) |
754 | return(_01inverse(vb,vl,in,used,vorbis_book_decodev_add)); |
755 | else |
756 | return(0); |
757 | } |
758 | |
759 | long **res2_class(vorbis_block *vb,vorbis_look_residue *vl, |
760 | int **in,int *nonzero,int ch){ |
761 | int i,used=0; |
762 | for(i=0;i<ch;i++) |
763 | if(nonzero[i])used++; |
764 | if(used) |
765 | return(_2class(vb,vl,in,ch)); |
766 | else |
767 | return(0); |
768 | } |
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 | int **in,int *nonzero,int ch, long **partword,int submap){ |
776 | 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 | int *work=_vorbis_block_alloc(vb,ch*n*sizeof(*work)); |
782 | for(i=0;i<ch;i++){ |
783 | int *pcm=in[i]; |
784 | if(nonzero[i])used++; |
785 | for(j=0,k=i;j<n;j++,k+=ch) |
786 | work[k]=pcm[j]; |
787 | } |
788 | |
789 | if(used){ |
790 | #ifdef TRAIN_RES |
791 | return _01forward(opb,vl,&work,1,partword,_encodepart,submap); |
792 | #else |
793 | (void)submap; |
794 | return _01forward(opb,vl,&work,1,partword,_encodepart); |
795 | #endif |
796 | }else{ |
797 | return(0); |
798 | } |
799 | } |
800 | |
801 | /* duplicate code here as speed is somewhat more important */ |
802 | int res2_inverse(vorbis_block *vb,vorbis_look_residue *vl, |
803 | float **in,int *nonzero,int ch){ |
804 | long i,k,l,s; |
805 | vorbis_look_residue0 *look=(vorbis_look_residue0 *)vl; |
806 | vorbis_info_residue0 *info=look->info; |
807 | |
808 | /* move all this setup out later */ |
809 | int samples_per_partition=info->grouping; |
810 | int partitions_per_word=look->phrasebook->dim; |
811 | int max=(vb->pcmend*ch)>>1; |
812 | int end=(info->end<max?info->end:max); |
813 | int n=end-info->begin; |
814 | |
815 | if(n>0){ |
816 | int partvals=n/samples_per_partition; |
817 | int partwords=(partvals+partitions_per_word-1)/partitions_per_word; |
818 | int **partword=_vorbis_block_alloc(vb,partwords*sizeof(*partword)); |
819 | |
820 | for(i=0;i<ch;i++)if(nonzero[i])break; |
821 | if(i==ch)return(0); /* no nonzero vectors */ |
822 | |
823 | for(s=0;s<look->stages;s++){ |
824 | for(i=0,l=0;i<partvals;l++){ |
825 | |
826 | if(s==0){ |
827 | /* fetch the partition word */ |
828 | int temp=vorbis_book_decode(look->phrasebook,&vb->opb); |
829 | if(temp==-1 || temp>=info->partvals)goto eopbreak; |
830 | partword[l]=look->decodemap[temp]; |
831 | if(partword[l]==NULL)goto errout; |
832 | } |
833 | |
834 | /* now we decode residual values for the partitions */ |
835 | for(k=0;k<partitions_per_word && i<partvals;k++,i++) |
836 | if(info->secondstages[partword[l][k]]&(1<<s)){ |
837 | codebook *stagebook=look->partbooks[partword[l][k]][s]; |
838 | |
839 | if(stagebook){ |
840 | if(vorbis_book_decodevv_add(stagebook,in, |
841 | i*samples_per_partition+info->begin,ch, |
842 | &vb->opb,samples_per_partition)==-1) |
843 | goto eopbreak; |
844 | } |
845 | } |
846 | } |
847 | } |
848 | } |
849 | errout: |
850 | eopbreak: |
851 | return(0); |
852 | } |
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 | }; |
887 | |