annotate src/libvorbis-1.3.3/lib/block.c @ 79:91c729825bca pa_catalina

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