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