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