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