1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/media/libtremor/lib/tremor_block.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,497 @@ 1.4 +/******************************************************************** 1.5 + * * 1.6 + * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * 1.7 + * * 1.8 + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * 1.9 + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * 1.10 + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * 1.11 + * * 1.12 + * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * 1.13 + * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * 1.14 + * * 1.15 + ******************************************************************** 1.16 + 1.17 + function: PCM data vector blocking, windowing and dis/reassembly 1.18 + 1.19 + ********************************************************************/ 1.20 + 1.21 +#include <stdio.h> 1.22 +#include <stdlib.h> 1.23 +#include <string.h> 1.24 +#include <ogg/ogg.h> 1.25 +#include "ivorbiscodec.h" 1.26 +#include "codec_internal.h" 1.27 + 1.28 +#include "window.h" 1.29 +#include "registry.h" 1.30 +#include "misc.h" 1.31 + 1.32 +static int ilog(unsigned int v){ 1.33 + int ret=0; 1.34 + if(v)--v; 1.35 + while(v){ 1.36 + ret++; 1.37 + v>>=1; 1.38 + } 1.39 + return(ret); 1.40 +} 1.41 + 1.42 +/* pcm accumulator examples (not exhaustive): 1.43 + 1.44 + <-------------- lW ----------------> 1.45 + <--------------- W ----------------> 1.46 +: .....|..... _______________ | 1.47 +: .''' | '''_--- | |\ | 1.48 +:.....''' |_____--- '''......| | \_______| 1.49 +:.................|__________________|_______|__|______| 1.50 + |<------ Sl ------>| > Sr < |endW 1.51 + |beginSl |endSl | |endSr 1.52 + |beginW |endlW |beginSr 1.53 + 1.54 + 1.55 + |< lW >| 1.56 + <--------------- W ----------------> 1.57 + | | .. ______________ | 1.58 + | | ' `/ | ---_ | 1.59 + |___.'___/`. | ---_____| 1.60 + |_______|__|_______|_________________| 1.61 + | >|Sl|< |<------ Sr ----->|endW 1.62 + | | |endSl |beginSr |endSr 1.63 + |beginW | |endlW 1.64 + mult[0] |beginSl mult[n] 1.65 + 1.66 + <-------------- lW -----------------> 1.67 + |<--W-->| 1.68 +: .............. ___ | | 1.69 +: .''' |`/ \ | | 1.70 +:.....''' |/`....\|...| 1.71 +:.........................|___|___|___| 1.72 + |Sl |Sr |endW 1.73 + | | |endSr 1.74 + | |beginSr 1.75 + | |endSl 1.76 + |beginSl 1.77 + |beginW 1.78 +*/ 1.79 + 1.80 +/* block abstraction setup *********************************************/ 1.81 + 1.82 +#ifndef WORD_ALIGN 1.83 +#define WORD_ALIGN 8 1.84 +#endif 1.85 + 1.86 +int vorbis_block_init(vorbis_dsp_state *v, vorbis_block *vb){ 1.87 + memset(vb,0,sizeof(*vb)); 1.88 + vb->vd=v; 1.89 + vb->localalloc=0; 1.90 + vb->localstore=NULL; 1.91 + 1.92 + return(0); 1.93 +} 1.94 + 1.95 +void *_vorbis_block_alloc(vorbis_block *vb,long bytes){ 1.96 + bytes=(bytes+(WORD_ALIGN-1)) & ~(WORD_ALIGN-1); 1.97 + if(bytes+vb->localtop>vb->localalloc){ 1.98 + /* can't just _ogg_realloc... there are outstanding pointers */ 1.99 + if(vb->localstore){ 1.100 + struct alloc_chain *link=(struct alloc_chain *)_ogg_malloc(sizeof(*link)); 1.101 + vb->totaluse+=vb->localtop; 1.102 + link->next=vb->reap; 1.103 + link->ptr=vb->localstore; 1.104 + vb->reap=link; 1.105 + } 1.106 + /* highly conservative */ 1.107 + vb->localalloc=bytes; 1.108 + vb->localstore=_ogg_malloc(vb->localalloc); 1.109 + vb->localtop=0; 1.110 + } 1.111 + { 1.112 + void *ret=(void *)(((char *)vb->localstore)+vb->localtop); 1.113 + vb->localtop+=bytes; 1.114 + return ret; 1.115 + } 1.116 +} 1.117 + 1.118 +/* reap the chain, pull the ripcord */ 1.119 +void _vorbis_block_ripcord(vorbis_block *vb){ 1.120 + /* reap the chain */ 1.121 + struct alloc_chain *reap=vb->reap; 1.122 + while(reap){ 1.123 + struct alloc_chain *next=reap->next; 1.124 + _ogg_free(reap->ptr); 1.125 + memset(reap,0,sizeof(*reap)); 1.126 + _ogg_free(reap); 1.127 + reap=next; 1.128 + } 1.129 + /* consolidate storage */ 1.130 + if(vb->totaluse){ 1.131 + vb->localstore=_ogg_realloc(vb->localstore,vb->totaluse+vb->localalloc); 1.132 + vb->localalloc+=vb->totaluse; 1.133 + vb->totaluse=0; 1.134 + } 1.135 + 1.136 + /* pull the ripcord */ 1.137 + vb->localtop=0; 1.138 + vb->reap=NULL; 1.139 +} 1.140 + 1.141 +int vorbis_block_clear(vorbis_block *vb){ 1.142 + _vorbis_block_ripcord(vb); 1.143 + if(vb->localstore)_ogg_free(vb->localstore); 1.144 + 1.145 + memset(vb,0,sizeof(*vb)); 1.146 + return(0); 1.147 +} 1.148 + 1.149 +static int _vds_init(vorbis_dsp_state *v,vorbis_info *vi){ 1.150 + int i; 1.151 + codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; 1.152 + private_state *b=NULL; 1.153 + 1.154 + if(ci==NULL) return 1; 1.155 + 1.156 + memset(v,0,sizeof(*v)); 1.157 + b=(private_state *)(v->backend_state=_ogg_calloc(1,sizeof(*b))); 1.158 + 1.159 + v->vi=vi; 1.160 + b->modebits=ilog(ci->modes); 1.161 + 1.162 + /* Vorbis I uses only window type 0 */ 1.163 + b->window[0]=_vorbis_window(0,ci->blocksizes[0]/2); 1.164 + b->window[1]=_vorbis_window(0,ci->blocksizes[1]/2); 1.165 + 1.166 + /* finish the codebooks */ 1.167 + if(!ci->fullbooks){ 1.168 + ci->fullbooks=(codebook *)_ogg_calloc(ci->books,sizeof(*ci->fullbooks)); 1.169 + for(i=0;i<ci->books;i++){ 1.170 + if(ci->book_param[i]==NULL) 1.171 + goto abort_books; 1.172 + if(vorbis_book_init_decode(ci->fullbooks+i,ci->book_param[i])) 1.173 + goto abort_books; 1.174 + /* decode codebooks are now standalone after init */ 1.175 + vorbis_staticbook_destroy(ci->book_param[i]); 1.176 + ci->book_param[i]=NULL; 1.177 + } 1.178 + } 1.179 + 1.180 + v->pcm_storage=ci->blocksizes[1]; 1.181 + v->pcm=(ogg_int32_t **)_ogg_malloc(vi->channels*sizeof(*v->pcm)); 1.182 + v->pcmret=(ogg_int32_t **)_ogg_malloc(vi->channels*sizeof(*v->pcmret)); 1.183 + for(i=0;i<vi->channels;i++) 1.184 + v->pcm[i]=(ogg_int32_t *)_ogg_calloc(v->pcm_storage,sizeof(*v->pcm[i])); 1.185 + 1.186 + /* all 1 (large block) or 0 (small block) */ 1.187 + /* explicitly set for the sake of clarity */ 1.188 + v->lW=0; /* previous window size */ 1.189 + v->W=0; /* current window size */ 1.190 + 1.191 + /* initialize all the mapping/backend lookups */ 1.192 + b->mode=(vorbis_look_mapping **)_ogg_calloc(ci->modes,sizeof(*b->mode)); 1.193 + for(i=0;i<ci->modes;i++){ 1.194 + int mapnum=ci->mode_param[i]->mapping; 1.195 + int maptype=ci->map_type[mapnum]; 1.196 + b->mode[i]=_mapping_P[maptype]->look(v,ci->mode_param[i], 1.197 + ci->map_param[mapnum]); 1.198 + } 1.199 + return 0; 1.200 +abort_books: 1.201 + for(i=0;i<ci->books;i++){ 1.202 + if(ci->book_param[i]!=NULL){ 1.203 + vorbis_staticbook_destroy(ci->book_param[i]); 1.204 + ci->book_param[i]=NULL; 1.205 + } 1.206 + } 1.207 + vorbis_dsp_clear(v); 1.208 + return -1; 1.209 +} 1.210 + 1.211 +int vorbis_synthesis_restart(vorbis_dsp_state *v){ 1.212 + vorbis_info *vi=v->vi; 1.213 + codec_setup_info *ci; 1.214 + 1.215 + if(!v->backend_state)return -1; 1.216 + if(!vi)return -1; 1.217 + ci=vi->codec_setup; 1.218 + if(!ci)return -1; 1.219 + 1.220 + v->centerW=ci->blocksizes[1]/2; 1.221 + v->pcm_current=v->centerW; 1.222 + 1.223 + v->pcm_returned=-1; 1.224 + v->granulepos=-1; 1.225 + v->sequence=-1; 1.226 + ((private_state *)(v->backend_state))->sample_count=-1; 1.227 + 1.228 + return(0); 1.229 +} 1.230 + 1.231 +int vorbis_synthesis_init(vorbis_dsp_state *v,vorbis_info *vi){ 1.232 + if(_vds_init(v,vi))return 1; 1.233 + vorbis_synthesis_restart(v); 1.234 + 1.235 + return 0; 1.236 +} 1.237 + 1.238 +void vorbis_dsp_clear(vorbis_dsp_state *v){ 1.239 + int i; 1.240 + if(v){ 1.241 + vorbis_info *vi=v->vi; 1.242 + codec_setup_info *ci=(codec_setup_info *)(vi?vi->codec_setup:NULL); 1.243 + private_state *b=(private_state *)v->backend_state; 1.244 + 1.245 + if(v->pcm){ 1.246 + for(i=0;i<vi->channels;i++) 1.247 + if(v->pcm[i])_ogg_free(v->pcm[i]); 1.248 + _ogg_free(v->pcm); 1.249 + if(v->pcmret)_ogg_free(v->pcmret); 1.250 + } 1.251 + 1.252 + /* free mode lookups; these are actually vorbis_look_mapping structs */ 1.253 + if(ci){ 1.254 + for(i=0;i<ci->modes;i++){ 1.255 + int mapnum=ci->mode_param[i]->mapping; 1.256 + int maptype=ci->map_type[mapnum]; 1.257 + if(b && b->mode)_mapping_P[maptype]->free_look(b->mode[i]); 1.258 + } 1.259 + } 1.260 + 1.261 + if(b){ 1.262 + if(b->mode)_ogg_free(b->mode); 1.263 + _ogg_free(b); 1.264 + } 1.265 + 1.266 + memset(v,0,sizeof(*v)); 1.267 + } 1.268 +} 1.269 + 1.270 +/* Unlike in analysis, the window is only partially applied for each 1.271 + block. The time domain envelope is not yet handled at the point of 1.272 + calling (as it relies on the previous block). */ 1.273 + 1.274 +int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb){ 1.275 + vorbis_info *vi=v->vi; 1.276 + codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; 1.277 + private_state *b=v->backend_state; 1.278 + int i,j; 1.279 + 1.280 + if(v->pcm_current>v->pcm_returned && v->pcm_returned!=-1)return(OV_EINVAL); 1.281 + 1.282 + v->lW=v->W; 1.283 + v->W=vb->W; 1.284 + v->nW=-1; 1.285 + 1.286 + if((v->sequence==-1)|| 1.287 + (v->sequence+1 != vb->sequence)){ 1.288 + v->granulepos=-1; /* out of sequence; lose count */ 1.289 + b->sample_count=-1; 1.290 + } 1.291 + 1.292 + v->sequence=vb->sequence; 1.293 + 1.294 + if(vb->pcm){ /* no pcm to process if vorbis_synthesis_trackonly 1.295 + was called on block */ 1.296 + int n=ci->blocksizes[v->W]/2; 1.297 + int n0=ci->blocksizes[0]/2; 1.298 + int n1=ci->blocksizes[1]/2; 1.299 + 1.300 + int thisCenter; 1.301 + int prevCenter; 1.302 + 1.303 + if(v->centerW){ 1.304 + thisCenter=n1; 1.305 + prevCenter=0; 1.306 + }else{ 1.307 + thisCenter=0; 1.308 + prevCenter=n1; 1.309 + } 1.310 + 1.311 + /* v->pcm is now used like a two-stage double buffer. We don't want 1.312 + to have to constantly shift *or* adjust memory usage. Don't 1.313 + accept a new block until the old is shifted out */ 1.314 + 1.315 + /* overlap/add PCM */ 1.316 + 1.317 + for(j=0;j<vi->channels;j++){ 1.318 + /* the overlap/add section */ 1.319 + if(v->lW){ 1.320 + if(v->W){ 1.321 + /* large/large */ 1.322 + ogg_int32_t *pcm=v->pcm[j]+prevCenter; 1.323 + ogg_int32_t *p=vb->pcm[j]; 1.324 + for(i=0;i<n1;i++) 1.325 + pcm[i]+=p[i]; 1.326 + }else{ 1.327 + /* large/small */ 1.328 + ogg_int32_t *pcm=v->pcm[j]+prevCenter+n1/2-n0/2; 1.329 + ogg_int32_t *p=vb->pcm[j]; 1.330 + for(i=0;i<n0;i++) 1.331 + pcm[i]+=p[i]; 1.332 + } 1.333 + }else{ 1.334 + if(v->W){ 1.335 + /* small/large */ 1.336 + ogg_int32_t *pcm=v->pcm[j]+prevCenter; 1.337 + ogg_int32_t *p=vb->pcm[j]+n1/2-n0/2; 1.338 + for(i=0;i<n0;i++) 1.339 + pcm[i]+=p[i]; 1.340 + for(;i<n1/2+n0/2;i++) 1.341 + pcm[i]=p[i]; 1.342 + }else{ 1.343 + /* small/small */ 1.344 + ogg_int32_t *pcm=v->pcm[j]+prevCenter; 1.345 + ogg_int32_t *p=vb->pcm[j]; 1.346 + for(i=0;i<n0;i++) 1.347 + pcm[i]+=p[i]; 1.348 + } 1.349 + } 1.350 + 1.351 + /* the copy section */ 1.352 + { 1.353 + ogg_int32_t *pcm=v->pcm[j]+thisCenter; 1.354 + ogg_int32_t *p=vb->pcm[j]+n; 1.355 + for(i=0;i<n;i++) 1.356 + pcm[i]=p[i]; 1.357 + } 1.358 + } 1.359 + 1.360 + if(v->centerW) 1.361 + v->centerW=0; 1.362 + else 1.363 + v->centerW=n1; 1.364 + 1.365 + /* deal with initial packet state; we do this using the explicit 1.366 + pcm_returned==-1 flag otherwise we're sensitive to first block 1.367 + being short or long */ 1.368 + 1.369 + if(v->pcm_returned==-1){ 1.370 + v->pcm_returned=thisCenter; 1.371 + v->pcm_current=thisCenter; 1.372 + }else{ 1.373 + v->pcm_returned=prevCenter; 1.374 + v->pcm_current=prevCenter+ 1.375 + ci->blocksizes[v->lW]/4+ 1.376 + ci->blocksizes[v->W]/4; 1.377 + } 1.378 + 1.379 + } 1.380 + 1.381 + /* track the frame number... This is for convenience, but also 1.382 + making sure our last packet doesn't end with added padding. If 1.383 + the last packet is partial, the number of samples we'll have to 1.384 + return will be past the vb->granulepos. 1.385 + 1.386 + This is not foolproof! It will be confused if we begin 1.387 + decoding at the last page after a seek or hole. In that case, 1.388 + we don't have a starting point to judge where the last frame 1.389 + is. For this reason, vorbisfile will always try to make sure 1.390 + it reads the last two marked pages in proper sequence */ 1.391 + 1.392 + if(b->sample_count==-1){ 1.393 + b->sample_count=0; 1.394 + }else{ 1.395 + b->sample_count+=ci->blocksizes[v->lW]/4+ci->blocksizes[v->W]/4; 1.396 + } 1.397 + 1.398 + if(v->granulepos==-1){ 1.399 + if(vb->granulepos!=-1){ /* only set if we have a position to set to */ 1.400 + 1.401 + v->granulepos=vb->granulepos; 1.402 + 1.403 + /* is this a short page? */ 1.404 + if(b->sample_count>v->granulepos){ 1.405 + /* corner case; if this is both the first and last audio page, 1.406 + then spec says the end is cut, not beginning */ 1.407 + long extra=b->sample_count-vb->granulepos; 1.408 + 1.409 + /* we use ogg_int64_t for granule positions because a 1.410 + uint64 isn't universally available. Unfortunately, 1.411 + that means granposes can be 'negative' and result in 1.412 + extra being negative */ 1.413 + if(extra<0) 1.414 + extra=0; 1.415 + 1.416 + if(vb->eofflag){ 1.417 + /* trim the end */ 1.418 + /* no preceeding granulepos; assume we started at zero (we'd 1.419 + have to in a short single-page stream) */ 1.420 + /* granulepos could be -1 due to a seek, but that would result 1.421 + in a long coun`t, not short count */ 1.422 + 1.423 + /* Guard against corrupt/malicious frames that set EOP and 1.424 + a backdated granpos; don't rewind more samples than we 1.425 + actually have */ 1.426 + if(extra > v->pcm_current - v->pcm_returned) 1.427 + extra = v->pcm_current - v->pcm_returned; 1.428 + 1.429 + v->pcm_current-=extra; 1.430 + }else{ 1.431 + /* trim the beginning */ 1.432 + v->pcm_returned+=extra; 1.433 + if(v->pcm_returned>v->pcm_current) 1.434 + v->pcm_returned=v->pcm_current; 1.435 + } 1.436 + 1.437 + } 1.438 + 1.439 + } 1.440 + }else{ 1.441 + v->granulepos+=ci->blocksizes[v->lW]/4+ci->blocksizes[v->W]/4; 1.442 + if(vb->granulepos!=-1 && v->granulepos!=vb->granulepos){ 1.443 + 1.444 + if(v->granulepos>vb->granulepos){ 1.445 + long extra=v->granulepos-vb->granulepos; 1.446 + 1.447 + if(extra) 1.448 + if(vb->eofflag){ 1.449 + /* partial last frame. Strip the extra samples off */ 1.450 + 1.451 + /* Guard against corrupt/malicious frames that set EOP and 1.452 + a backdated granpos; don't rewind more samples than we 1.453 + actually have */ 1.454 + if(extra > v->pcm_current - v->pcm_returned) 1.455 + extra = v->pcm_current - v->pcm_returned; 1.456 + 1.457 + /* we use ogg_int64_t for granule positions because a 1.458 + uint64 isn't universally available. Unfortunately, 1.459 + that means granposes can be 'negative' and result in 1.460 + extra being negative */ 1.461 + if(extra<0) 1.462 + extra=0; 1.463 + 1.464 + v->pcm_current-=extra; 1.465 + 1.466 + } /* else {Shouldn't happen *unless* the bitstream is out of 1.467 + spec. Either way, believe the bitstream } */ 1.468 + } /* else {Shouldn't happen *unless* the bitstream is out of 1.469 + spec. Either way, believe the bitstream } */ 1.470 + v->granulepos=vb->granulepos; 1.471 + } 1.472 + } 1.473 + 1.474 + /* Update, cleanup */ 1.475 + 1.476 + if(vb->eofflag)v->eofflag=1; 1.477 + return(0); 1.478 +} 1.479 + 1.480 +/* pcm==NULL indicates we just want the pending samples, no more */ 1.481 +int vorbis_synthesis_pcmout(vorbis_dsp_state *v,ogg_int32_t ***pcm){ 1.482 + vorbis_info *vi=v->vi; 1.483 + if(v->pcm_returned>-1 && v->pcm_returned<v->pcm_current){ 1.484 + if(pcm){ 1.485 + int i; 1.486 + for(i=0;i<vi->channels;i++) 1.487 + v->pcmret[i]=v->pcm[i]+v->pcm_returned; 1.488 + *pcm=v->pcmret; 1.489 + } 1.490 + return(v->pcm_current-v->pcm_returned); 1.491 + } 1.492 + return(0); 1.493 +} 1.494 + 1.495 +int vorbis_synthesis_read(vorbis_dsp_state *v,int bytes){ 1.496 + if(bytes && v->pcm_returned+bytes>v->pcm_current)return(OV_EINVAL); 1.497 + v->pcm_returned+=bytes; 1.498 + return(0); 1.499 +} 1.500 +