vorbis_floor0.c (6889B)
1 /******************************************************************** 2 * * 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. * 7 * * 8 * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2015 * 9 * by the Xiph.Org Foundation https://xiph.org/ * 10 * * 11 ******************************************************************** 12 13 function: floor backend 0 implementation 14 15 ********************************************************************/ 16 17 #include <stdlib.h> 18 #include <string.h> 19 #include <math.h> 20 #include <ogg/ogg.h> 21 #include "vorbis/codec.h" 22 #include "codec_internal.h" 23 #include "registry.h" 24 #include "lpc.h" 25 #include "lsp.h" 26 #include "codebook.h" 27 #include "scales.h" 28 #include "misc.h" 29 #include "os.h" 30 31 #include "misc.h" 32 #include <stdio.h> 33 34 typedef struct { 35 int ln; 36 int m; 37 int **linearmap; 38 int n[2]; 39 40 vorbis_info_floor0 *vi; 41 42 long bits; 43 long frames; 44 } vorbis_look_floor0; 45 46 47 /***********************************************/ 48 49 static void floor0_free_info(vorbis_info_floor *i){ 50 vorbis_info_floor0 *info=(vorbis_info_floor0 *)i; 51 if(info){ 52 memset(info,0,sizeof(*info)); 53 _ogg_free(info); 54 } 55 } 56 57 static void floor0_free_look(vorbis_look_floor *i){ 58 vorbis_look_floor0 *look=(vorbis_look_floor0 *)i; 59 if(look){ 60 61 if(look->linearmap){ 62 63 if(look->linearmap[0])_ogg_free(look->linearmap[0]); 64 if(look->linearmap[1])_ogg_free(look->linearmap[1]); 65 66 _ogg_free(look->linearmap); 67 } 68 memset(look,0,sizeof(*look)); 69 _ogg_free(look); 70 } 71 } 72 73 static vorbis_info_floor *floor0_unpack (vorbis_info *vi,oggpack_buffer *opb){ 74 codec_setup_info *ci=vi->codec_setup; 75 int j; 76 77 vorbis_info_floor0 *info=_ogg_malloc(sizeof(*info)); 78 info->order=oggpack_read(opb,8); 79 info->rate=oggpack_read(opb,16); 80 info->barkmap=oggpack_read(opb,16); 81 info->ampbits=oggpack_read(opb,6); 82 info->ampdB=oggpack_read(opb,8); 83 info->numbooks=oggpack_read(opb,4)+1; 84 85 if(info->order<1)goto err_out; 86 if(info->rate<1)goto err_out; 87 if(info->barkmap<1)goto err_out; 88 if(info->numbooks<1)goto err_out; 89 90 for(j=0;j<info->numbooks;j++){ 91 info->books[j]=oggpack_read(opb,8); 92 if(info->books[j]<0 || info->books[j]>=ci->books)goto err_out; 93 if(ci->book_param[info->books[j]]->maptype==0)goto err_out; 94 if(ci->book_param[info->books[j]]->dim<1)goto err_out; 95 } 96 return(info); 97 98 err_out: 99 floor0_free_info(info); 100 return(NULL); 101 } 102 103 /* initialize Bark scale and normalization lookups. We could do this 104 with static tables, but Vorbis allows a number of possible 105 combinations, so it's best to do it computationally. 106 107 The below is authoritative in terms of defining scale mapping. 108 Note that the scale depends on the sampling rate as well as the 109 linear block and mapping sizes */ 110 111 static void floor0_map_lazy_init(vorbis_block *vb, 112 vorbis_info_floor *infoX, 113 vorbis_look_floor0 *look){ 114 if(!look->linearmap[vb->W]){ 115 vorbis_dsp_state *vd=vb->vd; 116 vorbis_info *vi=vd->vi; 117 codec_setup_info *ci=vi->codec_setup; 118 vorbis_info_floor0 *info=(vorbis_info_floor0 *)infoX; 119 int W=vb->W; 120 int n=ci->blocksizes[W]/2,j; 121 122 /* we choose a scaling constant so that: 123 floor(bark(rate/2-1)*C)=mapped-1 124 floor(bark(rate/2)*C)=mapped */ 125 float scale=look->ln/toBARK(info->rate/2.f); 126 127 /* the mapping from a linear scale to a smaller bark scale is 128 straightforward. We do *not* make sure that the linear mapping 129 does not skip bark-scale bins; the decoder simply skips them and 130 the encoder may do what it wishes in filling them. They're 131 necessary in some mapping combinations to keep the scale spacing 132 accurate */ 133 look->linearmap[W]=_ogg_malloc((n+1)*sizeof(**look->linearmap)); 134 for(j=0;j<n;j++){ 135 int val=floor( toBARK((info->rate/2.f)/n*j) 136 *scale); /* bark numbers represent band edges */ 137 if(val>=look->ln)val=look->ln-1; /* guard against the approximation */ 138 look->linearmap[W][j]=val; 139 } 140 look->linearmap[W][j]=-1; 141 look->n[W]=n; 142 } 143 } 144 145 static vorbis_look_floor *floor0_look(vorbis_dsp_state *vd, 146 vorbis_info_floor *i){ 147 vorbis_info_floor0 *info=(vorbis_info_floor0 *)i; 148 vorbis_look_floor0 *look=_ogg_calloc(1,sizeof(*look)); 149 150 (void)vd; 151 152 look->m=info->order; 153 look->ln=info->barkmap; 154 look->vi=info; 155 156 look->linearmap=_ogg_calloc(2,sizeof(*look->linearmap)); 157 158 return look; 159 } 160 161 static void *floor0_inverse1(vorbis_block *vb,vorbis_look_floor *i){ 162 vorbis_look_floor0 *look=(vorbis_look_floor0 *)i; 163 vorbis_info_floor0 *info=look->vi; 164 int j,k; 165 166 int ampraw=oggpack_read(&vb->opb,info->ampbits); 167 if(ampraw>0){ /* also handles the -1 out of data case */ 168 long maxval=(1<<info->ampbits)-1; 169 float amp=(float)ampraw/maxval*info->ampdB; 170 int booknum=oggpack_read(&vb->opb,ov_ilog(info->numbooks)); 171 172 if(booknum!=-1 && booknum<info->numbooks){ /* be paranoid */ 173 codec_setup_info *ci=vb->vd->vi->codec_setup; 174 codebook *b=ci->fullbooks+info->books[booknum]; 175 float last=0.f; 176 177 /* the additional b->dim is a guard against any possible stack 178 smash; b->dim is provably more than we can overflow the 179 vector */ 180 float *lsp=_vorbis_block_alloc(vb,sizeof(*lsp)*(look->m+b->dim+1)); 181 182 if(vorbis_book_decodev_set(b,lsp,&vb->opb,look->m)==-1)goto eop; 183 for(j=0;j<look->m;){ 184 for(k=0;j<look->m && k<b->dim;k++,j++)lsp[j]+=last; 185 last=lsp[j-1]; 186 } 187 188 lsp[look->m]=amp; 189 return(lsp); 190 } 191 } 192 eop: 193 return(NULL); 194 } 195 196 static int floor0_inverse2(vorbis_block *vb,vorbis_look_floor *i, 197 void *memo,float *out){ 198 vorbis_look_floor0 *look=(vorbis_look_floor0 *)i; 199 vorbis_info_floor0 *info=look->vi; 200 201 floor0_map_lazy_init(vb,info,look); 202 203 if(memo){ 204 float *lsp=(float *)memo; 205 float amp=lsp[look->m]; 206 207 /* take the coefficients back to a spectral envelope curve */ 208 vorbis_lsp_to_curve(out, 209 look->linearmap[vb->W], 210 look->n[vb->W], 211 look->ln, 212 lsp,look->m,amp,(float)info->ampdB); 213 return(1); 214 } 215 memset(out,0,sizeof(*out)*look->n[vb->W]); 216 return(0); 217 } 218 219 /* export hooks */ 220 const vorbis_func_floor floor0_exportbundle={ 221 NULL,&floor0_unpack,&floor0_look,&floor0_free_info, 222 &floor0_free_look,&floor0_inverse1,&floor0_inverse2 223 };