Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/libvorbis-1.2.0/vq/residuedata.c @ 28

Last change on this file since 28 was 16, checked in by landauf, 17 years ago

added libvorbis

File size: 4.5 KB
RevLine 
[16]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 residue VQ codebooks
14 last mod: $Id: residuedata.c 13293 2007-07-24 00:09:47Z xiphmont $
15
16 ********************************************************************/
17
18#include <stdlib.h>
19#include <math.h>
20#include <stdio.h>
21#include <string.h>
22#include "vqgen.h"
23#include "bookutil.h"
24#include "../lib/scales.h"
25#include "vqext.h"
26
27float scalequant=3.f;
28char *vqext_booktype="RESdata"; 
29quant_meta q={0,0,0,0};          /* set sequence data */
30int vqext_aux=0;
31
32static float *quant_save=NULL;
33
34float *vqext_weight(vqgen *v,float *p){
35  return p;
36}
37
38/* quantize aligned on unit boundaries.  Because our grid is likely
39   very coarse, play 'shuffle the blocks'; don't allow multiple
40   entries to fill the same spot as is nearly certain to happen. */
41
42void vqext_quantize(vqgen *v,quant_meta *q){
43  int j,k;
44  long dim=v->elements;
45  long n=v->entries;
46  float max=-1;
47  float *test=alloca(sizeof(float)*dim);
48  int moved=0;
49
50 
51  /* allow movement only to unoccupied coordinates on the coarse grid */
52  for(j=0;j<n;j++){
53    for(k=0;k<dim;k++){
54      float val=_now(v,j)[k];
55      float norm=rint(fabs(val)/scalequant);
56      if(norm>max)max=norm;
57      test[k]=norm;
58    }
59
60    /* allow move only if unoccupied */
61    if(quant_save){
62      for(k=0;k<n;k++)
63        if(j!=k && memcmp(test,quant_save+dim*k,dim*sizeof(float))==0)
64          break;
65      if(k==n){
66        if(memcmp(test,quant_save+dim*j,dim*sizeof(float)))     
67          moved++;
68        memcpy(quant_save+dim*j,test,sizeof(float)*dim);
69      }
70    }else{
71      memcpy(_now(v,j),test,sizeof(float)*dim);
72    }
73  }
74
75  /* unlike the other trainers, we fill in our quantization
76     information (as we know granularity beforehand and don't need to
77     maximize it) */
78
79  q->min=_float32_pack(0.f);
80  q->delta=_float32_pack(scalequant);
81  q->quant=_ilog(max);
82
83  if(quant_save){
84    memcpy(_now(v,0),quant_save,sizeof(float)*dim*n);
85    fprintf(stderr,"cells shifted this iteration: %d\n",moved);
86  }
87}
88
89                            /* candidate,actual */
90float vqext_metric(vqgen *v,float *e, float *p){
91  int i;
92  float acc=0.f;
93  for(i=0;i<v->elements;i++){
94    float val=p[i]-e[i];
95    acc+=val*val;
96  }
97  return sqrt(acc);
98}
99
100/* We don't interleave here; we assume that the interleave is provided
101   for us by residuesplit in vorbis/huff/ */
102void vqext_addpoint_adj(vqgen *v,float *b,int start,int dim,int cols,int num){
103  vqgen_addpoint(v,b+start,NULL);
104}
105
106/* need to reseed because of the coarse quantization we tend to use on
107   residuals (which causes lots & lots of dupes) */
108void vqext_preprocess(vqgen *v){
109  long i,j,k,l;
110  float *test=alloca(sizeof(float)*v->elements);
111  scalequant=q.quant;
112
113  vqext_quantize(v,&q);
114  vqgen_unquantize(v,&q);
115
116  /* if there are any dupes, reseed */
117  for(k=0;k<v->entries;k++){
118    for(l=0;l<k;l++){
119      if(memcmp(_now(v,k),_now(v,l),sizeof(float)*v->elements)==0)
120        break;
121    }
122    if(l<k)break;
123  }
124
125  if(k<v->entries){
126    fprintf(stderr,"reseeding with quantization....\n");
127
128    /* seed the inputs to input points, but points on unit boundaries,
129     ignoring quantbits for now, making sure each seed is unique */
130   
131    for(i=0,j=0;i<v->points && j<v->entries;i++){
132      for(k=0;k<v->elements;k++){
133        float val=_point(v,i)[k];
134        test[k]=rint(val/scalequant)*scalequant;
135      }
136     
137      for(l=0;l<j;l++){
138        for(k=0;k<v->elements;k++)
139          if(test[k]!=_now(v,l)[k])
140            break;
141        if(k==v->elements)break;
142      }
143      if(l==j){
144        memcpy(_now(v,j),test,v->elements*sizeof(float));
145        j++;
146      }
147    }
148   
149    if(j<v->elements){
150      fprintf(stderr,"Not enough unique entries after prequantization\n");
151      exit(1);
152    }
153  } 
154  vqext_quantize(v,&q);
155  quant_save=_ogg_malloc(sizeof(float)*v->elements*v->entries);
156  memcpy(quant_save,_now(v,0),sizeof(float)*v->elements*v->entries);
157  vqgen_unquantize(v,&q);
158
159}
160
Note: See TracBrowser for help on using the repository browser.