1 /********************************************************************
3 * THIS FILE IS PART OF THE Ogg Vorbis SOFTWARE CODEC SOURCE CODE. *
4 * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY *
5 * THE GNU PUBLIC LICENSE 2, WHICH IS INCLUDED WITH THIS SOURCE. *
6 * PLEASE READ THESE TERMS DISTRIBUTING. *
8 * THE OggSQUISH SOURCE CODE IS (C) COPYRIGHT 1994-2000 *
9 * by Monty <monty@xiph.org> and The XIPHOPHORUS Company *
10 * http://www.xiph.org/ *
12 ********************************************************************
14 function: build a VQ codebook and the encoding decision 'tree'
15 last mod: $Id: vqsplit.c,v 1.17 2000/02/21 01:13:02 xiphmont Exp $
17 ********************************************************************/
19 /* This code is *not* part of libvorbis. It is used to generate
20 trained codebooks offline and then spit the results into a
21 pregenerated codebook that is compiled into libvorbis. It is an
22 expensive (but good) algorithm. Run it on big iron. */
24 /* There are so many optimizations to explore in *both* stages that
25 considering the undertaking is almost withering. For now, we brute
38 /* Codebook generation happens in two steps:
40 1) Train the codebook with data collected from the encoder: We use
41 one of a few error metrics (which represent the distance between a
42 given data point and a candidate point in the training set) to
43 divide the training set up into cells representing roughly equal
44 probability of occurring.
46 2) Generate the codebook and auxiliary data from the trained data set
49 /* Building a codebook from trained set **********************************
51 The codebook in raw form is technically finished once it's trained.
52 However, we want to finalize the representative codebook values for
53 each entry and generate auxiliary information to optimize encoding.
54 We generate the auxiliary coding tree using collected data,
55 probably the same data as in the original training */
57 /* At each recursion, the data set is split in half. Cells with data
58 points on side A go into set A, same with set B. The sets may
59 overlap. If the cell overlaps the deviding line only very slightly
60 (provided parameter), we may choose to ignore the overlap in order
61 to pare the tree down */
64 int iascsort(const void *a,const void *b){
65 long av=isortvals[*((long *)a)];
66 long bv=isortvals[*((long *)b)];
70 /* grab it from vqgen.c */
71 extern double _dist(vqgen *v,double *a, double *b);
73 /* goes through the split, but just counts it and returns a metric*/
74 void vqsp_count(vqgen *v,long *membership,
75 long *entryindex,long entries,
76 long *pointindex,long points,
77 long *entryA,long *entryB,
79 long *entriesA,long *entriesB,long *entriesC){
83 memset(entryA,0,sizeof(long)*entries);
84 memset(entryB,0,sizeof(long)*entries);
86 /* Do the points belonging to this cell occur on sideA, sideB or
89 for(i=0;i<points;i++){
90 double *ppt=_point(v,pointindex[i]);
91 long firstentry=membership[i];
94 if(!entryA[firstentry] || !entryB[firstentry]){
95 for(k=0;k<v->elements;k++)
96 position+=ppt[k]*n[k];
100 entryB[firstentry]=1;
104 /* The entry splitting isn't total, so that storage has to be
105 allocated for recursion. Reuse the entryA/entryB vectors */
106 /* keep the entries in ascending order (relative to the original
107 list); we rely on that stability when ordering p/q choice */
108 for(j=0;j<entries;j++){
109 if(entryA[j] && entryB[j])C++;
110 if(entryA[j])entryA[A++]=entryindex[j];
111 if(entryB[j])entryB[B++]=entryindex[j];
118 void pq_in_out(vqgen *v,double *n,double *c,double *p,double *q){
121 for(k=0;k<v->elements;k++){
122 double center=(p[k]+q[k])/2.;
123 n[k]=(center-q[k])*2.;
128 int lp_split(vqgen *v,codebook *b,
129 long *entryindex,long entries,
130 long *pointindex,long points,
131 long depth, long *pointsofar){
133 encode_aux *t=b->c->encode_tree;
135 /* The encoder, regardless of book, will be using a straight
136 euclidian distance-to-point metric to determine closest point.
137 Thus we split the cells using the same (we've already trained the
138 codebook set spacing and distribution using special metrics and
139 even a midpoint division won't disturb the basic properties) */
142 double *n=alloca(sizeof(double)*v->elements);
144 long *entryA=calloc(entries,sizeof(long));
145 long *entryB=calloc(entries,sizeof(long));
152 long *membership=malloc(sizeof(long)*points);
158 sprintf(spinbuf,"splitting [%ld left]... ",v->points-*pointsofar);
160 if(depth==22 && points==9 && entries==2 && *pointsofar==252935){
161 fprintf(stderr,"HERE\n");
166 /* which cells do points belong to? Do this before n^2 best pair chooser. */
168 for(i=0;i<points;i++){
169 double *ppt=_point(v,pointindex[i]);
171 double firstmetric=_dist(v,_now(v,entryindex[0]),ppt);
173 if(points*entries>64*1024)spinnit(spinbuf,entries);
175 for(j=1;j<entries;j++){
176 double thismetric=_dist(v,_now(v,entryindex[j]),ppt);
177 if(thismetric<=firstmetric){ /* Not <; on the line goes to higher number */
178 firstmetric=thismetric;
183 membership[i]=firstentry;
186 /* We need to find the dividing hyperplane. find the median of each
187 axis as the centerpoint and the normal facing farthest point */
189 /* more than one way to do this part. For small sets, we can brute
192 if(entries<8 || (double)points*entries*entries<16.*1024*1024){
193 /* try every pair possibility */
196 for(i=0;i<entries-1;i++){
197 for(j=i+1;j<entries;j++){
198 spinnit(spinbuf,entries-i);
199 pq_in_out(v,n,&c,_now(v,entryindex[i]),_now(v,entryindex[j]));
200 vqsp_count(v,membership,
205 &entriesA,&entriesB,&entriesC);
206 this=(entriesA-entriesC)*(entriesB-entriesC);
208 /* when choosing best, we also want some form of stability to
209 make sure more branches are pared later; secondary
210 weighting isn;t needed as the entry lists are in ascending
211 order, and we always try p/q in the same sequence */
224 double *p=alloca(v->elements*sizeof(double));
225 double *q=alloca(v->elements*sizeof(double));
228 /* try COG/normal and furthest pairs */
230 /* eventually, we want to select the closest entry and figure n/c
231 from p/q (because storing n/c is too large */
232 for(k=0;k<v->elements;k++){
233 spinnit(spinbuf,entries);
236 for(j=0;j<entries;j++)
237 p[k]+=v->entrylist[entryindex[j]*v->elements+k];
242 /* we go through the entries one by one, looking for the entry on
243 the other side closest to the point of reflection through the
246 for(i=0;i<entries;i++){
247 double *ppi=_now(v,entryindex[i]);
251 spinnit(spinbuf,entries-i);
253 for(k=0;k<v->elements;k++)
256 for(j=0;j<entries;j++){
258 double this=_dist(v,q,_now(v,entryindex[j]));
259 if(ref_j==-1 || this<=ref_best){ /* <=, not <; very important */
266 pq_in_out(v,n,&c,ppi,_now(v,ref_j));
267 vqsp_count(v,membership,
272 &entriesA,&entriesB,&entriesC);
273 this=(entriesA-entriesC)*(entriesB-entriesC);
275 /* when choosing best, we also want some form of stability to
276 make sure more branches are pared later; secondary
277 weighting isn;t needed as the entry lists are in ascending
278 order, and we always try p/q in the same sequence */
297 /* find cells enclosing points */
298 /* count A/B points */
300 pq_in_out(v,n,&c,_now(v,besti),_now(v,bestj));
301 vqsp_count(v,membership,
306 &entriesA,&entriesB,&entriesC);
310 /* the point index is split, so we do an Order n rearrangement into
311 A first/B last and just pass it on */
318 for(k=0;k<v->elements;k++)
319 position+=_point(v,pointindex[Aptr])[k]*n[k];
320 if(position<=0.)break; /* not in A */
325 for(k=0;k<v->elements;k++)
326 position+=_point(v,pointindex[Bptr])[k]*n[k];
327 if(position>0.)break; /* not in B */
331 long temp=pointindex[Aptr];
332 pointindex[Aptr]=pointindex[Bptr];
333 pointindex[Bptr]=temp;
339 /* fprintf(stderr,"split: total=%ld depth=%ld set A=%ld:%ld:%ld=B\n",
340 entries,depth,entriesA-entriesC,entriesC,entriesB-entriesC);*/
342 long thisaux=t->aux++;
343 if(t->aux>=t->alloc){
345 t->ptr0=realloc(t->ptr0,sizeof(long)*t->alloc);
346 t->ptr1=realloc(t->ptr1,sizeof(long)*t->alloc);
347 t->p=realloc(t->p,sizeof(long)*t->alloc);
348 t->q=realloc(t->q,sizeof(long)*t->alloc);
356 t->ptr0[thisaux]=entryA[0];
357 *pointsofar+=pointsA;
359 t->ptr0[thisaux]= -t->aux;
360 ret=lp_split(v,b,entryA,entriesA,pointindex,pointsA,depth+1,pointsofar);
364 t->ptr1[thisaux]=entryB[0];
365 *pointsofar+=points-pointsA;
367 t->ptr1[thisaux]= -t->aux;
368 ret+=lp_split(v,b,entryB,entriesB,pointindex+pointsA,points-pointsA,
377 static int _node_eq(encode_aux *v, long a, long b){
378 long Aptr0=v->ptr0[a];
379 long Aptr1=v->ptr1[a];
380 long Bptr0=v->ptr0[b];
381 long Bptr1=v->ptr1[b];
383 /* the possibility of choosing the same p and q, but switched, can;t
384 happen because we always look for the best p/q in the same search
385 order and the search is stable */
387 if(Aptr0==Bptr0 && Aptr1==Bptr1)
393 void vqsp_book(vqgen *v, codebook *b, long *quantlist){
395 static_codebook *c=(static_codebook *)b->c;
398 memset(b,0,sizeof(codebook));
399 memset(c,0,sizeof(static_codebook));
401 t=c->encode_tree=calloc(1,sizeof(encode_aux));
403 /* make sure there are no duplicate entries and that every
406 for(i=0;i<v->entries;){
407 /* duplicate? if so, eliminate */
409 if(_dist(v,_now(v,i),_now(v,j))==0.){
410 fprintf(stderr,"found a duplicate entry! removing...\n");
412 memcpy(_now(v,i),_now(v,v->entries),sizeof(double)*v->elements);
413 memcpy(quantlist+i*v->elements,quantlist+v->entries*v->elements,
414 sizeof(long)*v->elements);
422 v->assigned=calloc(v->entries,sizeof(long));
423 for(i=0;i<v->points;i++){
424 double *ppt=_point(v,i);
425 double firstmetric=_dist(v,_now(v,0),ppt);
428 if(!(i&0xff))spinnit("checking... ",v->points-i);
430 for(j=0;j<v->entries;j++){
431 double thismetric=_dist(v,_now(v,j),ppt);
432 if(thismetric<firstmetric){
433 firstmetric=thismetric;
438 v->assigned[firstentry]++;
441 for(j=0;j<v->entries;){
442 if(v->assigned[j]==0){
443 fprintf(stderr,"found an unused entry! removing...\n");
445 memcpy(_now(v,j),_now(v,v->entries),sizeof(double)*v->elements);
446 v->assigned[j]=v->assigned[v->elements];
447 memcpy(quantlist+j*v->elements,quantlist+v->entries*v->elements,
448 sizeof(long)*v->elements);
455 fprintf(stderr,"Building a book with %ld unique entries...\n",v->entries);
457 /* We don't always generate a single tree; it tends to be large. We
458 trade off by splitting the cell and point sets into n totally
459 non-overlapping subsets (where the decision tree tends to have
460 substantial overlap in hyperplane splits) and generating a tree
461 for each. Because the tree depth is O(n) o(lg(n)), the smaller
462 data set will get us much better storage usage for worst cases
463 (and we will run toward worst case) */
466 /* split data set... */
467 int trees=v->entries/(32+log(v->entries)/log(2)*2)+1; /* a guess */
468 long *entrymap=malloc(v->entries*sizeof(long *));
469 long **entryindex=malloc(trees*sizeof(long *));
470 long *entries=calloc(trees,sizeof(long));
471 long *pointmap=malloc(v->points*sizeof(long));
472 long desired=(v->entries/trees)+1;
476 for(i=0;i<trees;i++)entryindex[i]=calloc(desired,sizeof(long));
478 fprintf(stderr,"Prepartitioning into %d trees...\n",trees);
480 /* map points to cells */
481 for(i=0;i<v->points;i++){
482 double *ppt=_point(v,i);
483 double firstmetric=_dist(v,_now(v,0),ppt);
486 if(!(i&0xff))spinnit("parititoning... ",v->points-i);
488 for(j=0;j<v->entries;j++){
489 double thismetric=_dist(v,_now(v,j),ppt);
490 if(thismetric<firstmetric){
491 firstmetric=thismetric;
495 pointmap[i]=firstentry;
498 /* this could be more effective; long, narrow slices are probably
499 better than these porous blobs */
501 for(j=0;j<v->entries;j++){
503 for(i=0;i<trees;i++){
504 if(entries[i]<desired){ /* still has open space */
510 entryindex[choice][entries[choice]++]=j;
515 /* we overload the static codebook ptrs just a bit... the first
516 <tree> ptr0s just point to the starting point in the struct for
517 that tree. The first ptr0 points to the first tree at offset
518 <tree>, and thus can be used as the tree count. Clever but
519 totally opaque :-( . */
522 t->ptr0=malloc(sizeof(long)*t->alloc);
523 t->ptr1=malloc(sizeof(long)*t->alloc);
524 t->p=malloc(sizeof(long)*t->alloc);
525 t->q=malloc(sizeof(long)*t->alloc);
528 c->entries=v->entries;
529 c->lengthlist=calloc(c->entries,sizeof(long));
531 for(booknum=0;booknum<trees;booknum++){
535 t->ptr0[booknum]=t->aux;
536 for(i=0;i<v->points;i++)
537 if(entrymap[pointmap[i]]==booknum)points++;
538 pointindex=malloc(points*sizeof(long));
540 for(i=0;i<v->points;i++)
541 if(entrymap[pointmap[i]]==booknum)pointindex[points++]=i;
543 /* generate the encoding decision heirarchy */
544 fprintf(stderr,"Leaves added: %d \n",
545 lp_split(v,b,entryindex[booknum],entries[booknum],
546 pointindex,points,0,&pointssofar));
549 fprintf(stderr,"Paring/rerouting redundant branches... ");
551 /* The tree is likely big and redundant. Pare and reroute branches */
558 /* span the tree node by node; list unique decision nodes and
559 short circuit redundant branches */
561 for(i=t->ptr0[booknum];i<t->aux;){
564 /* check list of unique decisions */
565 for(j=t->ptr0[booknum];j<i;j++)
566 if(_node_eq(t,i,j))break;
569 /* a redundant entry; find all higher nodes referencing it and
570 short circuit them to the previously noted unique entry */
572 for(k=0;k<t->aux;k++){
573 if(t->ptr0[k]==-i)t->ptr0[k]=-j;
574 if(t->ptr1[k]==-i)t->ptr1[k]=-j;
577 /* Now, we need to fill in the hole from this redundant
578 entry in the listing. Insert the last entry in the list.
579 Fix the forward pointers to that last entry */
581 t->ptr0[i]=t->ptr0[t->aux];
582 t->ptr1[i]=t->ptr1[t->aux];
583 t->p[i]=t->p[t->aux];
584 t->q[i]=t->q[t->aux];
585 for(k=0;k<t->aux;k++){
586 if(t->ptr0[k]==-t->aux)t->ptr0[k]=-i;
587 if(t->ptr1[k]==-t->aux)t->ptr1[k]=-i;
595 fprintf(stderr,"\rParing/rerouting redundant branches... "
596 "%ld remaining ",t->aux);
598 fprintf(stderr,"\n");
603 /* run all training points through the decision tree to get a final
606 long *probability=malloc(c->entries*sizeof(long));
607 for(i=0;i<c->entries;i++)probability[i]=1; /* trivial guard */
608 b->valuelist=v->entrylist; /* temporary for vqenc_entry; replaced later */
610 for(i=0;i<v->points;i++){
611 int ret=codebook_entry(b,v->pointlist+i*v->elements);
613 if(!(i&0xff))spinnit("counting hits... ",v->points-i);
616 build_tree_from_lengths(c->entries,probability,c->lengthlist);
621 /* Sort the entries by codeword length, short to long (eases
622 assignment and packing to do it now) */
624 long *wordlen=c->lengthlist;
625 long *index=malloc(c->entries*sizeof(long));
626 long *revindex=malloc(c->entries*sizeof(long));
628 for(i=0;i<c->entries;i++)index[i]=i;
629 isortvals=c->lengthlist;
630 qsort(index,c->entries,sizeof(long),iascsort);
632 /* rearrange storage; ptr0/1 first as it needs a reverse index */
633 /* n and c stay unchanged */
634 for(i=0;i<c->entries;i++)revindex[index[i]]=i;
635 for(i=t->ptr0[0];i<t->aux;i++){
636 if(!(i&0x3f))spinnit("sorting... ",t->aux-i);
638 if(t->ptr0[i]>=0)t->ptr0[i]=revindex[t->ptr0[i]];
639 if(t->ptr1[i]>=0)t->ptr1[i]=revindex[t->ptr1[i]];
640 t->p[i]=revindex[t->p[i]];
641 t->q[i]=revindex[t->q[i]];
645 /* map lengthlist and vallist with index */
646 c->lengthlist=calloc(c->entries,sizeof(long));
647 b->valuelist=malloc(sizeof(double)*c->entries*c->dim);
648 c->quantlist=malloc(sizeof(long)*c->entries*c->dim);
649 for(i=0;i<c->entries;i++){
651 for(k=0;k<c->dim;k++){
652 b->valuelist[i*c->dim+k]=v->entrylist[e*c->dim+k];
653 c->quantlist[i*c->dim+k]=quantlist[e*c->dim+k];
655 c->lengthlist[i]=wordlen[e];
661 fprintf(stderr,"Done. \n\n");