dbf-halloween2015

annotate libs/vorbis/block.c @ 1:c3f5c32cb210

barfed all the libraries in the source tree to make porting easier
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 01 Nov 2015 00:36:56 +0200
parents
children
rev   line source
nuclear@1 1 /********************************************************************
nuclear@1 2 * *
nuclear@1 3 * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
nuclear@1 4 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
nuclear@1 5 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
nuclear@1 6 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
nuclear@1 7 * *
nuclear@1 8 * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 *
nuclear@1 9 * by the Xiph.Org Foundation http://www.xiph.org/ *
nuclear@1 10 * *
nuclear@1 11 ********************************************************************
nuclear@1 12
nuclear@1 13 function: PCM data vector blocking, windowing and dis/reassembly
nuclear@1 14 last mod: $Id: block.c 17561 2010-10-23 10:34:24Z xiphmont $
nuclear@1 15
nuclear@1 16 Handle windowing, overlap-add, etc of the PCM vectors. This is made
nuclear@1 17 more amusing by Vorbis' current two allowed block sizes.
nuclear@1 18
nuclear@1 19 ********************************************************************/
nuclear@1 20
nuclear@1 21 #include <stdio.h>
nuclear@1 22 #include <stdlib.h>
nuclear@1 23 #include <string.h>
nuclear@1 24 #include <ogg/ogg.h>
nuclear@1 25 #include "vorbis/codec.h"
nuclear@1 26 #include "codec_internal.h"
nuclear@1 27
nuclear@1 28 #include "window.h"
nuclear@1 29 #include "mdct.h"
nuclear@1 30 #include "lpc.h"
nuclear@1 31 #include "registry.h"
nuclear@1 32 #include "misc.h"
nuclear@1 33
nuclear@1 34 static int ilog2(unsigned int v){
nuclear@1 35 int ret=0;
nuclear@1 36 if(v)--v;
nuclear@1 37 while(v){
nuclear@1 38 ret++;
nuclear@1 39 v>>=1;
nuclear@1 40 }
nuclear@1 41 return(ret);
nuclear@1 42 }
nuclear@1 43
nuclear@1 44 /* pcm accumulator examples (not exhaustive):
nuclear@1 45
nuclear@1 46 <-------------- lW ---------------->
nuclear@1 47 <--------------- W ---------------->
nuclear@1 48 : .....|..... _______________ |
nuclear@1 49 : .''' | '''_--- | |\ |
nuclear@1 50 :.....''' |_____--- '''......| | \_______|
nuclear@1 51 :.................|__________________|_______|__|______|
nuclear@1 52 |<------ Sl ------>| > Sr < |endW
nuclear@1 53 |beginSl |endSl | |endSr
nuclear@1 54 |beginW |endlW |beginSr
nuclear@1 55
nuclear@1 56
nuclear@1 57 |< lW >|
nuclear@1 58 <--------------- W ---------------->
nuclear@1 59 | | .. ______________ |
nuclear@1 60 | | ' `/ | ---_ |
nuclear@1 61 |___.'___/`. | ---_____|
nuclear@1 62 |_______|__|_______|_________________|
nuclear@1 63 | >|Sl|< |<------ Sr ----->|endW
nuclear@1 64 | | |endSl |beginSr |endSr
nuclear@1 65 |beginW | |endlW
nuclear@1 66 mult[0] |beginSl mult[n]
nuclear@1 67
nuclear@1 68 <-------------- lW ----------------->
nuclear@1 69 |<--W-->|
nuclear@1 70 : .............. ___ | |
nuclear@1 71 : .''' |`/ \ | |
nuclear@1 72 :.....''' |/`....\|...|
nuclear@1 73 :.........................|___|___|___|
nuclear@1 74 |Sl |Sr |endW
nuclear@1 75 | | |endSr
nuclear@1 76 | |beginSr
nuclear@1 77 | |endSl
nuclear@1 78 |beginSl
nuclear@1 79 |beginW
nuclear@1 80 */
nuclear@1 81
nuclear@1 82 /* block abstraction setup *********************************************/
nuclear@1 83
nuclear@1 84 #ifndef WORD_ALIGN
nuclear@1 85 #define WORD_ALIGN 8
nuclear@1 86 #endif
nuclear@1 87
nuclear@1 88 int vorbis_block_init(vorbis_dsp_state *v, vorbis_block *vb){
nuclear@1 89 int i;
nuclear@1 90 memset(vb,0,sizeof(*vb));
nuclear@1 91 vb->vd=v;
nuclear@1 92 vb->localalloc=0;
nuclear@1 93 vb->localstore=NULL;
nuclear@1 94 if(v->analysisp){
nuclear@1 95 vorbis_block_internal *vbi=
nuclear@1 96 vb->internal=_ogg_calloc(1,sizeof(vorbis_block_internal));
nuclear@1 97 vbi->ampmax=-9999;
nuclear@1 98
nuclear@1 99 for(i=0;i<PACKETBLOBS;i++){
nuclear@1 100 if(i==PACKETBLOBS/2){
nuclear@1 101 vbi->packetblob[i]=&vb->opb;
nuclear@1 102 }else{
nuclear@1 103 vbi->packetblob[i]=
nuclear@1 104 _ogg_calloc(1,sizeof(oggpack_buffer));
nuclear@1 105 }
nuclear@1 106 oggpack_writeinit(vbi->packetblob[i]);
nuclear@1 107 }
nuclear@1 108 }
nuclear@1 109
nuclear@1 110 return(0);
nuclear@1 111 }
nuclear@1 112
nuclear@1 113 void *_vorbis_block_alloc(vorbis_block *vb,long bytes){
nuclear@1 114 bytes=(bytes+(WORD_ALIGN-1)) & ~(WORD_ALIGN-1);
nuclear@1 115 if(bytes+vb->localtop>vb->localalloc){
nuclear@1 116 /* can't just _ogg_realloc... there are outstanding pointers */
nuclear@1 117 if(vb->localstore){
nuclear@1 118 struct alloc_chain *link=_ogg_malloc(sizeof(*link));
nuclear@1 119 vb->totaluse+=vb->localtop;
nuclear@1 120 link->next=vb->reap;
nuclear@1 121 link->ptr=vb->localstore;
nuclear@1 122 vb->reap=link;
nuclear@1 123 }
nuclear@1 124 /* highly conservative */
nuclear@1 125 vb->localalloc=bytes;
nuclear@1 126 vb->localstore=_ogg_malloc(vb->localalloc);
nuclear@1 127 vb->localtop=0;
nuclear@1 128 }
nuclear@1 129 {
nuclear@1 130 void *ret=(void *)(((char *)vb->localstore)+vb->localtop);
nuclear@1 131 vb->localtop+=bytes;
nuclear@1 132 return ret;
nuclear@1 133 }
nuclear@1 134 }
nuclear@1 135
nuclear@1 136 /* reap the chain, pull the ripcord */
nuclear@1 137 void _vorbis_block_ripcord(vorbis_block *vb){
nuclear@1 138 /* reap the chain */
nuclear@1 139 struct alloc_chain *reap=vb->reap;
nuclear@1 140 while(reap){
nuclear@1 141 struct alloc_chain *next=reap->next;
nuclear@1 142 _ogg_free(reap->ptr);
nuclear@1 143 memset(reap,0,sizeof(*reap));
nuclear@1 144 _ogg_free(reap);
nuclear@1 145 reap=next;
nuclear@1 146 }
nuclear@1 147 /* consolidate storage */
nuclear@1 148 if(vb->totaluse){
nuclear@1 149 vb->localstore=_ogg_realloc(vb->localstore,vb->totaluse+vb->localalloc);
nuclear@1 150 vb->localalloc+=vb->totaluse;
nuclear@1 151 vb->totaluse=0;
nuclear@1 152 }
nuclear@1 153
nuclear@1 154 /* pull the ripcord */
nuclear@1 155 vb->localtop=0;
nuclear@1 156 vb->reap=NULL;
nuclear@1 157 }
nuclear@1 158
nuclear@1 159 int vorbis_block_clear(vorbis_block *vb){
nuclear@1 160 int i;
nuclear@1 161 vorbis_block_internal *vbi=vb->internal;
nuclear@1 162
nuclear@1 163 _vorbis_block_ripcord(vb);
nuclear@1 164 if(vb->localstore)_ogg_free(vb->localstore);
nuclear@1 165
nuclear@1 166 if(vbi){
nuclear@1 167 for(i=0;i<PACKETBLOBS;i++){
nuclear@1 168 oggpack_writeclear(vbi->packetblob[i]);
nuclear@1 169 if(i!=PACKETBLOBS/2)_ogg_free(vbi->packetblob[i]);
nuclear@1 170 }
nuclear@1 171 _ogg_free(vbi);
nuclear@1 172 }
nuclear@1 173 memset(vb,0,sizeof(*vb));
nuclear@1 174 return(0);
nuclear@1 175 }
nuclear@1 176
nuclear@1 177 /* Analysis side code, but directly related to blocking. Thus it's
nuclear@1 178 here and not in analysis.c (which is for analysis transforms only).
nuclear@1 179 The init is here because some of it is shared */
nuclear@1 180
nuclear@1 181 static int _vds_shared_init(vorbis_dsp_state *v,vorbis_info *vi,int encp){
nuclear@1 182 int i;
nuclear@1 183 codec_setup_info *ci=vi->codec_setup;
nuclear@1 184 private_state *b=NULL;
nuclear@1 185 int hs;
nuclear@1 186
nuclear@1 187 if(ci==NULL) return 1;
nuclear@1 188 hs=ci->halfrate_flag;
nuclear@1 189
nuclear@1 190 memset(v,0,sizeof(*v));
nuclear@1 191 b=v->backend_state=_ogg_calloc(1,sizeof(*b));
nuclear@1 192
nuclear@1 193 v->vi=vi;
nuclear@1 194 b->modebits=ilog2(ci->modes);
nuclear@1 195
nuclear@1 196 b->transform[0]=_ogg_calloc(VI_TRANSFORMB,sizeof(*b->transform[0]));
nuclear@1 197 b->transform[1]=_ogg_calloc(VI_TRANSFORMB,sizeof(*b->transform[1]));
nuclear@1 198
nuclear@1 199 /* MDCT is tranform 0 */
nuclear@1 200
nuclear@1 201 b->transform[0][0]=_ogg_calloc(1,sizeof(mdct_lookup));
nuclear@1 202 b->transform[1][0]=_ogg_calloc(1,sizeof(mdct_lookup));
nuclear@1 203 mdct_init(b->transform[0][0],ci->blocksizes[0]>>hs);
nuclear@1 204 mdct_init(b->transform[1][0],ci->blocksizes[1]>>hs);
nuclear@1 205
nuclear@1 206 /* Vorbis I uses only window type 0 */
nuclear@1 207 b->window[0]=ilog2(ci->blocksizes[0])-6;
nuclear@1 208 b->window[1]=ilog2(ci->blocksizes[1])-6;
nuclear@1 209
nuclear@1 210 if(encp){ /* encode/decode differ here */
nuclear@1 211
nuclear@1 212 /* analysis always needs an fft */
nuclear@1 213 drft_init(&b->fft_look[0],ci->blocksizes[0]);
nuclear@1 214 drft_init(&b->fft_look[1],ci->blocksizes[1]);
nuclear@1 215
nuclear@1 216 /* finish the codebooks */
nuclear@1 217 if(!ci->fullbooks){
nuclear@1 218 ci->fullbooks=_ogg_calloc(ci->books,sizeof(*ci->fullbooks));
nuclear@1 219 for(i=0;i<ci->books;i++)
nuclear@1 220 vorbis_book_init_encode(ci->fullbooks+i,ci->book_param[i]);
nuclear@1 221 }
nuclear@1 222
nuclear@1 223 b->psy=_ogg_calloc(ci->psys,sizeof(*b->psy));
nuclear@1 224 for(i=0;i<ci->psys;i++){
nuclear@1 225 _vp_psy_init(b->psy+i,
nuclear@1 226 ci->psy_param[i],
nuclear@1 227 &ci->psy_g_param,
nuclear@1 228 ci->blocksizes[ci->psy_param[i]->blockflag]/2,
nuclear@1 229 vi->rate);
nuclear@1 230 }
nuclear@1 231
nuclear@1 232 v->analysisp=1;
nuclear@1 233 }else{
nuclear@1 234 /* finish the codebooks */
nuclear@1 235 if(!ci->fullbooks){
nuclear@1 236 ci->fullbooks=_ogg_calloc(ci->books,sizeof(*ci->fullbooks));
nuclear@1 237 for(i=0;i<ci->books;i++){
nuclear@1 238 if(ci->book_param[i]==NULL)
nuclear@1 239 goto abort_books;
nuclear@1 240 if(vorbis_book_init_decode(ci->fullbooks+i,ci->book_param[i]))
nuclear@1 241 goto abort_books;
nuclear@1 242 /* decode codebooks are now standalone after init */
nuclear@1 243 vorbis_staticbook_destroy(ci->book_param[i]);
nuclear@1 244 ci->book_param[i]=NULL;
nuclear@1 245 }
nuclear@1 246 }
nuclear@1 247 }
nuclear@1 248
nuclear@1 249 /* initialize the storage vectors. blocksize[1] is small for encode,
nuclear@1 250 but the correct size for decode */
nuclear@1 251 v->pcm_storage=ci->blocksizes[1];
nuclear@1 252 v->pcm=_ogg_malloc(vi->channels*sizeof(*v->pcm));
nuclear@1 253 v->pcmret=_ogg_malloc(vi->channels*sizeof(*v->pcmret));
nuclear@1 254 {
nuclear@1 255 int i;
nuclear@1 256 for(i=0;i<vi->channels;i++)
nuclear@1 257 v->pcm[i]=_ogg_calloc(v->pcm_storage,sizeof(*v->pcm[i]));
nuclear@1 258 }
nuclear@1 259
nuclear@1 260 /* all 1 (large block) or 0 (small block) */
nuclear@1 261 /* explicitly set for the sake of clarity */
nuclear@1 262 v->lW=0; /* previous window size */
nuclear@1 263 v->W=0; /* current window size */
nuclear@1 264
nuclear@1 265 /* all vector indexes */
nuclear@1 266 v->centerW=ci->blocksizes[1]/2;
nuclear@1 267
nuclear@1 268 v->pcm_current=v->centerW;
nuclear@1 269
nuclear@1 270 /* initialize all the backend lookups */
nuclear@1 271 b->flr=_ogg_calloc(ci->floors,sizeof(*b->flr));
nuclear@1 272 b->residue=_ogg_calloc(ci->residues,sizeof(*b->residue));
nuclear@1 273
nuclear@1 274 for(i=0;i<ci->floors;i++)
nuclear@1 275 b->flr[i]=_floor_P[ci->floor_type[i]]->
nuclear@1 276 look(v,ci->floor_param[i]);
nuclear@1 277
nuclear@1 278 for(i=0;i<ci->residues;i++)
nuclear@1 279 b->residue[i]=_residue_P[ci->residue_type[i]]->
nuclear@1 280 look(v,ci->residue_param[i]);
nuclear@1 281
nuclear@1 282 return 0;
nuclear@1 283 abort_books:
nuclear@1 284 for(i=0;i<ci->books;i++){
nuclear@1 285 if(ci->book_param[i]!=NULL){
nuclear@1 286 vorbis_staticbook_destroy(ci->book_param[i]);
nuclear@1 287 ci->book_param[i]=NULL;
nuclear@1 288 }
nuclear@1 289 }
nuclear@1 290 vorbis_dsp_clear(v);
nuclear@1 291 return -1;
nuclear@1 292 }
nuclear@1 293
nuclear@1 294 /* arbitrary settings and spec-mandated numbers get filled in here */
nuclear@1 295 int vorbis_analysis_init(vorbis_dsp_state *v,vorbis_info *vi){
nuclear@1 296 private_state *b=NULL;
nuclear@1 297
nuclear@1 298 if(_vds_shared_init(v,vi,1))return 1;
nuclear@1 299 b=v->backend_state;
nuclear@1 300 b->psy_g_look=_vp_global_look(vi);
nuclear@1 301
nuclear@1 302 /* Initialize the envelope state storage */
nuclear@1 303 b->ve=_ogg_calloc(1,sizeof(*b->ve));
nuclear@1 304 _ve_envelope_init(b->ve,vi);
nuclear@1 305
nuclear@1 306 vorbis_bitrate_init(vi,&b->bms);
nuclear@1 307
nuclear@1 308 /* compressed audio packets start after the headers
nuclear@1 309 with sequence number 3 */
nuclear@1 310 v->sequence=3;
nuclear@1 311
nuclear@1 312 return(0);
nuclear@1 313 }
nuclear@1 314
nuclear@1 315 void vorbis_dsp_clear(vorbis_dsp_state *v){
nuclear@1 316 int i;
nuclear@1 317 if(v){
nuclear@1 318 vorbis_info *vi=v->vi;
nuclear@1 319 codec_setup_info *ci=(vi?vi->codec_setup:NULL);
nuclear@1 320 private_state *b=v->backend_state;
nuclear@1 321
nuclear@1 322 if(b){
nuclear@1 323
nuclear@1 324 if(b->ve){
nuclear@1 325 _ve_envelope_clear(b->ve);
nuclear@1 326 _ogg_free(b->ve);
nuclear@1 327 }
nuclear@1 328
nuclear@1 329 if(b->transform[0]){
nuclear@1 330 mdct_clear(b->transform[0][0]);
nuclear@1 331 _ogg_free(b->transform[0][0]);
nuclear@1 332 _ogg_free(b->transform[0]);
nuclear@1 333 }
nuclear@1 334 if(b->transform[1]){
nuclear@1 335 mdct_clear(b->transform[1][0]);
nuclear@1 336 _ogg_free(b->transform[1][0]);
nuclear@1 337 _ogg_free(b->transform[1]);
nuclear@1 338 }
nuclear@1 339
nuclear@1 340 if(b->flr){
nuclear@1 341 if(ci)
nuclear@1 342 for(i=0;i<ci->floors;i++)
nuclear@1 343 _floor_P[ci->floor_type[i]]->
nuclear@1 344 free_look(b->flr[i]);
nuclear@1 345 _ogg_free(b->flr);
nuclear@1 346 }
nuclear@1 347 if(b->residue){
nuclear@1 348 if(ci)
nuclear@1 349 for(i=0;i<ci->residues;i++)
nuclear@1 350 _residue_P[ci->residue_type[i]]->
nuclear@1 351 free_look(b->residue[i]);
nuclear@1 352 _ogg_free(b->residue);
nuclear@1 353 }
nuclear@1 354 if(b->psy){
nuclear@1 355 if(ci)
nuclear@1 356 for(i=0;i<ci->psys;i++)
nuclear@1 357 _vp_psy_clear(b->psy+i);
nuclear@1 358 _ogg_free(b->psy);
nuclear@1 359 }
nuclear@1 360
nuclear@1 361 if(b->psy_g_look)_vp_global_free(b->psy_g_look);
nuclear@1 362 vorbis_bitrate_clear(&b->bms);
nuclear@1 363
nuclear@1 364 drft_clear(&b->fft_look[0]);
nuclear@1 365 drft_clear(&b->fft_look[1]);
nuclear@1 366
nuclear@1 367 }
nuclear@1 368
nuclear@1 369 if(v->pcm){
nuclear@1 370 if(vi)
nuclear@1 371 for(i=0;i<vi->channels;i++)
nuclear@1 372 if(v->pcm[i])_ogg_free(v->pcm[i]);
nuclear@1 373 _ogg_free(v->pcm);
nuclear@1 374 if(v->pcmret)_ogg_free(v->pcmret);
nuclear@1 375 }
nuclear@1 376
nuclear@1 377 if(b){
nuclear@1 378 /* free header, header1, header2 */
nuclear@1 379 if(b->header)_ogg_free(b->header);
nuclear@1 380 if(b->header1)_ogg_free(b->header1);
nuclear@1 381 if(b->header2)_ogg_free(b->header2);
nuclear@1 382 _ogg_free(b);
nuclear@1 383 }
nuclear@1 384
nuclear@1 385 memset(v,0,sizeof(*v));
nuclear@1 386 }
nuclear@1 387 }
nuclear@1 388
nuclear@1 389 float **vorbis_analysis_buffer(vorbis_dsp_state *v, int vals){
nuclear@1 390 int i;
nuclear@1 391 vorbis_info *vi=v->vi;
nuclear@1 392 private_state *b=v->backend_state;
nuclear@1 393
nuclear@1 394 /* free header, header1, header2 */
nuclear@1 395 if(b->header)_ogg_free(b->header);b->header=NULL;
nuclear@1 396 if(b->header1)_ogg_free(b->header1);b->header1=NULL;
nuclear@1 397 if(b->header2)_ogg_free(b->header2);b->header2=NULL;
nuclear@1 398
nuclear@1 399 /* Do we have enough storage space for the requested buffer? If not,
nuclear@1 400 expand the PCM (and envelope) storage */
nuclear@1 401
nuclear@1 402 if(v->pcm_current+vals>=v->pcm_storage){
nuclear@1 403 v->pcm_storage=v->pcm_current+vals*2;
nuclear@1 404
nuclear@1 405 for(i=0;i<vi->channels;i++){
nuclear@1 406 v->pcm[i]=_ogg_realloc(v->pcm[i],v->pcm_storage*sizeof(*v->pcm[i]));
nuclear@1 407 }
nuclear@1 408 }
nuclear@1 409
nuclear@1 410 for(i=0;i<vi->channels;i++)
nuclear@1 411 v->pcmret[i]=v->pcm[i]+v->pcm_current;
nuclear@1 412
nuclear@1 413 return(v->pcmret);
nuclear@1 414 }
nuclear@1 415
nuclear@1 416 static void _preextrapolate_helper(vorbis_dsp_state *v){
nuclear@1 417 int i;
nuclear@1 418 int order=16;
nuclear@1 419 float *lpc=alloca(order*sizeof(*lpc));
nuclear@1 420 float *work=alloca(v->pcm_current*sizeof(*work));
nuclear@1 421 long j;
nuclear@1 422 v->preextrapolate=1;
nuclear@1 423
nuclear@1 424 if(v->pcm_current-v->centerW>order*2){ /* safety */
nuclear@1 425 for(i=0;i<v->vi->channels;i++){
nuclear@1 426 /* need to run the extrapolation in reverse! */
nuclear@1 427 for(j=0;j<v->pcm_current;j++)
nuclear@1 428 work[j]=v->pcm[i][v->pcm_current-j-1];
nuclear@1 429
nuclear@1 430 /* prime as above */
nuclear@1 431 vorbis_lpc_from_data(work,lpc,v->pcm_current-v->centerW,order);
nuclear@1 432
nuclear@1 433 #if 0
nuclear@1 434 if(v->vi->channels==2){
nuclear@1 435 if(i==0)
nuclear@1 436 _analysis_output("predataL",0,work,v->pcm_current-v->centerW,0,0,0);
nuclear@1 437 else
nuclear@1 438 _analysis_output("predataR",0,work,v->pcm_current-v->centerW,0,0,0);
nuclear@1 439 }else{
nuclear@1 440 _analysis_output("predata",0,work,v->pcm_current-v->centerW,0,0,0);
nuclear@1 441 }
nuclear@1 442 #endif
nuclear@1 443
nuclear@1 444 /* run the predictor filter */
nuclear@1 445 vorbis_lpc_predict(lpc,work+v->pcm_current-v->centerW-order,
nuclear@1 446 order,
nuclear@1 447 work+v->pcm_current-v->centerW,
nuclear@1 448 v->centerW);
nuclear@1 449
nuclear@1 450 for(j=0;j<v->pcm_current;j++)
nuclear@1 451 v->pcm[i][v->pcm_current-j-1]=work[j];
nuclear@1 452
nuclear@1 453 }
nuclear@1 454 }
nuclear@1 455 }
nuclear@1 456
nuclear@1 457
nuclear@1 458 /* call with val<=0 to set eof */
nuclear@1 459
nuclear@1 460 int vorbis_analysis_wrote(vorbis_dsp_state *v, int vals){
nuclear@1 461 vorbis_info *vi=v->vi;
nuclear@1 462 codec_setup_info *ci=vi->codec_setup;
nuclear@1 463
nuclear@1 464 if(vals<=0){
nuclear@1 465 int order=32;
nuclear@1 466 int i;
nuclear@1 467 float *lpc=alloca(order*sizeof(*lpc));
nuclear@1 468
nuclear@1 469 /* if it wasn't done earlier (very short sample) */
nuclear@1 470 if(!v->preextrapolate)
nuclear@1 471 _preextrapolate_helper(v);
nuclear@1 472
nuclear@1 473 /* We're encoding the end of the stream. Just make sure we have
nuclear@1 474 [at least] a few full blocks of zeroes at the end. */
nuclear@1 475 /* actually, we don't want zeroes; that could drop a large
nuclear@1 476 amplitude off a cliff, creating spread spectrum noise that will
nuclear@1 477 suck to encode. Extrapolate for the sake of cleanliness. */
nuclear@1 478
nuclear@1 479 vorbis_analysis_buffer(v,ci->blocksizes[1]*3);
nuclear@1 480 v->eofflag=v->pcm_current;
nuclear@1 481 v->pcm_current+=ci->blocksizes[1]*3;
nuclear@1 482
nuclear@1 483 for(i=0;i<vi->channels;i++){
nuclear@1 484 if(v->eofflag>order*2){
nuclear@1 485 /* extrapolate with LPC to fill in */
nuclear@1 486 long n;
nuclear@1 487
nuclear@1 488 /* make a predictor filter */
nuclear@1 489 n=v->eofflag;
nuclear@1 490 if(n>ci->blocksizes[1])n=ci->blocksizes[1];
nuclear@1 491 vorbis_lpc_from_data(v->pcm[i]+v->eofflag-n,lpc,n,order);
nuclear@1 492
nuclear@1 493 /* run the predictor filter */
nuclear@1 494 vorbis_lpc_predict(lpc,v->pcm[i]+v->eofflag-order,order,
nuclear@1 495 v->pcm[i]+v->eofflag,v->pcm_current-v->eofflag);
nuclear@1 496 }else{
nuclear@1 497 /* not enough data to extrapolate (unlikely to happen due to
nuclear@1 498 guarding the overlap, but bulletproof in case that
nuclear@1 499 assumtion goes away). zeroes will do. */
nuclear@1 500 memset(v->pcm[i]+v->eofflag,0,
nuclear@1 501 (v->pcm_current-v->eofflag)*sizeof(*v->pcm[i]));
nuclear@1 502
nuclear@1 503 }
nuclear@1 504 }
nuclear@1 505 }else{
nuclear@1 506
nuclear@1 507 if(v->pcm_current+vals>v->pcm_storage)
nuclear@1 508 return(OV_EINVAL);
nuclear@1 509
nuclear@1 510 v->pcm_current+=vals;
nuclear@1 511
nuclear@1 512 /* we may want to reverse extrapolate the beginning of a stream
nuclear@1 513 too... in case we're beginning on a cliff! */
nuclear@1 514 /* clumsy, but simple. It only runs once, so simple is good. */
nuclear@1 515 if(!v->preextrapolate && v->pcm_current-v->centerW>ci->blocksizes[1])
nuclear@1 516 _preextrapolate_helper(v);
nuclear@1 517
nuclear@1 518 }
nuclear@1 519 return(0);
nuclear@1 520 }
nuclear@1 521
nuclear@1 522 /* do the deltas, envelope shaping, pre-echo and determine the size of
nuclear@1 523 the next block on which to continue analysis */
nuclear@1 524 int vorbis_analysis_blockout(vorbis_dsp_state *v,vorbis_block *vb){
nuclear@1 525 int i;
nuclear@1 526 vorbis_info *vi=v->vi;
nuclear@1 527 codec_setup_info *ci=vi->codec_setup;
nuclear@1 528 private_state *b=v->backend_state;
nuclear@1 529 vorbis_look_psy_global *g=b->psy_g_look;
nuclear@1 530 long beginW=v->centerW-ci->blocksizes[v->W]/2,centerNext;
nuclear@1 531 vorbis_block_internal *vbi=(vorbis_block_internal *)vb->internal;
nuclear@1 532
nuclear@1 533 /* check to see if we're started... */
nuclear@1 534 if(!v->preextrapolate)return(0);
nuclear@1 535
nuclear@1 536 /* check to see if we're done... */
nuclear@1 537 if(v->eofflag==-1)return(0);
nuclear@1 538
nuclear@1 539 /* By our invariant, we have lW, W and centerW set. Search for
nuclear@1 540 the next boundary so we can determine nW (the next window size)
nuclear@1 541 which lets us compute the shape of the current block's window */
nuclear@1 542
nuclear@1 543 /* we do an envelope search even on a single blocksize; we may still
nuclear@1 544 be throwing more bits at impulses, and envelope search handles
nuclear@1 545 marking impulses too. */
nuclear@1 546 {
nuclear@1 547 long bp=_ve_envelope_search(v);
nuclear@1 548 if(bp==-1){
nuclear@1 549
nuclear@1 550 if(v->eofflag==0)return(0); /* not enough data currently to search for a
nuclear@1 551 full long block */
nuclear@1 552 v->nW=0;
nuclear@1 553 }else{
nuclear@1 554
nuclear@1 555 if(ci->blocksizes[0]==ci->blocksizes[1])
nuclear@1 556 v->nW=0;
nuclear@1 557 else
nuclear@1 558 v->nW=bp;
nuclear@1 559 }
nuclear@1 560 }
nuclear@1 561
nuclear@1 562 centerNext=v->centerW+ci->blocksizes[v->W]/4+ci->blocksizes[v->nW]/4;
nuclear@1 563
nuclear@1 564 {
nuclear@1 565 /* center of next block + next block maximum right side. */
nuclear@1 566
nuclear@1 567 long blockbound=centerNext+ci->blocksizes[v->nW]/2;
nuclear@1 568 if(v->pcm_current<blockbound)return(0); /* not enough data yet;
nuclear@1 569 although this check is
nuclear@1 570 less strict that the
nuclear@1 571 _ve_envelope_search,
nuclear@1 572 the search is not run
nuclear@1 573 if we only use one
nuclear@1 574 block size */
nuclear@1 575
nuclear@1 576
nuclear@1 577 }
nuclear@1 578
nuclear@1 579 /* fill in the block. Note that for a short window, lW and nW are *short*
nuclear@1 580 regardless of actual settings in the stream */
nuclear@1 581
nuclear@1 582 _vorbis_block_ripcord(vb);
nuclear@1 583 vb->lW=v->lW;
nuclear@1 584 vb->W=v->W;
nuclear@1 585 vb->nW=v->nW;
nuclear@1 586
nuclear@1 587 if(v->W){
nuclear@1 588 if(!v->lW || !v->nW){
nuclear@1 589 vbi->blocktype=BLOCKTYPE_TRANSITION;
nuclear@1 590 /*fprintf(stderr,"-");*/
nuclear@1 591 }else{
nuclear@1 592 vbi->blocktype=BLOCKTYPE_LONG;
nuclear@1 593 /*fprintf(stderr,"_");*/
nuclear@1 594 }
nuclear@1 595 }else{
nuclear@1 596 if(_ve_envelope_mark(v)){
nuclear@1 597 vbi->blocktype=BLOCKTYPE_IMPULSE;
nuclear@1 598 /*fprintf(stderr,"|");*/
nuclear@1 599
nuclear@1 600 }else{
nuclear@1 601 vbi->blocktype=BLOCKTYPE_PADDING;
nuclear@1 602 /*fprintf(stderr,".");*/
nuclear@1 603
nuclear@1 604 }
nuclear@1 605 }
nuclear@1 606
nuclear@1 607 vb->vd=v;
nuclear@1 608 vb->sequence=v->sequence++;
nuclear@1 609 vb->granulepos=v->granulepos;
nuclear@1 610 vb->pcmend=ci->blocksizes[v->W];
nuclear@1 611
nuclear@1 612 /* copy the vectors; this uses the local storage in vb */
nuclear@1 613
nuclear@1 614 /* this tracks 'strongest peak' for later psychoacoustics */
nuclear@1 615 /* moved to the global psy state; clean this mess up */
nuclear@1 616 if(vbi->ampmax>g->ampmax)g->ampmax=vbi->ampmax;
nuclear@1 617 g->ampmax=_vp_ampmax_decay(g->ampmax,v);
nuclear@1 618 vbi->ampmax=g->ampmax;
nuclear@1 619
nuclear@1 620 vb->pcm=_vorbis_block_alloc(vb,sizeof(*vb->pcm)*vi->channels);
nuclear@1 621 vbi->pcmdelay=_vorbis_block_alloc(vb,sizeof(*vbi->pcmdelay)*vi->channels);
nuclear@1 622 for(i=0;i<vi->channels;i++){
nuclear@1 623 vbi->pcmdelay[i]=
nuclear@1 624 _vorbis_block_alloc(vb,(vb->pcmend+beginW)*sizeof(*vbi->pcmdelay[i]));
nuclear@1 625 memcpy(vbi->pcmdelay[i],v->pcm[i],(vb->pcmend+beginW)*sizeof(*vbi->pcmdelay[i]));
nuclear@1 626 vb->pcm[i]=vbi->pcmdelay[i]+beginW;
nuclear@1 627
nuclear@1 628 /* before we added the delay
nuclear@1 629 vb->pcm[i]=_vorbis_block_alloc(vb,vb->pcmend*sizeof(*vb->pcm[i]));
nuclear@1 630 memcpy(vb->pcm[i],v->pcm[i]+beginW,ci->blocksizes[v->W]*sizeof(*vb->pcm[i]));
nuclear@1 631 */
nuclear@1 632
nuclear@1 633 }
nuclear@1 634
nuclear@1 635 /* handle eof detection: eof==0 means that we've not yet received EOF
nuclear@1 636 eof>0 marks the last 'real' sample in pcm[]
nuclear@1 637 eof<0 'no more to do'; doesn't get here */
nuclear@1 638
nuclear@1 639 if(v->eofflag){
nuclear@1 640 if(v->centerW>=v->eofflag){
nuclear@1 641 v->eofflag=-1;
nuclear@1 642 vb->eofflag=1;
nuclear@1 643 return(1);
nuclear@1 644 }
nuclear@1 645 }
nuclear@1 646
nuclear@1 647 /* advance storage vectors and clean up */
nuclear@1 648 {
nuclear@1 649 int new_centerNext=ci->blocksizes[1]/2;
nuclear@1 650 int movementW=centerNext-new_centerNext;
nuclear@1 651
nuclear@1 652 if(movementW>0){
nuclear@1 653
nuclear@1 654 _ve_envelope_shift(b->ve,movementW);
nuclear@1 655 v->pcm_current-=movementW;
nuclear@1 656
nuclear@1 657 for(i=0;i<vi->channels;i++)
nuclear@1 658 memmove(v->pcm[i],v->pcm[i]+movementW,
nuclear@1 659 v->pcm_current*sizeof(*v->pcm[i]));
nuclear@1 660
nuclear@1 661
nuclear@1 662 v->lW=v->W;
nuclear@1 663 v->W=v->nW;
nuclear@1 664 v->centerW=new_centerNext;
nuclear@1 665
nuclear@1 666 if(v->eofflag){
nuclear@1 667 v->eofflag-=movementW;
nuclear@1 668 if(v->eofflag<=0)v->eofflag=-1;
nuclear@1 669 /* do not add padding to end of stream! */
nuclear@1 670 if(v->centerW>=v->eofflag){
nuclear@1 671 v->granulepos+=movementW-(v->centerW-v->eofflag);
nuclear@1 672 }else{
nuclear@1 673 v->granulepos+=movementW;
nuclear@1 674 }
nuclear@1 675 }else{
nuclear@1 676 v->granulepos+=movementW;
nuclear@1 677 }
nuclear@1 678 }
nuclear@1 679 }
nuclear@1 680
nuclear@1 681 /* done */
nuclear@1 682 return(1);
nuclear@1 683 }
nuclear@1 684
nuclear@1 685 int vorbis_synthesis_restart(vorbis_dsp_state *v){
nuclear@1 686 vorbis_info *vi=v->vi;
nuclear@1 687 codec_setup_info *ci;
nuclear@1 688 int hs;
nuclear@1 689
nuclear@1 690 if(!v->backend_state)return -1;
nuclear@1 691 if(!vi)return -1;
nuclear@1 692 ci=vi->codec_setup;
nuclear@1 693 if(!ci)return -1;
nuclear@1 694 hs=ci->halfrate_flag;
nuclear@1 695
nuclear@1 696 v->centerW=ci->blocksizes[1]>>(hs+1);
nuclear@1 697 v->pcm_current=v->centerW>>hs;
nuclear@1 698
nuclear@1 699 v->pcm_returned=-1;
nuclear@1 700 v->granulepos=-1;
nuclear@1 701 v->sequence=-1;
nuclear@1 702 v->eofflag=0;
nuclear@1 703 ((private_state *)(v->backend_state))->sample_count=-1;
nuclear@1 704
nuclear@1 705 return(0);
nuclear@1 706 }
nuclear@1 707
nuclear@1 708 int vorbis_synthesis_init(vorbis_dsp_state *v,vorbis_info *vi){
nuclear@1 709 if(_vds_shared_init(v,vi,0)){
nuclear@1 710 vorbis_dsp_clear(v);
nuclear@1 711 return 1;
nuclear@1 712 }
nuclear@1 713 vorbis_synthesis_restart(v);
nuclear@1 714 return 0;
nuclear@1 715 }
nuclear@1 716
nuclear@1 717 /* Unlike in analysis, the window is only partially applied for each
nuclear@1 718 block. The time domain envelope is not yet handled at the point of
nuclear@1 719 calling (as it relies on the previous block). */
nuclear@1 720
nuclear@1 721 int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb){
nuclear@1 722 vorbis_info *vi=v->vi;
nuclear@1 723 codec_setup_info *ci=vi->codec_setup;
nuclear@1 724 private_state *b=v->backend_state;
nuclear@1 725 int hs=ci->halfrate_flag;
nuclear@1 726 int i,j;
nuclear@1 727
nuclear@1 728 if(!vb)return(OV_EINVAL);
nuclear@1 729 if(v->pcm_current>v->pcm_returned && v->pcm_returned!=-1)return(OV_EINVAL);
nuclear@1 730
nuclear@1 731 v->lW=v->W;
nuclear@1 732 v->W=vb->W;
nuclear@1 733 v->nW=-1;
nuclear@1 734
nuclear@1 735 if((v->sequence==-1)||
nuclear@1 736 (v->sequence+1 != vb->sequence)){
nuclear@1 737 v->granulepos=-1; /* out of sequence; lose count */
nuclear@1 738 b->sample_count=-1;
nuclear@1 739 }
nuclear@1 740
nuclear@1 741 v->sequence=vb->sequence;
nuclear@1 742
nuclear@1 743 if(vb->pcm){ /* no pcm to process if vorbis_synthesis_trackonly
nuclear@1 744 was called on block */
nuclear@1 745 int n=ci->blocksizes[v->W]>>(hs+1);
nuclear@1 746 int n0=ci->blocksizes[0]>>(hs+1);
nuclear@1 747 int n1=ci->blocksizes[1]>>(hs+1);
nuclear@1 748
nuclear@1 749 int thisCenter;
nuclear@1 750 int prevCenter;
nuclear@1 751
nuclear@1 752 v->glue_bits+=vb->glue_bits;
nuclear@1 753 v->time_bits+=vb->time_bits;
nuclear@1 754 v->floor_bits+=vb->floor_bits;
nuclear@1 755 v->res_bits+=vb->res_bits;
nuclear@1 756
nuclear@1 757 if(v->centerW){
nuclear@1 758 thisCenter=n1;
nuclear@1 759 prevCenter=0;
nuclear@1 760 }else{
nuclear@1 761 thisCenter=0;
nuclear@1 762 prevCenter=n1;
nuclear@1 763 }
nuclear@1 764
nuclear@1 765 /* v->pcm is now used like a two-stage double buffer. We don't want
nuclear@1 766 to have to constantly shift *or* adjust memory usage. Don't
nuclear@1 767 accept a new block until the old is shifted out */
nuclear@1 768
nuclear@1 769 for(j=0;j<vi->channels;j++){
nuclear@1 770 /* the overlap/add section */
nuclear@1 771 if(v->lW){
nuclear@1 772 if(v->W){
nuclear@1 773 /* large/large */
nuclear@1 774 float *w=_vorbis_window_get(b->window[1]-hs);
nuclear@1 775 float *pcm=v->pcm[j]+prevCenter;
nuclear@1 776 float *p=vb->pcm[j];
nuclear@1 777 for(i=0;i<n1;i++)
nuclear@1 778 pcm[i]=pcm[i]*w[n1-i-1] + p[i]*w[i];
nuclear@1 779 }else{
nuclear@1 780 /* large/small */
nuclear@1 781 float *w=_vorbis_window_get(b->window[0]-hs);
nuclear@1 782 float *pcm=v->pcm[j]+prevCenter+n1/2-n0/2;
nuclear@1 783 float *p=vb->pcm[j];
nuclear@1 784 for(i=0;i<n0;i++)
nuclear@1 785 pcm[i]=pcm[i]*w[n0-i-1] +p[i]*w[i];
nuclear@1 786 }
nuclear@1 787 }else{
nuclear@1 788 if(v->W){
nuclear@1 789 /* small/large */
nuclear@1 790 float *w=_vorbis_window_get(b->window[0]-hs);
nuclear@1 791 float *pcm=v->pcm[j]+prevCenter;
nuclear@1 792 float *p=vb->pcm[j]+n1/2-n0/2;
nuclear@1 793 for(i=0;i<n0;i++)
nuclear@1 794 pcm[i]=pcm[i]*w[n0-i-1] +p[i]*w[i];
nuclear@1 795 for(;i<n1/2+n0/2;i++)
nuclear@1 796 pcm[i]=p[i];
nuclear@1 797 }else{
nuclear@1 798 /* small/small */
nuclear@1 799 float *w=_vorbis_window_get(b->window[0]-hs);
nuclear@1 800 float *pcm=v->pcm[j]+prevCenter;
nuclear@1 801 float *p=vb->pcm[j];
nuclear@1 802 for(i=0;i<n0;i++)
nuclear@1 803 pcm[i]=pcm[i]*w[n0-i-1] +p[i]*w[i];
nuclear@1 804 }
nuclear@1 805 }
nuclear@1 806
nuclear@1 807 /* the copy section */
nuclear@1 808 {
nuclear@1 809 float *pcm=v->pcm[j]+thisCenter;
nuclear@1 810 float *p=vb->pcm[j]+n;
nuclear@1 811 for(i=0;i<n;i++)
nuclear@1 812 pcm[i]=p[i];
nuclear@1 813 }
nuclear@1 814 }
nuclear@1 815
nuclear@1 816 if(v->centerW)
nuclear@1 817 v->centerW=0;
nuclear@1 818 else
nuclear@1 819 v->centerW=n1;
nuclear@1 820
nuclear@1 821 /* deal with initial packet state; we do this using the explicit
nuclear@1 822 pcm_returned==-1 flag otherwise we're sensitive to first block
nuclear@1 823 being short or long */
nuclear@1 824
nuclear@1 825 if(v->pcm_returned==-1){
nuclear@1 826 v->pcm_returned=thisCenter;
nuclear@1 827 v->pcm_current=thisCenter;
nuclear@1 828 }else{
nuclear@1 829 v->pcm_returned=prevCenter;
nuclear@1 830 v->pcm_current=prevCenter+
nuclear@1 831 ((ci->blocksizes[v->lW]/4+
nuclear@1 832 ci->blocksizes[v->W]/4)>>hs);
nuclear@1 833 }
nuclear@1 834
nuclear@1 835 }
nuclear@1 836
nuclear@1 837 /* track the frame number... This is for convenience, but also
nuclear@1 838 making sure our last packet doesn't end with added padding. If
nuclear@1 839 the last packet is partial, the number of samples we'll have to
nuclear@1 840 return will be past the vb->granulepos.
nuclear@1 841
nuclear@1 842 This is not foolproof! It will be confused if we begin
nuclear@1 843 decoding at the last page after a seek or hole. In that case,
nuclear@1 844 we don't have a starting point to judge where the last frame
nuclear@1 845 is. For this reason, vorbisfile will always try to make sure
nuclear@1 846 it reads the last two marked pages in proper sequence */
nuclear@1 847
nuclear@1 848 if(b->sample_count==-1){
nuclear@1 849 b->sample_count=0;
nuclear@1 850 }else{
nuclear@1 851 b->sample_count+=ci->blocksizes[v->lW]/4+ci->blocksizes[v->W]/4;
nuclear@1 852 }
nuclear@1 853
nuclear@1 854 if(v->granulepos==-1){
nuclear@1 855 if(vb->granulepos!=-1){ /* only set if we have a position to set to */
nuclear@1 856
nuclear@1 857 v->granulepos=vb->granulepos;
nuclear@1 858
nuclear@1 859 /* is this a short page? */
nuclear@1 860 if(b->sample_count>v->granulepos){
nuclear@1 861 /* corner case; if this is both the first and last audio page,
nuclear@1 862 then spec says the end is cut, not beginning */
nuclear@1 863 long extra=b->sample_count-vb->granulepos;
nuclear@1 864
nuclear@1 865 /* we use ogg_int64_t for granule positions because a
nuclear@1 866 uint64 isn't universally available. Unfortunately,
nuclear@1 867 that means granposes can be 'negative' and result in
nuclear@1 868 extra being negative */
nuclear@1 869 if(extra<0)
nuclear@1 870 extra=0;
nuclear@1 871
nuclear@1 872 if(vb->eofflag){
nuclear@1 873 /* trim the end */
nuclear@1 874 /* no preceding granulepos; assume we started at zero (we'd
nuclear@1 875 have to in a short single-page stream) */
nuclear@1 876 /* granulepos could be -1 due to a seek, but that would result
nuclear@1 877 in a long count, not short count */
nuclear@1 878
nuclear@1 879 /* Guard against corrupt/malicious frames that set EOP and
nuclear@1 880 a backdated granpos; don't rewind more samples than we
nuclear@1 881 actually have */
nuclear@1 882 if(extra > (v->pcm_current - v->pcm_returned)<<hs)
nuclear@1 883 extra = (v->pcm_current - v->pcm_returned)<<hs;
nuclear@1 884
nuclear@1 885 v->pcm_current-=extra>>hs;
nuclear@1 886 }else{
nuclear@1 887 /* trim the beginning */
nuclear@1 888 v->pcm_returned+=extra>>hs;
nuclear@1 889 if(v->pcm_returned>v->pcm_current)
nuclear@1 890 v->pcm_returned=v->pcm_current;
nuclear@1 891 }
nuclear@1 892
nuclear@1 893 }
nuclear@1 894
nuclear@1 895 }
nuclear@1 896 }else{
nuclear@1 897 v->granulepos+=ci->blocksizes[v->lW]/4+ci->blocksizes[v->W]/4;
nuclear@1 898 if(vb->granulepos!=-1 && v->granulepos!=vb->granulepos){
nuclear@1 899
nuclear@1 900 if(v->granulepos>vb->granulepos){
nuclear@1 901 long extra=v->granulepos-vb->granulepos;
nuclear@1 902
nuclear@1 903 if(extra)
nuclear@1 904 if(vb->eofflag){
nuclear@1 905 /* partial last frame. Strip the extra samples off */
nuclear@1 906
nuclear@1 907 /* Guard against corrupt/malicious frames that set EOP and
nuclear@1 908 a backdated granpos; don't rewind more samples than we
nuclear@1 909 actually have */
nuclear@1 910 if(extra > (v->pcm_current - v->pcm_returned)<<hs)
nuclear@1 911 extra = (v->pcm_current - v->pcm_returned)<<hs;
nuclear@1 912
nuclear@1 913 /* we use ogg_int64_t for granule positions because a
nuclear@1 914 uint64 isn't universally available. Unfortunately,
nuclear@1 915 that means granposes can be 'negative' and result in
nuclear@1 916 extra being negative */
nuclear@1 917 if(extra<0)
nuclear@1 918 extra=0;
nuclear@1 919
nuclear@1 920 v->pcm_current-=extra>>hs;
nuclear@1 921 } /* else {Shouldn't happen *unless* the bitstream is out of
nuclear@1 922 spec. Either way, believe the bitstream } */
nuclear@1 923 } /* else {Shouldn't happen *unless* the bitstream is out of
nuclear@1 924 spec. Either way, believe the bitstream } */
nuclear@1 925 v->granulepos=vb->granulepos;
nuclear@1 926 }
nuclear@1 927 }
nuclear@1 928
nuclear@1 929 /* Update, cleanup */
nuclear@1 930
nuclear@1 931 if(vb->eofflag)v->eofflag=1;
nuclear@1 932 return(0);
nuclear@1 933
nuclear@1 934 }
nuclear@1 935
nuclear@1 936 /* pcm==NULL indicates we just want the pending samples, no more */
nuclear@1 937 int vorbis_synthesis_pcmout(vorbis_dsp_state *v,float ***pcm){
nuclear@1 938 vorbis_info *vi=v->vi;
nuclear@1 939
nuclear@1 940 if(v->pcm_returned>-1 && v->pcm_returned<v->pcm_current){
nuclear@1 941 if(pcm){
nuclear@1 942 int i;
nuclear@1 943 for(i=0;i<vi->channels;i++)
nuclear@1 944 v->pcmret[i]=v->pcm[i]+v->pcm_returned;
nuclear@1 945 *pcm=v->pcmret;
nuclear@1 946 }
nuclear@1 947 return(v->pcm_current-v->pcm_returned);
nuclear@1 948 }
nuclear@1 949 return(0);
nuclear@1 950 }
nuclear@1 951
nuclear@1 952 int vorbis_synthesis_read(vorbis_dsp_state *v,int n){
nuclear@1 953 if(n && v->pcm_returned+n>v->pcm_current)return(OV_EINVAL);
nuclear@1 954 v->pcm_returned+=n;
nuclear@1 955 return(0);
nuclear@1 956 }
nuclear@1 957
nuclear@1 958 /* intended for use with a specific vorbisfile feature; we want access
nuclear@1 959 to the [usually synthetic/postextrapolated] buffer and lapping at
nuclear@1 960 the end of a decode cycle, specifically, a half-short-block worth.
nuclear@1 961 This funtion works like pcmout above, except it will also expose
nuclear@1 962 this implicit buffer data not normally decoded. */
nuclear@1 963 int vorbis_synthesis_lapout(vorbis_dsp_state *v,float ***pcm){
nuclear@1 964 vorbis_info *vi=v->vi;
nuclear@1 965 codec_setup_info *ci=vi->codec_setup;
nuclear@1 966 int hs=ci->halfrate_flag;
nuclear@1 967
nuclear@1 968 int n=ci->blocksizes[v->W]>>(hs+1);
nuclear@1 969 int n0=ci->blocksizes[0]>>(hs+1);
nuclear@1 970 int n1=ci->blocksizes[1]>>(hs+1);
nuclear@1 971 int i,j;
nuclear@1 972
nuclear@1 973 if(v->pcm_returned<0)return 0;
nuclear@1 974
nuclear@1 975 /* our returned data ends at pcm_returned; because the synthesis pcm
nuclear@1 976 buffer is a two-fragment ring, that means our data block may be
nuclear@1 977 fragmented by buffering, wrapping or a short block not filling
nuclear@1 978 out a buffer. To simplify things, we unfragment if it's at all
nuclear@1 979 possibly needed. Otherwise, we'd need to call lapout more than
nuclear@1 980 once as well as hold additional dsp state. Opt for
nuclear@1 981 simplicity. */
nuclear@1 982
nuclear@1 983 /* centerW was advanced by blockin; it would be the center of the
nuclear@1 984 *next* block */
nuclear@1 985 if(v->centerW==n1){
nuclear@1 986 /* the data buffer wraps; swap the halves */
nuclear@1 987 /* slow, sure, small */
nuclear@1 988 for(j=0;j<vi->channels;j++){
nuclear@1 989 float *p=v->pcm[j];
nuclear@1 990 for(i=0;i<n1;i++){
nuclear@1 991 float temp=p[i];
nuclear@1 992 p[i]=p[i+n1];
nuclear@1 993 p[i+n1]=temp;
nuclear@1 994 }
nuclear@1 995 }
nuclear@1 996
nuclear@1 997 v->pcm_current-=n1;
nuclear@1 998 v->pcm_returned-=n1;
nuclear@1 999 v->centerW=0;
nuclear@1 1000 }
nuclear@1 1001
nuclear@1 1002 /* solidify buffer into contiguous space */
nuclear@1 1003 if((v->lW^v->W)==1){
nuclear@1 1004 /* long/short or short/long */
nuclear@1 1005 for(j=0;j<vi->channels;j++){
nuclear@1 1006 float *s=v->pcm[j];
nuclear@1 1007 float *d=v->pcm[j]+(n1-n0)/2;
nuclear@1 1008 for(i=(n1+n0)/2-1;i>=0;--i)
nuclear@1 1009 d[i]=s[i];
nuclear@1 1010 }
nuclear@1 1011 v->pcm_returned+=(n1-n0)/2;
nuclear@1 1012 v->pcm_current+=(n1-n0)/2;
nuclear@1 1013 }else{
nuclear@1 1014 if(v->lW==0){
nuclear@1 1015 /* short/short */
nuclear@1 1016 for(j=0;j<vi->channels;j++){
nuclear@1 1017 float *s=v->pcm[j];
nuclear@1 1018 float *d=v->pcm[j]+n1-n0;
nuclear@1 1019 for(i=n0-1;i>=0;--i)
nuclear@1 1020 d[i]=s[i];
nuclear@1 1021 }
nuclear@1 1022 v->pcm_returned+=n1-n0;
nuclear@1 1023 v->pcm_current+=n1-n0;
nuclear@1 1024 }
nuclear@1 1025 }
nuclear@1 1026
nuclear@1 1027 if(pcm){
nuclear@1 1028 int i;
nuclear@1 1029 for(i=0;i<vi->channels;i++)
nuclear@1 1030 v->pcmret[i]=v->pcm[i]+v->pcm_returned;
nuclear@1 1031 *pcm=v->pcmret;
nuclear@1 1032 }
nuclear@1 1033
nuclear@1 1034 return(n1+n-v->pcm_returned);
nuclear@1 1035
nuclear@1 1036 }
nuclear@1 1037
nuclear@1 1038 float *vorbis_window(vorbis_dsp_state *v,int W){
nuclear@1 1039 vorbis_info *vi=v->vi;
nuclear@1 1040 codec_setup_info *ci=vi->codec_setup;
nuclear@1 1041 int hs=ci->halfrate_flag;
nuclear@1 1042 private_state *b=v->backend_state;
nuclear@1 1043
nuclear@1 1044 if(b->window[W]-1<0)return NULL;
nuclear@1 1045 return _vorbis_window_get(b->window[W]-hs);
nuclear@1 1046 }