First merge of new psychoacoustics. Have some unused codebooks to
[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.7 2000/05/08 20:49:50 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 double meanamplitude_acc=0.;
43 double meanamplitudesq_acc=0.;
44 double meanerror_acc=0.;
45 double meanerrorsq_acc=0.;
46
47 double **histogram=NULL;
48 double **histogram_error=NULL;
49 double **histogram_errorsq=NULL;
50 double **histogram_hi=NULL;
51 double **histogram_lo=NULL;
52 double bits=0.;
53 double count=0.;
54
55 static double *_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(double *));
67     histogram_error=calloc(books,sizeof(double *));
68     histogram_errorsq=calloc(books,sizeof(double *));
69     histogram_hi=calloc(books,sizeof(double *));
70     histogram_lo=calloc(books,sizeof(double *));
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(double));
79     histogram_error[i]=calloc(b->entries*b->dim,sizeof(double));
80     histogram_errorsq[i]=calloc(b->entries*b->dim,sizeof(double));
81     histogram_hi[i]=calloc(b->entries*b->dim,sizeof(double));
82     histogram_lo[i]=calloc(b->entries*b->dim,sizeof(double));
83   }
84 }
85
86 static double _dist(int el,double *a, double *b){
87   int i;
88   double acc=0.;
89   for(i=0;i<el;i++){
90     double 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   double 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       double localmin=-1.;
105       for(k=0;k<c->c->entries;k++){
106         if(c->c->lengthlist[k]>0){
107           double 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 double process_one(codebook *b,int book,double *a,int dim,int step,int addmul,
213                    double base){
214   int j,entry;
215   double amplitude=0.;
216
217   if(book==0){
218     double last=base;
219     for(j=0;j<dim;j++){
220       amplitude=a[j*step]-last;
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     double 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   histogram[book][entry]++;  
240   bits+=vorbis_book_codelen(b,entry);
241           
242   for(j=0;j<dim;j++){
243     double error=a[j*step];
244
245     if(book==books-1){
246       meanerror_acc+=fabs(error);
247       meanerrorsq_acc+=error*error;
248     }
249     histogram_errorsq[book][entry*dim+j]+=error*error;
250     histogram_error[book][entry*dim+j]+=fabs(error);
251     if(histogram[book][entry]==0 || histogram_hi[book][entry*dim+j]<error)
252       histogram_hi[book][entry*dim+j]=error;
253     if(histogram[book][entry]==0 || histogram_lo[book][entry*dim+j]>error)
254       histogram_lo[book][entry*dim+j]=error;
255   }
256   return base;
257 }
258
259
260 void process_vector(codebook **bs,int *addmul,int inter,double *a,int n){
261   int bi;
262   int i;
263
264   for(bi=0;bi<books;bi++){
265     codebook *b=bs[bi];
266     int dim=b->dim;
267     double base=0.;
268
269     if(inter){
270       for(i=0;i<n/dim;i++)
271         base=process_one(b,bi,a+i,dim,n/dim,addmul[bi],base);
272     }else{
273       for(i=0;i<=n-dim;i+=dim)
274         base=process_one(b,bi,a+i,dim,1,addmul[bi],base);
275     }
276   }
277   
278   if((long)(count)%100)spinnit("working.... samples: ",count);
279 }
280
281 void process_usage(void){
282   fprintf(stderr,
283           "usage: vqmetrics [-i] +|*<codebook>.vqh [ +|*<codebook.vqh> ]... \n"
284           "                 datafile.vqd [datafile.vqd]...\n\n"
285           "       data can be taken on stdin.  -i indicates interleaved coding.\n"
286           "       Output goes to output files:\n"
287           "       basename-me.m:       gnuplot: mean error by entry value\n"
288           "       basename-mse.m:      gnuplot: mean square error by entry value\n"
289           "       basename-worst.m:    gnuplot: worst error by entry value\n"
290           "       basename-distance.m: gnuplot file showing distance probability\n"
291           "\n");
292
293 }