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