| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050 | 
							- /********************************************************************
 
-  *                                                                  *
 
-  * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
 
-  * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
 
-  * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
 
-  * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
 
-  *                                                                  *
 
-  * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009             *
 
-  * by the Xiph.Org Foundation http://www.xiph.org/                  *
 
-  *                                                                  *
 
-  ********************************************************************
 
-  function: PCM data vector blocking, windowing and dis/reassembly
 
-  last mod: $Id: block.c 19031 2013-12-03 19:20:50Z tterribe $
 
-  Handle windowing, overlap-add, etc of the PCM vectors.  This is made
 
-  more amusing by Vorbis' current two allowed block sizes.
 
-  ********************************************************************/
 
- #include <stdio.h>
 
- #include <stdlib.h>
 
- #include <string.h>
 
- #include <ogg/ogg.h>
 
- #include "vorbis/codec.h"
 
- #include "codec_internal.h"
 
- #include "window.h"
 
- #include "mdct.h"
 
- #include "lpc.h"
 
- #include "registry.h"
 
- #include "misc.h"
 
- static int ilog2(unsigned int v){
 
-   int ret=0;
 
-   if(v)--v;
 
-   while(v){
 
-     ret++;
 
-     v>>=1;
 
-   }
 
-   return(ret);
 
- }
 
- /* pcm accumulator examples (not exhaustive):
 
-  <-------------- lW ---------------->
 
-                    <--------------- W ---------------->
 
- :            .....|.....       _______________         |
 
- :        .'''     |     '''_---      |       |\        |
 
- :.....'''         |_____--- '''......|       | \_______|
 
- :.................|__________________|_______|__|______|
 
-                   |<------ Sl ------>|      > Sr <     |endW
 
-                   |beginSl           |endSl  |  |endSr
 
-                   |beginW            |endlW  |beginSr
 
-                       |< lW >|
 
-                    <--------------- W ---------------->
 
-                   |   |  ..  ______________            |
 
-                   |   | '  `/        |     ---_        |
 
-                   |___.'___/`.       |         ---_____|
 
-                   |_______|__|_______|_________________|
 
-                   |      >|Sl|<      |<------ Sr ----->|endW
 
-                   |       |  |endSl  |beginSr          |endSr
 
-                   |beginW |  |endlW
 
-                   mult[0] |beginSl                     mult[n]
 
-  <-------------- lW ----------------->
 
-                           |<--W-->|
 
- :            ..............  ___  |   |
 
- :        .'''             |`/   \ |   |
 
- :.....'''                 |/`....\|...|
 
- :.........................|___|___|___|
 
-                           |Sl |Sr |endW
 
-                           |   |   |endSr
 
-                           |   |beginSr
 
-                           |   |endSl
 
-                           |beginSl
 
-                           |beginW
 
- */
 
- /* block abstraction setup *********************************************/
 
- #ifndef WORD_ALIGN
 
- #define WORD_ALIGN 8
 
- #endif
 
- int vorbis_block_init(vorbis_dsp_state *v, vorbis_block *vb){
 
-   int i;
 
-   memset(vb,0,sizeof(*vb));
 
-   vb->vd=v;
 
-   vb->localalloc=0;
 
-   vb->localstore=NULL;
 
-   if(v->analysisp){
 
-     vorbis_block_internal *vbi=
 
-       vb->internal=_ogg_calloc(1,sizeof(vorbis_block_internal));
 
-     vbi->ampmax=-9999;
 
-     for(i=0;i<PACKETBLOBS;i++){
 
-       if(i==PACKETBLOBS/2){
 
-         vbi->packetblob[i]=&vb->opb;
 
-       }else{
 
-         vbi->packetblob[i]=
 
-           _ogg_calloc(1,sizeof(oggpack_buffer));
 
-       }
 
-       oggpack_writeinit(vbi->packetblob[i]);
 
-     }
 
-   }
 
-   return(0);
 
- }
 
- void *_vorbis_block_alloc(vorbis_block *vb,long bytes){
 
-   bytes=(bytes+(WORD_ALIGN-1)) & ~(WORD_ALIGN-1);
 
-   if(bytes+vb->localtop>vb->localalloc){
 
-     /* can't just _ogg_realloc... there are outstanding pointers */
 
-     if(vb->localstore){
 
-       struct alloc_chain *link=_ogg_malloc(sizeof(*link));
 
-       vb->totaluse+=vb->localtop;
 
-       link->next=vb->reap;
 
-       link->ptr=vb->localstore;
 
-       vb->reap=link;
 
-     }
 
-     /* highly conservative */
 
-     vb->localalloc=bytes;
 
-     vb->localstore=_ogg_malloc(vb->localalloc);
 
-     vb->localtop=0;
 
-   }
 
-   {
 
-     void *ret=(void *)(((char *)vb->localstore)+vb->localtop);
 
-     vb->localtop+=bytes;
 
-     return ret;
 
-   }
 
- }
 
- /* reap the chain, pull the ripcord */
 
- void _vorbis_block_ripcord(vorbis_block *vb){
 
-   /* reap the chain */
 
-   struct alloc_chain *reap=vb->reap;
 
-   while(reap){
 
-     struct alloc_chain *next=reap->next;
 
-     _ogg_free(reap->ptr);
 
-     memset(reap,0,sizeof(*reap));
 
-     _ogg_free(reap);
 
-     reap=next;
 
-   }
 
-   /* consolidate storage */
 
-   if(vb->totaluse){
 
-     vb->localstore=_ogg_realloc(vb->localstore,vb->totaluse+vb->localalloc);
 
-     vb->localalloc+=vb->totaluse;
 
-     vb->totaluse=0;
 
-   }
 
-   /* pull the ripcord */
 
-   vb->localtop=0;
 
-   vb->reap=NULL;
 
- }
 
- int vorbis_block_clear(vorbis_block *vb){
 
-   int i;
 
-   vorbis_block_internal *vbi=vb->internal;
 
-   _vorbis_block_ripcord(vb);
 
-   if(vb->localstore)_ogg_free(vb->localstore);
 
-   if(vbi){
 
-     for(i=0;i<PACKETBLOBS;i++){
 
-       oggpack_writeclear(vbi->packetblob[i]);
 
-       if(i!=PACKETBLOBS/2)_ogg_free(vbi->packetblob[i]);
 
-     }
 
-     _ogg_free(vbi);
 
-   }
 
-   memset(vb,0,sizeof(*vb));
 
-   return(0);
 
- }
 
- /* Analysis side code, but directly related to blocking.  Thus it's
 
-    here and not in analysis.c (which is for analysis transforms only).
 
-    The init is here because some of it is shared */
 
- static int _vds_shared_init(vorbis_dsp_state *v,vorbis_info *vi,int encp){
 
-   int i;
 
-   codec_setup_info *ci=vi->codec_setup;
 
-   private_state *b=NULL;
 
-   int hs;
 
-   if(ci==NULL) return 1;
 
-   hs=ci->halfrate_flag;
 
-   memset(v,0,sizeof(*v));
 
-   b=v->backend_state=_ogg_calloc(1,sizeof(*b));
 
-   v->vi=vi;
 
-   b->modebits=ilog2(ci->modes);
 
-   b->transform[0]=_ogg_calloc(VI_TRANSFORMB,sizeof(*b->transform[0]));
 
-   b->transform[1]=_ogg_calloc(VI_TRANSFORMB,sizeof(*b->transform[1]));
 
-   /* MDCT is tranform 0 */
 
-   b->transform[0][0]=_ogg_calloc(1,sizeof(mdct_lookup));
 
-   b->transform[1][0]=_ogg_calloc(1,sizeof(mdct_lookup));
 
-   mdct_init(b->transform[0][0],ci->blocksizes[0]>>hs);
 
-   mdct_init(b->transform[1][0],ci->blocksizes[1]>>hs);
 
-   /* Vorbis I uses only window type 0 */
 
-   b->window[0]=ilog2(ci->blocksizes[0])-6;
 
-   b->window[1]=ilog2(ci->blocksizes[1])-6;
 
-   if(encp){ /* encode/decode differ here */
 
-     /* analysis always needs an fft */
 
-     drft_init(&b->fft_look[0],ci->blocksizes[0]);
 
-     drft_init(&b->fft_look[1],ci->blocksizes[1]);
 
-     /* finish the codebooks */
 
-     if(!ci->fullbooks){
 
-       ci->fullbooks=_ogg_calloc(ci->books,sizeof(*ci->fullbooks));
 
-       for(i=0;i<ci->books;i++)
 
-         vorbis_book_init_encode(ci->fullbooks+i,ci->book_param[i]);
 
-     }
 
-     b->psy=_ogg_calloc(ci->psys,sizeof(*b->psy));
 
-     for(i=0;i<ci->psys;i++){
 
-       _vp_psy_init(b->psy+i,
 
-                    ci->psy_param[i],
 
-                    &ci->psy_g_param,
 
-                    ci->blocksizes[ci->psy_param[i]->blockflag]/2,
 
-                    vi->rate);
 
-     }
 
-     v->analysisp=1;
 
-   }else{
 
-     /* finish the codebooks */
 
-     if(!ci->fullbooks){
 
-       ci->fullbooks=_ogg_calloc(ci->books,sizeof(*ci->fullbooks));
 
-       for(i=0;i<ci->books;i++){
 
-         if(ci->book_param[i]==NULL)
 
-           goto abort_books;
 
-         if(vorbis_book_init_decode(ci->fullbooks+i,ci->book_param[i]))
 
-           goto abort_books;
 
-         /* decode codebooks are now standalone after init */
 
-         vorbis_staticbook_destroy(ci->book_param[i]);
 
-         ci->book_param[i]=NULL;
 
-       }
 
-     }
 
-   }
 
-   /* initialize the storage vectors. blocksize[1] is small for encode,
 
-      but the correct size for decode */
 
-   v->pcm_storage=ci->blocksizes[1];
 
-   v->pcm=_ogg_malloc(vi->channels*sizeof(*v->pcm));
 
-   v->pcmret=_ogg_malloc(vi->channels*sizeof(*v->pcmret));
 
-   {
 
-     int i;
 
-     for(i=0;i<vi->channels;i++)
 
-       v->pcm[i]=_ogg_calloc(v->pcm_storage,sizeof(*v->pcm[i]));
 
-   }
 
-   /* all 1 (large block) or 0 (small block) */
 
-   /* explicitly set for the sake of clarity */
 
-   v->lW=0; /* previous window size */
 
-   v->W=0;  /* current window size */
 
-   /* all vector indexes */
 
-   v->centerW=ci->blocksizes[1]/2;
 
-   v->pcm_current=v->centerW;
 
-   /* initialize all the backend lookups */
 
-   b->flr=_ogg_calloc(ci->floors,sizeof(*b->flr));
 
-   b->residue=_ogg_calloc(ci->residues,sizeof(*b->residue));
 
-   for(i=0;i<ci->floors;i++)
 
-     b->flr[i]=_floor_P[ci->floor_type[i]]->
 
-       look(v,ci->floor_param[i]);
 
-   for(i=0;i<ci->residues;i++)
 
-     b->residue[i]=_residue_P[ci->residue_type[i]]->
 
-       look(v,ci->residue_param[i]);
 
-   return 0;
 
-  abort_books:
 
-   for(i=0;i<ci->books;i++){
 
-     if(ci->book_param[i]!=NULL){
 
-       vorbis_staticbook_destroy(ci->book_param[i]);
 
-       ci->book_param[i]=NULL;
 
-     }
 
-   }
 
-   vorbis_dsp_clear(v);
 
-   return -1;
 
- }
 
- /* arbitrary settings and spec-mandated numbers get filled in here */
 
- int vorbis_analysis_init(vorbis_dsp_state *v,vorbis_info *vi){
 
-   private_state *b=NULL;
 
-   if(_vds_shared_init(v,vi,1))return 1;
 
-   b=v->backend_state;
 
-   b->psy_g_look=_vp_global_look(vi);
 
-   /* Initialize the envelope state storage */
 
-   b->ve=_ogg_calloc(1,sizeof(*b->ve));
 
-   _ve_envelope_init(b->ve,vi);
 
-   vorbis_bitrate_init(vi,&b->bms);
 
-   /* compressed audio packets start after the headers
 
-      with sequence number 3 */
 
-   v->sequence=3;
 
-   return(0);
 
- }
 
- void vorbis_dsp_clear(vorbis_dsp_state *v){
 
-   int i;
 
-   if(v){
 
-     vorbis_info *vi=v->vi;
 
-     codec_setup_info *ci=(vi?vi->codec_setup:NULL);
 
-     private_state *b=v->backend_state;
 
-     if(b){
 
-       if(b->ve){
 
-         _ve_envelope_clear(b->ve);
 
-         _ogg_free(b->ve);
 
-       }
 
-       if(b->transform[0]){
 
-         mdct_clear(b->transform[0][0]);
 
-         _ogg_free(b->transform[0][0]);
 
-         _ogg_free(b->transform[0]);
 
-       }
 
-       if(b->transform[1]){
 
-         mdct_clear(b->transform[1][0]);
 
-         _ogg_free(b->transform[1][0]);
 
-         _ogg_free(b->transform[1]);
 
-       }
 
-       if(b->flr){
 
-         if(ci)
 
-           for(i=0;i<ci->floors;i++)
 
-             _floor_P[ci->floor_type[i]]->
 
-               free_look(b->flr[i]);
 
-         _ogg_free(b->flr);
 
-       }
 
-       if(b->residue){
 
-         if(ci)
 
-           for(i=0;i<ci->residues;i++)
 
-             _residue_P[ci->residue_type[i]]->
 
-               free_look(b->residue[i]);
 
-         _ogg_free(b->residue);
 
-       }
 
-       if(b->psy){
 
-         if(ci)
 
-           for(i=0;i<ci->psys;i++)
 
-             _vp_psy_clear(b->psy+i);
 
-         _ogg_free(b->psy);
 
-       }
 
-       if(b->psy_g_look)_vp_global_free(b->psy_g_look);
 
-       vorbis_bitrate_clear(&b->bms);
 
-       drft_clear(&b->fft_look[0]);
 
-       drft_clear(&b->fft_look[1]);
 
-     }
 
-     if(v->pcm){
 
-       if(vi)
 
-         for(i=0;i<vi->channels;i++)
 
-           if(v->pcm[i])_ogg_free(v->pcm[i]);
 
-       _ogg_free(v->pcm);
 
-       if(v->pcmret)_ogg_free(v->pcmret);
 
-     }
 
-     if(b){
 
-       /* free header, header1, header2 */
 
-       if(b->header)_ogg_free(b->header);
 
-       if(b->header1)_ogg_free(b->header1);
 
-       if(b->header2)_ogg_free(b->header2);
 
-       _ogg_free(b);
 
-     }
 
-     memset(v,0,sizeof(*v));
 
-   }
 
- }
 
- float **vorbis_analysis_buffer(vorbis_dsp_state *v, int vals){
 
-   int i;
 
-   vorbis_info *vi=v->vi;
 
-   private_state *b=v->backend_state;
 
-   /* free header, header1, header2 */
 
-   if(b->header)_ogg_free(b->header);b->header=NULL;
 
-   if(b->header1)_ogg_free(b->header1);b->header1=NULL;
 
-   if(b->header2)_ogg_free(b->header2);b->header2=NULL;
 
-   /* Do we have enough storage space for the requested buffer? If not,
 
-      expand the PCM (and envelope) storage */
 
-   if(v->pcm_current+vals>=v->pcm_storage){
 
-     v->pcm_storage=v->pcm_current+vals*2;
 
-     for(i=0;i<vi->channels;i++){
 
-       v->pcm[i]=_ogg_realloc(v->pcm[i],v->pcm_storage*sizeof(*v->pcm[i]));
 
-     }
 
-   }
 
-   for(i=0;i<vi->channels;i++)
 
-     v->pcmret[i]=v->pcm[i]+v->pcm_current;
 
-   return(v->pcmret);
 
- }
 
- static void _preextrapolate_helper(vorbis_dsp_state *v){
 
-   int i;
 
-   int order=16;
 
-   float *lpc=alloca(order*sizeof(*lpc));
 
-   float *work=alloca(v->pcm_current*sizeof(*work));
 
-   long j;
 
-   v->preextrapolate=1;
 
-   if(v->pcm_current-v->centerW>order*2){ /* safety */
 
-     for(i=0;i<v->vi->channels;i++){
 
-       /* need to run the extrapolation in reverse! */
 
-       for(j=0;j<v->pcm_current;j++)
 
-         work[j]=v->pcm[i][v->pcm_current-j-1];
 
-       /* prime as above */
 
-       vorbis_lpc_from_data(work,lpc,v->pcm_current-v->centerW,order);
 
- #if 0
 
-       if(v->vi->channels==2){
 
-         if(i==0)
 
-           _analysis_output("predataL",0,work,v->pcm_current-v->centerW,0,0,0);
 
-         else
 
-           _analysis_output("predataR",0,work,v->pcm_current-v->centerW,0,0,0);
 
-       }else{
 
-         _analysis_output("predata",0,work,v->pcm_current-v->centerW,0,0,0);
 
-       }
 
- #endif
 
-       /* run the predictor filter */
 
-       vorbis_lpc_predict(lpc,work+v->pcm_current-v->centerW-order,
 
-                          order,
 
-                          work+v->pcm_current-v->centerW,
 
-                          v->centerW);
 
-       for(j=0;j<v->pcm_current;j++)
 
-         v->pcm[i][v->pcm_current-j-1]=work[j];
 
-     }
 
-   }
 
- }
 
- /* call with val<=0 to set eof */
 
- int vorbis_analysis_wrote(vorbis_dsp_state *v, int vals){
 
-   vorbis_info *vi=v->vi;
 
-   codec_setup_info *ci=vi->codec_setup;
 
-   if(vals<=0){
 
-     int order=32;
 
-     int i;
 
-     float *lpc=alloca(order*sizeof(*lpc));
 
-     /* if it wasn't done earlier (very short sample) */
 
-     if(!v->preextrapolate)
 
-       _preextrapolate_helper(v);
 
-     /* We're encoding the end of the stream.  Just make sure we have
 
-        [at least] a few full blocks of zeroes at the end. */
 
-     /* actually, we don't want zeroes; that could drop a large
 
-        amplitude off a cliff, creating spread spectrum noise that will
 
-        suck to encode.  Extrapolate for the sake of cleanliness. */
 
-     vorbis_analysis_buffer(v,ci->blocksizes[1]*3);
 
-     v->eofflag=v->pcm_current;
 
-     v->pcm_current+=ci->blocksizes[1]*3;
 
-     for(i=0;i<vi->channels;i++){
 
-       if(v->eofflag>order*2){
 
-         /* extrapolate with LPC to fill in */
 
-         long n;
 
-         /* make a predictor filter */
 
-         n=v->eofflag;
 
-         if(n>ci->blocksizes[1])n=ci->blocksizes[1];
 
-         vorbis_lpc_from_data(v->pcm[i]+v->eofflag-n,lpc,n,order);
 
-         /* run the predictor filter */
 
-         vorbis_lpc_predict(lpc,v->pcm[i]+v->eofflag-order,order,
 
-                            v->pcm[i]+v->eofflag,v->pcm_current-v->eofflag);
 
-       }else{
 
-         /* not enough data to extrapolate (unlikely to happen due to
 
-            guarding the overlap, but bulletproof in case that
 
-            assumtion goes away). zeroes will do. */
 
-         memset(v->pcm[i]+v->eofflag,0,
 
-                (v->pcm_current-v->eofflag)*sizeof(*v->pcm[i]));
 
-       }
 
-     }
 
-   }else{
 
-     if(v->pcm_current+vals>v->pcm_storage)
 
-       return(OV_EINVAL);
 
-     v->pcm_current+=vals;
 
-     /* we may want to reverse extrapolate the beginning of a stream
 
-        too... in case we're beginning on a cliff! */
 
-     /* clumsy, but simple.  It only runs once, so simple is good. */
 
-     if(!v->preextrapolate && v->pcm_current-v->centerW>ci->blocksizes[1])
 
-       _preextrapolate_helper(v);
 
-   }
 
-   return(0);
 
- }
 
- /* do the deltas, envelope shaping, pre-echo and determine the size of
 
-    the next block on which to continue analysis */
 
- int vorbis_analysis_blockout(vorbis_dsp_state *v,vorbis_block *vb){
 
-   int i;
 
-   vorbis_info *vi=v->vi;
 
-   codec_setup_info *ci=vi->codec_setup;
 
-   private_state *b=v->backend_state;
 
-   vorbis_look_psy_global *g=b->psy_g_look;
 
-   long beginW=v->centerW-ci->blocksizes[v->W]/2,centerNext;
 
-   vorbis_block_internal *vbi=(vorbis_block_internal *)vb->internal;
 
-   /* check to see if we're started... */
 
-   if(!v->preextrapolate)return(0);
 
-   /* check to see if we're done... */
 
-   if(v->eofflag==-1)return(0);
 
-   /* By our invariant, we have lW, W and centerW set.  Search for
 
-      the next boundary so we can determine nW (the next window size)
 
-      which lets us compute the shape of the current block's window */
 
-   /* we do an envelope search even on a single blocksize; we may still
 
-      be throwing more bits at impulses, and envelope search handles
 
-      marking impulses too. */
 
-   {
 
-     long bp=_ve_envelope_search(v);
 
-     if(bp==-1){
 
-       if(v->eofflag==0)return(0); /* not enough data currently to search for a
 
-                                      full long block */
 
-       v->nW=0;
 
-     }else{
 
-       if(ci->blocksizes[0]==ci->blocksizes[1])
 
-         v->nW=0;
 
-       else
 
-         v->nW=bp;
 
-     }
 
-   }
 
-   centerNext=v->centerW+ci->blocksizes[v->W]/4+ci->blocksizes[v->nW]/4;
 
-   {
 
-     /* center of next block + next block maximum right side. */
 
-     long blockbound=centerNext+ci->blocksizes[v->nW]/2;
 
-     if(v->pcm_current<blockbound)return(0); /* not enough data yet;
 
-                                                although this check is
 
-                                                less strict that the
 
-                                                _ve_envelope_search,
 
-                                                the search is not run
 
-                                                if we only use one
 
-                                                block size */
 
-   }
 
-   /* fill in the block.  Note that for a short window, lW and nW are *short*
 
-      regardless of actual settings in the stream */
 
-   _vorbis_block_ripcord(vb);
 
-   vb->lW=v->lW;
 
-   vb->W=v->W;
 
-   vb->nW=v->nW;
 
-   if(v->W){
 
-     if(!v->lW || !v->nW){
 
-       vbi->blocktype=BLOCKTYPE_TRANSITION;
 
-       /*fprintf(stderr,"-");*/
 
-     }else{
 
-       vbi->blocktype=BLOCKTYPE_LONG;
 
-       /*fprintf(stderr,"_");*/
 
-     }
 
-   }else{
 
-     if(_ve_envelope_mark(v)){
 
-       vbi->blocktype=BLOCKTYPE_IMPULSE;
 
-       /*fprintf(stderr,"|");*/
 
-     }else{
 
-       vbi->blocktype=BLOCKTYPE_PADDING;
 
-       /*fprintf(stderr,".");*/
 
-     }
 
-   }
 
-   vb->vd=v;
 
-   vb->sequence=v->sequence++;
 
-   vb->granulepos=v->granulepos;
 
-   vb->pcmend=ci->blocksizes[v->W];
 
-   /* copy the vectors; this uses the local storage in vb */
 
-   /* this tracks 'strongest peak' for later psychoacoustics */
 
-   /* moved to the global psy state; clean this mess up */
 
-   if(vbi->ampmax>g->ampmax)g->ampmax=vbi->ampmax;
 
-   g->ampmax=_vp_ampmax_decay(g->ampmax,v);
 
-   vbi->ampmax=g->ampmax;
 
-   vb->pcm=_vorbis_block_alloc(vb,sizeof(*vb->pcm)*vi->channels);
 
-   vbi->pcmdelay=_vorbis_block_alloc(vb,sizeof(*vbi->pcmdelay)*vi->channels);
 
-   for(i=0;i<vi->channels;i++){
 
-     vbi->pcmdelay[i]=
 
-       _vorbis_block_alloc(vb,(vb->pcmend+beginW)*sizeof(*vbi->pcmdelay[i]));
 
-     memcpy(vbi->pcmdelay[i],v->pcm[i],(vb->pcmend+beginW)*sizeof(*vbi->pcmdelay[i]));
 
-     vb->pcm[i]=vbi->pcmdelay[i]+beginW;
 
-     /* before we added the delay
 
-        vb->pcm[i]=_vorbis_block_alloc(vb,vb->pcmend*sizeof(*vb->pcm[i]));
 
-        memcpy(vb->pcm[i],v->pcm[i]+beginW,ci->blocksizes[v->W]*sizeof(*vb->pcm[i]));
 
-     */
 
-   }
 
-   /* handle eof detection: eof==0 means that we've not yet received EOF
 
-                            eof>0  marks the last 'real' sample in pcm[]
 
-                            eof<0  'no more to do'; doesn't get here */
 
-   if(v->eofflag){
 
-     if(v->centerW>=v->eofflag){
 
-       v->eofflag=-1;
 
-       vb->eofflag=1;
 
-       return(1);
 
-     }
 
-   }
 
-   /* advance storage vectors and clean up */
 
-   {
 
-     int new_centerNext=ci->blocksizes[1]/2;
 
-     int movementW=centerNext-new_centerNext;
 
-     if(movementW>0){
 
-       _ve_envelope_shift(b->ve,movementW);
 
-       v->pcm_current-=movementW;
 
-       for(i=0;i<vi->channels;i++)
 
-         memmove(v->pcm[i],v->pcm[i]+movementW,
 
-                 v->pcm_current*sizeof(*v->pcm[i]));
 
-       v->lW=v->W;
 
-       v->W=v->nW;
 
-       v->centerW=new_centerNext;
 
-       if(v->eofflag){
 
-         v->eofflag-=movementW;
 
-         if(v->eofflag<=0)v->eofflag=-1;
 
-         /* do not add padding to end of stream! */
 
-         if(v->centerW>=v->eofflag){
 
-           v->granulepos+=movementW-(v->centerW-v->eofflag);
 
-         }else{
 
-           v->granulepos+=movementW;
 
-         }
 
-       }else{
 
-         v->granulepos+=movementW;
 
-       }
 
-     }
 
-   }
 
-   /* done */
 
-   return(1);
 
- }
 
- int vorbis_synthesis_restart(vorbis_dsp_state *v){
 
-   vorbis_info *vi=v->vi;
 
-   codec_setup_info *ci;
 
-   int hs;
 
-   if(!v->backend_state)return -1;
 
-   if(!vi)return -1;
 
-   ci=vi->codec_setup;
 
-   if(!ci)return -1;
 
-   hs=ci->halfrate_flag;
 
-   v->centerW=ci->blocksizes[1]>>(hs+1);
 
-   v->pcm_current=v->centerW>>hs;
 
-   v->pcm_returned=-1;
 
-   v->granulepos=-1;
 
-   v->sequence=-1;
 
-   v->eofflag=0;
 
-   ((private_state *)(v->backend_state))->sample_count=-1;
 
-   return(0);
 
- }
 
- int vorbis_synthesis_init(vorbis_dsp_state *v,vorbis_info *vi){
 
-   if(_vds_shared_init(v,vi,0)){
 
-     vorbis_dsp_clear(v);
 
-     return 1;
 
-   }
 
-   vorbis_synthesis_restart(v);
 
-   return 0;
 
- }
 
- int vorbis_synthesis_samplecount(vorbis_dsp_state *v){
 
- 	return ((private_state *)v->backend_state)->sample_count;
 
- }
 
- /* Unlike in analysis, the window is only partially applied for each
 
-    block.  The time domain envelope is not yet handled at the point of
 
-    calling (as it relies on the previous block). */
 
- int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb){
 
-   vorbis_info *vi=v->vi;
 
-   codec_setup_info *ci=vi->codec_setup;
 
-   private_state *b=v->backend_state;
 
-   int hs=ci->halfrate_flag;
 
-   int i,j;
 
-   if(!vb)return(OV_EINVAL);
 
-   if(v->pcm_current>v->pcm_returned  && v->pcm_returned!=-1)return(OV_EINVAL);
 
-   v->lW=v->W;
 
-   v->W=vb->W;
 
-   v->nW=-1;
 
-   if((v->sequence==-1)||
 
-      (v->sequence+1 != vb->sequence)){
 
-     v->granulepos=-1; /* out of sequence; lose count */
 
-     b->sample_count=-1;
 
-   }
 
-   v->sequence=vb->sequence;
 
-   if(vb->pcm){  /* no pcm to process if vorbis_synthesis_trackonly
 
-                    was called on block */
 
-     int n=ci->blocksizes[v->W]>>(hs+1);
 
-     int n0=ci->blocksizes[0]>>(hs+1);
 
-     int n1=ci->blocksizes[1]>>(hs+1);
 
-     int thisCenter;
 
-     int prevCenter;
 
-     v->glue_bits+=vb->glue_bits;
 
-     v->time_bits+=vb->time_bits;
 
-     v->floor_bits+=vb->floor_bits;
 
-     v->res_bits+=vb->res_bits;
 
-     if(v->centerW){
 
-       thisCenter=n1;
 
-       prevCenter=0;
 
-     }else{
 
-       thisCenter=0;
 
-       prevCenter=n1;
 
-     }
 
-     /* v->pcm is now used like a two-stage double buffer.  We don't want
 
-        to have to constantly shift *or* adjust memory usage.  Don't
 
-        accept a new block until the old is shifted out */
 
-     for(j=0;j<vi->channels;j++){
 
-       /* the overlap/add section */
 
-       if(v->lW){
 
-         if(v->W){
 
-           /* large/large */
 
-           const float *w=_vorbis_window_get(b->window[1]-hs);
 
-           float *pcm=v->pcm[j]+prevCenter;
 
-           float *p=vb->pcm[j];
 
-           for(i=0;i<n1;i++)
 
-             pcm[i]=pcm[i]*w[n1-i-1] + p[i]*w[i];
 
-         }else{
 
-           /* large/small */
 
-           const float *w=_vorbis_window_get(b->window[0]-hs);
 
-           float *pcm=v->pcm[j]+prevCenter+n1/2-n0/2;
 
-           float *p=vb->pcm[j];
 
-           for(i=0;i<n0;i++)
 
-             pcm[i]=pcm[i]*w[n0-i-1] +p[i]*w[i];
 
-         }
 
-       }else{
 
-         if(v->W){
 
-           /* small/large */
 
-           const float *w=_vorbis_window_get(b->window[0]-hs);
 
-           float *pcm=v->pcm[j]+prevCenter;
 
-           float *p=vb->pcm[j]+n1/2-n0/2;
 
-           for(i=0;i<n0;i++)
 
-             pcm[i]=pcm[i]*w[n0-i-1] +p[i]*w[i];
 
-           for(;i<n1/2+n0/2;i++)
 
-             pcm[i]=p[i];
 
-         }else{
 
-           /* small/small */
 
-           const float *w=_vorbis_window_get(b->window[0]-hs);
 
-           float *pcm=v->pcm[j]+prevCenter;
 
-           float *p=vb->pcm[j];
 
-           for(i=0;i<n0;i++)
 
-             pcm[i]=pcm[i]*w[n0-i-1] +p[i]*w[i];
 
-         }
 
-       }
 
-       /* the copy section */
 
-       {
 
-         float *pcm=v->pcm[j]+thisCenter;
 
-         float *p=vb->pcm[j]+n;
 
-         for(i=0;i<n;i++)
 
-           pcm[i]=p[i];
 
-       }
 
-     }
 
-     if(v->centerW)
 
-       v->centerW=0;
 
-     else
 
-       v->centerW=n1;
 
-     /* deal with initial packet state; we do this using the explicit
 
-        pcm_returned==-1 flag otherwise we're sensitive to first block
 
-        being short or long */
 
-     if(v->pcm_returned==-1){
 
-       v->pcm_returned=thisCenter;
 
-       v->pcm_current=thisCenter;
 
-     }else{
 
-       v->pcm_returned=prevCenter;
 
-       v->pcm_current=prevCenter+
 
-         ((ci->blocksizes[v->lW]/4+
 
-         ci->blocksizes[v->W]/4)>>hs);
 
-     }
 
-   }
 
-   /* track the frame number... This is for convenience, but also
 
-      making sure our last packet doesn't end with added padding.  If
 
-      the last packet is partial, the number of samples we'll have to
 
-      return will be past the vb->granulepos.
 
-      This is not foolproof!  It will be confused if we begin
 
-      decoding at the last page after a seek or hole.  In that case,
 
-      we don't have a starting point to judge where the last frame
 
-      is.  For this reason, vorbisfile will always try to make sure
 
-      it reads the last two marked pages in proper sequence */
 
-   if(b->sample_count==-1){
 
-     b->sample_count=0;
 
-   }else{
 
-     b->sample_count+=ci->blocksizes[v->lW]/4+ci->blocksizes[v->W]/4;
 
-   }
 
-   if(v->granulepos==-1){
 
-     if(vb->granulepos!=-1){ /* only set if we have a position to set to */
 
-       v->granulepos=vb->granulepos;
 
-       /* is this a short page? */
 
-       if(b->sample_count>v->granulepos){
 
-         /* corner case; if this is both the first and last audio page,
 
-            then spec says the end is cut, not beginning */
 
-        long extra=b->sample_count-vb->granulepos;
 
-         /* we use ogg_int64_t for granule positions because a
 
-            uint64 isn't universally available.  Unfortunately,
 
-            that means granposes can be 'negative' and result in
 
-            extra being negative */
 
-         if(extra<0)
 
-           extra=0;
 
-         if(vb->eofflag){
 
-           /* trim the end */
 
-           /* no preceding granulepos; assume we started at zero (we'd
 
-              have to in a short single-page stream) */
 
-           /* granulepos could be -1 due to a seek, but that would result
 
-              in a long count, not short count */
 
-           /* Guard against corrupt/malicious frames that set EOP and
 
-              a backdated granpos; don't rewind more samples than we
 
-              actually have */
 
-           if(extra > (v->pcm_current - v->pcm_returned)<<hs)
 
-             extra = (v->pcm_current - v->pcm_returned)<<hs;
 
-           v->pcm_current-=extra>>hs;
 
-         }else{
 
-           /* trim the beginning */
 
-           v->pcm_returned+=extra>>hs;
 
-           if(v->pcm_returned>v->pcm_current)
 
-             v->pcm_returned=v->pcm_current;
 
-         }
 
-       }
 
-     }
 
-   }else{
 
-     v->granulepos+=ci->blocksizes[v->lW]/4+ci->blocksizes[v->W]/4;
 
-     if(vb->granulepos!=-1 && v->granulepos!=vb->granulepos){
 
-       if(v->granulepos>vb->granulepos){
 
-         long extra=v->granulepos-vb->granulepos;
 
-         if(extra)
 
-           if(vb->eofflag){
 
-             /* partial last frame.  Strip the extra samples off */
 
-             /* Guard against corrupt/malicious frames that set EOP and
 
-                a backdated granpos; don't rewind more samples than we
 
-                actually have */
 
-             if(extra > (v->pcm_current - v->pcm_returned)<<hs)
 
-               extra = (v->pcm_current - v->pcm_returned)<<hs;
 
-             /* we use ogg_int64_t for granule positions because a
 
-                uint64 isn't universally available.  Unfortunately,
 
-                that means granposes can be 'negative' and result in
 
-                extra being negative */
 
-             if(extra<0)
 
-               extra=0;
 
-             v->pcm_current-=extra>>hs;
 
-           } /* else {Shouldn't happen *unless* the bitstream is out of
 
-                spec.  Either way, believe the bitstream } */
 
-       } /* else {Shouldn't happen *unless* the bitstream is out of
 
-            spec.  Either way, believe the bitstream } */
 
-       v->granulepos=vb->granulepos;
 
-     }
 
-   }
 
-   /* Update, cleanup */
 
-   if(vb->eofflag)v->eofflag=1;
 
-   return(0);
 
- }
 
- /* pcm==NULL indicates we just want the pending samples, no more */
 
- int vorbis_synthesis_pcmout(vorbis_dsp_state *v,float ***pcm){
 
-   vorbis_info *vi=v->vi;
 
-   if(v->pcm_returned>-1 && v->pcm_returned<v->pcm_current){
 
-     if(pcm){
 
-       int i;
 
-       for(i=0;i<vi->channels;i++)
 
-         v->pcmret[i]=v->pcm[i]+v->pcm_returned;
 
-       *pcm=v->pcmret;
 
-     }
 
-     return(v->pcm_current-v->pcm_returned);
 
-   }
 
-   return(0);
 
- }
 
- int vorbis_synthesis_read(vorbis_dsp_state *v,int n){
 
-   if(n && v->pcm_returned+n>v->pcm_current)return(OV_EINVAL);
 
-   v->pcm_returned+=n;
 
-   return(0);
 
- }
 
- /* intended for use with a specific vorbisfile feature; we want access
 
-    to the [usually synthetic/postextrapolated] buffer and lapping at
 
-    the end of a decode cycle, specifically, a half-short-block worth.
 
-    This funtion works like pcmout above, except it will also expose
 
-    this implicit buffer data not normally decoded. */
 
- int vorbis_synthesis_lapout(vorbis_dsp_state *v,float ***pcm){
 
-   vorbis_info *vi=v->vi;
 
-   codec_setup_info *ci=vi->codec_setup;
 
-   int hs=ci->halfrate_flag;
 
-   int n=ci->blocksizes[v->W]>>(hs+1);
 
-   int n0=ci->blocksizes[0]>>(hs+1);
 
-   int n1=ci->blocksizes[1]>>(hs+1);
 
-   int i,j;
 
-   if(v->pcm_returned<0)return 0;
 
-   /* our returned data ends at pcm_returned; because the synthesis pcm
 
-      buffer is a two-fragment ring, that means our data block may be
 
-      fragmented by buffering, wrapping or a short block not filling
 
-      out a buffer.  To simplify things, we unfragment if it's at all
 
-      possibly needed. Otherwise, we'd need to call lapout more than
 
-      once as well as hold additional dsp state.  Opt for
 
-      simplicity. */
 
-   /* centerW was advanced by blockin; it would be the center of the
 
-      *next* block */
 
-   if(v->centerW==n1){
 
-     /* the data buffer wraps; swap the halves */
 
-     /* slow, sure, small */
 
-     for(j=0;j<vi->channels;j++){
 
-       float *p=v->pcm[j];
 
-       for(i=0;i<n1;i++){
 
-         float temp=p[i];
 
-         p[i]=p[i+n1];
 
-         p[i+n1]=temp;
 
-       }
 
-     }
 
-     v->pcm_current-=n1;
 
-     v->pcm_returned-=n1;
 
-     v->centerW=0;
 
-   }
 
-   /* solidify buffer into contiguous space */
 
-   if((v->lW^v->W)==1){
 
-     /* long/short or short/long */
 
-     for(j=0;j<vi->channels;j++){
 
-       float *s=v->pcm[j];
 
-       float *d=v->pcm[j]+(n1-n0)/2;
 
-       for(i=(n1+n0)/2-1;i>=0;--i)
 
-         d[i]=s[i];
 
-     }
 
-     v->pcm_returned+=(n1-n0)/2;
 
-     v->pcm_current+=(n1-n0)/2;
 
-   }else{
 
-     if(v->lW==0){
 
-       /* short/short */
 
-       for(j=0;j<vi->channels;j++){
 
-         float *s=v->pcm[j];
 
-         float *d=v->pcm[j]+n1-n0;
 
-         for(i=n0-1;i>=0;--i)
 
-           d[i]=s[i];
 
-       }
 
-       v->pcm_returned+=n1-n0;
 
-       v->pcm_current+=n1-n0;
 
-     }
 
-   }
 
-   if(pcm){
 
-     int i;
 
-     for(i=0;i<vi->channels;i++)
 
-       v->pcmret[i]=v->pcm[i]+v->pcm_returned;
 
-     *pcm=v->pcmret;
 
-   }
 
-   return(n1+n-v->pcm_returned);
 
- }
 
- const float *vorbis_window(vorbis_dsp_state *v,int W){
 
-   vorbis_info *vi=v->vi;
 
-   codec_setup_info *ci=vi->codec_setup;
 
-   int hs=ci->halfrate_flag;
 
-   private_state *b=v->backend_state;
 
-   if(b->window[W]-1<0)return NULL;
 
-   return _vorbis_window_get(b->window[W]-hs);
 
- }
 
 
  |