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.52 2002/06/28 22:19:35 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];
184 float *lsp=_vorbis_block_alloc(vb,sizeof(*lsp)*(look->m+1));
186 for(j=0;j<look->m;j+=b->dim)
187 if(vorbis_book_decodev_set(b,lsp+j,&vb->opb,b->dim)==-1)goto eop;
189 for(k=0;k<b->dim;k++,j++)lsp[j]+=last;
201 static int floor0_inverse2(vorbis_block *vb,vorbis_look_floor *i,
202 void *memo,float *out){
203 vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
204 vorbis_info_floor0 *info=look->vi;
206 floor0_map_lazy_init(vb,info,look);
209 float *lsp=(float *)memo;
210 float amp=lsp[look->m];
212 /* take the coefficients back to a spectral envelope curve */
213 vorbis_lsp_to_curve(out,
214 look->linearmap[vb->W],
217 lsp,look->m,amp,(float)info->ampdB);
220 memset(out,0,sizeof(*out)*look->n[vb->W]);
225 vorbis_func_floor floor0_exportbundle={
226 NULL,&floor0_unpack,&floor0_look,&floor0_free_info,
227 &floor0_free_look,&floor0_inverse1,&floor0_inverse2