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