1 /********************************************************************
3 * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
4 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
5 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
6 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
8 * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001 *
9 * by the XIPHOPHORUS Company http://www.xiph.org/ *
11 ********************************************************************
13 function: PCM data vector blocking, windowing and dis/reassembly
14 last mod: $Id: block.c,v 1.51 2001/12/12 09:45:24 xiphmont Exp $
16 Handle windowing, overlap-add, etc of the PCM vectors. This is made
17 more amusing by Vorbis' current two allowed block sizes.
19 ********************************************************************/
25 #include "vorbis/codec.h"
26 #include "codec_internal.h"
34 static int ilog2(unsigned int v){
43 /* pcm accumulator examples (not exhaustive):
45 <-------------- lW ---------------->
46 <--------------- W ---------------->
47 : .....|..... _______________ |
48 : .''' | '''_--- | |\ |
49 :.....''' |_____--- '''......| | \_______|
50 :.................|__________________|_______|__|______|
51 |<------ Sl ------>| > Sr < |endW
52 |beginSl |endSl | |endSr
53 |beginW |endlW |beginSr
57 <--------------- W ---------------->
58 | | .. ______________ |
60 |___.'___/`. | ---_____|
61 |_______|__|_______|_________________|
62 | >|Sl|< |<------ Sr ----->|endW
63 | | |endSl |beginSr |endSr
65 mult[0] |beginSl mult[n]
67 <-------------- lW ----------------->
69 : .............. ___ | |
71 :.....''' |/`....\|...|
72 :.........................|___|___|___|
81 /* block abstraction setup *********************************************/
87 int vorbis_block_init(vorbis_dsp_state *v, vorbis_block *vb){
88 memset(vb,0,sizeof(*vb));
93 vorbis_block_internal *vbi=
94 vb->internal=_ogg_calloc(1,sizeof(vorbis_block_internal));
95 oggpack_writeinit(&vb->opb);
97 vbi->packet_markers=_ogg_malloc(vorbis_bitrate_maxmarkers()*
98 sizeof(*vbi->packet_markers));
104 void *_vorbis_block_alloc(vorbis_block *vb,long bytes){
105 bytes=(bytes+(WORD_ALIGN-1)) & ~(WORD_ALIGN-1);
106 if(bytes+vb->localtop>vb->localalloc){
107 /* can't just _ogg_realloc... there are outstanding pointers */
109 struct alloc_chain *link=_ogg_malloc(sizeof(*link));
110 vb->totaluse+=vb->localtop;
112 link->ptr=vb->localstore;
115 /* highly conservative */
116 vb->localalloc=bytes;
117 vb->localstore=_ogg_malloc(vb->localalloc);
121 void *ret=(void *)(((char *)vb->localstore)+vb->localtop);
127 /* reap the chain, pull the ripcord */
128 void _vorbis_block_ripcord(vorbis_block *vb){
130 struct alloc_chain *reap=vb->reap;
132 struct alloc_chain *next=reap->next;
133 _ogg_free(reap->ptr);
134 memset(reap,0,sizeof(*reap));
138 /* consolidate storage */
140 vb->localstore=_ogg_realloc(vb->localstore,vb->totaluse+vb->localalloc);
141 vb->localalloc+=vb->totaluse;
145 /* pull the ripcord */
150 int vorbis_block_clear(vorbis_block *vb){
152 if(vb->vd->analysisp)
153 oggpack_writeclear(&vb->opb);
154 _vorbis_block_ripcord(vb);
155 if(vb->localstore)_ogg_free(vb->localstore);
158 vorbis_block_internal *vbi=(vorbis_block_internal *)vb->internal;
159 if(vbi->packet_markers)_ogg_free(vbi->packet_markers);
161 _ogg_free(vb->internal);
164 memset(vb,0,sizeof(*vb));
168 /* Analysis side code, but directly related to blocking. Thus it's
169 here and not in analysis.c (which is for analysis transforms only).
170 The init is here because some of it is shared */
172 static int _vds_shared_init(vorbis_dsp_state *v,vorbis_info *vi,int encp){
174 codec_setup_info *ci=vi->codec_setup;
175 backend_lookup_state *b=NULL;
177 memset(v,0,sizeof(*v));
178 b=v->backend_state=_ogg_calloc(1,sizeof(*b));
181 b->modebits=ilog2(ci->modes);
183 b->transform[0]=_ogg_calloc(VI_TRANSFORMB,sizeof(*b->transform[0]));
184 b->transform[1]=_ogg_calloc(VI_TRANSFORMB,sizeof(*b->transform[1]));
186 /* MDCT is tranform 0 */
188 b->transform[0][0]=_ogg_calloc(1,sizeof(mdct_lookup));
189 b->transform[1][0]=_ogg_calloc(1,sizeof(mdct_lookup));
190 mdct_init(b->transform[0][0],ci->blocksizes[0]);
191 mdct_init(b->transform[1][0],ci->blocksizes[1]);
193 b->window[0][0][0]=_ogg_calloc(VI_WINDOWB,sizeof(*b->window[0][0][0]));
194 b->window[0][0][1]=b->window[0][0][0];
195 b->window[0][1][0]=b->window[0][0][0];
196 b->window[0][1][1]=b->window[0][0][0];
197 b->window[1][0][0]=_ogg_calloc(VI_WINDOWB,sizeof(*b->window[1][0][0]));
198 b->window[1][0][1]=_ogg_calloc(VI_WINDOWB,sizeof(*b->window[1][0][1]));
199 b->window[1][1][0]=_ogg_calloc(VI_WINDOWB,sizeof(*b->window[1][1][0]));
200 b->window[1][1][1]=_ogg_calloc(VI_WINDOWB,sizeof(*b->window[1][1][1]));
202 for(i=0;i<VI_WINDOWB;i++){
203 b->window[0][0][0][i]=
204 _vorbis_window(i,ci->blocksizes[0],ci->blocksizes[0]/2,ci->blocksizes[0]/2);
205 b->window[1][0][0][i]=
206 _vorbis_window(i,ci->blocksizes[1],ci->blocksizes[0]/2,ci->blocksizes[0]/2);
207 b->window[1][0][1][i]=
208 _vorbis_window(i,ci->blocksizes[1],ci->blocksizes[0]/2,ci->blocksizes[1]/2);
209 b->window[1][1][0][i]=
210 _vorbis_window(i,ci->blocksizes[1],ci->blocksizes[1]/2,ci->blocksizes[0]/2);
211 b->window[1][1][1][i]=
212 _vorbis_window(i,ci->blocksizes[1],ci->blocksizes[1]/2,ci->blocksizes[1]/2);
215 if(encp){ /* encode/decode differ here */
216 /* finish the codebooks */
217 b->fullbooks=_ogg_calloc(ci->books,sizeof(*b->fullbooks));
218 for(i=0;i<ci->books;i++)
219 vorbis_book_init_encode(b->fullbooks+i,ci->book_param[i]);
222 /* finish the codebooks */
223 b->fullbooks=_ogg_calloc(ci->books,sizeof(*b->fullbooks));
224 for(i=0;i<ci->books;i++)
225 vorbis_book_init_decode(b->fullbooks+i,ci->book_param[i]);
228 /* initialize the storage vectors to a decent size greater than the
231 v->pcm_storage=8192; /* we'll assume later that we have
232 a minimum of twice the blocksize of
233 accumulated samples in analysis */
234 v->pcm=_ogg_malloc(vi->channels*sizeof(*v->pcm));
235 v->pcmret=_ogg_malloc(vi->channels*sizeof(*v->pcmret));
238 for(i=0;i<vi->channels;i++)
239 v->pcm[i]=_ogg_calloc(v->pcm_storage,sizeof(*v->pcm[i]));
242 /* all 1 (large block) or 0 (small block) */
243 /* explicitly set for the sake of clarity */
244 v->lW=0; /* previous window size */
245 v->W=0; /* current window size */
247 /* all vector indexes */
248 v->centerW=ci->blocksizes[1]/2;
250 v->pcm_current=v->centerW;
252 /* initialize all the mapping/backend lookups */
253 b->mode=_ogg_calloc(ci->modes,sizeof(*b->mode));
254 for(i=0;i<ci->modes;i++){
255 int mapnum=ci->mode_param[i]->mapping;
256 int maptype=ci->map_type[mapnum];
257 b->mode[i]=_mapping_P[maptype]->look(v,ci->mode_param[i],
258 ci->map_param[mapnum]);
264 /* arbitrary settings and spec-mandated numbers get filled in here */
265 int vorbis_analysis_init(vorbis_dsp_state *v,vorbis_info *vi){
266 backend_lookup_state *b=NULL;
268 _vds_shared_init(v,vi,1);
270 b->psy_g_look=_vp_global_look(vi);
272 /* Initialize the envelope state storage */
273 b->ve=_ogg_calloc(1,sizeof(*b->ve));
274 _ve_envelope_init(b->ve,vi);
276 vorbis_bitrate_init(vi,&b->bms);
281 void vorbis_dsp_clear(vorbis_dsp_state *v){
284 vorbis_info *vi=v->vi;
285 codec_setup_info *ci=(vi?vi->codec_setup:NULL);
286 backend_lookup_state *b=v->backend_state;
289 if(b->window[0][0][0]){
290 for(i=0;i<VI_WINDOWB;i++)
291 if(b->window[0][0][0][i])_ogg_free(b->window[0][0][0][i]);
292 _ogg_free(b->window[0][0][0]);
296 for(i=0;i<VI_WINDOWB;i++)
297 if(b->window[1][j][k][i])_ogg_free(b->window[1][j][k][i]);
298 _ogg_free(b->window[1][j][k]);
303 _ve_envelope_clear(b->ve);
308 mdct_clear(b->transform[0][0]);
309 _ogg_free(b->transform[0][0]);
310 _ogg_free(b->transform[0]);
313 mdct_clear(b->transform[1][0]);
314 _ogg_free(b->transform[1][0]);
315 _ogg_free(b->transform[1]);
317 if(b->psy_g_look)_vp_global_free(b->psy_g_look);
318 vorbis_bitrate_clear(&b->bms);
322 for(i=0;i<vi->channels;i++)
323 if(v->pcm[i])_ogg_free(v->pcm[i]);
325 if(v->pcmret)_ogg_free(v->pcmret);
328 /* free mode lookups; these are actually vorbis_look_mapping structs */
330 for(i=0;i<ci->modes;i++){
331 int mapnum=ci->mode_param[i]->mapping;
332 int maptype=ci->map_type[mapnum];
333 if(b && b->mode)_mapping_P[maptype]->free_look(b->mode[i]);
336 for(i=0;i<ci->books;i++)
337 if(b && b->fullbooks)vorbis_book_clear(b->fullbooks+i);
341 if(b->mode)_ogg_free(b->mode);
342 if(b->fullbooks)_ogg_free(b->fullbooks);
344 /* free header, header1, header2 */
345 if(b->header)_ogg_free(b->header);
346 if(b->header1)_ogg_free(b->header1);
347 if(b->header2)_ogg_free(b->header2);
351 memset(v,0,sizeof(*v));
355 float **vorbis_analysis_buffer(vorbis_dsp_state *v, int vals){
357 vorbis_info *vi=v->vi;
358 backend_lookup_state *b=v->backend_state;
360 /* free header, header1, header2 */
361 if(b->header)_ogg_free(b->header);b->header=NULL;
362 if(b->header1)_ogg_free(b->header1);b->header1=NULL;
363 if(b->header2)_ogg_free(b->header2);b->header2=NULL;
365 /* Do we have enough storage space for the requested buffer? If not,
366 expand the PCM (and envelope) storage */
368 if(v->pcm_current+vals>=v->pcm_storage){
369 v->pcm_storage=v->pcm_current+vals*2;
371 for(i=0;i<vi->channels;i++){
372 v->pcm[i]=_ogg_realloc(v->pcm[i],v->pcm_storage*sizeof(*v->pcm[i]));
376 for(i=0;i<vi->channels;i++)
377 v->pcmret[i]=v->pcm[i]+v->pcm_current;
383 static void _preextrapolate_helper(vorbis_dsp_state *v){
386 float *lpc=alloca(order*sizeof(*lpc));
387 float *work=alloca(v->pcm_current*sizeof(*work));
391 if(v->pcm_current-v->centerW>order*2){ /* safety */
392 for(i=0;i<v->vi->channels;i++){
393 /* need to run the extrapolation in reverse! */
394 for(j=0;j<v->pcm_current;j++)
395 work[j]=v->pcm[i][v->pcm_current-j-1];
397 _analysis_output("preextrap",seq,v->pcm[i],v->pcm_current,0,0);
398 _analysis_output("workextrap",seq,work,v->pcm_current,0,0);
401 vorbis_lpc_from_data(work,lpc,v->pcm_current-v->centerW,order);
402 _analysis_output("lpc",seq,lpc,order,0,0);
404 /* run the predictor filter */
405 vorbis_lpc_predict(lpc,work+v->pcm_current-v->centerW-order,
407 work+v->pcm_current-v->centerW,
410 _analysis_output("extrap",seq,work,v->pcm_current,0,0);
413 for(j=0;j<v->pcm_current;j++)
414 v->pcm[i][v->pcm_current-j-1]=work[j];
416 _analysis_output("postextrap",seq++,v->pcm[i],v->pcm_current,0,0);
422 /* call with val<=0 to set eof */
424 int vorbis_analysis_wrote(vorbis_dsp_state *v, int vals){
425 vorbis_info *vi=v->vi;
426 codec_setup_info *ci=vi->codec_setup;
427 /*backend_lookup_state *b=v->backend_state;*/
432 float *lpc=alloca(order*sizeof(*lpc));
434 /* if it wasn't done earlier (very short sample) */
435 if(!v->preextrapolate)
436 _preextrapolate_helper(v);
438 /* We're encoding the end of the stream. Just make sure we have
439 [at least] a full block of zeroes at the end. */
440 /* actually, we don't want zeroes; that could drop a large
441 amplitude off a cliff, creating spread spectrum noise that will
442 suck to encode. Extrapolate for the sake of cleanliness. */
444 vorbis_analysis_buffer(v,ci->blocksizes[1]*2);
445 v->eofflag=v->pcm_current;
446 v->pcm_current+=ci->blocksizes[1]*2;
448 for(i=0;i<vi->channels;i++){
449 if(v->eofflag>order*2){
450 /* extrapolate with LPC to fill in */
453 /* make a predictor filter */
455 if(n>ci->blocksizes[1])n=ci->blocksizes[1];
456 vorbis_lpc_from_data(v->pcm[i]+v->eofflag-n,lpc,n,order);
458 /* run the predictor filter */
459 vorbis_lpc_predict(lpc,v->pcm[i]+v->eofflag-order,order,
460 v->pcm[i]+v->eofflag,v->pcm_current-v->eofflag);
462 /* not enough data to extrapolate (unlikely to happen due to
463 guarding the overlap, but bulletproof in case that
464 assumtion goes away). zeroes will do. */
465 memset(v->pcm[i]+v->eofflag,0,
466 (v->pcm_current-v->eofflag)*sizeof(*v->pcm[i]));
472 if(v->pcm_current+vals>v->pcm_storage)
475 v->pcm_current+=vals;
477 /* we may want to reverse extrapolate the beginning of a stream
478 too... in case we're beginning on a cliff! */
479 /* clumsy, but simple. It only runs once, so simple is good. */
480 if(!v->preextrapolate && v->pcm_current-v->centerW>ci->blocksizes[1])
481 _preextrapolate_helper(v);
487 /* do the deltas, envelope shaping, pre-echo and determine the size of
488 the next block on which to continue analysis */
489 int vorbis_analysis_blockout(vorbis_dsp_state *v,vorbis_block *vb){
491 vorbis_info *vi=v->vi;
492 codec_setup_info *ci=vi->codec_setup;
493 backend_lookup_state *b=v->backend_state;
494 vorbis_look_psy_global *g=b->psy_g_look;
495 vorbis_info_psy_global *gi=&ci->psy_g_param;
496 long beginW=v->centerW-ci->blocksizes[v->W]/2,centerNext;
497 vorbis_block_internal *vbi=(vorbis_block_internal *)vb->internal;
499 /* check to see if we're started... */
500 if(!v->preextrapolate)return(0);
502 /* check to see if we're done... */
503 if(v->eofflag==-1)return(0);
505 /* By our invariant, we have lW, W and centerW set. Search for
506 the next boundary so we can determine nW (the next window size)
507 which lets us compute the shape of the current block's window */
509 if(ci->blocksizes[0]<ci->blocksizes[1]){
510 long bp=_ve_envelope_search(v);
511 if(bp==-1)return(0); /* not enough data currently to search for a
519 centerNext=v->centerW+ci->blocksizes[v->W]/4+ci->blocksizes[v->nW]/4;
522 /* center of next block + next block maximum right side. */
524 long blockbound=centerNext+ci->blocksizes[v->nW]/2;
525 if(v->pcm_current<blockbound)return(0); /* not enough data yet;
526 although this check is
529 the search is not run
536 /* fill in the block. Note that for a short window, lW and nW are *short*
537 regardless of actual settings in the stream */
539 _vorbis_block_ripcord(vb);
552 vbi->blocktype=BLOCKTYPE_TRANSITION;
554 vbi->blocktype=BLOCKTYPE_LONG;
556 if(_ve_envelope_mark(v))
557 vbi->blocktype=BLOCKTYPE_IMPULSE;
559 vbi->blocktype=BLOCKTYPE_PADDING;
563 vb->sequence=v->sequence;
564 vb->granulepos=v->granulepos;
565 vb->pcmend=ci->blocksizes[v->W];
568 /* copy the vectors; this uses the local storage in vb */
570 vorbis_block_internal *vbi=(vorbis_block_internal *)vb->internal;
572 /* this tracks 'strongest peak' for later psychoacoustics */
573 /* moved to the global psy state; clean this mess up */
574 if(vbi->ampmax>g->ampmax)g->ampmax=vbi->ampmax;
575 g->ampmax=_vp_ampmax_decay(g->ampmax,v);
576 vbi->ampmax=g->ampmax;
578 vb->pcm=_vorbis_block_alloc(vb,sizeof(*vb->pcm)*vi->channels);
579 vbi->pcmdelay=_vorbis_block_alloc(vb,sizeof(*vbi->pcmdelay)*vi->channels);
580 for(i=0;i<vi->channels;i++){
582 _vorbis_block_alloc(vb,(vb->pcmend+beginW)*sizeof(*vbi->pcmdelay[i]));
583 memcpy(vbi->pcmdelay[i],v->pcm[i],(vb->pcmend+beginW)*sizeof(*vbi->pcmdelay[i]));
584 vb->pcm[i]=vbi->pcmdelay[i]+beginW;
586 /* before we added the delay
587 vb->pcm[i]=_vorbis_block_alloc(vb,vb->pcmend*sizeof(*vb->pcm[i]));
588 memcpy(vb->pcm[i],v->pcm[i]+beginW,ci->blocksizes[v->W]*sizeof(*vb->pcm[i]));
594 /* handle eof detection: eof==0 means that we've not yet received EOF
595 eof>0 marks the last 'real' sample in pcm[]
596 eof<0 'no more to do'; doesn't get here */
599 if(v->centerW>=v->eofflag){
606 /* advance storage vectors and clean up */
608 int new_centerNext=ci->blocksizes[1]/2+gi->delaycache;
609 int movementW=centerNext-new_centerNext;
613 _ve_envelope_shift(b->ve,movementW);
614 v->pcm_current-=movementW;
616 for(i=0;i<vi->channels;i++)
617 memmove(v->pcm[i],v->pcm[i]+movementW,
618 v->pcm_current*sizeof(*v->pcm[i]));
623 v->centerW=new_centerNext;
628 v->eofflag-=movementW;
629 /* do not add padding to end of stream! */
630 if(v->centerW>=v->eofflag){
631 v->granulepos+=movementW-(v->centerW-v->eofflag);
633 v->granulepos+=movementW;
636 v->granulepos+=movementW;
645 int vorbis_synthesis_init(vorbis_dsp_state *v,vorbis_info *vi){
646 _vds_shared_init(v,vi,0);
655 /* Unlike in analysis, the window is only partially applied for each
656 block. The time domain envelope is not yet handled at the point of
657 calling (as it relies on the previous block). */
659 int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb){
660 vorbis_info *vi=v->vi;
661 codec_setup_info *ci=vi->codec_setup;
663 /* Shift out any PCM that we returned previously */
664 /* centerW is currently the center of the last block added */
666 if(v->centerW>ci->blocksizes[1]/2 &&
667 /* Quick additional hack; to avoid *alot* of shifts, use an
668 oversized buffer. This increases memory usage, but doesn't make
669 much difference wrt L1/L2 cache pressure. */
670 v->pcm_returned>8192){
672 /* don't shift too much; we need to have a minimum PCM buffer of
675 int shiftPCM=v->centerW-ci->blocksizes[1]/2;
676 shiftPCM=(v->pcm_returned<shiftPCM?v->pcm_returned:shiftPCM);
678 v->pcm_current-=shiftPCM;
679 v->centerW-=shiftPCM;
680 v->pcm_returned-=shiftPCM;
684 for(i=0;i<vi->channels;i++)
685 memmove(v->pcm[i],v->pcm[i]+shiftPCM,
686 v->pcm_current*sizeof(*v->pcm[i]));
694 v->glue_bits+=vb->glue_bits;
695 v->time_bits+=vb->time_bits;
696 v->floor_bits+=vb->floor_bits;
697 v->res_bits+=vb->res_bits;
699 if(v->sequence+1 != vb->sequence)v->granulepos=-1; /* out of sequence;
702 v->sequence=vb->sequence;
705 int sizeW=ci->blocksizes[v->W];
706 int centerW=v->centerW+ci->blocksizes[v->lW]/4+sizeW/4;
707 int beginW=centerW-sizeW/2;
708 int endW=beginW+sizeW;
713 /* Do we have enough PCM/mult storage for the block? */
714 if(endW>v->pcm_storage){
715 /* expand the storage */
716 v->pcm_storage=endW+ci->blocksizes[1];
718 for(i=0;i<vi->channels;i++)
719 v->pcm[i]=_ogg_realloc(v->pcm[i],v->pcm_storage*sizeof(*v->pcm[i]));
722 /* overlap/add PCM */
727 endSl=ci->blocksizes[0]/2;
730 beginSl=ci->blocksizes[1]/4-ci->blocksizes[v->lW]/4;
731 endSl=beginSl+ci->blocksizes[v->lW]/2;
737 for(j=0;j<vi->channels;j++){
739 float *pcm=v->pcm[j]+beginW;
742 /* the overlap/add section */
743 for(i=beginSl;i<endSl;i++)
745 /* the remaining section */
749 //_analysis_output("lapped",seq,pcm,sizeW,0,0);
750 //_analysis_output("buffered",seq++,v->pcm[j],sizeW+beginW,0,0);
754 /* deal with initial packet state; we do this using the explicit
755 pcm_returned==-1 flag otherwise we're sensitive to first block
756 being short or long */
758 if(v->pcm_returned==-1)
759 v->pcm_returned=centerW;
761 /* track the frame number... This is for convenience, but also
762 making sure our last packet doesn't end with added padding. If
763 the last packet is partial, the number of samples we'll have to
764 return will be past the vb->granulepos.
766 This is not foolproof! It will be confused if we begin
767 decoding at the last page after a seek or hole. In that case,
768 we don't have a starting point to judge where the last frame
769 is. For this reason, vorbisfile will always try to make sure
770 it reads the last two marked pages in proper sequence */
772 if(v->granulepos==-1)
773 if(vb->granulepos==-1){
776 v->granulepos=vb->granulepos;
779 v->granulepos+=(centerW-v->centerW);
780 if(vb->granulepos!=-1 && v->granulepos!=vb->granulepos){
782 if(v->granulepos>vb->granulepos){
783 long extra=v->granulepos-vb->granulepos;
786 /* partial last frame. Strip the extra samples off */
788 }else if(vb->sequence == 1){
789 /* ^^^ argh, this can be 1 from seeking! */
792 /* partial first frame. Discard extra leading samples */
793 v->pcm_returned+=extra;
794 if(v->pcm_returned>centerW)v->pcm_returned=centerW;
798 }/* else{ Shouldn't happen *unless* the bitstream is out of
799 spec. Either way, believe the bitstream } */
800 v->granulepos=vb->granulepos;
804 /* Update, cleanup */
809 if(vb->eofflag)v->eofflag=1;
815 /* pcm==NULL indicates we just want the pending samples, no more */
816 int vorbis_synthesis_pcmout(vorbis_dsp_state *v,float ***pcm){
817 vorbis_info *vi=v->vi;
818 if(v->pcm_returned>-1 && v->pcm_returned<v->centerW){
821 for(i=0;i<vi->channels;i++)
822 v->pcmret[i]=v->pcm[i]+v->pcm_returned;
825 return(v->centerW-v->pcm_returned);
830 int vorbis_synthesis_read(vorbis_dsp_state *v,int bytes){
831 if(bytes && v->pcm_returned+bytes>v->centerW)return(OV_EINVAL);
832 v->pcm_returned+=bytes;