rambokid noticed that we were exporting host_is_big_endian() accidentally
[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.53 2001/12/14 00:30:33 jack 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 ret;
140   int offset=-1;
141
142   while(offset==-1){
143     begin-=CHUNKSIZE;
144     if(begin<0)
145       begin=0;
146     _seek_helper(vf,begin);
147     while(vf->offset<begin+CHUNKSIZE){
148       ret=_get_next_page(vf,og,begin+CHUNKSIZE-vf->offset);
149       if(ret==OV_EREAD)return(OV_EREAD);
150       if(ret<0){
151         break;
152       }else{
153         offset=ret;
154       }
155     }
156   }
157
158   /* we have the offset.  Actually snork and hold the page now */
159   _seek_helper(vf,offset);
160   ret=_get_next_page(vf,og,CHUNKSIZE);
161   if(ret<0)
162     /* this shouldn't be possible */
163     return(OV_EFAULT);
164
165   return(offset);
166 }
167
168 /* finds each bitstream link one at a time using a bisection search
169    (has to begin by knowing the offset of the lb's initial page).
170    Recurses for each link so it can alloc the link storage after
171    finding them all, then unroll and fill the cache at the same time */
172 static int _bisect_forward_serialno(OggVorbis_File *vf,
173                                     long begin,
174                                     long searched,
175                                     long end,
176                                     long currentno,
177                                     long m){
178   long endsearched=end;
179   long next=end;
180   ogg_page og;
181   long ret;
182   
183   /* the below guards against garbage seperating the last and
184      first pages of two links. */
185   while(searched<endsearched){
186     long bisect;
187     
188     if(endsearched-searched<CHUNKSIZE){
189       bisect=searched;
190     }else{
191       bisect=(searched+endsearched)/2;
192     }
193     
194     _seek_helper(vf,bisect);
195     ret=_get_next_page(vf,&og,-1);
196     if(ret==OV_EREAD)return(OV_EREAD);
197     if(ret<0 || ogg_page_serialno(&og)!=currentno){
198       endsearched=bisect;
199       if(ret>=0)next=ret;
200     }else{
201       searched=ret+og.header_len+og.body_len;
202     }
203   }
204
205   _seek_helper(vf,next);
206   ret=_get_next_page(vf,&og,-1);
207   if(ret==OV_EREAD)return(OV_EREAD);
208   
209   if(searched>=end || ret<0){
210     vf->links=m+1;
211     vf->offsets=_ogg_malloc((m+2)*sizeof(*vf->offsets));
212     vf->offsets[m+1]=searched;
213   }else{
214     ret=_bisect_forward_serialno(vf,next,vf->offset,
215                                  end,ogg_page_serialno(&og),m+1);
216     if(ret==OV_EREAD)return(OV_EREAD);
217   }
218   
219   vf->offsets[m]=begin;
220   return(0);
221 }
222
223 /* uses the local ogg_stream storage in vf; this is important for
224    non-streaming input sources */
225 static int _fetch_headers(OggVorbis_File *vf,vorbis_info *vi,vorbis_comment *vc,
226                           long *serialno,ogg_page *og_ptr){
227   ogg_page og;
228   ogg_packet op;
229   int i,ret=0;
230   
231   if(!og_ptr){
232     ret=_get_next_page(vf,&og,CHUNKSIZE);
233     if(ret==OV_EREAD)return(OV_EREAD);
234     if(ret<0)return OV_ENOTVORBIS;
235     og_ptr=&og;
236   }
237
238   if(serialno)*serialno=ogg_page_serialno(og_ptr);
239   ogg_stream_init(&vf->os,ogg_page_serialno(og_ptr));
240   vf->ready_state=STREAMSET;
241   
242   /* extract the initial header from the first page and verify that the
243      Ogg bitstream is in fact Vorbis data */
244   
245   vorbis_info_init(vi);
246   vorbis_comment_init(vc);
247   
248   i=0;
249   while(i<3){
250     ogg_stream_pagein(&vf->os,og_ptr);
251     while(i<3){
252       int result=ogg_stream_packetout(&vf->os,&op);
253       if(result==0)break;
254       if(result==-1){
255         ret=OV_EBADHEADER;
256         goto bail_header;
257       }
258       if((ret=vorbis_synthesis_headerin(vi,vc,&op))){
259         goto bail_header;
260       }
261       i++;
262     }
263     if(i<3)
264       if(_get_next_page(vf,og_ptr,CHUNKSIZE)<0){
265         ret=OV_EBADHEADER;
266         goto bail_header;
267       }
268   }
269   return 0; 
270
271  bail_header:
272   vorbis_info_clear(vi);
273   vorbis_comment_clear(vc);
274   ogg_stream_clear(&vf->os);
275   vf->ready_state=OPENED;
276
277   return ret;
278 }
279
280 /* last step of the OggVorbis_File initialization; get all the
281    vorbis_info structs and PCM positions.  Only called by the seekable
282    initialization (local stream storage is hacked slightly; pay
283    attention to how that's done) */
284
285 /* this is void and does not propogate errors up because we want to be
286    able to open and use damaged bitstreams as well as we can.  Just
287    watch out for missing information for links in the OggVorbis_File
288    struct */
289 static void _prefetch_all_headers(OggVorbis_File *vf, long dataoffset){
290   ogg_page og;
291   int i,ret;
292   
293   vf->vi=_ogg_realloc(vf->vi,vf->links*sizeof(*vf->vi));
294   vf->vc=_ogg_realloc(vf->vc,vf->links*sizeof(*vf->vc));
295   vf->dataoffsets=_ogg_malloc(vf->links*sizeof(*vf->dataoffsets));
296   vf->pcmlengths=_ogg_malloc(vf->links*sizeof(*vf->pcmlengths));
297   vf->serialnos=_ogg_malloc(vf->links*sizeof(*vf->serialnos));
298   
299   for(i=0;i<vf->links;i++){
300     if(i==0){
301       /* we already grabbed the initial header earlier.  Just set the offset */
302       vf->dataoffsets[i]=dataoffset;
303     }else{
304
305       /* seek to the location of the initial header */
306
307       _seek_helper(vf,vf->offsets[i]);
308       if(_fetch_headers(vf,vf->vi+i,vf->vc+i,NULL,NULL)<0){
309         vf->dataoffsets[i]=-1;
310       }else{
311         vf->dataoffsets[i]=vf->offset;
312         ogg_stream_clear(&vf->os);
313       }
314     }
315
316     /* get the serial number and PCM length of this link. To do this,
317        get the last page of the stream */
318     {
319       long end=vf->offsets[i+1];
320       _seek_helper(vf,end);
321
322       while(1){
323         ret=_get_prev_page(vf,&og);
324         if(ret<0){
325           /* this should not be possible */
326           vorbis_info_clear(vf->vi+i);
327           vorbis_comment_clear(vf->vc+i);
328           break;
329         }
330         if(ogg_page_granulepos(&og)!=-1){
331           vf->serialnos[i]=ogg_page_serialno(&og);
332           vf->pcmlengths[i]=ogg_page_granulepos(&og);
333           break;
334         }
335         vf->offset=ret;
336       }
337     }
338   }
339 }
340
341 static void _make_decode_ready(OggVorbis_File *vf){
342   if(vf->ready_state!=STREAMSET)return;
343   if(vf->seekable){
344     vorbis_synthesis_init(&vf->vd,vf->vi+vf->current_link);
345   }else{
346     vorbis_synthesis_init(&vf->vd,vf->vi);
347   }    
348   vorbis_block_init(&vf->vd,&vf->vb);
349   vf->ready_state=INITSET;
350   return;
351 }
352
353 static int _open_seekable2(OggVorbis_File *vf){
354   long serialno=vf->current_serialno,end;
355   long dataoffset=vf->offset;
356   ogg_page og;
357
358   /* we're partially open and have a first link header state in
359      storage in vf */
360   /* we can seek, so set out learning all about this file */
361   (vf->callbacks.seek_func)(vf->datasource,0,SEEK_END);
362   vf->offset=vf->end=(vf->callbacks.tell_func)(vf->datasource);
363   
364   /* We get the offset for the last page of the physical bitstream.
365      Most OggVorbis files will contain a single logical bitstream */
366   end=_get_prev_page(vf,&og);
367   if(end<0){
368     ov_clear(vf);
369     return(end);
370   }
371
372   /* more than one logical bitstream? */
373   if(ogg_page_serialno(&og)!=serialno){
374
375     /* Chained bitstream. Bisect-search each logical bitstream
376        section.  Do so based on serial number only */
377     if(_bisect_forward_serialno(vf,0,0,end+1,serialno,0)<0){
378       ov_clear(vf);
379       return(OV_EREAD);
380     }
381
382   }else{
383
384     /* Only one logical bitstream */
385     if(_bisect_forward_serialno(vf,0,end,end+1,serialno,0)){
386       ov_clear(vf);
387       return(OV_EREAD);
388     }
389
390   }
391
392   /* the initial header memory is referenced by vf after; don't free it */
393   _prefetch_all_headers(vf,dataoffset);
394   return(ov_raw_seek(vf,0));
395 }
396
397 /* clear out the current logical bitstream decoder */ 
398 static void _decode_clear(OggVorbis_File *vf){
399   ogg_stream_clear(&vf->os);
400   vorbis_dsp_clear(&vf->vd);
401   vorbis_block_clear(&vf->vb);
402   vf->ready_state=OPENED;
403
404   vf->bittrack=0.f;
405   vf->samptrack=0.f;
406 }
407
408 /* fetch and process a packet.  Handles the case where we're at a
409    bitstream boundary and dumps the decoding machine.  If the decoding
410    machine is unloaded, it loads it.  It also keeps pcm_offset up to
411    date (seek and read both use this.  seek uses a special hack with
412    readp). 
413
414    return: <0) error, OV_HOLE (lost packet) or OV_EOF
415             0) need more data (only if readp==0)
416             1) got a packet 
417 */
418
419 static int _process_packet(OggVorbis_File *vf,int readp){
420   ogg_page og;
421
422   /* handle one packet.  Try to fetch it from current stream state */
423   /* extract packets from page */
424   while(1){
425     
426     /* process a packet if we can.  If the machine isn't loaded,
427        neither is a page */
428     if(vf->ready_state==INITSET){
429       while(1) {
430         ogg_packet op;
431         int result=ogg_stream_packetout(&vf->os,&op);
432         ogg_int64_t granulepos;
433
434         if(result==-1)return(OV_HOLE); /* hole in the data. */
435         if(result>0){
436           /* got a packet.  process it */
437           granulepos=op.granulepos;
438           if(!vorbis_synthesis(&vf->vb,&op)){ /* lazy check for lazy
439                                                  header handling.  The
440                                                  header packets aren't
441                                                  audio, so if/when we
442                                                  submit them,
443                                                  vorbis_synthesis will
444                                                  reject them */
445
446             /* suck in the synthesis data and track bitrate */
447             {
448               int oldsamples=vorbis_synthesis_pcmout(&vf->vd,NULL);
449               vorbis_synthesis_blockin(&vf->vd,&vf->vb);
450               vf->samptrack+=vorbis_synthesis_pcmout(&vf->vd,NULL)-oldsamples;
451               vf->bittrack+=op.bytes*8;
452             }
453           
454             /* update the pcm offset. */
455             if(granulepos!=-1 && !op.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.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           while(1){
1088             ret=_get_prev_page(vf,&og);
1089             if(ret<0)goto seek_error;
1090             if(ogg_page_granulepos(&og)>-1 ||
1091                !ogg_page_continued(&og)){
1092               return ov_raw_seek(vf,ret);
1093             }
1094             vf->offset=ret;
1095           }
1096         }
1097         if(ret<0)goto seek_error;
1098         if(op.granulepos!=-1){
1099           vf->pcm_offset=op.granulepos+total;
1100           break;
1101         }else
1102           ret=ogg_stream_packetout(&vf->os,NULL);
1103       }
1104     }
1105   }
1106   
1107   /* verify result */
1108   if(vf->pcm_offset>pos || pos>ov_pcm_total(vf,-1)){
1109     ret=OV_EFAULT;
1110     goto seek_error;
1111   }
1112   return(0);
1113   
1114  seek_error:
1115   /* dump machine so we're in a known state */
1116   vf->pcm_offset=-1;
1117   _decode_clear(vf);
1118   return ret;
1119 }
1120
1121 /* seek to a sample offset relative to the decompressed pcm stream 
1122    returns zero on success, nonzero on failure */
1123
1124 int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos){
1125   int thisblock,lastblock=0;
1126   int ret=ov_pcm_seek_page(vf,pos);
1127   if(ret<0)return(ret);
1128
1129   /* discard leading packets we don't need for the lapping of the
1130      position we want; don't decode them */
1131
1132   while(1){
1133     ogg_packet op;
1134     ogg_page og;
1135
1136     int ret=ogg_stream_packetpeek(&vf->os,&op);
1137     if(ret>0){
1138       thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op);
1139       if(lastblock)vf->pcm_offset+=(lastblock+thisblock)>>2;
1140
1141       if(vf->pcm_offset+((thisblock+
1142                           vorbis_info_blocksize(vf->vi,1))>>2)>=pos)break;
1143
1144       ogg_stream_packetout(&vf->os,NULL);
1145       
1146
1147       /* end of logical stream case is hard, especially with exact
1148          length positioning. */
1149
1150       if(op.granulepos>-1){
1151         int i;
1152         /* always believe the stream markers */
1153         vf->pcm_offset=op.granulepos;
1154         for(i=0;i<vf->current_link;i++)
1155           vf->pcm_offset+=vf->pcmlengths[i];
1156       }
1157
1158       lastblock=thisblock;
1159
1160     }else{
1161       if(ret<0 && ret!=OV_HOLE)break;
1162       
1163       /* suck in a new page */
1164       if(_get_next_page(vf,&og,-1)<0)break;
1165       if(vf->current_serialno!=ogg_page_serialno(&og))_decode_clear(vf);
1166       
1167       if(vf->ready_state<STREAMSET){
1168         int link;
1169         
1170         vf->current_serialno=ogg_page_serialno(&og);
1171         for(link=0;link<vf->links;link++)
1172           if(vf->serialnos[link]==vf->current_serialno)break;
1173         if(link==vf->links)return(OV_EBADLINK);
1174         vf->current_link=link;
1175         
1176         ogg_stream_init(&vf->os,vf->current_serialno);
1177         ogg_stream_reset(&vf->os); 
1178         vf->ready_state=STREAMSET;      
1179         lastblock=0;
1180       }
1181       ogg_stream_pagein(&vf->os,&og);
1182     }
1183   }
1184
1185   /* discard samples until we reach the desired position. Crossing a
1186      logical bitstream boundary with abandon is OK. */
1187   _make_decode_ready(vf);
1188   while(vf->pcm_offset<pos){
1189     float **pcm;
1190     long target=pos-vf->pcm_offset;
1191     long samples=vorbis_synthesis_pcmout(&vf->vd,&pcm);
1192
1193     if(samples>target)samples=target;
1194     vorbis_synthesis_read(&vf->vd,samples);
1195     vf->pcm_offset+=samples;
1196     
1197     if(samples<target)
1198       if(_process_packet(vf,1)<=0)
1199         vf->pcm_offset=ov_pcm_total(vf,-1); /* eof */
1200   }
1201   return 0;
1202 }
1203
1204 /* seek to a playback time relative to the decompressed pcm stream 
1205    returns zero on success, nonzero on failure */
1206 int ov_time_seek(OggVorbis_File *vf,double seconds){
1207   /* translate time to PCM position and call ov_pcm_seek */
1208
1209   int link=-1;
1210   ogg_int64_t pcm_total=ov_pcm_total(vf,-1);
1211   double time_total=ov_time_total(vf,-1);
1212
1213   if(vf->ready_state<OPENED)return(OV_EINVAL);
1214   if(!vf->seekable)return(OV_ENOSEEK);
1215   if(seconds<0 || seconds>time_total)return(OV_EINVAL);
1216   
1217   /* which bitstream section does this time offset occur in? */
1218   for(link=vf->links-1;link>=0;link--){
1219     pcm_total-=vf->pcmlengths[link];
1220     time_total-=ov_time_total(vf,link);
1221     if(seconds>=time_total)break;
1222   }
1223
1224   /* enough information to convert time offset to pcm offset */
1225   {
1226     ogg_int64_t target=pcm_total+(seconds-time_total)*vf->vi[link].rate;
1227     return(ov_pcm_seek(vf,target));
1228   }
1229 }
1230
1231 /* page-granularity version of ov_time_seek 
1232    returns zero on success, nonzero on failure */
1233 int ov_time_seek_page(OggVorbis_File *vf,double seconds){
1234   /* translate time to PCM position and call ov_pcm_seek */
1235
1236   int link=-1;
1237   ogg_int64_t pcm_total=ov_pcm_total(vf,-1);
1238   double time_total=ov_time_total(vf,-1);
1239
1240   if(vf->ready_state<OPENED)return(OV_EINVAL);
1241   if(!vf->seekable)return(OV_ENOSEEK);
1242   if(seconds<0 || seconds>time_total)return(OV_EINVAL);
1243   
1244   /* which bitstream section does this time offset occur in? */
1245   for(link=vf->links-1;link>=0;link--){
1246     pcm_total-=vf->pcmlengths[link];
1247     time_total-=ov_time_total(vf,link);
1248     if(seconds>=time_total)break;
1249   }
1250
1251   /* enough information to convert time offset to pcm offset */
1252   {
1253     ogg_int64_t target=pcm_total+(seconds-time_total)*vf->vi[link].rate;
1254     return(ov_pcm_seek_page(vf,target));
1255   }
1256 }
1257
1258 /* tell the current stream offset cursor.  Note that seek followed by
1259    tell will likely not give the set offset due to caching */
1260 ogg_int64_t ov_raw_tell(OggVorbis_File *vf){
1261   if(vf->ready_state<OPENED)return(OV_EINVAL);
1262   return(vf->offset);
1263 }
1264
1265 /* return PCM offset (sample) of next PCM sample to be read */
1266 ogg_int64_t ov_pcm_tell(OggVorbis_File *vf){
1267   if(vf->ready_state<OPENED)return(OV_EINVAL);
1268   return(vf->pcm_offset);
1269 }
1270
1271 /* return time offset (seconds) of next PCM sample to be read */
1272 double ov_time_tell(OggVorbis_File *vf){
1273   /* translate time to PCM position and call ov_pcm_seek */
1274
1275   int link=-1;
1276   ogg_int64_t pcm_total=0;
1277   double time_total=0.f;
1278   
1279   if(vf->ready_state<OPENED)return(OV_EINVAL);
1280   if(vf->seekable){
1281     pcm_total=ov_pcm_total(vf,-1);
1282     time_total=ov_time_total(vf,-1);
1283   
1284     /* which bitstream section does this time offset occur in? */
1285     for(link=vf->links-1;link>=0;link--){
1286       pcm_total-=vf->pcmlengths[link];
1287       time_total-=ov_time_total(vf,link);
1288       if(vf->pcm_offset>=pcm_total)break;
1289     }
1290   }
1291
1292   return((double)time_total+(double)(vf->pcm_offset-pcm_total)/vf->vi[link].rate);
1293 }
1294
1295 /*  link:   -1) return the vorbis_info struct for the bitstream section
1296                 currently being decoded
1297            0-n) to request information for a specific bitstream section
1298     
1299     In the case of a non-seekable bitstream, any call returns the
1300     current bitstream.  NULL in the case that the machine is not
1301     initialized */
1302
1303 vorbis_info *ov_info(OggVorbis_File *vf,int link){
1304   if(vf->seekable){
1305     if(link<0)
1306       if(vf->ready_state>=STREAMSET)
1307         return vf->vi+vf->current_link;
1308       else
1309       return vf->vi;
1310     else
1311       if(link>=vf->links)
1312         return NULL;
1313       else
1314         return vf->vi+link;
1315   }else{
1316     return vf->vi;
1317   }
1318 }
1319
1320 /* grr, strong typing, grr, no templates/inheritence, grr */
1321 vorbis_comment *ov_comment(OggVorbis_File *vf,int link){
1322   if(vf->seekable){
1323     if(link<0)
1324       if(vf->ready_state>=STREAMSET)
1325         return vf->vc+vf->current_link;
1326       else
1327         return vf->vc;
1328     else
1329       if(link>=vf->links)
1330         return NULL;
1331       else
1332         return vf->vc+link;
1333   }else{
1334     return vf->vc;
1335   }
1336 }
1337
1338 static int host_is_big_endian() {
1339   ogg_int32_t pattern = 0xfeedface; /* deadbeef */
1340   unsigned char *bytewise = (unsigned char *)&pattern;
1341   if (bytewise[0] == 0xfe) return 1;
1342   return 0;
1343 }
1344
1345 /* up to this point, everything could more or less hide the multiple
1346    logical bitstream nature of chaining from the toplevel application
1347    if the toplevel application didn't particularly care.  However, at
1348    the point that we actually read audio back, the multiple-section
1349    nature must surface: Multiple bitstream sections do not necessarily
1350    have to have the same number of channels or sampling rate.
1351
1352    ov_read returns the sequential logical bitstream number currently
1353    being decoded along with the PCM data in order that the toplevel
1354    application can take action on channel/sample rate changes.  This
1355    number will be incremented even for streamed (non-seekable) streams
1356    (for seekable streams, it represents the actual logical bitstream
1357    index within the physical bitstream.  Note that the accessor
1358    functions above are aware of this dichotomy).
1359
1360    input values: buffer) a buffer to hold packed PCM data for return
1361                  length) the byte length requested to be placed into buffer
1362                  bigendianp) should the data be packed LSB first (0) or
1363                              MSB first (1)
1364                  word) word size for output.  currently 1 (byte) or 
1365                        2 (16 bit short)
1366
1367    return values: <0) error/hole in data (OV_HOLE), partial open (OV_EINVAL)
1368                    0) EOF
1369                    n) number of bytes of PCM actually returned.  The
1370                    below works on a packet-by-packet basis, so the
1371                    return length is not related to the 'length' passed
1372                    in, just guaranteed to fit.
1373
1374             *section) set to the logical bitstream number */
1375
1376 long ov_read_float(OggVorbis_File *vf,float ***pcm_channels,int *bitstream){
1377
1378   if(vf->ready_state<OPENED)return(OV_EINVAL);
1379
1380   while(1){
1381     if(vf->ready_state>=STREAMSET){
1382       float **pcm;
1383       long samples=vorbis_synthesis_pcmout(&vf->vd,&pcm);
1384       if(samples){
1385         if(pcm_channels)*pcm_channels=pcm;
1386         vorbis_synthesis_read(&vf->vd,samples);
1387         vf->pcm_offset+=samples;
1388         if(bitstream)*bitstream=vf->current_link;
1389         return samples;
1390
1391       }
1392     }
1393
1394     /* suck in another packet */
1395     {
1396       int ret=_process_packet(vf,1);
1397       if(ret==OV_EOF)return(0);
1398       if(ret<=0)return(ret);
1399     }
1400
1401   }
1402 }
1403
1404 long ov_read(OggVorbis_File *vf,char *buffer,int length,
1405                     int bigendianp,int word,int sgned,int *bitstream){
1406   int i,j;
1407   int host_endian = host_is_big_endian();
1408
1409   float **pcm;
1410   long samples=ov_read_float(vf,&pcm,bitstream);
1411   if(samples>0){
1412   
1413     /* yay! proceed to pack data into the byte buffer */
1414     
1415     long channels=ov_info(vf,-1)->channels;
1416     long bytespersample=word * channels;
1417     vorbis_fpu_control fpu;
1418     if(samples>length/bytespersample)samples=length/bytespersample;
1419     
1420     /* a tight loop to pack each size */
1421     {
1422       int val;
1423       if(word==1){
1424         int off=(sgned?0:128);
1425         vorbis_fpu_setround(&fpu);
1426         for(j=0;j<samples;j++)
1427           for(i=0;i<channels;i++){
1428             val=vorbis_ftoi(pcm[i][j]*128.f);
1429             if(val>127)val=127;
1430             else if(val<-128)val=-128;
1431             *buffer++=val+off;
1432           }
1433         vorbis_fpu_restore(fpu);
1434       }else{
1435         int off=(sgned?0:32768);
1436         
1437         if(host_endian==bigendianp){
1438           if(sgned){
1439             
1440             vorbis_fpu_setround(&fpu);
1441             for(i=0;i<channels;i++) { /* It's faster in this order */
1442               float *src=pcm[i];
1443               short *dest=((short *)buffer)+i;
1444               for(j=0;j<samples;j++) {
1445                 val=vorbis_ftoi(src[j]*32768.f);
1446                 if(val>32767)val=32767;
1447                 else if(val<-32768)val=-32768;
1448                 *dest=val;
1449                 dest+=channels;
1450               }
1451             }
1452             vorbis_fpu_restore(fpu);
1453             
1454           }else{
1455             
1456             vorbis_fpu_setround(&fpu);
1457             for(i=0;i<channels;i++) {
1458               float *src=pcm[i];
1459               short *dest=((short *)buffer)+i;
1460               for(j=0;j<samples;j++) {
1461                 val=vorbis_ftoi(src[j]*32768.f);
1462                 if(val>32767)val=32767;
1463                 else if(val<-32768)val=-32768;
1464                 *dest=val+off;
1465                 dest+=channels;
1466               }
1467             }
1468             vorbis_fpu_restore(fpu);
1469             
1470           }
1471         }else if(bigendianp){
1472           
1473           vorbis_fpu_setround(&fpu);
1474           for(j=0;j<samples;j++)
1475             for(i=0;i<channels;i++){
1476               val=vorbis_ftoi(pcm[i][j]*32768.f);
1477               if(val>32767)val=32767;
1478               else if(val<-32768)val=-32768;
1479               val+=off;
1480               *buffer++=(val>>8);
1481               *buffer++=(val&0xff);
1482             }
1483           vorbis_fpu_restore(fpu);
1484           
1485         }else{
1486           int val;
1487           vorbis_fpu_setround(&fpu);
1488           for(j=0;j<samples;j++)
1489             for(i=0;i<channels;i++){
1490               val=vorbis_ftoi(pcm[i][j]*32768.f);
1491               if(val>32767)val=32767;
1492               else if(val<-32768)val=-32768;
1493               val+=off;
1494               *buffer++=(val&0xff);
1495               *buffer++=(val>>8);
1496                 }
1497           vorbis_fpu_restore(fpu);  
1498           
1499         }
1500       }
1501     }
1502     
1503     vorbis_synthesis_read(&vf->vd,samples);
1504     vf->pcm_offset+=samples;
1505     if(bitstream)*bitstream=vf->current_link;
1506     return(samples*bytespersample);
1507   }else{
1508     return(samples);
1509   }
1510 }
1511
1512
1513
1514