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: metrics and quantization code for LSP VQ codebooks 14 last mod: $Id: lspdata.c 16037 2009-05-26 21:10:58Z xiphmont $ 15 16 ********************************************************************/ 17 18#include <stdlib.h> 19#include <math.h> 20#include <stdio.h> 21#include "vqgen.h" 22#include "vqext.h" 23#include "codebook.h" 24 25char *vqext_booktype="LSPdata"; 26quant_meta q={0,0,0,1}; /* set sequence data */ 27int vqext_aux=1; 28 29float global_maxdel=M_PI; 30float global_mindel=M_PI; 31#if 0 32void vqext_quantize(vqgen *v,quant_meta *q){ 33 float delta,mindel; 34 float maxquant=((1<<q->quant)-1); 35 int j,k; 36 37 /* first find the basic delta amount from the maximum span to be 38 encoded. Loosen the delta slightly to allow for additional error 39 during sequence quantization */ 40 41 delta=(global_maxdel-global_mindel)/((1<<q->quant)-1.5f); 42 43 q->min=_float32_pack(global_mindel); 44 q->delta=_float32_pack(delta); 45 46 mindel=_float32_unpack(q->min); 47 delta=_float32_unpack(q->delta); 48 49 for(j=0;j<v->entries;j++){ 50 float last=0; 51 for(k=0;k<v->elements;k++){ 52 float val=_now(v,j)[k]; 53 float now=rint((val-last-mindel)/delta); 54 55 _now(v,j)[k]=now; 56 if(now<0){ 57 /* be paranoid; this should be impossible */ 58 fprintf(stderr,"fault; quantized value<0\n"); 59 exit(1); 60 } 61 62 if(now>maxquant){ 63 /* be paranoid; this should be impossible */ 64 fprintf(stderr,"fault; quantized value>max\n"); 65 exit(1); 66 } 67 last=(now*delta)+mindel+last; 68 } 69 } 70 71} 72#else 73void vqext_quantize(vqgen *v,quant_meta *q){ 74 vqgen_quantize(v,q); 75} 76#endif 77 78float *weight=NULL; 79#if 0 80/* LSP training metric. We weight error proportional to distance 81 *between* LSP vector values. The idea of this metric is not to set 82 final cells, but get the midpoint spacing into a form conducive to 83 what we want, which is weighting toward preserving narrower 84 features. */ 85 86#define FUDGE (global_maxdel-weight[i]) 87 88float *vqext_weight(vqgen *v,float *p){ 89 int i; 90 int el=v->elements; 91 float lastp=0.f; 92 for(i=0;i<el;i++){ 93 float predist=(p[i]-lastp); 94 float postdist=(p[i+1]-p[i]); 95 weight[i]=(predist<postdist?predist:postdist); 96 lastp=p[i]; 97 } 98 return p; 99} 100#else 101#define FUDGE 1.f 102float *vqext_weight(vqgen *v,float *p){ 103 return p; 104} 105#endif 106 107 /* candidate,actual */ 108float vqext_metric(vqgen *v,float *e, float *p){ 109 int i; 110 int el=v->elements; 111 float acc=0.f; 112 for(i=0;i<el;i++){ 113 float val=(p[i]-e[i])*FUDGE; 114 acc+=val*val; 115 } 116 return sqrt(acc/v->elements); 117} 118 119/* Data files are line-vectors, now just deltas. The codebook entries 120 want to be monotonically increasing, so we adjust */ 121 122/* assume vqext_aux==1 */ 123void vqext_addpoint_adj(vqgen *v,float *b,int start,int dim,int cols,int num){ 124 float *a=alloca(sizeof(float)*(dim+1)); /* +aux */ 125 float base=0; 126 int i; 127 128 for(i=0;i<dim;i++) 129 base=a[i]=b[i+start]+base; 130 131 if(start+dim+1>cols) /* +aux */ 132 a[i]=M_PI; 133 else 134 a[i]=b[i+start]+base; 135 136 vqgen_addpoint(v,a,a+dim); 137} 138 139/* we just need to calc the global_maxdel from the training set */ 140void vqext_preprocess(vqgen *v){ 141 long j,k; 142 143 global_maxdel=0.f; 144 global_mindel=M_PI; 145 for(j=0;j<v->points;j++){ 146 float last=0.; 147 for(k=0;k<v->elements+v->aux;k++){ 148 float p=_point(v,j)[k]; 149 if(p-last>global_maxdel)global_maxdel=p-last; 150 if(p-last<global_mindel)global_mindel=p-last; 151 last=p; 152 } 153 } 154 155 weight=_ogg_malloc(sizeof(float)*v->elements); 156} 157 158