Additional optimizations, rearrangement.
[platform/upstream/libvorbis.git] / vq / residuesplit.c
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 XIPHOPHORUS Company http://www.xiph.org/                  *
10
11  ********************************************************************
12
13  function: residue backend 0 partitioner/classifier
14  last mod: $Id: residuesplit.c,v 1.10 2001/02/26 03:51:12 xiphmont Exp $
15
16  ********************************************************************/
17
18 #include <stdlib.h>
19 #include <string.h>
20 #include <math.h>
21 #include <stdio.h>
22 #include "bookutil.h"
23
24 /* does not guard against invalid settings; eg, a subn of 16 and a
25    subgroup request of 32.  Max subn of 128 */
26 static void _testhack(float *vec,int n,float *entropy){
27   int i,j=0;
28   float max=0.f;
29   float temp[128];
30
31   /* setup */
32   for(i=0;i<n;i++)temp[i]=fabs(vec[i]);
33
34   /* handle case subgrp==1 outside */
35   for(i=0;i<n;i++)
36     if(temp[i]>max)max=temp[i];
37
38   for(i=0;i<n;i++)temp[i]=rint(temp[i]);
39
40   while(1){
41     entropy[j]=max;
42     n>>=1;
43     j++;
44
45     if(n<=0)break;
46     for(i=0;i<n;i++){
47       temp[i]+=temp[i+n];
48     }
49     max=0.f;
50     for(i=0;i<n;i++)
51       if(temp[i]>max)max=temp[i];
52   }
53 }
54
55 static FILE *of;
56 static FILE **or;
57
58 /* we evaluate the the entropy measure for each interleaved subgroup */
59 /* This is currently a bit specific to/hardwired for mapping 0; things
60    will need to change in the future when we get real multichannel
61    mappings */
62 int quantaux(float *res,int n,float *ebound,float *mbound,int *subgrp,int parts, int subn){
63   long i,j;
64   float entropy[8];
65   int aux;
66
67   for(i=0;i<=n-subn;i+=subn){
68     float max=0.f;
69
70     _testhack(res+i,subn,entropy);
71     for(j=0;j<subn;j++)
72       if(fabs(res[i+j])>max)max=fabs(res[i+j]);
73
74     for(j=0;j<parts-1;j++)
75       if(entropy[subgrp[j]]<=ebound[j] &&
76          max<=mbound[j])
77         break;
78     aux=j;
79     
80     fprintf(of,"%d, ",aux);
81     
82     for(j=0;j<subn;j++)
83       fprintf(or[aux],"%g, ",res[j+i]);
84     
85     fprintf(or[aux],"\n");
86   }
87
88   fprintf(of,"\n");
89
90   return(0);
91 }
92
93 static int getline(FILE *in,float *vec,int begin,int n){
94   int i,next=0;
95
96   reset_next_value();
97   if(get_next_value(in,vec))return(0);
98   if(begin){
99     for(i=1;i<begin;i++)
100       get_line_value(in,vec);
101     next=0;
102   }else{
103     next=1;
104   }
105
106   for(i=next;i<n;i++)
107     if(get_line_value(in,vec+i)){
108       fprintf(stderr,"ran out of columns in input data\n");
109       exit(1);
110     }
111   
112   return(1);
113 }
114
115 static void usage(){
116   fprintf(stderr,
117           "usage:\n" 
118           "residuesplit <res> <begin,n,group> <baseout> <ent,peak,sub> [<ent,peak,sub>]...\n"
119           "   where begin,n,group is first scalar, \n"
120           "                          number of scalars of each in line,\n"
121           "                          number of scalars in a group\n"
122           "         ent is the maximum entropy value allowed for membership in a group\n"
123           "         peak is the maximum amplitude value allowed for membership in a group\n"
124           "         subn is the maximum entropy value allowed for membership in a group\n"
125                    
126           "eg: residuesplit mask.vqd floor.vqd 0,1024,16 res 0,.5,16 3,1.5,8 \n"
127           "produces resaux.vqd and res_0...n.vqd\n\n");
128   exit(1);
129 }
130
131 int main(int argc, char *argv[]){
132   char *buffer;
133   char *base;
134   int i,parts,begin,n,subn,*subgrp;
135   FILE *res;
136   float *ebound,*mbound,*vec;
137   long c=0;
138   if(argc<5)usage();
139
140   base=strdup(argv[3]);
141   buffer=alloca(strlen(base)+20);
142   {
143     char *pos=strchr(argv[2],',');
144     begin=atoi(argv[2]);
145     if(!pos)
146       usage();
147     else
148       n=atoi(pos+1);
149     pos=strchr(pos+1,',');
150     if(!pos)
151       usage();
152     else
153       subn=atoi(pos+1);
154     if(n/subn*subn != n){
155       fprintf(stderr,"n must be divisible by group\n");
156       exit(1);
157     }
158   }
159
160   /* how many parts?... */
161   parts=argc-3;
162   
163   ebound=_ogg_malloc(sizeof(float)*parts);
164   mbound=_ogg_malloc(sizeof(float)*parts);
165   subgrp=_ogg_malloc(sizeof(int)*parts);
166   
167   for(i=0;i<parts-1;i++){
168     char *pos=strchr(argv[4+i],',');
169     if(*argv[4+i]==',')
170       ebound[i]=1e50f;
171     else
172       ebound[i]=atof(argv[4+i]);
173
174     if(!pos){
175       mbound[i]=1e50f;
176       subgrp[i]=_ilog(subn)-1;
177      }else{
178        if(*(pos+1)==',')
179          mbound[i]=1e50f;
180        else
181          mbound[i]=atof(pos+1);
182        pos=strchr(pos+1,',');
183        
184        if(!pos){
185          subgrp[i]=_ilog(subn)-1;
186        }else{
187          subgrp[i]=_ilog(atoi(pos+1))-1;
188        }
189      }
190   }
191
192   ebound[i]=1e50f;
193   mbound[i]=1e50f;
194   subgrp[i]=_ilog(subn)-1;
195
196   res=fopen(argv[1],"r");
197   if(!res){
198     fprintf(stderr,"Could not open file %s\n",argv[1]);
199     exit(1);
200   }
201
202   or=alloca(parts*sizeof(FILE*));
203   sprintf(buffer,"%saux.vqd",base);
204   of=fopen(buffer,"w");
205   if(!of){
206     fprintf(stderr,"Could not open file %s for writing\n",buffer);
207     exit(1);
208   }
209   for(i=0;i<parts;i++){
210     sprintf(buffer,"%s_%d.vqd",base,i);
211     or[i]=fopen(buffer,"w");
212     if(!or[i]){
213       fprintf(stderr,"Could not open file %s for writing\n",buffer);
214       exit(1);
215     }
216   }
217   
218   vec=_ogg_malloc(sizeof(float)*n);
219   /* get the input line by line and process it */
220   while(!feof(res)){
221     if(getline(res,vec,begin,n))
222       quantaux(vec,n,ebound,mbound,subgrp,parts,subn);
223     c++;
224     if(!(c&0xf)){
225       spinnit("kB so far...",(int)(ftell(res)/1024));
226     }
227   }
228   fclose(res);
229   fclose(of);
230   for(i=0;i<parts;i++)
231     fclose(or[i]);
232   fprintf(stderr,"\rDone                         \n");
233   return(0);
234 }
235
236
237
238