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: utility main for building codebooks from training sets 14 last mod: $Id: build.c 16037 2009-05-26 21:10:58Z xiphmont $ 15 16 ********************************************************************/ 17 18#include <stdlib.h> 19#include <stdio.h> 20#include <math.h> 21#include <string.h> 22#include <errno.h> 23#include "bookutil.h" 24 25#include "vqgen.h" 26#include "vqsplit.h" 27 28static char *linebuffer=NULL; 29static int lbufsize=0; 30static char *rline(FILE *in,FILE *out){ 31 long sofar=0; 32 if(feof(in))return NULL; 33 34 while(1){ 35 int gotline=0; 36 37 while(!gotline){ 38 if(sofar>=lbufsize){ 39 if(!lbufsize){ 40 lbufsize=1024; 41 linebuffer=_ogg_malloc(lbufsize); 42 }else{ 43 lbufsize*=2; 44 linebuffer=_ogg_realloc(linebuffer,lbufsize); 45 } 46 } 47 { 48 long c=fgetc(in); 49 switch(c){ 50 case '\n': 51 case EOF: 52 gotline=1; 53 break; 54 default: 55 linebuffer[sofar++]=c; 56 linebuffer[sofar]='\0'; 57 break; 58 } 59 } 60 } 61 62 if(linebuffer[0]=='#'){ 63 sofar=0; 64 }else{ 65 return(linebuffer); 66 } 67 } 68} 69 70/* command line: 71 buildvq file 72*/ 73 74int main(int argc,char *argv[]){ 75 vqgen v; 76 static_codebook c; 77 codebook b; 78 quant_meta q; 79 80 long *quantlist=NULL; 81 int entries=-1,dim=-1,aux=-1; 82 FILE *out=NULL; 83 FILE *in=NULL; 84 char *line,*name; 85 long i,j,k; 86 87 b.c=&c; 88 89 if(argv[1]==NULL){ 90 fprintf(stderr,"Need a trained data set on the command line.\n"); 91 exit(1); 92 } 93 94 { 95 char *ptr; 96 char *filename=strdup(argv[1]); 97 98 in=fopen(filename,"r"); 99 if(!in){ 100 fprintf(stderr,"Could not open input file %s\n",filename); 101 exit(1); 102 } 103 104 ptr=strrchr(filename,'-'); 105 if(ptr){ 106 *ptr='\0'; 107 name=strdup(filename); 108 sprintf(ptr,".vqh"); 109 }else{ 110 name=strdup(filename); 111 strcat(filename,".vqh"); 112 } 113 114 out=fopen(filename,"w"); 115 if(out==NULL){ 116 fprintf(stderr,"Unable to open %s for writing\n",filename); 117 exit(1); 118 } 119 } 120 121 /* suck in the trained book */ 122 123 /* read book type, but it doesn't matter */ 124 line=rline(in,out); 125 126 line=rline(in,out); 127 if(sscanf(line,"%d %d %d",&entries,&dim,&aux)!=3){ 128 fprintf(stderr,"Syntax error reading book file\n"); 129 exit(1); 130 } 131 132 /* just use it to allocate mem */ 133 vqgen_init(&v,dim,0,entries,0.f,NULL,NULL,0); 134 135 /* quant */ 136 line=rline(in,out); 137 if(sscanf(line,"%ld %ld %d %d",&q.min,&q.delta, 138 &q.quant,&q.sequencep)!=4){ 139 fprintf(stderr,"Syntax error reading book file\n"); 140 exit(1); 141 } 142 143 /* quantized entries */ 144 /* save quant data; we don't want to requantize later as our method 145 is currently imperfect wrt repeated application */ 146 i=0; 147 quantlist=_ogg_malloc(sizeof(long)*v.elements*v.entries); 148 for(j=0;j<entries;j++){ 149 float a; 150 for(k=0;k<dim;k++){ 151 line=rline(in,out); 152 sscanf(line,"%f",&a); 153 v.entrylist[i]=a; 154 quantlist[i++]=rint(a); 155 } 156 } 157 158 /* ignore bias */ 159 for(j=0;j<entries;j++)line=rline(in,out); 160 free(v.bias); 161 v.bias=NULL; 162 163 /* training points */ 164 { 165 float *b=alloca(sizeof(float)*(dim+aux)); 166 i=0; 167 v.entries=0; /* hack to avoid reseeding */ 168 while(1){ 169 for(k=0;k<dim+aux;k++){ 170 line=rline(in,out); 171 if(!line)break; 172 sscanf(line,"%f",b+k); 173 } 174 if(feof(in))break; 175 vqgen_addpoint(&v,b,NULL); 176 } 177 v.entries=entries; 178 } 179 180 fclose(in); 181 vqgen_unquantize(&v,&q); 182 183 /* build the book */ 184 vqsp_book(&v,&b,quantlist); 185 c.q_min=q.min; 186 c.q_delta=q.delta; 187 c.q_quant=q.quant; 188 c.q_sequencep=q.sequencep; 189 190 /* save the book in C header form */ 191 write_codebook(out,name,b.c); 192 193 fclose(out); 194 exit(0); 195} 196