Merge branch_beta3 onto the mainline.
[platform/upstream/libvorbis.git] / vq / lspdata.c
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
14  function: metrics and quantization code for LSP VQ codebooks
15  last mod: $Id: lspdata.c,v 1.14 2000/11/06 00:07:26 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, now just deltas.  The codebook entries
121    want to be monotonically increasing, so we adjust */
122
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 */
126   float base=0;
127   int i;
128
129   for(i=0;i<dim;i++)
130     base=a[i]=b[i+start]+base;
131
132   if(start+dim+1>cols) /* +aux */
133     a[i]=M_PI;
134   else
135     a[i]=b[i+start]+base;
136   
137   vqgen_addpoint(v,a,a+dim);
138 }
139
140 /* we just need to calc the global_maxdel from the training set */
141 void vqext_preprocess(vqgen *v){
142   long j,k;
143
144   global_maxdel=0.;
145   global_mindel=M_PI;
146   for(j=0;j<v->points;j++){
147     float last=0.;
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;
152       last=p;
153     }
154   }
155
156   weight=_ogg_malloc(sizeof(float)*v->elements);
157 }
158