Fixes for codebook geenration (keeping up to date)
[platform/upstream/libvorbis.git] / vq / metrics.c
1 /********************************************************************
2  *                                                                  *
3  * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
4  * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY *
5  * THE GNU LESSER/LIBRARY PUBLIC LICENSE, WHICH IS INCLUDED WITH    *
6  * THIS SOURCE. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.        *
7  *                                                                  *
8  * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2000             *
9  * by Monty <monty@xiph.org> and the XIPHOPHORUS Company            *
10  * http://www.xiph.org/                                             *
11  *                                                                  *
12  ********************************************************************
13
14  function: function calls to collect codebook metrics
15  last mod: $Id: metrics.c,v 1.11 2000/11/08 03:23:23 xiphmont Exp $
16
17  ********************************************************************/
18
19
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include <math.h>
23 #include "bookutil.h"
24
25 /* collect the following metrics:
26
27    mean and mean squared amplitude
28    mean and mean squared error 
29    mean and mean squared error (per sample) by entry
30    worst case fit by entry
31    entry cell size
32    hits by entry
33    total bits
34    total samples
35    (average bits per sample)*/
36    
37
38 /* set up metrics */
39
40 float meanamplitude_acc=0.;
41 float meanamplitudesq_acc=0.;
42 float meanerror_acc=0.;
43 float meanerrorsq_acc=0.;
44
45 float **histogram=NULL;
46 float **histogram_error=NULL;
47 float **histogram_errorsq=NULL;
48 float **histogram_hi=NULL;
49 float **histogram_lo=NULL;
50 float bits=0.;
51 float count=0.;
52
53 static float *_now(codebook *c, int i){
54   return c->valuelist+i*c->c->dim;
55 }
56
57 int books=0;
58
59 void process_preprocess(codebook **bs,char *basename){
60   int i;
61   while(bs[books])books++;
62   
63   if(books){
64     histogram=_ogg_calloc(books,sizeof(float *));
65     histogram_error=_ogg_calloc(books,sizeof(float *));
66     histogram_errorsq=_ogg_calloc(books,sizeof(float *));
67     histogram_hi=_ogg_calloc(books,sizeof(float *));
68     histogram_lo=_ogg_calloc(books,sizeof(float *));
69   }else{
70     fprintf(stderr,"Specify at least one codebook\n");
71     exit(1);
72   }
73
74   for(i=0;i<books;i++){
75     codebook *b=bs[i];
76     histogram[i]=_ogg_calloc(b->entries,sizeof(float));
77     histogram_error[i]=_ogg_calloc(b->entries*b->dim,sizeof(float));
78     histogram_errorsq[i]=_ogg_calloc(b->entries*b->dim,sizeof(float));
79     histogram_hi[i]=_ogg_calloc(b->entries*b->dim,sizeof(float));
80     histogram_lo[i]=_ogg_calloc(b->entries*b->dim,sizeof(float));
81   }
82 }
83
84 static float _dist(int el,float *a, float *b){
85   int i;
86   float acc=0.;
87   for(i=0;i<el;i++){
88     float val=(a[i]-b[i]);
89     acc+=val*val;
90   }
91   return acc;
92 }
93
94 void cell_spacing(codebook *c){
95   int j,k;
96   float min=-1,max=-1,mean=0.,meansq=0.;
97   long total=0;
98
99   /* minimum, maximum, mean, ms cell spacing */
100   for(j=0;j<c->c->entries;j++){
101     if(c->c->lengthlist[j]>0){
102       float localmin=-1.;
103       for(k=0;k<c->c->entries;k++){
104         if(c->c->lengthlist[k]>0){
105           float this=_dist(c->c->dim,_now(c,j),_now(c,k));
106           if(j!=k &&
107              (localmin==-1 || this<localmin))
108             localmin=this;
109         }
110       }
111       
112       if(min==-1 || localmin<min)min=localmin;
113       if(max==-1 || localmin>max)max=localmin;
114       mean+=sqrt(localmin);
115       meansq+=localmin;
116       total++;
117     }
118   }
119   
120   fprintf(stderr,"\tminimum cell spacing (closest side): %g\n",sqrt(min));
121   fprintf(stderr,"\tmaximum cell spacing (closest side): %g\n",sqrt(max));
122   fprintf(stderr,"\tmean closest side spacing: %g\n",mean/total);
123   fprintf(stderr,"\tmean sq closest side spacing: %g\n",sqrt(meansq/total));
124 }
125
126 void process_postprocess(codebook **bs,char *basename){
127   int i,k,book;
128   char *buffer=alloca(strlen(basename)+80);
129
130   fprintf(stderr,"Done.  Processed %ld data points:\n\n",
131           (long)count);
132
133   fprintf(stderr,"Global statistics:******************\n\n");
134
135   fprintf(stderr,"\ttotal samples: %ld\n",(long)count);
136   fprintf(stderr,"\ttotal bits required to code: %ld\n",(long)bits);
137   fprintf(stderr,"\taverage bits per sample: %g\n\n",bits/count);
138
139   fprintf(stderr,"\tmean sample amplitude: %g\n",
140           meanamplitude_acc/count);
141   fprintf(stderr,"\tmean squared sample amplitude: %g\n\n",
142           sqrt(meanamplitudesq_acc/count));
143
144   fprintf(stderr,"\tmean code error: %g\n",
145           meanerror_acc/count);
146   fprintf(stderr,"\tmean squared code error: %g\n\n",
147           sqrt(meanerrorsq_acc/count));
148
149   for(book=0;book<books;book++){
150     FILE *out;
151     codebook *b=bs[book];
152     int n=b->c->entries;
153     int dim=b->c->dim;
154
155     fprintf(stderr,"Book %d statistics:------------------\n",book);
156
157     cell_spacing(b);
158
159     sprintf(buffer,"%s-%d-mse.m",basename,book);
160     out=fopen(buffer,"w");
161     if(!out){
162       fprintf(stderr,"Could not open file %s for writing\n",buffer);
163       exit(1);
164     }
165     
166     for(i=0;i<n;i++){
167       for(k=0;k<dim;k++){
168         fprintf(out,"%d, %g, %g\n",
169                 i*dim+k,(b->valuelist+i*dim)[k],
170                 sqrt((histogram_errorsq[book]+i*dim)[k]/histogram[book][i]));
171       }
172     }
173     fclose(out);
174       
175     sprintf(buffer,"%s-%d-me.m",basename,book);
176     out=fopen(buffer,"w");
177     if(!out){
178       fprintf(stderr,"Could not open file %s for writing\n",buffer);
179       exit(1);
180     }
181     
182     for(i=0;i<n;i++){
183       for(k=0;k<dim;k++){
184         fprintf(out,"%d, %g, %g\n",
185                 i*dim+k,(b->valuelist+i*dim)[k],
186                 (histogram_error[book]+i*dim)[k]/histogram[book][i]);
187       }
188     }
189     fclose(out);
190
191     sprintf(buffer,"%s-%d-worst.m",basename,book);
192     out=fopen(buffer,"w");
193     if(!out){
194       fprintf(stderr,"Could not open file %s for writing\n",buffer);
195       exit(1);
196     }
197     
198     for(i=0;i<n;i++){
199       for(k=0;k<dim;k++){
200         fprintf(out,"%d, %g, %g, %g\n",
201                 i*dim+k,(b->valuelist+i*dim)[k],
202                 (b->valuelist+i*dim)[k]+(histogram_lo[book]+i*dim)[k],
203                 (b->valuelist+i*dim)[k]+(histogram_hi[book]+i*dim)[k]);
204       }
205     }
206     fclose(out);
207   }
208 }
209
210 float process_one(codebook *b,int book,float *a,int dim,int step,int addmul,
211                    float base){
212   int j,entry;
213   float amplitude=0.;
214
215   if(book==0){
216     float last=base;
217     for(j=0;j<dim;j++){
218       amplitude=a[j*step]-(b->c->q_sequencep?last:0);
219       meanamplitude_acc+=fabs(amplitude);
220       meanamplitudesq_acc+=amplitude*amplitude;
221       count++;
222       last=a[j*step];
223     }
224   }
225
226   if(b->c->q_sequencep){
227     float temp;
228     for(j=0;j<dim;j++){
229       temp=a[j*step];
230       a[j*step]-=base;
231     }
232     base=temp;
233   }
234
235   entry=vorbis_book_besterror(b,a,step,addmul);
236
237   if(entry==-1){
238     fprintf(stderr,"Internal error: _best returned -1.\n");
239     exit(1);
240   }
241   
242   histogram[book][entry]++;  
243   bits+=vorbis_book_codelen(b,entry);
244           
245   for(j=0;j<dim;j++){
246     float error=a[j*step];
247
248     if(book==books-1){
249       meanerror_acc+=fabs(error);
250       meanerrorsq_acc+=error*error;
251     }
252     histogram_errorsq[book][entry*dim+j]+=error*error;
253     histogram_error[book][entry*dim+j]+=fabs(error);
254     if(histogram[book][entry]==0 || histogram_hi[book][entry*dim+j]<error)
255       histogram_hi[book][entry*dim+j]=error;
256     if(histogram[book][entry]==0 || histogram_lo[book][entry*dim+j]>error)
257       histogram_lo[book][entry*dim+j]=error;
258   }
259   return base;
260 }
261
262
263 void process_vector(codebook **bs,int *addmul,int inter,float *a,int n){
264   int bi;
265   int i;
266
267   for(bi=0;bi<books;bi++){
268     codebook *b=bs[bi];
269     int dim=b->dim;
270     float base=0.;
271
272     if(inter){
273       for(i=0;i<n/dim;i++)
274         base=process_one(b,bi,a+i,dim,n/dim,addmul[bi],base);
275     }else{
276       for(i=0;i<=n-dim;i+=dim)
277         base=process_one(b,bi,a+i,dim,1,addmul[bi],base);
278     }
279   }
280   
281   if((long)(count)%100)spinnit("working.... samples: ",count);
282 }
283
284 void process_usage(void){
285   fprintf(stderr,
286           "usage: vqmetrics [-i] +|*<codebook>.vqh [ +|*<codebook.vqh> ]... \n"
287           "                 datafile.vqd [datafile.vqd]...\n\n"
288           "       data can be taken on stdin.  -i indicates interleaved coding.\n"
289           "       Output goes to output files:\n"
290           "       basename-me.m:       gnuplot: mean error by entry value\n"
291           "       basename-mse.m:      gnuplot: mean square error by entry value\n"
292           "       basename-worst.m:    gnuplot: worst error by entry value\n"
293           "       basename-distance.m: gnuplot file showing distance probability\n"
294           "\n");
295
296 }