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.20 2000/08/15 09:09:42 xiphmont Exp $
17 ********************************************************************/
22 #include "vorbis/codec.h"
27 #include "bookinternal.h"
28 #include "sharedbook.h"
42 vorbis_info_floor0 *vi;
47 /* infrastructure for finding fit */
48 static long _f0_fit(codebook *book,
53 double norm,base=0.,err=0.;
55 double *lsp=workfit+cursor;
57 /* gen a curve for fitting */
58 if(cursor)base=workfit[cursor-1];
59 norm=orig[cursor+dim-1]-base;
63 lsp[i]=(orig[i+cursor]-base);
64 best=_best(book,lsp,1);
66 memcpy(lsp,book->valuelist+best*dim,dim*sizeof(double));
72 /***********************************************/
74 static void free_info(vorbis_info_floor *i){
76 memset(i,0,sizeof(vorbis_info_floor0));
81 static void free_look(vorbis_look_floor *i){
82 vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
84 if(look->linearmap)free(look->linearmap);
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=malloc(sizeof(vorbis_look_floor0));
145 look->n=vi->blocksizes[mi->blockflag]/2;
146 look->ln=info->barkmap;
148 lpc_init(&look->lpclook,look->ln,look->m);
150 /* we choose a scaling constant so that:
151 floor(bark(rate/2-1)*C)=mapped-1
152 floor(bark(rate/2)*C)=mapped */
153 scale=look->ln/toBARK(info->rate/2.);
155 /* the mapping from a linear scale to a smaller bark scale is
156 straightforward. We do *not* make sure that the linear mapping
157 does not skip bark-scale bins; the decoder simply skips them and
158 the encoder may do what it wishes in filling them. They're
159 necessary in some mapping combinations to keep the scale spacing
161 look->linearmap=malloc(look->n*sizeof(int));
162 for(j=0;j<look->n;j++){
163 int val=floor( toBARK((info->rate/2.)/look->n*j)
164 *scale); /* bark numbers represent band edges */
165 if(val>look->ln)val=look->ln; /* guard against the approximation */
166 look->linearmap[j]=val;
172 /* less efficient than the decode side (written for clarity). We're
173 not bottlenecked here anyway */
175 double _curve_to_lpc(double *curve,double *lpc,
176 vorbis_look_floor0 *l,long frameno){
177 /* map the input curve to a bark-scale curve for encoding */
180 double *work=alloca(sizeof(double)*mapped);
184 memset(work,0,sizeof(double)*mapped);
186 /* Only the decode side is behavior-specced; for now in the encoder,
187 we select the maximum value of each band as representative (this
188 helps make sure peaks don't go out of range. In error terms,
189 selecting min would make more sense, but the codebook is trained
190 numerically, so we don't actually lose. We'd still want to
191 use the original curve for error and noise estimation */
194 bark=l->linearmap[i];
195 if(work[bark]<curve[i])work[bark]=curve[i];
197 /* If the bark scale is climbing rapidly, some bins may end up
198 going unused. This isn't a waste actually; it keeps the
199 scale resolution even so that the LPC generator has an easy
200 time. However, if we leave the bins empty we lose energy.
201 So, fill 'em in. The decoder does not do anything with he
202 unused bins, so we can fill them anyway we like to end up
203 with a better spectral curve */
205 /* we'll always have a bin zero, so we don't need to guard init */
208 double del=(double)j/span;
209 work[j+last]=work[bark]*del+work[last]*(1.-del);
215 /* If we're over-ranged to avoid edge effects, fill in the end of spectrum gap */
216 for(i=bark+1;i<mapped;i++)
220 { /******************/
225 sprintf(buffer,"Fmask_%d.m",frameno);
226 of=fopen(buffer,"w");
227 for(i=0;i<mapped;i++)
228 fprintf(of,"%g\n",work[i]);
233 return vorbis_lpc_from_curve(work,lpc,&(l->lpclook));
236 /* generate the whole freq response curve of an LPC IIR filter */
238 void _lpc_to_curve(double *curve,double *lpc,double amp,
239 vorbis_look_floor0 *l,char *name,long frameno){
240 /* l->m+1 must be less than l->ln, but guard in case we get a bad stream */
241 double *lcurve=alloca(sizeof(double)*max(l->ln*2,l->m*2+2));
245 memset(curve,0,sizeof(double)*l->n);
248 vorbis_lpc_to_curve(lcurve,lpc,amp,&(l->lpclook));
251 { /******************/
256 sprintf(buffer,"%s_%d.m",name,frameno);
257 of=fopen(buffer,"w");
259 fprintf(of,"%g\n",lcurve[i]);
264 for(i=0;i<l->n;i++)curve[i]=lcurve[l->linearmap[i]];
269 static int forward(vorbis_block *vb,vorbis_look_floor *i,
270 double *in,double *out){
272 vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
273 vorbis_info_floor0 *info=look->vi;
274 double *work=alloca((look->ln+look->n)*sizeof(double));
284 sprintf(buffer,"lsp0coeff_%d.vqd",vb->mode);
285 of=fopen(buffer,"a");
288 sprintf(buffer,"lsp0ent_%d.vqd",vb->mode);
289 ef=fopen(buffer,"a");
292 /* our floor comes in on a linear scale; go to a [-Inf...0] dB
293 scale. The curve has to be positive, so we offset it. */
295 for(j=0;j<look->n;j++){
296 double val=todB(in[j])+info->ampdB;
303 /* use 'out' as temp storage */
304 /* Convert our floor to a set of lpc coefficients */
305 amp=sqrt(_curve_to_lpc(work,out,look,seq));
307 /* amp is in the range (0. to ampdB]. Encode that range using
311 long maxval=(1L<<info->ampbits)-1;
313 long val=rint(amp/info->ampdB*maxval);
315 if(val<0)val=0; /* likely */
316 if(val>maxval)val=maxval; /* not bloody likely */
318 _oggpack_write(&vb->opb,val,info->ampbits);
320 amp=(float)val/maxval*info->ampdB;
327 /* the spec supports using one of a number of codebooks. Right
328 now, encode using this lib supports only one */
329 codebook *b=vb->vd->fullbooks+info->books[0];
330 _oggpack_write(&vb->opb,0,_ilog(info->numbooks));
332 /* LSP <-> LPC is orthogonal and LSP quantizes more stably */
333 vorbis_lpc_to_lsp(out,out,look->m);
336 if(vb->W==0){fprintf(stderr,"%d ",seq);}
337 vorbis_lsp_to_lpc(out,work,look->m);
338 _lpc_to_curve(work,work,amp,look,"Ffloor",seq);
339 for(j=0;j<look->n;j++)work[j]-=info->ampdB;
340 _analysis_output("rawfloor",seq,work,look->n,0,0);
343 for(j=0;j<look->m;j++){
348 _analysis_output("rawlsp",seq,work,look->m,0,0);
356 for(j=0;j<look->m;j++){
357 fprintf(of,"%.12g, ",out[j]-last);
366 /* code the spectral envelope, and keep track of the actual
367 quantized values; we don't want creeping error as each block is
368 nailed to the last quantized value of the previous block. */
370 for(j=0;j<look->m;j+=b->dim){
371 int entry=_f0_fit(b,out,work,j);
372 bits+=vorbis_book_encode(b,entry,&vb->opb);
375 fprintf(ef,"%d,\n",entry);
383 for(j=0;j<look->m;j++){
388 _analysis_output("lsp",seq,out,look->m,0,0);
396 /* take the coefficients back to a spectral envelope curve */
397 vorbis_lsp_to_lpc(work,out,look->m);
398 _lpc_to_curve(out,out,amp,look,"Ffloor",seq++);
399 for(j=0;j<look->n;j++)out[j]= fromdB(out[j]-info->ampdB);
403 memset(out,0,sizeof(double)*look->n);
408 static int inverse(vorbis_block *vb,vorbis_look_floor *i,double *out){
409 vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
410 vorbis_info_floor0 *info=look->vi;
413 int ampraw=_oggpack_read(&vb->opb,info->ampbits);
414 if(ampraw>0){ /* also handles the -1 out of data case */
415 long maxval=(1<<info->ampbits)-1;
416 double amp=(float)ampraw/maxval*info->ampdB;
417 int booknum=_oggpack_read(&vb->opb,_ilog(info->numbooks));
420 codebook *b=vb->vd->fullbooks+info->books[booknum];
423 memset(out,0,sizeof(double)*look->m);
425 for(j=0;j<look->m;j+=b->dim)
426 if(vorbis_book_decodevs(b,out+j,&vb->opb,1,-1)==-1)goto eop;
428 for(k=0;k<b->dim;k++,j++)out[j]+=last;
432 /* take the coefficients back to a spectral envelope curve */
433 vorbis_lsp_to_lpc(out,out,look->m);
434 _lpc_to_curve(out,out,amp,look,"",0);
436 for(j=0;j<look->n;j++)out[j]=fromdB(out[j]-info->ampdB);
442 memset(out,0,sizeof(double)*look->n);
447 vorbis_func_floor floor0_exportbundle={
448 &pack,&unpack,&look,&free_info,&free_look,&forward,&inverse