1 /********************************************************************
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. *
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/ *
12 ********************************************************************
14 function: metrics and quantization code for residue VQ codebooks
15 last mod: $Id: residuedata.c,v 1.5 2000/11/06 00:07:26 xiphmont Exp $
17 ********************************************************************/
25 #include "../lib/sharedbook.h"
26 #include "../lib/scales.h"
30 char *vqext_booktype="RESdata";
31 quant_meta q={0,0,0,0}; /* set sequence data */
34 static float *quant_save=NULL;
36 float *vqext_weight(vqgen *v,float *p){
40 /* quantize aligned on unit boundaries. Because our grid is likely
41 very coarse, play 'shuffle the blocks'; don't allow multiple
42 entries to fill the same spot as is nearly certain to happen. */
44 void vqext_quantize(vqgen *v,quant_meta *q){
49 float *test=alloca(sizeof(float)*dim);
53 /* allow movement only to unoccupied coordinates on the coarse grid */
56 float val=_now(v,j)[k];
57 float norm=rint(fabs(val)/scalequant);
62 /* allow move only if unoccupied */
65 if(j!=k && memcmp(test,quant_save+dim*k,dim*sizeof(float))==0)
68 if(memcmp(test,quant_save+dim*j,dim*sizeof(float)))
70 memcpy(quant_save+dim*j,test,sizeof(float)*dim);
73 memcpy(_now(v,j),test,sizeof(float)*dim);
77 /* unlike the other trainers, we fill in our quantization
78 information (as we know granularity beforehand and don't need to
81 q->min=_float32_pack(0.);
82 q->delta=_float32_pack(scalequant);
86 memcpy(_now(v,0),quant_save,sizeof(float)*dim*n);
87 fprintf(stderr,"cells shifted this iteration: %d\n",moved);
91 /* candidate,actual */
92 float vqext_metric(vqgen *v,float *e, float *p){
95 for(i=0;i<v->elements;i++){
102 /* We don't interleave here; we assume that the interleave is provided
103 for us by residuesplit in vorbis/huff/ */
104 void vqext_addpoint_adj(vqgen *v,float *b,int start,int dim,int cols,int num){
105 vqgen_addpoint(v,b+start,NULL);
108 /* need to reseed because of the coarse quantization we tend to use on
109 residuals (which causes lots & lots of dupes) */
110 void vqext_preprocess(vqgen *v){
112 float *test=alloca(sizeof(float)*v->elements);
115 vqext_quantize(v,&q);
116 vqgen_unquantize(v,&q);
118 /* if there are any dupes, reseed */
119 for(k=0;k<v->entries;k++){
121 if(memcmp(_now(v,k),_now(v,l),sizeof(float)*v->elements)==0)
128 fprintf(stderr,"reseeding with quantization....\n");
130 /* seed the inputs to input points, but points on unit boundaries,
131 ignoring quantbits for now, making sure each seed is unique */
133 for(i=0,j=0;i<v->points && j<v->entries;i++){
134 for(k=0;k<v->elements;k++){
135 float val=_point(v,i)[k];
136 test[k]=rint(val/scalequant)*scalequant;
140 for(k=0;k<v->elements;k++)
141 if(test[k]!=_now(v,l)[k])
143 if(k==v->elements)break;
146 memcpy(_now(v,j),test,v->elements*sizeof(float));
152 fprintf(stderr,"Not enough unique entries after prequantization\n");
156 vqext_quantize(v,&q);
157 quant_save=_ogg_malloc(sizeof(float)*v->elements*v->entries);
158 memcpy(quant_save,_now(v,0),sizeof(float)*v->elements*v->entries);
159 vqgen_unquantize(v,&q);