Don't reduce open state during ov_open().
[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-2001             *
9  * by the XIPHOPHORUS Company http://www.xiph.org/                  *
10  *                                                                  *
11  ********************************************************************
12
13  function: stdio-based convenience library for opening/seeking/decoding
14  last mod: $Id: vorbisfile.c,v 1.48 2001/06/02 11:38:14 msmith Exp $
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 "codec_internal.h"
29 #include "misc.h"
30
31 /* A 'chained bitstream' is a Vorbis bitstream that contains more than
32    one logical bitstream arranged end to end (the only form of Ogg
33    multiplexing allowed in a Vorbis bitstream; grouping [parallel
34    multiplexing] is not allowed in Vorbis) */
35
36 /* A Vorbis file can be played beginning to end (streamed) without
37    worrying ahead of time about chaining (see decoder_example.c).  If
38    we have the whole file, however, and want random access
39    (seeking/scrubbing) or desire to know the total length/time of a
40    file, we need to account for the possibility of chaining. */
41
42 /* We can handle things a number of ways; we can determine the entire
43    bitstream structure right off the bat, or find pieces on demand.
44    This example determines and caches structure for the entire
45    bitstream, but builds a virtual decoder on the fly when moving
46    between links in the chain. */
47
48 /* There are also different ways to implement seeking.  Enough
49    information exists in an Ogg bitstream to seek to
50    sample-granularity positions in the output.  Or, one can seek by
51    picking some portion of the stream roughly in the desired area if
52    we only want coarse navigation through the stream. */
53
54 /*************************************************************************
55  * Many, many internal helpers.  The intention is not to be confusing; 
56  * rampant duplication and monolithic function implementation would be 
57  * harder to understand anyway.  The high level functions are last.  Begin
58  * grokking near the end of the file */
59
60 /* read a little more data from the file/pipe into the ogg_sync framer
61 */
62 #define CHUNKSIZE 8500 /* a shade over 8k; anyone using pages well
63                           over 8k gets what they deserve */
64 static long _get_data(OggVorbis_File *vf){
65   errno=0;
66   if(vf->datasource){
67     char *buffer=ogg_sync_buffer(&vf->oy,CHUNKSIZE);
68     long bytes=(vf->callbacks.read_func)(buffer,1,CHUNKSIZE,vf->datasource);
69     if(bytes>0)ogg_sync_wrote(&vf->oy,bytes);
70     if(bytes==0 && errno)return(-1);
71     return(bytes);
72   }else
73     return(0);
74 }
75
76 /* save a tiny smidge of verbosity to make the code more readable */
77 static void _seek_helper(OggVorbis_File *vf,long offset){
78   if(vf->datasource){ 
79     (vf->callbacks.seek_func)(vf->datasource, offset, SEEK_SET);
80     vf->offset=offset;
81     ogg_sync_reset(&vf->oy);
82   }else{
83     /* shouldn't happen unless someone writes a broken callback */
84     return;
85   }
86 }
87
88 /* The read/seek functions track absolute position within the stream */
89
90 /* from the head of the stream, get the next page.  boundary specifies
91    if the function is allowed to fetch more data from the stream (and
92    how much) or only use internally buffered data.
93
94    boundary: -1) unbounded search
95               0) read no additional data; use cached only
96               n) search for a new page beginning for n bytes
97
98    return:   <0) did not find a page (OV_FALSE, OV_EOF, OV_EREAD)
99               n) found a page at absolute offset n */
100
101 static long _get_next_page(OggVorbis_File *vf,ogg_page *og,int boundary){
102   if(boundary>0)boundary+=vf->offset;
103   while(1){
104     long more;
105
106     if(boundary>0 && vf->offset>=boundary)return(OV_FALSE);
107     more=ogg_sync_pageseek(&vf->oy,og);
108     
109     if(more<0){
110       /* skipped n bytes */
111       vf->offset-=more;
112     }else{
113       if(more==0){
114         /* send more paramedics */
115         if(!boundary)return(OV_FALSE);
116         {
117           long ret=_get_data(vf);
118           if(ret==0)return(OV_EOF);
119           if(ret<0)return(OV_EREAD);
120         }
121       }else{
122         /* got a page.  Return the offset at the page beginning,
123            advance the internal offset past the page end */
124         long ret=vf->offset;
125         vf->offset+=more;
126         return(ret);
127         
128       }
129     }
130   }
131 }
132
133 /* find the latest page beginning before the current stream cursor
134    position. Much dirtier than the above as Ogg doesn't have any
135    backward search linkage.  no 'readp' as it will certainly have to
136    read. */
137 /* returns offset or OV_EREAD, OV_FAULT */
138 static long _get_prev_page(OggVorbis_File *vf,ogg_page *og){
139   long begin=vf->offset;
140   long ret;
141   int offset=-1;
142
143   while(offset==-1){
144     begin-=CHUNKSIZE;
145     _seek_helper(vf,begin);
146     while(vf->offset<begin+CHUNKSIZE){
147       ret=_get_next_page(vf,og,begin+CHUNKSIZE-vf->offset);
148       if(ret==OV_EREAD)return(OV_EREAD);
149       if(ret<0){
150         break;
151       }else{
152         offset=ret;
153       }
154     }
155   }
156
157   /* we have the offset.  Actually snork and hold the page now */
158   _seek_helper(vf,offset);
159   ret=_get_next_page(vf,og,CHUNKSIZE);
160   if(ret<0)
161     /* this shouldn't be possible */
162     return(OV_EFAULT);
163
164   return(offset);
165 }
166
167 /* finds each bitstream link one at a time using a bisection search
168    (has to begin by knowing the offset of the lb's initial page).
169    Recurses for each link so it can alloc the link storage after
170    finding them all, then unroll and fill the cache at the same time */
171 static int _bisect_forward_serialno(OggVorbis_File *vf,
172                                     long begin,
173                                     long searched,
174                                     long end,
175                                     long currentno,
176                                     long m){
177   long endsearched=end;
178   long next=end;
179   ogg_page og;
180   long ret;
181   
182   /* the below guards against garbage seperating the last and
183      first pages of two links. */
184   while(searched<endsearched){
185     long bisect;
186     
187     if(endsearched-searched<CHUNKSIZE){
188       bisect=searched;
189     }else{
190       bisect=(searched+endsearched)/2;
191     }
192     
193     _seek_helper(vf,bisect);
194     ret=_get_next_page(vf,&og,-1);
195     if(ret==OV_EREAD)return(OV_EREAD);
196     if(ret<0 || ogg_page_serialno(&og)!=currentno){
197       endsearched=bisect;
198       if(ret>=0)next=ret;
199     }else{
200       searched=ret+og.header_len+og.body_len;
201     }
202   }
203
204   _seek_helper(vf,next);
205   ret=_get_next_page(vf,&og,-1);
206   if(ret==OV_EREAD)return(OV_EREAD);
207   
208   if(searched>=end || ret<0){
209     vf->links=m+1;
210     vf->offsets=_ogg_malloc((m+2)*sizeof(ogg_int64_t));
211     vf->offsets[m+1]=searched;
212   }else{
213     ret=_bisect_forward_serialno(vf,next,vf->offset,
214                                  end,ogg_page_serialno(&og),m+1);
215     if(ret==OV_EREAD)return(OV_EREAD);
216   }
217   
218   vf->offsets[m]=begin;
219   return(0);
220 }
221
222 /* uses the local ogg_stream storage in vf; this is important for
223    non-streaming input sources */
224 static int _fetch_headers(OggVorbis_File *vf,vorbis_info *vi,vorbis_comment *vc,
225                           long *serialno,ogg_page *og_ptr){
226   ogg_page og;
227   ogg_packet op;
228   int i,ret=0;
229   
230   if(!og_ptr){
231     ret=_get_next_page(vf,&og,CHUNKSIZE);
232     if(ret==OV_EREAD)return(OV_EREAD);
233     if(ret<0)return OV_ENOTVORBIS;
234     og_ptr=&og;
235   }
236
237   if(serialno)*serialno=ogg_page_serialno(og_ptr);
238   ogg_stream_init(&vf->os,ogg_page_serialno(og_ptr));
239   vf->ready_state=STREAMSET;
240   
241   /* extract the initial header from the first page and verify that the
242      Ogg bitstream is in fact Vorbis data */
243   
244   vorbis_info_init(vi);
245   vorbis_comment_init(vc);
246   
247   i=0;
248   while(i<3){
249     ogg_stream_pagein(&vf->os,og_ptr);
250     while(i<3){
251       int result=ogg_stream_packetout(&vf->os,&op);
252       if(result==0)break;
253       if(result==-1){
254         ret=OV_EBADHEADER;
255         goto bail_header;
256       }
257       if((ret=vorbis_synthesis_headerin(vi,vc,&op))){
258         goto bail_header;
259       }
260       i++;
261     }
262     if(i<3)
263       if(_get_next_page(vf,og_ptr,1)<0){
264         ret=OV_EBADHEADER;
265         goto bail_header;
266       }
267   }
268   return 0; 
269
270  bail_header:
271   vorbis_info_clear(vi);
272   vorbis_comment_clear(vc);
273   ogg_stream_clear(&vf->os);
274   return ret;
275 }
276
277 /* last step of the OggVorbis_File initialization; get all the
278    vorbis_info structs and PCM positions.  Only called by the seekable
279    initialization (local stream storage is hacked slightly; pay
280    attention to how that's done) */
281
282 /* this is void and does not propogate errors up because we want to be
283    able to open and use damaged bitstreams as well as we can.  Just
284    watch out for missing information for links in the OggVorbis_File
285    struct */
286 static void _prefetch_all_headers(OggVorbis_File *vf, long dataoffset){
287   ogg_page og;
288   int i,ret;
289   
290   vf->vi=_ogg_realloc(vf->vi,vf->links*sizeof(vorbis_info));
291   vf->vc=_ogg_realloc(vf->vc,vf->links*sizeof(vorbis_info));
292   vf->dataoffsets=_ogg_malloc(vf->links*sizeof(ogg_int64_t));
293   vf->pcmlengths=_ogg_malloc(vf->links*sizeof(ogg_int64_t));
294   vf->serialnos=_ogg_malloc(vf->links*sizeof(long));
295   
296   for(i=0;i<vf->links;i++){
297     if(i==0){
298       /* we already grabbed the initial header earlier.  Just set the offset */
299       vf->dataoffsets[i]=dataoffset;
300     }else{
301
302       /* seek to the location of the initial header */
303
304       _seek_helper(vf,vf->offsets[i]);
305       if(_fetch_headers(vf,vf->vi+i,vf->vc+i,NULL,NULL)<0){
306         vf->dataoffsets[i]=-1;
307       }else{
308         vf->dataoffsets[i]=vf->offset;
309         ogg_stream_clear(&vf->os);
310       }
311     }
312
313     /* get the serial number and PCM length of this link. To do this,
314        get the last page of the stream */
315     {
316       long end=vf->offsets[i+1];
317       _seek_helper(vf,end);
318
319       while(1){
320         ret=_get_prev_page(vf,&og);
321         if(ret<0){
322           /* this should not be possible */
323           vorbis_info_clear(vf->vi+i);
324           vorbis_comment_clear(vf->vc+i);
325           break;
326         }
327         if(ogg_page_granulepos(&og)!=-1){
328           vf->serialnos[i]=ogg_page_serialno(&og);
329           vf->pcmlengths[i]=ogg_page_granulepos(&og);
330           break;
331         }
332         vf->offset=ret;
333       }
334     }
335   }
336 }
337
338 static void _make_decode_ready(OggVorbis_File *vf){
339   if(vf->ready_state!=STREAMSET)return;
340   if(vf->seekable){
341     vorbis_synthesis_init(&vf->vd,vf->vi+vf->current_link);
342   }else{
343     vorbis_synthesis_init(&vf->vd,vf->vi);
344   }    
345   vorbis_block_init(&vf->vd,&vf->vb);
346   vf->ready_state=INITSET;
347   return;
348 }
349
350 static int _open_seekable2(OggVorbis_File *vf){
351   long serialno=vf->current_serialno,end;
352   long dataoffset=vf->offset;
353   ogg_page og;
354
355   /* we're partially open and have a first link header state in
356      storage in vf */
357   /* we can seek, so set out learning all about this file */
358   (vf->callbacks.seek_func)(vf->datasource,0,SEEK_END);
359   vf->offset=vf->end=(vf->callbacks.tell_func)(vf->datasource);
360   
361   /* We get the offset for the last page of the physical bitstream.
362      Most OggVorbis files will contain a single logical bitstream */
363   end=_get_prev_page(vf,&og);
364   if(end<0){
365     ov_clear(vf);
366     return(end);
367   }
368
369   /* more than one logical bitstream? */
370   if(ogg_page_serialno(&og)!=serialno){
371
372     /* Chained bitstream. Bisect-search each logical bitstream
373        section.  Do so based on serial number only */
374     if(_bisect_forward_serialno(vf,0,0,end+1,serialno,0)<0){
375       ov_clear(vf);
376       return(OV_EREAD);
377     }
378
379   }else{
380
381     /* Only one logical bitstream */
382     if(_bisect_forward_serialno(vf,0,end,end+1,serialno,0)){
383       ov_clear(vf);
384       return(OV_EREAD);
385     }
386
387   }
388
389   /* the initial header memory is referenced by vf after; don't free it */
390   _prefetch_all_headers(vf,dataoffset);
391   return(ov_raw_seek(vf,0));
392 }
393
394 /* clear out the current logical bitstream decoder */ 
395 static void _decode_clear(OggVorbis_File *vf){
396   ogg_stream_clear(&vf->os);
397   vorbis_dsp_clear(&vf->vd);
398   vorbis_block_clear(&vf->vb);
399   vf->ready_state=OPENED;
400
401   vf->bittrack=0.f;
402   vf->samptrack=0.f;
403 }
404
405 /* fetch and process a packet.  Handles the case where we're at a
406    bitstream boundary and dumps the decoding machine.  If the decoding
407    machine is unloaded, it loads it.  It also keeps pcm_offset up to
408    date (seek and read both use this.  seek uses a special hack with
409    readp). 
410
411    return: <0) error, OV_HOLE (lost packet) or OV_EOF
412             0) need more data (only if readp==0)
413             1) got a packet 
414 */
415
416 static int _process_packet(OggVorbis_File *vf,int readp){
417   ogg_page og;
418
419   /* handle one packet.  Try to fetch it from current stream state */
420   /* extract packets from page */
421   while(1){
422     
423     /* process a packet if we can.  If the machine isn't loaded,
424        neither is a page */
425     if(vf->ready_state==INITSET){
426       ogg_packet op;
427       int result=ogg_stream_packetout(&vf->os,&op);
428       ogg_int64_t granulepos;
429
430       if(result==-1)return(OV_HOLE); /* hole in the data. */
431       if(result>0){
432         /* got a packet.  process it */
433         granulepos=op.granulepos;
434         if(!vorbis_synthesis(&vf->vb,&op)){ /* lazy check for lazy
435                                                header handling.  The
436                                                header packets aren't
437                                                audio, so if/when we
438                                                submit them,
439                                                vorbis_synthesis will
440                                                reject them */
441
442           /* suck in the synthesis data and track bitrate */
443           {
444             int oldsamples=vorbis_synthesis_pcmout(&vf->vd,NULL);
445             vorbis_synthesis_blockin(&vf->vd,&vf->vb);
446             vf->samptrack+=vorbis_synthesis_pcmout(&vf->vd,NULL)-oldsamples;
447             vf->bittrack+=op.bytes*8;
448           }
449           
450           /* update the pcm offset. */
451           if(granulepos!=-1 && !op.e_o_s){
452             int link=(vf->seekable?vf->current_link:0);
453             int i,samples;
454             
455             /* this packet has a pcm_offset on it (the last packet
456                completed on a page carries the offset) After processing
457                (above), we know the pcm position of the *last* sample
458                ready to be returned. Find the offset of the *first*
459
460                As an aside, this trick is inaccurate if we begin
461                reading anew right at the last page; the end-of-stream
462                granulepos declares the last frame in the stream, and the
463                last packet of the last page may be a partial frame.
464                So, we need a previous granulepos from an in-sequence page
465                to have a reference point.  Thus the !op.e_o_s clause
466                above */
467             
468             samples=vorbis_synthesis_pcmout(&vf->vd,NULL);
469             
470             granulepos-=samples;
471             for(i=0;i<link;i++)
472               granulepos+=vf->pcmlengths[i];
473             vf->pcm_offset=granulepos;
474           }
475           return(1);
476         }
477       }
478     }
479
480     if(vf->ready_state>=STREAMSET){
481       if(!readp)return(0);
482       if(_get_next_page(vf,&og,-1)<0)return(OV_EOF); /* eof. 
483                                                         leave unitialized */
484       
485       /* bitrate tracking; add the header's bytes here, the body bytes
486          are done by packet above */
487       vf->bittrack+=og.header_len*8;
488       
489       /* has our decoding just traversed a bitstream boundary? */
490       if(vf->ready_state==INITSET){
491         if(vf->current_serialno!=ogg_page_serialno(&og)){
492           _decode_clear(vf);
493           
494           if(!vf->seekable){
495             vorbis_info_clear(vf->vi);
496             vorbis_comment_clear(vf->vc);
497           }
498         }
499       }
500     }
501
502     /* Do we need to load a new machine before submitting the page? */
503     /* This is different in the seekable and non-seekable cases.  
504
505        In the seekable case, we already have all the header
506        information loaded and cached; we just initialize the machine
507        with it and continue on our merry way.
508
509        In the non-seekable (streaming) case, we'll only be at a
510        boundary if we just left the previous logical bitstream and
511        we're now nominally at the header of the next bitstream
512     */
513
514     if(vf->ready_state!=INITSET){ 
515       int link;
516
517       if(vf->ready_state<STREAMSET){
518         if(vf->seekable){
519           vf->current_serialno=ogg_page_serialno(&og);
520           
521           /* match the serialno to bitstream section.  We use this rather than
522              offset positions to avoid problems near logical bitstream
523              boundaries */
524           for(link=0;link<vf->links;link++)
525             if(vf->serialnos[link]==vf->current_serialno)break;
526           if(link==vf->links)return(OV_EBADLINK); /* sign of a bogus
527                                                      stream.  error out,
528                                                      leave machine
529                                                      uninitialized */
530           
531           vf->current_link=link;
532           
533           ogg_stream_init(&vf->os,vf->current_serialno);
534           ogg_stream_reset(&vf->os); 
535           vf->ready_state=STREAMSET;
536           
537         }else{
538           /* we're streaming */
539           /* fetch the three header packets, build the info struct */
540           
541           _fetch_headers(vf,vf->vi,vf->vc,&vf->current_serialno,&og);
542           vf->current_link++;
543           link=0;
544         }
545       }
546       
547       _make_decode_ready(vf);
548     }
549     ogg_stream_pagein(&vf->os,&og);
550   }
551 }
552
553 static int _fseek64_wrap(FILE *f,ogg_int64_t off,int whence){
554   if(f==NULL)return(-1);
555   return fseek(f,(int)off,whence);
556 }
557
558 static int _ov_open1(void *f,OggVorbis_File *vf,char *initial,
559                      long ibytes, ov_callbacks callbacks){
560   long offset=(f?callbacks.seek_func(f,0,SEEK_CUR):-1);
561   int ret;
562
563   memset(vf,0,sizeof(OggVorbis_File));
564   vf->datasource=f;
565   vf->callbacks = callbacks;
566
567   /* init the framing state */
568   ogg_sync_init(&vf->oy);
569
570   /* perhaps some data was previously read into a buffer for testing
571      against other stream types.  Allow initialization from this
572      previously read data (as we may be reading from a non-seekable
573      stream) */
574   if(initial){
575     char *buffer=ogg_sync_buffer(&vf->oy,ibytes);
576     memcpy(buffer,initial,ibytes);
577     ogg_sync_wrote(&vf->oy,ibytes);
578   }
579
580   /* can we seek? Stevens suggests the seek test was portable */
581   if(offset!=-1)vf->seekable=1;
582
583   /* No seeking yet; Set up a 'single' (current) logical bitstream
584      entry for partial open */
585   vf->links=1;
586   vf->vi=_ogg_calloc(vf->links,sizeof(vorbis_info));
587   vf->vc=_ogg_calloc(vf->links,sizeof(vorbis_info));
588   
589   /* Try to fetch the headers, maintaining all the storage */
590   if((ret=_fetch_headers(vf,vf->vi,vf->vc,&vf->current_serialno,NULL))<0){
591     vf->datasource=NULL;
592     ov_clear(vf);
593   }else if(vf->ready_state < PARTOPEN)
594     vf->ready_state=PARTOPEN;
595   return(ret);
596 }
597
598 static int _ov_open2(OggVorbis_File *vf){
599   if(vf->ready_state < OPENED)
600     vf->ready_state=OPENED;
601   if(vf->seekable){
602     int ret=_open_seekable2(vf);
603     if(ret){
604       vf->datasource=NULL;
605       ov_clear(vf);
606     }
607     return(ret);
608   }
609   return 0;
610 }
611
612
613 /* clear out the OggVorbis_File struct */
614 int ov_clear(OggVorbis_File *vf){
615   if(vf){
616     vorbis_block_clear(&vf->vb);
617     vorbis_dsp_clear(&vf->vd);
618     ogg_stream_clear(&vf->os);
619     
620     if(vf->vi && vf->links){
621       int i;
622       for(i=0;i<vf->links;i++){
623         vorbis_info_clear(vf->vi+i);
624         vorbis_comment_clear(vf->vc+i);
625       }
626       _ogg_free(vf->vi);
627       _ogg_free(vf->vc);
628     }
629     if(vf->dataoffsets)_ogg_free(vf->dataoffsets);
630     if(vf->pcmlengths)_ogg_free(vf->pcmlengths);
631     if(vf->serialnos)_ogg_free(vf->serialnos);
632     if(vf->offsets)_ogg_free(vf->offsets);
633     ogg_sync_clear(&vf->oy);
634     if(vf->datasource)(vf->callbacks.close_func)(vf->datasource);
635     memset(vf,0,sizeof(OggVorbis_File));
636   }
637 #ifdef DEBUG_LEAKS
638   _VDBG_dump();
639 #endif
640   return(0);
641 }
642
643 /* inspects the OggVorbis file and finds/documents all the logical
644    bitstreams contained in it.  Tries to be tolerant of logical
645    bitstream sections that are truncated/woogie. 
646
647    return: -1) error
648             0) OK
649 */
650
651 int ov_open_callbacks(void *f,OggVorbis_File *vf,char *initial,long ibytes,
652     ov_callbacks callbacks){
653   int ret=_ov_open1(f,vf,initial,ibytes,callbacks);
654   if(ret)return ret;
655   return _ov_open2(vf);
656 }
657
658 int ov_open(FILE *f,OggVorbis_File *vf,char *initial,long ibytes){
659   ov_callbacks callbacks = {
660     (size_t (*)(void *, size_t, size_t, void *))  fread,
661     (int (*)(void *, ogg_int64_t, int))              _fseek64_wrap,
662     (int (*)(void *))                             fclose,
663     (long (*)(void *))                            ftell
664   };
665
666   return ov_open_callbacks((void *)f, vf, initial, ibytes, callbacks);
667 }
668   
669 /* Only partially open the vorbis file; test for Vorbisness, and load
670    the headers for the first chain.  Do not seek (although test for
671    seekability).  Use ov_test_open to finish opening the file, else
672    ov_clear to close/free it. Same return codes as open. */
673
674 int ov_test_callbacks(void *f,OggVorbis_File *vf,char *initial,long ibytes,
675     ov_callbacks callbacks)
676 {
677   return _ov_open1(f,vf,initial,ibytes,callbacks);
678 }
679
680 int ov_test(FILE *f,OggVorbis_File *vf,char *initial,long ibytes){
681   ov_callbacks callbacks = {
682     (size_t (*)(void *, size_t, size_t, void *))  fread,
683     (int (*)(void *, ogg_int64_t, int))              _fseek64_wrap,
684     (int (*)(void *))                             fclose,
685     (long (*)(void *))                            ftell
686   };
687
688   return ov_test_callbacks((void *)f, vf, initial, ibytes, callbacks);
689 }
690   
691 int ov_test_open(OggVorbis_File *vf){
692   if(vf->ready_state!=PARTOPEN)return(OV_EINVAL);
693   return _ov_open2(vf);
694 }
695
696 /* How many logical bitstreams in this physical bitstream? */
697 long ov_streams(OggVorbis_File *vf){
698   return vf->links;
699 }
700
701 /* Is the FILE * associated with vf seekable? */
702 long ov_seekable(OggVorbis_File *vf){
703   return vf->seekable;
704 }
705
706 /* returns the bitrate for a given logical bitstream or the entire
707    physical bitstream.  If the file is open for random access, it will
708    find the *actual* average bitrate.  If the file is streaming, it
709    returns the nominal bitrate (if set) else the average of the
710    upper/lower bounds (if set) else -1 (unset).
711
712    If you want the actual bitrate field settings, get them from the
713    vorbis_info structs */
714
715 long ov_bitrate(OggVorbis_File *vf,int i){
716   if(vf->ready_state<OPENED)return(OV_EINVAL);
717   if(i>=vf->links)return(OV_EINVAL);
718   if(!vf->seekable && i!=0)return(ov_bitrate(vf,0));
719   if(i<0){
720     ogg_int64_t bits=0;
721     int i;
722     for(i=0;i<vf->links;i++)
723       bits+=(vf->offsets[i+1]-vf->dataoffsets[i])*8;
724     return(rint(bits/ov_time_total(vf,-1)));
725   }else{
726     if(vf->seekable){
727       /* return the actual bitrate */
728       return(rint((vf->offsets[i+1]-vf->dataoffsets[i])*8/ov_time_total(vf,i)));
729     }else{
730       /* return nominal if set */
731       if(vf->vi[i].bitrate_nominal>0){
732         return vf->vi[i].bitrate_nominal;
733       }else{
734         if(vf->vi[i].bitrate_upper>0){
735           if(vf->vi[i].bitrate_lower>0){
736             return (vf->vi[i].bitrate_upper+vf->vi[i].bitrate_lower)/2;
737           }else{
738             return vf->vi[i].bitrate_upper;
739           }
740         }
741         return(OV_FALSE);
742       }
743     }
744   }
745 }
746
747 /* returns the actual bitrate since last call.  returns -1 if no
748    additional data to offer since last call (or at beginning of stream),
749    EINVAL if stream is only partially open 
750 */
751 long ov_bitrate_instant(OggVorbis_File *vf){
752   int link=(vf->seekable?vf->current_link:0);
753   long ret;
754   if(vf->ready_state<OPENED)return(OV_EINVAL);
755   if(vf->samptrack==0)return(OV_FALSE);
756   ret=vf->bittrack/vf->samptrack*vf->vi[link].rate+.5;
757   vf->bittrack=0.f;
758   vf->samptrack=0.f;
759   return(ret);
760 }
761
762 /* Guess */
763 long ov_serialnumber(OggVorbis_File *vf,int i){
764   if(i>=vf->links)return(ov_serialnumber(vf,vf->links-1));
765   if(!vf->seekable && i>=0)return(ov_serialnumber(vf,-1));
766   if(i<0){
767     return(vf->current_serialno);
768   }else{
769     return(vf->serialnos[i]);
770   }
771 }
772
773 /* returns: total raw (compressed) length of content if i==-1
774             raw (compressed) length of that logical bitstream for i==0 to n
775             OV_EINVAL if the stream is not seekable (we can't know the length)
776             or if stream is only partially open
777 */
778 ogg_int64_t ov_raw_total(OggVorbis_File *vf,int i){
779   if(vf->ready_state<OPENED)return(OV_EINVAL);
780   if(!vf->seekable || i>=vf->links)return(OV_EINVAL);
781   if(i<0){
782     long acc=0;
783     int i;
784     for(i=0;i<vf->links;i++)
785       acc+=ov_raw_total(vf,i);
786     return(acc);
787   }else{
788     return(vf->offsets[i+1]-vf->offsets[i]);
789   }
790 }
791
792 /* returns: total PCM length (samples) of content if i==-1 PCM length
793             (samples) of that logical bitstream for i==0 to n
794             OV_EINVAL if the stream is not seekable (we can't know the
795             length) or only partially open 
796 */
797 ogg_int64_t ov_pcm_total(OggVorbis_File *vf,int i){
798   if(vf->ready_state<OPENED)return(OV_EINVAL);
799   if(!vf->seekable || i>=vf->links)return(OV_EINVAL);
800   if(i<0){
801     ogg_int64_t acc=0;
802     int i;
803     for(i=0;i<vf->links;i++)
804       acc+=ov_pcm_total(vf,i);
805     return(acc);
806   }else{
807     return(vf->pcmlengths[i]);
808   }
809 }
810
811 /* returns: total seconds of content if i==-1
812             seconds in that logical bitstream for i==0 to n
813             OV_EINVAL if the stream is not seekable (we can't know the
814             length) or only partially open 
815 */
816 double ov_time_total(OggVorbis_File *vf,int i){
817   if(vf->ready_state<OPENED)return(OV_EINVAL);
818   if(!vf->seekable || i>=vf->links)return(OV_EINVAL);
819   if(i<0){
820     double acc=0;
821     int i;
822     for(i=0;i<vf->links;i++)
823       acc+=ov_time_total(vf,i);
824     return(acc);
825   }else{
826     return((float)(vf->pcmlengths[i])/vf->vi[i].rate);
827   }
828 }
829
830 /* seek to an offset relative to the *compressed* data. This also
831    scans packets to update the PCM cursor. It will cross a logical
832    bitstream boundary, but only if it can't get any packets out of the
833    tail of the bitstream we seek to (so no surprises).
834
835    returns zero on success, nonzero on failure */
836
837 int ov_raw_seek(OggVorbis_File *vf,long pos){
838   ogg_stream_state work_os;
839
840   if(vf->ready_state<OPENED)return(OV_EINVAL);
841   if(!vf->seekable)
842     return(OV_ENOSEEK); /* don't dump machine if we can't seek */
843
844   if(pos<0 || pos>vf->offsets[vf->links])return(OV_EINVAL);
845
846   /* clear out decoding machine state */
847   vf->pcm_offset=-1;
848   _decode_clear(vf);
849   
850   _seek_helper(vf,pos);
851
852   /* we need to make sure the pcm_offset is set, but we don't want to
853      advance the raw cursor past good packets just to get to the first
854      with a granulepos.  That's not equivalent behavior to beginning
855      decoding as immediately after the seek position as possible.
856
857      So, a hack.  We use two stream states; a local scratch state and
858      a the shared vf->os stream state.  We use the local state to
859      scan, and the shared state as a buffer for later decode. 
860
861      Unfortuantely, on the last page we still advance to last packet
862      because the granulepos on the last page is not necessarily on a
863      packet boundary, and we need to make sure the granpos is
864      correct. 
865   */
866
867   {
868     ogg_page og;
869     ogg_packet op;
870     int lastblock=0;
871     int accblock=0;
872     int thisblock;
873     int eosflag;
874
875     memset(&work_os,0,sizeof(work_os));/* so that it's safe to clear
876                                           it later even if we don't
877                                           init it */
878
879     while(1){
880       if(vf->ready_state==STREAMSET){
881         /* snarf/scan a packet if we can */
882         int result=ogg_stream_packetout(&work_os,&op);
883       
884         if(result>0){
885
886           if(vf->vi[vf->current_link].codec_setup)
887             thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op);
888           if(eosflag)
889             ogg_stream_packetout(&vf->os,NULL);
890           else
891             if(lastblock)accblock+=(lastblock+thisblock)>>2;
892
893           if(op.granulepos!=-1){
894             int i,link=vf->current_link;
895             ogg_int64_t granulepos=op.granulepos;
896             
897             for(i=0;i<link;i++)
898               granulepos+=vf->pcmlengths[i];
899             vf->pcm_offset=granulepos-accblock;
900             break;
901           }
902           lastblock=thisblock;
903           continue;
904         }
905       }
906       
907       if(!lastblock){
908         if(_get_next_page(vf,&og,-1)<0){
909           vf->pcm_offset=ov_pcm_total(vf,-1);
910           break;
911         }
912       }else{
913         /* huh?  Bogus stream with packets but no granulepos */
914         vf->pcm_offset=-1;
915         break;
916       }
917       
918       /* has our decoding just traversed a bitstream boundary? */
919       if(vf->ready_state==STREAMSET)
920         if(vf->current_serialno!=ogg_page_serialno(&og)){
921         _decode_clear(vf); /* clear out stream state */
922         ogg_stream_clear(&work_os);
923       }
924
925       if(vf->ready_state<STREAMSET){
926         int link;
927         
928         vf->current_serialno=ogg_page_serialno(&og);
929         for(link=0;link<vf->links;link++)
930           if(vf->serialnos[link]==vf->current_serialno)break;
931         if(link==vf->links)goto seek_error; /* sign of a bogus stream.
932                                                error out, leave
933                                                machine uninitialized */
934         vf->current_link=link;
935         
936         ogg_stream_init(&vf->os,vf->current_serialno);
937         ogg_stream_reset(&vf->os); 
938         ogg_stream_init(&work_os,vf->current_serialno);
939         ogg_stream_reset(&work_os); 
940         vf->ready_state=STREAMSET;
941         
942       }
943     
944       ogg_stream_pagein(&vf->os,&og);
945       ogg_stream_pagein(&work_os,&og);
946       eosflag=ogg_page_eos(&og);
947     }
948   }
949
950   ogg_stream_clear(&work_os);
951   return(0);
952
953  seek_error:
954   /* dump the machine so we're in a known state */
955   vf->pcm_offset=-1;
956   ogg_stream_clear(&work_os);
957   _decode_clear(vf);
958   return OV_EBADLINK;
959 }
960
961 /* Page granularity seek (faster than sample granularity because we
962    don't do the last bit of decode to find a specific sample).
963
964    Seek to the last [granule marked] page preceeding the specified pos
965    location, such that decoding past the returned point will quickly
966    arrive at the requested position. */
967 int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
968   int link=-1;
969   long ret;
970   ogg_int64_t total=ov_pcm_total(vf,-1);
971
972   if(vf->ready_state<OPENED)return(OV_EINVAL);
973   if(!vf->seekable)return(OV_ENOSEEK);
974   if(pos<0 || pos>total)return(OV_EINVAL);
975  
976   /* which bitstream section does this pcm offset occur in? */
977   for(link=vf->links-1;link>=0;link--){
978     total-=vf->pcmlengths[link];
979     if(pos>=total)break;
980   }
981
982   /* search within the logical bitstream for the page with the highest
983      pcm_pos preceeding (or equal to) pos.  There is a danger here;
984      missing pages or incorrect frame number information in the
985      bitstream could make our task impossible.  Account for that (it
986      would be an error condition) */
987
988   /* new search algorithm by HB (Nicholas Vinen) */
989   {
990     ogg_int64_t target=pos-total;
991     long end=vf->offsets[link+1];
992     long begin=vf->offsets[link];
993     ogg_int64_t endtime = vf->pcmlengths[link];
994     ogg_int64_t begintime = 0;
995     long best=begin;
996     
997     ogg_page og;
998     while(begin<end){
999       long bisect;
1000       
1001       if(end-begin<CHUNKSIZE){
1002         bisect=begin;
1003       }else{
1004         /* take a (pretty decent) guess. */
1005         bisect=begin + 
1006           (target-begintime)*(end-begin)/(endtime-begintime) - CHUNKSIZE;
1007         if(bisect<=begin)
1008           bisect=begin+1;
1009       }
1010       _seek_helper(vf,bisect);
1011     
1012       while(begin<end){
1013         ret=_get_next_page(vf,&og,end-bisect);
1014         if(ret==OV_EREAD) goto seek_error;
1015         if(ret<0){
1016           if(bisect<=begin+1)
1017             end=begin; /* found it */
1018           else{
1019             if(bisect==0)goto seek_error;
1020             bisect-=CHUNKSIZE;
1021             if(bisect<=begin)bisect=begin+1;
1022             _seek_helper(vf,bisect);
1023           }
1024         }else{
1025           ogg_int64_t granulepos=ogg_page_granulepos(&og);
1026           if(granulepos<target){
1027             best=ret;  /* raw offset of packet with granulepos */ 
1028             begin=vf->offset; /* raw offset of next page */
1029             begintime=granulepos;
1030             
1031             if(target-begin>44100)break;
1032             bisect=begin; /* *not* begin + 1 */
1033           }else{
1034             if(bisect<=begin+1)
1035               end=begin;  /* found it */
1036             else{
1037               if(end==vf->offset){ /* we're pretty close - we'd be stuck in */
1038                 end=ret;
1039                 bisect-=CHUNKSIZE; /* an endless loop otherwise. */
1040                 if(bisect<=begin)bisect=begin+1;
1041                 _seek_helper(vf,bisect);
1042               }else{
1043                 end=ret;
1044                 endtime=granulepos;
1045                 break;
1046               }
1047             }
1048           }
1049         }
1050       }
1051     }
1052
1053     /* found our page. seek to it, update pcm offset. Easier case than
1054        raw_seek, don't keep packets preceeding granulepos. */
1055     {
1056       ogg_page og;
1057       ogg_packet op;
1058       /* clear out decoding machine state */
1059       _decode_clear(vf);  
1060       /* seek */
1061       _seek_helper(vf,best);
1062       
1063       if(_get_next_page(vf,&og,-1)<0)return(OV_EOF); /* shouldn't happen */
1064       vf->current_serialno=ogg_page_serialno(&og);
1065       vf->current_link=link;
1066       
1067       ogg_stream_init(&vf->os,vf->current_serialno);
1068       ogg_stream_reset(&vf->os); 
1069       vf->ready_state=STREAMSET;
1070       ogg_stream_pagein(&vf->os,&og);
1071
1072       /* pull out all but last packet; the one with granulepos */
1073       while(1){
1074         ret=ogg_stream_packetpeek(&vf->os,&op);
1075         if(ret==0){
1076           /* !!! the packet finishing this page originated on a
1077              preceeding page. Keep fetching previous pages until we
1078              get one with a granulepos or without the 'continued' flag
1079              set.  Then just use raw_seek for simplicity. */
1080           while(1){
1081             ret=_get_prev_page(vf,&og);
1082             if(ret<0)goto seek_error;
1083             if(ogg_page_granulepos(&og)>-1 ||
1084                !ogg_page_continued(&og)){
1085               return ov_raw_seek(vf,ret);
1086             }
1087             vf->offset=ret;
1088           }
1089         }
1090         if(ret<0)goto seek_error;
1091         if(op.granulepos!=-1){
1092           vf->pcm_offset=op.granulepos+total;
1093           break;
1094         }else
1095           ret=ogg_stream_packetout(&vf->os,NULL);
1096       }
1097     }
1098   }
1099   
1100   /* verify result */
1101   if(vf->pcm_offset>pos || pos>ov_pcm_total(vf,-1)){
1102     ret=OV_EFAULT;
1103     goto seek_error;
1104   }
1105   return(0);
1106   
1107  seek_error:
1108   /* dump machine so we're in a known state */
1109   vf->pcm_offset=-1;
1110   _decode_clear(vf);
1111   return ret;
1112 }
1113
1114 /* seek to a sample offset relative to the decompressed pcm stream 
1115    returns zero on success, nonzero on failure */
1116
1117 int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos){
1118   int thisblock,lastblock=0;
1119   int ret=ov_pcm_seek_page(vf,pos);
1120   codec_setup_info *ci=vf->vi->codec_setup;
1121   if(ret<0)return(ret);
1122
1123   /* discard leading packets we don't need for the lapping of the
1124      position we want; don't decode them */
1125
1126   while(1){
1127     ogg_packet op;
1128     ogg_page og;
1129
1130     int ret=ogg_stream_packetpeek(&vf->os,&op);
1131     if(ret>0){
1132       thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op);
1133       if(lastblock)vf->pcm_offset+=(lastblock+thisblock)>>2;
1134
1135       if(vf->pcm_offset+((thisblock+ci->blocksizes[1])>>2)>=pos)break;
1136
1137       ogg_stream_packetout(&vf->os,NULL);
1138       
1139
1140       /* end of logical stream case is hard, especially with exact
1141          length positioning. */
1142
1143       if(op.granulepos>-1){
1144         int i;
1145         /* always believe the stream markers */
1146         vf->pcm_offset=op.granulepos;
1147         for(i=0;i<vf->current_link;i++)
1148           vf->pcm_offset+=vf->pcmlengths[i];
1149       }
1150
1151       lastblock=thisblock;
1152
1153     }else{
1154       if(ret<0 && ret!=OV_HOLE)break;
1155       
1156       /* suck in a new page */
1157       if(_get_next_page(vf,&og,-1)<0)break;
1158       if(vf->current_serialno!=ogg_page_serialno(&og))_decode_clear(vf);
1159       
1160       if(vf->ready_state<STREAMSET){
1161         int link;
1162         
1163         vf->current_serialno=ogg_page_serialno(&og);
1164         for(link=0;link<vf->links;link++)
1165           if(vf->serialnos[link]==vf->current_serialno)break;
1166         if(link==vf->links)return(OV_EBADLINK);
1167         vf->current_link=link;
1168         
1169         ogg_stream_init(&vf->os,vf->current_serialno);
1170         ogg_stream_reset(&vf->os); 
1171         vf->ready_state=STREAMSET;      
1172         lastblock=0;
1173       }
1174       ogg_stream_pagein(&vf->os,&og);
1175     }
1176   }
1177
1178   /* discard samples until we reach the desired position. Crossing a
1179      logical bitstream boundary with abandon is OK. */
1180   _make_decode_ready(vf);
1181   while(vf->pcm_offset<pos){
1182     float **pcm;
1183     long target=pos-vf->pcm_offset;
1184     long samples=vorbis_synthesis_pcmout(&vf->vd,&pcm);
1185
1186     if(samples>target)samples=target;
1187     vorbis_synthesis_read(&vf->vd,samples);
1188     vf->pcm_offset+=samples;
1189     
1190     if(samples<target)
1191       if(_process_packet(vf,1)<=0)
1192         vf->pcm_offset=ov_pcm_total(vf,-1); /* eof */
1193   }
1194   return 0;
1195 }
1196
1197 /* seek to a playback time relative to the decompressed pcm stream 
1198    returns zero on success, nonzero on failure */
1199 int ov_time_seek(OggVorbis_File *vf,double seconds){
1200   /* translate time to PCM position and call ov_pcm_seek */
1201
1202   int link=-1;
1203   ogg_int64_t pcm_total=ov_pcm_total(vf,-1);
1204   double time_total=ov_time_total(vf,-1);
1205
1206   if(vf->ready_state<OPENED)return(OV_EINVAL);
1207   if(!vf->seekable)return(OV_ENOSEEK);
1208   if(seconds<0 || seconds>time_total)return(OV_EINVAL);
1209   
1210   /* which bitstream section does this time offset occur in? */
1211   for(link=vf->links-1;link>=0;link--){
1212     pcm_total-=vf->pcmlengths[link];
1213     time_total-=ov_time_total(vf,link);
1214     if(seconds>=time_total)break;
1215   }
1216
1217   /* enough information to convert time offset to pcm offset */
1218   {
1219     ogg_int64_t target=pcm_total+(seconds-time_total)*vf->vi[link].rate;
1220     return(ov_pcm_seek(vf,target));
1221   }
1222 }
1223
1224 /* page-granularity version of ov_time_seek 
1225    returns zero on success, nonzero on failure */
1226 int ov_time_seek_page(OggVorbis_File *vf,double seconds){
1227   /* translate time to PCM position and call ov_pcm_seek */
1228
1229   int link=-1;
1230   ogg_int64_t pcm_total=ov_pcm_total(vf,-1);
1231   double time_total=ov_time_total(vf,-1);
1232
1233   if(vf->ready_state<OPENED)return(OV_EINVAL);
1234   if(!vf->seekable)return(OV_ENOSEEK);
1235   if(seconds<0 || seconds>time_total)return(OV_EINVAL);
1236   
1237   /* which bitstream section does this time offset occur in? */
1238   for(link=vf->links-1;link>=0;link--){
1239     pcm_total-=vf->pcmlengths[link];
1240     time_total-=ov_time_total(vf,link);
1241     if(seconds>=time_total)break;
1242   }
1243
1244   /* enough information to convert time offset to pcm offset */
1245   {
1246     ogg_int64_t target=pcm_total+(seconds-time_total)*vf->vi[link].rate;
1247     return(ov_pcm_seek_page(vf,target));
1248   }
1249 }
1250
1251 /* tell the current stream offset cursor.  Note that seek followed by
1252    tell will likely not give the set offset due to caching */
1253 ogg_int64_t ov_raw_tell(OggVorbis_File *vf){
1254   if(vf->ready_state<OPENED)return(OV_EINVAL);
1255   return(vf->offset);
1256 }
1257
1258 /* return PCM offset (sample) of next PCM sample to be read */
1259 ogg_int64_t ov_pcm_tell(OggVorbis_File *vf){
1260   if(vf->ready_state<OPENED)return(OV_EINVAL);
1261   return(vf->pcm_offset);
1262 }
1263
1264 /* return time offset (seconds) of next PCM sample to be read */
1265 double ov_time_tell(OggVorbis_File *vf){
1266   /* translate time to PCM position and call ov_pcm_seek */
1267
1268   int link=-1;
1269   ogg_int64_t pcm_total=0;
1270   double time_total=0.f;
1271   
1272   if(vf->ready_state<OPENED)return(OV_EINVAL);
1273   if(vf->seekable){
1274     pcm_total=ov_pcm_total(vf,-1);
1275     time_total=ov_time_total(vf,-1);
1276   
1277     /* which bitstream section does this time offset occur in? */
1278     for(link=vf->links-1;link>=0;link--){
1279       pcm_total-=vf->pcmlengths[link];
1280       time_total-=ov_time_total(vf,link);
1281       if(vf->pcm_offset>=pcm_total)break;
1282     }
1283   }
1284
1285   return((double)time_total+(double)(vf->pcm_offset-pcm_total)/vf->vi[link].rate);
1286 }
1287
1288 /*  link:   -1) return the vorbis_info struct for the bitstream section
1289                 currently being decoded
1290            0-n) to request information for a specific bitstream section
1291     
1292     In the case of a non-seekable bitstream, any call returns the
1293     current bitstream.  NULL in the case that the machine is not
1294     initialized */
1295
1296 vorbis_info *ov_info(OggVorbis_File *vf,int link){
1297   if(vf->seekable){
1298     if(link<0)
1299       if(vf->ready_state>=STREAMSET)
1300         return vf->vi+vf->current_link;
1301       else
1302       return vf->vi;
1303     else
1304       if(link>=vf->links)
1305         return NULL;
1306       else
1307         return vf->vi+link;
1308   }else{
1309     return vf->vi;
1310   }
1311 }
1312
1313 /* grr, strong typing, grr, no templates/inheritence, grr */
1314 vorbis_comment *ov_comment(OggVorbis_File *vf,int link){
1315   if(vf->seekable){
1316     if(link<0)
1317       if(vf->ready_state>=STREAMSET)
1318         return vf->vc+vf->current_link;
1319       else
1320         return vf->vc;
1321     else
1322       if(link>=vf->links)
1323         return NULL;
1324       else
1325         return vf->vc+link;
1326   }else{
1327     return vf->vc;
1328   }
1329 }
1330
1331 int host_is_big_endian() {
1332   ogg_int32_t pattern = 0xfeedface; /* deadbeef */
1333   unsigned char *bytewise = (unsigned char *)&pattern;
1334   if (bytewise[0] == 0xfe) return 1;
1335   return 0;
1336 }
1337
1338 /* up to this point, everything could more or less hide the multiple
1339    logical bitstream nature of chaining from the toplevel application
1340    if the toplevel application didn't particularly care.  However, at
1341    the point that we actually read audio back, the multiple-section
1342    nature must surface: Multiple bitstream sections do not necessarily
1343    have to have the same number of channels or sampling rate.
1344
1345    ov_read returns the sequential logical bitstream number currently
1346    being decoded along with the PCM data in order that the toplevel
1347    application can take action on channel/sample rate changes.  This
1348    number will be incremented even for streamed (non-seekable) streams
1349    (for seekable streams, it represents the actual logical bitstream
1350    index within the physical bitstream.  Note that the accessor
1351    functions above are aware of this dichotomy).
1352
1353    input values: buffer) a buffer to hold packed PCM data for return
1354                  length) the byte length requested to be placed into buffer
1355                  bigendianp) should the data be packed LSB first (0) or
1356                              MSB first (1)
1357                  word) word size for output.  currently 1 (byte) or 
1358                        2 (16 bit short)
1359
1360    return values: <0) error/hole in data (OV_HOLE), partial open (OV_EINVAL)
1361                    0) EOF
1362                    n) number of bytes of PCM actually returned.  The
1363                    below works on a packet-by-packet basis, so the
1364                    return length is not related to the 'length' passed
1365                    in, just guaranteed to fit.
1366
1367             *section) set to the logical bitstream number */
1368
1369 long ov_read(OggVorbis_File *vf,char *buffer,int length,
1370                     int bigendianp,int word,int sgned,int *bitstream){
1371   int i,j;
1372   int host_endian = host_is_big_endian();
1373
1374   if(vf->ready_state<OPENED)return(OV_EINVAL);
1375   if(vf->ready_state==OPENED)return(OV_EOF); /* stream is always
1376                                                 initialized after
1377                                                 other calls (after
1378                                                 open)... unless there
1379                                                 was no page at the end
1380                                                 to initialize state
1381                                                 with. */
1382
1383   while(1){
1384     if(vf->ready_state>=STREAMSET){
1385       float **pcm;
1386       long samples=vorbis_synthesis_pcmout(&vf->vd,&pcm);
1387       if(samples){
1388         /* yay! proceed to pack data into the byte buffer */
1389
1390         long channels=ov_info(vf,-1)->channels;
1391         long bytespersample=word * channels;
1392         vorbis_fpu_control fpu;
1393         if(samples>length/bytespersample)samples=length/bytespersample;
1394         
1395         /* a tight loop to pack each size */
1396         {
1397           int val;
1398           if(word==1){
1399             int off=(sgned?0:128);
1400             vorbis_fpu_setround(&fpu);
1401             for(j=0;j<samples;j++)
1402               for(i=0;i<channels;i++){
1403                 val=vorbis_ftoi(pcm[i][j]*128.f);
1404                 if(val>127)val=127;
1405                 else if(val<-128)val=-128;
1406                 *buffer++=val+off;
1407               }
1408             vorbis_fpu_restore(fpu);
1409           }else{
1410             int off=(sgned?0:32768);
1411
1412             if(host_endian==bigendianp){
1413               if(sgned){
1414
1415                 vorbis_fpu_setround(&fpu);
1416                 for(i=0;i<channels;i++) { /* It's faster in this order */
1417                   float *src=pcm[i];
1418                   short *dest=((short *)buffer)+i;
1419                   for(j=0;j<samples;j++) {
1420                     val=vorbis_ftoi(src[j]*32768.f);
1421                     if(val>32767)val=32767;
1422                     else if(val<-32768)val=-32768;
1423                     *dest=val;
1424                     dest+=channels;
1425                   }
1426                 }
1427                 vorbis_fpu_restore(fpu);
1428
1429               }else{
1430
1431                 vorbis_fpu_setround(&fpu);
1432                 for(i=0;i<channels;i++) {
1433                   float *src=pcm[i];
1434                   short *dest=((short *)buffer)+i;
1435                   for(j=0;j<samples;j++) {
1436                     val=vorbis_ftoi(src[j]*32768.f);
1437                     if(val>32767)val=32767;
1438                     else if(val<-32768)val=-32768;
1439                     *dest=val+off;
1440                     dest+=channels;
1441                   }
1442                 }
1443                 vorbis_fpu_restore(fpu);
1444
1445               }
1446             }else if(bigendianp){
1447
1448               vorbis_fpu_setround(&fpu);
1449               for(j=0;j<samples;j++)
1450                 for(i=0;i<channels;i++){
1451                   val=vorbis_ftoi(pcm[i][j]*32768.f);
1452                   if(val>32767)val=32767;
1453                   else if(val<-32768)val=-32768;
1454                   val+=off;
1455                   *buffer++=(val>>8);
1456                   *buffer++=(val&0xff);
1457                 }
1458               vorbis_fpu_restore(fpu);
1459
1460             }else{
1461               int val;
1462               vorbis_fpu_setround(&fpu);
1463               for(j=0;j<samples;j++)
1464                 for(i=0;i<channels;i++){
1465                   val=vorbis_ftoi(pcm[i][j]*32768.f);
1466                   if(val>32767)val=32767;
1467                   else if(val<-32768)val=-32768;
1468                   val+=off;
1469                   *buffer++=(val&0xff);
1470                   *buffer++=(val>>8);
1471                 }
1472               vorbis_fpu_restore(fpu);  
1473
1474             }
1475           }
1476         }
1477         
1478         vorbis_synthesis_read(&vf->vd,samples);
1479         vf->pcm_offset+=samples;
1480         if(bitstream)*bitstream=vf->current_link;
1481         return(samples*bytespersample);
1482       }
1483     }
1484
1485     /* suck in another packet */
1486     switch(_process_packet(vf,1)){
1487     case 0:case OV_EOF:
1488       return(0);
1489     case OV_HOLE:
1490       return(OV_HOLE);
1491     case OV_EBADLINK:
1492       return(OV_EBADLINK);
1493     }
1494   }
1495 }
1496
1497
1498
1499