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