bookutil.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594
  1. /********************************************************************
  2. * *
  3. * THIS FILE IS PART OF THE Ogg Vorbis SOFTWARE CODEC SOURCE CODE. *
  4. * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY *
  5. * THE GNU PUBLIC LICENSE 2, WHICH IS INCLUDED WITH THIS SOURCE. *
  6. * PLEASE READ THESE TERMS DISTRIBUTING. *
  7. * *
  8. * THE OggSQUISH SOURCE CODE IS (C) COPYRIGHT 1994-2000 *
  9. * by Monty <monty@xiph.org> and The XIPHOPHORUS Company *
  10. * http://www.xiph.org/ *
  11. * *
  12. ********************************************************************
  13. function: utility functions for loading .vqh and .vqd files
  14. last mod: $Id: bookutil.c,v 1.12.4.8 2000/05/08 08:25:43 xiphmont Exp $
  15. ********************************************************************/
  16. #include <stdlib.h>
  17. #include <stdio.h>
  18. #include <math.h>
  19. #include <string.h>
  20. #include <errno.h>
  21. #include "vorbis/codebook.h"
  22. #include "../lib/sharedbook.h"
  23. #include "bookutil.h"
  24. /* A few little utils for reading files */
  25. /* read a line. Use global, persistent buffering */
  26. static char *linebuffer=NULL;
  27. static int lbufsize=0;
  28. char *get_line(FILE *in){
  29. long sofar=0;
  30. if(feof(in))return NULL;
  31. while(1){
  32. int gotline=0;
  33. while(!gotline){
  34. if(sofar+1>=lbufsize){
  35. if(!lbufsize){
  36. lbufsize=1024;
  37. linebuffer=malloc(lbufsize);
  38. }else{
  39. lbufsize*=2;
  40. linebuffer=realloc(linebuffer,lbufsize);
  41. }
  42. }
  43. {
  44. long c=fgetc(in);
  45. switch(c){
  46. case EOF:
  47. if(sofar==0)return(NULL);
  48. /* fallthrough correct */
  49. case '\n':
  50. linebuffer[sofar]='\0';
  51. gotline=1;
  52. break;
  53. default:
  54. linebuffer[sofar++]=c;
  55. linebuffer[sofar]='\0';
  56. break;
  57. }
  58. }
  59. }
  60. if(linebuffer[0]=='#'){
  61. sofar=0;
  62. }else{
  63. return(linebuffer);
  64. }
  65. }
  66. }
  67. /* read the next numerical value from the given file */
  68. static char *value_line_buff=NULL;
  69. int get_line_value(FILE *in,double *value){
  70. char *next;
  71. if(!value_line_buff)return(-1);
  72. *value=strtod(value_line_buff, &next);
  73. if(next==value_line_buff){
  74. value_line_buff=NULL;
  75. return(-1);
  76. }else{
  77. value_line_buff=next;
  78. while(*value_line_buff>44)value_line_buff++;
  79. if(*value_line_buff==44)value_line_buff++;
  80. return(0);
  81. }
  82. }
  83. int get_next_value(FILE *in,double *value){
  84. while(1){
  85. if(get_line_value(in,value)){
  86. value_line_buff=get_line(in);
  87. if(!value_line_buff)return(-1);
  88. }else{
  89. return(0);
  90. }
  91. }
  92. }
  93. int get_next_ivalue(FILE *in,long *ivalue){
  94. double value;
  95. int ret=get_next_value(in,&value);
  96. *ivalue=value;
  97. return(ret);
  98. }
  99. static double sequence_base=0.;
  100. static int v_sofar=0;
  101. void reset_next_value(void){
  102. value_line_buff=NULL;
  103. sequence_base=0.;
  104. v_sofar=0;
  105. }
  106. char *setup_line(FILE *in){
  107. reset_next_value();
  108. value_line_buff=get_line(in);
  109. return(value_line_buff);
  110. }
  111. int get_vector(codebook *b,FILE *in,int start, int n,double *a){
  112. int i;
  113. const static_codebook *c=b->c;
  114. while(1){
  115. if(v_sofar==n || get_line_value(in,a)){
  116. reset_next_value();
  117. if(get_next_value(in,a))
  118. break;
  119. for(i=0;i<start;i++){
  120. sequence_base=*a;
  121. get_line_value(in,a);
  122. }
  123. }
  124. for(i=1;i<c->dim;i++)
  125. if(get_line_value(in,a+i))
  126. break;
  127. if(i==c->dim){
  128. double temp=a[c->dim-1];
  129. for(i=0;i<c->dim;i++)a[i]-=sequence_base;
  130. if(c->q_sequencep)sequence_base=temp;
  131. v_sofar++;
  132. return(0);
  133. }
  134. sequence_base=0.;
  135. }
  136. return(-1);
  137. }
  138. /* read lines fromt he beginning until we find one containing the
  139. specified string */
  140. char *find_seek_to(FILE *in,char *s){
  141. rewind(in);
  142. while(1){
  143. char *line=get_line(in);
  144. if(line){
  145. if(strstr(line,s))
  146. return(line);
  147. }else
  148. return(NULL);
  149. }
  150. }
  151. /* this reads the format as written by vqbuild; innocent (legal)
  152. tweaking of the file that would not affect its valid header-ness
  153. will break this routine */
  154. codebook *codebook_load(char *filename){
  155. codebook *b=calloc(1,sizeof(codebook));
  156. static_codebook *c=(static_codebook *)(b->c=calloc(1,sizeof(static_codebook)));
  157. encode_aux_nearestmatch *a=NULL;
  158. encode_aux_threshmatch *t=NULL;
  159. int quant_to_read=0;
  160. FILE *in=fopen(filename,"r");
  161. char *line;
  162. long i;
  163. if(in==NULL){
  164. fprintf(stderr,"Couldn't open codebook %s\n",filename);
  165. exit(1);
  166. }
  167. /* find the codebook struct */
  168. find_seek_to(in,"static static_codebook _vq_book_");
  169. /* get the major important values */
  170. line=get_line(in);
  171. if(sscanf(line,"%ld, %ld,",
  172. &(c->dim),&(c->entries))!=2){
  173. fprintf(stderr,"1: syntax in %s in line:\t %s",filename,line);
  174. exit(1);
  175. }
  176. line=get_line(in);
  177. line=get_line(in);
  178. if(sscanf(line,"%d, %ld, %ld, %d, %d,",
  179. &(c->maptype),&(c->q_min),&(c->q_delta),&(c->q_quant),
  180. &(c->q_sequencep))!=5){
  181. fprintf(stderr,"1: syntax in %s in line:\t %s",filename,line);
  182. exit(1);
  183. }
  184. /* find the auxiliary encode struct[s] (if any) */
  185. if(find_seek_to(in,"static encode_aux_nearestmatch _vq_aux")){
  186. /* how big? */
  187. c->nearest_tree=a=calloc(1,sizeof(encode_aux_nearestmatch));
  188. line=get_line(in);
  189. line=get_line(in);
  190. line=get_line(in);
  191. line=get_line(in);
  192. line=get_line(in);
  193. if(sscanf(line,"%ld, %ld",&(a->aux),&(a->alloc))!=2){
  194. fprintf(stderr,"2: syntax in %s in line:\t %s",filename,line);
  195. exit(1);
  196. }
  197. /* load ptr0 */
  198. find_seek_to(in,"static long _vq_ptr0");
  199. reset_next_value();
  200. a->ptr0=malloc(sizeof(long)*a->aux);
  201. for(i=0;i<a->aux;i++)
  202. if(get_next_ivalue(in,a->ptr0+i)){
  203. fprintf(stderr,"out of data while reading codebook %s\n",filename);
  204. exit(1);
  205. }
  206. /* load ptr1 */
  207. find_seek_to(in,"static long _vq_ptr1");
  208. reset_next_value();
  209. a->ptr1=malloc(sizeof(long)*a->aux);
  210. for(i=0;i<a->aux;i++)
  211. if(get_next_ivalue(in,a->ptr1+i)){
  212. fprintf(stderr,"out of data while reading codebook %s\n",filename);
  213. exit(1);
  214. }
  215. /* load p */
  216. find_seek_to(in,"static long _vq_p_");
  217. reset_next_value();
  218. a->p=malloc(sizeof(long)*a->aux);
  219. for(i=0;i<a->aux;i++)
  220. if(get_next_ivalue(in,a->p+i)){
  221. fprintf(stderr,"out of data while reading codebook %s\n",filename);
  222. exit(1);
  223. }
  224. /* load q */
  225. find_seek_to(in,"static long _vq_q_");
  226. reset_next_value();
  227. a->q=malloc(sizeof(long)*a->aux);
  228. for(i=0;i<a->aux;i++)
  229. if(get_next_ivalue(in,a->q+i)){
  230. fprintf(stderr,"out of data while reading codebook %s\n",filename);
  231. exit(1);
  232. }
  233. }
  234. if(find_seek_to(in,"static encode_aux_threshmatch _vq_aux")){
  235. /* how big? */
  236. c->thresh_tree=t=calloc(1,sizeof(encode_aux_threshmatch));
  237. line=get_line(in);
  238. line=get_line(in);
  239. line=get_line(in);
  240. if(sscanf(line,"%d",&(t->quantvals))!=1){
  241. fprintf(stderr,"3: syntax in %s in line:\t %s",filename,line);
  242. exit(1);
  243. }
  244. line=get_line(in);
  245. if(sscanf(line,"%d",&(t->threshvals))!=1){
  246. fprintf(stderr,"4: syntax in %s in line:\t %s",filename,line);
  247. exit(1);
  248. }
  249. /* load quantthresh */
  250. find_seek_to(in,"static double _vq_quantthresh_");
  251. reset_next_value();
  252. t->quantthresh=malloc(sizeof(double)*t->threshvals);
  253. for(i=0;i<t->threshvals-1;i++)
  254. if(get_next_value(in,t->quantthresh+i)){
  255. fprintf(stderr,"out of data 1 while reading codebook %s\n",filename);
  256. exit(1);
  257. }
  258. /* load quantmap */
  259. find_seek_to(in,"static long _vq_quantmap_");
  260. reset_next_value();
  261. t->quantmap=malloc(sizeof(long)*t->threshvals);
  262. for(i=0;i<t->threshvals;i++)
  263. if(get_next_ivalue(in,t->quantmap+i)){
  264. fprintf(stderr,"out of data 2 while reading codebook %s\n",filename);
  265. exit(1);
  266. }
  267. }
  268. switch(c->maptype){
  269. case 0:
  270. quant_to_read=0;
  271. break;
  272. case 1:
  273. quant_to_read=_book_maptype1_quantvals(c);
  274. break;
  275. case 2:
  276. quant_to_read=c->entries*c->dim;
  277. break;
  278. }
  279. /* load the quantized entries */
  280. find_seek_to(in,"static long _vq_quantlist_");
  281. reset_next_value();
  282. c->quantlist=malloc(sizeof(long)*quant_to_read);
  283. for(i=0;i<quant_to_read;i++)
  284. if(get_next_ivalue(in,c->quantlist+i)){
  285. fprintf(stderr,"out of data while reading codebook %s\n",filename);
  286. exit(1);
  287. }
  288. /* load the lengthlist */
  289. find_seek_to(in,"static long _vq_lengthlist");
  290. reset_next_value();
  291. c->lengthlist=malloc(sizeof(long)*c->entries);
  292. for(i=0;i<c->entries;i++)
  293. if(get_next_ivalue(in,c->lengthlist+i)){
  294. fprintf(stderr,"out of data while reading codebook %s\n",filename);
  295. exit(1);
  296. }
  297. /* got it all */
  298. fclose(in);
  299. vorbis_book_init_encode(b,c);
  300. return(b);
  301. }
  302. void spinnit(char *s,int n){
  303. static int p=0;
  304. static long lasttime=0;
  305. long test;
  306. struct timeval thistime;
  307. gettimeofday(&thistime,NULL);
  308. test=thistime.tv_sec*10+thistime.tv_usec/100000;
  309. if(lasttime!=test){
  310. lasttime=test;
  311. fprintf(stderr,"%s%d ",s,n);
  312. p++;if(p>3)p=0;
  313. switch(p){
  314. case 0:
  315. fprintf(stderr,"| \r");
  316. break;
  317. case 1:
  318. fprintf(stderr,"/ \r");
  319. break;
  320. case 2:
  321. fprintf(stderr,"- \r");
  322. break;
  323. case 3:
  324. fprintf(stderr,"\\ \r");
  325. break;
  326. }
  327. fflush(stderr);
  328. }
  329. }
  330. void build_tree_from_lengths(int vals, long *hist, long *lengths){
  331. int i,j;
  332. long *membership=malloc(vals*sizeof(long));
  333. long *histsave=alloca(vals*sizeof(long));
  334. memcpy(histsave,hist,vals*sizeof(long));
  335. for(i=0;i<vals;i++)membership[i]=i;
  336. /* find codeword lengths */
  337. /* much more elegant means exist. Brute force n^2, minimum thought */
  338. for(i=vals;i>1;i--){
  339. int first=-1,second=-1;
  340. long least=-1;
  341. spinnit("building... ",i);
  342. /* find the two nodes to join */
  343. for(j=0;j<vals;j++)
  344. if(least==-1 || hist[j]<least){
  345. least=hist[j];
  346. first=membership[j];
  347. }
  348. least=-1;
  349. for(j=0;j<vals;j++)
  350. if((least==-1 || hist[j]<least) && membership[j]!=first){
  351. least=hist[j];
  352. second=membership[j];
  353. }
  354. if(first==-1 || second==-1){
  355. fprintf(stderr,"huffman fault; no free branch\n");
  356. exit(1);
  357. }
  358. /* join them */
  359. least=hist[first]+hist[second];
  360. for(j=0;j<vals;j++)
  361. if(membership[j]==first || membership[j]==second){
  362. membership[j]=first;
  363. hist[j]=least;
  364. lengths[j]++;
  365. }
  366. }
  367. for(i=0;i<vals-1;i++)
  368. if(membership[i]!=membership[i+1]){
  369. fprintf(stderr,"huffman fault; failed to build single tree\n");
  370. exit(1);
  371. }
  372. /* for sanity check purposes: how many bits would it have taken to
  373. encode the training set? */
  374. {
  375. long bitsum=0;
  376. long samples=0;
  377. for(i=0;i<vals;i++){
  378. bitsum+=(histsave[i]-1)*lengths[i];
  379. samples+=histsave[i]-1;
  380. }
  381. fprintf(stderr,"\rTotal samples in training set: %ld \n",samples);
  382. fprintf(stderr,"\rTotal bits used to represent training set: %ld\n",
  383. bitsum);
  384. }
  385. free(membership);
  386. }
  387. void write_codebook(FILE *out,char *name,const static_codebook *c){
  388. encode_aux_threshmatch *t=c->thresh_tree;
  389. encode_aux_nearestmatch *n=c->nearest_tree;
  390. int j,k;
  391. /* save the book in C header form */
  392. fprintf(out,
  393. "/********************************************************************\n"
  394. " * *\n"
  395. " * THIS FILE IS PART OF THE Ogg Vorbis SOFTWARE CODEC SOURCE CODE. *\n"
  396. " * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY *\n"
  397. " * THE GNU PUBLIC LICENSE 2, WHICH IS INCLUDED WITH THIS SOURCE. *\n"
  398. " * PLEASE READ THESE TERMS DISTRIBUTING. *\n"
  399. " * *\n"
  400. " * THE OggSQUISH SOURCE CODE IS (C) COPYRIGHT 1994-1999 *\n"
  401. " * by 1999 Monty <monty@xiph.org> and The XIPHOPHORUS Company *\n"
  402. " * http://www.xiph.org/ *\n"
  403. " * *\n"
  404. " ********************************************************************\n"
  405. "\n"
  406. " function: static codebook autogenerated by vq/somethingorother\n"
  407. "\n"
  408. " ********************************************************************/\n\n");
  409. fprintf(out,"#ifndef _V_%s_VQH_\n#define _V_%s_VQH_\n",name,name);
  410. fprintf(out,"#include \"vorbis/codebook.h\"\n\n");
  411. /* first, the static vectors, then the book structure to tie it together. */
  412. /* quantlist */
  413. if(c->quantlist){
  414. long vals=(c->maptype==1?_book_maptype1_quantvals(c):c->entries*c->dim);
  415. fprintf(out,"static long _vq_quantlist_%s[] = {\n",name);
  416. for(j=0;j<vals;j++){
  417. fprintf(out,"\t%ld,\n",c->quantlist[j]);
  418. }
  419. fprintf(out,"};\n\n");
  420. }
  421. /* lengthlist */
  422. fprintf(out,"static long _vq_lengthlist_%s[] = {\n",name);
  423. for(j=0;j<c->entries;){
  424. fprintf(out,"\t");
  425. for(k=0;k<16 && j<c->entries;k++,j++)
  426. fprintf(out,"%2ld,",c->lengthlist[j]);
  427. fprintf(out,"\n");
  428. }
  429. fprintf(out,"};\n\n");
  430. if(t){
  431. /* quantthresh */
  432. fprintf(out,"static double _vq_quantthresh_%s[] = {\n",name);
  433. for(j=0;j<t->threshvals-1;){
  434. fprintf(out,"\t");
  435. for(k=0;k<8 && j<t->threshvals-1;k++,j++)
  436. fprintf(out,"%.5g, ",t->quantthresh[j]);
  437. fprintf(out,"\n");
  438. }
  439. fprintf(out,"};\n\n");
  440. /* quantmap */
  441. fprintf(out,"static long _vq_quantmap_%s[] = {\n",name);
  442. for(j=0;j<t->threshvals;){
  443. fprintf(out,"\t");
  444. for(k=0;k<8 && j<t->threshvals;k++,j++)
  445. fprintf(out,"%5ld,",t->quantmap[j]);
  446. fprintf(out,"\n");
  447. }
  448. fprintf(out,"};\n\n");
  449. fprintf(out,"static encode_aux_threshmatch _vq_auxt_%s = {\n",name);
  450. fprintf(out,"\t_vq_quantthresh_%s,\n",name);
  451. fprintf(out,"\t_vq_quantmap_%s,\n",name);
  452. fprintf(out,"\t%d,\n",t->quantvals);
  453. fprintf(out,"\t%d\n};\n\n",t->threshvals);
  454. }
  455. if(n){
  456. /* ptr0 */
  457. fprintf(out,"static long _vq_ptr0_%s[] = {\n",name);
  458. for(j=0;j<n->aux;){
  459. fprintf(out,"\t");
  460. for(k=0;k<8 && j<n->aux;k++,j++)
  461. fprintf(out,"%6ld,",n->ptr0[j]);
  462. fprintf(out,"\n");
  463. }
  464. fprintf(out,"};\n\n");
  465. /* ptr1 */
  466. fprintf(out,"static long _vq_ptr1_%s[] = {\n",name);
  467. for(j=0;j<n->aux;){
  468. fprintf(out,"\t");
  469. for(k=0;k<8 && j<n->aux;k++,j++)
  470. fprintf(out,"%6ld,",n->ptr1[j]);
  471. fprintf(out,"\n");
  472. }
  473. fprintf(out,"};\n\n");
  474. /* p */
  475. fprintf(out,"static long _vq_p_%s[] = {\n",name);
  476. for(j=0;j<n->aux;){
  477. fprintf(out,"\t");
  478. for(k=0;k<8 && j<n->aux;k++,j++)
  479. fprintf(out,"%6ld,",n->p[j]*c->dim);
  480. fprintf(out,"\n");
  481. }
  482. fprintf(out,"};\n\n");
  483. /* q */
  484. fprintf(out,"static long _vq_q_%s[] = {\n",name);
  485. for(j=0;j<n->aux;){
  486. fprintf(out,"\t");
  487. for(k=0;k<8 && j<n->aux;k++,j++)
  488. fprintf(out,"%6ld,",n->q[j]*c->dim);
  489. fprintf(out,"\n");
  490. }
  491. fprintf(out,"};\n\n");
  492. fprintf(out,"static encode_aux_nearestmatch _vq_auxn_%s = {\n",name);
  493. fprintf(out,"\t_vq_ptr0_%s,\n",name);
  494. fprintf(out,"\t_vq_ptr1_%s,\n",name);
  495. fprintf(out,"\t_vq_p_%s,\n",name);
  496. fprintf(out,"\t_vq_q_%s,\n",name);
  497. fprintf(out,"\t%ld, %ld\n};\n\n",n->aux,n->aux);
  498. }
  499. /* tie it all together */
  500. fprintf(out,"static static_codebook _vq_book_%s = {\n",name);
  501. fprintf(out,"\t%ld, %ld,\n",c->dim,c->entries);
  502. fprintf(out,"\t_vq_lengthlist_%s,\n",name);
  503. fprintf(out,"\t%d, %ld, %ld, %d, %d,\n",
  504. c->maptype,c->q_min,c->q_delta,c->q_quant,c->q_sequencep);
  505. if(c->quantlist)
  506. fprintf(out,"\t_vq_quantlist_%s,\n",name);
  507. else
  508. fprintf(out,"\tNULL,\n");
  509. if(n)
  510. fprintf(out,"\t&_vq_auxn_%s,\n",name);
  511. else
  512. fprintf(out,"\tNULL,\n");
  513. if(t)
  514. fprintf(out,"\t&_vq_auxt_%s,\n",name);
  515. else
  516. fprintf(out,"\tNULL,\n");
  517. fprintf(out,"};\n\n");
  518. fprintf(out,"\n#endif\n");
  519. }