Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/libvorbis-1.2.0/lib/vorbisfile.c @ 29

Last change on this file since 29 was 16, checked in by landauf, 17 years ago

added libvorbis

File size: 61.0 KB
Line 
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-2007             *
9 * by the Xiph.Org Foundation http://www.xiph.org/                  *
10 *                                                                  *
11 ********************************************************************
12
13 function: stdio-based convenience library for opening/seeking/decoding
14 last mod: $Id: vorbisfile.c 13294 2007-07-24 01:08:23Z xiphmont $
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 65536
62
63static long _get_data(OggVorbis_File *vf){
64  errno=0;
65  if(!(vf->callbacks.read_func))return(-1);
66  if(vf->datasource){
67    char *buffer=ogg_sync_buffer(&vf->oy,CHUNKSIZE);
68    long bytes=(vf->callbacks.read_func)(buffer,1,CHUNKSIZE,vf->datasource);
69    if(bytes>0)ogg_sync_wrote(&vf->oy,bytes);
70    if(bytes==0 && errno)return(-1);
71    return(bytes);
72  }else
73    return(0);
74}
75
76/* save a tiny smidge of verbosity to make the code more readable */
77static int _seek_helper(OggVorbis_File *vf,ogg_int64_t offset){
78  if(vf->datasource){ 
79    if(!(vf->callbacks.seek_func)||
80       (vf->callbacks.seek_func)(vf->datasource, offset, SEEK_SET) == -1)
81      return OV_EREAD;
82    vf->offset=offset;
83    ogg_sync_reset(&vf->oy);
84  }else{
85    /* shouldn't happen unless someone writes a broken callback */
86    return OV_EFAULT;
87  }
88  return 0;
89}
90
91/* The read/seek functions track absolute position within the stream */
92
93/* from the head of the stream, get the next page.  boundary specifies
94   if the function is allowed to fetch more data from the stream (and
95   how much) or only use internally buffered data.
96
97   boundary: -1) unbounded search
98              0) read no additional data; use cached only
99              n) search for a new page beginning for n bytes
100
101   return:   <0) did not find a page (OV_FALSE, OV_EOF, OV_EREAD)
102              n) found a page at absolute offset n */
103
104static ogg_int64_t _get_next_page(OggVorbis_File *vf,ogg_page *og,
105                                  ogg_int64_t boundary){
106  if(boundary>0)boundary+=vf->offset;
107  while(1){
108    long more;
109
110    if(boundary>0 && vf->offset>=boundary)return(OV_FALSE);
111    more=ogg_sync_pageseek(&vf->oy,og);
112   
113    if(more<0){
114      /* skipped n bytes */
115      vf->offset-=more;
116    }else{
117      if(more==0){
118        /* send more paramedics */
119        if(!boundary)return(OV_FALSE);
120        {
121          long ret=_get_data(vf);
122          if(ret==0)return(OV_EOF);
123          if(ret<0)return(OV_EREAD);
124        }
125      }else{
126        /* got a page.  Return the offset at the page beginning,
127           advance the internal offset past the page end */
128        ogg_int64_t ret=vf->offset;
129        vf->offset+=more;
130        return(ret);
131       
132      }
133    }
134  }
135}
136
137/* find the latest page beginning before the current stream cursor
138   position. Much dirtier than the above as Ogg doesn't have any
139   backward search linkage.  no 'readp' as it will certainly have to
140   read. */
141/* returns offset or OV_EREAD, OV_FAULT */
142static ogg_int64_t _get_prev_page(OggVorbis_File *vf,ogg_page *og){
143  ogg_int64_t begin=vf->offset;
144  ogg_int64_t end=begin;
145  ogg_int64_t ret;
146  ogg_int64_t offset=-1;
147
148  while(offset==-1){
149    begin-=CHUNKSIZE;
150    if(begin<0)
151      begin=0;
152
153    ret=_seek_helper(vf,begin);
154    if(ret)return(ret);
155
156    while(vf->offset<end){
157      ret=_get_next_page(vf,og,end-vf->offset);
158      if(ret==OV_EREAD)return(OV_EREAD);
159      if(ret<0){
160        break;
161      }else{
162        offset=ret;
163      }
164    }
165  }
166
167  /* we have the offset.  Actually snork and hold the page now */
168  ret=_seek_helper(vf,offset);
169  if(ret)return(ret);
170
171  ret=_get_next_page(vf,og,CHUNKSIZE);
172  if(ret<0)
173    /* this shouldn't be possible */
174    return(OV_EFAULT);
175
176  return(offset);
177}
178
179static void _add_serialno(ogg_page *og,long **serialno_list, int *n){
180  long s = ogg_page_serialno(og);
181  (*n)++;
182
183  if(serialno_list){
184    *serialno_list = _ogg_realloc(*serialno_list, sizeof(*serialno_list)*(*n));
185  }else{
186    *serialno_list = _ogg_malloc(sizeof(**serialno_list));
187  }
188 
189  (*serialno_list)[(*n)-1] = s;
190}
191
192/* returns nonzero if found */
193static int _lookup_serialno(ogg_page *og, long *serialno_list, int n){
194  long s = ogg_page_serialno(og);
195
196  if(serialno_list){
197    while(n--){
198      if(*serialno_list == s) return 1;
199      serialno_list++;
200    }
201  }
202  return 0;
203}
204
205/* start parsing pages at current offset, remembering all serial
206   numbers.  Stop logging at first non-bos page */
207static int _get_serialnos(OggVorbis_File *vf, long **s, int *n){
208  ogg_page og;
209
210  *s=NULL;
211  *n=0;
212
213  while(1){
214    ogg_int64_t llret=_get_next_page(vf,&og,CHUNKSIZE);
215    if(llret==OV_EOF)return(0);
216    if(llret<0)return(llret);
217    if(!ogg_page_bos(&og)) return 0;
218
219    /* look for duplicate serialnos; add this one if unique */
220    if(_lookup_serialno(&og,*s,*n)){
221      if(*s)_ogg_free(*s);
222      *s=0;
223      *n=0;
224      return(OV_EBADHEADER);
225    }
226
227    _add_serialno(&og,s,n);
228  }
229}
230
231/* finds each bitstream link one at a time using a bisection search
232   (has to begin by knowing the offset of the lb's initial page).
233   Recurses for each link so it can alloc the link storage after
234   finding them all, then unroll and fill the cache at the same time */
235static int _bisect_forward_serialno(OggVorbis_File *vf,
236                                    ogg_int64_t begin,
237                                    ogg_int64_t searched,
238                                    ogg_int64_t end,
239                                    long *currentno_list,
240                                    int  currentnos,
241                                    long m){
242  ogg_int64_t endsearched=end;
243  ogg_int64_t next=end;
244  ogg_page og;
245  ogg_int64_t ret;
246 
247  /* the below guards against garbage seperating the last and
248     first pages of two links. */
249  while(searched<endsearched){
250    ogg_int64_t bisect;
251   
252    if(endsearched-searched<CHUNKSIZE){
253      bisect=searched;
254    }else{
255      bisect=(searched+endsearched)/2;
256    }
257   
258    ret=_seek_helper(vf,bisect);
259    if(ret)return(ret);
260
261    ret=_get_next_page(vf,&og,-1);
262    if(ret==OV_EREAD)return(OV_EREAD);
263    if(ret<0 || !_lookup_serialno(&og,currentno_list,currentnos)){
264      endsearched=bisect;
265      if(ret>=0)next=ret;
266    }else{
267      searched=ret+og.header_len+og.body_len;
268    }
269  }
270
271  {
272    long *next_serialno_list=NULL;
273    int next_serialnos=0;
274
275    ret=_seek_helper(vf,next);
276    if(ret)return(ret);
277    ret=_get_serialnos(vf,&next_serialno_list,&next_serialnos);
278    if(ret)return(ret);
279   
280    if(searched>=end || next_serialnos==0){
281      vf->links=m+1;
282      vf->offsets=_ogg_malloc((vf->links+1)*sizeof(*vf->offsets));
283      vf->offsets[m+1]=searched;
284    }else{
285      ret=_bisect_forward_serialno(vf,next,vf->offset,
286                                   end,next_serialno_list,next_serialnos,m+1);
287      if(ret)return(ret);
288    }
289   
290    if(next_serialno_list)_ogg_free(next_serialno_list);
291  }
292  vf->offsets[m]=begin;
293  return(0);
294}
295
296/* uses the local ogg_stream storage in vf; this is important for
297   non-streaming input sources */
298static int _fetch_headers(OggVorbis_File *vf,vorbis_info *vi,vorbis_comment *vc,
299                          long *serialno,ogg_page *og_ptr){
300  ogg_page og;
301  ogg_packet op;
302  int i,ret;
303  int allbos=0;
304
305  if(!og_ptr){
306    ogg_int64_t llret=_get_next_page(vf,&og,CHUNKSIZE);
307    if(llret==OV_EREAD)return(OV_EREAD);
308    if(llret<0)return(OV_ENOTVORBIS);
309    og_ptr=&og;
310  }
311
312  vorbis_info_init(vi);
313  vorbis_comment_init(vc);
314
315  /* extract the first set of vorbis headers we see in the headerset */
316
317  while(1){
318 
319    /* if we're past the ID headers, we won't be finding a Vorbis
320       stream in this link */
321    if(!ogg_page_bos(og_ptr)){
322      ret = OV_ENOTVORBIS;
323      goto bail_header;
324    }
325
326    /* prospective stream setup; we need a stream to get packets */
327    ogg_stream_reset_serialno(&vf->os,ogg_page_serialno(og_ptr));
328    ogg_stream_pagein(&vf->os,og_ptr);
329
330    if(ogg_stream_packetout(&vf->os,&op) > 0 &&
331       vorbis_synthesis_idheader(&op)){
332
333      /* continue Vorbis header load; past this point, any error will
334         render this link useless (we won't continue looking for more
335         Vorbis streams */
336      if(serialno)*serialno=vf->os.serialno;
337      vf->ready_state=STREAMSET;
338      if((ret=vorbis_synthesis_headerin(vi,vc,&op)))
339        goto bail_header;
340
341      i=0;
342      while(i<2){ /* get a page loop */
343       
344        while(i<2){ /* get a packet loop */
345
346          int result=ogg_stream_packetout(&vf->os,&op);
347          if(result==0)break;
348          if(result==-1){
349            ret=OV_EBADHEADER;
350            goto bail_header;
351          }
352       
353          if((ret=vorbis_synthesis_headerin(vi,vc,&op)))
354            goto bail_header;
355
356          i++;
357        }
358
359        while(i<2){
360          if(_get_next_page(vf,og_ptr,CHUNKSIZE)<0){
361            ret=OV_EBADHEADER;
362            goto bail_header;
363          }
364
365          /* if this page belongs to the correct stream, go parse it */
366          if(vf->os.serialno == ogg_page_serialno(og_ptr)){
367            ogg_stream_pagein(&vf->os,og_ptr);
368            break;
369          }
370
371          /* if we never see the final vorbis headers before the link
372             ends, abort */
373          if(ogg_page_bos(og_ptr)){
374            if(allbos){
375              ret = OV_EBADHEADER;
376              goto bail_header;
377            }else
378              allbos=1;
379          }
380
381          /* otherwise, keep looking */
382        }
383      }
384
385      return 0; 
386    }
387
388    /* this wasn't vorbis, get next page, try again */
389    {
390      ogg_int64_t llret=_get_next_page(vf,og_ptr,CHUNKSIZE);
391      if(llret==OV_EREAD)return(OV_EREAD);
392      if(llret<0)return(OV_ENOTVORBIS);
393    } 
394  }
395
396 bail_header:
397  vorbis_info_clear(vi);
398  vorbis_comment_clear(vc);
399  vf->ready_state=OPENED;
400
401  return ret;
402}
403
404/* last step of the OggVorbis_File initialization; get all the
405   vorbis_info structs and PCM positions.  Only called by the seekable
406   initialization (local stream storage is hacked slightly; pay
407   attention to how that's done) */
408
409/* this is void and does not propogate errors up because we want to be
410   able to open and use damaged bitstreams as well as we can.  Just
411   watch out for missing information for links in the OggVorbis_File
412   struct */
413static void _prefetch_all_headers(OggVorbis_File *vf, ogg_int64_t dataoffset){
414  ogg_page og;
415  int i;
416  ogg_int64_t ret;
417
418  vf->vi=_ogg_realloc(vf->vi,vf->links*sizeof(*vf->vi));
419  vf->vc=_ogg_realloc(vf->vc,vf->links*sizeof(*vf->vc));
420  vf->serialnos=_ogg_malloc(vf->links*sizeof(*vf->serialnos));
421  vf->dataoffsets=_ogg_malloc(vf->links*sizeof(*vf->dataoffsets));
422  vf->pcmlengths=_ogg_malloc(vf->links*2*sizeof(*vf->pcmlengths));
423 
424  for(i=0;i<vf->links;i++){
425    if(i==0){
426      /* we already grabbed the initial header earlier.  Just set the offset */
427      vf->serialnos[i]=vf->current_serialno;
428      vf->dataoffsets[i]=dataoffset;
429      ret=_seek_helper(vf,dataoffset);
430      if(ret)
431        vf->dataoffsets[i]=-1;
432
433    }else{
434
435      /* seek to the location of the initial header */
436
437      ret=_seek_helper(vf,vf->offsets[i]);
438      if(ret){
439        vf->dataoffsets[i]=-1;
440      }else{
441        if(_fetch_headers(vf,vf->vi+i,vf->vc+i,vf->serialnos+i,NULL)<0){
442          vf->dataoffsets[i]=-1;
443        }else{
444          vf->dataoffsets[i]=vf->offset;
445        }
446      }
447    }
448
449    /* fetch beginning PCM offset */
450
451    if(vf->dataoffsets[i]!=-1){
452      ogg_int64_t accumulated=0;
453      long        lastblock=-1;
454      int         result;
455
456      ogg_stream_reset_serialno(&vf->os,vf->serialnos[i]);
457
458      while(1){
459        ogg_packet op;
460
461        ret=_get_next_page(vf,&og,-1);
462        if(ret<0)
463          /* this should not be possible unless the file is
464             truncated/mangled */
465          break;
466       
467        if(ogg_page_bos(&og)) break;
468
469        if(ogg_page_serialno(&og)!=vf->serialnos[i])
470          continue;
471       
472        /* count blocksizes of all frames in the page */
473        ogg_stream_pagein(&vf->os,&og);
474        while((result=ogg_stream_packetout(&vf->os,&op))){
475          if(result>0){ /* ignore holes */
476            long thisblock=vorbis_packet_blocksize(vf->vi+i,&op);
477            if(lastblock!=-1)
478              accumulated+=(lastblock+thisblock)>>2;
479            lastblock=thisblock;
480          }
481        }
482
483        if(ogg_page_granulepos(&og)!=-1){
484          /* pcm offset of last packet on the first audio page */
485          accumulated= ogg_page_granulepos(&og)-accumulated;
486          break;
487        }
488      }
489
490      /* less than zero?  This is a stream with samples trimmed off
491         the beginning, a normal occurrence; set the offset to zero */
492      if(accumulated<0)accumulated=0;
493
494      vf->pcmlengths[i*2]=accumulated;
495    }
496
497    /* get the PCM length of this link. To do this,
498       get the last page of the stream */
499    {
500      ogg_int64_t end=vf->offsets[i+1];
501      ret=_seek_helper(vf,end);
502      if(ret){
503        /* this should not be possible */
504        vorbis_info_clear(vf->vi+i);
505        vorbis_comment_clear(vf->vc+i);
506      }else{
507       
508        while(1){
509          ret=_get_prev_page(vf,&og);
510          if(ret<0){
511            /* this should not be possible */
512            vorbis_info_clear(vf->vi+i);
513            vorbis_comment_clear(vf->vc+i);
514            break;
515          }
516          if(ogg_page_serialno(&og)==vf->serialnos[i]){
517            if(ogg_page_granulepos(&og)!=-1){
518              vf->pcmlengths[i*2+1]=ogg_page_granulepos(&og)-vf->pcmlengths[i*2];
519              break;
520            }
521          }
522          vf->offset=ret;
523        }
524      }
525    }
526  }
527}
528
529static int _make_decode_ready(OggVorbis_File *vf){
530  if(vf->ready_state>STREAMSET)return 0;
531  if(vf->ready_state<STREAMSET)return OV_EFAULT;
532  if(vf->seekable){
533    if(vorbis_synthesis_init(&vf->vd,vf->vi+vf->current_link))
534      return OV_EBADLINK;
535  }else{
536    if(vorbis_synthesis_init(&vf->vd,vf->vi))
537      return OV_EBADLINK;
538  }   
539  vorbis_block_init(&vf->vd,&vf->vb);
540  vf->ready_state=INITSET;
541  vf->bittrack=0.f;
542  vf->samptrack=0.f;
543  return 0;
544}
545
546static int _open_seekable2(OggVorbis_File *vf){
547  ogg_int64_t dataoffset=vf->offset,end;
548  long *serialno_list=NULL;
549  int serialnos=0;
550  int ret;
551  ogg_page og;
552
553  /* we're partially open and have a first link header state in
554     storage in vf */
555  /* we can seek, so set out learning all about this file */
556  if(vf->callbacks.seek_func && vf->callbacks.tell_func){
557    (vf->callbacks.seek_func)(vf->datasource,0,SEEK_END);
558    vf->offset=vf->end=(vf->callbacks.tell_func)(vf->datasource);
559  }else{
560    vf->offset=vf->end=-1;
561  }
562
563  /* If seek_func is implemented, tell_func must also be implemented */
564  if(vf->end==-1) return(OV_EINVAL);
565
566  /* We get the offset for the last page of the physical bitstream.
567     Most OggVorbis files will contain a single logical bitstream */
568  end=_get_prev_page(vf,&og);
569  if(end<0)return(end);
570
571  /* back to beginning, learn all serialnos of first link */
572  ret=_seek_helper(vf,0);
573  if(ret)return(ret);
574  ret=_get_serialnos(vf,&serialno_list,&serialnos);
575  if(ret)return(ret);
576
577  /* now determine bitstream structure recursively */
578  if(_bisect_forward_serialno(vf,0,0,end+1,serialno_list,serialnos,0)<0)return(OV_EREAD); 
579  if(serialno_list)_ogg_free(serialno_list);
580
581  /* the initial header memory is referenced by vf after; don't free it */
582  _prefetch_all_headers(vf,dataoffset);
583  return(ov_raw_seek(vf,0));
584}
585
586/* clear out the current logical bitstream decoder */ 
587static void _decode_clear(OggVorbis_File *vf){
588  vorbis_dsp_clear(&vf->vd);
589  vorbis_block_clear(&vf->vb);
590  vf->ready_state=OPENED;
591}
592
593/* fetch and process a packet.  Handles the case where we're at a
594   bitstream boundary and dumps the decoding machine.  If the decoding
595   machine is unloaded, it loads it.  It also keeps pcm_offset up to
596   date (seek and read both use this.  seek uses a special hack with
597   readp).
598
599   return: <0) error, OV_HOLE (lost packet) or OV_EOF
600            0) need more data (only if readp==0)
601            1) got a packet
602*/
603
604static int _fetch_and_process_packet(OggVorbis_File *vf,
605                                     ogg_packet *op_in,
606                                     int readp,
607                                     int spanp){
608  ogg_page og;
609
610  /* handle one packet.  Try to fetch it from current stream state */
611  /* extract packets from page */
612  while(1){
613   
614    /* process a packet if we can.  If the machine isn't loaded,
615       neither is a page */
616    if(vf->ready_state==INITSET){
617      while(1) {
618        ogg_packet op;
619        ogg_packet *op_ptr=(op_in?op_in:&op);
620        int result=ogg_stream_packetout(&vf->os,op_ptr);
621        ogg_int64_t granulepos;
622
623        op_in=NULL;
624        if(result==-1)return(OV_HOLE); /* hole in the data. */
625        if(result>0){
626          /* got a packet.  process it */
627          granulepos=op_ptr->granulepos;
628          if(!vorbis_synthesis(&vf->vb,op_ptr)){ /* lazy check for lazy
629                                                    header handling.  The
630                                                    header packets aren't
631                                                    audio, so if/when we
632                                                    submit them,
633                                                    vorbis_synthesis will
634                                                    reject them */
635
636            /* suck in the synthesis data and track bitrate */
637            {
638              int oldsamples=vorbis_synthesis_pcmout(&vf->vd,NULL);
639              /* for proper use of libvorbis within libvorbisfile,
640                 oldsamples will always be zero. */
641              if(oldsamples)return(OV_EFAULT);
642             
643              vorbis_synthesis_blockin(&vf->vd,&vf->vb);
644              vf->samptrack+=vorbis_synthesis_pcmout(&vf->vd,NULL)-oldsamples;
645              vf->bittrack+=op_ptr->bytes*8;
646            }
647         
648            /* update the pcm offset. */
649            if(granulepos!=-1 && !op_ptr->e_o_s){
650              int link=(vf->seekable?vf->current_link:0);
651              int i,samples;
652           
653              /* this packet has a pcm_offset on it (the last packet
654                 completed on a page carries the offset) After processing
655                 (above), we know the pcm position of the *last* sample
656                 ready to be returned. Find the offset of the *first*
657
658                 As an aside, this trick is inaccurate if we begin
659                 reading anew right at the last page; the end-of-stream
660                 granulepos declares the last frame in the stream, and the
661                 last packet of the last page may be a partial frame.
662                 So, we need a previous granulepos from an in-sequence page
663                 to have a reference point.  Thus the !op_ptr->e_o_s clause
664                 above */
665
666              if(vf->seekable && link>0)
667                granulepos-=vf->pcmlengths[link*2];
668              if(granulepos<0)granulepos=0; /* actually, this
669                                               shouldn't be possible
670                                               here unless the stream
671                                               is very broken */
672
673              samples=vorbis_synthesis_pcmout(&vf->vd,NULL);
674           
675              granulepos-=samples;
676              for(i=0;i<link;i++)
677                granulepos+=vf->pcmlengths[i*2+1];
678              vf->pcm_offset=granulepos;
679            }
680            return(1);
681          }
682        }
683        else 
684          break;
685      }
686    }
687
688    if(vf->ready_state>=OPENED){
689      ogg_int64_t ret;
690     
691      while(1){ 
692        /* the loop is not strictly necessary, but there's no sense in
693           doing the extra checks of the larger loop for the common
694           case in a multiplexed bistream where the page is simply
695           part of a different logical bitstream; keep reading until
696           we get one with the correct serialno */
697       
698        if(!readp)return(0);
699        if((ret=_get_next_page(vf,&og,-1))<0){
700          return(OV_EOF); /* eof. leave unitialized */
701        }
702
703        /* bitrate tracking; add the header's bytes here, the body bytes
704           are done by packet above */
705        vf->bittrack+=og.header_len*8;
706       
707        if(vf->ready_state==INITSET){
708          if(vf->current_serialno!=ogg_page_serialno(&og)){
709           
710            /* two possibilities:
711               1) our decoding just traversed a bitstream boundary
712               2) another stream is multiplexed into this logical section? */
713           
714            if(ogg_page_bos(&og)){
715              /* boundary case */
716              if(!spanp)
717                return(OV_EOF);
718             
719              _decode_clear(vf);
720             
721              if(!vf->seekable){
722                vorbis_info_clear(vf->vi);
723                vorbis_comment_clear(vf->vc);
724              }
725              break;
726
727            }else
728              continue; /* possibility #2 */
729          }
730        }
731
732        break;
733      }
734    }
735
736    /* Do we need to load a new machine before submitting the page? */
737    /* This is different in the seekable and non-seekable cases. 
738
739       In the seekable case, we already have all the header
740       information loaded and cached; we just initialize the machine
741       with it and continue on our merry way.
742
743       In the non-seekable (streaming) case, we'll only be at a
744       boundary if we just left the previous logical bitstream and
745       we're now nominally at the header of the next bitstream
746    */
747
748    if(vf->ready_state!=INITSET){ 
749      int link;
750
751      if(vf->ready_state<STREAMSET){
752        if(vf->seekable){
753          long serialno = ogg_page_serialno(&og);
754
755          /* match the serialno to bitstream section.  We use this rather than
756             offset positions to avoid problems near logical bitstream
757             boundaries */
758
759          for(link=0;link<vf->links;link++)
760            if(vf->serialnos[link]==serialno)break;
761
762          if(link==vf->links) continue; /* not the desired Vorbis
763                                           bitstream section; keep
764                                           trying */
765
766          vf->current_serialno=serialno;
767          vf->current_link=link;
768         
769          ogg_stream_reset_serialno(&vf->os,vf->current_serialno);
770          vf->ready_state=STREAMSET;
771         
772        }else{
773          /* we're streaming */
774          /* fetch the three header packets, build the info struct */
775         
776          int ret=_fetch_headers(vf,vf->vi,vf->vc,&vf->current_serialno,&og);
777          if(ret)return(ret);
778          vf->current_link++;
779          link=0;
780        }
781      }
782     
783      {
784        int ret=_make_decode_ready(vf);
785        if(ret<0)return ret;
786      }
787    }
788
789    /* the buffered page is the data we want, and we're ready for it;
790       add it to the stream state */
791    ogg_stream_pagein(&vf->os,&og);
792
793  }
794}
795
796/* if, eg, 64 bit stdio is configured by default, this will build with
797   fseek64 */
798static int _fseek64_wrap(FILE *f,ogg_int64_t off,int whence){
799  if(f==NULL)return(-1);
800  return fseek(f,off,whence);
801}
802
803static int _ov_open1(void *f,OggVorbis_File *vf,char *initial,
804                     long ibytes, ov_callbacks callbacks){
805  int offsettest=((f && callbacks.seek_func)?callbacks.seek_func(f,0,SEEK_CUR):-1);
806  int ret;
807 
808  memset(vf,0,sizeof(*vf));
809  vf->datasource=f;
810  vf->callbacks = callbacks;
811
812  /* init the framing state */
813  ogg_sync_init(&vf->oy);
814
815  /* perhaps some data was previously read into a buffer for testing
816     against other stream types.  Allow initialization from this
817     previously read data (as we may be reading from a non-seekable
818     stream) */
819  if(initial){
820    char *buffer=ogg_sync_buffer(&vf->oy,ibytes);
821    memcpy(buffer,initial,ibytes);
822    ogg_sync_wrote(&vf->oy,ibytes);
823  }
824
825  /* can we seek? Stevens suggests the seek test was portable */
826  if(offsettest!=-1)vf->seekable=1;
827
828  /* No seeking yet; Set up a 'single' (current) logical bitstream
829     entry for partial open */
830  vf->links=1;
831  vf->vi=_ogg_calloc(vf->links,sizeof(*vf->vi));
832  vf->vc=_ogg_calloc(vf->links,sizeof(*vf->vc));
833  ogg_stream_init(&vf->os,-1); /* fill in the serialno later */
834
835  /* Try to fetch the headers, maintaining all the storage */
836  if((ret=_fetch_headers(vf,vf->vi,vf->vc,&vf->current_serialno,NULL))<0){
837    vf->datasource=NULL;
838    ov_clear(vf);
839  }else 
840    vf->ready_state=PARTOPEN;
841  return(ret);
842}
843
844static int _ov_open2(OggVorbis_File *vf){
845  if(vf->ready_state != PARTOPEN) return OV_EINVAL;
846  vf->ready_state=OPENED;
847  if(vf->seekable){
848    int ret=_open_seekable2(vf);
849    if(ret){
850      vf->datasource=NULL;
851      ov_clear(vf);
852    }
853    return(ret);
854  }else
855    vf->ready_state=STREAMSET;
856
857  return 0;
858}
859
860
861/* clear out the OggVorbis_File struct */
862int ov_clear(OggVorbis_File *vf){
863  if(vf){
864    vorbis_block_clear(&vf->vb);
865    vorbis_dsp_clear(&vf->vd);
866    ogg_stream_clear(&vf->os);
867   
868    if(vf->vi && vf->links){
869      int i;
870      for(i=0;i<vf->links;i++){
871        vorbis_info_clear(vf->vi+i);
872        vorbis_comment_clear(vf->vc+i);
873      }
874      _ogg_free(vf->vi);
875      _ogg_free(vf->vc);
876    }
877    if(vf->dataoffsets)_ogg_free(vf->dataoffsets);
878    if(vf->pcmlengths)_ogg_free(vf->pcmlengths);
879    if(vf->serialnos)_ogg_free(vf->serialnos);
880    if(vf->offsets)_ogg_free(vf->offsets);
881    ogg_sync_clear(&vf->oy);
882    if(vf->datasource && vf->callbacks.close_func)
883      (vf->callbacks.close_func)(vf->datasource);
884    memset(vf,0,sizeof(*vf));
885  }
886#ifdef DEBUG_LEAKS
887  _VDBG_dump();
888#endif
889  return(0);
890}
891
892/* inspects the OggVorbis file and finds/documents all the logical
893   bitstreams contained in it.  Tries to be tolerant of logical
894   bitstream sections that are truncated/woogie.
895
896   return: -1) error
897            0) OK
898*/
899
900int ov_open_callbacks(void *f,OggVorbis_File *vf,char *initial,long ibytes,
901    ov_callbacks callbacks){
902  int ret=_ov_open1(f,vf,initial,ibytes,callbacks);
903  if(ret)return ret;
904  return _ov_open2(vf);
905}
906
907int ov_open(FILE *f,OggVorbis_File *vf,char *initial,long ibytes){
908  ov_callbacks callbacks = {
909    (size_t (*)(void *, size_t, size_t, void *))  fread,
910    (int (*)(void *, ogg_int64_t, int))              _fseek64_wrap,
911    (int (*)(void *))                             fclose,
912    (long (*)(void *))                            ftell
913  };
914
915  return ov_open_callbacks((void *)f, vf, initial, ibytes, callbacks);
916}
917
918int ov_fopen(char *path,OggVorbis_File *vf){
919  int ret;
920  FILE *f = fopen(path,"rb");
921  if(!f) return -1;
922
923  ret = ov_open(f,vf,NULL,0);
924  if(ret) fclose(f);
925  return ret;
926}
927
928 
929/* cheap hack for game usage where downsampling is desirable; there's
930   no need for SRC as we can just do it cheaply in libvorbis. */
931 
932int ov_halfrate(OggVorbis_File *vf,int flag){
933  int i;
934  if(vf->vi==NULL)return OV_EINVAL;
935  if(!vf->seekable)return OV_EINVAL;
936  if(vf->ready_state>=STREAMSET)
937    _decode_clear(vf); /* clear out stream state; later on libvorbis
938                          will be able to swap this on the fly, but
939                          for now dumping the decode machine is needed
940                          to reinit the MDCT lookups.  1.1 libvorbis
941                          is planned to be able to switch on the fly */
942 
943  for(i=0;i<vf->links;i++){
944    if(vorbis_synthesis_halfrate(vf->vi+i,flag)){
945      ov_halfrate(vf,0);
946      return OV_EINVAL;
947    }
948  }
949  return 0;
950}
951
952int ov_halfrate_p(OggVorbis_File *vf){
953  if(vf->vi==NULL)return OV_EINVAL;
954  return vorbis_synthesis_halfrate_p(vf->vi);
955}
956
957/* Only partially open the vorbis file; test for Vorbisness, and load
958   the headers for the first chain.  Do not seek (although test for
959   seekability).  Use ov_test_open to finish opening the file, else
960   ov_clear to close/free it. Same return codes as open. */
961
962int ov_test_callbacks(void *f,OggVorbis_File *vf,char *initial,long ibytes,
963    ov_callbacks callbacks)
964{
965  return _ov_open1(f,vf,initial,ibytes,callbacks);
966}
967
968int ov_test(FILE *f,OggVorbis_File *vf,char *initial,long ibytes){
969  ov_callbacks callbacks = {
970    (size_t (*)(void *, size_t, size_t, void *))  fread,
971    (int (*)(void *, ogg_int64_t, int))              _fseek64_wrap,
972    (int (*)(void *))                             fclose,
973    (long (*)(void *))                            ftell
974  };
975
976  return ov_test_callbacks((void *)f, vf, initial, ibytes, callbacks);
977}
978 
979int ov_test_open(OggVorbis_File *vf){
980  if(vf->ready_state!=PARTOPEN)return(OV_EINVAL);
981  return _ov_open2(vf);
982}
983
984/* How many logical bitstreams in this physical bitstream? */
985long ov_streams(OggVorbis_File *vf){
986  return vf->links;
987}
988
989/* Is the FILE * associated with vf seekable? */
990long ov_seekable(OggVorbis_File *vf){
991  return vf->seekable;
992}
993
994/* returns the bitrate for a given logical bitstream or the entire
995   physical bitstream.  If the file is open for random access, it will
996   find the *actual* average bitrate.  If the file is streaming, it
997   returns the nominal bitrate (if set) else the average of the
998   upper/lower bounds (if set) else -1 (unset).
999
1000   If you want the actual bitrate field settings, get them from the
1001   vorbis_info structs */
1002
1003long ov_bitrate(OggVorbis_File *vf,int i){
1004  if(vf->ready_state<OPENED)return(OV_EINVAL);
1005  if(i>=vf->links)return(OV_EINVAL);
1006  if(!vf->seekable && i!=0)return(ov_bitrate(vf,0));
1007  if(i<0){
1008    ogg_int64_t bits=0;
1009    int i;
1010    float br;
1011    for(i=0;i<vf->links;i++)
1012      bits+=(vf->offsets[i+1]-vf->dataoffsets[i])*8;
1013    /* This once read: return(rint(bits/ov_time_total(vf,-1)));
1014     * gcc 3.x on x86 miscompiled this at optimisation level 2 and above,
1015     * so this is slightly transformed to make it work.
1016     */
1017    br = bits/ov_time_total(vf,-1);
1018    return(rint(br));
1019  }else{
1020    if(vf->seekable){
1021      /* return the actual bitrate */
1022      return(rint((vf->offsets[i+1]-vf->dataoffsets[i])*8/ov_time_total(vf,i)));
1023    }else{
1024      /* return nominal if set */
1025      if(vf->vi[i].bitrate_nominal>0){
1026        return vf->vi[i].bitrate_nominal;
1027      }else{
1028        if(vf->vi[i].bitrate_upper>0){
1029          if(vf->vi[i].bitrate_lower>0){
1030            return (vf->vi[i].bitrate_upper+vf->vi[i].bitrate_lower)/2;
1031          }else{
1032            return vf->vi[i].bitrate_upper;
1033          }
1034        }
1035        return(OV_FALSE);
1036      }
1037    }
1038  }
1039}
1040
1041/* returns the actual bitrate since last call.  returns -1 if no
1042   additional data to offer since last call (or at beginning of stream),
1043   EINVAL if stream is only partially open
1044*/
1045long ov_bitrate_instant(OggVorbis_File *vf){
1046  int link=(vf->seekable?vf->current_link:0);
1047  long ret;
1048  if(vf->ready_state<OPENED)return(OV_EINVAL);
1049  if(vf->samptrack==0)return(OV_FALSE);
1050  ret=vf->bittrack/vf->samptrack*vf->vi[link].rate+.5;
1051  vf->bittrack=0.f;
1052  vf->samptrack=0.f;
1053  return(ret);
1054}
1055
1056/* Guess */
1057long ov_serialnumber(OggVorbis_File *vf,int i){
1058  if(i>=vf->links)return(ov_serialnumber(vf,vf->links-1));
1059  if(!vf->seekable && i>=0)return(ov_serialnumber(vf,-1));
1060  if(i<0){
1061    return(vf->current_serialno);
1062  }else{
1063    return(vf->serialnos[i]);
1064  }
1065}
1066
1067/* returns: total raw (compressed) length of content if i==-1
1068            raw (compressed) length of that logical bitstream for i==0 to n
1069            OV_EINVAL if the stream is not seekable (we can't know the length)
1070            or if stream is only partially open
1071*/
1072ogg_int64_t ov_raw_total(OggVorbis_File *vf,int i){
1073  if(vf->ready_state<OPENED)return(OV_EINVAL);
1074  if(!vf->seekable || i>=vf->links)return(OV_EINVAL);
1075  if(i<0){
1076    ogg_int64_t acc=0;
1077    int i;
1078    for(i=0;i<vf->links;i++)
1079      acc+=ov_raw_total(vf,i);
1080    return(acc);
1081  }else{
1082    return(vf->offsets[i+1]-vf->offsets[i]);
1083  }
1084}
1085
1086/* returns: total PCM length (samples) of content if i==-1 PCM length
1087            (samples) of that logical bitstream for i==0 to n
1088            OV_EINVAL if the stream is not seekable (we can't know the
1089            length) or only partially open
1090*/
1091ogg_int64_t ov_pcm_total(OggVorbis_File *vf,int i){
1092  if(vf->ready_state<OPENED)return(OV_EINVAL);
1093  if(!vf->seekable || i>=vf->links)return(OV_EINVAL);
1094  if(i<0){
1095    ogg_int64_t acc=0;
1096    int i;
1097    for(i=0;i<vf->links;i++)
1098      acc+=ov_pcm_total(vf,i);
1099    return(acc);
1100  }else{
1101    return(vf->pcmlengths[i*2+1]);
1102  }
1103}
1104
1105/* returns: total seconds of content if i==-1
1106            seconds in that logical bitstream for i==0 to n
1107            OV_EINVAL if the stream is not seekable (we can't know the
1108            length) or only partially open
1109*/
1110double ov_time_total(OggVorbis_File *vf,int i){
1111  if(vf->ready_state<OPENED)return(OV_EINVAL);
1112  if(!vf->seekable || i>=vf->links)return(OV_EINVAL);
1113  if(i<0){
1114    double acc=0;
1115    int i;
1116    for(i=0;i<vf->links;i++)
1117      acc+=ov_time_total(vf,i);
1118    return(acc);
1119  }else{
1120    return((double)(vf->pcmlengths[i*2+1])/vf->vi[i].rate);
1121  }
1122}
1123
1124/* seek to an offset relative to the *compressed* data. This also
1125   scans packets to update the PCM cursor. It will cross a logical
1126   bitstream boundary, but only if it can't get any packets out of the
1127   tail of the bitstream we seek to (so no surprises).
1128
1129   returns zero on success, nonzero on failure */
1130
1131int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos){
1132  ogg_stream_state work_os;
1133  int ret;
1134
1135  if(vf->ready_state<OPENED)return(OV_EINVAL);
1136  if(!vf->seekable)
1137    return(OV_ENOSEEK); /* don't dump machine if we can't seek */
1138
1139  if(pos<0 || pos>vf->end)return(OV_EINVAL);
1140
1141  /* don't yet clear out decoding machine (if it's initialized), in
1142     the case we're in the same link.  Restart the decode lapping, and
1143     let _fetch_and_process_packet deal with a potential bitstream
1144     boundary */
1145  vf->pcm_offset=-1;
1146  ogg_stream_reset_serialno(&vf->os,
1147                            vf->current_serialno); /* must set serialno */
1148  vorbis_synthesis_restart(&vf->vd);
1149   
1150  ret=_seek_helper(vf,pos);
1151  if(ret)goto seek_error;
1152
1153  /* we need to make sure the pcm_offset is set, but we don't want to
1154     advance the raw cursor past good packets just to get to the first
1155     with a granulepos.  That's not equivalent behavior to beginning
1156     decoding as immediately after the seek position as possible.
1157
1158     So, a hack.  We use two stream states; a local scratch state and
1159     the shared vf->os stream state.  We use the local state to
1160     scan, and the shared state as a buffer for later decode.
1161
1162     Unfortuantely, on the last page we still advance to last packet
1163     because the granulepos on the last page is not necessarily on a
1164     packet boundary, and we need to make sure the granpos is
1165     correct.
1166  */
1167
1168  {
1169    ogg_page og;
1170    ogg_packet op;
1171    int lastblock=0;
1172    int accblock=0;
1173    int thisblock=0;
1174    int eosflag=0; 
1175
1176    ogg_stream_init(&work_os,vf->current_serialno); /* get the memory ready */
1177    ogg_stream_reset(&work_os); /* eliminate the spurious OV_HOLE
1178                                   return from not necessarily
1179                                   starting from the beginning */
1180
1181    while(1){
1182      if(vf->ready_state>=STREAMSET){
1183        /* snarf/scan a packet if we can */
1184        int result=ogg_stream_packetout(&work_os,&op);
1185     
1186        if(result>0){
1187
1188          if(vf->vi[vf->current_link].codec_setup){
1189            thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op);
1190            if(thisblock<0){
1191              ogg_stream_packetout(&vf->os,NULL);
1192              thisblock=0;
1193            }else{
1194             
1195              if(eosflag)
1196                ogg_stream_packetout(&vf->os,NULL);
1197              else
1198                if(lastblock)accblock+=(lastblock+thisblock)>>2;
1199            }       
1200
1201            if(op.granulepos!=-1){
1202              int i,link=vf->current_link;
1203              ogg_int64_t granulepos=op.granulepos-vf->pcmlengths[link*2];
1204              if(granulepos<0)granulepos=0;
1205             
1206              for(i=0;i<link;i++)
1207                granulepos+=vf->pcmlengths[i*2+1];
1208              vf->pcm_offset=granulepos-accblock;
1209              break;
1210            }
1211            lastblock=thisblock;
1212            continue;
1213          }else
1214            ogg_stream_packetout(&vf->os,NULL);
1215        }
1216      }
1217     
1218      if(!lastblock){
1219        if(_get_next_page(vf,&og,-1)<0){
1220          vf->pcm_offset=ov_pcm_total(vf,-1);
1221          break;
1222        }
1223      }else{
1224        /* huh?  Bogus stream with packets but no granulepos */
1225        vf->pcm_offset=-1;
1226        break;
1227      }
1228     
1229      /* has our decoding just traversed a bitstream boundary? */
1230      if(vf->ready_state>=STREAMSET){
1231        if(vf->current_serialno!=ogg_page_serialno(&og)){
1232         
1233          /* two possibilities:
1234             1) our decoding just traversed a bitstream boundary
1235             2) another stream is multiplexed into this logical section? */
1236           
1237          if(ogg_page_bos(&og)){
1238            /* we traversed */
1239            _decode_clear(vf); /* clear out stream state */
1240            ogg_stream_clear(&work_os);
1241          } /* else, do nothing; next loop will scoop another page */
1242        }
1243      }
1244
1245      if(vf->ready_state<STREAMSET){
1246        int link;
1247        long serialno = ogg_page_serialno(&og);
1248
1249        for(link=0;link<vf->links;link++)
1250          if(vf->serialnos[link]==serialno)break;
1251
1252        if(link==vf->links) continue; /* not the desired Vorbis
1253                                         bitstream section; keep
1254                                         trying */
1255        vf->current_link=link;
1256        vf->current_serialno=serialno;
1257        ogg_stream_reset_serialno(&vf->os,serialno);
1258        ogg_stream_reset_serialno(&work_os,serialno); 
1259        vf->ready_state=STREAMSET;
1260       
1261      }
1262   
1263      ogg_stream_pagein(&vf->os,&og);
1264      ogg_stream_pagein(&work_os,&og);
1265      eosflag=ogg_page_eos(&og);
1266    }
1267  }
1268
1269  ogg_stream_clear(&work_os);
1270  vf->bittrack=0.f;
1271  vf->samptrack=0.f;
1272  return(0);
1273
1274 seek_error:
1275  /* dump the machine so we're in a known state */
1276  vf->pcm_offset=-1;
1277  ogg_stream_clear(&work_os);
1278  _decode_clear(vf);
1279  return OV_EBADLINK;
1280}
1281
1282/* Page granularity seek (faster than sample granularity because we
1283   don't do the last bit of decode to find a specific sample).
1284
1285   Seek to the last [granule marked] page preceeding the specified pos
1286   location, such that decoding past the returned point will quickly
1287   arrive at the requested position. */
1288int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
1289  int link=-1;
1290  ogg_int64_t result=0;
1291  ogg_int64_t total=ov_pcm_total(vf,-1);
1292 
1293  if(vf->ready_state<OPENED)return(OV_EINVAL);
1294  if(!vf->seekable)return(OV_ENOSEEK);
1295
1296  if(pos<0 || pos>total)return(OV_EINVAL);
1297 
1298  /* which bitstream section does this pcm offset occur in? */
1299  for(link=vf->links-1;link>=0;link--){
1300    total-=vf->pcmlengths[link*2+1];
1301    if(pos>=total)break;
1302  }
1303
1304  /* search within the logical bitstream for the page with the highest
1305     pcm_pos preceeding (or equal to) pos.  There is a danger here;
1306     missing pages or incorrect frame number information in the
1307     bitstream could make our task impossible.  Account for that (it
1308     would be an error condition) */
1309
1310  /* new search algorithm by HB (Nicholas Vinen) */
1311  {
1312    ogg_int64_t end=vf->offsets[link+1];
1313    ogg_int64_t begin=vf->offsets[link];
1314    ogg_int64_t begintime = vf->pcmlengths[link*2];
1315    ogg_int64_t endtime = vf->pcmlengths[link*2+1]+begintime;
1316    ogg_int64_t target=pos-total+begintime;
1317    ogg_int64_t best=begin;
1318   
1319    ogg_page og;
1320    while(begin<end){
1321      ogg_int64_t bisect;
1322     
1323      if(end-begin<CHUNKSIZE){
1324        bisect=begin;
1325      }else{
1326        /* take a (pretty decent) guess. */
1327        bisect=begin + 
1328          (target-begintime)*(end-begin)/(endtime-begintime) - CHUNKSIZE;
1329        if(bisect<=begin)
1330          bisect=begin+1;
1331      }
1332     
1333      result=_seek_helper(vf,bisect);
1334      if(result) goto seek_error;
1335     
1336      while(begin<end){
1337        result=_get_next_page(vf,&og,end-vf->offset);
1338        if(result==OV_EREAD) goto seek_error;
1339        if(result<0){
1340          if(bisect<=begin+1)
1341            end=begin; /* found it */
1342          else{
1343            if(bisect==0) goto seek_error;
1344            bisect-=CHUNKSIZE;
1345            if(bisect<=begin)bisect=begin+1;
1346            result=_seek_helper(vf,bisect);
1347            if(result) goto seek_error;
1348          }
1349        }else{
1350          ogg_int64_t granulepos;
1351
1352          if(ogg_page_serialno(&og)!=vf->serialnos[link])
1353            continue;
1354
1355          granulepos=ogg_page_granulepos(&og);
1356          if(granulepos==-1)continue;
1357         
1358          if(granulepos<target){
1359            best=result;  /* raw offset of packet with granulepos */ 
1360            begin=vf->offset; /* raw offset of next page */
1361            begintime=granulepos;
1362           
1363            if(target-begintime>44100)break;
1364            bisect=begin; /* *not* begin + 1 */
1365          }else{
1366            if(bisect<=begin+1)
1367              end=begin;  /* found it */
1368            else{
1369              if(end==vf->offset){ /* we're pretty close - we'd be stuck in */
1370                end=result;
1371                bisect-=CHUNKSIZE; /* an endless loop otherwise. */
1372                if(bisect<=begin)bisect=begin+1;
1373                result=_seek_helper(vf,bisect);
1374                if(result) goto seek_error;
1375              }else{
1376                end=bisect;
1377                endtime=granulepos;
1378                break;
1379              }
1380            }
1381          }
1382        }
1383      }
1384    }
1385
1386    /* found our page. seek to it, update pcm offset. Easier case than
1387       raw_seek, don't keep packets preceeding granulepos. */
1388    {
1389      ogg_page og;
1390      ogg_packet op;
1391     
1392      /* seek */
1393      result=_seek_helper(vf,best);
1394      vf->pcm_offset=-1;
1395      if(result) goto seek_error;
1396      result=_get_next_page(vf,&og,-1);
1397      if(result<0) goto seek_error;
1398     
1399      if(link!=vf->current_link){
1400        /* Different link; dump entire decode machine */
1401        _decode_clear(vf); 
1402       
1403        vf->current_link=link;
1404        vf->current_serialno=vf->serialnos[link];
1405        vf->ready_state=STREAMSET;
1406       
1407      }else{
1408        vorbis_synthesis_restart(&vf->vd);
1409      }
1410
1411      ogg_stream_reset_serialno(&vf->os,vf->current_serialno);
1412      ogg_stream_pagein(&vf->os,&og);
1413
1414      /* pull out all but last packet; the one with granulepos */
1415      while(1){
1416        result=ogg_stream_packetpeek(&vf->os,&op);
1417        if(result==0){
1418          /* !!! the packet finishing this page originated on a
1419             preceeding page. Keep fetching previous pages until we
1420             get one with a granulepos or without the 'continued' flag
1421             set.  Then just use raw_seek for simplicity. */
1422         
1423          result=_seek_helper(vf,best);
1424          if(result<0) goto seek_error;
1425         
1426          while(1){
1427            result=_get_prev_page(vf,&og);
1428            if(result<0) goto seek_error;
1429            if(ogg_page_serialno(&og)==vf->current_serialno &&
1430               (ogg_page_granulepos(&og)>-1 ||
1431                !ogg_page_continued(&og))){
1432              return ov_raw_seek(vf,result);
1433            }
1434            vf->offset=result;
1435          }
1436        }
1437        if(result<0){
1438          result = OV_EBADPACKET; 
1439          goto seek_error;
1440        }
1441        if(op.granulepos!=-1){
1442          vf->pcm_offset=op.granulepos-vf->pcmlengths[vf->current_link*2];
1443          if(vf->pcm_offset<0)vf->pcm_offset=0;
1444          vf->pcm_offset+=total;
1445          break;
1446        }else
1447          result=ogg_stream_packetout(&vf->os,NULL);
1448      }
1449    }
1450  }
1451 
1452  /* verify result */
1453  if(vf->pcm_offset>pos || pos>ov_pcm_total(vf,-1)){
1454    result=OV_EFAULT;
1455    goto seek_error;
1456  }
1457  vf->bittrack=0.f;
1458  vf->samptrack=0.f;
1459  return(0);
1460 
1461 seek_error:
1462  /* dump machine so we're in a known state */
1463  vf->pcm_offset=-1;
1464  _decode_clear(vf);
1465  return (int)result;
1466}
1467
1468/* seek to a sample offset relative to the decompressed pcm stream
1469   returns zero on success, nonzero on failure */
1470
1471int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos){
1472  int thisblock,lastblock=0;
1473  int ret=ov_pcm_seek_page(vf,pos);
1474  if(ret<0)return(ret);
1475  if((ret=_make_decode_ready(vf)))return ret;
1476
1477  /* discard leading packets we don't need for the lapping of the
1478     position we want; don't decode them */
1479
1480  while(1){
1481    ogg_packet op;
1482    ogg_page og;
1483
1484    int ret=ogg_stream_packetpeek(&vf->os,&op);
1485    if(ret>0){
1486      thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op);
1487      if(thisblock<0){
1488        ogg_stream_packetout(&vf->os,NULL);
1489        continue; /* non audio packet */
1490      }
1491      if(lastblock)vf->pcm_offset+=(lastblock+thisblock)>>2;
1492     
1493      if(vf->pcm_offset+((thisblock+
1494                          vorbis_info_blocksize(vf->vi,1))>>2)>=pos)break;
1495     
1496      /* remove the packet from packet queue and track its granulepos */
1497      ogg_stream_packetout(&vf->os,NULL);
1498      vorbis_synthesis_trackonly(&vf->vb,&op);  /* set up a vb with
1499                                                   only tracking, no
1500                                                   pcm_decode */
1501      vorbis_synthesis_blockin(&vf->vd,&vf->vb); 
1502     
1503      /* end of logical stream case is hard, especially with exact
1504         length positioning. */
1505     
1506      if(op.granulepos>-1){
1507        int i;
1508        /* always believe the stream markers */
1509        vf->pcm_offset=op.granulepos-vf->pcmlengths[vf->current_link*2];
1510        if(vf->pcm_offset<0)vf->pcm_offset=0;
1511        for(i=0;i<vf->current_link;i++)
1512          vf->pcm_offset+=vf->pcmlengths[i*2+1];
1513      }
1514       
1515      lastblock=thisblock;
1516     
1517    }else{
1518      if(ret<0 && ret!=OV_HOLE)break;
1519     
1520      /* suck in a new page */
1521      if(_get_next_page(vf,&og,-1)<0)break;
1522      if(ogg_page_bos(&og))_decode_clear(vf);
1523     
1524      if(vf->ready_state<STREAMSET){
1525        long serialno=ogg_page_serialno(&og);
1526        int link;
1527       
1528        for(link=0;link<vf->links;link++)
1529          if(vf->serialnos[link]==serialno)break;
1530        if(link==vf->links) continue; 
1531        vf->current_link=link;
1532       
1533        vf->ready_state=STREAMSET;     
1534        vf->current_serialno=ogg_page_serialno(&og);
1535        ogg_stream_reset_serialno(&vf->os,serialno); 
1536        ret=_make_decode_ready(vf);
1537        if(ret)return ret;
1538        lastblock=0;
1539      }
1540
1541      ogg_stream_pagein(&vf->os,&og);
1542    }
1543  }
1544
1545  vf->bittrack=0.f;
1546  vf->samptrack=0.f;
1547  /* discard samples until we reach the desired position. Crossing a
1548     logical bitstream boundary with abandon is OK. */
1549  while(vf->pcm_offset<pos){
1550    ogg_int64_t target=pos-vf->pcm_offset;
1551    long samples=vorbis_synthesis_pcmout(&vf->vd,NULL);
1552
1553    if(samples>target)samples=target;
1554    vorbis_synthesis_read(&vf->vd,samples);
1555    vf->pcm_offset+=samples;
1556   
1557    if(samples<target)
1558      if(_fetch_and_process_packet(vf,NULL,1,1)<=0)
1559        vf->pcm_offset=ov_pcm_total(vf,-1); /* eof */
1560  }
1561  return 0;
1562}
1563
1564/* seek to a playback time relative to the decompressed pcm stream
1565   returns zero on success, nonzero on failure */
1566int ov_time_seek(OggVorbis_File *vf,double seconds){
1567  /* translate time to PCM position and call ov_pcm_seek */
1568
1569  int link=-1;
1570  ogg_int64_t pcm_total=0;
1571  double time_total=0.;
1572
1573  if(vf->ready_state<OPENED)return(OV_EINVAL);
1574  if(!vf->seekable)return(OV_ENOSEEK);
1575  if(seconds<0)return(OV_EINVAL);
1576 
1577  /* which bitstream section does this time offset occur in? */
1578  for(link=0;link<vf->links;link++){
1579    double addsec = ov_time_total(vf,link);
1580    if(seconds<time_total+addsec)break;
1581    time_total+=addsec;
1582    pcm_total+=vf->pcmlengths[link*2+1];
1583  }
1584
1585  if(link==vf->links)return(OV_EINVAL);
1586
1587  /* enough information to convert time offset to pcm offset */
1588  {
1589    ogg_int64_t target=pcm_total+(seconds-time_total)*vf->vi[link].rate;
1590    return(ov_pcm_seek(vf,target));
1591  }
1592}
1593
1594/* page-granularity version of ov_time_seek
1595   returns zero on success, nonzero on failure */
1596int ov_time_seek_page(OggVorbis_File *vf,double seconds){
1597  /* translate time to PCM position and call ov_pcm_seek */
1598
1599  int link=-1;
1600  ogg_int64_t pcm_total=0;
1601  double time_total=0.;
1602
1603  if(vf->ready_state<OPENED)return(OV_EINVAL);
1604  if(!vf->seekable)return(OV_ENOSEEK);
1605  if(seconds<0)return(OV_EINVAL);
1606 
1607  /* which bitstream section does this time offset occur in? */
1608  for(link=0;link<vf->links;link++){
1609    double addsec = ov_time_total(vf,link);
1610    if(seconds<time_total+addsec)break;
1611    time_total+=addsec;
1612    pcm_total+=vf->pcmlengths[link*2+1];
1613  }
1614
1615  if(link==vf->links)return(OV_EINVAL);
1616
1617  /* enough information to convert time offset to pcm offset */
1618  {
1619    ogg_int64_t target=pcm_total+(seconds-time_total)*vf->vi[link].rate;
1620    return(ov_pcm_seek_page(vf,target));
1621  }
1622}
1623
1624/* tell the current stream offset cursor.  Note that seek followed by
1625   tell will likely not give the set offset due to caching */
1626ogg_int64_t ov_raw_tell(OggVorbis_File *vf){
1627  if(vf->ready_state<OPENED)return(OV_EINVAL);
1628  return(vf->offset);
1629}
1630
1631/* return PCM offset (sample) of next PCM sample to be read */
1632ogg_int64_t ov_pcm_tell(OggVorbis_File *vf){
1633  if(vf->ready_state<OPENED)return(OV_EINVAL);
1634  return(vf->pcm_offset);
1635}
1636
1637/* return time offset (seconds) of next PCM sample to be read */
1638double ov_time_tell(OggVorbis_File *vf){
1639  int link=0;
1640  ogg_int64_t pcm_total=0;
1641  double time_total=0.f;
1642 
1643  if(vf->ready_state<OPENED)return(OV_EINVAL);
1644  if(vf->seekable){
1645    pcm_total=ov_pcm_total(vf,-1);
1646    time_total=ov_time_total(vf,-1);
1647 
1648    /* which bitstream section does this time offset occur in? */
1649    for(link=vf->links-1;link>=0;link--){
1650      pcm_total-=vf->pcmlengths[link*2+1];
1651      time_total-=ov_time_total(vf,link);
1652      if(vf->pcm_offset>=pcm_total)break;
1653    }
1654  }
1655
1656  return((double)time_total+(double)(vf->pcm_offset-pcm_total)/vf->vi[link].rate);
1657}
1658
1659/*  link:   -1) return the vorbis_info struct for the bitstream section
1660                currently being decoded
1661           0-n) to request information for a specific bitstream section
1662   
1663    In the case of a non-seekable bitstream, any call returns the
1664    current bitstream.  NULL in the case that the machine is not
1665    initialized */
1666
1667vorbis_info *ov_info(OggVorbis_File *vf,int link){
1668  if(vf->seekable){
1669    if(link<0)
1670      if(vf->ready_state>=STREAMSET)
1671        return vf->vi+vf->current_link;
1672      else
1673      return vf->vi;
1674    else
1675      if(link>=vf->links)
1676        return NULL;
1677      else
1678        return vf->vi+link;
1679  }else{
1680    return vf->vi;
1681  }
1682}
1683
1684/* grr, strong typing, grr, no templates/inheritence, grr */
1685vorbis_comment *ov_comment(OggVorbis_File *vf,int link){
1686  if(vf->seekable){
1687    if(link<0)
1688      if(vf->ready_state>=STREAMSET)
1689        return vf->vc+vf->current_link;
1690      else
1691        return vf->vc;
1692    else
1693      if(link>=vf->links)
1694        return NULL;
1695      else
1696        return vf->vc+link;
1697  }else{
1698    return vf->vc;
1699  }
1700}
1701
1702static int host_is_big_endian() {
1703  ogg_int32_t pattern = 0xfeedface; /* deadbeef */
1704  unsigned char *bytewise = (unsigned char *)&pattern;
1705  if (bytewise[0] == 0xfe) return 1;
1706  return 0;
1707}
1708
1709/* up to this point, everything could more or less hide the multiple
1710   logical bitstream nature of chaining from the toplevel application
1711   if the toplevel application didn't particularly care.  However, at
1712   the point that we actually read audio back, the multiple-section
1713   nature must surface: Multiple bitstream sections do not necessarily
1714   have to have the same number of channels or sampling rate.
1715
1716   ov_read returns the sequential logical bitstream number currently
1717   being decoded along with the PCM data in order that the toplevel
1718   application can take action on channel/sample rate changes.  This
1719   number will be incremented even for streamed (non-seekable) streams
1720   (for seekable streams, it represents the actual logical bitstream
1721   index within the physical bitstream.  Note that the accessor
1722   functions above are aware of this dichotomy).
1723
1724   input values: buffer) a buffer to hold packed PCM data for return
1725                 length) the byte length requested to be placed into buffer
1726                 bigendianp) should the data be packed LSB first (0) or
1727                             MSB first (1)
1728                 word) word size for output.  currently 1 (byte) or
1729                       2 (16 bit short)
1730
1731   return values: <0) error/hole in data (OV_HOLE), partial open (OV_EINVAL)
1732                   0) EOF
1733                   n) number of bytes of PCM actually returned.  The
1734                   below works on a packet-by-packet basis, so the
1735                   return length is not related to the 'length' passed
1736                   in, just guaranteed to fit.
1737
1738            *section) set to the logical bitstream number */
1739
1740long ov_read(OggVorbis_File *vf,char *buffer,int length,
1741                    int bigendianp,int word,int sgned,int *bitstream){
1742  int i,j;
1743  int host_endian = host_is_big_endian();
1744
1745  float **pcm;
1746  long samples;
1747
1748  if(vf->ready_state<OPENED)return(OV_EINVAL);
1749
1750  while(1){
1751    if(vf->ready_state==INITSET){
1752      samples=vorbis_synthesis_pcmout(&vf->vd,&pcm);
1753      if(samples)break;
1754    }
1755
1756    /* suck in another packet */
1757    {
1758      int ret=_fetch_and_process_packet(vf,NULL,1,1);
1759      if(ret==OV_EOF)
1760        return(0);
1761      if(ret<=0)
1762        return(ret);
1763    }
1764
1765  }
1766
1767  if(samples>0){
1768 
1769    /* yay! proceed to pack data into the byte buffer */
1770   
1771    long channels=ov_info(vf,-1)->channels;
1772    long bytespersample=word * channels;
1773    vorbis_fpu_control fpu;
1774    if(samples>length/bytespersample)samples=length/bytespersample;
1775
1776    if(samples <= 0)
1777      return OV_EINVAL;
1778   
1779    /* a tight loop to pack each size */
1780    {
1781      int val;
1782      if(word==1){
1783        int off=(sgned?0:128);
1784        vorbis_fpu_setround(&fpu);
1785        for(j=0;j<samples;j++)
1786          for(i=0;i<channels;i++){
1787            val=vorbis_ftoi(pcm[i][j]*128.f);
1788            if(val>127)val=127;
1789            else if(val<-128)val=-128;
1790            *buffer++=val+off;
1791          }
1792        vorbis_fpu_restore(fpu);
1793      }else{
1794        int off=(sgned?0:32768);
1795       
1796        if(host_endian==bigendianp){
1797          if(sgned){
1798           
1799            vorbis_fpu_setround(&fpu);
1800            for(i=0;i<channels;i++) { /* It's faster in this order */
1801              float *src=pcm[i];
1802              short *dest=((short *)buffer)+i;
1803              for(j=0;j<samples;j++) {
1804                val=vorbis_ftoi(src[j]*32768.f);
1805                if(val>32767)val=32767;
1806                else if(val<-32768)val=-32768;
1807                *dest=val;
1808                dest+=channels;
1809              }
1810            }
1811            vorbis_fpu_restore(fpu);
1812           
1813          }else{
1814           
1815            vorbis_fpu_setround(&fpu);
1816            for(i=0;i<channels;i++) {
1817              float *src=pcm[i];
1818              short *dest=((short *)buffer)+i;
1819              for(j=0;j<samples;j++) {
1820                val=vorbis_ftoi(src[j]*32768.f);
1821                if(val>32767)val=32767;
1822                else if(val<-32768)val=-32768;
1823                *dest=val+off;
1824                dest+=channels;
1825              }
1826            }
1827            vorbis_fpu_restore(fpu);
1828           
1829          }
1830        }else if(bigendianp){
1831         
1832          vorbis_fpu_setround(&fpu);
1833          for(j=0;j<samples;j++)
1834            for(i=0;i<channels;i++){
1835              val=vorbis_ftoi(pcm[i][j]*32768.f);
1836              if(val>32767)val=32767;
1837              else if(val<-32768)val=-32768;
1838              val+=off;
1839              *buffer++=(val>>8);
1840              *buffer++=(val&0xff);
1841            }
1842          vorbis_fpu_restore(fpu);
1843         
1844        }else{
1845          int val;
1846          vorbis_fpu_setround(&fpu);
1847          for(j=0;j<samples;j++)
1848            for(i=0;i<channels;i++){
1849              val=vorbis_ftoi(pcm[i][j]*32768.f);
1850              if(val>32767)val=32767;
1851              else if(val<-32768)val=-32768;
1852              val+=off;
1853              *buffer++=(val&0xff);
1854              *buffer++=(val>>8);
1855                }
1856          vorbis_fpu_restore(fpu); 
1857         
1858        }
1859      }
1860    }
1861   
1862    vorbis_synthesis_read(&vf->vd,samples);
1863    vf->pcm_offset+=samples;
1864    if(bitstream)*bitstream=vf->current_link;
1865    return(samples*bytespersample);
1866  }else{
1867    return(samples);
1868  }
1869}
1870
1871/* input values: pcm_channels) a float vector per channel of output
1872                 length) the sample length being read by the app
1873
1874   return values: <0) error/hole in data (OV_HOLE), partial open (OV_EINVAL)
1875                   0) EOF
1876                   n) number of samples of PCM actually returned.  The
1877                   below works on a packet-by-packet basis, so the
1878                   return length is not related to the 'length' passed
1879                   in, just guaranteed to fit.
1880
1881            *section) set to the logical bitstream number */
1882
1883
1884
1885long ov_read_float(OggVorbis_File *vf,float ***pcm_channels,int length,
1886                   int *bitstream){
1887
1888  if(vf->ready_state<OPENED)return(OV_EINVAL);
1889
1890  while(1){
1891    if(vf->ready_state==INITSET){
1892      float **pcm;
1893      long samples=vorbis_synthesis_pcmout(&vf->vd,&pcm);
1894      if(samples){
1895        if(pcm_channels)*pcm_channels=pcm;
1896        if(samples>length)samples=length;
1897        vorbis_synthesis_read(&vf->vd,samples);
1898        vf->pcm_offset+=samples;
1899        if(bitstream)*bitstream=vf->current_link;
1900        return samples;
1901
1902      }
1903    }
1904
1905    /* suck in another packet */
1906    {
1907      int ret=_fetch_and_process_packet(vf,NULL,1,1);
1908      if(ret==OV_EOF)return(0);
1909      if(ret<=0)return(ret);
1910    }
1911
1912  }
1913}
1914
1915extern float *vorbis_window(vorbis_dsp_state *v,int W);
1916extern void _analysis_output_always(char *base,int i,float *v,int n,int bark,int dB,
1917                             ogg_int64_t off);
1918
1919static void _ov_splice(float **pcm,float **lappcm,
1920                       int n1, int n2,
1921                       int ch1, int ch2,
1922                       float *w1, float *w2){
1923  int i,j;
1924  float *w=w1;
1925  int n=n1;
1926
1927  if(n1>n2){
1928    n=n2;
1929    w=w2;
1930  }
1931
1932  /* splice */
1933  for(j=0;j<ch1 && j<ch2;j++){
1934    float *s=lappcm[j];
1935    float *d=pcm[j];
1936
1937    for(i=0;i<n;i++){
1938      float wd=w[i]*w[i];
1939      float ws=1.-wd;
1940      d[i]=d[i]*wd + s[i]*ws;
1941    }
1942  }
1943  /* window from zero */
1944  for(;j<ch2;j++){
1945    float *d=pcm[j];
1946    for(i=0;i<n;i++){
1947      float wd=w[i]*w[i];
1948      d[i]=d[i]*wd;
1949    }
1950  }
1951
1952}
1953               
1954/* make sure vf is INITSET */
1955static int _ov_initset(OggVorbis_File *vf){
1956  while(1){
1957    if(vf->ready_state==INITSET)break;
1958    /* suck in another packet */
1959    {
1960      int ret=_fetch_and_process_packet(vf,NULL,1,0);
1961      if(ret<0 && ret!=OV_HOLE)return(ret);
1962    }
1963  }
1964  return 0;
1965}
1966
1967/* make sure vf is INITSET and that we have a primed buffer; if
1968   we're crosslapping at a stream section boundary, this also makes
1969   sure we're sanity checking against the right stream information */
1970static int _ov_initprime(OggVorbis_File *vf){
1971  vorbis_dsp_state *vd=&vf->vd;
1972  while(1){
1973    if(vf->ready_state==INITSET)
1974      if(vorbis_synthesis_pcmout(vd,NULL))break;
1975   
1976    /* suck in another packet */
1977    {
1978      int ret=_fetch_and_process_packet(vf,NULL,1,0);
1979      if(ret<0 && ret!=OV_HOLE)return(ret);
1980    }
1981  } 
1982  return 0;
1983}
1984
1985/* grab enough data for lapping from vf; this may be in the form of
1986   unreturned, already-decoded pcm, remaining PCM we will need to
1987   decode, or synthetic postextrapolation from last packets. */
1988static void _ov_getlap(OggVorbis_File *vf,vorbis_info *vi,vorbis_dsp_state *vd,
1989                       float **lappcm,int lapsize){
1990  int lapcount=0,i;
1991  float **pcm;
1992
1993  /* try first to decode the lapping data */
1994  while(lapcount<lapsize){
1995    int samples=vorbis_synthesis_pcmout(vd,&pcm);
1996    if(samples){
1997      if(samples>lapsize-lapcount)samples=lapsize-lapcount;
1998      for(i=0;i<vi->channels;i++)
1999        memcpy(lappcm[i]+lapcount,pcm[i],sizeof(**pcm)*samples);
2000      lapcount+=samples;
2001      vorbis_synthesis_read(vd,samples);
2002    }else{
2003    /* suck in another packet */
2004      int ret=_fetch_and_process_packet(vf,NULL,1,0); /* do *not* span */
2005      if(ret==OV_EOF)break;
2006    }
2007  }
2008  if(lapcount<lapsize){
2009    /* failed to get lapping data from normal decode; pry it from the
2010       postextrapolation buffering, or the second half of the MDCT
2011       from the last packet */
2012    int samples=vorbis_synthesis_lapout(&vf->vd,&pcm);
2013    if(samples==0){
2014      for(i=0;i<vi->channels;i++)
2015        memset(lappcm[i]+lapcount,0,sizeof(**pcm)*lapsize-lapcount);
2016      lapcount=lapsize;
2017    }else{
2018      if(samples>lapsize-lapcount)samples=lapsize-lapcount;
2019      for(i=0;i<vi->channels;i++)
2020        memcpy(lappcm[i]+lapcount,pcm[i],sizeof(**pcm)*samples);
2021      lapcount+=samples;
2022    }
2023  }
2024}
2025
2026/* this sets up crosslapping of a sample by using trailing data from
2027   sample 1 and lapping it into the windowing buffer of sample 2 */
2028int ov_crosslap(OggVorbis_File *vf1, OggVorbis_File *vf2){
2029  vorbis_info *vi1,*vi2;
2030  float **lappcm;
2031  float **pcm;
2032  float *w1,*w2;
2033  int n1,n2,i,ret,hs1,hs2;
2034
2035  if(vf1==vf2)return(0); /* degenerate case */
2036  if(vf1->ready_state<OPENED)return(OV_EINVAL);
2037  if(vf2->ready_state<OPENED)return(OV_EINVAL);
2038
2039  /* the relevant overlap buffers must be pre-checked and pre-primed
2040     before looking at settings in the event that priming would cross
2041     a bitstream boundary.  So, do it now */
2042
2043  ret=_ov_initset(vf1);
2044  if(ret)return(ret);
2045  ret=_ov_initprime(vf2);
2046  if(ret)return(ret);
2047
2048  vi1=ov_info(vf1,-1);
2049  vi2=ov_info(vf2,-1);
2050  hs1=ov_halfrate_p(vf1);
2051  hs2=ov_halfrate_p(vf2);
2052
2053  lappcm=alloca(sizeof(*lappcm)*vi1->channels);
2054  n1=vorbis_info_blocksize(vi1,0)>>(1+hs1);
2055  n2=vorbis_info_blocksize(vi2,0)>>(1+hs2);
2056  w1=vorbis_window(&vf1->vd,0);
2057  w2=vorbis_window(&vf2->vd,0);
2058
2059  for(i=0;i<vi1->channels;i++)
2060    lappcm[i]=alloca(sizeof(**lappcm)*n1);
2061
2062  _ov_getlap(vf1,vi1,&vf1->vd,lappcm,n1);
2063
2064  /* have a lapping buffer from vf1; now to splice it into the lapping
2065     buffer of vf2 */
2066  /* consolidate and expose the buffer. */
2067  vorbis_synthesis_lapout(&vf2->vd,&pcm);
2068  _analysis_output_always("pcmL",0,pcm[0],n1*2,0,0,0);
2069  _analysis_output_always("pcmR",0,pcm[1],n1*2,0,0,0);
2070
2071  /* splice */
2072  _ov_splice(pcm,lappcm,n1,n2,vi1->channels,vi2->channels,w1,w2);
2073 
2074  /* done */
2075  return(0);
2076}
2077
2078static int _ov_64_seek_lap(OggVorbis_File *vf,ogg_int64_t pos,
2079                           int (*localseek)(OggVorbis_File *,ogg_int64_t)){
2080  vorbis_info *vi;
2081  float **lappcm;
2082  float **pcm;
2083  float *w1,*w2;
2084  int n1,n2,ch1,ch2,hs;
2085  int i,ret;
2086
2087  if(vf->ready_state<OPENED)return(OV_EINVAL);
2088  ret=_ov_initset(vf);
2089  if(ret)return(ret);
2090  vi=ov_info(vf,-1);
2091  hs=ov_halfrate_p(vf);
2092 
2093  ch1=vi->channels;
2094  n1=vorbis_info_blocksize(vi,0)>>(1+hs);
2095  w1=vorbis_window(&vf->vd,0);  /* window arrays from libvorbis are
2096                                   persistent; even if the decode state
2097                                   from this link gets dumped, this
2098                                   window array continues to exist */
2099
2100  lappcm=alloca(sizeof(*lappcm)*ch1);
2101  for(i=0;i<ch1;i++)
2102    lappcm[i]=alloca(sizeof(**lappcm)*n1);
2103  _ov_getlap(vf,vi,&vf->vd,lappcm,n1);
2104
2105  /* have lapping data; seek and prime the buffer */
2106  ret=localseek(vf,pos);
2107  if(ret)return ret;
2108  ret=_ov_initprime(vf);
2109  if(ret)return(ret);
2110
2111 /* Guard against cross-link changes; they're perfectly legal */
2112  vi=ov_info(vf,-1);
2113  ch2=vi->channels;
2114  n2=vorbis_info_blocksize(vi,0)>>(1+hs);
2115  w2=vorbis_window(&vf->vd,0);
2116
2117  /* consolidate and expose the buffer. */
2118  vorbis_synthesis_lapout(&vf->vd,&pcm);
2119
2120  /* splice */
2121  _ov_splice(pcm,lappcm,n1,n2,ch1,ch2,w1,w2);
2122
2123  /* done */
2124  return(0);
2125}
2126
2127int ov_raw_seek_lap(OggVorbis_File *vf,ogg_int64_t pos){
2128  return _ov_64_seek_lap(vf,pos,ov_raw_seek);
2129}
2130
2131int ov_pcm_seek_lap(OggVorbis_File *vf,ogg_int64_t pos){
2132  return _ov_64_seek_lap(vf,pos,ov_pcm_seek);
2133}
2134
2135int ov_pcm_seek_page_lap(OggVorbis_File *vf,ogg_int64_t pos){
2136  return _ov_64_seek_lap(vf,pos,ov_pcm_seek_page);
2137}
2138
2139static int _ov_d_seek_lap(OggVorbis_File *vf,double pos,
2140                           int (*localseek)(OggVorbis_File *,double)){
2141  vorbis_info *vi;
2142  float **lappcm;
2143  float **pcm;
2144  float *w1,*w2;
2145  int n1,n2,ch1,ch2,hs;
2146  int i,ret;
2147
2148  if(vf->ready_state<OPENED)return(OV_EINVAL);
2149  ret=_ov_initset(vf);
2150  if(ret)return(ret);
2151  vi=ov_info(vf,-1);
2152  hs=ov_halfrate_p(vf);
2153
2154  ch1=vi->channels;
2155  n1=vorbis_info_blocksize(vi,0)>>(1+hs);
2156  w1=vorbis_window(&vf->vd,0);  /* window arrays from libvorbis are
2157                                   persistent; even if the decode state
2158                                   from this link gets dumped, this
2159                                   window array continues to exist */
2160
2161  lappcm=alloca(sizeof(*lappcm)*ch1);
2162  for(i=0;i<ch1;i++)
2163    lappcm[i]=alloca(sizeof(**lappcm)*n1);
2164  _ov_getlap(vf,vi,&vf->vd,lappcm,n1);
2165
2166  /* have lapping data; seek and prime the buffer */
2167  ret=localseek(vf,pos);
2168  if(ret)return ret;
2169  ret=_ov_initprime(vf);
2170  if(ret)return(ret);
2171
2172 /* Guard against cross-link changes; they're perfectly legal */
2173  vi=ov_info(vf,-1);
2174  ch2=vi->channels;
2175  n2=vorbis_info_blocksize(vi,0)>>(1+hs);
2176  w2=vorbis_window(&vf->vd,0);
2177
2178  /* consolidate and expose the buffer. */
2179  vorbis_synthesis_lapout(&vf->vd,&pcm);
2180
2181  /* splice */
2182  _ov_splice(pcm,lappcm,n1,n2,ch1,ch2,w1,w2);
2183
2184  /* done */
2185  return(0);
2186}
2187
2188int ov_time_seek_lap(OggVorbis_File *vf,double pos){
2189  return _ov_d_seek_lap(vf,pos,ov_time_seek);
2190}
2191
2192int ov_time_seek_page_lap(OggVorbis_File *vf,double pos){
2193  return _ov_d_seek_lap(vf,pos,ov_time_seek_page);
2194}
Note: See TracBrowser for help on using the repository browser.