1 /********************************************************************
3 * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
4 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
5 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
6 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
8 * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001 *
9 * by the XIPHOPHORUS Company http://www.xiph.org/ *
11 ********************************************************************
13 function: floor backend 0 implementation
14 last mod: $Id: floor0.c,v 1.45 2001/08/13 01:36:56 xiphmont Exp $
16 ********************************************************************/
22 #include "vorbis/codec.h"
23 #include "codec_internal.h"
41 vorbis_info_floor0 *vi;
49 /* infrastructure for finding fit */
50 static long _f0_fit(codebook *book,
57 float *lsp=workfit+cursor;
59 if(cursor)base=workfit[cursor-1];
60 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(float));
72 /***********************************************/
74 static vorbis_info_floor *floor0_copy_info (vorbis_info_floor *i){
75 vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
76 vorbis_info_floor0 *ret=_ogg_malloc(sizeof(vorbis_info_floor0));
77 memcpy(ret,info,sizeof(vorbis_info_floor0));
81 static void floor0_free_info(vorbis_info_floor *i){
83 memset(i,0,sizeof(vorbis_info_floor0));
88 static void floor0_free_look(vorbis_look_floor *i){
89 vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
92 /*fprintf(stderr,"floor 0 bit usage %f\n",
93 (float)look->bits/look->frames);*/
95 if(look->linearmap)_ogg_free(look->linearmap);
96 if(look->lsp_look)_ogg_free(look->lsp_look);
97 lpc_clear(&look->lpclook);
98 memset(look,0,sizeof(vorbis_look_floor0));
103 static void floor0_pack (vorbis_info_floor *i,oggpack_buffer *opb){
104 vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
106 oggpack_write(opb,info->order,8);
107 oggpack_write(opb,info->rate,16);
108 oggpack_write(opb,info->barkmap,16);
109 oggpack_write(opb,info->ampbits,6);
110 oggpack_write(opb,info->ampdB,8);
111 oggpack_write(opb,info->numbooks-1,4);
112 for(j=0;j<info->numbooks;j++)
113 oggpack_write(opb,info->books[j],8);
116 static vorbis_info_floor *floor0_unpack (vorbis_info *vi,oggpack_buffer *opb){
117 codec_setup_info *ci=vi->codec_setup;
120 vorbis_info_floor0 *info=_ogg_malloc(sizeof(vorbis_info_floor0));
121 info->order=oggpack_read(opb,8);
122 info->rate=oggpack_read(opb,16);
123 info->barkmap=oggpack_read(opb,16);
124 info->ampbits=oggpack_read(opb,6);
125 info->ampdB=oggpack_read(opb,8);
126 info->numbooks=oggpack_read(opb,4)+1;
128 if(info->order<1)goto err_out;
129 if(info->rate<1)goto err_out;
130 if(info->barkmap<1)goto err_out;
131 if(info->numbooks<1)goto err_out;
133 for(j=0;j<info->numbooks;j++){
134 info->books[j]=oggpack_read(opb,8);
135 if(info->books[j]<0 || info->books[j]>=ci->books)goto err_out;
140 floor0_free_info(info);
144 /* initialize Bark scale and normalization lookups. We could do this
145 with static tables, but Vorbis allows a number of possible
146 combinations, so it's best to do it computationally.
148 The below is authoritative in terms of defining scale mapping.
149 Note that the scale depends on the sampling rate as well as the
150 linear block and mapping sizes */
152 static vorbis_look_floor *floor0_look (vorbis_dsp_state *vd,vorbis_info_mode *mi,
153 vorbis_info_floor *i){
156 vorbis_info *vi=vd->vi;
157 codec_setup_info *ci=vi->codec_setup;
158 vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
159 vorbis_look_floor0 *look=_ogg_calloc(1,sizeof(vorbis_look_floor0));
161 look->n=ci->blocksizes[mi->blockflag]/2;
162 look->ln=info->barkmap;
166 lpc_init(&look->lpclook,look->ln,look->m);
168 /* we choose a scaling constant so that:
169 floor(bark(rate/2-1)*C)=mapped-1
170 floor(bark(rate/2)*C)=mapped */
171 scale=look->ln/toBARK(info->rate/2.f);
173 /* the mapping from a linear scale to a smaller bark scale is
174 straightforward. We do *not* make sure that the linear mapping
175 does not skip bark-scale bins; the decoder simply skips them and
176 the encoder may do what it wishes in filling them. They're
177 necessary in some mapping combinations to keep the scale spacing
179 look->linearmap=_ogg_malloc((look->n+1)*sizeof(int));
180 for(j=0;j<look->n;j++){
181 int val=floor( toBARK((info->rate/2.f)/look->n*j)
182 *scale); /* bark numbers represent band edges */
183 if(val>=look->ln)val=look->ln; /* guard against the approximation */
184 look->linearmap[j]=val;
186 look->linearmap[j]=-1;
188 look->lsp_look=_ogg_malloc(look->ln*sizeof(float));
189 for(j=0;j<look->ln;j++)
190 look->lsp_look[j]=2*cos(M_PI/look->ln*j);
195 /* less efficient than the decode side (written for clarity). We're
196 not bottlenecked here anyway */
198 float _curve_to_lpc(float *curve,float *lpc,
199 vorbis_look_floor0 *l){
200 /* map the input curve to a bark-scale curve for encoding */
203 float *work=alloca(sizeof(float)*mapped);
208 memset(work,0,sizeof(float)*mapped);
210 /* Only the decode side is behavior-specced; for now in the encoder,
211 we select the maximum value of each band as representative (this
212 helps make sure peaks don't go out of range. In error terms,
213 selecting min would make more sense, but the codebook is trained
214 numerically, so we don't actually lose. We'd still want to
215 use the original curve for error and noise estimation */
218 bark=l->linearmap[i];
219 if(work[bark]<curve[i])work[bark]=curve[i];
221 /* If the bark scale is climbing rapidly, some bins may end up
222 going unused. This isn't a waste actually; it keeps the
223 scale resolution even so that the LPC generator has an easy
224 time. However, if we leave the bins empty we lose energy.
225 So, fill 'em in. The decoder does not do anything with he
226 unused bins, so we can fill them anyway we like to end up
227 with a better spectral curve */
229 /* we'll always have a bin zero, so we don't need to guard init */
232 float del=(float)j/span;
233 work[j+last]=work[bark]*del+work[last]*(1.f-del);
239 /* If we're over-ranged to avoid edge effects, fill in the end of spectrum gap */
240 for(i=bark+1;i<mapped;i++)
244 /**********************/
249 _analysis_output("barkfloor",seq,work,bark,0,0);
250 _analysis_output("barkcurve",seq++,curve,l->n,1,0);
255 /**********************/
257 return vorbis_lpc_from_curve(work,lpc,&(l->lpclook));
260 static int floor0_forward(vorbis_block *vb,vorbis_look_floor *in,
261 float *mdct, const float *logmdct, /* in */
262 const float *logmask, const float *logmax, /* in */
263 float *codedflr){ /* out */
265 vorbis_look_floor0 *look=(vorbis_look_floor0 *)in;
266 vorbis_info_floor0 *info=look->vi;
278 sprintf(buffer,"lsp0coeff_%d.vqd",vb->mode);
279 of=fopen(buffer,"a");
286 /* our floor comes in on a [-Inf...0] dB scale. The curve has to be
287 positive, so we offset it. */
289 for(j=0;j<look->n;j++)
290 codedflr[j]=logmask[j]+info->ampdB;
292 /* use 'out' as temp storage */
293 /* Convert our floor to a set of lpc coefficients */
294 amp=sqrt(_curve_to_lpc(codedflr,codedflr,look));
296 /* amp is in the range (0. to ampdB]. Encode that range using
300 long maxval=(1L<<info->ampbits)-1;
302 val=rint(amp/info->ampdB*maxval);
304 if(val<0)val=0; /* likely */
305 if(val>maxval)val=maxval; /* not bloody likely */
308 amp=(float)val/maxval*info->ampdB;
314 /* LSP <-> LPC is orthogonal and LSP quantizes more stably */
315 _analysis_output("lpc",seq-1,codedflr,look->m,0,0);
316 if(vorbis_lpc_to_lsp(codedflr,codedflr,look->m))
321 oggpack_write(&vb->opb,val,info->ampbits);
322 look->bits+=info->ampbits+1;
326 float *lspwork=alloca(look->m*sizeof(float));
328 /* the spec supports using one of a number of codebooks. Right
329 now, encode using this lib supports only one */
330 backend_lookup_state *be=vb->vd->backend_state;
334 _analysis_output("lsp",seq-1,codedflr,look->m,0,0);
336 /* which codebook to use? We do it only by range right now. */
337 if(info->numbooks>1){
339 for(j=0;j<look->m;j++){
340 float val=codedflr[j]-last;
341 if(val<info->lessthan || val>info->greaterthan)break;
351 b=be->fullbooks+info->books[booknum];
352 oggpack_write(&vb->opb,booknum,_ilog(info->numbooks));
353 look->bits+=_ilog(info->numbooks);
358 for(j=0;j<look->m;j++){
359 fprintf(of,"%.12g, ",codedflr[j]-last);
366 sprintf(buffer,"lsp0ent_m%d_b%d.vqd",vb->mode,booknum);
367 ef=fopen(buffer,"a");
371 /* code the spectral envelope, and keep track of the actual
372 quantized values; we don't want creeping error as each block is
373 nailed to the last quantized value of the previous block. */
375 for(j=0;j<look->m;j+=b->dim){
376 int entry=_f0_fit(b,codedflr,lspwork,j);
377 look->bits+=vorbis_book_encode(b,entry,&vb->opb);
380 fprintf(ef,"%d,\n",entry);
389 _analysis_output("lsp2",seq-1,lspwork,look->m,0,0);
391 /* take the coefficients back to a spectral envelope curve */
392 for(j=0;j<look->n;j++)
394 vorbis_lsp_to_curve(codedflr,look->linearmap,look->n,look->ln,
395 lspwork,look->m,amp,info->ampdB);
397 _analysis_output("barklsp",seq-1,codedflr,look->n,1,1);
398 _analysis_output("lsp3",seq-1,codedflr,look->n,0,1);
407 memset(codedflr,0,sizeof(float)*look->n);
408 memset(mdct,0,sizeof(float)*look->n);
412 static void *floor0_inverse1(vorbis_block *vb,vorbis_look_floor *i){
413 vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
414 vorbis_info_floor0 *info=look->vi;
417 int ampraw=oggpack_read(&vb->opb,info->ampbits);
418 if(ampraw>0){ /* also handles the -1 out of data case */
419 long maxval=(1<<info->ampbits)-1;
420 float amp=(float)ampraw/maxval*info->ampdB;
421 int booknum=oggpack_read(&vb->opb,_ilog(info->numbooks));
423 if(booknum!=-1 && booknum<info->numbooks){ /* be paranoid */
424 backend_lookup_state *be=vb->vd->backend_state;
425 codebook *b=be->fullbooks+info->books[booknum];
427 float *lsp=_vorbis_block_alloc(vb,sizeof(float)*(look->m+1));
429 for(j=0;j<look->m;j+=b->dim)
430 if(vorbis_book_decodev_set(b,lsp+j,&vb->opb,b->dim)==-1)goto eop;
432 for(k=0;k<b->dim;k++,j++)lsp[j]+=last;
444 static int floor0_inverse2(vorbis_block *vb,vorbis_look_floor *i,
445 void *memo,float *out){
446 vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
447 vorbis_info_floor0 *info=look->vi;
450 float *lsp=(float *)memo;
451 float amp=lsp[look->m];
453 /* take the coefficients back to a spectral envelope curve */
454 vorbis_lsp_to_curve(out,look->linearmap,look->n,look->ln,
455 lsp,look->m,amp,info->ampdB);
458 memset(out,0,sizeof(float)*look->n);
463 vorbis_func_floor floor0_exportbundle={
464 &floor0_pack,&floor0_unpack,&floor0_look,&floor0_copy_info,&floor0_free_info,
465 &floor0_free_look,&floor0_forward,&floor0_inverse1,&floor0_inverse2