vorbisfile.c - vx32 - Local 9vx git repository for patches.
 (HTM) git clone git://r-36.net/vx32
 (DIR) Log
 (DIR) Files
 (DIR) Refs
       ---
       vorbisfile.c (57581B)
       ---
            1 /********************************************************************
            2  *                                                                  *
            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.       *
            7  *                                                                  *
            8  * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002             *
            9  * by the XIPHOPHORUS Company http://www.xiph.org/                  *
           10  *                                                                  *
           11  ********************************************************************
           12 
           13  function: stdio-based convenience library for opening/seeking/decoding
           14  last mod: $Id: vorbisfile.c 1919 2005-07-24 14:18:04Z baford $
           15 
           16  ********************************************************************/
           17 
           18 #include <stdlib.h>
           19 #include <stdio.h>
           20 #include <errno.h>
           21 #include <string.h>
           22 #include <math.h>
           23 
           24 #include "vorbis/codec.h"
           25 #include "vorbis/vorbisfile.h"
           26 
           27 #include "os.h"
           28 #include "misc.h"
           29 
           30 /* A 'chained bitstream' is a Vorbis bitstream that contains more than
           31    one logical bitstream arranged end to end (the only form of Ogg
           32    multiplexing allowed in a Vorbis bitstream; grouping [parallel
           33    multiplexing] is not allowed in Vorbis) */
           34 
           35 /* A Vorbis file can be played beginning to end (streamed) without
           36    worrying ahead of time about chaining (see decoder_example.c).  If
           37    we have the whole file, however, and want random access
           38    (seeking/scrubbing) or desire to know the total length/time of a
           39    file, we need to account for the possibility of chaining. */
           40 
           41 /* We can handle things a number of ways; we can determine the entire
           42    bitstream structure right off the bat, or find pieces on demand.
           43    This example determines and caches structure for the entire
           44    bitstream, but builds a virtual decoder on the fly when moving
           45    between links in the chain. */
           46 
           47 /* There are also different ways to implement seeking.  Enough
           48    information exists in an Ogg bitstream to seek to
           49    sample-granularity positions in the output.  Or, one can seek by
           50    picking some portion of the stream roughly in the desired area if
           51    we only want coarse navigation through the stream. */
           52 
           53 /*************************************************************************
           54  * Many, many internal helpers.  The intention is not to be confusing; 
           55  * rampant duplication and monolithic function implementation would be 
           56  * harder to understand anyway.  The high level functions are last.  Begin
           57  * grokking near the end of the file */
           58 
           59 /* read a little more data from the file/pipe into the ogg_sync framer
           60 */
           61 #define CHUNKSIZE 8500 /* a shade over 8k; anyone using pages well
           62                           over 8k gets what they deserve */
           63 static long _get_data(OggVorbis_File *vf){
           64   errno=0;
           65   if(vf->datasource){
           66     char *buffer=ogg_sync_buffer(&vf->oy,CHUNKSIZE);
           67     long bytes=(vf->callbacks.read_func)(buffer,1,CHUNKSIZE,vf->datasource);
           68     if(bytes>0)ogg_sync_wrote(&vf->oy,bytes);
           69     if(bytes==0 && errno)return(-1);
           70     return(bytes);
           71   }else
           72     return(0);
           73 }
           74 
           75 /* save a tiny smidge of verbosity to make the code more readable */
           76 static void _seek_helper(OggVorbis_File *vf,ogg_int64_t offset){
           77   if(vf->datasource){ 
           78     (vf->callbacks.seek_func)(vf->datasource, offset, SEEK_SET);
           79     vf->offset=offset;
           80     ogg_sync_reset(&vf->oy);
           81   }else{
           82     /* shouldn't happen unless someone writes a broken callback */
           83     return;
           84   }
           85 }
           86 
           87 /* The read/seek functions track absolute position within the stream */
           88 
           89 /* from the head of the stream, get the next page.  boundary specifies
           90    if the function is allowed to fetch more data from the stream (and
           91    how much) or only use internally buffered data.
           92 
           93    boundary: -1) unbounded search
           94               0) read no additional data; use cached only
           95               n) search for a new page beginning for n bytes
           96 
           97    return:   <0) did not find a page (OV_FALSE, OV_EOF, OV_EREAD)
           98               n) found a page at absolute offset n */
           99 
          100 static ogg_int64_t _get_next_page(OggVorbis_File *vf,ogg_page *og,
          101                                   ogg_int64_t boundary){
          102   if(boundary>0)boundary+=vf->offset;
          103   while(1){
          104     long more;
          105 
          106     if(boundary>0 && vf->offset>=boundary)return(OV_FALSE);
          107     more=ogg_sync_pageseek(&vf->oy,og);
          108     
          109     if(more<0){
          110       /* skipped n bytes */
          111       vf->offset-=more;
          112     }else{
          113       if(more==0){
          114         /* send more paramedics */
          115         if(!boundary)return(OV_FALSE);
          116         {
          117           long ret=_get_data(vf);
          118           if(ret==0)return(OV_EOF);
          119           if(ret<0)return(OV_EREAD);
          120         }
          121       }else{
          122         /* got a page.  Return the offset at the page beginning,
          123            advance the internal offset past the page end */
          124         ogg_int64_t ret=vf->offset;
          125         vf->offset+=more;
          126         return(ret);
          127         
          128       }
          129     }
          130   }
          131 }
          132 
          133 /* find the latest page beginning before the current stream cursor
          134    position. Much dirtier than the above as Ogg doesn't have any
          135    backward search linkage.  no 'readp' as it will certainly have to
          136    read. */
          137 /* returns offset or OV_EREAD, OV_FAULT */
          138 static ogg_int64_t _get_prev_page(OggVorbis_File *vf,ogg_page *og){
          139   ogg_int64_t begin=vf->offset;
          140   ogg_int64_t end=begin;
          141   ogg_int64_t ret;
          142   ogg_int64_t offset=-1;
          143 
          144   while(offset==-1){
          145     begin-=CHUNKSIZE;
          146     if(begin<0)
          147       begin=0;
          148     _seek_helper(vf,begin);
          149     while(vf->offset<end){
          150       ret=_get_next_page(vf,og,end-vf->offset);
          151       if(ret==OV_EREAD)return(OV_EREAD);
          152       if(ret<0){
          153         break;
          154       }else{
          155         offset=ret;
          156       }
          157     }
          158   }
          159 
          160   /* we have the offset.  Actually snork and hold the page now */
          161   _seek_helper(vf,offset);
          162   ret=_get_next_page(vf,og,CHUNKSIZE);
          163   if(ret<0)
          164     /* this shouldn't be possible */
          165     return(OV_EFAULT);
          166 
          167   return(offset);
          168 }
          169 
          170 /* finds each bitstream link one at a time using a bisection search
          171    (has to begin by knowing the offset of the lb's initial page).
          172    Recurses for each link so it can alloc the link storage after
          173    finding them all, then unroll and fill the cache at the same time */
          174 static int _bisect_forward_serialno(OggVorbis_File *vf,
          175                                     ogg_int64_t begin,
          176                                     ogg_int64_t searched,
          177                                     ogg_int64_t end,
          178                                     long currentno,
          179                                     long m){
          180   ogg_int64_t endsearched=end;
          181   ogg_int64_t next=end;
          182   ogg_page og;
          183   ogg_int64_t ret;
          184   
          185   /* the below guards against garbage seperating the last and
          186      first pages of two links. */
          187   while(searched<endsearched){
          188     ogg_int64_t bisect;
          189     
          190     if(endsearched-searched<CHUNKSIZE){
          191       bisect=searched;
          192     }else{
          193       bisect=(searched+endsearched)/2;
          194     }
          195     
          196     _seek_helper(vf,bisect);
          197     ret=_get_next_page(vf,&og,-1);
          198     if(ret==OV_EREAD)return(OV_EREAD);
          199     if(ret<0 || ogg_page_serialno(&og)!=currentno){
          200       endsearched=bisect;
          201       if(ret>=0)next=ret;
          202     }else{
          203       searched=ret+og.header_len+og.body_len;
          204     }
          205   }
          206 
          207   _seek_helper(vf,next);
          208   ret=_get_next_page(vf,&og,-1);
          209   if(ret==OV_EREAD)return(OV_EREAD);
          210   
          211   if(searched>=end || ret<0){
          212     vf->links=m+1;
          213     vf->offsets=_ogg_malloc((vf->links+1)*sizeof(*vf->offsets));
          214     vf->serialnos=_ogg_malloc(vf->links*sizeof(*vf->serialnos));
          215     vf->offsets[m+1]=searched;
          216   }else{
          217     ret=_bisect_forward_serialno(vf,next,vf->offset,
          218                                  end,ogg_page_serialno(&og),m+1);
          219     if(ret==OV_EREAD)return(OV_EREAD);
          220   }
          221   
          222   vf->offsets[m]=begin;
          223   vf->serialnos[m]=currentno;
          224   return(0);
          225 }
          226 
          227 /* uses the local ogg_stream storage in vf; this is important for
          228    non-streaming input sources */
          229 static int _fetch_headers(OggVorbis_File *vf,vorbis_info *vi,vorbis_comment *vc,
          230                           long *serialno,ogg_page *og_ptr){
          231   ogg_page og;
          232   ogg_packet op;
          233   int i,ret;
          234   
          235   if(!og_ptr){
          236     ogg_int64_t llret=_get_next_page(vf,&og,CHUNKSIZE);
          237     if(llret==OV_EREAD)return(OV_EREAD);
          238     if(llret<0)return OV_ENOTVORBIS;
          239     og_ptr=&og;
          240   }
          241 
          242   ogg_stream_reset_serialno(&vf->os,ogg_page_serialno(og_ptr));
          243   if(serialno)*serialno=vf->os.serialno;
          244   vf->ready_state=STREAMSET;
          245   
          246   /* extract the initial header from the first page and verify that the
          247      Ogg bitstream is in fact Vorbis data */
          248   
          249   vorbis_info_init(vi);
          250   vorbis_comment_init(vc);
          251   
          252   i=0;
          253   while(i<3){
          254     ogg_stream_pagein(&vf->os,og_ptr);
          255     while(i<3){
          256       int result=ogg_stream_packetout(&vf->os,&op);
          257       if(result==0)break;
          258       if(result==-1){
          259         ret=OV_EBADHEADER;
          260         goto bail_header;
          261       }
          262       if((ret=vorbis_synthesis_headerin(vi,vc,&op))){
          263         goto bail_header;
          264       }
          265       i++;
          266     }
          267     if(i<3)
          268       if(_get_next_page(vf,og_ptr,CHUNKSIZE)<0){
          269         ret=OV_EBADHEADER;
          270         goto bail_header;
          271       }
          272   }
          273   return 0; 
          274 
          275  bail_header:
          276   vorbis_info_clear(vi);
          277   vorbis_comment_clear(vc);
          278   vf->ready_state=OPENED;
          279 
          280   return ret;
          281 }
          282 
          283 /* last step of the OggVorbis_File initialization; get all the
          284    vorbis_info structs and PCM positions.  Only called by the seekable
          285    initialization (local stream storage is hacked slightly; pay
          286    attention to how that's done) */
          287 
          288 /* this is void and does not propogate errors up because we want to be
          289    able to open and use damaged bitstreams as well as we can.  Just
          290    watch out for missing information for links in the OggVorbis_File
          291    struct */
          292 static void _prefetch_all_headers(OggVorbis_File *vf, ogg_int64_t dataoffset){
          293   ogg_page og;
          294   int i;
          295   ogg_int64_t ret;
          296   
          297   vf->vi=_ogg_realloc(vf->vi,vf->links*sizeof(*vf->vi));
          298   vf->vc=_ogg_realloc(vf->vc,vf->links*sizeof(*vf->vc));
          299   vf->dataoffsets=_ogg_malloc(vf->links*sizeof(*vf->dataoffsets));
          300   vf->pcmlengths=_ogg_malloc(vf->links*2*sizeof(*vf->pcmlengths));
          301   
          302   for(i=0;i<vf->links;i++){
          303     if(i==0){
          304       /* we already grabbed the initial header earlier.  Just set the offset */
          305       vf->dataoffsets[i]=dataoffset;
          306       _seek_helper(vf,dataoffset);
          307 
          308     }else{
          309 
          310       /* seek to the location of the initial header */
          311 
          312       _seek_helper(vf,vf->offsets[i]);
          313       if(_fetch_headers(vf,vf->vi+i,vf->vc+i,NULL,NULL)<0){
          314             vf->dataoffsets[i]=-1;
          315       }else{
          316         vf->dataoffsets[i]=vf->offset;
          317       }
          318     }
          319 
          320     /* fetch beginning PCM offset */
          321 
          322     if(vf->dataoffsets[i]!=-1){
          323       ogg_int64_t accumulated=0;
          324       long        lastblock=-1;
          325       int         result;
          326 
          327       ogg_stream_reset_serialno(&vf->os,vf->serialnos[i]);
          328 
          329       while(1){
          330         ogg_packet op;
          331 
          332         ret=_get_next_page(vf,&og,-1);
          333         if(ret<0)
          334           /* this should not be possible unless the file is
          335              truncated/mangled */
          336           break;
          337        
          338         if(ogg_page_serialno(&og)!=vf->serialnos[i])
          339           break;
          340         
          341         /* count blocksizes of all frames in the page */
          342         ogg_stream_pagein(&vf->os,&og);
          343         while((result=ogg_stream_packetout(&vf->os,&op))){
          344           if(result>0){ /* ignore holes */
          345             long thisblock=vorbis_packet_blocksize(vf->vi+i,&op);
          346             if(lastblock!=-1)
          347               accumulated+=(lastblock+thisblock)>>2;
          348             lastblock=thisblock;
          349           }
          350         }
          351 
          352         if(ogg_page_granulepos(&og)!=-1){
          353           /* pcm offset of last packet on the first audio page */
          354           accumulated= ogg_page_granulepos(&og)-accumulated;
          355           break;
          356         }
          357       }
          358 
          359       /* less than zero?  This is a stream with samples trimmed off
          360          the beginning, a normal occurrence; set the offset to zero */
          361       if(accumulated<0)accumulated=0;
          362 
          363       vf->pcmlengths[i*2]=accumulated;
          364     }
          365 
          366     /* get the PCM length of this link. To do this,
          367        get the last page of the stream */
          368     {
          369       ogg_int64_t end=vf->offsets[i+1];
          370       _seek_helper(vf,end);
          371 
          372       while(1){
          373         ret=_get_prev_page(vf,&og);
          374         if(ret<0){
          375           /* this should not be possible */
          376           vorbis_info_clear(vf->vi+i);
          377           vorbis_comment_clear(vf->vc+i);
          378           break;
          379         }
          380         if(ogg_page_granulepos(&og)!=-1){
          381           vf->pcmlengths[i*2+1]=ogg_page_granulepos(&og)-vf->pcmlengths[i*2];
          382           break;
          383         }
          384         vf->offset=ret;
          385       }
          386     }
          387   }
          388 }
          389 
          390 static int _make_decode_ready(OggVorbis_File *vf){
          391   if(vf->ready_state>STREAMSET)return 0;
          392   if(vf->ready_state<STREAMSET)return OV_EFAULT;
          393   if(vf->seekable){
          394     if(vorbis_synthesis_init(&vf->vd,vf->vi+vf->current_link))
          395       return OV_EBADLINK;
          396   }else{
          397     if(vorbis_synthesis_init(&vf->vd,vf->vi))
          398       return OV_EBADLINK;
          399   }    
          400   vorbis_block_init(&vf->vd,&vf->vb);
          401   vf->ready_state=INITSET;
          402   vf->bittrack=0.f;
          403   vf->samptrack=0.f;
          404   return 0;
          405 }
          406 
          407 static int _open_seekable2(OggVorbis_File *vf){
          408   long serialno=vf->current_serialno;
          409   ogg_int64_t dataoffset=vf->offset, end;
          410   ogg_page og;
          411 
          412   /* we're partially open and have a first link header state in
          413      storage in vf */
          414   /* we can seek, so set out learning all about this file */
          415   (vf->callbacks.seek_func)(vf->datasource,0,SEEK_END);
          416   vf->offset=vf->end=(vf->callbacks.tell_func)(vf->datasource);
          417   
          418   /* We get the offset for the last page of the physical bitstream.
          419      Most OggVorbis files will contain a single logical bitstream */
          420   end=_get_prev_page(vf,&og);
          421   if(end<0)return(end);
          422 
          423   /* more than one logical bitstream? */
          424   if(ogg_page_serialno(&og)!=serialno){
          425 
          426     /* Chained bitstream. Bisect-search each logical bitstream
          427        section.  Do so based on serial number only */
          428     if(_bisect_forward_serialno(vf,0,0,end+1,serialno,0)<0)return(OV_EREAD);
          429 
          430   }else{
          431 
          432     /* Only one logical bitstream */
          433     if(_bisect_forward_serialno(vf,0,end,end+1,serialno,0))return(OV_EREAD);
          434 
          435   }
          436 
          437   /* the initial header memory is referenced by vf after; don't free it */
          438   _prefetch_all_headers(vf,dataoffset);
          439   return(ov_raw_seek(vf,0));
          440 }
          441 
          442 /* clear out the current logical bitstream decoder */ 
          443 static void _decode_clear(OggVorbis_File *vf){
          444   vorbis_dsp_clear(&vf->vd);
          445   vorbis_block_clear(&vf->vb);
          446   vf->ready_state=OPENED;
          447 }
          448 
          449 /* fetch and process a packet.  Handles the case where we're at a
          450    bitstream boundary and dumps the decoding machine.  If the decoding
          451    machine is unloaded, it loads it.  It also keeps pcm_offset up to
          452    date (seek and read both use this.  seek uses a special hack with
          453    readp). 
          454 
          455    return: <0) error, OV_HOLE (lost packet) or OV_EOF
          456             0) need more data (only if readp==0)
          457             1) got a packet 
          458 */
          459 
          460 static int _fetch_and_process_packet(OggVorbis_File *vf,
          461                                      ogg_packet *op_in,
          462                                      int readp,
          463                                      int spanp){
          464   ogg_page og;
          465 
          466   /* handle one packet.  Try to fetch it from current stream state */
          467   /* extract packets from page */
          468   while(1){
          469     
          470     /* process a packet if we can.  If the machine isn't loaded,
          471        neither is a page */
          472     if(vf->ready_state==INITSET){
          473       while(1) {
          474               ogg_packet op;
          475               ogg_packet *op_ptr=(op_in?op_in:&op);
          476         int result=ogg_stream_packetout(&vf->os,op_ptr);
          477         ogg_int64_t granulepos;
          478 
          479         op_in=NULL;
          480         if(result==-1)return(OV_HOLE); /* hole in the data. */
          481         if(result>0){
          482           /* got a packet.  process it */
          483           granulepos=op_ptr->granulepos;
          484           if(!vorbis_synthesis(&vf->vb,op_ptr)){ /* lazy check for lazy
          485                                                     header handling.  The
          486                                                     header packets aren't
          487                                                     audio, so if/when we
          488                                                     submit them,
          489                                                     vorbis_synthesis will
          490                                                     reject them */
          491 
          492             /* suck in the synthesis data and track bitrate */
          493             {
          494               int oldsamples=vorbis_synthesis_pcmout(&vf->vd,NULL);
          495               /* for proper use of libvorbis within libvorbisfile,
          496                  oldsamples will always be zero. */
          497               if(oldsamples)return(OV_EFAULT);
          498               
          499               vorbis_synthesis_blockin(&vf->vd,&vf->vb);
          500               vf->samptrack+=vorbis_synthesis_pcmout(&vf->vd,NULL)-oldsamples;
          501               vf->bittrack+=op_ptr->bytes*8;
          502             }
          503           
          504             /* update the pcm offset. */
          505             if(granulepos!=-1 && !op_ptr->e_o_s){
          506               int link=(vf->seekable?vf->current_link:0);
          507               int i,samples;
          508             
          509               /* this packet has a pcm_offset on it (the last packet
          510                  completed on a page carries the offset) After processing
          511                  (above), we know the pcm position of the *last* sample
          512                  ready to be returned. Find the offset of the *first*
          513 
          514                  As an aside, this trick is inaccurate if we begin
          515                  reading anew right at the last page; the end-of-stream
          516                  granulepos declares the last frame in the stream, and the
          517                  last packet of the last page may be a partial frame.
          518                  So, we need a previous granulepos from an in-sequence page
          519                  to have a reference point.  Thus the !op_ptr->e_o_s clause
          520                  above */
          521 
          522               if(vf->seekable && link>0)
          523                 granulepos-=vf->pcmlengths[link*2];
          524               if(granulepos<0)granulepos=0; /* actually, this
          525                                                shouldn't be possible
          526                                                here unless the stream
          527                                                is very broken */
          528 
          529               samples=vorbis_synthesis_pcmout(&vf->vd,NULL);
          530             
          531               granulepos-=samples;
          532               for(i=0;i<link;i++)
          533                 granulepos+=vf->pcmlengths[i*2+1];
          534               vf->pcm_offset=granulepos;
          535             }
          536             return(1);
          537           }
          538         }
          539         else 
          540           break;
          541       }
          542     }
          543 
          544     if(vf->ready_state>=OPENED){
          545       int ret;
          546       if(!readp)return(0);
          547       if((ret=_get_next_page(vf,&og,-1))<0){
          548         return(OV_EOF); /* eof. 
          549                            leave unitialized */
          550       }
          551 
          552         /* bitrate tracking; add the header's bytes here, the body bytes
          553            are done by packet above */
          554       vf->bittrack+=og.header_len*8;
          555       
          556       /* has our decoding just traversed a bitstream boundary? */
          557       if(vf->ready_state==INITSET){
          558         if(vf->current_serialno!=ogg_page_serialno(&og)){
          559           if(!spanp)
          560             return(OV_EOF);
          561 
          562           _decode_clear(vf);
          563           
          564           if(!vf->seekable){
          565             vorbis_info_clear(vf->vi);
          566             vorbis_comment_clear(vf->vc);
          567           }
          568         }
          569       }
          570     }
          571 
          572     /* Do we need to load a new machine before submitting the page? */
          573     /* This is different in the seekable and non-seekable cases.  
          574 
          575        In the seekable case, we already have all the header
          576        information loaded and cached; we just initialize the machine
          577        with it and continue on our merry way.
          578 
          579        In the non-seekable (streaming) case, we'll only be at a
          580        boundary if we just left the previous logical bitstream and
          581        we're now nominally at the header of the next bitstream
          582     */
          583 
          584     if(vf->ready_state!=INITSET){ 
          585       int link;
          586 
          587       if(vf->ready_state<STREAMSET){
          588         if(vf->seekable){
          589           vf->current_serialno=ogg_page_serialno(&og);
          590           
          591           /* match the serialno to bitstream section.  We use this rather than
          592              offset positions to avoid problems near logical bitstream
          593              boundaries */
          594           for(link=0;link<vf->links;link++)
          595             if(vf->serialnos[link]==vf->current_serialno)break;
          596           if(link==vf->links)return(OV_EBADLINK); /* sign of a bogus
          597                                                      stream.  error out,
          598                                                      leave machine
          599                                                      uninitialized */
          600           
          601           vf->current_link=link;
          602           
          603           ogg_stream_reset_serialno(&vf->os,vf->current_serialno);
          604           vf->ready_state=STREAMSET;
          605           
          606         }else{
          607           /* we're streaming */
          608           /* fetch the three header packets, build the info struct */
          609           
          610           int ret=_fetch_headers(vf,vf->vi,vf->vc,&vf->current_serialno,&og);
          611           if(ret)return(ret);
          612           vf->current_link++;
          613           link=0;
          614         }
          615       }
          616       
          617       {
          618         int ret=_make_decode_ready(vf);
          619         if(ret<0)return ret;
          620       }
          621     }
          622     ogg_stream_pagein(&vf->os,&og);
          623   }
          624 }
          625 
          626 /* if, eg, 64 bit stdio is configured by default, this will build with
          627    fseek64 */
          628 static int _fseek64_wrap(FILE *f,ogg_int64_t off,int whence){
          629   if(f==NULL)return(-1);
          630   return fseek(f,off,whence);
          631 }
          632 
          633 static int _ov_open1(void *f,OggVorbis_File *vf,char *initial,
          634                      long ibytes, ov_callbacks callbacks){
          635   int offsettest=(f?callbacks.seek_func(f,0,SEEK_CUR):-1);
          636   int ret;
          637 
          638   memset(vf,0,sizeof(*vf));
          639   vf->datasource=f;
          640   vf->callbacks = callbacks;
          641 
          642   /* init the framing state */
          643   ogg_sync_init(&vf->oy);
          644 
          645   /* perhaps some data was previously read into a buffer for testing
          646      against other stream types.  Allow initialization from this
          647      previously read data (as we may be reading from a non-seekable
          648      stream) */
          649   if(initial){
          650     char *buffer=ogg_sync_buffer(&vf->oy,ibytes);
          651     memcpy(buffer,initial,ibytes);
          652     ogg_sync_wrote(&vf->oy,ibytes);
          653   }
          654 
          655   /* can we seek? Stevens suggests the seek test was portable */
          656   if(offsettest!=-1)vf->seekable=1;
          657 
          658   /* No seeking yet; Set up a 'single' (current) logical bitstream
          659      entry for partial open */
          660   vf->links=1;
          661   vf->vi=_ogg_calloc(vf->links,sizeof(*vf->vi));
          662   vf->vc=_ogg_calloc(vf->links,sizeof(*vf->vc));
          663   ogg_stream_init(&vf->os,-1); /* fill in the serialno later */
          664 
          665   /* Try to fetch the headers, maintaining all the storage */
          666   if((ret=_fetch_headers(vf,vf->vi,vf->vc,&vf->current_serialno,NULL))<0){
          667     vf->datasource=NULL;
          668     ov_clear(vf);
          669   }else 
          670     vf->ready_state=PARTOPEN;
          671   return(ret);
          672 }
          673 
          674 static int _ov_open2(OggVorbis_File *vf){
          675   if(vf->ready_state != PARTOPEN) return OV_EINVAL;
          676   vf->ready_state=OPENED;
          677   if(vf->seekable){
          678     int ret=_open_seekable2(vf);
          679     if(ret){
          680       vf->datasource=NULL;
          681       ov_clear(vf);
          682     }
          683     return(ret);
          684   }else
          685     vf->ready_state=STREAMSET;
          686 
          687   return 0;
          688 }
          689 
          690 
          691 /* clear out the OggVorbis_File struct */
          692 int ov_clear(OggVorbis_File *vf){
          693   if(vf){
          694     vorbis_block_clear(&vf->vb);
          695     vorbis_dsp_clear(&vf->vd);
          696     ogg_stream_clear(&vf->os);
          697     
          698     if(vf->vi && vf->links){
          699       int i;
          700       for(i=0;i<vf->links;i++){
          701         vorbis_info_clear(vf->vi+i);
          702         vorbis_comment_clear(vf->vc+i);
          703       }
          704       _ogg_free(vf->vi);
          705       _ogg_free(vf->vc);
          706     }
          707     if(vf->dataoffsets)_ogg_free(vf->dataoffsets);
          708     if(vf->pcmlengths)_ogg_free(vf->pcmlengths);
          709     if(vf->serialnos)_ogg_free(vf->serialnos);
          710     if(vf->offsets)_ogg_free(vf->offsets);
          711     ogg_sync_clear(&vf->oy);
          712     if(vf->datasource)(vf->callbacks.close_func)(vf->datasource);
          713     memset(vf,0,sizeof(*vf));
          714   }
          715 #ifdef DEBUG_LEAKS
          716   _VDBG_dump();
          717 #endif
          718   return(0);
          719 }
          720 
          721 /* inspects the OggVorbis file and finds/documents all the logical
          722    bitstreams contained in it.  Tries to be tolerant of logical
          723    bitstream sections that are truncated/woogie. 
          724 
          725    return: -1) error
          726             0) OK
          727 */
          728 
          729 int ov_open_callbacks(void *f,OggVorbis_File *vf,char *initial,long ibytes,
          730     ov_callbacks callbacks){
          731   int ret=_ov_open1(f,vf,initial,ibytes,callbacks);
          732   if(ret)return ret;
          733   return _ov_open2(vf);
          734 }
          735 
          736 int ov_open(FILE *f,OggVorbis_File *vf,char *initial,long ibytes){
          737   ov_callbacks callbacks = {
          738     (size_t (*)(void *, size_t, size_t, void *))  fread,
          739     (int (*)(void *, ogg_int64_t, int))              _fseek64_wrap,
          740     (int (*)(void *))                             fclose,
          741     (long (*)(void *))                            ftell
          742   };
          743 
          744   return ov_open_callbacks((void *)f, vf, initial, ibytes, callbacks);
          745 }
          746  
          747 /* cheap hack for game usage where downsampling is desirable; there's
          748    no need for SRC as we can just do it cheaply in libvorbis. */
          749  
          750 int ov_halfrate(OggVorbis_File *vf,int flag){
          751   int i;
          752   if(vf->vi==NULL)return OV_EINVAL;
          753   if(!vf->seekable)return OV_EINVAL;
          754   if(vf->ready_state>=STREAMSET)
          755     _decode_clear(vf); /* clear out stream state; later on libvorbis
          756                           will be able to swap this on the fly, but
          757                           for now dumping the decode machine is needed
          758                           to reinit the MDCT lookups.  1.1 libvorbis
          759                           is planned to be able to switch on the fly */
          760   
          761   for(i=0;i<vf->links;i++){
          762     if(vorbis_synthesis_halfrate(vf->vi+i,flag)){
          763       ov_halfrate(vf,0);
          764       return OV_EINVAL;
          765     }
          766   }
          767   return 0;
          768 }
          769 
          770 int ov_halfrate_p(OggVorbis_File *vf){
          771   if(vf->vi==NULL)return OV_EINVAL;
          772   return vorbis_synthesis_halfrate_p(vf->vi);
          773 }
          774 
          775 /* Only partially open the vorbis file; test for Vorbisness, and load
          776    the headers for the first chain.  Do not seek (although test for
          777    seekability).  Use ov_test_open to finish opening the file, else
          778    ov_clear to close/free it. Same return codes as open. */
          779 
          780 int ov_test_callbacks(void *f,OggVorbis_File *vf,char *initial,long ibytes,
          781     ov_callbacks callbacks)
          782 {
          783   return _ov_open1(f,vf,initial,ibytes,callbacks);
          784 }
          785 
          786 int ov_test(FILE *f,OggVorbis_File *vf,char *initial,long ibytes){
          787   ov_callbacks callbacks = {
          788     (size_t (*)(void *, size_t, size_t, void *))  fread,
          789     (int (*)(void *, ogg_int64_t, int))              _fseek64_wrap,
          790     (int (*)(void *))                             fclose,
          791     (long (*)(void *))                            ftell
          792   };
          793 
          794   return ov_test_callbacks((void *)f, vf, initial, ibytes, callbacks);
          795 }
          796   
          797 int ov_test_open(OggVorbis_File *vf){
          798   if(vf->ready_state!=PARTOPEN)return(OV_EINVAL);
          799   return _ov_open2(vf);
          800 }
          801 
          802 /* How many logical bitstreams in this physical bitstream? */
          803 long ov_streams(OggVorbis_File *vf){
          804   return vf->links;
          805 }
          806 
          807 /* Is the FILE * associated with vf seekable? */
          808 long ov_seekable(OggVorbis_File *vf){
          809   return vf->seekable;
          810 }
          811 
          812 /* returns the bitrate for a given logical bitstream or the entire
          813    physical bitstream.  If the file is open for random access, it will
          814    find the *actual* average bitrate.  If the file is streaming, it
          815    returns the nominal bitrate (if set) else the average of the
          816    upper/lower bounds (if set) else -1 (unset).
          817 
          818    If you want the actual bitrate field settings, get them from the
          819    vorbis_info structs */
          820 
          821 long ov_bitrate(OggVorbis_File *vf,int i){
          822   if(vf->ready_state<OPENED)return(OV_EINVAL);
          823   if(i>=vf->links)return(OV_EINVAL);
          824   if(!vf->seekable && i!=0)return(ov_bitrate(vf,0));
          825   if(i<0){
          826     ogg_int64_t bits=0;
          827     int i;
          828     float br;
          829     for(i=0;i<vf->links;i++)
          830       bits+=(vf->offsets[i+1]-vf->dataoffsets[i])*8;
          831     /* This once read: return(rint(bits/ov_time_total(vf,-1)));
          832      * gcc 3.x on x86 miscompiled this at optimisation level 2 and above,
          833      * so this is slightly transformed to make it work.
          834      */
          835     br = bits/ov_time_total(vf,-1);
          836     return(rint(br));
          837   }else{
          838     if(vf->seekable){
          839       /* return the actual bitrate */
          840       return(rint((vf->offsets[i+1]-vf->dataoffsets[i])*8/ov_time_total(vf,i)));
          841     }else{
          842       /* return nominal if set */
          843       if(vf->vi[i].bitrate_nominal>0){
          844         return vf->vi[i].bitrate_nominal;
          845       }else{
          846         if(vf->vi[i].bitrate_upper>0){
          847           if(vf->vi[i].bitrate_lower>0){
          848             return (vf->vi[i].bitrate_upper+vf->vi[i].bitrate_lower)/2;
          849           }else{
          850             return vf->vi[i].bitrate_upper;
          851           }
          852         }
          853         return(OV_FALSE);
          854       }
          855     }
          856   }
          857 }
          858 
          859 /* returns the actual bitrate since last call.  returns -1 if no
          860    additional data to offer since last call (or at beginning of stream),
          861    EINVAL if stream is only partially open 
          862 */
          863 long ov_bitrate_instant(OggVorbis_File *vf){
          864   int link=(vf->seekable?vf->current_link:0);
          865   long ret;
          866   if(vf->ready_state<OPENED)return(OV_EINVAL);
          867   if(vf->samptrack==0)return(OV_FALSE);
          868   ret=vf->bittrack/vf->samptrack*vf->vi[link].rate+.5;
          869   vf->bittrack=0.f;
          870   vf->samptrack=0.f;
          871   return(ret);
          872 }
          873 
          874 /* Guess */
          875 long ov_serialnumber(OggVorbis_File *vf,int i){
          876   if(i>=vf->links)return(ov_serialnumber(vf,vf->links-1));
          877   if(!vf->seekable && i>=0)return(ov_serialnumber(vf,-1));
          878   if(i<0){
          879     return(vf->current_serialno);
          880   }else{
          881     return(vf->serialnos[i]);
          882   }
          883 }
          884 
          885 /* returns: total raw (compressed) length of content if i==-1
          886             raw (compressed) length of that logical bitstream for i==0 to n
          887             OV_EINVAL if the stream is not seekable (we can't know the length)
          888             or if stream is only partially open
          889 */
          890 ogg_int64_t ov_raw_total(OggVorbis_File *vf,int i){
          891   if(vf->ready_state<OPENED)return(OV_EINVAL);
          892   if(!vf->seekable || i>=vf->links)return(OV_EINVAL);
          893   if(i<0){
          894     ogg_int64_t acc=0;
          895     int i;
          896     for(i=0;i<vf->links;i++)
          897       acc+=ov_raw_total(vf,i);
          898     return(acc);
          899   }else{
          900     return(vf->offsets[i+1]-vf->offsets[i]);
          901   }
          902 }
          903 
          904 /* returns: total PCM length (samples) of content if i==-1 PCM length
          905             (samples) of that logical bitstream for i==0 to n
          906             OV_EINVAL if the stream is not seekable (we can't know the
          907             length) or only partially open 
          908 */
          909 ogg_int64_t ov_pcm_total(OggVorbis_File *vf,int i){
          910   if(vf->ready_state<OPENED)return(OV_EINVAL);
          911   if(!vf->seekable || i>=vf->links)return(OV_EINVAL);
          912   if(i<0){
          913     ogg_int64_t acc=0;
          914     int i;
          915     for(i=0;i<vf->links;i++)
          916       acc+=ov_pcm_total(vf,i);
          917     return(acc);
          918   }else{
          919     return(vf->pcmlengths[i*2+1]);
          920   }
          921 }
          922 
          923 /* returns: total seconds of content if i==-1
          924             seconds in that logical bitstream for i==0 to n
          925             OV_EINVAL if the stream is not seekable (we can't know the
          926             length) or only partially open 
          927 */
          928 double ov_time_total(OggVorbis_File *vf,int i){
          929   if(vf->ready_state<OPENED)return(OV_EINVAL);
          930   if(!vf->seekable || i>=vf->links)return(OV_EINVAL);
          931   if(i<0){
          932     double acc=0;
          933     int i;
          934     for(i=0;i<vf->links;i++)
          935       acc+=ov_time_total(vf,i);
          936     return(acc);
          937   }else{
          938     return((double)(vf->pcmlengths[i*2+1])/vf->vi[i].rate);
          939   }
          940 }
          941 
          942 /* seek to an offset relative to the *compressed* data. This also
          943    scans packets to update the PCM cursor. It will cross a logical
          944    bitstream boundary, but only if it can't get any packets out of the
          945    tail of the bitstream we seek to (so no surprises).
          946 
          947    returns zero on success, nonzero on failure */
          948 
          949 int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos){
          950   ogg_stream_state work_os;
          951 
          952   if(vf->ready_state<OPENED)return(OV_EINVAL);
          953   if(!vf->seekable)
          954     return(OV_ENOSEEK); /* don't dump machine if we can't seek */
          955 
          956   if(pos<0 || pos>vf->end)return(OV_EINVAL);
          957 
          958   /* don't yet clear out decoding machine (if it's initialized), in
          959      the case we're in the same link.  Restart the decode lapping, and
          960      let _fetch_and_process_packet deal with a potential bitstream
          961      boundary */
          962   vf->pcm_offset=-1;
          963   ogg_stream_reset_serialno(&vf->os,
          964                             vf->current_serialno); /* must set serialno */
          965   vorbis_synthesis_restart(&vf->vd);
          966     
          967   _seek_helper(vf,pos);
          968 
          969   /* we need to make sure the pcm_offset is set, but we don't want to
          970      advance the raw cursor past good packets just to get to the first
          971      with a granulepos.  That's not equivalent behavior to beginning
          972      decoding as immediately after the seek position as possible.
          973 
          974      So, a hack.  We use two stream states; a local scratch state and
          975      the shared vf->os stream state.  We use the local state to
          976      scan, and the shared state as a buffer for later decode. 
          977 
          978      Unfortuantely, on the last page we still advance to last packet
          979      because the granulepos on the last page is not necessarily on a
          980      packet boundary, and we need to make sure the granpos is
          981      correct. 
          982   */
          983 
          984   {
          985     ogg_page og;
          986     ogg_packet op;
          987     int lastblock=0;
          988     int accblock=0;
          989     int thisblock;
          990     int eosflag;
          991 
          992     ogg_stream_init(&work_os,vf->current_serialno); /* get the memory ready */
          993     ogg_stream_reset(&work_os); /* eliminate the spurious OV_HOLE
          994                                    return from not necessarily
          995                                    starting from the beginning */
          996 
          997     while(1){
          998       if(vf->ready_state>=STREAMSET){
          999         /* snarf/scan a packet if we can */
         1000         int result=ogg_stream_packetout(&work_os,&op);
         1001       
         1002         if(result>0){
         1003 
         1004           if(vf->vi[vf->current_link].codec_setup){
         1005             thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op);
         1006             if(thisblock<0){
         1007               ogg_stream_packetout(&vf->os,NULL);
         1008               thisblock=0;
         1009             }else{
         1010               
         1011               if(eosflag)
         1012               ogg_stream_packetout(&vf->os,NULL);
         1013               else
         1014                 if(lastblock)accblock+=(lastblock+thisblock)>>2;
         1015             }            
         1016 
         1017             if(op.granulepos!=-1){
         1018               int i,link=vf->current_link;
         1019               ogg_int64_t granulepos=op.granulepos-vf->pcmlengths[link*2];
         1020               if(granulepos<0)granulepos=0;
         1021               
         1022               for(i=0;i<link;i++)
         1023                 granulepos+=vf->pcmlengths[i*2+1];
         1024               vf->pcm_offset=granulepos-accblock;
         1025               break;
         1026             }
         1027             lastblock=thisblock;
         1028             continue;
         1029           }else
         1030             ogg_stream_packetout(&vf->os,NULL);
         1031         }
         1032       }
         1033       
         1034       if(!lastblock){
         1035         if(_get_next_page(vf,&og,-1)<0){
         1036           vf->pcm_offset=ov_pcm_total(vf,-1);
         1037           break;
         1038         }
         1039       }else{
         1040         /* huh?  Bogus stream with packets but no granulepos */
         1041         vf->pcm_offset=-1;
         1042         break;
         1043       }
         1044       
         1045       /* has our decoding just traversed a bitstream boundary? */
         1046       if(vf->ready_state>=STREAMSET)
         1047         if(vf->current_serialno!=ogg_page_serialno(&og)){
         1048           _decode_clear(vf); /* clear out stream state */
         1049           ogg_stream_clear(&work_os);
         1050         }
         1051 
         1052       if(vf->ready_state<STREAMSET){
         1053         int link;
         1054         
         1055         vf->current_serialno=ogg_page_serialno(&og);
         1056         for(link=0;link<vf->links;link++)
         1057           if(vf->serialnos[link]==vf->current_serialno)break;
         1058         if(link==vf->links)goto seek_error; /* sign of a bogus stream.
         1059                                                error out, leave
         1060                                                machine uninitialized */
         1061         vf->current_link=link;
         1062         
         1063         ogg_stream_reset_serialno(&vf->os,vf->current_serialno);
         1064         ogg_stream_reset_serialno(&work_os,vf->current_serialno); 
         1065         vf->ready_state=STREAMSET;
         1066         
         1067       }
         1068     
         1069       ogg_stream_pagein(&vf->os,&og);
         1070       ogg_stream_pagein(&work_os,&og);
         1071       eosflag=ogg_page_eos(&og);
         1072     }
         1073   }
         1074 
         1075   ogg_stream_clear(&work_os);
         1076   vf->bittrack=0.f;
         1077   vf->samptrack=0.f;
         1078   return(0);
         1079 
         1080  seek_error:
         1081   /* dump the machine so we're in a known state */
         1082   vf->pcm_offset=-1;
         1083   ogg_stream_clear(&work_os);
         1084   _decode_clear(vf);
         1085   return OV_EBADLINK;
         1086 }
         1087 
         1088 /* Page granularity seek (faster than sample granularity because we
         1089    don't do the last bit of decode to find a specific sample).
         1090 
         1091    Seek to the last [granule marked] page preceeding the specified pos
         1092    location, such that decoding past the returned point will quickly
         1093    arrive at the requested position. */
         1094 int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
         1095   int link=-1;
         1096   ogg_int64_t result=0;
         1097   ogg_int64_t total=ov_pcm_total(vf,-1);
         1098 
         1099   if(vf->ready_state<OPENED)return(OV_EINVAL);
         1100   if(!vf->seekable)return(OV_ENOSEEK);
         1101 
         1102   if(pos<0 || pos>total)return(OV_EINVAL);
         1103  
         1104   /* which bitstream section does this pcm offset occur in? */
         1105   for(link=vf->links-1;link>=0;link--){
         1106     total-=vf->pcmlengths[link*2+1];
         1107     if(pos>=total)break;
         1108   }
         1109 
         1110   /* search within the logical bitstream for the page with the highest
         1111      pcm_pos preceeding (or equal to) pos.  There is a danger here;
         1112      missing pages or incorrect frame number information in the
         1113      bitstream could make our task impossible.  Account for that (it
         1114      would be an error condition) */
         1115 
         1116   /* new search algorithm by HB (Nicholas Vinen) */
         1117   {
         1118     ogg_int64_t end=vf->offsets[link+1];
         1119     ogg_int64_t begin=vf->offsets[link];
         1120     ogg_int64_t begintime = vf->pcmlengths[link*2];
         1121     ogg_int64_t endtime = vf->pcmlengths[link*2+1]+begintime;
         1122     ogg_int64_t target=pos-total+begintime;
         1123     ogg_int64_t best=begin;
         1124     
         1125     ogg_page og;
         1126     while(begin<end){
         1127       ogg_int64_t bisect;
         1128       
         1129       if(end-begin<CHUNKSIZE){
         1130         bisect=begin;
         1131       }else{
         1132         /* take a (pretty decent) guess. */
         1133         bisect=begin + 
         1134           (target-begintime)*(end-begin)/(endtime-begintime) - CHUNKSIZE;
         1135         if(bisect<=begin)
         1136           bisect=begin+1;
         1137       }
         1138       
         1139       _seek_helper(vf,bisect);
         1140     
         1141       while(begin<end){
         1142         result=_get_next_page(vf,&og,end-vf->offset);
         1143         if(result==OV_EREAD) goto seek_error;
         1144         if(result<0){
         1145           if(bisect<=begin+1)
         1146             end=begin; /* found it */
         1147           else{
         1148             if(bisect==0) goto seek_error;
         1149             bisect-=CHUNKSIZE;
         1150             if(bisect<=begin)bisect=begin+1;
         1151             _seek_helper(vf,bisect);
         1152           }
         1153         }else{
         1154           ogg_int64_t granulepos=ogg_page_granulepos(&og);
         1155           if(granulepos==-1)continue;
         1156           if(granulepos<target){
         1157             best=result;  /* raw offset of packet with granulepos */ 
         1158             begin=vf->offset; /* raw offset of next page */
         1159             begintime=granulepos;
         1160             
         1161             if(target-begintime>44100)break;
         1162             bisect=begin; /* *not* begin + 1 */
         1163           }else{
         1164             if(bisect<=begin+1)
         1165               end=begin;  /* found it */
         1166             else{
         1167               if(end==vf->offset){ /* we're pretty close - we'd be stuck in */
         1168                 end=result;
         1169                 bisect-=CHUNKSIZE; /* an endless loop otherwise. */
         1170                 if(bisect<=begin)bisect=begin+1;
         1171                 _seek_helper(vf,bisect);
         1172               }else{
         1173                 end=result;
         1174                 endtime=granulepos;
         1175                 break;
         1176               }
         1177             }
         1178           }
         1179         }
         1180       }
         1181     }
         1182 
         1183     /* found our page. seek to it, update pcm offset. Easier case than
         1184        raw_seek, don't keep packets preceeding granulepos. */
         1185     {
         1186       ogg_page og;
         1187       ogg_packet op;
         1188       
         1189       /* seek */
         1190       _seek_helper(vf,best);
         1191       vf->pcm_offset=-1;
         1192       
         1193       if(_get_next_page(vf,&og,-1)<0)return(OV_EOF); /* shouldn't happen */
         1194       
         1195       if(link!=vf->current_link){
         1196         /* Different link; dump entire decode machine */
         1197         _decode_clear(vf);  
         1198         
         1199         vf->current_link=link;
         1200         vf->current_serialno=ogg_page_serialno(&og);
         1201         vf->ready_state=STREAMSET;
         1202         
         1203       }else{
         1204         vorbis_synthesis_restart(&vf->vd);
         1205       }
         1206 
         1207       ogg_stream_reset_serialno(&vf->os,vf->current_serialno);
         1208       ogg_stream_pagein(&vf->os,&og);
         1209 
         1210       /* pull out all but last packet; the one with granulepos */
         1211       while(1){
         1212         result=ogg_stream_packetpeek(&vf->os,&op);
         1213         if(result==0){
         1214           /* !!! the packet finishing this page originated on a
         1215              preceeding page. Keep fetching previous pages until we
         1216              get one with a granulepos or without the 'continued' flag
         1217              set.  Then just use raw_seek for simplicity. */
         1218           
         1219           _seek_helper(vf,best);
         1220           
         1221           while(1){
         1222             result=_get_prev_page(vf,&og);
         1223             if(result<0) goto seek_error;
         1224             if(ogg_page_granulepos(&og)>-1 ||
         1225                !ogg_page_continued(&og)){
         1226               return ov_raw_seek(vf,result);
         1227             }
         1228             vf->offset=result;
         1229           }
         1230         }
         1231         if(result<0){
         1232           result = OV_EBADPACKET; 
         1233           goto seek_error;
         1234         }
         1235         if(op.granulepos!=-1){
         1236           vf->pcm_offset=op.granulepos-vf->pcmlengths[vf->current_link*2];
         1237           if(vf->pcm_offset<0)vf->pcm_offset=0;
         1238           vf->pcm_offset+=total;
         1239           break;
         1240         }else
         1241           result=ogg_stream_packetout(&vf->os,NULL);
         1242       }
         1243     }
         1244   }
         1245   
         1246   /* verify result */
         1247   if(vf->pcm_offset>pos || pos>ov_pcm_total(vf,-1)){
         1248     result=OV_EFAULT;
         1249     goto seek_error;
         1250   }
         1251   vf->bittrack=0.f;
         1252   vf->samptrack=0.f;
         1253   return(0);
         1254   
         1255  seek_error:
         1256   /* dump machine so we're in a known state */
         1257   vf->pcm_offset=-1;
         1258   _decode_clear(vf);
         1259   return (int)result;
         1260 }
         1261 
         1262 /* seek to a sample offset relative to the decompressed pcm stream 
         1263    returns zero on success, nonzero on failure */
         1264 
         1265 int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos){
         1266   int thisblock,lastblock=0;
         1267   int ret=ov_pcm_seek_page(vf,pos);
         1268   if(ret<0)return(ret);
         1269   if((ret=_make_decode_ready(vf)))return ret;
         1270 
         1271   /* discard leading packets we don't need for the lapping of the
         1272      position we want; don't decode them */
         1273 
         1274   while(1){
         1275     ogg_packet op;
         1276     ogg_page og;
         1277 
         1278     int ret=ogg_stream_packetpeek(&vf->os,&op);
         1279     if(ret>0){
         1280       thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op);
         1281       if(thisblock<0){
         1282         ogg_stream_packetout(&vf->os,NULL);
         1283         continue; /* non audio packet */
         1284       }
         1285       if(lastblock)vf->pcm_offset+=(lastblock+thisblock)>>2;
         1286       
         1287       if(vf->pcm_offset+((thisblock+
         1288                           vorbis_info_blocksize(vf->vi,1))>>2)>=pos)break;
         1289       
         1290       /* remove the packet from packet queue and track its granulepos */
         1291       ogg_stream_packetout(&vf->os,NULL);
         1292       vorbis_synthesis_trackonly(&vf->vb,&op);  /* set up a vb with
         1293                                                    only tracking, no
         1294                                                    pcm_decode */
         1295       vorbis_synthesis_blockin(&vf->vd,&vf->vb); 
         1296       
         1297       /* end of logical stream case is hard, especially with exact
         1298          length positioning. */
         1299       
         1300       if(op.granulepos>-1){
         1301         int i;
         1302         /* always believe the stream markers */
         1303         vf->pcm_offset=op.granulepos-vf->pcmlengths[vf->current_link*2];
         1304         if(vf->pcm_offset<0)vf->pcm_offset=0;
         1305         for(i=0;i<vf->current_link;i++)
         1306           vf->pcm_offset+=vf->pcmlengths[i*2+1];
         1307       }
         1308         
         1309       lastblock=thisblock;
         1310       
         1311     }else{
         1312       if(ret<0 && ret!=OV_HOLE)break;
         1313       
         1314       /* suck in a new page */
         1315       if(_get_next_page(vf,&og,-1)<0)break;
         1316       if(vf->current_serialno!=ogg_page_serialno(&og))_decode_clear(vf);
         1317       
         1318       if(vf->ready_state<STREAMSET){
         1319         int link;
         1320         
         1321         vf->current_serialno=ogg_page_serialno(&og);
         1322         for(link=0;link<vf->links;link++)
         1323           if(vf->serialnos[link]==vf->current_serialno)break;
         1324         if(link==vf->links)return(OV_EBADLINK);
         1325         vf->current_link=link;
         1326         
         1327         ogg_stream_reset_serialno(&vf->os,vf->current_serialno); 
         1328         vf->ready_state=STREAMSET;      
         1329         ret=_make_decode_ready(vf);
         1330         if(ret)return ret;
         1331         lastblock=0;
         1332       }
         1333 
         1334       ogg_stream_pagein(&vf->os,&og);
         1335     }
         1336   }
         1337 
         1338   vf->bittrack=0.f;
         1339   vf->samptrack=0.f;
         1340   /* discard samples until we reach the desired position. Crossing a
         1341      logical bitstream boundary with abandon is OK. */
         1342   while(vf->pcm_offset<pos){
         1343     ogg_int64_t target=pos-vf->pcm_offset;
         1344     long samples=vorbis_synthesis_pcmout(&vf->vd,NULL);
         1345 
         1346     if(samples>target)samples=target;
         1347     vorbis_synthesis_read(&vf->vd,samples);
         1348     vf->pcm_offset+=samples;
         1349     
         1350     if(samples<target)
         1351       if(_fetch_and_process_packet(vf,NULL,1,1)<=0)
         1352         vf->pcm_offset=ov_pcm_total(vf,-1); /* eof */
         1353   }
         1354   return 0;
         1355 }
         1356 
         1357 /* seek to a playback time relative to the decompressed pcm stream 
         1358    returns zero on success, nonzero on failure */
         1359 int ov_time_seek(OggVorbis_File *vf,double seconds){
         1360   /* translate time to PCM position and call ov_pcm_seek */
         1361 
         1362   int link=-1;
         1363   ogg_int64_t pcm_total=ov_pcm_total(vf,-1);
         1364   double time_total=ov_time_total(vf,-1);
         1365 
         1366   if(vf->ready_state<OPENED)return(OV_EINVAL);
         1367   if(!vf->seekable)return(OV_ENOSEEK);
         1368   if(seconds<0 || seconds>time_total)return(OV_EINVAL);
         1369   
         1370   /* which bitstream section does this time offset occur in? */
         1371   for(link=vf->links-1;link>=0;link--){
         1372     pcm_total-=vf->pcmlengths[link*2+1];
         1373     time_total-=ov_time_total(vf,link);
         1374     if(seconds>=time_total)break;
         1375   }
         1376 
         1377   /* enough information to convert time offset to pcm offset */
         1378   {
         1379     ogg_int64_t target=pcm_total+(seconds-time_total)*vf->vi[link].rate;
         1380     return(ov_pcm_seek(vf,target));
         1381   }
         1382 }
         1383 
         1384 /* page-granularity version of ov_time_seek 
         1385    returns zero on success, nonzero on failure */
         1386 int ov_time_seek_page(OggVorbis_File *vf,double seconds){
         1387   /* translate time to PCM position and call ov_pcm_seek */
         1388 
         1389   int link=-1;
         1390   ogg_int64_t pcm_total=ov_pcm_total(vf,-1);
         1391   double time_total=ov_time_total(vf,-1);
         1392 
         1393   if(vf->ready_state<OPENED)return(OV_EINVAL);
         1394   if(!vf->seekable)return(OV_ENOSEEK);
         1395   if(seconds<0 || seconds>time_total)return(OV_EINVAL);
         1396   
         1397   /* which bitstream section does this time offset occur in? */
         1398   for(link=vf->links-1;link>=0;link--){
         1399     pcm_total-=vf->pcmlengths[link*2+1];
         1400     time_total-=ov_time_total(vf,link);
         1401     if(seconds>=time_total)break;
         1402   }
         1403 
         1404   /* enough information to convert time offset to pcm offset */
         1405   {
         1406     ogg_int64_t target=pcm_total+(seconds-time_total)*vf->vi[link].rate;
         1407     return(ov_pcm_seek_page(vf,target));
         1408   }
         1409 }
         1410 
         1411 /* tell the current stream offset cursor.  Note that seek followed by
         1412    tell will likely not give the set offset due to caching */
         1413 ogg_int64_t ov_raw_tell(OggVorbis_File *vf){
         1414   if(vf->ready_state<OPENED)return(OV_EINVAL);
         1415   return(vf->offset);
         1416 }
         1417 
         1418 /* return PCM offset (sample) of next PCM sample to be read */
         1419 ogg_int64_t ov_pcm_tell(OggVorbis_File *vf){
         1420   if(vf->ready_state<OPENED)return(OV_EINVAL);
         1421   return(vf->pcm_offset);
         1422 }
         1423 
         1424 /* return time offset (seconds) of next PCM sample to be read */
         1425 double ov_time_tell(OggVorbis_File *vf){
         1426   int link=0;
         1427   ogg_int64_t pcm_total=0;
         1428   double time_total=0.f;
         1429   
         1430   if(vf->ready_state<OPENED)return(OV_EINVAL);
         1431   if(vf->seekable){
         1432     pcm_total=ov_pcm_total(vf,-1);
         1433     time_total=ov_time_total(vf,-1);
         1434   
         1435     /* which bitstream section does this time offset occur in? */
         1436     for(link=vf->links-1;link>=0;link--){
         1437       pcm_total-=vf->pcmlengths[link*2+1];
         1438       time_total-=ov_time_total(vf,link);
         1439       if(vf->pcm_offset>=pcm_total)break;
         1440     }
         1441   }
         1442 
         1443   return((double)time_total+(double)(vf->pcm_offset-pcm_total)/vf->vi[link].rate);
         1444 }
         1445 
         1446 /*  link:   -1) return the vorbis_info struct for the bitstream section
         1447                 currently being decoded
         1448            0-n) to request information for a specific bitstream section
         1449     
         1450     In the case of a non-seekable bitstream, any call returns the
         1451     current bitstream.  NULL in the case that the machine is not
         1452     initialized */
         1453 
         1454 vorbis_info *ov_info(OggVorbis_File *vf,int link){
         1455   if(vf->seekable){
         1456     if(link<0)
         1457       if(vf->ready_state>=STREAMSET)
         1458         return vf->vi+vf->current_link;
         1459       else
         1460       return vf->vi;
         1461     else
         1462       if(link>=vf->links)
         1463         return NULL;
         1464       else
         1465         return vf->vi+link;
         1466   }else{
         1467     return vf->vi;
         1468   }
         1469 }
         1470 
         1471 /* grr, strong typing, grr, no templates/inheritence, grr */
         1472 vorbis_comment *ov_comment(OggVorbis_File *vf,int link){
         1473   if(vf->seekable){
         1474     if(link<0)
         1475       if(vf->ready_state>=STREAMSET)
         1476         return vf->vc+vf->current_link;
         1477       else
         1478         return vf->vc;
         1479     else
         1480       if(link>=vf->links)
         1481         return NULL;
         1482       else
         1483         return vf->vc+link;
         1484   }else{
         1485     return vf->vc;
         1486   }
         1487 }
         1488 
         1489 static int host_is_big_endian() {
         1490   ogg_int32_t pattern = 0xfeedface; /* deadbeef */
         1491   unsigned char *bytewise = (unsigned char *)&pattern;
         1492   if (bytewise[0] == 0xfe) return 1;
         1493   return 0;
         1494 }
         1495 
         1496 /* up to this point, everything could more or less hide the multiple
         1497    logical bitstream nature of chaining from the toplevel application
         1498    if the toplevel application didn't particularly care.  However, at
         1499    the point that we actually read audio back, the multiple-section
         1500    nature must surface: Multiple bitstream sections do not necessarily
         1501    have to have the same number of channels or sampling rate.
         1502 
         1503    ov_read returns the sequential logical bitstream number currently
         1504    being decoded along with the PCM data in order that the toplevel
         1505    application can take action on channel/sample rate changes.  This
         1506    number will be incremented even for streamed (non-seekable) streams
         1507    (for seekable streams, it represents the actual logical bitstream
         1508    index within the physical bitstream.  Note that the accessor
         1509    functions above are aware of this dichotomy).
         1510 
         1511    input values: buffer) a buffer to hold packed PCM data for return
         1512                  length) the byte length requested to be placed into buffer
         1513                  bigendianp) should the data be packed LSB first (0) or
         1514                              MSB first (1)
         1515                  word) word size for output.  currently 1 (byte) or 
         1516                        2 (16 bit short)
         1517 
         1518    return values: <0) error/hole in data (OV_HOLE), partial open (OV_EINVAL)
         1519                    0) EOF
         1520                    n) number of bytes of PCM actually returned.  The
         1521                    below works on a packet-by-packet basis, so the
         1522                    return length is not related to the 'length' passed
         1523                    in, just guaranteed to fit.
         1524 
         1525             *section) set to the logical bitstream number */
         1526 
         1527 long ov_read(OggVorbis_File *vf,char *buffer,int length,
         1528                     int bigendianp,int word,int sgned,int *bitstream){
         1529   int i,j;
         1530   int host_endian = host_is_big_endian();
         1531 
         1532   float **pcm;
         1533   long samples;
         1534 
         1535   if(vf->ready_state<OPENED)return(OV_EINVAL);
         1536 
         1537   while(1){
         1538     if(vf->ready_state==INITSET){
         1539       samples=vorbis_synthesis_pcmout(&vf->vd,&pcm);
         1540       if(samples)break;
         1541     }
         1542 
         1543     /* suck in another packet */
         1544     {
         1545       int ret=_fetch_and_process_packet(vf,NULL,1,1);
         1546       if(ret==OV_EOF)
         1547         return(0);
         1548       if(ret<=0)
         1549         return(ret);
         1550     }
         1551 
         1552   }
         1553 
         1554   if(samples>0){
         1555   
         1556     /* yay! proceed to pack data into the byte buffer */
         1557     
         1558     long channels=ov_info(vf,-1)->channels;
         1559     long bytespersample=word * channels;
         1560     vorbis_fpu_control fpu;
         1561     if(samples>length/bytespersample)samples=length/bytespersample;
         1562 
         1563     if(samples <= 0)
         1564       return OV_EINVAL;
         1565     
         1566     /* a tight loop to pack each size */
         1567     {
         1568       int val;
         1569       if(word==1){
         1570         int off=(sgned?0:128);
         1571         vorbis_fpu_setround(&fpu);
         1572         for(j=0;j<samples;j++)
         1573           for(i=0;i<channels;i++){
         1574             val=vorbis_ftoi(pcm[i][j]*128.f);
         1575             if(val>127)val=127;
         1576             else if(val<-128)val=-128;
         1577             *buffer++=val+off;
         1578           }
         1579         vorbis_fpu_restore(fpu);
         1580       }else{
         1581         int off=(sgned?0:32768);
         1582         
         1583         if(host_endian==bigendianp){
         1584           if(sgned){
         1585             
         1586             vorbis_fpu_setround(&fpu);
         1587             for(i=0;i<channels;i++) { /* It's faster in this order */
         1588               float *src=pcm[i];
         1589               short *dest=((short *)buffer)+i;
         1590               for(j=0;j<samples;j++) {
         1591                 val=vorbis_ftoi(src[j]*32768.f);
         1592                 if(val>32767)val=32767;
         1593                 else if(val<-32768)val=-32768;
         1594                 *dest=val;
         1595                 dest+=channels;
         1596               }
         1597             }
         1598             vorbis_fpu_restore(fpu);
         1599             
         1600           }else{
         1601             
         1602             vorbis_fpu_setround(&fpu);
         1603             for(i=0;i<channels;i++) {
         1604               float *src=pcm[i];
         1605               short *dest=((short *)buffer)+i;
         1606               for(j=0;j<samples;j++) {
         1607                 val=vorbis_ftoi(src[j]*32768.f);
         1608                 if(val>32767)val=32767;
         1609                 else if(val<-32768)val=-32768;
         1610                 *dest=val+off;
         1611                 dest+=channels;
         1612               }
         1613             }
         1614             vorbis_fpu_restore(fpu);
         1615             
         1616           }
         1617         }else if(bigendianp){
         1618           
         1619           vorbis_fpu_setround(&fpu);
         1620           for(j=0;j<samples;j++)
         1621             for(i=0;i<channels;i++){
         1622               val=vorbis_ftoi(pcm[i][j]*32768.f);
         1623               if(val>32767)val=32767;
         1624               else if(val<-32768)val=-32768;
         1625               val+=off;
         1626               *buffer++=(val>>8);
         1627               *buffer++=(val&0xff);
         1628             }
         1629           vorbis_fpu_restore(fpu);
         1630           
         1631         }else{
         1632           int val;
         1633           vorbis_fpu_setround(&fpu);
         1634           for(j=0;j<samples;j++)
         1635             for(i=0;i<channels;i++){
         1636               val=vorbis_ftoi(pcm[i][j]*32768.f);
         1637               if(val>32767)val=32767;
         1638               else if(val<-32768)val=-32768;
         1639               val+=off;
         1640               *buffer++=(val&0xff);
         1641               *buffer++=(val>>8);
         1642                   }
         1643           vorbis_fpu_restore(fpu);  
         1644           
         1645         }
         1646       }
         1647     }
         1648     
         1649     vorbis_synthesis_read(&vf->vd,samples);
         1650     vf->pcm_offset+=samples;
         1651     if(bitstream)*bitstream=vf->current_link;
         1652     return(samples*bytespersample);
         1653   }else{
         1654     return(samples);
         1655   }
         1656 }
         1657 
         1658 /* input values: pcm_channels) a float vector per channel of output
         1659                  length) the sample length being read by the app
         1660 
         1661    return values: <0) error/hole in data (OV_HOLE), partial open (OV_EINVAL)
         1662                    0) EOF
         1663                    n) number of samples of PCM actually returned.  The
         1664                    below works on a packet-by-packet basis, so the
         1665                    return length is not related to the 'length' passed
         1666                    in, just guaranteed to fit.
         1667 
         1668             *section) set to the logical bitstream number */
         1669 
         1670 
         1671 
         1672 long ov_read_float(OggVorbis_File *vf,float ***pcm_channels,int length,
         1673                    int *bitstream){
         1674 
         1675   if(vf->ready_state<OPENED)return(OV_EINVAL);
         1676 
         1677   while(1){
         1678     if(vf->ready_state==INITSET){
         1679       float **pcm;
         1680       long samples=vorbis_synthesis_pcmout(&vf->vd,&pcm);
         1681       if(samples){
         1682         if(pcm_channels)*pcm_channels=pcm;
         1683         if(samples>length)samples=length;
         1684         vorbis_synthesis_read(&vf->vd,samples);
         1685         vf->pcm_offset+=samples;
         1686         if(bitstream)*bitstream=vf->current_link;
         1687         return samples;
         1688 
         1689       }
         1690     }
         1691 
         1692     /* suck in another packet */
         1693     {
         1694       int ret=_fetch_and_process_packet(vf,NULL,1,1);
         1695       if(ret==OV_EOF)return(0);
         1696       if(ret<=0)return(ret);
         1697     }
         1698 
         1699   }
         1700 }
         1701 
         1702 extern float *vorbis_window(vorbis_dsp_state *v,int W);
         1703 extern void _analysis_output_always(char *base,int i,float *v,int n,int bark,int dB,
         1704                              ogg_int64_t off);
         1705 
         1706 static void _ov_splice(float **pcm,float **lappcm,
         1707                        int n1, int n2,
         1708                        int ch1, int ch2,
         1709                        float *w1, float *w2){
         1710   int i,j;
         1711   float *w=w1;
         1712   int n=n1;
         1713 
         1714   if(n1>n2){
         1715     n=n2;
         1716     w=w2;
         1717   }
         1718 
         1719   /* splice */
         1720   for(j=0;j<ch1 && j<ch2;j++){
         1721     float *s=lappcm[j];
         1722     float *d=pcm[j];
         1723 
         1724     for(i=0;i<n;i++){
         1725       float wd=w[i]*w[i];
         1726       float ws=1.-wd;
         1727       d[i]=d[i]*wd + s[i]*ws;
         1728     }
         1729   }
         1730   /* window from zero */
         1731   for(;j<ch2;j++){
         1732     float *d=pcm[j];
         1733     for(i=0;i<n;i++){
         1734       float wd=w[i]*w[i];
         1735       d[i]=d[i]*wd;
         1736     }
         1737   }
         1738 
         1739 }
         1740                 
         1741 /* make sure vf is INITSET */
         1742 static int _ov_initset(OggVorbis_File *vf){
         1743   while(1){
         1744     if(vf->ready_state==INITSET)break;
         1745     /* suck in another packet */
         1746     {
         1747       int ret=_fetch_and_process_packet(vf,NULL,1,0);
         1748       if(ret<0 && ret!=OV_HOLE)return(ret);
         1749     }
         1750   }
         1751   return 0;
         1752 }
         1753 
         1754 /* make sure vf is INITSET and that we have a primed buffer; if
         1755    we're crosslapping at a stream section boundary, this also makes
         1756    sure we're sanity checking against the right stream information */
         1757 static int _ov_initprime(OggVorbis_File *vf){
         1758   vorbis_dsp_state *vd=&vf->vd;
         1759   while(1){
         1760     if(vf->ready_state==INITSET)
         1761       if(vorbis_synthesis_pcmout(vd,NULL))break;
         1762     
         1763     /* suck in another packet */
         1764     {
         1765       int ret=_fetch_and_process_packet(vf,NULL,1,0);
         1766       if(ret<0 && ret!=OV_HOLE)return(ret);
         1767     }
         1768   }  
         1769   return 0;
         1770 }
         1771 
         1772 /* grab enough data for lapping from vf; this may be in the form of
         1773    unreturned, already-decoded pcm, remaining PCM we will need to
         1774    decode, or synthetic postextrapolation from last packets. */
         1775 static void _ov_getlap(OggVorbis_File *vf,vorbis_info *vi,vorbis_dsp_state *vd,
         1776                        float **lappcm,int lapsize){
         1777   int lapcount=0,i;
         1778   float **pcm;
         1779 
         1780   /* try first to decode the lapping data */
         1781   while(lapcount<lapsize){
         1782     int samples=vorbis_synthesis_pcmout(vd,&pcm);
         1783     if(samples){
         1784       if(samples>lapsize-lapcount)samples=lapsize-lapcount;
         1785       for(i=0;i<vi->channels;i++)
         1786         memcpy(lappcm[i]+lapcount,pcm[i],sizeof(**pcm)*samples);
         1787       lapcount+=samples;
         1788       vorbis_synthesis_read(vd,samples);
         1789     }else{
         1790     /* suck in another packet */
         1791       int ret=_fetch_and_process_packet(vf,NULL,1,0); /* do *not* span */
         1792       if(ret==OV_EOF)break;
         1793     }
         1794   }
         1795   if(lapcount<lapsize){
         1796     /* failed to get lapping data from normal decode; pry it from the
         1797        postextrapolation buffering, or the second half of the MDCT
         1798        from the last packet */
         1799     int samples=vorbis_synthesis_lapout(&vf->vd,&pcm);
         1800     if(samples==0){
         1801       for(i=0;i<vi->channels;i++)
         1802         memset(lappcm[i]+lapcount,0,sizeof(**pcm)*lapsize-lapcount);
         1803       lapcount=lapsize;
         1804     }else{
         1805       if(samples>lapsize-lapcount)samples=lapsize-lapcount;
         1806       for(i=0;i<vi->channels;i++)
         1807         memcpy(lappcm[i]+lapcount,pcm[i],sizeof(**pcm)*samples);
         1808       lapcount+=samples;
         1809     }
         1810   }
         1811 }
         1812 
         1813 /* this sets up crosslapping of a sample by using trailing data from
         1814    sample 1 and lapping it into the windowing buffer of sample 2 */
         1815 int ov_crosslap(OggVorbis_File *vf1, OggVorbis_File *vf2){
         1816   vorbis_info *vi1,*vi2;
         1817   float **lappcm;
         1818   float **pcm;
         1819   float *w1,*w2;
         1820   int n1,n2,i,ret,hs1,hs2;
         1821 
         1822   if(vf1==vf2)return(0); /* degenerate case */
         1823   if(vf1->ready_state<OPENED)return(OV_EINVAL);
         1824   if(vf2->ready_state<OPENED)return(OV_EINVAL);
         1825 
         1826   /* the relevant overlap buffers must be pre-checked and pre-primed
         1827      before looking at settings in the event that priming would cross
         1828      a bitstream boundary.  So, do it now */
         1829 
         1830   ret=_ov_initset(vf1);
         1831   if(ret)return(ret);
         1832   ret=_ov_initprime(vf2);
         1833   if(ret)return(ret);
         1834 
         1835   vi1=ov_info(vf1,-1);
         1836   vi2=ov_info(vf2,-1);
         1837   hs1=ov_halfrate_p(vf1);
         1838   hs2=ov_halfrate_p(vf2);
         1839 
         1840   lappcm=alloca(sizeof(*lappcm)*vi1->channels);
         1841   n1=vorbis_info_blocksize(vi1,0)>>(1+hs1);
         1842   n2=vorbis_info_blocksize(vi2,0)>>(1+hs2);
         1843   w1=vorbis_window(&vf1->vd,0);
         1844   w2=vorbis_window(&vf2->vd,0);
         1845 
         1846   for(i=0;i<vi1->channels;i++)
         1847     lappcm[i]=alloca(sizeof(**lappcm)*n1);
         1848 
         1849   _ov_getlap(vf1,vi1,&vf1->vd,lappcm,n1);
         1850 
         1851   /* have a lapping buffer from vf1; now to splice it into the lapping
         1852      buffer of vf2 */
         1853   /* consolidate and expose the buffer. */
         1854   vorbis_synthesis_lapout(&vf2->vd,&pcm);
         1855   _analysis_output_always("pcmL",0,pcm[0],n1*2,0,0,0);
         1856   _analysis_output_always("pcmR",0,pcm[1],n1*2,0,0,0);
         1857 
         1858   /* splice */
         1859   _ov_splice(pcm,lappcm,n1,n2,vi1->channels,vi2->channels,w1,w2);
         1860   
         1861   /* done */
         1862   return(0);
         1863 }
         1864 
         1865 static int _ov_64_seek_lap(OggVorbis_File *vf,ogg_int64_t pos,
         1866                            int (*localseek)(OggVorbis_File *,ogg_int64_t)){
         1867   vorbis_info *vi;
         1868   float **lappcm;
         1869   float **pcm;
         1870   float *w1,*w2;
         1871   int n1,n2,ch1,ch2,hs;
         1872   int i,ret;
         1873 
         1874   if(vf->ready_state<OPENED)return(OV_EINVAL);
         1875   ret=_ov_initset(vf);
         1876   if(ret)return(ret);
         1877   vi=ov_info(vf,-1);
         1878   hs=ov_halfrate_p(vf);
         1879   
         1880   ch1=vi->channels;
         1881   n1=vorbis_info_blocksize(vi,0)>>(1+hs);
         1882   w1=vorbis_window(&vf->vd,0);  /* window arrays from libvorbis are
         1883                                    persistent; even if the decode state
         1884                                    from this link gets dumped, this
         1885                                    window array continues to exist */
         1886 
         1887   lappcm=alloca(sizeof(*lappcm)*ch1);
         1888   for(i=0;i<ch1;i++)
         1889     lappcm[i]=alloca(sizeof(**lappcm)*n1);
         1890   _ov_getlap(vf,vi,&vf->vd,lappcm,n1);
         1891 
         1892   /* have lapping data; seek and prime the buffer */
         1893   ret=localseek(vf,pos);
         1894   if(ret)return ret;
         1895   ret=_ov_initprime(vf);
         1896   if(ret)return(ret);
         1897 
         1898  /* Guard against cross-link changes; they're perfectly legal */
         1899   vi=ov_info(vf,-1);
         1900   ch2=vi->channels;
         1901   n2=vorbis_info_blocksize(vi,0)>>(1+hs);
         1902   w2=vorbis_window(&vf->vd,0);
         1903 
         1904   /* consolidate and expose the buffer. */
         1905   vorbis_synthesis_lapout(&vf->vd,&pcm);
         1906 
         1907   /* splice */
         1908   _ov_splice(pcm,lappcm,n1,n2,ch1,ch2,w1,w2);
         1909 
         1910   /* done */
         1911   return(0);
         1912 }
         1913 
         1914 int ov_raw_seek_lap(OggVorbis_File *vf,ogg_int64_t pos){
         1915   return _ov_64_seek_lap(vf,pos,ov_raw_seek);
         1916 }
         1917 
         1918 int ov_pcm_seek_lap(OggVorbis_File *vf,ogg_int64_t pos){
         1919   return _ov_64_seek_lap(vf,pos,ov_pcm_seek);
         1920 }
         1921 
         1922 int ov_pcm_seek_page_lap(OggVorbis_File *vf,ogg_int64_t pos){
         1923   return _ov_64_seek_lap(vf,pos,ov_pcm_seek_page);
         1924 }
         1925 
         1926 static int _ov_d_seek_lap(OggVorbis_File *vf,double pos,
         1927                            int (*localseek)(OggVorbis_File *,double)){
         1928   vorbis_info *vi;
         1929   float **lappcm;
         1930   float **pcm;
         1931   float *w1,*w2;
         1932   int n1,n2,ch1,ch2,hs;
         1933   int i,ret;
         1934 
         1935   if(vf->ready_state<OPENED)return(OV_EINVAL);
         1936   ret=_ov_initset(vf);
         1937   if(ret)return(ret);
         1938   vi=ov_info(vf,-1);
         1939   hs=ov_halfrate_p(vf);
         1940 
         1941   ch1=vi->channels;
         1942   n1=vorbis_info_blocksize(vi,0)>>(1+hs);
         1943   w1=vorbis_window(&vf->vd,0);  /* window arrays from libvorbis are
         1944                                    persistent; even if the decode state
         1945                                    from this link gets dumped, this
         1946                                    window array continues to exist */
         1947 
         1948   lappcm=alloca(sizeof(*lappcm)*ch1);
         1949   for(i=0;i<ch1;i++)
         1950     lappcm[i]=alloca(sizeof(**lappcm)*n1);
         1951   _ov_getlap(vf,vi,&vf->vd,lappcm,n1);
         1952 
         1953   /* have lapping data; seek and prime the buffer */
         1954   ret=localseek(vf,pos);
         1955   if(ret)return ret;
         1956   ret=_ov_initprime(vf);
         1957   if(ret)return(ret);
         1958 
         1959  /* Guard against cross-link changes; they're perfectly legal */
         1960   vi=ov_info(vf,-1);
         1961   ch2=vi->channels;
         1962   n2=vorbis_info_blocksize(vi,0)>>(1+hs);
         1963   w2=vorbis_window(&vf->vd,0);
         1964 
         1965   /* consolidate and expose the buffer. */
         1966   vorbis_synthesis_lapout(&vf->vd,&pcm);
         1967 
         1968   /* splice */
         1969   _ov_splice(pcm,lappcm,n1,n2,ch1,ch2,w1,w2);
         1970 
         1971   /* done */
         1972   return(0);
         1973 }
         1974 
         1975 int ov_time_seek_lap(OggVorbis_File *vf,double pos){
         1976   return _ov_d_seek_lap(vf,pos,ov_time_seek);
         1977 }
         1978 
         1979 int ov_time_seek_page_lap(OggVorbis_File *vf,double pos){
         1980   return _ov_d_seek_lap(vf,pos,ov_time_seek_page);
         1981 }