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