e18689f9ec1cd6abaadf2077d79ae865708db788
[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.6 2000/02/06 13:39:40 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
29 typedef struct {
30   long n;
31   long m;
32   vorbis_info_floor0 *vi;
33   lpc_lookup lpclook;
34 } vorbis_look_floor0;
35
36 static void free_info(vorbis_info_floor *i){
37   if(i){
38     memset(i,0,sizeof(vorbis_info_floor0));
39     free(i);
40   }
41 }
42
43 static void free_look(vorbis_look_floor *i){
44   vorbis_look_floor0 *f=(vorbis_look_floor0 *)i;
45   if(i){
46     lpc_clear(&f->lpclook);
47     memset(f,0,sizeof(vorbis_look_floor0));
48     free(f);
49   }
50 }
51
52 static void pack (vorbis_info_floor *i,oggpack_buffer *opb){
53   vorbis_info_floor0 *d=(vorbis_info_floor0 *)i;
54   int j;
55   _oggpack_write(opb,d->order,8);
56   _oggpack_write(opb,d->rate,16);
57   _oggpack_write(opb,d->barkmap,16);
58   _oggpack_write(opb,d->stages-1,4);
59   for(j=0;j<d->stages;j++)
60     _oggpack_write(opb,d->books[j],8);
61 }
62
63 static vorbis_info_floor *unpack (vorbis_info *vi,oggpack_buffer *opb){
64   int j;
65   vorbis_info_floor0 *d=malloc(sizeof(vorbis_info_floor0));
66   d->order=_oggpack_read(opb,8);
67   d->rate=_oggpack_read(opb,16);
68   d->barkmap=_oggpack_read(opb,16);
69   d->stages=_oggpack_read(opb,4)+1;
70   
71   if(d->order<1)goto err_out;
72   if(d->rate<1)goto err_out;
73   if(d->barkmap<1)goto err_out;
74   if(d->stages<1)goto err_out;
75
76   for(j=0;j<d->stages;j++){
77     d->books[j]=_oggpack_read(opb,8);
78     if(d->books[j]<0 || d->books[j]>=vi->books)goto err_out;
79   }
80   return(d);  
81  err_out:
82   free_info(d);
83   return(NULL);
84 }
85
86 static vorbis_look_floor *look (vorbis_info *vi,vorbis_info_mode *mi,
87                               vorbis_info_floor *i){
88   vorbis_info_floor0 *d=(vorbis_info_floor0 *)i;
89   vorbis_look_floor0 *ret=malloc(sizeof(vorbis_look_floor0));
90   ret->m=d->order;
91   ret->n=vi->blocksizes[mi->blockflag]/2;
92   ret->vi=d;
93   lpc_init(&ret->lpclook,ret->n,d->barkmap,d->rate,ret->m);
94   return ret;
95 }
96
97 #include <stdio.h>
98
99 static int forward(vorbis_block *vb,vorbis_look_floor *i,
100                     double *in,double *out){
101   long j,k,l;
102   vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
103   vorbis_info_floor0 *info=look->vi;
104
105   /* use 'out' as temp storage */
106   /* Convert our floor to a set of lpc coefficients */ 
107   double amp=sqrt(vorbis_curve_to_lpc(in,out,&look->lpclook));
108   double *work=alloca(sizeof(double)*look->m);
109
110   /* LSP <-> LPC is orthogonal and LSP quantizes more stably  */
111   vorbis_lpc_to_lsp(out,out,look->m);
112   memcpy(work,out,sizeof(double)*look->m);
113
114   for(j=12;j<20;j++)
115     fprintf(stderr,"%0.3g, ",out[j]);
116   fprintf(stderr,"\n");
117
118   /* code the spectral envelope, and keep track of the actual quantized
119      values */
120   _oggpack_write(&vb->opb,amp*32768,18);
121   {
122     codebook *b=vb->vd->fullbooks+info->books[0];
123     double last=0.;
124     for(j=0;j<look->m;){
125       double next=out[j+b->dim-1];
126       for(k=0;k<b->dim;k++,j++)out[j]-=last;
127       last=next;
128     }
129   }
130
131   for(k=0;k<info->stages;k++){
132     codebook *b=vb->vd->fullbooks+info->books[k];
133     for(j=0;j<look->m;j+=b->dim)
134       vorbis_book_encodev(b,out+j,&vb->opb);
135   }
136   
137   for(j=0;j<look->m;j++)
138     out[j]=work[j]-out[j];
139
140         
141
142   /* take the coefficients back to a spectral envelope curve */
143   vorbis_lsp_to_lpc(out,out,look->m); 
144   vorbis_lpc_to_curve(out,out,amp,&look->lpclook);
145
146   return(0);
147 }
148
149 static int inverse(vorbis_block *vb,vorbis_look_floor *i,double *out){
150   vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
151   vorbis_info_floor0 *info=look->vi;
152   int j,k;
153   
154   double amp=_oggpack_read(&vb->opb,18)/32768.;
155   memset(out,0,sizeof(double)*look->m);    
156   for(k=0;k<info->stages;k++){
157     codebook *b=vb->vd->fullbooks+info->books[k];
158     for(j=0;j<look->m;j+=b->dim)
159       vorbis_book_decodev(b,out+j,&vb->opb);
160   }
161   
162   {
163     codebook *b=vb->vd->fullbooks+info->books[0];
164     double last=0.;
165     for(j=0;j<look->m;){
166       for(k=0;k<b->dim;k++,j++)out[j]+=last;
167       last=out[j-1];
168     }
169   }
170
171   for(j=12;j<20;j++)
172     fprintf(stderr,"%0.3g, ",out[j]);
173   fprintf(stderr,"\n");
174   
175
176   /* take the coefficients back to a spectral envelope curve */
177   vorbis_lsp_to_lpc(out,out,look->m); 
178   vorbis_lpc_to_curve(out,out,amp,&look->lpclook);
179
180   return(0);
181 }
182
183 /* export hooks */
184 vorbis_func_floor floor0_exportbundle={
185   &pack,&unpack,&look,&free_info,&free_look,&forward,&inverse
186 };
187
188