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.18 2000/07/12 09:36:17 xiphmont Exp $
17 ********************************************************************/
22 #include "vorbis/codec.h"
27 #include "bookinternal.h"
28 #include "sharedbook.h"
36 /* error relationship from coefficient->curve is nonlinear, so fit
37 using curve lookups, not the coefficients */
53 vorbis_info_floor0 *vi;
56 LSP_fit_lookup *encodefit;
59 /* infrastructure for setting up, finding and encoding fit */
60 static void _f0_fit_init(LSP_fit_lookup *f,codebook *b){
67 memset(f,0,sizeof(LSP_fit_lookup));
69 /* count actual codeword usage in case the book is sparse */
70 for(i=0;i<b->entries;i++)
71 if(b->c->lengthlist[i]>0){
72 if(b->valuelist[(i+1)*b->dim-1]>max)
73 max=b->valuelist[(i+1)*b->dim-1];
79 f->entrymap=malloc(usage*sizeof(long));
80 f->fits=malloc(usage*sizeof(double *));
83 lpc_init(&f->lpclook,f->fitsize,dim-1);
86 work=alloca(f->fitsize*2*sizeof(double));
87 lsp=alloca(dim*sizeof(double));
88 for(i=0;i<b->entries;i++)
89 if(b->c->lengthlist[i]>0){
90 double *orig=b->valuelist+i*b->dim;
91 double norm=orig[b->dim-1];
92 f->fits[usage]=malloc(f->fitsize*sizeof(double));
95 lsp[j]=orig[j]/norm*M_PI;
96 vorbis_lsp_to_lpc(lsp,lsp,dim-1);
97 vorbis_lpc_to_curve(work,lsp,norm*norm,&f->lpclook);
98 memcpy(f->fits[usage],work,f->fitsize*sizeof(double));
100 f->entrymap[usage]=i;
106 static void _f0_fit_clear(LSP_fit_lookup *f){
109 for(i=0;i<f->usage;i++)
113 lpc_clear(&f->lpclook);
114 memset(f,0,sizeof(LSP_fit_lookup));
118 double _curve_error1(double *curve1,double *curve2,long n){
122 double val=curve1[i]-curve2[i];
128 double _curve_error2(double *curve1,double *curve2,long n,double max){
132 double val=curve1[i]-curve2[i];
134 if(acc>max)return(acc);
139 static long _f0_fit(LSP_fit_lookup *f,
145 double norm,base=0.,err=0.;
147 double *lsp=alloca(dim*sizeof(double));
148 double *ref=alloca(f->fitsize*2*sizeof(double));
150 if(f->usage<=0)return(-1);
152 /* gen a curve for fitting */
153 if(cursor)base=workfit[cursor-1];
154 norm=orig[cursor+dim-1]-base;
156 lsp[i]=(orig[i+cursor]-base)/norm*M_PI;
157 vorbis_lsp_to_lpc(lsp,lsp,dim-1);
158 vorbis_lpc_to_curve(ref,lsp,norm*norm,&f->lpclook);
160 err=_curve_error1(f->fits[0],ref,f->fitsize);
161 for(i=1;i<f->usage;i++){
162 double this=_curve_error2(f->fits[i],ref,f->fitsize,err);
169 /* choose the best fit from the tests and set workfit to it */
170 best=f->entrymap[best];
171 memcpy(workfit+cursor,book->valuelist+best*dim,dim*sizeof(double));
173 workfit[i+cursor]+=base;
177 /***********************************************/
179 static void free_info(vorbis_info_floor *i){
181 memset(i,0,sizeof(vorbis_info_floor0));
186 static void free_look(vorbis_look_floor *i){
187 vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
190 for(j=0;j<look->vi->numbooks;j++)
191 _f0_fit_clear(look->encodefit+j);
192 free(look->encodefit);
193 if(look->linearmap)free(look->linearmap);
194 lpc_clear(&look->lpclook);
195 memset(look,0,sizeof(vorbis_look_floor0));
200 static void pack (vorbis_info_floor *i,oggpack_buffer *opb){
201 vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
203 _oggpack_write(opb,info->order,8);
204 _oggpack_write(opb,info->rate,16);
205 _oggpack_write(opb,info->barkmap,16);
206 _oggpack_write(opb,info->ampbits,6);
207 _oggpack_write(opb,info->ampdB,8);
208 _oggpack_write(opb,info->numbooks-1,4);
209 for(j=0;j<info->numbooks;j++)
210 _oggpack_write(opb,info->books[j],8);
213 static vorbis_info_floor *unpack (vorbis_info *vi,oggpack_buffer *opb){
215 vorbis_info_floor0 *info=malloc(sizeof(vorbis_info_floor0));
216 info->order=_oggpack_read(opb,8);
217 info->rate=_oggpack_read(opb,16);
218 info->barkmap=_oggpack_read(opb,16);
219 info->ampbits=_oggpack_read(opb,6);
220 info->ampdB=_oggpack_read(opb,8);
221 info->numbooks=_oggpack_read(opb,4)+1;
223 if(info->order<1)goto err_out;
224 if(info->rate<1)goto err_out;
225 if(info->barkmap<1)goto err_out;
226 if(info->numbooks<1)goto err_out;
228 for(j=0;j<info->numbooks;j++){
229 info->books[j]=_oggpack_read(opb,8);
230 if(info->books[j]<0 || info->books[j]>=vi->books)goto err_out;
238 /* initialize Bark scale and normalization lookups. We could do this
239 with static tables, but Vorbis allows a number of possible
240 combinations, so it's best to do it computationally.
242 The below is authoritative in terms of defining scale mapping.
243 Note that the scale depends on the sampling rate as well as the
244 linear block and mapping sizes */
246 static vorbis_look_floor *look (vorbis_dsp_state *vd,vorbis_info_mode *mi,
247 vorbis_info_floor *i){
250 vorbis_info *vi=vd->vi;
251 vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
252 vorbis_look_floor0 *look=malloc(sizeof(vorbis_look_floor0));
254 look->n=vi->blocksizes[mi->blockflag]/2;
255 look->ln=info->barkmap;
257 lpc_init(&look->lpclook,look->ln,look->m);
259 /* we choose a scaling constant so that:
260 floor(bark(rate/2-1)*C)=mapped-1
261 floor(bark(rate/2)*C)=mapped */
262 scale=look->ln/toBARK(info->rate/2.);
264 /* the mapping from a linear scale to a smaller bark scale is
265 straightforward. We do *not* make sure that the linear mapping
266 does not skip bark-scale bins; the decoder simply skips them and
267 the encoder may do what it wishes in filling them. They're
268 necessary in some mapping combinations to keep the scale spacing
270 look->linearmap=malloc(look->n*sizeof(int));
271 for(j=0;j<look->n;j++){
272 int val=floor( toBARK((info->rate/2.)/look->n*j)
273 *scale); /* bark numbers represent band edges */
274 if(val>look->ln)val=look->ln; /* guard against the approximation */
275 look->linearmap[j]=val;
279 look->encodefit=calloc(info->numbooks,sizeof(LSP_fit_lookup));
280 for(j=0;j<info->numbooks;j++){
281 codebook *b=vd->fullbooks+info->books[j];
282 _f0_fit_init(look->encodefit+j,b);
289 /* less efficient than the decode side (written for clarity). We're
290 not bottlenecked here anyway */
292 double _curve_to_lpc(double *curve,double *lpc,
293 vorbis_look_floor0 *l,long frameno){
294 /* map the input curve to a bark-scale curve for encoding */
297 double *work=alloca(sizeof(double)*mapped);
301 memset(work,0,sizeof(double)*mapped);
303 /* Only the decode side is behavior-specced; for now in the encoder,
304 we select the maximum value of each band as representative (this
305 helps make sure peaks don't go out of range. In error terms,
306 selecting min would make more sense, but the codebook is trained
307 numerically, so we don't actually lose. We'd still want to
308 use the original curve for error and noise estimation */
311 bark=l->linearmap[i];
312 if(work[bark]<curve[i])work[bark]=curve[i];
314 /* If the bark scale is climbing rapidly, some bins may end up
315 going unused. This isn't a waste actually; it keeps the
316 scale resolution even so that the LPC generator has an easy
317 time. However, if we leave the bins empty we lose energy.
318 So, fill 'em in. The decoder does not do anything with he
319 unused bins, so we can fill them anyway we like to end up
320 with a better spectral curve */
322 /* we'll always have a bin zero, so we don't need to guard init */
325 double del=(double)j/span;
326 work[j+last]=work[bark]*del+work[last]*(1.-del);
332 /* If we're over-ranged to avoid edge effects, fill in the end of spectrum gap */
333 for(i=bark+1;i<mapped;i++)
337 { /******************/
342 sprintf(buffer,"Fmask_%d.m",frameno);
343 of=fopen(buffer,"w");
344 for(i=0;i<mapped;i++)
345 fprintf(of,"%g\n",work[i]);
350 return vorbis_lpc_from_curve(work,lpc,&(l->lpclook));
353 /* generate the whole freq response curve of an LPC IIR filter */
355 void _lpc_to_curve(double *curve,double *lpc,double amp,
356 vorbis_look_floor0 *l,char *name,long frameno){
357 /* l->m+1 must be less than l->ln, but guard in case we get a bad stream */
358 double *lcurve=alloca(sizeof(double)*max(l->ln*2,l->m*2+2));
362 memset(curve,0,sizeof(double)*l->n);
365 vorbis_lpc_to_curve(lcurve,lpc,amp,&(l->lpclook));
368 { /******************/
373 sprintf(buffer,"%s_%d.m",name,frameno);
374 of=fopen(buffer,"w");
376 fprintf(of,"%g\n",lcurve[i]);
381 for(i=0;i<l->n;i++)curve[i]=lcurve[l->linearmap[i]];
386 static int forward(vorbis_block *vb,vorbis_look_floor *i,
387 double *in,double *out){
389 vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
390 vorbis_info_floor0 *info=look->vi;
391 double *work=alloca((look->ln+look->n)*sizeof(double));
401 sprintf(buffer,"lsp0coeff_%d.vqd",vb->mode);
402 of=fopen(buffer,"a");
405 sprintf(buffer,"lsp0ent_%d.vqd",vb->mode);
406 ef=fopen(buffer,"a");
409 /* our floor comes in on a linear scale; go to a [-Inf...0] dB
410 scale. The curve has to be positive, so we offset it. */
412 for(j=0;j<look->n;j++){
413 double val=todB(in[j])+info->ampdB;
420 /* use 'out' as temp storage */
421 /* Convert our floor to a set of lpc coefficients */
422 amp=sqrt(_curve_to_lpc(work,out,look,seq));
424 /* amp is in the range (0. to ampdB]. Encode that range using
428 long maxval=(1L<<info->ampbits)-1;
430 long val=rint(amp/info->ampdB*maxval);
432 if(val<0)val=0; /* likely */
433 if(val>maxval)val=maxval; /* not bloody likely */
435 _oggpack_write(&vb->opb,val,info->ampbits);
437 amp=(float)val/maxval*info->ampdB;
444 /* the spec supports using one of a number of codebooks. Right
445 now, encode using this lib supports only one */
446 codebook *b=vb->vd->fullbooks+info->books[0];
447 LSP_fit_lookup *f=look->encodefit;
448 _oggpack_write(&vb->opb,0,_ilog(info->numbooks));
450 /* LSP <-> LPC is orthogonal and LSP quantizes more stably */
451 vorbis_lpc_to_lsp(out,out,look->m);
454 if(vb->W==0){fprintf(stderr,"%d ",seq);}
455 vorbis_lsp_to_lpc(out,work,look->m);
456 _lpc_to_curve(work,work,amp,look,"Ffloor",seq);
457 for(j=0;j<look->n;j++)work[j]-=info->ampdB;
458 _analysis_output("rawfloor",seq,work,look->n,0,0);
461 for(j=0;j<look->m;j++){
466 _analysis_output("rawlsp",seq,work,look->m,0,0);
472 for(j=0;j<look->m;j++)
473 fprintf(of,"%.12g, ",out[j]);
479 /* code the spectral envelope, and keep track of the actual
480 quantized values; we don't want creeping error as each block is
481 nailed to the last quantized value of the previous block. */
483 for(j=0;j<look->m;j+=b->dim){
484 int entry=_f0_fit(f,b,out,work,j);
485 bits+=vorbis_book_encode(b,entry,&vb->opb);
487 if(entry==2921)fprintf(stderr,"\n*************found\n");
491 fprintf(ef,"%d,\n",entry);
499 for(j=0;j<look->m;j++){
504 _analysis_output("lsp",seq,out,look->m,0,0);
512 /* take the coefficients back to a spectral envelope curve */
513 vorbis_lsp_to_lpc(work,out,look->m);
514 _lpc_to_curve(out,out,amp,look,"Ffloor",seq++);
515 for(j=0;j<look->n;j++)out[j]= fromdB(out[j]-info->ampdB);
519 memset(out,0,sizeof(double)*look->n);
524 static int inverse(vorbis_block *vb,vorbis_look_floor *i,double *out){
525 vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
526 vorbis_info_floor0 *info=look->vi;
529 int ampraw=_oggpack_read(&vb->opb,info->ampbits);
530 if(ampraw>0){ /* also handles the -1 out of data case */
531 long maxval=(1<<info->ampbits)-1;
532 double amp=(float)ampraw/maxval*info->ampdB;
533 int booknum=_oggpack_read(&vb->opb,_ilog(info->numbooks));
536 codebook *b=vb->vd->fullbooks+info->books[booknum];
539 memset(out,0,sizeof(double)*look->m);
541 for(j=0;j<look->m;j+=b->dim)
542 if(vorbis_book_decodevs(b,out+j,&vb->opb,1,-1)==-1)goto eop;
544 for(k=0;k<b->dim;k++,j++)out[j]+=last;
548 /* take the coefficients back to a spectral envelope curve */
549 vorbis_lsp_to_lpc(out,out,look->m);
550 _lpc_to_curve(out,out,amp,look,"",0);
552 for(j=0;j<look->n;j++)out[j]=fromdB(out[j]-info->ampdB);
558 memset(out,0,sizeof(double)*look->n);
563 vorbis_func_floor floor0_exportbundle={
564 &pack,&unpack,&look,&free_info,&free_look,&forward,&inverse