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