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