Coverage Report

Created: 2024-10-29 06:38

/src/vorbis/lib/vorbisfile.c
Line
Count
Source (jump to first uncovered 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-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
40.7k
#define CHUNKSIZE 65536 /* greater-than-page-size granularity seeking */
64
36.2k
#define READSIZE 2048 /* a smaller read size is needed for low-rate streaming. */
65
66
18.1k
static long _get_data(OggVorbis_File *vf){
67
18.1k
  errno=0;
68
18.1k
  if(!(vf->callbacks.read_func))return(-1);
69
18.1k
  if(vf->datasource){
70
18.1k
    char *buffer=ogg_sync_buffer(&vf->oy,READSIZE);
71
18.1k
    long bytes=(vf->callbacks.read_func)(buffer,1,READSIZE,vf->datasource);
72
18.1k
    if(bytes>0)ogg_sync_wrote(&vf->oy,bytes);
73
18.1k
    if(bytes==0 && errno)return(-1);
74
18.1k
    return(bytes);
75
18.1k
  }else
76
0
    return(0);
77
18.1k
}
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
72.5k
                                  ogg_int64_t boundary){
112
72.5k
  if(boundary>0)boundary+=vf->offset;
113
728k
  while(1){
114
728k
    long more;
115
116
728k
    if(boundary>0 && vf->offset>=boundary)return(OV_FALSE);
117
728k
    more=ogg_sync_pageseek(&vf->oy,og);
118
119
728k
    if(more<0){
120
      /* skipped n bytes */
121
641k
      vf->offset-=more;
122
641k
    }else{
123
87.1k
      if(more==0){
124
        /* send more paramedics */
125
18.1k
        if(!boundary)return(OV_FALSE);
126
18.1k
        {
127
18.1k
          long ret=_get_data(vf);
128
18.1k
          if(ret==0)return(OV_EOF);
129
14.6k
          if(ret<0)return(OV_EREAD);
130
14.6k
        }
131
69.0k
      }else{
132
        /* got a page.  Return the offset at the page beginning,
133
           advance the internal offset past the page end */
134
69.0k
        ogg_int64_t ret=vf->offset;
135
69.0k
        vf->offset+=more;
136
69.0k
        return(ret);
137
138
69.0k
      }
139
87.1k
    }
140
728k
  }
141
72.5k
}
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
6.40k
static void _add_serialno(ogg_page *og,long **serialno_list, int *n){
189
6.40k
  long s = ogg_page_serialno(og);
190
6.40k
  (*n)++;
191
192
6.40k
  if(*serialno_list){
193
860
    *serialno_list = _ogg_realloc(*serialno_list, sizeof(**serialno_list)*(*n));
194
5.54k
  }else{
195
5.54k
    *serialno_list = _ogg_malloc(sizeof(**serialno_list));
196
5.54k
  }
197
198
6.40k
  (*serialno_list)[(*n)-1] = s;
199
6.40k
}
200
201
/* returns nonzero if found */
202
6.40k
static int _lookup_serialno(long s, long *serialno_list, int n){
203
6.40k
  if(serialno_list){
204
7.54k
    while(n--){
205
6.68k
      if(*serialno_list == s) return 1;
206
6.67k
      serialno_list++;
207
6.67k
    }
208
865
  }
209
6.40k
  return 0;
210
6.40k
}
211
212
6.40k
static int _lookup_page_serialno(ogg_page *og, long *serialno_list, int n){
213
6.40k
  long s = ogg_page_serialno(og);
214
6.40k
  return _lookup_serialno(s,serialno_list,n);
215
6.40k
}
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
14.8k
                          ogg_page *og_ptr){
287
14.8k
  ogg_page og;
288
14.8k
  ogg_packet op;
289
14.8k
  int i,ret;
290
14.8k
  int allbos=0;
291
292
14.8k
  if(!og_ptr){
293
5.69k
    ogg_int64_t llret=_get_next_page(vf,&og,CHUNKSIZE);
294
5.69k
    if(llret==OV_EREAD)return(OV_EREAD);
295
5.69k
    if(llret<0)return(OV_ENOTVORBIS);
296
5.54k
    og_ptr=&og;
297
5.54k
  }
298
299
14.7k
  vorbis_info_init(vi);
300
14.7k
  vorbis_comment_init(vc);
301
14.7k
  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
30.7k
  while(ogg_page_bos(og_ptr)){
307
29.8k
    if(serialno_list){
308
6.40k
      if(_lookup_page_serialno(og_ptr,*serialno_list,*serialno_n)){
309
        /* a dupe serialnumber in an initial header packet set == invalid stream */
310
5
        if(*serialno_list)_ogg_free(*serialno_list);
311
5
        *serialno_list=0;
312
5
        *serialno_n=0;
313
5
        ret=OV_EBADHEADER;
314
5
        goto bail_header;
315
5
      }
316
317
6.40k
      _add_serialno(og_ptr,serialno_list,serialno_n);
318
6.40k
    }
319
320
29.8k
    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
29.5k
      ogg_stream_reset_serialno(&vf->os,ogg_page_serialno(og_ptr));
324
29.5k
      ogg_stream_pagein(&vf->os,og_ptr);
325
326
29.5k
      if(ogg_stream_packetout(&vf->os,&op) > 0 &&
327
29.5k
         vorbis_synthesis_idheader(&op)){
328
        /* vorbis header; continue setup */
329
14.2k
        vf->ready_state=STREAMSET;
330
14.2k
        if((ret=vorbis_synthesis_headerin(vi,vc,&op))){
331
113
          ret=OV_EBADHEADER;
332
113
          goto bail_header;
333
113
        }
334
14.2k
      }
335
29.5k
    }
336
337
    /* get next page */
338
29.6k
    {
339
29.6k
      ogg_int64_t llret=_get_next_page(vf,og_ptr,CHUNKSIZE);
340
29.6k
      if(llret==OV_EREAD){
341
0
        ret=OV_EREAD;
342
0
        goto bail_header;
343
0
      }
344
29.6k
      if(llret<0){
345
568
        ret=OV_ENOTVORBIS;
346
568
        goto bail_header;
347
568
      }
348
349
      /* if this page also belongs to our vorbis stream, submit it and break */
350
29.1k
      if(vf->ready_state==STREAMSET &&
351
29.1k
         vf->os.serialno == ogg_page_serialno(og_ptr)){
352
13.0k
        ogg_stream_pagein(&vf->os,og_ptr);
353
13.0k
        break;
354
13.0k
      }
355
29.1k
    }
356
29.1k
  }
357
358
14.0k
  if(vf->ready_state!=STREAMSET){
359
16
    ret = OV_ENOTVORBIS;
360
16
    goto bail_header;
361
16
  }
362
363
14.0k
  while(1){
364
365
14.0k
    i=0;
366
27.1k
    while(i<2){ /* get a page loop */
367
368
40.5k
      while(i<2){ /* get a packet loop */
369
370
28.5k
        int result=ogg_stream_packetout(&vf->os,&op);
371
28.5k
        if(result==0)break;
372
27.1k
        if(result==-1){
373
55
          ret=OV_EBADHEADER;
374
55
          goto bail_header;
375
55
        }
376
377
27.1k
        if((ret=vorbis_synthesis_headerin(vi,vc,&op)))
378
1.77k
          goto bail_header;
379
380
25.3k
        i++;
381
25.3k
      }
382
383
17.4k
      while(i<2){
384
5.39k
        if(_get_next_page(vf,og_ptr,CHUNKSIZE)<0){
385
169
          ret=OV_EBADHEADER;
386
169
          goto bail_header;
387
169
        }
388
389
        /* if this page belongs to the correct stream, go parse it */
390
5.22k
        if(vf->os.serialno == ogg_page_serialno(og_ptr)){
391
1.14k
          ogg_stream_pagein(&vf->os,og_ptr);
392
1.14k
          break;
393
1.14k
        }
394
395
        /* if we never see the final vorbis headers before the link
396
           ends, abort */
397
4.07k
        if(ogg_page_bos(og_ptr)){
398
351
          if(allbos){
399
3
            ret = OV_EBADHEADER;
400
3
            goto bail_header;
401
3
          }else
402
348
            allbos=1;
403
351
        }
404
405
        /* otherwise, keep looking */
406
4.07k
      }
407
13.3k
    }
408
409
12.0k
    return 0;
410
14.0k
  }
411
412
2.70k
 bail_header:
413
2.70k
  vorbis_info_clear(vi);
414
2.70k
  vorbis_comment_clear(vc);
415
2.70k
  vf->ready_state=OPENED;
416
417
2.70k
  return ret;
418
14.0k
}
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
12.0k
static int _make_decode_ready(OggVorbis_File *vf){
602
12.0k
  if(vf->ready_state>STREAMSET)return 0;
603
12.0k
  if(vf->ready_state<STREAMSET)return OV_EFAULT;
604
12.0k
  if(vf->seekable){
605
0
    if(vorbis_synthesis_init(&vf->vd,vf->vi+vf->current_link))
606
0
      return OV_EBADLINK;
607
12.0k
  }else{
608
12.0k
    if(vorbis_synthesis_init(&vf->vd,vf->vi))
609
205
      return OV_EBADLINK;
610
12.0k
  }
611
11.8k
  vorbis_block_init(&vf->vd,&vf->vb);
612
11.8k
  vf->ready_state=INITSET;
613
11.8k
  vf->bittrack=0.f;
614
11.8k
  vf->samptrack=0.f;
615
11.8k
  return 0;
616
12.0k
}
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
9.17k
static void _decode_clear(OggVorbis_File *vf){
662
9.17k
  vorbis_dsp_clear(&vf->vd);
663
9.17k
  vorbis_block_clear(&vf->vb);
664
9.17k
  vf->ready_state=OPENED;
665
9.17k
}
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
133k
                                     int spanp){
682
133k
  ogg_page og;
683
684
  /* handle one packet.  Try to fetch it from current stream state */
685
  /* extract packets from page */
686
161k
  while(1){
687
688
161k
    if(vf->ready_state==STREAMSET){
689
12.0k
      int ret=_make_decode_ready(vf);
690
12.0k
      if(ret<0)return ret;
691
12.0k
    }
692
693
    /* process a packet if we can. */
694
695
161k
    if(vf->ready_state==INITSET){
696
161k
      int hs=vorbis_synthesis_halfrate_p(vf->vi);
697
698
2.29M
      while(1) {
699
2.29M
              ogg_packet op;
700
2.29M
              ogg_packet *op_ptr=(op_in?op_in:&op);
701
2.29M
        int result=ogg_stream_packetout(&vf->os,op_ptr);
702
2.29M
        ogg_int64_t granulepos;
703
704
2.29M
        op_in=NULL;
705
2.29M
        if(result==-1)return(OV_HOLE); /* hole in the data. */
706
2.27M
        if(result>0){
707
          /* got a packet.  process it */
708
2.23M
          granulepos=op_ptr->granulepos;
709
2.23M
          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
106k
            {
719
106k
              int oldsamples=vorbis_synthesis_pcmout(&vf->vd,NULL);
720
              /* for proper use of libvorbis within libvorbisfile,
721
                 oldsamples will always be zero. */
722
106k
              if(oldsamples)return(OV_EFAULT);
723
724
106k
              vorbis_synthesis_blockin(&vf->vd,&vf->vb);
725
106k
              vf->samptrack+=(vorbis_synthesis_pcmout(&vf->vd,NULL)<<hs);
726
106k
              vf->bittrack+=op_ptr->bytes*8;
727
106k
            }
728
729
            /* update the pcm offset. */
730
106k
            if(granulepos!=-1 && !op_ptr->e_o_s){
731
16.3k
              int link=(vf->seekable?vf->current_link:0);
732
16.3k
              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
16.3k
              if(vf->seekable && link>0)
748
0
                granulepos-=vf->pcmlengths[link*2];
749
16.3k
              if(granulepos<0)granulepos=0; /* actually, this
750
                                               shouldn't be possible
751
                                               here unless the stream
752
                                               is very broken */
753
754
16.3k
              samples=(vorbis_synthesis_pcmout(&vf->vd,NULL)<<hs);
755
756
16.3k
              granulepos-=samples;
757
16.3k
              for(i=0;i<link;i++)
758
0
                granulepos+=vf->pcmlengths[i*2+1];
759
16.3k
              vf->pcm_offset=granulepos;
760
16.3k
            }
761
106k
            return(1);
762
106k
          }
763
2.23M
        }
764
31.1k
        else
765
31.1k
          break;
766
2.27M
      }
767
161k
    }
768
769
31.1k
    if(vf->ready_state>=OPENED){
770
31.1k
      ogg_int64_t ret;
771
772
31.7k
      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
31.7k
        if(!readp)return(0);
780
31.7k
        if((ret=_get_next_page(vf,&og,-1))<0){
781
2.63k
          return(OV_EOF); /* eof. leave unitialized */
782
2.63k
        }
783
784
        /* bitrate tracking; add the header's bytes here, the body bytes
785
           are done by packet above */
786
29.1k
        vf->bittrack+=og.header_len*8;
787
788
29.1k
        if(vf->ready_state==INITSET){
789
29.1k
          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.74k
            if(ogg_page_bos(&og)){
796
              /* boundary case */
797
9.17k
              if(!spanp)
798
0
                return(OV_EOF);
799
800
9.17k
              _decode_clear(vf);
801
802
9.17k
              if(!vf->seekable){
803
9.17k
                vorbis_info_clear(vf->vi);
804
9.17k
                vorbis_comment_clear(vf->vc);
805
9.17k
              }
806
9.17k
              break;
807
808
9.17k
            }else
809
574
              continue; /* possibility #2 */
810
9.74k
          }
811
29.1k
        }
812
813
19.3k
        break;
814
29.1k
      }
815
31.1k
    }
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.5k
    if(vf->ready_state!=INITSET){
830
9.17k
      int link;
831
832
9.17k
      if(vf->ready_state<STREAMSET){
833
9.17k
        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
9.17k
        }else{
854
          /* we're streaming */
855
          /* fetch the three header packets, build the info struct */
856
857
9.17k
          int ret=_fetch_headers(vf,vf->vi,vf->vc,NULL,NULL,&og);
858
9.17k
          if(ret)return(ret);
859
8.87k
          vf->current_serialno=vf->os.serialno;
860
8.87k
          vf->current_link++;
861
8.87k
          link=0;
862
8.87k
        }
863
9.17k
      }
864
9.17k
    }
865
866
    /* the buffered page is the data we want, and we're ready for it;
867
       add it to the stream state */
868
28.2k
    ogg_stream_pagein(&vf->os,&og);
869
870
28.2k
  }
871
133k
}
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.69k
                     long ibytes, ov_callbacks callbacks){
882
5.69k
  int offsettest=((f && callbacks.seek_func)?callbacks.seek_func(f,0,SEEK_CUR):-1);
883
5.69k
  long *serialno_list=NULL;
884
5.69k
  int serialno_list_size=0;
885
5.69k
  int ret;
886
887
5.69k
  memset(vf,0,sizeof(*vf));
888
5.69k
  vf->datasource=f;
889
5.69k
  vf->callbacks = callbacks;
890
891
  /* init the framing state */
892
5.69k
  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.69k
  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.69k
  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.69k
  vf->links=1;
910
5.69k
  vf->vi=_ogg_calloc(vf->links,sizeof(*vf->vi));
911
5.69k
  vf->vc=_ogg_calloc(vf->links,sizeof(*vf->vc));
912
5.69k
  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.69k
  if((ret=_fetch_headers(vf,vf->vi,vf->vc,&serialno_list,&serialno_list_size,NULL))<0){
917
2.54k
    vf->datasource=NULL;
918
2.54k
    ov_clear(vf);
919
3.14k
  }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
3.14k
    vf->serialnos=_ogg_calloc(serialno_list_size+2,sizeof(*vf->serialnos));
924
3.14k
    vf->serialnos[0]=vf->current_serialno=vf->os.serialno;
925
3.14k
    vf->serialnos[1]=serialno_list_size;
926
3.14k
    memcpy(vf->serialnos+2,serialno_list,serialno_list_size*sizeof(*vf->serialnos));
927
928
3.14k
    vf->offsets=_ogg_calloc(1,sizeof(*vf->offsets));
929
3.14k
    vf->dataoffsets=_ogg_calloc(1,sizeof(*vf->dataoffsets));
930
3.14k
    vf->offsets[0]=0;
931
3.14k
    vf->dataoffsets[0]=vf->offset;
932
933
3.14k
    vf->ready_state=PARTOPEN;
934
3.14k
  }
935
5.69k
  if(serialno_list)_ogg_free(serialno_list);
936
5.69k
  return(ret);
937
5.69k
}
938
939
3.14k
static int _ov_open2(OggVorbis_File *vf){
940
3.14k
  if(vf->ready_state != PARTOPEN) return OV_EINVAL;
941
3.14k
  vf->ready_state=OPENED;
942
3.14k
  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
3.14k
    vf->ready_state=STREAMSET;
951
952
3.14k
  return 0;
953
3.14k
}
954
955
956
/* clear out the OggVorbis_File struct */
957
5.69k
int ov_clear(OggVorbis_File *vf){
958
5.69k
  if(vf){
959
5.69k
    vorbis_block_clear(&vf->vb);
960
5.69k
    vorbis_dsp_clear(&vf->vd);
961
5.69k
    ogg_stream_clear(&vf->os);
962
963
5.69k
    if(vf->vi && vf->links){
964
5.69k
      int i;
965
11.3k
      for(i=0;i<vf->links;i++){
966
5.69k
        vorbis_info_clear(vf->vi+i);
967
5.69k
        vorbis_comment_clear(vf->vc+i);
968
5.69k
      }
969
5.69k
      _ogg_free(vf->vi);
970
5.69k
      _ogg_free(vf->vc);
971
5.69k
    }
972
5.69k
    if(vf->dataoffsets)_ogg_free(vf->dataoffsets);
973
5.69k
    if(vf->pcmlengths)_ogg_free(vf->pcmlengths);
974
5.69k
    if(vf->serialnos)_ogg_free(vf->serialnos);
975
5.69k
    if(vf->offsets)_ogg_free(vf->offsets);
976
5.69k
    ogg_sync_clear(&vf->oy);
977
5.69k
    if(vf->datasource && vf->callbacks.close_func)
978
0
      (vf->callbacks.close_func)(vf->datasource);
979
5.69k
    memset(vf,0,sizeof(*vf));
980
5.69k
  }
981
#ifdef DEBUG_LEAKS
982
  _VDBG_dump();
983
#endif
984
5.69k
  return(0);
985
5.69k
}
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.69k
    const char *initial,long ibytes,ov_callbacks callbacks){
997
5.69k
  int ret=_ov_open1(f,vf,initial,ibytes,callbacks);
998
5.69k
  if(ret)return ret;
999
3.14k
  return _ov_open2(vf);
1000
5.69k
}
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
721k
vorbis_info *ov_info(OggVorbis_File *vf,int link){
1879
721k
  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
721k
  }else{
1891
721k
    return vf->vi;
1892
721k
  }
1893
721k
}
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
748k
static int host_is_big_endian() {
1914
748k
  ogg_int32_t pattern = 0xfeedface; /* deadbeef */
1915
748k
  unsigned char *bytewise = (unsigned char *)&pattern;
1916
748k
  if (bytewise[0] == 0xfe) return 1;
1917
748k
  return 0;
1918
748k
}
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
748k
                    void (*filter)(float **pcm,long channels,long samples,void *filter_param),void *filter_param){
1959
748k
  int i,j;
1960
748k
  int host_endian = host_is_big_endian();
1961
748k
  int hs;
1962
1963
748k
  float **pcm;
1964
748k
  long samples;
1965
1966
748k
  if(vf->ready_state<OPENED)return(OV_EINVAL);
1967
748k
  if(word<=0)return(OV_EINVAL);
1968
1969
855k
  while(1){
1970
855k
    if(vf->ready_state==INITSET){
1971
852k
      samples=vorbis_synthesis_pcmout(&vf->vd,&pcm);
1972
852k
      if(samples)break;
1973
852k
    }
1974
1975
    /* suck in another packet */
1976
133k
    {
1977
133k
      int ret=_fetch_and_process_packet(vf,NULL,1,1);
1978
133k
      if(ret==OV_EOF)
1979
2.63k
        return(0);
1980
130k
      if(ret<=0)
1981
24.2k
        return(ret);
1982
130k
    }
1983
1984
130k
  }
1985
1986
721k
  if(samples>0){
1987
1988
    /* yay! proceed to pack data into the byte buffer */
1989
1990
721k
    long channels=ov_info(vf,-1)->channels;
1991
721k
    long bytespersample=word * channels;
1992
721k
    vorbis_fpu_control fpu;
1993
1994
721k
    if(channels<1||channels>255)return(OV_EINVAL);
1995
721k
    if(samples>length/bytespersample)samples=length/bytespersample;
1996
1997
721k
    if(samples <= 0)
1998
0
      return OV_EINVAL;
1999
2000
    /* Here. */
2001
721k
    if(filter)
2002
0
      filter(pcm,channels,samples,filter_param);
2003
2004
    /* a tight loop to pack each size */
2005
721k
    {
2006
721k
      int val;
2007
721k
      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
721k
      }else{
2019
721k
        int off=(sgned?0:32768);
2020
2021
721k
        if(host_endian==bigendianp){
2022
721k
          if(sgned){
2023
2024
721k
            vorbis_fpu_setround(&fpu);
2025
122M
            for(i=0;i<channels;i++) { /* It's faster in this order */
2026
121M
              float *src=pcm[i];
2027
121M
              short *dest=((short *)buffer)+i;
2028
1.40G
              for(j=0;j<samples;j++) {
2029
1.27G
                val=vorbis_ftoi(src[j]*32768.f);
2030
1.27G
                if(val>32767)val=32767;
2031
1.27G
                else if(val<-32768)val=-32768;
2032
1.27G
                *dest=val;
2033
1.27G
                dest+=channels;
2034
1.27G
              }
2035
121M
            }
2036
721k
            vorbis_fpu_restore(fpu);
2037
2038
721k
          }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
721k
        }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
721k
      }
2085
721k
    }
2086
2087
721k
    vorbis_synthesis_read(&vf->vd,samples);
2088
721k
    hs=vorbis_synthesis_halfrate_p(vf->vi);
2089
721k
    vf->pcm_offset+=(samples<<hs);
2090
721k
    if(bitstream)*bitstream=vf->current_link;
2091
721k
    return(samples*bytespersample);
2092
721k
  }else{
2093
0
    return(samples);
2094
0
  }
2095
721k
}
2096
2097
long ov_read(OggVorbis_File *vf,char *buffer,int length,
2098
748k
             int bigendianp,int word,int sgned,int *bitstream){
2099
748k
  return ov_read_filter(vf, buffer, length, bigendianp, word, sgned, bitstream, NULL, NULL);
2100
748k
}
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
}