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-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.37 2001/02/10 02:06:59 xiphmont Exp $
16 ********************************************************************/
22 #include "vorbis/codec.h"
23 #include "codec_internal.h"
41 vorbis_info_floor0 *vi;
47 /* infrastructure for finding fit */
48 static long _f0_fit(codebook *book,
55 float *lsp=workfit+cursor;
57 if(cursor)base=workfit[cursor-1];
58 norm=orig[cursor+dim-1]-base;
61 lsp[i]=(orig[i+cursor]-base);
62 best=_best(book,lsp,1);
64 memcpy(lsp,book->valuelist+best*dim,dim*sizeof(float));
70 /***********************************************/
72 static vorbis_info_floor *floor0_copy_info (vorbis_info_floor *i){
73 vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
74 vorbis_info_floor0 *ret=_ogg_malloc(sizeof(vorbis_info_floor0));
75 memcpy(ret,info,sizeof(vorbis_info_floor0));
79 static void floor0_free_info(vorbis_info_floor *i){
81 memset(i,0,sizeof(vorbis_info_floor0));
86 static void floor0_free_look(vorbis_look_floor *i){
87 vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
89 if(look->linearmap)_ogg_free(look->linearmap);
90 if(look->lsp_look)_ogg_free(look->lsp_look);
91 lpc_clear(&look->lpclook);
92 memset(look,0,sizeof(vorbis_look_floor0));
97 static void floor0_pack (vorbis_info_floor *i,oggpack_buffer *opb){
98 vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
100 oggpack_write(opb,info->order,8);
101 oggpack_write(opb,info->rate,16);
102 oggpack_write(opb,info->barkmap,16);
103 oggpack_write(opb,info->ampbits,6);
104 oggpack_write(opb,info->ampdB,8);
105 oggpack_write(opb,info->numbooks-1,4);
106 for(j=0;j<info->numbooks;j++)
107 oggpack_write(opb,info->books[j],8);
110 static vorbis_info_floor *floor0_unpack (vorbis_info *vi,oggpack_buffer *opb){
111 codec_setup_info *ci=vi->codec_setup;
114 vorbis_info_floor0 *info=_ogg_malloc(sizeof(vorbis_info_floor0));
115 info->order=oggpack_read(opb,8);
116 info->rate=oggpack_read(opb,16);
117 info->barkmap=oggpack_read(opb,16);
118 info->ampbits=oggpack_read(opb,6);
119 info->ampdB=oggpack_read(opb,8);
120 info->numbooks=oggpack_read(opb,4)+1;
122 if(info->order<1)goto err_out;
123 if(info->rate<1)goto err_out;
124 if(info->barkmap<1)goto err_out;
125 if(info->numbooks<1)goto err_out;
127 for(j=0;j<info->numbooks;j++){
128 info->books[j]=oggpack_read(opb,8);
129 if(info->books[j]<0 || info->books[j]>=ci->books)goto err_out;
134 floor0_free_info(info);
138 /* initialize Bark scale and normalization lookups. We could do this
139 with static tables, but Vorbis allows a number of possible
140 combinations, so it's best to do it computationally.
142 The below is authoritative in terms of defining scale mapping.
143 Note that the scale depends on the sampling rate as well as the
144 linear block and mapping sizes */
146 static vorbis_look_floor *floor0_look (vorbis_dsp_state *vd,vorbis_info_mode *mi,
147 vorbis_info_floor *i){
150 vorbis_info *vi=vd->vi;
151 codec_setup_info *ci=vi->codec_setup;
152 vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
153 vorbis_look_floor0 *look=_ogg_calloc(1,sizeof(vorbis_look_floor0));
155 look->n=ci->blocksizes[mi->blockflag]/2;
156 look->ln=info->barkmap;
160 lpc_init(&look->lpclook,look->ln,look->m);
162 /* we choose a scaling constant so that:
163 floor(bark(rate/2-1)*C)=mapped-1
164 floor(bark(rate/2)*C)=mapped */
165 scale=look->ln/toBARK(info->rate/2.f);
167 /* the mapping from a linear scale to a smaller bark scale is
168 straightforward. We do *not* make sure that the linear mapping
169 does not skip bark-scale bins; the decoder simply skips them and
170 the encoder may do what it wishes in filling them. They're
171 necessary in some mapping combinations to keep the scale spacing
173 look->linearmap=_ogg_malloc((look->n+1)*sizeof(int));
174 for(j=0;j<look->n;j++){
175 int val=floor( toBARK((info->rate/2.f)/look->n*j)
176 *scale); /* bark numbers represent band edges */
177 if(val>=look->ln)val=look->ln; /* guard against the approximation */
178 look->linearmap[j]=val;
180 look->linearmap[j]=-1;
182 look->lsp_look=_ogg_malloc(look->ln*sizeof(float));
183 for(j=0;j<look->ln;j++)
184 look->lsp_look[j]=2*cos(M_PI/look->ln*j);
189 /* less efficient than the decode side (written for clarity). We're
190 not bottlenecked here anyway */
192 float _curve_to_lpc(float *curve,float *lpc,
193 vorbis_look_floor0 *l){
194 /* map the input curve to a bark-scale curve for encoding */
197 float *work=alloca(sizeof(float)*mapped);
201 memset(work,0,sizeof(float)*mapped);
203 /* Only the decode side is behavior-specced; for now in the encoder,
204 we select the maximum value of each band as representative (this
205 helps make sure peaks don't go out of range. In error terms,
206 selecting min would make more sense, but the codebook is trained
207 numerically, so we don't actually lose. We'd still want to
208 use the original curve for error and noise estimation */
211 bark=l->linearmap[i];
212 if(work[bark]<curve[i])work[bark]=curve[i];
214 /* If the bark scale is climbing rapidly, some bins may end up
215 going unused. This isn't a waste actually; it keeps the
216 scale resolution even so that the LPC generator has an easy
217 time. However, if we leave the bins empty we lose energy.
218 So, fill 'em in. The decoder does not do anything with he
219 unused bins, so we can fill them anyway we like to end up
220 with a better spectral curve */
222 /* we'll always have a bin zero, so we don't need to guard init */
225 float del=(float)j/span;
226 work[j+last]=work[bark]*del+work[last]*(1.f-del);
232 /* If we're over-ranged to avoid edge effects, fill in the end of spectrum gap */
233 for(i=bark+1;i<mapped;i++)
236 return vorbis_lpc_from_curve(work,lpc,&(l->lpclook));
239 /* generate the whole freq response curve of an LSP IIR filter */
240 /* didn't need in->out seperation, modifies the flr[] vector; takes in
241 a dB scale floor, puts out linear */
242 static int floor0_forward(vorbis_block *vb,vorbis_look_floor *i,
245 vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
246 vorbis_info_floor0 *info=look->vi;
258 sprintf(buffer,"lsp0coeff_%d.vqd",vb->mode);
259 of=fopen(buffer,"a");
263 /* our floor comes in on a [-Inf...0] dB scale. The curve has to be
264 positive, so we offset it. */
266 for(j=0;j<look->n;j++)
269 /* use 'out' as temp storage */
270 /* Convert our floor to a set of lpc coefficients */
271 amp=sqrt(_curve_to_lpc(flr,flr,look));
273 /* amp is in the range (0. to ampdB]. Encode that range using
277 long maxval=(1L<<info->ampbits)-1;
279 val=rint(amp/info->ampdB*maxval);
281 if(val<0)val=0; /* likely */
282 if(val>maxval)val=maxval; /* not bloody likely */
284 oggpack_write(&vb->opb,val,info->ampbits);
286 amp=(float)val/maxval*info->ampdB;
292 float *lspwork=alloca(look->m*sizeof(float));
294 /* the spec supports using one of a number of codebooks. Right
295 now, encode using this lib supports only one */
296 backend_lookup_state *be=vb->vd->backend_state;
300 /* LSP <-> LPC is orthogonal and LSP quantizes more stably */
301 _analysis_output("lpc",seq,flr,look->m,0,0);
303 vorbis_lpc_to_lsp(flr,flr,look->m);
305 _analysis_output("lsp",seq,flr,look->m,0,0);
309 float *lspwork2=alloca(look->m*sizeof(float));
310 memcpy(lspwork2,flr,sizeof(float)*look->m);
311 memcpy(lspwork,flr,sizeof(float)*look->m);
312 vorbis_lsp_to_curve(flr,look->linearmap,look->n,look->ln,
313 lspwork2,look->m,amp,info->ampdB);
315 _analysis_output("prefit",seq++,flr,look->n,0,1);
316 memcpy(flr,lspwork,sizeof(float)*look->m);
321 /* which codebook to use? We do it only by range right now. */
322 if(info->numbooks>1){
324 for(j=0;j<look->m;j++){
325 float val=flr[j]-last;
326 if(val<info->lessthan || val>info->greaterthan)break;
336 b=be->fullbooks+info->books[booknum];
337 oggpack_write(&vb->opb,booknum,_ilog(info->numbooks));
343 for(j=0;j<look->m;j++){
344 fprintf(of,"%.12g, ",flr[j]-last);
351 sprintf(buffer,"lsp0ent_m%d_b%d.vqd",vb->mode,booknum);
352 ef=fopen(buffer,"a");
356 /* code the spectral envelope, and keep track of the actual
357 quantized values; we don't want creeping error as each block is
358 nailed to the last quantized value of the previous block. */
360 for(j=0;j<look->m;j+=b->dim){
361 int entry=_f0_fit(b,flr,lspwork,j);
362 bits+=vorbis_book_encode(b,entry,&vb->opb);
365 fprintf(ef,"%d,\n",entry);
374 /* take the coefficients back to a spectral envelope curve */
375 vorbis_lsp_to_curve(flr,look->linearmap,look->n,look->ln,
376 lspwork,look->m,amp,info->ampdB);
384 memset(flr,0,sizeof(float)*look->n);
389 static int floor0_inverse(vorbis_block *vb,vorbis_look_floor *i,float *out){
390 vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
391 vorbis_info_floor0 *info=look->vi;
394 int ampraw=oggpack_read(&vb->opb,info->ampbits);
395 if(ampraw>0){ /* also handles the -1 out of data case */
396 long maxval=(1<<info->ampbits)-1;
397 float amp=(float)ampraw/maxval*info->ampdB;
398 int booknum=oggpack_read(&vb->opb,_ilog(info->numbooks));
399 float *lsp=alloca(sizeof(float)*look->m);
401 if(booknum!=-1 && booknum<info->numbooks){ /* be paranoid */
402 backend_lookup_state *be=vb->vd->backend_state;
403 codebook *b=be->fullbooks+info->books[booknum];
406 memset(out,0,sizeof(float)*look->m);
408 for(j=0;j<look->m;j+=b->dim)
409 if(vorbis_book_decodevs(b,lsp+j,&vb->opb,1,-1)==-1)goto eop;
411 for(k=0;k<b->dim;k++,j++)lsp[j]+=last;
415 /* take the coefficients back to a spectral envelope curve */
416 vorbis_lsp_to_curve(out,look->linearmap,look->n,look->ln,
417 lsp,look->m,amp,info->ampdB);
423 memset(out,0,sizeof(float)*look->n);
428 vorbis_func_floor floor0_exportbundle={
429 &floor0_pack,&floor0_unpack,&floor0_look,&floor0_copy_info,&floor0_free_info,
430 &floor0_free_look,&floor0_forward,&floor0_inverse