media/libvorbis/lib/vorbis_block.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial