Port opus-tools check to see if underlying file was overwritten.
[platform/upstream/libvorbis.git] / vq / huffbuild.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-2014             *
9  * by the Xiph.Org Foundation http://www.xiph.org/                  *
10  *                                                                  *
11  ********************************************************************
12
13  function: hufftree builder
14
15  ********************************************************************/
16
17 #include <stdlib.h>
18 #include <string.h>
19 #include <math.h>
20 #include <stdio.h>
21 #include "bookutil.h"
22
23 static int nsofar=0;
24 static int getval(FILE *in,int begin,int n,int group,int max){
25   float v;
26   int i;
27   long val=0;
28
29   if(nsofar>=n || get_line_value(in,&v)){
30     reset_next_value();
31     nsofar=0;
32     if(get_next_value(in,&v))
33       return(-1);
34     for(i=1;i<=begin;i++)
35       get_line_value(in,&v);
36   }
37
38   val=(int)v;
39   nsofar++;
40
41   for(i=1;i<group;i++,nsofar++)
42     if(nsofar>=n || get_line_value(in,&v))
43       return(getval(in,begin,n,group,max));
44     else
45       val = val*max+(int)v;
46   return(val);
47 }
48
49 static void usage(){
50   fprintf(stderr,
51           "usage:\n"
52           "huffbuild <input>.vqd <begin,n,group>|<lorange-hirange> [noguard]\n"
53           "   where begin,n,group is first scalar, \n"
54           "                          number of scalars of each in line,\n"
55           "                          number of scalars in a group\n"
56           "eg: huffbuild reslongaux.vqd 0,1024,4\n"
57           "produces reslongaux.vqh\n\n");
58   exit(1);
59 }
60
61 int main(int argc, char *argv[]){
62   char *base;
63   char *infile;
64   int i,j,k,begin,n,subn,guard=1;
65   FILE *file;
66   int maxval=0;
67   int loval=0;
68
69   if(argc<3)usage();
70   if(argc==4)guard=0;
71
72   infile=strdup(argv[1]);
73   base=strdup(infile);
74   if(strrchr(base,'.'))
75     strrchr(base,'.')[0]='\0';
76
77   {
78     char *pos=strchr(argv[2],',');
79     char *dpos=strchr(argv[2],'-');
80     if(dpos){
81       loval=atoi(argv[2]);
82       maxval=atoi(dpos+1);
83       subn=1;
84       begin=0;
85     }else{
86       begin=atoi(argv[2]);
87       if(!pos)
88         usage();
89       else
90         n=atoi(pos+1);
91       pos=strchr(pos+1,',');
92       if(!pos)
93         usage();
94       else
95         subn=atoi(pos+1);
96       if(n/subn*subn != n){
97         fprintf(stderr,"n must be divisible by group\n");
98         exit(1);
99       }
100     }
101   }
102
103   /* scan the file for maximum value */
104   file=fopen(infile,"r");
105   if(!file){
106     fprintf(stderr,"Could not open file %s\n",infile);
107     if(!maxval)
108       exit(1);
109     else
110       fprintf(stderr,"  making untrained books.\n");
111
112   }
113
114   if(!maxval){
115     i=0;
116     while(1){
117       long v;
118       if(get_next_ivalue(file,&v))break;
119       if(v>maxval)maxval=v;
120
121       if(!(i++&0xff))spinnit("loading... ",i);
122     }
123     rewind(file);
124     maxval++;
125   }
126
127   {
128     long vals=pow(maxval,subn);
129     long *hist=_ogg_calloc(vals,sizeof(long));
130     long *lengths=_ogg_calloc(vals,sizeof(long));
131
132     for(j=loval;j<vals;j++)hist[j]=guard;
133
134     if(file){
135       reset_next_value();
136       i/=subn;
137       while(!feof(file)){
138         long val=getval(file,begin,n,subn,maxval);
139         if(val==-1 || val>=vals)break;
140         hist[val]++;
141         if(!(i--&0xff))spinnit("loading... ",i*subn);
142       }
143       fclose(file);
144     }
145
146     /* we have the probabilities, build the tree */
147     fprintf(stderr,"Building tree for %ld entries\n",vals);
148     build_tree_from_lengths0(vals,hist,lengths);
149
150     /* save the book */
151     {
152       char *buffer=alloca(strlen(base)+5);
153       strcpy(buffer,base);
154       strcat(buffer,".vqh");
155       file=fopen(buffer,"w");
156       if(!file){
157         fprintf(stderr,"Could not open file %s\n",buffer);
158         exit(1);
159       }
160     }
161
162     /* first, the static vectors, then the book structure to tie it together. */
163     /* lengthlist */
164     fprintf(file,"static const char _huff_lengthlist_%s[] = {\n",base);
165     for(j=0;j<vals;){
166       fprintf(file,"\t");
167       for(k=0;k<16 && j<vals;k++,j++)
168         fprintf(file,"%2ld,",lengths[j]);
169       fprintf(file,"\n");
170     }
171     fprintf(file,"};\n\n");
172
173     /* the toplevel book */
174     fprintf(file,"static const static_codebook _huff_book_%s = {\n",base);
175     fprintf(file,"\t%d, %ld,\n",subn,vals);
176     fprintf(file,"\t(char *)_huff_lengthlist_%s,\n",base);
177     fprintf(file,"\t0, 0, 0, 0, 0,\n");
178     fprintf(file,"\tNULL,\n");
179
180     fprintf(file,"\t0\n};\n\n");
181
182     fclose(file);
183     fprintf(stderr,"Done.                                \n\n");
184   }
185   exit(0);
186 }
187
188
189
190
191
192
193
194
195
196
197