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