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.52 2001/12/19 01:08:13 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;
382 static void _preextrapolate_helper(vorbis_dsp_state *v){
385 float *lpc=alloca(order*sizeof(*lpc));
386 float *work=alloca(v->pcm_current*sizeof(*work));
390 if(v->pcm_current-v->centerW>order*2){ /* safety */
391 for(i=0;i<v->vi->channels;i++){
392 /* need to run the extrapolation in reverse! */
393 for(j=0;j<v->pcm_current;j++)
394 work[j]=v->pcm[i][v->pcm_current-j-1];
397 vorbis_lpc_from_data(work,lpc,v->pcm_current-v->centerW,order);
399 /* run the predictor filter */
400 vorbis_lpc_predict(lpc,work+v->pcm_current-v->centerW-order,
402 work+v->pcm_current-v->centerW,
405 for(j=0;j<v->pcm_current;j++)
406 v->pcm[i][v->pcm_current-j-1]=work[j];
413 /* call with val<=0 to set eof */
415 int vorbis_analysis_wrote(vorbis_dsp_state *v, int vals){
416 vorbis_info *vi=v->vi;
417 codec_setup_info *ci=vi->codec_setup;
418 /*backend_lookup_state *b=v->backend_state;*/
423 float *lpc=alloca(order*sizeof(*lpc));
425 /* if it wasn't done earlier (very short sample) */
426 if(!v->preextrapolate)
427 _preextrapolate_helper(v);
429 /* We're encoding the end of the stream. Just make sure we have
430 [at least] a full block of zeroes at the end. */
431 /* actually, we don't want zeroes; that could drop a large
432 amplitude off a cliff, creating spread spectrum noise that will
433 suck to encode. Extrapolate for the sake of cleanliness. */
435 vorbis_analysis_buffer(v,ci->blocksizes[1]*2);
436 v->eofflag=v->pcm_current;
437 v->pcm_current+=ci->blocksizes[1]*2;
439 for(i=0;i<vi->channels;i++){
440 if(v->eofflag>order*2){
441 /* extrapolate with LPC to fill in */
444 /* make a predictor filter */
446 if(n>ci->blocksizes[1])n=ci->blocksizes[1];
447 vorbis_lpc_from_data(v->pcm[i]+v->eofflag-n,lpc,n,order);
449 /* run the predictor filter */
450 vorbis_lpc_predict(lpc,v->pcm[i]+v->eofflag-order,order,
451 v->pcm[i]+v->eofflag,v->pcm_current-v->eofflag);
453 /* not enough data to extrapolate (unlikely to happen due to
454 guarding the overlap, but bulletproof in case that
455 assumtion goes away). zeroes will do. */
456 memset(v->pcm[i]+v->eofflag,0,
457 (v->pcm_current-v->eofflag)*sizeof(*v->pcm[i]));
463 if(v->pcm_current+vals>v->pcm_storage)
466 v->pcm_current+=vals;
468 /* we may want to reverse extrapolate the beginning of a stream
469 too... in case we're beginning on a cliff! */
470 /* clumsy, but simple. It only runs once, so simple is good. */
471 if(!v->preextrapolate && v->pcm_current-v->centerW>ci->blocksizes[1])
472 _preextrapolate_helper(v);
478 /* do the deltas, envelope shaping, pre-echo and determine the size of
479 the next block on which to continue analysis */
480 int vorbis_analysis_blockout(vorbis_dsp_state *v,vorbis_block *vb){
482 vorbis_info *vi=v->vi;
483 codec_setup_info *ci=vi->codec_setup;
484 backend_lookup_state *b=v->backend_state;
485 vorbis_look_psy_global *g=b->psy_g_look;
486 vorbis_info_psy_global *gi=&ci->psy_g_param;
487 long beginW=v->centerW-ci->blocksizes[v->W]/2,centerNext;
488 vorbis_block_internal *vbi=(vorbis_block_internal *)vb->internal;
490 /* check to see if we're started... */
491 if(!v->preextrapolate)return(0);
493 /* check to see if we're done... */
494 if(v->eofflag==-1)return(0);
496 /* By our invariant, we have lW, W and centerW set. Search for
497 the next boundary so we can determine nW (the next window size)
498 which lets us compute the shape of the current block's window */
500 if(ci->blocksizes[0]<ci->blocksizes[1]){
501 long bp=_ve_envelope_search(v);
502 if(bp==-1)return(0); /* not enough data currently to search for a
510 centerNext=v->centerW+ci->blocksizes[v->W]/4+ci->blocksizes[v->nW]/4;
513 /* center of next block + next block maximum right side. */
515 long blockbound=centerNext+ci->blocksizes[v->nW]/2;
516 if(v->pcm_current<blockbound)return(0); /* not enough data yet;
517 although this check is
520 the search is not run
527 /* fill in the block. Note that for a short window, lW and nW are *short*
528 regardless of actual settings in the stream */
530 _vorbis_block_ripcord(vb);
543 vbi->blocktype=BLOCKTYPE_TRANSITION;
545 vbi->blocktype=BLOCKTYPE_LONG;
547 if(_ve_envelope_mark(v))
548 vbi->blocktype=BLOCKTYPE_IMPULSE;
550 vbi->blocktype=BLOCKTYPE_PADDING;
554 vb->sequence=v->sequence;
555 vb->granulepos=v->granulepos;
556 vb->pcmend=ci->blocksizes[v->W];
559 /* copy the vectors; this uses the local storage in vb */
561 vorbis_block_internal *vbi=(vorbis_block_internal *)vb->internal;
563 /* this tracks 'strongest peak' for later psychoacoustics */
564 /* moved to the global psy state; clean this mess up */
565 if(vbi->ampmax>g->ampmax)g->ampmax=vbi->ampmax;
566 g->ampmax=_vp_ampmax_decay(g->ampmax,v);
567 vbi->ampmax=g->ampmax;
569 vb->pcm=_vorbis_block_alloc(vb,sizeof(*vb->pcm)*vi->channels);
570 vbi->pcmdelay=_vorbis_block_alloc(vb,sizeof(*vbi->pcmdelay)*vi->channels);
571 for(i=0;i<vi->channels;i++){
573 _vorbis_block_alloc(vb,(vb->pcmend+beginW)*sizeof(*vbi->pcmdelay[i]));
574 memcpy(vbi->pcmdelay[i],v->pcm[i],(vb->pcmend+beginW)*sizeof(*vbi->pcmdelay[i]));
575 vb->pcm[i]=vbi->pcmdelay[i]+beginW;
577 /* before we added the delay
578 vb->pcm[i]=_vorbis_block_alloc(vb,vb->pcmend*sizeof(*vb->pcm[i]));
579 memcpy(vb->pcm[i],v->pcm[i]+beginW,ci->blocksizes[v->W]*sizeof(*vb->pcm[i]));
585 /* handle eof detection: eof==0 means that we've not yet received EOF
586 eof>0 marks the last 'real' sample in pcm[]
587 eof<0 'no more to do'; doesn't get here */
590 if(v->centerW>=v->eofflag){
597 /* advance storage vectors and clean up */
599 int new_centerNext=ci->blocksizes[1]/2+gi->delaycache;
600 int movementW=centerNext-new_centerNext;
604 _ve_envelope_shift(b->ve,movementW);
605 v->pcm_current-=movementW;
607 for(i=0;i<vi->channels;i++)
608 memmove(v->pcm[i],v->pcm[i]+movementW,
609 v->pcm_current*sizeof(*v->pcm[i]));
614 v->centerW=new_centerNext;
619 v->eofflag-=movementW;
620 /* do not add padding to end of stream! */
621 if(v->centerW>=v->eofflag){
622 v->granulepos+=movementW-(v->centerW-v->eofflag);
624 v->granulepos+=movementW;
627 v->granulepos+=movementW;
636 int vorbis_synthesis_init(vorbis_dsp_state *v,vorbis_info *vi){
637 _vds_shared_init(v,vi,0);
646 /* Unlike in analysis, the window is only partially applied for each
647 block. The time domain envelope is not yet handled at the point of
648 calling (as it relies on the previous block). */
650 int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb){
651 vorbis_info *vi=v->vi;
652 codec_setup_info *ci=vi->codec_setup;
654 /* Shift out any PCM that we returned previously */
655 /* centerW is currently the center of the last block added */
657 if(v->centerW>ci->blocksizes[1]/2 &&
658 /* Quick additional hack; to avoid *alot* of shifts, use an
659 oversized buffer. This increases memory usage, but doesn't make
660 much difference wrt L1/L2 cache pressure. */
661 v->pcm_returned>8192){
663 /* don't shift too much; we need to have a minimum PCM buffer of
666 int shiftPCM=v->centerW-ci->blocksizes[1]/2;
667 shiftPCM=(v->pcm_returned<shiftPCM?v->pcm_returned:shiftPCM);
669 v->pcm_current-=shiftPCM;
670 v->centerW-=shiftPCM;
671 v->pcm_returned-=shiftPCM;
675 for(i=0;i<vi->channels;i++)
676 memmove(v->pcm[i],v->pcm[i]+shiftPCM,
677 v->pcm_current*sizeof(*v->pcm[i]));
685 v->glue_bits+=vb->glue_bits;
686 v->time_bits+=vb->time_bits;
687 v->floor_bits+=vb->floor_bits;
688 v->res_bits+=vb->res_bits;
690 if(v->sequence+1 != vb->sequence)v->granulepos=-1; /* out of sequence;
693 v->sequence=vb->sequence;
696 int sizeW=ci->blocksizes[v->W];
697 int centerW=v->centerW+ci->blocksizes[v->lW]/4+sizeW/4;
698 int beginW=centerW-sizeW/2;
699 int endW=beginW+sizeW;
704 /* Do we have enough PCM/mult storage for the block? */
705 if(endW>v->pcm_storage){
706 /* expand the storage */
707 v->pcm_storage=endW+ci->blocksizes[1];
709 for(i=0;i<vi->channels;i++)
710 v->pcm[i]=_ogg_realloc(v->pcm[i],v->pcm_storage*sizeof(*v->pcm[i]));
713 /* overlap/add PCM */
718 endSl=ci->blocksizes[0]/2;
721 beginSl=ci->blocksizes[1]/4-ci->blocksizes[v->lW]/4;
722 endSl=beginSl+ci->blocksizes[v->lW]/2;
728 for(j=0;j<vi->channels;j++){
729 float *pcm=v->pcm[j]+beginW;
732 /* the overlap/add section */
733 for(i=beginSl;i<endSl;i++)
735 /* the remaining section */
741 /* deal with initial packet state; we do this using the explicit
742 pcm_returned==-1 flag otherwise we're sensitive to first block
743 being short or long */
745 if(v->pcm_returned==-1)
746 v->pcm_returned=centerW;
748 /* track the frame number... This is for convenience, but also
749 making sure our last packet doesn't end with added padding. If
750 the last packet is partial, the number of samples we'll have to
751 return will be past the vb->granulepos.
753 This is not foolproof! It will be confused if we begin
754 decoding at the last page after a seek or hole. In that case,
755 we don't have a starting point to judge where the last frame
756 is. For this reason, vorbisfile will always try to make sure
757 it reads the last two marked pages in proper sequence */
759 if(v->granulepos==-1)
760 if(vb->granulepos==-1){
763 v->granulepos=vb->granulepos;
766 v->granulepos+=(centerW-v->centerW);
767 if(vb->granulepos!=-1 && v->granulepos!=vb->granulepos){
769 if(v->granulepos>vb->granulepos){
770 long extra=v->granulepos-vb->granulepos;
773 /* partial last frame. Strip the extra samples off */
775 }else if(vb->sequence == 1){
776 /* ^^^ argh, this can be 1 from seeking! */
779 /* partial first frame. Discard extra leading samples */
780 v->pcm_returned+=extra;
781 if(v->pcm_returned>centerW)v->pcm_returned=centerW;
785 }/* else{ Shouldn't happen *unless* the bitstream is out of
786 spec. Either way, believe the bitstream } */
787 v->granulepos=vb->granulepos;
791 /* Update, cleanup */
796 if(vb->eofflag)v->eofflag=1;
802 /* pcm==NULL indicates we just want the pending samples, no more */
803 int vorbis_synthesis_pcmout(vorbis_dsp_state *v,float ***pcm){
804 vorbis_info *vi=v->vi;
805 if(v->pcm_returned>-1 && v->pcm_returned<v->centerW){
808 for(i=0;i<vi->channels;i++)
809 v->pcmret[i]=v->pcm[i]+v->pcm_returned;
812 return(v->centerW-v->pcm_returned);
817 int vorbis_synthesis_read(vorbis_dsp_state *v,int bytes){
818 if(bytes && v->pcm_returned+bytes>v->centerW)return(OV_EINVAL);
819 v->pcm_returned+=bytes;