Collect training data from the lib when compiled with -DTRAIN
[platform/upstream/libvorbis.git] / lib / floor0.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: floor backend 0 implementation
15  last mod: $Id: floor0.c,v 1.9 2000/02/12 08:33:05 xiphmont Exp $
16
17  ********************************************************************/
18
19 #include <stdlib.h>
20 #include <string.h>
21 #include <math.h>
22 #include "vorbis/codec.h"
23 #include "bitwise.h"
24 #include "registry.h"
25 #include "lpc.h"
26 #include "lsp.h"
27 #include "bookinternal.h"
28 #include "scales.h"
29
30 typedef struct {
31   long n;
32   long m;
33   
34   double ampscale;
35   double ampvals;
36
37   vorbis_info_floor0 *vi;
38   lpc_lookup lpclook;
39 } vorbis_look_floor0;
40
41 static void free_info(vorbis_info_floor *i){
42   if(i){
43     memset(i,0,sizeof(vorbis_info_floor0));
44     free(i);
45   }
46 }
47
48 static void free_look(vorbis_look_floor *i){
49   vorbis_look_floor0 *f=(vorbis_look_floor0 *)i;
50   if(i){
51     lpc_clear(&f->lpclook);
52     memset(f,0,sizeof(vorbis_look_floor0));
53     free(f);
54   }
55 }
56
57 static void pack (vorbis_info_floor *i,oggpack_buffer *opb){
58   vorbis_info_floor0 *d=(vorbis_info_floor0 *)i;
59   int j;
60   _oggpack_write(opb,d->order,8);
61   _oggpack_write(opb,d->rate,16);
62   _oggpack_write(opb,d->barkmap,16);
63   _oggpack_write(opb,d->ampbits,6);
64   _oggpack_write(opb,d->ampdB,8);
65   _oggpack_write(opb,d->stages-1,4);
66   for(j=0;j<d->stages;j++)
67     _oggpack_write(opb,d->books[j],8);
68 }
69
70 static vorbis_info_floor *unpack (vorbis_info *vi,oggpack_buffer *opb){
71   int j;
72   vorbis_info_floor0 *d=malloc(sizeof(vorbis_info_floor0));
73   d->order=_oggpack_read(opb,8);
74   d->rate=_oggpack_read(opb,16);
75   d->barkmap=_oggpack_read(opb,16);
76   d->ampbits=_oggpack_read(opb,6);
77   d->ampdB=_oggpack_read(opb,8);
78   d->stages=_oggpack_read(opb,4)+1;
79   
80   if(d->order<1)goto err_out;
81   if(d->rate<1)goto err_out;
82   if(d->barkmap<1)goto err_out;
83   if(d->stages<1)goto err_out;
84
85   for(j=0;j<d->stages;j++){
86     d->books[j]=_oggpack_read(opb,8);
87     if(d->books[j]<0 || d->books[j]>=vi->books)goto err_out;
88   }
89   return(d);  
90  err_out:
91   free_info(d);
92   return(NULL);
93 }
94
95 static vorbis_look_floor *look (vorbis_info *vi,vorbis_info_mode *mi,
96                               vorbis_info_floor *i){
97   vorbis_info_floor0 *d=(vorbis_info_floor0 *)i;
98   vorbis_look_floor0 *ret=malloc(sizeof(vorbis_look_floor0));
99   ret->m=d->order;
100   ret->n=vi->blocksizes[mi->blockflag]/2;
101   ret->vi=d;
102   lpc_init(&ret->lpclook,ret->n,d->barkmap,d->rate,ret->m);
103
104   return ret;
105 }
106
107 #include <stdio.h>
108
109 static int forward(vorbis_block *vb,vorbis_look_floor *i,
110                     double *in,double *out){
111   long j,k,stage;
112   vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
113   vorbis_info_floor0 *info=look->vi;
114
115   /* use 'out' as temp storage */
116   /* Convert our floor to a set of lpc coefficients */ 
117   double amp=sqrt(vorbis_curve_to_lpc(in,out,&look->lpclook));
118
119   /* amp is in the range 0. to 1. (well, more like .7). Log scale it */
120   
121   /* 0              == 0 dB
122      (1<<ampbits)-1 == amp dB   = 1. amp */
123   {
124     long ampscale=fromdB(info->ampdB);
125     long maxval=(1<<info->ampbits)-1;
126
127     long val=todB(amp*ampscale)/info->ampdB*maxval+1;
128
129     if(val<0)val=0;           /* likely */
130     if(val>maxval)val=maxval; /* not bloody likely */
131
132     _oggpack_write(&vb->opb,val,info->ampbits);
133     if(val>0)
134       amp=fromdB((val-.5)/maxval*info->ampdB)/ampscale;
135     else
136       amp=0;
137   }
138
139   if(amp>0){
140     double *work=alloca(sizeof(double)*look->m);
141     
142     /* LSP <-> LPC is orthogonal and LSP quantizes more stably  */
143     vorbis_lpc_to_lsp(out,out,look->m);
144     memcpy(work,out,sizeof(double)*look->m);
145
146 #ifdef TRAIN
147     {
148       int j;
149       FILE *of;
150       char buffer[80];
151       sprintf(buffer,"lsp0coeff_%d.vqd",vb->mode);
152       of=fopen(buffer,"a");
153       for(j=0;j<look->m;j++)
154         fprintf(of,"%g, ",out[j]);
155       fprintf(of,"\n");
156       fclose(of);
157     }
158 #endif
159
160     /* code the spectral envelope, and keep track of the actual
161        quantized values; we don't want creeping error as each block is
162        nailed to the last quantized value of the previous block. */
163     
164     /* first stage is a bit different because quantization error must be
165        handled carefully */
166     for(stage=0;stage<info->stages;stage++){
167       codebook *b=vb->vd->fullbooks+info->books[stage];
168       
169       if(stage==0){
170         double last=0.;
171         for(j=0;j<look->m;){
172           for(k=0;k<b->dim;k++)out[j+k]-=last;
173           vorbis_book_encodev(b,out+j,&vb->opb);
174           for(k=0;k<b->dim;k++,j++){
175             out[j]+=last;
176             work[j]-=out[j];
177           }
178           last=out[j-1];
179         }
180       }else{
181         memcpy(out,work,sizeof(double)*look->m);
182         for(j=0;j<look->m;){
183           vorbis_book_encodev(b,out+j,&vb->opb);
184           for(k=0;k<b->dim;k++,j++)work[j]-=out[j];
185         }
186       }
187     }
188     /* take the coefficients back to a spectral envelope curve */
189     vorbis_lsp_to_lpc(out,out,look->m); 
190     vorbis_lpc_to_curve(out,out,amp,&look->lpclook);
191     return(1);
192   }
193
194   memset(out,0,sizeof(double)*look->n);
195   return(0);
196 }
197
198 static int inverse(vorbis_block *vb,vorbis_look_floor *i,double *out){
199   vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
200   vorbis_info_floor0 *info=look->vi;
201   int j,k,stage;
202   
203   long ampraw=_oggpack_read(&vb->opb,info->ampbits);
204   if(ampraw>0){
205     long ampscale=fromdB(info->ampdB);
206     long maxval=(1<<info->ampbits)-1;
207     double amp=fromdB((ampraw-.5)/maxval*info->ampdB)/ampscale;
208
209     memset(out,0,sizeof(double)*look->m);    
210     for(stage=0;stage<info->stages;stage++){
211       codebook *b=vb->vd->fullbooks+info->books[stage];
212       for(j=0;j<look->m;j+=b->dim)
213         vorbis_book_decodev(b,out+j,&vb->opb);
214       if(stage==0){
215         double last=0.;
216         for(j=0;j<look->m;){
217           for(k=0;k<b->dim;k++,j++)out[j]+=last;
218           last=out[j-1];
219         }
220       }
221     }
222   
223
224     /* take the coefficients back to a spectral envelope curve */
225     vorbis_lsp_to_lpc(out,out,look->m); 
226     vorbis_lpc_to_curve(out,out,amp,&look->lpclook);
227     return(1);
228   }else
229     memset(out,0,sizeof(double)*look->n);
230   return(0);
231 }
232
233 /* export hooks */
234 vorbis_func_floor floor0_exportbundle={
235   &pack,&unpack,&look,&free_info,&free_look,&forward,&inverse
236 };
237
238