1 /********************************************************************
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. *
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/ *
12 ********************************************************************
14 function: floor backend 0 implementation
15 last mod: $Id: floor0.c,v 1.24 2000/08/31 08:01:34 xiphmont Exp $
17 ********************************************************************/
22 #include "vorbis/codec.h"
27 #include "bookinternal.h"
28 #include "sharedbook.h"
42 vorbis_info_floor0 *vi;
48 /* infrastructure for finding fit */
49 static long _f0_fit(codebook *book,
56 double *lsp=workfit+cursor;
58 if(cursor)base=workfit[cursor-1];
59 norm=orig[cursor+dim-1]-base;
62 lsp[i]=(orig[i+cursor]-base);
63 best=_best(book,lsp,1);
65 memcpy(lsp,book->valuelist+best*dim,dim*sizeof(double));
71 /***********************************************/
73 static void free_info(vorbis_info_floor *i){
75 memset(i,0,sizeof(vorbis_info_floor0));
80 static void free_look(vorbis_look_floor *i){
81 vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
83 if(look->linearmap)free(look->linearmap);
84 if(look->lsp_look)free(look->lsp_look);
85 lpc_clear(&look->lpclook);
86 memset(look,0,sizeof(vorbis_look_floor0));
91 static void pack (vorbis_info_floor *i,oggpack_buffer *opb){
92 vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
94 _oggpack_write(opb,info->order,8);
95 _oggpack_write(opb,info->rate,16);
96 _oggpack_write(opb,info->barkmap,16);
97 _oggpack_write(opb,info->ampbits,6);
98 _oggpack_write(opb,info->ampdB,8);
99 _oggpack_write(opb,info->numbooks-1,4);
100 for(j=0;j<info->numbooks;j++)
101 _oggpack_write(opb,info->books[j],8);
104 static vorbis_info_floor *unpack (vorbis_info *vi,oggpack_buffer *opb){
106 vorbis_info_floor0 *info=malloc(sizeof(vorbis_info_floor0));
107 info->order=_oggpack_read(opb,8);
108 info->rate=_oggpack_read(opb,16);
109 info->barkmap=_oggpack_read(opb,16);
110 info->ampbits=_oggpack_read(opb,6);
111 info->ampdB=_oggpack_read(opb,8);
112 info->numbooks=_oggpack_read(opb,4)+1;
114 if(info->order<1)goto err_out;
115 if(info->rate<1)goto err_out;
116 if(info->barkmap<1)goto err_out;
117 if(info->numbooks<1)goto err_out;
119 for(j=0;j<info->numbooks;j++){
120 info->books[j]=_oggpack_read(opb,8);
121 if(info->books[j]<0 || info->books[j]>=vi->books)goto err_out;
129 /* initialize Bark scale and normalization lookups. We could do this
130 with static tables, but Vorbis allows a number of possible
131 combinations, so it's best to do it computationally.
133 The below is authoritative in terms of defining scale mapping.
134 Note that the scale depends on the sampling rate as well as the
135 linear block and mapping sizes */
137 static vorbis_look_floor *look (vorbis_dsp_state *vd,vorbis_info_mode *mi,
138 vorbis_info_floor *i){
141 vorbis_info *vi=vd->vi;
142 vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
143 vorbis_look_floor0 *look=calloc(1,sizeof(vorbis_look_floor0));
145 look->n=vi->blocksizes[mi->blockflag]/2;
146 look->ln=info->barkmap;
150 lpc_init(&look->lpclook,look->ln,look->m);
152 /* we choose a scaling constant so that:
153 floor(bark(rate/2-1)*C)=mapped-1
154 floor(bark(rate/2)*C)=mapped */
155 scale=look->ln/toBARK(info->rate/2.);
157 /* the mapping from a linear scale to a smaller bark scale is
158 straightforward. We do *not* make sure that the linear mapping
159 does not skip bark-scale bins; the decoder simply skips them and
160 the encoder may do what it wishes in filling them. They're
161 necessary in some mapping combinations to keep the scale spacing
163 look->linearmap=malloc(look->n*sizeof(int));
164 for(j=0;j<look->n;j++){
165 int val=floor( toBARK((info->rate/2.)/look->n*j)
166 *scale); /* bark numbers represent band edges */
167 if(val>look->ln)val=look->ln; /* guard against the approximation */
168 look->linearmap[j]=val;
171 look->lsp_look=malloc(look->ln*sizeof(double));
172 for(j=0;j<look->ln;j++)
173 look->lsp_look[j]=2*cos(M_PI/look->ln*j);
178 /* less efficient than the decode side (written for clarity). We're
179 not bottlenecked here anyway */
181 double _curve_to_lpc(double *curve,double *lpc,
182 vorbis_look_floor0 *l,long frameno){
183 /* map the input curve to a bark-scale curve for encoding */
186 double *work=alloca(sizeof(double)*mapped);
190 memset(work,0,sizeof(double)*mapped);
192 /* Only the decode side is behavior-specced; for now in the encoder,
193 we select the maximum value of each band as representative (this
194 helps make sure peaks don't go out of range. In error terms,
195 selecting min would make more sense, but the codebook is trained
196 numerically, so we don't actually lose. We'd still want to
197 use the original curve for error and noise estimation */
200 bark=l->linearmap[i];
201 if(work[bark]<curve[i])work[bark]=curve[i];
203 /* If the bark scale is climbing rapidly, some bins may end up
204 going unused. This isn't a waste actually; it keeps the
205 scale resolution even so that the LPC generator has an easy
206 time. However, if we leave the bins empty we lose energy.
207 So, fill 'em in. The decoder does not do anything with he
208 unused bins, so we can fill them anyway we like to end up
209 with a better spectral curve */
211 /* we'll always have a bin zero, so we don't need to guard init */
214 double del=(double)j/span;
215 work[j+last]=work[bark]*del+work[last]*(1.-del);
221 /* If we're over-ranged to avoid edge effects, fill in the end of spectrum gap */
222 for(i=bark+1;i<mapped;i++)
226 { /******************/
231 sprintf(buffer,"Fmask_%d.m",frameno);
232 of=fopen(buffer,"w");
233 for(i=0;i<mapped;i++)
234 fprintf(of,"%g\n",work[i]);
239 return vorbis_lpc_from_curve(work,lpc,&(l->lpclook));
242 /* generate the whole freq response curve of an LSP IIR filter */
244 void _lsp_to_curve(double *curve,double *lsp,double amp,
245 vorbis_look_floor0 *l,char *name,long frameno){
246 /* l->m+1 must be less than l->ln, but guard in case we get a bad stream */
247 double *lcurve=alloca(sizeof(double)*l->ln);
251 memset(curve,0,sizeof(double)*l->n);
254 vorbis_lsp_to_curve(lcurve,l->ln,lsp,l->m,amp,l->lsp_look);
256 for(i=0;i<l->n;i++)curve[i]=lcurve[l->linearmap[i]];
261 static int forward(vorbis_block *vb,vorbis_look_floor *i,
262 double *in,double *out){
264 vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
265 vorbis_info_floor0 *info=look->vi;
266 double *work=alloca((look->ln+look->n)*sizeof(double));
276 sprintf(buffer,"lsp0coeff_%d.vqd",vb->mode);
277 of=fopen(buffer,"a");
280 sprintf(buffer,"lsp0ent_%d.vqd",vb->mode);
281 ef=fopen(buffer,"a");
284 /* our floor comes in on a linear scale; go to a [-Inf...0] dB
285 scale. The curve has to be positive, so we offset it. */
287 for(j=0;j<look->n;j++)
288 work[j]=todB(in[j])+info->ampdB;
290 /* use 'out' as temp storage */
291 /* Convert our floor to a set of lpc coefficients */
292 amp=sqrt(_curve_to_lpc(work,out,look,seq));
294 /* amp is in the range (0. to ampdB]. Encode that range using
298 long maxval=(1L<<info->ampbits)-1;
300 long val=rint(amp/info->ampdB*maxval);
302 if(val<0)val=0; /* likely */
303 if(val>maxval)val=maxval; /* not bloody likely */
305 _oggpack_write(&vb->opb,val,info->ampbits);
307 amp=(float)val/maxval*info->ampdB;
314 /* the spec supports using one of a number of codebooks. Right
315 now, encode using this lib supports only one */
316 codebook *b=vb->vd->fullbooks+info->books[0];
317 _oggpack_write(&vb->opb,0,_ilog(info->numbooks));
319 /* LSP <-> LPC is orthogonal and LSP quantizes more stably */
320 vorbis_lpc_to_lsp(out,out,look->m);
326 for(j=0;j<look->m;j++){
327 fprintf(of,"%.12g, ",out[j]-last);
336 /* code the spectral envelope, and keep track of the actual
337 quantized values; we don't want creeping error as each block is
338 nailed to the last quantized value of the previous block. */
340 for(j=0;j<look->m;j+=b->dim){
341 int entry=_f0_fit(b,out,work,j);
342 bits+=vorbis_book_encode(b,entry,&vb->opb);
345 fprintf(ef,"%d,\n",entry);
353 for(j=0;j<look->m;j++){
358 _analysis_output("lsp",seq,out,look->m,0,0);
366 /* take the coefficients back to a spectral envelope curve */
367 _lsp_to_curve(out,work,amp,look,"Ffloor",seq++);
368 for(j=0;j<look->n;j++)out[j]= fromdB(out[j]-info->ampdB);
372 memset(out,0,sizeof(double)*look->n);
377 static int inverse(vorbis_block *vb,vorbis_look_floor *i,double *out){
378 vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
379 vorbis_info_floor0 *info=look->vi;
382 int ampraw=_oggpack_read(&vb->opb,info->ampbits);
383 if(ampraw>0){ /* also handles the -1 out of data case */
384 long maxval=(1<<info->ampbits)-1;
385 double amp=(float)ampraw/maxval*info->ampdB;
386 int booknum=_oggpack_read(&vb->opb,_ilog(info->numbooks));
389 codebook *b=vb->vd->fullbooks+info->books[booknum];
392 memset(out,0,sizeof(double)*look->m);
394 for(j=0;j<look->m;j+=b->dim)
395 if(vorbis_book_decodevs(b,out+j,&vb->opb,1,-1)==-1)goto eop;
397 for(k=0;k<b->dim;k++,j++)out[j]+=last;
401 /* take the coefficients back to a spectral envelope curve */
402 _lsp_to_curve(out,out,amp,look,"",0);
404 for(j=0;j<look->n;j++)out[j]=fromdB(out[j]-info->ampdB);
410 memset(out,0,sizeof(double)*look->n);
415 vorbis_func_floor floor0_exportbundle={
416 &pack,&unpack,&look,&free_info,&free_look,&forward,&inverse