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