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