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-2002 *
9 * by the XIPHOPHORUS Company http://www.xiph.org/ *
11 ********************************************************************
13 function: floor backend 0 implementation
14 last mod: $Id: floor0.c,v 1.53 2002/07/17 21:34:31 xiphmont Exp $
16 ********************************************************************/
22 #include "vorbis/codec.h"
23 #include "codec_internal.h"
41 vorbis_info_floor0 *vi;
50 /***********************************************/
52 static void floor0_free_info(vorbis_info_floor *i){
53 vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
55 memset(info,0,sizeof(*info));
60 static void floor0_free_look(vorbis_look_floor *i){
61 vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
66 if(look->linearmap[0])_ogg_free(look->linearmap[0]);
67 if(look->linearmap[1])_ogg_free(look->linearmap[1]);
69 _ogg_free(look->linearmap);
71 if(look->lsp_look)_ogg_free(look->lsp_look);
72 lpc_clear(&look->lpclook);
73 memset(look,0,sizeof(*look));
78 static vorbis_info_floor *floor0_unpack (vorbis_info *vi,oggpack_buffer *opb){
79 codec_setup_info *ci=vi->codec_setup;
82 vorbis_info_floor0 *info=_ogg_malloc(sizeof(*info));
83 info->order=oggpack_read(opb,8);
84 info->rate=oggpack_read(opb,16);
85 info->barkmap=oggpack_read(opb,16);
86 info->ampbits=oggpack_read(opb,6);
87 info->ampdB=oggpack_read(opb,8);
88 info->numbooks=oggpack_read(opb,4)+1;
90 if(info->order<1)goto err_out;
91 if(info->rate<1)goto err_out;
92 if(info->barkmap<1)goto err_out;
93 if(info->numbooks<1)goto err_out;
95 for(j=0;j<info->numbooks;j++){
96 info->books[j]=oggpack_read(opb,8);
97 if(info->books[j]<0 || info->books[j]>=ci->books)goto err_out;
102 floor0_free_info(info);
106 /* initialize Bark scale and normalization lookups. We could do this
107 with static tables, but Vorbis allows a number of possible
108 combinations, so it's best to do it computationally.
110 The below is authoritative in terms of defining scale mapping.
111 Note that the scale depends on the sampling rate as well as the
112 linear block and mapping sizes */
114 static void floor0_map_lazy_init(vorbis_block *vb,
115 vorbis_info_floor *infoX,
116 vorbis_look_floor0 *look){
117 if(!look->linearmap[vb->W]){
118 vorbis_dsp_state *vd=vb->vd;
119 vorbis_info *vi=vd->vi;
120 codec_setup_info *ci=vi->codec_setup;
121 vorbis_info_floor0 *info=(vorbis_info_floor0 *)infoX;
123 int n=ci->blocksizes[W]/2,j;
125 /* we choose a scaling constant so that:
126 floor(bark(rate/2-1)*C)=mapped-1
127 floor(bark(rate/2)*C)=mapped */
128 float scale=look->ln/toBARK(info->rate/2.f);
130 /* the mapping from a linear scale to a smaller bark scale is
131 straightforward. We do *not* make sure that the linear mapping
132 does not skip bark-scale bins; the decoder simply skips them and
133 the encoder may do what it wishes in filling them. They're
134 necessary in some mapping combinations to keep the scale spacing
136 look->linearmap[W]=_ogg_malloc((n+1)*sizeof(**look->linearmap));
138 int val=floor( toBARK((info->rate/2.f)/n*j)
139 *scale); /* bark numbers represent band edges */
140 if(val>=look->ln)val=look->ln-1; /* guard against the approximation */
141 look->linearmap[W][j]=val;
143 look->linearmap[W][j]=-1;
148 static vorbis_look_floor *floor0_look(vorbis_dsp_state *vd,
149 vorbis_info_floor *i){
151 vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
152 vorbis_look_floor0 *look=_ogg_calloc(1,sizeof(*look));
154 look->ln=info->barkmap;
158 lpc_init(&look->lpclook,look->ln,look->m);
160 look->linearmap=_ogg_calloc(2,sizeof(*look->linearmap));
162 look->lsp_look=_ogg_malloc(look->ln*sizeof(*look->lsp_look));
163 for(j=0;j<look->ln;j++)
164 look->lsp_look[j]=2*cos(M_PI/look->ln*j);
169 static void *floor0_inverse1(vorbis_block *vb,vorbis_look_floor *i){
170 vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
171 vorbis_info_floor0 *info=look->vi;
174 int ampraw=oggpack_read(&vb->opb,info->ampbits);
175 if(ampraw>0){ /* also handles the -1 out of data case */
176 long maxval=(1<<info->ampbits)-1;
177 float amp=(float)ampraw/maxval*info->ampdB;
178 int booknum=oggpack_read(&vb->opb,_ilog(info->numbooks));
180 if(booknum!=-1 && booknum<info->numbooks){ /* be paranoid */
181 codec_setup_info *ci=vb->vd->vi->codec_setup;
182 codebook *b=ci->fullbooks+info->books[booknum];
185 /* the additional b->dim is a guard against any possible stack
186 smash; b->dim is provably more than we can overflow the
188 float *lsp=_vorbis_block_alloc(vb,sizeof(*lsp)*(look->m+b->dim+1));
190 for(j=0;j<look->m;j+=b->dim)
191 if(vorbis_book_decodev_set(b,lsp+j,&vb->opb,b->dim)==-1)goto eop;
193 for(k=0;k<b->dim;k++,j++)lsp[j]+=last;
205 static int floor0_inverse2(vorbis_block *vb,vorbis_look_floor *i,
206 void *memo,float *out){
207 vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
208 vorbis_info_floor0 *info=look->vi;
210 floor0_map_lazy_init(vb,info,look);
213 float *lsp=(float *)memo;
214 float amp=lsp[look->m];
216 /* take the coefficients back to a spectral envelope curve */
217 vorbis_lsp_to_curve(out,
218 look->linearmap[vb->W],
221 lsp,look->m,amp,(float)info->ampdB);
224 memset(out,0,sizeof(*out)*look->n[vb->W]);
229 vorbis_func_floor floor0_exportbundle={
230 NULL,&floor0_unpack,&floor0_look,&floor0_free_info,
231 &floor0_free_look,&floor0_inverse1,&floor0_inverse2