vrshoot
diff libs/vorbis/floor0.c @ 0:b2f14e535253
initial commit
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sat, 01 Feb 2014 19:58:19 +0200 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/libs/vorbis/floor0.c Sat Feb 01 19:58:19 2014 +0200 1.3 @@ -0,0 +1,221 @@ 1.4 +/******************************************************************** 1.5 + * * 1.6 + * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * 1.7 + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * 1.8 + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * 1.9 + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * 1.10 + * * 1.11 + * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 * 1.12 + * by the Xiph.Org Foundation http://www.xiph.org/ * 1.13 + * * 1.14 + ******************************************************************** 1.15 + 1.16 + function: floor backend 0 implementation 1.17 + last mod: $Id: floor0.c 18184 2012-02-03 20:55:12Z xiphmont $ 1.18 + 1.19 + ********************************************************************/ 1.20 + 1.21 +#include <stdlib.h> 1.22 +#include <string.h> 1.23 +#include <math.h> 1.24 +#include <ogg/ogg.h> 1.25 +#include "vorbis/codec.h" 1.26 +#include "codec_internal.h" 1.27 +#include "registry.h" 1.28 +#include "lpc.h" 1.29 +#include "lsp.h" 1.30 +#include "codebook.h" 1.31 +#include "scales.h" 1.32 +#include "misc.h" 1.33 +#include "os.h" 1.34 + 1.35 +#include "misc.h" 1.36 +#include <stdio.h> 1.37 + 1.38 +typedef struct { 1.39 + int ln; 1.40 + int m; 1.41 + int **linearmap; 1.42 + int n[2]; 1.43 + 1.44 + vorbis_info_floor0 *vi; 1.45 + 1.46 + long bits; 1.47 + long frames; 1.48 +} vorbis_look_floor0; 1.49 + 1.50 + 1.51 +/***********************************************/ 1.52 + 1.53 +static void floor0_free_info(vorbis_info_floor *i){ 1.54 + vorbis_info_floor0 *info=(vorbis_info_floor0 *)i; 1.55 + if(info){ 1.56 + memset(info,0,sizeof(*info)); 1.57 + _ogg_free(info); 1.58 + } 1.59 +} 1.60 + 1.61 +static void floor0_free_look(vorbis_look_floor *i){ 1.62 + vorbis_look_floor0 *look=(vorbis_look_floor0 *)i; 1.63 + if(look){ 1.64 + 1.65 + if(look->linearmap){ 1.66 + 1.67 + if(look->linearmap[0])_ogg_free(look->linearmap[0]); 1.68 + if(look->linearmap[1])_ogg_free(look->linearmap[1]); 1.69 + 1.70 + _ogg_free(look->linearmap); 1.71 + } 1.72 + memset(look,0,sizeof(*look)); 1.73 + _ogg_free(look); 1.74 + } 1.75 +} 1.76 + 1.77 +static vorbis_info_floor *floor0_unpack (vorbis_info *vi,oggpack_buffer *opb){ 1.78 + codec_setup_info *ci=vi->codec_setup; 1.79 + int j; 1.80 + 1.81 + vorbis_info_floor0 *info=_ogg_malloc(sizeof(*info)); 1.82 + info->order=oggpack_read(opb,8); 1.83 + info->rate=oggpack_read(opb,16); 1.84 + info->barkmap=oggpack_read(opb,16); 1.85 + info->ampbits=oggpack_read(opb,6); 1.86 + info->ampdB=oggpack_read(opb,8); 1.87 + info->numbooks=oggpack_read(opb,4)+1; 1.88 + 1.89 + if(info->order<1)goto err_out; 1.90 + if(info->rate<1)goto err_out; 1.91 + if(info->barkmap<1)goto err_out; 1.92 + if(info->numbooks<1)goto err_out; 1.93 + 1.94 + for(j=0;j<info->numbooks;j++){ 1.95 + info->books[j]=oggpack_read(opb,8); 1.96 + if(info->books[j]<0 || info->books[j]>=ci->books)goto err_out; 1.97 + if(ci->book_param[info->books[j]]->maptype==0)goto err_out; 1.98 + if(ci->book_param[info->books[j]]->dim<1)goto err_out; 1.99 + } 1.100 + return(info); 1.101 + 1.102 + err_out: 1.103 + floor0_free_info(info); 1.104 + return(NULL); 1.105 +} 1.106 + 1.107 +/* initialize Bark scale and normalization lookups. We could do this 1.108 + with static tables, but Vorbis allows a number of possible 1.109 + combinations, so it's best to do it computationally. 1.110 + 1.111 + The below is authoritative in terms of defining scale mapping. 1.112 + Note that the scale depends on the sampling rate as well as the 1.113 + linear block and mapping sizes */ 1.114 + 1.115 +static void floor0_map_lazy_init(vorbis_block *vb, 1.116 + vorbis_info_floor *infoX, 1.117 + vorbis_look_floor0 *look){ 1.118 + if(!look->linearmap[vb->W]){ 1.119 + vorbis_dsp_state *vd=vb->vd; 1.120 + vorbis_info *vi=vd->vi; 1.121 + codec_setup_info *ci=vi->codec_setup; 1.122 + vorbis_info_floor0 *info=(vorbis_info_floor0 *)infoX; 1.123 + int W=vb->W; 1.124 + int n=ci->blocksizes[W]/2,j; 1.125 + 1.126 + /* we choose a scaling constant so that: 1.127 + floor(bark(rate/2-1)*C)=mapped-1 1.128 + floor(bark(rate/2)*C)=mapped */ 1.129 + float scale=look->ln/toBARK(info->rate/2.f); 1.130 + 1.131 + /* the mapping from a linear scale to a smaller bark scale is 1.132 + straightforward. We do *not* make sure that the linear mapping 1.133 + does not skip bark-scale bins; the decoder simply skips them and 1.134 + the encoder may do what it wishes in filling them. They're 1.135 + necessary in some mapping combinations to keep the scale spacing 1.136 + accurate */ 1.137 + look->linearmap[W]=_ogg_malloc((n+1)*sizeof(**look->linearmap)); 1.138 + for(j=0;j<n;j++){ 1.139 + int val=floor( toBARK((info->rate/2.f)/n*j) 1.140 + *scale); /* bark numbers represent band edges */ 1.141 + if(val>=look->ln)val=look->ln-1; /* guard against the approximation */ 1.142 + look->linearmap[W][j]=val; 1.143 + } 1.144 + look->linearmap[W][j]=-1; 1.145 + look->n[W]=n; 1.146 + } 1.147 +} 1.148 + 1.149 +static vorbis_look_floor *floor0_look(vorbis_dsp_state *vd, 1.150 + vorbis_info_floor *i){ 1.151 + vorbis_info_floor0 *info=(vorbis_info_floor0 *)i; 1.152 + vorbis_look_floor0 *look=_ogg_calloc(1,sizeof(*look)); 1.153 + look->m=info->order; 1.154 + look->ln=info->barkmap; 1.155 + look->vi=info; 1.156 + 1.157 + look->linearmap=_ogg_calloc(2,sizeof(*look->linearmap)); 1.158 + 1.159 + return look; 1.160 +} 1.161 + 1.162 +static void *floor0_inverse1(vorbis_block *vb,vorbis_look_floor *i){ 1.163 + vorbis_look_floor0 *look=(vorbis_look_floor0 *)i; 1.164 + vorbis_info_floor0 *info=look->vi; 1.165 + int j,k; 1.166 + 1.167 + int ampraw=oggpack_read(&vb->opb,info->ampbits); 1.168 + if(ampraw>0){ /* also handles the -1 out of data case */ 1.169 + long maxval=(1<<info->ampbits)-1; 1.170 + float amp=(float)ampraw/maxval*info->ampdB; 1.171 + int booknum=oggpack_read(&vb->opb,_ilog(info->numbooks)); 1.172 + 1.173 + if(booknum!=-1 && booknum<info->numbooks){ /* be paranoid */ 1.174 + codec_setup_info *ci=vb->vd->vi->codec_setup; 1.175 + codebook *b=ci->fullbooks+info->books[booknum]; 1.176 + float last=0.f; 1.177 + 1.178 + /* the additional b->dim is a guard against any possible stack 1.179 + smash; b->dim is provably more than we can overflow the 1.180 + vector */ 1.181 + float *lsp=_vorbis_block_alloc(vb,sizeof(*lsp)*(look->m+b->dim+1)); 1.182 + 1.183 + if(vorbis_book_decodev_set(b,lsp,&vb->opb,look->m)==-1)goto eop; 1.184 + for(j=0;j<look->m;){ 1.185 + for(k=0;j<look->m && k<b->dim;k++,j++)lsp[j]+=last; 1.186 + last=lsp[j-1]; 1.187 + } 1.188 + 1.189 + lsp[look->m]=amp; 1.190 + return(lsp); 1.191 + } 1.192 + } 1.193 + eop: 1.194 + return(NULL); 1.195 +} 1.196 + 1.197 +static int floor0_inverse2(vorbis_block *vb,vorbis_look_floor *i, 1.198 + void *memo,float *out){ 1.199 + vorbis_look_floor0 *look=(vorbis_look_floor0 *)i; 1.200 + vorbis_info_floor0 *info=look->vi; 1.201 + 1.202 + floor0_map_lazy_init(vb,info,look); 1.203 + 1.204 + if(memo){ 1.205 + float *lsp=(float *)memo; 1.206 + float amp=lsp[look->m]; 1.207 + 1.208 + /* take the coefficients back to a spectral envelope curve */ 1.209 + vorbis_lsp_to_curve(out, 1.210 + look->linearmap[vb->W], 1.211 + look->n[vb->W], 1.212 + look->ln, 1.213 + lsp,look->m,amp,(float)info->ampdB); 1.214 + return(1); 1.215 + } 1.216 + memset(out,0,sizeof(*out)*look->n[vb->W]); 1.217 + return(0); 1.218 +} 1.219 + 1.220 +/* export hooks */ 1.221 +const vorbis_func_floor floor0_exportbundle={ 1.222 + NULL,&floor0_unpack,&floor0_look,&floor0_free_info, 1.223 + &floor0_free_look,&floor0_inverse1,&floor0_inverse2 1.224 +};