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