residuedata.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. /********************************************************************
  2. * *
  3. * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
  4. * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY *
  5. * THE GNU LESSER/LIBRARY PUBLIC LICENSE, WHICH IS INCLUDED WITH *
  6. * THIS SOURCE. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
  7. * *
  8. * THE OggVorbis 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: metrics and quantization code for residue VQ codebooks
  14. last mod: $Id: residuedata.c,v 1.4.2.2 2000/11/04 06:43:55 xiphmont Exp $
  15. ********************************************************************/
  16. #include <stdlib.h>
  17. #include <math.h>
  18. #include <stdio.h>
  19. #include <string.h>
  20. #include "vqgen.h"
  21. #include "bookutil.h"
  22. #include "../lib/sharedbook.h"
  23. #include "../lib/scales.h"
  24. #include "vqext.h"
  25. float scalequant=3.;
  26. char *vqext_booktype="RESdata";
  27. quant_meta q={0,0,0,0}; /* set sequence data */
  28. int vqext_aux=0;
  29. static float *quant_save=NULL;
  30. float *vqext_weight(vqgen *v,float *p){
  31. return p;
  32. }
  33. /* quantize aligned on unit boundaries. Because our grid is likely
  34. very coarse, play 'shuffle the blocks'; don't allow multiple
  35. entries to fill the same spot as is nearly certain to happen. */
  36. void vqext_quantize(vqgen *v,quant_meta *q){
  37. int j,k;
  38. long dim=v->elements;
  39. long n=v->entries;
  40. float max=-1;
  41. float *test=alloca(sizeof(float)*dim);
  42. int moved=0;
  43. /* allow movement only to unoccupied coordinates on the coarse grid */
  44. for(j=0;j<n;j++){
  45. for(k=0;k<dim;k++){
  46. float val=_now(v,j)[k];
  47. float norm=rint(fabs(val)/scalequant);
  48. if(norm>max)max=norm;
  49. test[k]=norm;
  50. }
  51. /* allow move only if unoccupied */
  52. if(quant_save){
  53. for(k=0;k<n;k++)
  54. if(j!=k && memcmp(test,quant_save+dim*k,dim*sizeof(float))==0)
  55. break;
  56. if(k==n){
  57. if(memcmp(test,quant_save+dim*j,dim*sizeof(float)))
  58. moved++;
  59. memcpy(quant_save+dim*j,test,sizeof(float)*dim);
  60. }
  61. }else{
  62. memcpy(_now(v,j),test,sizeof(float)*dim);
  63. }
  64. }
  65. /* unlike the other trainers, we fill in our quantization
  66. information (as we know granularity beforehand and don't need to
  67. maximize it) */
  68. q->min=_float32_pack(0.);
  69. q->delta=_float32_pack(scalequant);
  70. q->quant=_ilog(max);
  71. if(quant_save){
  72. memcpy(_now(v,0),quant_save,sizeof(float)*dim*n);
  73. fprintf(stderr,"cells shifted this iteration: %d\n",moved);
  74. }
  75. }
  76. /* candidate,actual */
  77. float vqext_metric(vqgen *v,float *e, float *p){
  78. int i;
  79. float acc=0.;
  80. for(i=0;i<v->elements;i++){
  81. float val=p[i]-e[i];
  82. acc+=val*val;
  83. }
  84. return sqrt(acc);
  85. }
  86. /* We don't interleave here; we assume that the interleave is provided
  87. for us by residuesplit in vorbis/huff/ */
  88. void vqext_addpoint_adj(vqgen *v,float *b,int start,int dim,int cols,int num){
  89. vqgen_addpoint(v,b+start,NULL);
  90. }
  91. /* need to reseed because of the coarse quantization we tend to use on
  92. residuals (which causes lots & lots of dupes) */
  93. void vqext_preprocess(vqgen *v){
  94. long i,j,k,l;
  95. float *test=alloca(sizeof(float)*v->elements);
  96. scalequant=q.quant;
  97. vqext_quantize(v,&q);
  98. vqgen_unquantize(v,&q);
  99. /* if there are any dupes, reseed */
  100. for(k=0;k<v->entries;k++){
  101. for(l=0;l<k;l++){
  102. if(memcmp(_now(v,k),_now(v,l),sizeof(float)*v->elements)==0)
  103. break;
  104. }
  105. if(l<k)break;
  106. }
  107. if(k<v->entries){
  108. fprintf(stderr,"reseeding with quantization....\n");
  109. /* seed the inputs to input points, but points on unit boundaries,
  110. ignoring quantbits for now, making sure each seed is unique */
  111. for(i=0,j=0;i<v->points && j<v->entries;i++){
  112. for(k=0;k<v->elements;k++){
  113. float val=_point(v,i)[k];
  114. test[k]=rint(val/scalequant)*scalequant;
  115. }
  116. for(l=0;l<j;l++){
  117. for(k=0;k<v->elements;k++)
  118. if(test[k]!=_now(v,l)[k])
  119. break;
  120. if(k==v->elements)break;
  121. }
  122. if(l==j){
  123. memcpy(_now(v,j),test,v->elements*sizeof(float));
  124. j++;
  125. }
  126. }
  127. if(j<v->elements){
  128. fprintf(stderr,"Not enough unique entries after prequantization\n");
  129. exit(1);
  130. }
  131. }
  132. vqext_quantize(v,&q);
  133. quant_save=_ogg_malloc(sizeof(float)*v->elements*v->entries);
  134. memcpy(quant_save,_now(v,0),sizeof(float)*v->elements*v->entries);
  135. vqgen_unquantize(v,&q);
  136. }