Coverage Report

Created: 2025-11-16 06:59

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