1 /********************************************************************
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. *
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/ *
12 ********************************************************************
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 $
17 ********************************************************************/
24 #include "../lib/sharedbook.h"
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, 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
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 */
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 */
137 a[i]=b[i+start]-base;
139 vqgen_addpoint(v,a,a+dim);
142 /* we just need to calc the global_maxdel from the training set */
143 void vqext_preprocess(vqgen *v){
148 for(j=0;j<v->points;j++){
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;
158 weight=malloc(sizeof(float)*v->elements);