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