vrshoot
diff libs/vorbis/block.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/block.c Sat Feb 01 19:58:19 2014 +0200 1.3 @@ -0,0 +1,1046 @@ 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: PCM data vector blocking, windowing and dis/reassembly 1.17 + last mod: $Id: block.c 17561 2010-10-23 10:34:24Z xiphmont $ 1.18 + 1.19 + Handle windowing, overlap-add, etc of the PCM vectors. This is made 1.20 + more amusing by Vorbis' current two allowed block sizes. 1.21 + 1.22 + ********************************************************************/ 1.23 + 1.24 +#include <stdio.h> 1.25 +#include <stdlib.h> 1.26 +#include <string.h> 1.27 +#include <ogg/ogg.h> 1.28 +#include "vorbis/codec.h" 1.29 +#include "codec_internal.h" 1.30 + 1.31 +#include "window.h" 1.32 +#include "mdct.h" 1.33 +#include "lpc.h" 1.34 +#include "registry.h" 1.35 +#include "misc.h" 1.36 + 1.37 +static int ilog2(unsigned int v){ 1.38 + int ret=0; 1.39 + if(v)--v; 1.40 + while(v){ 1.41 + ret++; 1.42 + v>>=1; 1.43 + } 1.44 + return(ret); 1.45 +} 1.46 + 1.47 +/* pcm accumulator examples (not exhaustive): 1.48 + 1.49 + <-------------- lW ----------------> 1.50 + <--------------- W ----------------> 1.51 +: .....|..... _______________ | 1.52 +: .''' | '''_--- | |\ | 1.53 +:.....''' |_____--- '''......| | \_______| 1.54 +:.................|__________________|_______|__|______| 1.55 + |<------ Sl ------>| > Sr < |endW 1.56 + |beginSl |endSl | |endSr 1.57 + |beginW |endlW |beginSr 1.58 + 1.59 + 1.60 + |< lW >| 1.61 + <--------------- W ----------------> 1.62 + | | .. ______________ | 1.63 + | | ' `/ | ---_ | 1.64 + |___.'___/`. | ---_____| 1.65 + |_______|__|_______|_________________| 1.66 + | >|Sl|< |<------ Sr ----->|endW 1.67 + | | |endSl |beginSr |endSr 1.68 + |beginW | |endlW 1.69 + mult[0] |beginSl mult[n] 1.70 + 1.71 + <-------------- lW -----------------> 1.72 + |<--W-->| 1.73 +: .............. ___ | | 1.74 +: .''' |`/ \ | | 1.75 +:.....''' |/`....\|...| 1.76 +:.........................|___|___|___| 1.77 + |Sl |Sr |endW 1.78 + | | |endSr 1.79 + | |beginSr 1.80 + | |endSl 1.81 + |beginSl 1.82 + |beginW 1.83 +*/ 1.84 + 1.85 +/* block abstraction setup *********************************************/ 1.86 + 1.87 +#ifndef WORD_ALIGN 1.88 +#define WORD_ALIGN 8 1.89 +#endif 1.90 + 1.91 +int vorbis_block_init(vorbis_dsp_state *v, vorbis_block *vb){ 1.92 + int i; 1.93 + memset(vb,0,sizeof(*vb)); 1.94 + vb->vd=v; 1.95 + vb->localalloc=0; 1.96 + vb->localstore=NULL; 1.97 + if(v->analysisp){ 1.98 + vorbis_block_internal *vbi= 1.99 + vb->internal=_ogg_calloc(1,sizeof(vorbis_block_internal)); 1.100 + vbi->ampmax=-9999; 1.101 + 1.102 + for(i=0;i<PACKETBLOBS;i++){ 1.103 + if(i==PACKETBLOBS/2){ 1.104 + vbi->packetblob[i]=&vb->opb; 1.105 + }else{ 1.106 + vbi->packetblob[i]= 1.107 + _ogg_calloc(1,sizeof(oggpack_buffer)); 1.108 + } 1.109 + oggpack_writeinit(vbi->packetblob[i]); 1.110 + } 1.111 + } 1.112 + 1.113 + return(0); 1.114 +} 1.115 + 1.116 +void *_vorbis_block_alloc(vorbis_block *vb,long bytes){ 1.117 + bytes=(bytes+(WORD_ALIGN-1)) & ~(WORD_ALIGN-1); 1.118 + if(bytes+vb->localtop>vb->localalloc){ 1.119 + /* can't just _ogg_realloc... there are outstanding pointers */ 1.120 + if(vb->localstore){ 1.121 + struct alloc_chain *link=_ogg_malloc(sizeof(*link)); 1.122 + vb->totaluse+=vb->localtop; 1.123 + link->next=vb->reap; 1.124 + link->ptr=vb->localstore; 1.125 + vb->reap=link; 1.126 + } 1.127 + /* highly conservative */ 1.128 + vb->localalloc=bytes; 1.129 + vb->localstore=_ogg_malloc(vb->localalloc); 1.130 + vb->localtop=0; 1.131 + } 1.132 + { 1.133 + void *ret=(void *)(((char *)vb->localstore)+vb->localtop); 1.134 + vb->localtop+=bytes; 1.135 + return ret; 1.136 + } 1.137 +} 1.138 + 1.139 +/* reap the chain, pull the ripcord */ 1.140 +void _vorbis_block_ripcord(vorbis_block *vb){ 1.141 + /* reap the chain */ 1.142 + struct alloc_chain *reap=vb->reap; 1.143 + while(reap){ 1.144 + struct alloc_chain *next=reap->next; 1.145 + _ogg_free(reap->ptr); 1.146 + memset(reap,0,sizeof(*reap)); 1.147 + _ogg_free(reap); 1.148 + reap=next; 1.149 + } 1.150 + /* consolidate storage */ 1.151 + if(vb->totaluse){ 1.152 + vb->localstore=_ogg_realloc(vb->localstore,vb->totaluse+vb->localalloc); 1.153 + vb->localalloc+=vb->totaluse; 1.154 + vb->totaluse=0; 1.155 + } 1.156 + 1.157 + /* pull the ripcord */ 1.158 + vb->localtop=0; 1.159 + vb->reap=NULL; 1.160 +} 1.161 + 1.162 +int vorbis_block_clear(vorbis_block *vb){ 1.163 + int i; 1.164 + vorbis_block_internal *vbi=vb->internal; 1.165 + 1.166 + _vorbis_block_ripcord(vb); 1.167 + if(vb->localstore)_ogg_free(vb->localstore); 1.168 + 1.169 + if(vbi){ 1.170 + for(i=0;i<PACKETBLOBS;i++){ 1.171 + oggpack_writeclear(vbi->packetblob[i]); 1.172 + if(i!=PACKETBLOBS/2)_ogg_free(vbi->packetblob[i]); 1.173 + } 1.174 + _ogg_free(vbi); 1.175 + } 1.176 + memset(vb,0,sizeof(*vb)); 1.177 + return(0); 1.178 +} 1.179 + 1.180 +/* Analysis side code, but directly related to blocking. Thus it's 1.181 + here and not in analysis.c (which is for analysis transforms only). 1.182 + The init is here because some of it is shared */ 1.183 + 1.184 +static int _vds_shared_init(vorbis_dsp_state *v,vorbis_info *vi,int encp){ 1.185 + int i; 1.186 + codec_setup_info *ci=vi->codec_setup; 1.187 + private_state *b=NULL; 1.188 + int hs; 1.189 + 1.190 + if(ci==NULL) return 1; 1.191 + hs=ci->halfrate_flag; 1.192 + 1.193 + memset(v,0,sizeof(*v)); 1.194 + b=v->backend_state=_ogg_calloc(1,sizeof(*b)); 1.195 + 1.196 + v->vi=vi; 1.197 + b->modebits=ilog2(ci->modes); 1.198 + 1.199 + b->transform[0]=_ogg_calloc(VI_TRANSFORMB,sizeof(*b->transform[0])); 1.200 + b->transform[1]=_ogg_calloc(VI_TRANSFORMB,sizeof(*b->transform[1])); 1.201 + 1.202 + /* MDCT is tranform 0 */ 1.203 + 1.204 + b->transform[0][0]=_ogg_calloc(1,sizeof(mdct_lookup)); 1.205 + b->transform[1][0]=_ogg_calloc(1,sizeof(mdct_lookup)); 1.206 + mdct_init(b->transform[0][0],ci->blocksizes[0]>>hs); 1.207 + mdct_init(b->transform[1][0],ci->blocksizes[1]>>hs); 1.208 + 1.209 + /* Vorbis I uses only window type 0 */ 1.210 + b->window[0]=ilog2(ci->blocksizes[0])-6; 1.211 + b->window[1]=ilog2(ci->blocksizes[1])-6; 1.212 + 1.213 + if(encp){ /* encode/decode differ here */ 1.214 + 1.215 + /* analysis always needs an fft */ 1.216 + drft_init(&b->fft_look[0],ci->blocksizes[0]); 1.217 + drft_init(&b->fft_look[1],ci->blocksizes[1]); 1.218 + 1.219 + /* finish the codebooks */ 1.220 + if(!ci->fullbooks){ 1.221 + ci->fullbooks=_ogg_calloc(ci->books,sizeof(*ci->fullbooks)); 1.222 + for(i=0;i<ci->books;i++) 1.223 + vorbis_book_init_encode(ci->fullbooks+i,ci->book_param[i]); 1.224 + } 1.225 + 1.226 + b->psy=_ogg_calloc(ci->psys,sizeof(*b->psy)); 1.227 + for(i=0;i<ci->psys;i++){ 1.228 + _vp_psy_init(b->psy+i, 1.229 + ci->psy_param[i], 1.230 + &ci->psy_g_param, 1.231 + ci->blocksizes[ci->psy_param[i]->blockflag]/2, 1.232 + vi->rate); 1.233 + } 1.234 + 1.235 + v->analysisp=1; 1.236 + }else{ 1.237 + /* finish the codebooks */ 1.238 + if(!ci->fullbooks){ 1.239 + ci->fullbooks=_ogg_calloc(ci->books,sizeof(*ci->fullbooks)); 1.240 + for(i=0;i<ci->books;i++){ 1.241 + if(ci->book_param[i]==NULL) 1.242 + goto abort_books; 1.243 + if(vorbis_book_init_decode(ci->fullbooks+i,ci->book_param[i])) 1.244 + goto abort_books; 1.245 + /* decode codebooks are now standalone after init */ 1.246 + vorbis_staticbook_destroy(ci->book_param[i]); 1.247 + ci->book_param[i]=NULL; 1.248 + } 1.249 + } 1.250 + } 1.251 + 1.252 + /* initialize the storage vectors. blocksize[1] is small for encode, 1.253 + but the correct size for decode */ 1.254 + v->pcm_storage=ci->blocksizes[1]; 1.255 + v->pcm=_ogg_malloc(vi->channels*sizeof(*v->pcm)); 1.256 + v->pcmret=_ogg_malloc(vi->channels*sizeof(*v->pcmret)); 1.257 + { 1.258 + int i; 1.259 + for(i=0;i<vi->channels;i++) 1.260 + v->pcm[i]=_ogg_calloc(v->pcm_storage,sizeof(*v->pcm[i])); 1.261 + } 1.262 + 1.263 + /* all 1 (large block) or 0 (small block) */ 1.264 + /* explicitly set for the sake of clarity */ 1.265 + v->lW=0; /* previous window size */ 1.266 + v->W=0; /* current window size */ 1.267 + 1.268 + /* all vector indexes */ 1.269 + v->centerW=ci->blocksizes[1]/2; 1.270 + 1.271 + v->pcm_current=v->centerW; 1.272 + 1.273 + /* initialize all the backend lookups */ 1.274 + b->flr=_ogg_calloc(ci->floors,sizeof(*b->flr)); 1.275 + b->residue=_ogg_calloc(ci->residues,sizeof(*b->residue)); 1.276 + 1.277 + for(i=0;i<ci->floors;i++) 1.278 + b->flr[i]=_floor_P[ci->floor_type[i]]-> 1.279 + look(v,ci->floor_param[i]); 1.280 + 1.281 + for(i=0;i<ci->residues;i++) 1.282 + b->residue[i]=_residue_P[ci->residue_type[i]]-> 1.283 + look(v,ci->residue_param[i]); 1.284 + 1.285 + return 0; 1.286 + abort_books: 1.287 + for(i=0;i<ci->books;i++){ 1.288 + if(ci->book_param[i]!=NULL){ 1.289 + vorbis_staticbook_destroy(ci->book_param[i]); 1.290 + ci->book_param[i]=NULL; 1.291 + } 1.292 + } 1.293 + vorbis_dsp_clear(v); 1.294 + return -1; 1.295 +} 1.296 + 1.297 +/* arbitrary settings and spec-mandated numbers get filled in here */ 1.298 +int vorbis_analysis_init(vorbis_dsp_state *v,vorbis_info *vi){ 1.299 + private_state *b=NULL; 1.300 + 1.301 + if(_vds_shared_init(v,vi,1))return 1; 1.302 + b=v->backend_state; 1.303 + b->psy_g_look=_vp_global_look(vi); 1.304 + 1.305 + /* Initialize the envelope state storage */ 1.306 + b->ve=_ogg_calloc(1,sizeof(*b->ve)); 1.307 + _ve_envelope_init(b->ve,vi); 1.308 + 1.309 + vorbis_bitrate_init(vi,&b->bms); 1.310 + 1.311 + /* compressed audio packets start after the headers 1.312 + with sequence number 3 */ 1.313 + v->sequence=3; 1.314 + 1.315 + return(0); 1.316 +} 1.317 + 1.318 +void vorbis_dsp_clear(vorbis_dsp_state *v){ 1.319 + int i; 1.320 + if(v){ 1.321 + vorbis_info *vi=v->vi; 1.322 + codec_setup_info *ci=(vi?vi->codec_setup:NULL); 1.323 + private_state *b=v->backend_state; 1.324 + 1.325 + if(b){ 1.326 + 1.327 + if(b->ve){ 1.328 + _ve_envelope_clear(b->ve); 1.329 + _ogg_free(b->ve); 1.330 + } 1.331 + 1.332 + if(b->transform[0]){ 1.333 + mdct_clear(b->transform[0][0]); 1.334 + _ogg_free(b->transform[0][0]); 1.335 + _ogg_free(b->transform[0]); 1.336 + } 1.337 + if(b->transform[1]){ 1.338 + mdct_clear(b->transform[1][0]); 1.339 + _ogg_free(b->transform[1][0]); 1.340 + _ogg_free(b->transform[1]); 1.341 + } 1.342 + 1.343 + if(b->flr){ 1.344 + if(ci) 1.345 + for(i=0;i<ci->floors;i++) 1.346 + _floor_P[ci->floor_type[i]]-> 1.347 + free_look(b->flr[i]); 1.348 + _ogg_free(b->flr); 1.349 + } 1.350 + if(b->residue){ 1.351 + if(ci) 1.352 + for(i=0;i<ci->residues;i++) 1.353 + _residue_P[ci->residue_type[i]]-> 1.354 + free_look(b->residue[i]); 1.355 + _ogg_free(b->residue); 1.356 + } 1.357 + if(b->psy){ 1.358 + if(ci) 1.359 + for(i=0;i<ci->psys;i++) 1.360 + _vp_psy_clear(b->psy+i); 1.361 + _ogg_free(b->psy); 1.362 + } 1.363 + 1.364 + if(b->psy_g_look)_vp_global_free(b->psy_g_look); 1.365 + vorbis_bitrate_clear(&b->bms); 1.366 + 1.367 + drft_clear(&b->fft_look[0]); 1.368 + drft_clear(&b->fft_look[1]); 1.369 + 1.370 + } 1.371 + 1.372 + if(v->pcm){ 1.373 + if(vi) 1.374 + for(i=0;i<vi->channels;i++) 1.375 + if(v->pcm[i])_ogg_free(v->pcm[i]); 1.376 + _ogg_free(v->pcm); 1.377 + if(v->pcmret)_ogg_free(v->pcmret); 1.378 + } 1.379 + 1.380 + if(b){ 1.381 + /* free header, header1, header2 */ 1.382 + if(b->header)_ogg_free(b->header); 1.383 + if(b->header1)_ogg_free(b->header1); 1.384 + if(b->header2)_ogg_free(b->header2); 1.385 + _ogg_free(b); 1.386 + } 1.387 + 1.388 + memset(v,0,sizeof(*v)); 1.389 + } 1.390 +} 1.391 + 1.392 +float **vorbis_analysis_buffer(vorbis_dsp_state *v, int vals){ 1.393 + int i; 1.394 + vorbis_info *vi=v->vi; 1.395 + private_state *b=v->backend_state; 1.396 + 1.397 + /* free header, header1, header2 */ 1.398 + if(b->header)_ogg_free(b->header);b->header=NULL; 1.399 + if(b->header1)_ogg_free(b->header1);b->header1=NULL; 1.400 + if(b->header2)_ogg_free(b->header2);b->header2=NULL; 1.401 + 1.402 + /* Do we have enough storage space for the requested buffer? If not, 1.403 + expand the PCM (and envelope) storage */ 1.404 + 1.405 + if(v->pcm_current+vals>=v->pcm_storage){ 1.406 + v->pcm_storage=v->pcm_current+vals*2; 1.407 + 1.408 + for(i=0;i<vi->channels;i++){ 1.409 + v->pcm[i]=_ogg_realloc(v->pcm[i],v->pcm_storage*sizeof(*v->pcm[i])); 1.410 + } 1.411 + } 1.412 + 1.413 + for(i=0;i<vi->channels;i++) 1.414 + v->pcmret[i]=v->pcm[i]+v->pcm_current; 1.415 + 1.416 + return(v->pcmret); 1.417 +} 1.418 + 1.419 +static void _preextrapolate_helper(vorbis_dsp_state *v){ 1.420 + int i; 1.421 + int order=16; 1.422 + float *lpc=alloca(order*sizeof(*lpc)); 1.423 + float *work=alloca(v->pcm_current*sizeof(*work)); 1.424 + long j; 1.425 + v->preextrapolate=1; 1.426 + 1.427 + if(v->pcm_current-v->centerW>order*2){ /* safety */ 1.428 + for(i=0;i<v->vi->channels;i++){ 1.429 + /* need to run the extrapolation in reverse! */ 1.430 + for(j=0;j<v->pcm_current;j++) 1.431 + work[j]=v->pcm[i][v->pcm_current-j-1]; 1.432 + 1.433 + /* prime as above */ 1.434 + vorbis_lpc_from_data(work,lpc,v->pcm_current-v->centerW,order); 1.435 + 1.436 +#if 0 1.437 + if(v->vi->channels==2){ 1.438 + if(i==0) 1.439 + _analysis_output("predataL",0,work,v->pcm_current-v->centerW,0,0,0); 1.440 + else 1.441 + _analysis_output("predataR",0,work,v->pcm_current-v->centerW,0,0,0); 1.442 + }else{ 1.443 + _analysis_output("predata",0,work,v->pcm_current-v->centerW,0,0,0); 1.444 + } 1.445 +#endif 1.446 + 1.447 + /* run the predictor filter */ 1.448 + vorbis_lpc_predict(lpc,work+v->pcm_current-v->centerW-order, 1.449 + order, 1.450 + work+v->pcm_current-v->centerW, 1.451 + v->centerW); 1.452 + 1.453 + for(j=0;j<v->pcm_current;j++) 1.454 + v->pcm[i][v->pcm_current-j-1]=work[j]; 1.455 + 1.456 + } 1.457 + } 1.458 +} 1.459 + 1.460 + 1.461 +/* call with val<=0 to set eof */ 1.462 + 1.463 +int vorbis_analysis_wrote(vorbis_dsp_state *v, int vals){ 1.464 + vorbis_info *vi=v->vi; 1.465 + codec_setup_info *ci=vi->codec_setup; 1.466 + 1.467 + if(vals<=0){ 1.468 + int order=32; 1.469 + int i; 1.470 + float *lpc=alloca(order*sizeof(*lpc)); 1.471 + 1.472 + /* if it wasn't done earlier (very short sample) */ 1.473 + if(!v->preextrapolate) 1.474 + _preextrapolate_helper(v); 1.475 + 1.476 + /* We're encoding the end of the stream. Just make sure we have 1.477 + [at least] a few full blocks of zeroes at the end. */ 1.478 + /* actually, we don't want zeroes; that could drop a large 1.479 + amplitude off a cliff, creating spread spectrum noise that will 1.480 + suck to encode. Extrapolate for the sake of cleanliness. */ 1.481 + 1.482 + vorbis_analysis_buffer(v,ci->blocksizes[1]*3); 1.483 + v->eofflag=v->pcm_current; 1.484 + v->pcm_current+=ci->blocksizes[1]*3; 1.485 + 1.486 + for(i=0;i<vi->channels;i++){ 1.487 + if(v->eofflag>order*2){ 1.488 + /* extrapolate with LPC to fill in */ 1.489 + long n; 1.490 + 1.491 + /* make a predictor filter */ 1.492 + n=v->eofflag; 1.493 + if(n>ci->blocksizes[1])n=ci->blocksizes[1]; 1.494 + vorbis_lpc_from_data(v->pcm[i]+v->eofflag-n,lpc,n,order); 1.495 + 1.496 + /* run the predictor filter */ 1.497 + vorbis_lpc_predict(lpc,v->pcm[i]+v->eofflag-order,order, 1.498 + v->pcm[i]+v->eofflag,v->pcm_current-v->eofflag); 1.499 + }else{ 1.500 + /* not enough data to extrapolate (unlikely to happen due to 1.501 + guarding the overlap, but bulletproof in case that 1.502 + assumtion goes away). zeroes will do. */ 1.503 + memset(v->pcm[i]+v->eofflag,0, 1.504 + (v->pcm_current-v->eofflag)*sizeof(*v->pcm[i])); 1.505 + 1.506 + } 1.507 + } 1.508 + }else{ 1.509 + 1.510 + if(v->pcm_current+vals>v->pcm_storage) 1.511 + return(OV_EINVAL); 1.512 + 1.513 + v->pcm_current+=vals; 1.514 + 1.515 + /* we may want to reverse extrapolate the beginning of a stream 1.516 + too... in case we're beginning on a cliff! */ 1.517 + /* clumsy, but simple. It only runs once, so simple is good. */ 1.518 + if(!v->preextrapolate && v->pcm_current-v->centerW>ci->blocksizes[1]) 1.519 + _preextrapolate_helper(v); 1.520 + 1.521 + } 1.522 + return(0); 1.523 +} 1.524 + 1.525 +/* do the deltas, envelope shaping, pre-echo and determine the size of 1.526 + the next block on which to continue analysis */ 1.527 +int vorbis_analysis_blockout(vorbis_dsp_state *v,vorbis_block *vb){ 1.528 + int i; 1.529 + vorbis_info *vi=v->vi; 1.530 + codec_setup_info *ci=vi->codec_setup; 1.531 + private_state *b=v->backend_state; 1.532 + vorbis_look_psy_global *g=b->psy_g_look; 1.533 + long beginW=v->centerW-ci->blocksizes[v->W]/2,centerNext; 1.534 + vorbis_block_internal *vbi=(vorbis_block_internal *)vb->internal; 1.535 + 1.536 + /* check to see if we're started... */ 1.537 + if(!v->preextrapolate)return(0); 1.538 + 1.539 + /* check to see if we're done... */ 1.540 + if(v->eofflag==-1)return(0); 1.541 + 1.542 + /* By our invariant, we have lW, W and centerW set. Search for 1.543 + the next boundary so we can determine nW (the next window size) 1.544 + which lets us compute the shape of the current block's window */ 1.545 + 1.546 + /* we do an envelope search even on a single blocksize; we may still 1.547 + be throwing more bits at impulses, and envelope search handles 1.548 + marking impulses too. */ 1.549 + { 1.550 + long bp=_ve_envelope_search(v); 1.551 + if(bp==-1){ 1.552 + 1.553 + if(v->eofflag==0)return(0); /* not enough data currently to search for a 1.554 + full long block */ 1.555 + v->nW=0; 1.556 + }else{ 1.557 + 1.558 + if(ci->blocksizes[0]==ci->blocksizes[1]) 1.559 + v->nW=0; 1.560 + else 1.561 + v->nW=bp; 1.562 + } 1.563 + } 1.564 + 1.565 + centerNext=v->centerW+ci->blocksizes[v->W]/4+ci->blocksizes[v->nW]/4; 1.566 + 1.567 + { 1.568 + /* center of next block + next block maximum right side. */ 1.569 + 1.570 + long blockbound=centerNext+ci->blocksizes[v->nW]/2; 1.571 + if(v->pcm_current<blockbound)return(0); /* not enough data yet; 1.572 + although this check is 1.573 + less strict that the 1.574 + _ve_envelope_search, 1.575 + the search is not run 1.576 + if we only use one 1.577 + block size */ 1.578 + 1.579 + 1.580 + } 1.581 + 1.582 + /* fill in the block. Note that for a short window, lW and nW are *short* 1.583 + regardless of actual settings in the stream */ 1.584 + 1.585 + _vorbis_block_ripcord(vb); 1.586 + vb->lW=v->lW; 1.587 + vb->W=v->W; 1.588 + vb->nW=v->nW; 1.589 + 1.590 + if(v->W){ 1.591 + if(!v->lW || !v->nW){ 1.592 + vbi->blocktype=BLOCKTYPE_TRANSITION; 1.593 + /*fprintf(stderr,"-");*/ 1.594 + }else{ 1.595 + vbi->blocktype=BLOCKTYPE_LONG; 1.596 + /*fprintf(stderr,"_");*/ 1.597 + } 1.598 + }else{ 1.599 + if(_ve_envelope_mark(v)){ 1.600 + vbi->blocktype=BLOCKTYPE_IMPULSE; 1.601 + /*fprintf(stderr,"|");*/ 1.602 + 1.603 + }else{ 1.604 + vbi->blocktype=BLOCKTYPE_PADDING; 1.605 + /*fprintf(stderr,".");*/ 1.606 + 1.607 + } 1.608 + } 1.609 + 1.610 + vb->vd=v; 1.611 + vb->sequence=v->sequence++; 1.612 + vb->granulepos=v->granulepos; 1.613 + vb->pcmend=ci->blocksizes[v->W]; 1.614 + 1.615 + /* copy the vectors; this uses the local storage in vb */ 1.616 + 1.617 + /* this tracks 'strongest peak' for later psychoacoustics */ 1.618 + /* moved to the global psy state; clean this mess up */ 1.619 + if(vbi->ampmax>g->ampmax)g->ampmax=vbi->ampmax; 1.620 + g->ampmax=_vp_ampmax_decay(g->ampmax,v); 1.621 + vbi->ampmax=g->ampmax; 1.622 + 1.623 + vb->pcm=_vorbis_block_alloc(vb,sizeof(*vb->pcm)*vi->channels); 1.624 + vbi->pcmdelay=_vorbis_block_alloc(vb,sizeof(*vbi->pcmdelay)*vi->channels); 1.625 + for(i=0;i<vi->channels;i++){ 1.626 + vbi->pcmdelay[i]= 1.627 + _vorbis_block_alloc(vb,(vb->pcmend+beginW)*sizeof(*vbi->pcmdelay[i])); 1.628 + memcpy(vbi->pcmdelay[i],v->pcm[i],(vb->pcmend+beginW)*sizeof(*vbi->pcmdelay[i])); 1.629 + vb->pcm[i]=vbi->pcmdelay[i]+beginW; 1.630 + 1.631 + /* before we added the delay 1.632 + vb->pcm[i]=_vorbis_block_alloc(vb,vb->pcmend*sizeof(*vb->pcm[i])); 1.633 + memcpy(vb->pcm[i],v->pcm[i]+beginW,ci->blocksizes[v->W]*sizeof(*vb->pcm[i])); 1.634 + */ 1.635 + 1.636 + } 1.637 + 1.638 + /* handle eof detection: eof==0 means that we've not yet received EOF 1.639 + eof>0 marks the last 'real' sample in pcm[] 1.640 + eof<0 'no more to do'; doesn't get here */ 1.641 + 1.642 + if(v->eofflag){ 1.643 + if(v->centerW>=v->eofflag){ 1.644 + v->eofflag=-1; 1.645 + vb->eofflag=1; 1.646 + return(1); 1.647 + } 1.648 + } 1.649 + 1.650 + /* advance storage vectors and clean up */ 1.651 + { 1.652 + int new_centerNext=ci->blocksizes[1]/2; 1.653 + int movementW=centerNext-new_centerNext; 1.654 + 1.655 + if(movementW>0){ 1.656 + 1.657 + _ve_envelope_shift(b->ve,movementW); 1.658 + v->pcm_current-=movementW; 1.659 + 1.660 + for(i=0;i<vi->channels;i++) 1.661 + memmove(v->pcm[i],v->pcm[i]+movementW, 1.662 + v->pcm_current*sizeof(*v->pcm[i])); 1.663 + 1.664 + 1.665 + v->lW=v->W; 1.666 + v->W=v->nW; 1.667 + v->centerW=new_centerNext; 1.668 + 1.669 + if(v->eofflag){ 1.670 + v->eofflag-=movementW; 1.671 + if(v->eofflag<=0)v->eofflag=-1; 1.672 + /* do not add padding to end of stream! */ 1.673 + if(v->centerW>=v->eofflag){ 1.674 + v->granulepos+=movementW-(v->centerW-v->eofflag); 1.675 + }else{ 1.676 + v->granulepos+=movementW; 1.677 + } 1.678 + }else{ 1.679 + v->granulepos+=movementW; 1.680 + } 1.681 + } 1.682 + } 1.683 + 1.684 + /* done */ 1.685 + return(1); 1.686 +} 1.687 + 1.688 +int vorbis_synthesis_restart(vorbis_dsp_state *v){ 1.689 + vorbis_info *vi=v->vi; 1.690 + codec_setup_info *ci; 1.691 + int hs; 1.692 + 1.693 + if(!v->backend_state)return -1; 1.694 + if(!vi)return -1; 1.695 + ci=vi->codec_setup; 1.696 + if(!ci)return -1; 1.697 + hs=ci->halfrate_flag; 1.698 + 1.699 + v->centerW=ci->blocksizes[1]>>(hs+1); 1.700 + v->pcm_current=v->centerW>>hs; 1.701 + 1.702 + v->pcm_returned=-1; 1.703 + v->granulepos=-1; 1.704 + v->sequence=-1; 1.705 + v->eofflag=0; 1.706 + ((private_state *)(v->backend_state))->sample_count=-1; 1.707 + 1.708 + return(0); 1.709 +} 1.710 + 1.711 +int vorbis_synthesis_init(vorbis_dsp_state *v,vorbis_info *vi){ 1.712 + if(_vds_shared_init(v,vi,0)){ 1.713 + vorbis_dsp_clear(v); 1.714 + return 1; 1.715 + } 1.716 + vorbis_synthesis_restart(v); 1.717 + return 0; 1.718 +} 1.719 + 1.720 +/* Unlike in analysis, the window is only partially applied for each 1.721 + block. The time domain envelope is not yet handled at the point of 1.722 + calling (as it relies on the previous block). */ 1.723 + 1.724 +int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb){ 1.725 + vorbis_info *vi=v->vi; 1.726 + codec_setup_info *ci=vi->codec_setup; 1.727 + private_state *b=v->backend_state; 1.728 + int hs=ci->halfrate_flag; 1.729 + int i,j; 1.730 + 1.731 + if(!vb)return(OV_EINVAL); 1.732 + if(v->pcm_current>v->pcm_returned && v->pcm_returned!=-1)return(OV_EINVAL); 1.733 + 1.734 + v->lW=v->W; 1.735 + v->W=vb->W; 1.736 + v->nW=-1; 1.737 + 1.738 + if((v->sequence==-1)|| 1.739 + (v->sequence+1 != vb->sequence)){ 1.740 + v->granulepos=-1; /* out of sequence; lose count */ 1.741 + b->sample_count=-1; 1.742 + } 1.743 + 1.744 + v->sequence=vb->sequence; 1.745 + 1.746 + if(vb->pcm){ /* no pcm to process if vorbis_synthesis_trackonly 1.747 + was called on block */ 1.748 + int n=ci->blocksizes[v->W]>>(hs+1); 1.749 + int n0=ci->blocksizes[0]>>(hs+1); 1.750 + int n1=ci->blocksizes[1]>>(hs+1); 1.751 + 1.752 + int thisCenter; 1.753 + int prevCenter; 1.754 + 1.755 + v->glue_bits+=vb->glue_bits; 1.756 + v->time_bits+=vb->time_bits; 1.757 + v->floor_bits+=vb->floor_bits; 1.758 + v->res_bits+=vb->res_bits; 1.759 + 1.760 + if(v->centerW){ 1.761 + thisCenter=n1; 1.762 + prevCenter=0; 1.763 + }else{ 1.764 + thisCenter=0; 1.765 + prevCenter=n1; 1.766 + } 1.767 + 1.768 + /* v->pcm is now used like a two-stage double buffer. We don't want 1.769 + to have to constantly shift *or* adjust memory usage. Don't 1.770 + accept a new block until the old is shifted out */ 1.771 + 1.772 + for(j=0;j<vi->channels;j++){ 1.773 + /* the overlap/add section */ 1.774 + if(v->lW){ 1.775 + if(v->W){ 1.776 + /* large/large */ 1.777 + float *w=_vorbis_window_get(b->window[1]-hs); 1.778 + float *pcm=v->pcm[j]+prevCenter; 1.779 + float *p=vb->pcm[j]; 1.780 + for(i=0;i<n1;i++) 1.781 + pcm[i]=pcm[i]*w[n1-i-1] + p[i]*w[i]; 1.782 + }else{ 1.783 + /* large/small */ 1.784 + float *w=_vorbis_window_get(b->window[0]-hs); 1.785 + float *pcm=v->pcm[j]+prevCenter+n1/2-n0/2; 1.786 + float *p=vb->pcm[j]; 1.787 + for(i=0;i<n0;i++) 1.788 + pcm[i]=pcm[i]*w[n0-i-1] +p[i]*w[i]; 1.789 + } 1.790 + }else{ 1.791 + if(v->W){ 1.792 + /* small/large */ 1.793 + float *w=_vorbis_window_get(b->window[0]-hs); 1.794 + float *pcm=v->pcm[j]+prevCenter; 1.795 + float *p=vb->pcm[j]+n1/2-n0/2; 1.796 + for(i=0;i<n0;i++) 1.797 + pcm[i]=pcm[i]*w[n0-i-1] +p[i]*w[i]; 1.798 + for(;i<n1/2+n0/2;i++) 1.799 + pcm[i]=p[i]; 1.800 + }else{ 1.801 + /* small/small */ 1.802 + float *w=_vorbis_window_get(b->window[0]-hs); 1.803 + float *pcm=v->pcm[j]+prevCenter; 1.804 + float *p=vb->pcm[j]; 1.805 + for(i=0;i<n0;i++) 1.806 + pcm[i]=pcm[i]*w[n0-i-1] +p[i]*w[i]; 1.807 + } 1.808 + } 1.809 + 1.810 + /* the copy section */ 1.811 + { 1.812 + float *pcm=v->pcm[j]+thisCenter; 1.813 + float *p=vb->pcm[j]+n; 1.814 + for(i=0;i<n;i++) 1.815 + pcm[i]=p[i]; 1.816 + } 1.817 + } 1.818 + 1.819 + if(v->centerW) 1.820 + v->centerW=0; 1.821 + else 1.822 + v->centerW=n1; 1.823 + 1.824 + /* deal with initial packet state; we do this using the explicit 1.825 + pcm_returned==-1 flag otherwise we're sensitive to first block 1.826 + being short or long */ 1.827 + 1.828 + if(v->pcm_returned==-1){ 1.829 + v->pcm_returned=thisCenter; 1.830 + v->pcm_current=thisCenter; 1.831 + }else{ 1.832 + v->pcm_returned=prevCenter; 1.833 + v->pcm_current=prevCenter+ 1.834 + ((ci->blocksizes[v->lW]/4+ 1.835 + ci->blocksizes[v->W]/4)>>hs); 1.836 + } 1.837 + 1.838 + } 1.839 + 1.840 + /* track the frame number... This is for convenience, but also 1.841 + making sure our last packet doesn't end with added padding. If 1.842 + the last packet is partial, the number of samples we'll have to 1.843 + return will be past the vb->granulepos. 1.844 + 1.845 + This is not foolproof! It will be confused if we begin 1.846 + decoding at the last page after a seek or hole. In that case, 1.847 + we don't have a starting point to judge where the last frame 1.848 + is. For this reason, vorbisfile will always try to make sure 1.849 + it reads the last two marked pages in proper sequence */ 1.850 + 1.851 + if(b->sample_count==-1){ 1.852 + b->sample_count=0; 1.853 + }else{ 1.854 + b->sample_count+=ci->blocksizes[v->lW]/4+ci->blocksizes[v->W]/4; 1.855 + } 1.856 + 1.857 + if(v->granulepos==-1){ 1.858 + if(vb->granulepos!=-1){ /* only set if we have a position to set to */ 1.859 + 1.860 + v->granulepos=vb->granulepos; 1.861 + 1.862 + /* is this a short page? */ 1.863 + if(b->sample_count>v->granulepos){ 1.864 + /* corner case; if this is both the first and last audio page, 1.865 + then spec says the end is cut, not beginning */ 1.866 + long extra=b->sample_count-vb->granulepos; 1.867 + 1.868 + /* we use ogg_int64_t for granule positions because a 1.869 + uint64 isn't universally available. Unfortunately, 1.870 + that means granposes can be 'negative' and result in 1.871 + extra being negative */ 1.872 + if(extra<0) 1.873 + extra=0; 1.874 + 1.875 + if(vb->eofflag){ 1.876 + /* trim the end */ 1.877 + /* no preceding granulepos; assume we started at zero (we'd 1.878 + have to in a short single-page stream) */ 1.879 + /* granulepos could be -1 due to a seek, but that would result 1.880 + in a long count, not short count */ 1.881 + 1.882 + /* Guard against corrupt/malicious frames that set EOP and 1.883 + a backdated granpos; don't rewind more samples than we 1.884 + actually have */ 1.885 + if(extra > (v->pcm_current - v->pcm_returned)<<hs) 1.886 + extra = (v->pcm_current - v->pcm_returned)<<hs; 1.887 + 1.888 + v->pcm_current-=extra>>hs; 1.889 + }else{ 1.890 + /* trim the beginning */ 1.891 + v->pcm_returned+=extra>>hs; 1.892 + if(v->pcm_returned>v->pcm_current) 1.893 + v->pcm_returned=v->pcm_current; 1.894 + } 1.895 + 1.896 + } 1.897 + 1.898 + } 1.899 + }else{ 1.900 + v->granulepos+=ci->blocksizes[v->lW]/4+ci->blocksizes[v->W]/4; 1.901 + if(vb->granulepos!=-1 && v->granulepos!=vb->granulepos){ 1.902 + 1.903 + if(v->granulepos>vb->granulepos){ 1.904 + long extra=v->granulepos-vb->granulepos; 1.905 + 1.906 + if(extra) 1.907 + if(vb->eofflag){ 1.908 + /* partial last frame. Strip the extra samples off */ 1.909 + 1.910 + /* Guard against corrupt/malicious frames that set EOP and 1.911 + a backdated granpos; don't rewind more samples than we 1.912 + actually have */ 1.913 + if(extra > (v->pcm_current - v->pcm_returned)<<hs) 1.914 + extra = (v->pcm_current - v->pcm_returned)<<hs; 1.915 + 1.916 + /* we use ogg_int64_t for granule positions because a 1.917 + uint64 isn't universally available. Unfortunately, 1.918 + that means granposes can be 'negative' and result in 1.919 + extra being negative */ 1.920 + if(extra<0) 1.921 + extra=0; 1.922 + 1.923 + v->pcm_current-=extra>>hs; 1.924 + } /* else {Shouldn't happen *unless* the bitstream is out of 1.925 + spec. Either way, believe the bitstream } */ 1.926 + } /* else {Shouldn't happen *unless* the bitstream is out of 1.927 + spec. Either way, believe the bitstream } */ 1.928 + v->granulepos=vb->granulepos; 1.929 + } 1.930 + } 1.931 + 1.932 + /* Update, cleanup */ 1.933 + 1.934 + if(vb->eofflag)v->eofflag=1; 1.935 + return(0); 1.936 + 1.937 +} 1.938 + 1.939 +/* pcm==NULL indicates we just want the pending samples, no more */ 1.940 +int vorbis_synthesis_pcmout(vorbis_dsp_state *v,float ***pcm){ 1.941 + vorbis_info *vi=v->vi; 1.942 + 1.943 + if(v->pcm_returned>-1 && v->pcm_returned<v->pcm_current){ 1.944 + if(pcm){ 1.945 + int i; 1.946 + for(i=0;i<vi->channels;i++) 1.947 + v->pcmret[i]=v->pcm[i]+v->pcm_returned; 1.948 + *pcm=v->pcmret; 1.949 + } 1.950 + return(v->pcm_current-v->pcm_returned); 1.951 + } 1.952 + return(0); 1.953 +} 1.954 + 1.955 +int vorbis_synthesis_read(vorbis_dsp_state *v,int n){ 1.956 + if(n && v->pcm_returned+n>v->pcm_current)return(OV_EINVAL); 1.957 + v->pcm_returned+=n; 1.958 + return(0); 1.959 +} 1.960 + 1.961 +/* intended for use with a specific vorbisfile feature; we want access 1.962 + to the [usually synthetic/postextrapolated] buffer and lapping at 1.963 + the end of a decode cycle, specifically, a half-short-block worth. 1.964 + This funtion works like pcmout above, except it will also expose 1.965 + this implicit buffer data not normally decoded. */ 1.966 +int vorbis_synthesis_lapout(vorbis_dsp_state *v,float ***pcm){ 1.967 + vorbis_info *vi=v->vi; 1.968 + codec_setup_info *ci=vi->codec_setup; 1.969 + int hs=ci->halfrate_flag; 1.970 + 1.971 + int n=ci->blocksizes[v->W]>>(hs+1); 1.972 + int n0=ci->blocksizes[0]>>(hs+1); 1.973 + int n1=ci->blocksizes[1]>>(hs+1); 1.974 + int i,j; 1.975 + 1.976 + if(v->pcm_returned<0)return 0; 1.977 + 1.978 + /* our returned data ends at pcm_returned; because the synthesis pcm 1.979 + buffer is a two-fragment ring, that means our data block may be 1.980 + fragmented by buffering, wrapping or a short block not filling 1.981 + out a buffer. To simplify things, we unfragment if it's at all 1.982 + possibly needed. Otherwise, we'd need to call lapout more than 1.983 + once as well as hold additional dsp state. Opt for 1.984 + simplicity. */ 1.985 + 1.986 + /* centerW was advanced by blockin; it would be the center of the 1.987 + *next* block */ 1.988 + if(v->centerW==n1){ 1.989 + /* the data buffer wraps; swap the halves */ 1.990 + /* slow, sure, small */ 1.991 + for(j=0;j<vi->channels;j++){ 1.992 + float *p=v->pcm[j]; 1.993 + for(i=0;i<n1;i++){ 1.994 + float temp=p[i]; 1.995 + p[i]=p[i+n1]; 1.996 + p[i+n1]=temp; 1.997 + } 1.998 + } 1.999 + 1.1000 + v->pcm_current-=n1; 1.1001 + v->pcm_returned-=n1; 1.1002 + v->centerW=0; 1.1003 + } 1.1004 + 1.1005 + /* solidify buffer into contiguous space */ 1.1006 + if((v->lW^v->W)==1){ 1.1007 + /* long/short or short/long */ 1.1008 + for(j=0;j<vi->channels;j++){ 1.1009 + float *s=v->pcm[j]; 1.1010 + float *d=v->pcm[j]+(n1-n0)/2; 1.1011 + for(i=(n1+n0)/2-1;i>=0;--i) 1.1012 + d[i]=s[i]; 1.1013 + } 1.1014 + v->pcm_returned+=(n1-n0)/2; 1.1015 + v->pcm_current+=(n1-n0)/2; 1.1016 + }else{ 1.1017 + if(v->lW==0){ 1.1018 + /* short/short */ 1.1019 + for(j=0;j<vi->channels;j++){ 1.1020 + float *s=v->pcm[j]; 1.1021 + float *d=v->pcm[j]+n1-n0; 1.1022 + for(i=n0-1;i>=0;--i) 1.1023 + d[i]=s[i]; 1.1024 + } 1.1025 + v->pcm_returned+=n1-n0; 1.1026 + v->pcm_current+=n1-n0; 1.1027 + } 1.1028 + } 1.1029 + 1.1030 + if(pcm){ 1.1031 + int i; 1.1032 + for(i=0;i<vi->channels;i++) 1.1033 + v->pcmret[i]=v->pcm[i]+v->pcm_returned; 1.1034 + *pcm=v->pcmret; 1.1035 + } 1.1036 + 1.1037 + return(n1+n-v->pcm_returned); 1.1038 + 1.1039 +} 1.1040 + 1.1041 +float *vorbis_window(vorbis_dsp_state *v,int W){ 1.1042 + vorbis_info *vi=v->vi; 1.1043 + codec_setup_info *ci=vi->codec_setup; 1.1044 + int hs=ci->halfrate_flag; 1.1045 + private_state *b=v->backend_state; 1.1046 + 1.1047 + if(b->window[W]-1<0)return NULL; 1.1048 + return _vorbis_window_get(b->window[W]-hs); 1.1049 +}