1 /********************************************************************
3 * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
4 * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY *
5 * THE GNU LESSER/LIBRARY PUBLIC LICENSE, WHICH IS INCLUDED WITH *
6 * THIS SOURCE. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
8 * THE OggVorbis 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.32 2000/12/12 04:18:54 xiphmont Exp $
17 ********************************************************************/
23 #include "vorbis/codec.h"
24 #include "codec_internal.h"
42 vorbis_info_floor0 *vi;
48 /* infrastructure for finding fit */
49 static long _f0_fit(codebook *book,
56 float *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(float));
71 /***********************************************/
73 static vorbis_info_floor *floor0_copy_info (vorbis_info_floor *i){
74 vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
75 vorbis_info_floor0 *ret=_ogg_malloc(sizeof(vorbis_info_floor0));
76 memcpy(ret,info,sizeof(vorbis_info_floor0));
80 static void floor0_free_info(vorbis_info_floor *i){
82 memset(i,0,sizeof(vorbis_info_floor0));
87 static void floor0_free_look(vorbis_look_floor *i){
88 vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
90 if(look->linearmap)_ogg_free(look->linearmap);
91 if(look->lsp_look)_ogg_free(look->lsp_look);
92 lpc_clear(&look->lpclook);
93 memset(look,0,sizeof(vorbis_look_floor0));
98 static void floor0_pack (vorbis_info_floor *i,oggpack_buffer *opb){
99 vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
101 oggpack_write(opb,info->order,8);
102 oggpack_write(opb,info->rate,16);
103 oggpack_write(opb,info->barkmap,16);
104 oggpack_write(opb,info->ampbits,6);
105 oggpack_write(opb,info->ampdB,8);
106 oggpack_write(opb,info->numbooks-1,4);
107 for(j=0;j<info->numbooks;j++)
108 oggpack_write(opb,info->books[j],8);
111 static vorbis_info_floor *floor0_unpack (vorbis_info *vi,oggpack_buffer *opb){
112 codec_setup_info *ci=vi->codec_setup;
115 vorbis_info_floor0 *info=_ogg_malloc(sizeof(vorbis_info_floor0));
116 info->order=oggpack_read(opb,8);
117 info->rate=oggpack_read(opb,16);
118 info->barkmap=oggpack_read(opb,16);
119 info->ampbits=oggpack_read(opb,6);
120 info->ampdB=oggpack_read(opb,8);
121 info->numbooks=oggpack_read(opb,4)+1;
123 if(info->order<1)goto err_out;
124 if(info->rate<1)goto err_out;
125 if(info->barkmap<1)goto err_out;
126 if(info->numbooks<1)goto err_out;
128 for(j=0;j<info->numbooks;j++){
129 info->books[j]=oggpack_read(opb,8);
130 if(info->books[j]<0 || info->books[j]>=ci->books)goto err_out;
135 floor0_free_info(info);
139 /* initialize Bark scale and normalization lookups. We could do this
140 with static tables, but Vorbis allows a number of possible
141 combinations, so it's best to do it computationally.
143 The below is authoritative in terms of defining scale mapping.
144 Note that the scale depends on the sampling rate as well as the
145 linear block and mapping sizes */
147 static vorbis_look_floor *floor0_look (vorbis_dsp_state *vd,vorbis_info_mode *mi,
148 vorbis_info_floor *i){
151 vorbis_info *vi=vd->vi;
152 codec_setup_info *ci=vi->codec_setup;
153 vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
154 vorbis_look_floor0 *look=_ogg_calloc(1,sizeof(vorbis_look_floor0));
156 look->n=ci->blocksizes[mi->blockflag]/2;
157 look->ln=info->barkmap;
161 lpc_init(&look->lpclook,look->ln,look->m);
163 /* we choose a scaling constant so that:
164 floor(bark(rate/2-1)*C)=mapped-1
165 floor(bark(rate/2)*C)=mapped */
166 scale=look->ln/toBARK(info->rate/2.);
168 /* the mapping from a linear scale to a smaller bark scale is
169 straightforward. We do *not* make sure that the linear mapping
170 does not skip bark-scale bins; the decoder simply skips them and
171 the encoder may do what it wishes in filling them. They're
172 necessary in some mapping combinations to keep the scale spacing
174 look->linearmap=_ogg_malloc((look->n+1)*sizeof(int));
175 for(j=0;j<look->n;j++){
176 int val=floor( toBARK((info->rate/2.)/look->n*j)
177 *scale); /* bark numbers represent band edges */
178 if(val>=look->ln)val=look->ln; /* guard against the approximation */
179 look->linearmap[j]=val;
181 look->linearmap[j]=-1;
183 look->lsp_look=_ogg_malloc(look->ln*sizeof(float));
184 for(j=0;j<look->ln;j++)
185 look->lsp_look[j]=2*cos(M_PI/look->ln*j);
190 /* less efficient than the decode side (written for clarity). We're
191 not bottlenecked here anyway */
193 float _curve_to_lpc(float *curve,float *lpc,
194 vorbis_look_floor0 *l){
195 /* map the input curve to a bark-scale curve for encoding */
198 float *work=alloca(sizeof(float)*mapped);
202 memset(work,0,sizeof(float)*mapped);
204 /* Only the decode side is behavior-specced; for now in the encoder,
205 we select the maximum value of each band as representative (this
206 helps make sure peaks don't go out of range. In error terms,
207 selecting min would make more sense, but the codebook is trained
208 numerically, so we don't actually lose. We'd still want to
209 use the original curve for error and noise estimation */
212 bark=l->linearmap[i];
213 if(work[bark]<curve[i])work[bark]=curve[i];
215 /* If the bark scale is climbing rapidly, some bins may end up
216 going unused. This isn't a waste actually; it keeps the
217 scale resolution even so that the LPC generator has an easy
218 time. However, if we leave the bins empty we lose energy.
219 So, fill 'em in. The decoder does not do anything with he
220 unused bins, so we can fill them anyway we like to end up
221 with a better spectral curve */
223 /* we'll always have a bin zero, so we don't need to guard init */
226 float del=(float)j/span;
227 work[j+last]=work[bark]*del+work[last]*(1.-del);
233 /* If we're over-ranged to avoid edge effects, fill in the end of spectrum gap */
234 for(i=bark+1;i<mapped;i++)
237 return vorbis_lpc_from_curve(work,lpc,&(l->lpclook));
240 /* generate the whole freq response curve of an LSP IIR filter */
241 static int floor0_forward(vorbis_block *vb,vorbis_look_floor *i,
242 float *in,float *out,vorbis_bitbuffer *vbb){
244 vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
245 vorbis_info_floor0 *info=look->vi;
246 float *work=alloca((look->ln+look->n)*sizeof(float));
258 sprintf(buffer,"lsp0coeff_%d.vqd",vb->mode);
259 of=fopen(buffer,"a");
262 sprintf(buffer,"lsp0ent_%d.vqd",vb->mode);
263 ef=fopen(buffer,"a");
266 /* our floor comes in on a linear scale; go to a [-Inf...0] dB
267 scale. The curve has to be positive, so we offset it. */
269 for(j=0;j<look->n;j++)
270 work[j]=todB(in[j])+info->ampdB;
272 /* use 'out' as temp storage */
273 /* Convert our floor to a set of lpc coefficients */
274 amp=sqrt(_curve_to_lpc(work,out,look));
276 /* amp is in the range (0. to ampdB]. Encode that range using
280 long maxval=(1L<<info->ampbits)-1;
282 val=rint(amp/info->ampdB*maxval);
284 if(val<0)val=0; /* likely */
285 if(val>maxval)val=maxval; /* not bloody likely */
287 /*oggpack_write(&vb->opb,val,info->ampbits);*/
289 amp=(float)val/maxval*info->ampdB;
296 /* the spec supports using one of a number of codebooks. Right
297 now, encode using this lib supports only one */
298 backend_lookup_state *be=vb->vd->backend_state;
299 codebook *b=be->fullbooks+info->books[0];
300 bitbuf_write(vbb,0,_ilog(info->numbooks));
302 /* LSP <-> LPC is orthogonal and LSP quantizes more stably */
303 vorbis_lpc_to_lsp(out,out,look->m);
307 float *lspwork=alloca(look->m*sizeof(float));
308 memcpy(lspwork,out,look->m*sizeof(float));
309 vorbis_lsp_to_curve(work,look->linearmap,look->n,look->ln,
310 lspwork,look->m,amp,info->ampdB);
311 _analysis_output("prefit",seq,work,look->n,0,1);
322 for(j=0;j<look->m;j++){
323 fprintf(of,"%.12g, ",out[j]-last);
332 /* code the spectral envelope, and keep track of the actual
333 quantized values; we don't want creeping error as each block is
334 nailed to the last quantized value of the previous block. */
336 for(j=0;j<look->m;j+=b->dim){
337 int entry=_f0_fit(b,out,work,j);
338 bits+=vorbis_book_bufencode(b,entry,vbb);
341 fprintf(ef,"%d,\n",entry);
349 for(j=0;j<look->m;j++){
361 /* take the coefficients back to a spectral envelope curve */
362 vorbis_lsp_to_curve(out,look->linearmap,look->n,look->ln,
363 work,look->m,amp,info->ampdB);
367 memset(out,0,sizeof(float)*look->n);
372 static float floor0_forward2(vorbis_block *vb,vorbis_look_floor *i,
373 long amp,float error,
374 vorbis_bitbuffer *vbb){
377 vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
378 vorbis_info_floor0 *info=look->vi;
379 long maxval=(1L<<info->ampbits)-1;
380 long adj=rint(todB(error)/info->ampdB*maxval/2);
385 oggpack_write(&vb->opb,amp,info->ampbits);
386 bitbuf_pack(&vb->opb,vbb);
387 return(fromdB((float)adj/maxval*info->ampdB));
393 static int floor0_inverse(vorbis_block *vb,vorbis_look_floor *i,float *out){
394 vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
395 vorbis_info_floor0 *info=look->vi;
398 int ampraw=oggpack_read(&vb->opb,info->ampbits);
399 if(ampraw>0){ /* also handles the -1 out of data case */
400 long maxval=(1<<info->ampbits)-1;
401 float amp=(float)ampraw/maxval*info->ampdB;
402 int booknum=oggpack_read(&vb->opb,_ilog(info->numbooks));
403 float *lsp=alloca(sizeof(float)*look->m);
406 backend_lookup_state *be=vb->vd->backend_state;
407 codebook *b=be->fullbooks+info->books[booknum];
410 memset(out,0,sizeof(float)*look->m);
412 for(j=0;j<look->m;j+=b->dim)
413 if(vorbis_book_decodevs(b,lsp+j,&vb->opb,1,-1)==-1)goto eop;
415 for(k=0;k<b->dim;k++,j++)lsp[j]+=last;
419 /* take the coefficients back to a spectral envelope curve */
420 vorbis_lsp_to_curve(out,look->linearmap,look->n,look->ln,
421 lsp,look->m,amp,info->ampdB);
427 memset(out,0,sizeof(float)*look->n);
432 vorbis_func_floor floor0_exportbundle={
433 &floor0_pack,&floor0_unpack,&floor0_look,&floor0_copy_info,&floor0_free_info,
434 &floor0_free_look,&floor0_forward,&floor0_forward2,&floor0_inverse