e2a61196ffbf295d691dffde7dd5fc95c2554f36
[platform/upstream/libvorbis.git] / vq / lspdata.c
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
14  function: metrics and quantization code for LSP VQ codebooks
15  last mod: $Id: lspdata.c,v 1.13 2000/10/12 03:13:02 xiphmont Exp $
16
17  ********************************************************************/
18
19 #include <stdlib.h>
20 #include <math.h>
21 #include <stdio.h>
22 #include "vqgen.h"
23 #include "vqext.h"
24 #include "../lib/sharedbook.h"
25
26 char *vqext_booktype="LSPdata";  
27 quant_meta q={0,0,0,1};          /* set sequence data */
28 int vqext_aux=1;
29
30 float global_maxdel=M_PI;
31 float global_mindel=M_PI;
32 #if 0
33 void vqext_quantize(vqgen *v,quant_meta *q){
34   float delta,mindel;
35   float maxquant=((1<<q->quant)-1);
36   int j,k;
37
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 */
41
42   delta=(global_maxdel-global_mindel)/((1<<q->quant)-1.5);
43   
44   q->min=_float32_pack(global_mindel);
45   q->delta=_float32_pack(delta);
46
47   mindel=_float32_unpack(q->min);
48   delta=_float32_unpack(q->delta);
49
50   for(j=0;j<v->entries;j++){
51     float last=0;
52     for(k=0;k<v->elements;k++){
53       float val=_now(v,j)[k];
54       float now=rint((val-last-mindel)/delta);
55       
56       _now(v,j)[k]=now;
57       if(now<0){
58         /* be paranoid; this should be impossible */
59         fprintf(stderr,"fault; quantized value<0\n");
60         exit(1);
61       }
62
63       if(now>maxquant){
64         /* be paranoid; this should be impossible */
65         fprintf(stderr,"fault; quantized value>max\n");
66         exit(1);
67       }
68       last=(now*delta)+mindel+last;
69     }
70   }
71
72 }
73 #else
74 void vqext_quantize(vqgen *v,quant_meta *q){
75   vqgen_quantize(v,q);
76 }
77 #endif
78
79 float *weight=NULL;
80 #if 0
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
85    features. */
86
87 #define FUDGE (global_maxdel-weight[i])
88
89 float *vqext_weight(vqgen *v,float *p){
90   int i;
91   int el=v->elements;
92   float lastp=0.;
93   for(i=0;i<el;i++){
94     float predist=(p[i]-lastp);
95     float postdist=(p[i+1]-p[i]);
96     weight[i]=(predist<postdist?predist:postdist);
97     lastp=p[i];
98   }
99   return p;
100 }
101 #else
102 #define FUDGE 1.
103 float *vqext_weight(vqgen *v,float *p){
104   return p;
105 }
106 #endif
107
108                             /* candidate,actual */
109 float vqext_metric(vqgen *v,float *e, float *p){
110   int i;
111   int el=v->elements;
112   float acc=0.;
113   for(i=0;i<el;i++){
114     float val=(p[i]-e[i])*FUDGE;
115     acc+=val*val;
116   }
117   return sqrt(acc/v->elements);
118 }
119
120 /* Data files are line-vectors, starting with zero.  If we want to
121    train on a subvector starting in the middle, we need to adjust the
122    data as if it was starting at zero.  we also need to add the 'aux'
123    value, which is an extra point at the end so we have leading and
124    trailing space */
125
126 /* assume vqext_aux==1 */
127 void vqext_addpoint_adj(vqgen *v,float *b,int start,int dim,int cols,int num){
128   float *a=alloca(sizeof(float)*(dim+1)); /* +aux */
129   float base=0;
130   int i;
131
132   if(start>0)base=b[start-1];
133   for(i=0;i<dim;i++)a[i]=b[i+start]-base;
134   if(start+dim+1>cols) /* +aux */
135     a[i]=a[i-1];
136   else
137     a[i]=b[i+start]-base;
138   
139   vqgen_addpoint(v,a,a+dim);
140 }
141
142 /* we just need to calc the global_maxdel from the training set */
143 void vqext_preprocess(vqgen *v){
144   long j,k;
145
146   global_maxdel=0.;
147   global_mindel=M_PI;
148   for(j=0;j<v->points;j++){
149     float last=0.;
150     for(k=0;k<v->elements+v->aux;k++){
151       float p=_point(v,j)[k];
152       if(p-last>global_maxdel)global_maxdel=p-last;
153       if(p-last<global_mindel)global_mindel=p-last;
154       last=p;
155     }
156   }
157
158   weight=malloc(sizeof(float)*v->elements);
159 }
160