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-2009 *
9 * by the Xiph.Org Foundation http://www.xiph.org/ *
11 ********************************************************************
13 function: floor backend 0 implementation
14 last mod: $Id: floor0.c 17558 2010-10-22 00:24:41Z tterribe $
16 ********************************************************************/
21 #include <ext/libogg/ogg.h>
23 #include "codec_internal.h"
41 vorbis_info_floor0 *vi;
48 /***********************************************/
50 static void floor0_free_info(vorbis_info_floor *i){
51 vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
53 memset(info,0,sizeof(*info));
58 static void floor0_free_look(vorbis_look_floor *i){
59 vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
64 if(look->linearmap[0])_ogg_free(look->linearmap[0]);
65 if(look->linearmap[1])_ogg_free(look->linearmap[1]);
67 _ogg_free(look->linearmap);
69 memset(look,0,sizeof(*look));
74 static vorbis_info_floor *floor0_unpack (vorbis_info *vi,oggpack_buffer *opb){
75 codec_setup_info *ci=vi->codec_setup;
78 vorbis_info_floor0 *info=_ogg_malloc(sizeof(*info));
79 info->order=oggpack_read(opb,8);
80 info->rate=oggpack_read(opb,16);
81 info->barkmap=oggpack_read(opb,16);
82 info->ampbits=oggpack_read(opb,6);
83 info->ampdB=oggpack_read(opb,8);
84 info->numbooks=oggpack_read(opb,4)+1;
86 if(info->order<1)goto err_out;
87 if(info->rate<1)goto err_out;
88 if(info->barkmap<1)goto err_out;
89 if(info->numbooks<1)goto err_out;
91 for(j=0;j<info->numbooks;j++){
92 info->books[j]=oggpack_read(opb,8);
93 if(info->books[j]<0 || info->books[j]>=ci->books)goto err_out;
94 if(ci->book_param[info->books[j]]->maptype==0)goto err_out;
95 if(ci->book_param[info->books[j]]->dim<1)goto err_out;
100 floor0_free_info(info);
104 /* initialize Bark scale and normalization lookups. We could do this
105 with static tables, but Vorbis allows a number of possible
106 combinations, so it's best to do it computationally.
108 The below is authoritative in terms of defining scale mapping.
109 Note that the scale depends on the sampling rate as well as the
110 linear block and mapping sizes */
112 static void floor0_map_lazy_init(vorbis_block *vb,
113 vorbis_info_floor *infoX,
114 vorbis_look_floor0 *look){
115 if(!look->linearmap[vb->W]){
116 vorbis_dsp_state *vd=vb->vd;
117 vorbis_info *vi=vd->vi;
118 codec_setup_info *ci=vi->codec_setup;
119 vorbis_info_floor0 *info=(vorbis_info_floor0 *)infoX;
121 int n=ci->blocksizes[W]/2,j;
123 /* we choose a scaling constant so that:
124 floor(bark(rate/2-1)*C)=mapped-1
125 floor(bark(rate/2)*C)=mapped */
126 float scale=look->ln/toBARK(info->rate/2.f);
128 /* the mapping from a linear scale to a smaller bark scale is
129 straightforward. We do *not* make sure that the linear mapping
130 does not skip bark-scale bins; the decoder simply skips them and
131 the encoder may do what it wishes in filling them. They're
132 necessary in some mapping combinations to keep the scale spacing
134 look->linearmap[W]=_ogg_malloc((n+1)*sizeof(**look->linearmap));
136 int val=floor( toBARK((info->rate/2.f)/n*j)
137 *scale); /* bark numbers represent band edges */
138 if(val>=look->ln)val=look->ln-1; /* guard against the approximation */
139 look->linearmap[W][j]=val;
141 look->linearmap[W][j]=-1;
146 static vorbis_look_floor *floor0_look(vorbis_dsp_state *vd,
147 vorbis_info_floor *i){
148 vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
149 vorbis_look_floor0 *look=_ogg_calloc(1,sizeof(*look));
151 look->ln=info->barkmap;
154 look->linearmap=_ogg_calloc(2,sizeof(*look->linearmap));
159 static void *floor0_inverse1(vorbis_block *vb,vorbis_look_floor *i){
160 vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
161 vorbis_info_floor0 *info=look->vi;
164 int ampraw=oggpack_read(&vb->opb,info->ampbits);
165 if(ampraw>0){ /* also handles the -1 out of data case */
166 long maxval=(1<<info->ampbits)-1;
167 float amp=(float)ampraw/maxval*info->ampdB;
168 int booknum=oggpack_read(&vb->opb,_ilog(info->numbooks));
170 if(booknum!=-1 && booknum<info->numbooks){ /* be paranoid */
171 codec_setup_info *ci=vb->vd->vi->codec_setup;
172 codebook *b=ci->fullbooks+info->books[booknum];
175 /* the additional b->dim is a guard against any possible stack
176 smash; b->dim is provably more than we can overflow the
178 float *lsp=_vorbis_block_alloc(vb,sizeof(*lsp)*(look->m+b->dim+1));
180 for(j=0;j<look->m;j+=b->dim)
181 if(vorbis_book_decodev_set(b,lsp+j,&vb->opb,b->dim)==-1)goto eop;
183 for(k=0;k<b->dim;k++,j++)lsp[j]+=last;
195 static int floor0_inverse2(vorbis_block *vb,vorbis_look_floor *i,
196 void *memo,float *out){
197 vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
198 vorbis_info_floor0 *info=look->vi;
200 floor0_map_lazy_init(vb,info,look);
203 float *lsp=(float *)memo;
204 float amp=lsp[look->m];
206 /* take the coefficients back to a spectral envelope curve */
207 vorbis_lsp_to_curve(out,
208 look->linearmap[vb->W],
211 lsp,look->m,amp,(float)info->ampdB);
214 memset(out,0,sizeof(*out)*look->n[vb->W]);
219 const vorbis_func_floor floor0_exportbundle={
220 NULL,&floor0_unpack,&floor0_look,&floor0_free_info,
221 &floor0_free_look,&floor0_inverse1,&floor0_inverse2