vrshoot

annotate libs/vorbis/block.c @ 2:334d17aed7de

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