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 LSP VQ codebooks
15 last mod: $Id: lspdata.c,v 1.15 2000/11/08 03:23:23 xiphmont Exp $
17 ********************************************************************/
26 char *vqext_booktype="LSPdata";
27 quant_meta q={0,0,0,1}; /* set sequence data */
30 float global_maxdel=M_PI;
31 float global_mindel=M_PI;
33 void vqext_quantize(vqgen *v,quant_meta *q){
35 float maxquant=((1<<q->quant)-1);
38 /* first find the basic delta amount from the maximum span to be
39 encoded. Loosen the delta slightly to allow for additional error
40 during sequence quantization */
42 delta=(global_maxdel-global_mindel)/((1<<q->quant)-1.5);
44 q->min=_float32_pack(global_mindel);
45 q->delta=_float32_pack(delta);
47 mindel=_float32_unpack(q->min);
48 delta=_float32_unpack(q->delta);
50 for(j=0;j<v->entries;j++){
52 for(k=0;k<v->elements;k++){
53 float val=_now(v,j)[k];
54 float now=rint((val-last-mindel)/delta);
58 /* be paranoid; this should be impossible */
59 fprintf(stderr,"fault; quantized value<0\n");
64 /* be paranoid; this should be impossible */
65 fprintf(stderr,"fault; quantized value>max\n");
68 last=(now*delta)+mindel+last;
74 void vqext_quantize(vqgen *v,quant_meta *q){
81 /* LSP training metric. We weight error proportional to distance
82 *between* LSP vector values. The idea of this metric is not to set
83 final cells, but get the midpoint spacing into a form conducive to
84 what we want, which is weighting toward preserving narrower
87 #define FUDGE (global_maxdel-weight[i])
89 float *vqext_weight(vqgen *v,float *p){
94 float predist=(p[i]-lastp);
95 float postdist=(p[i+1]-p[i]);
96 weight[i]=(predist<postdist?predist:postdist);
103 float *vqext_weight(vqgen *v,float *p){
108 /* candidate,actual */
109 float vqext_metric(vqgen *v,float *e, float *p){
114 float val=(p[i]-e[i])*FUDGE;
117 return sqrt(acc/v->elements);
120 /* Data files are line-vectors, now just deltas. The codebook entries
121 want to be monotonically increasing, so we adjust */
123 /* assume vqext_aux==1 */
124 void vqext_addpoint_adj(vqgen *v,float *b,int start,int dim,int cols,int num){
125 float *a=alloca(sizeof(float)*(dim+1)); /* +aux */
130 base=a[i]=b[i+start]+base;
132 if(start+dim+1>cols) /* +aux */
135 a[i]=b[i+start]+base;
137 vqgen_addpoint(v,a,a+dim);
140 /* we just need to calc the global_maxdel from the training set */
141 void vqext_preprocess(vqgen *v){
146 for(j=0;j<v->points;j++){
148 for(k=0;k<v->elements+v->aux;k++){
149 float p=_point(v,j)[k];
150 if(p-last>global_maxdel)global_maxdel=p-last;
151 if(p-last<global_mindel)global_mindel=p-last;
156 weight=_ogg_malloc(sizeof(float)*v->elements);