huffbuild.c 4.7 KB

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