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.54 2003/03/07 09:13:30 xiphmont Exp $
16 ********************************************************************/
22 #include "vorbis/codec.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;
98 floor0_free_info(info);
102 /* initialize Bark scale and normalization lookups. We could do this
103 with static tables, but Vorbis allows a number of possible
104 combinations, so it's best to do it computationally.
106 The below is authoritative in terms of defining scale mapping.
107 Note that the scale depends on the sampling rate as well as the
108 linear block and mapping sizes */
110 static void floor0_map_lazy_init(vorbis_block *vb,
111 vorbis_info_floor *infoX,
112 vorbis_look_floor0 *look){
113 if(!look->linearmap[vb->W]){
114 vorbis_dsp_state *vd=vb->vd;
115 vorbis_info *vi=vd->vi;
116 codec_setup_info *ci=vi->codec_setup;
117 vorbis_info_floor0 *info=(vorbis_info_floor0 *)infoX;
119 int n=ci->blocksizes[W]/2,j;
121 /* we choose a scaling constant so that:
122 floor(bark(rate/2-1)*C)=mapped-1
123 floor(bark(rate/2)*C)=mapped */
124 float scale=look->ln/toBARK(info->rate/2.f);
126 /* the mapping from a linear scale to a smaller bark scale is
127 straightforward. We do *not* make sure that the linear mapping
128 does not skip bark-scale bins; the decoder simply skips them and
129 the encoder may do what it wishes in filling them. They're
130 necessary in some mapping combinations to keep the scale spacing
132 look->linearmap[W]=_ogg_malloc((n+1)*sizeof(**look->linearmap));
134 int val=floor( toBARK((info->rate/2.f)/n*j)
135 *scale); /* bark numbers represent band edges */
136 if(val>=look->ln)val=look->ln-1; /* guard against the approximation */
137 look->linearmap[W][j]=val;
139 look->linearmap[W][j]=-1;
144 static vorbis_look_floor *floor0_look(vorbis_dsp_state *vd,
145 vorbis_info_floor *i){
147 vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
148 vorbis_look_floor0 *look=_ogg_calloc(1,sizeof(*look));
150 look->ln=info->barkmap;
153 look->linearmap=_ogg_calloc(2,sizeof(*look->linearmap));
158 static void *floor0_inverse1(vorbis_block *vb,vorbis_look_floor *i){
159 vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
160 vorbis_info_floor0 *info=look->vi;
163 int ampraw=oggpack_read(&vb->opb,info->ampbits);
164 if(ampraw>0){ /* also handles the -1 out of data case */
165 long maxval=(1<<info->ampbits)-1;
166 float amp=(float)ampraw/maxval*info->ampdB;
167 int booknum=oggpack_read(&vb->opb,_ilog(info->numbooks));
169 if(booknum!=-1 && booknum<info->numbooks){ /* be paranoid */
170 codec_setup_info *ci=vb->vd->vi->codec_setup;
171 codebook *b=ci->fullbooks+info->books[booknum];
174 /* the additional b->dim is a guard against any possible stack
175 smash; b->dim is provably more than we can overflow the
177 float *lsp=_vorbis_block_alloc(vb,sizeof(*lsp)*(look->m+b->dim+1));
179 for(j=0;j<look->m;j+=b->dim)
180 if(vorbis_book_decodev_set(b,lsp+j,&vb->opb,b->dim)==-1)goto eop;
182 for(k=0;k<b->dim;k++,j++)lsp[j]+=last;
194 static int floor0_inverse2(vorbis_block *vb,vorbis_look_floor *i,
195 void *memo,float *out){
196 vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
197 vorbis_info_floor0 *info=look->vi;
199 floor0_map_lazy_init(vb,info,look);
202 float *lsp=(float *)memo;
203 float amp=lsp[look->m];
205 /* take the coefficients back to a spectral envelope curve */
206 vorbis_lsp_to_curve(out,
207 look->linearmap[vb->W],
210 lsp,look->m,amp,(float)info->ampdB);
213 memset(out,0,sizeof(*out)*look->n[vb->W]);
218 vorbis_func_floor floor0_exportbundle={
219 NULL,&floor0_unpack,&floor0_look,&floor0_free_info,
220 &floor0_free_look,&floor0_inverse1,&floor0_inverse2