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#define CHUNKSIZE 65536 /* greater-than-page-size granularity seeking */
64#define READSIZE 2048 /* a smaller read size is needed for low-rate streaming. */
65
66static long _get_data(OggVorbis_File *vf){
67 errno=0;
68 if(!(vf->callbacks.read_func))return(-1);
69 if(vf->datasource){
70 char *buffer=ogg_sync_buffer(&vf->oy,READSIZE);
71 long bytes=(vf->callbacks.read_func)(buffer,1,READSIZE,vf->datasource);
72 if(bytes>0)ogg_sync_wrote(&vf->oy,bytes);
73 if(bytes==0 && errno)return(-1);
74 return(bytes);
75 }else
76 return(0);
77}
78
79/* save a tiny smidge of verbosity to make the code more readable */
80static int _seek_helper(OggVorbis_File *vf,ogg_int64_t offset){
81 if(vf->datasource){
82 /* only seek if the file position isn't already there */
83 if(vf->offset != offset){
84 if(!(vf->callbacks.seek_func)||
85 (vf->callbacks.seek_func)(vf->datasource, offset, SEEK_SET) == -1)
86 return OV_EREAD;
87 vf->offset=offset;
88 ogg_sync_reset(&vf->oy);
89 }
90 }else{
91 /* shouldn't happen unless someone writes a broken callback */
92 return OV_EFAULT;
93 }
94 return 0;
95}
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
110static ogg_int64_t _get_next_page(OggVorbis_File *vf,ogg_page *og,
111 ogg_int64_t boundary){
112 if(boundary>0)boundary+=vf->offset;
113 while(1){
114 long more;
115
116 if(boundary>0 && vf->offset>=boundary)return(OV_FALSE);
117 more=ogg_sync_pageseek(&vf->oy,og);
118
119 if(more<0){
120 /* skipped n bytes */
121 vf->offset-=more;
122 }else{
123 if(more==0){
124 /* send more paramedics */
125 if(!boundary)return(OV_FALSE);
126 {
127 long ret=_get_data(vf);
128 if(ret==0)return(OV_EOF);
129 if(ret<0)return(OV_EREAD);
130 }
131 }else{
132 /* got a page. Return the offset at the page beginning,
133 advance the internal offset past the page end */
134 ogg_int64_t ret=vf->offset;
135 vf->offset+=more;
136 return(ret);
137
138 }
139 }
140 }
141}
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 */
147static ogg_int64_t _get_prev_page(OggVorbis_File *vf,ogg_int64_t begin,ogg_page *og){
148 ogg_int64_t end = begin;
149 ogg_int64_t ret;
150 ogg_int64_t offset=-1;
151
152 while(offset==-1){
153 begin-=CHUNKSIZE;
154 if(begin<0)
155 begin=0;
156
157 ret=_seek_helper(vf,begin);
158 if(ret)return(ret);
159
160 while(vf->offset<end){
161 memset(og,0,sizeof(*og));
162 ret=_get_next_page(vf,og,end-vf->offset);
163 if(ret==OV_EREAD)return(OV_EREAD);
164 if(ret<0){
165 break;
166 }else{
167 offset=ret;
168 }
169 }
170 }
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 if(og->header_len==0){
176 ret=_seek_helper(vf,offset);
177 if(ret)return(ret);
178
179 ret=_get_next_page(vf,og,CHUNKSIZE);
180 if(ret<0)
181 /* this shouldn't be possible */
182 return(OV_EFAULT);
183 }
184
185 return(offset);
186}
187
188static void _add_serialno(ogg_page *og,long **serialno_list, int *n){
189 long s = ogg_page_serialno(og);
190 (*n)++;
191
192 if(*serialno_list){
193 *serialno_list = _ogg_realloc(*serialno_list, sizeof(**serialno_list)*(*n));
194 }else{
195 *serialno_list = _ogg_malloc(sizeof(**serialno_list));
196 }
197
198 (*serialno_list)[(*n)-1] = s;
199}
200
201/* returns nonzero if found */
202static int _lookup_serialno(long s, long *serialno_list, int n){
203 if(serialno_list){
204 while(n--){
205 if(*serialno_list == s) return 1;
206 serialno_list++;
207 }
208 }
209 return 0;
210}
211
212static int _lookup_page_serialno(ogg_page *og, long *serialno_list, int n){
213 long s = ogg_page_serialno(og);
214 return _lookup_serialno(s,serialno_list,n);
215}
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. */
223static ogg_int64_t _get_prev_page_serial(OggVorbis_File *vf, ogg_int64_t begin,
224 long *serial_list, int serial_n,
225 int *serialno, ogg_int64_t *granpos){
226 ogg_page og;
227 ogg_int64_t end=begin;
228 ogg_int64_t ret;
229
230 ogg_int64_t prefoffset=-1;
231 ogg_int64_t offset=-1;
232 ogg_int64_t ret_serialno=-1;
233 ogg_int64_t ret_gran=-1;
234
235 while(offset==-1){
236 begin-=CHUNKSIZE;
237 if(begin<0)
238 begin=0;
239
240 ret=_seek_helper(vf,begin);
241 if(ret)return(ret);
242
243 while(vf->offset<end){
244 ret=_get_next_page(vf,&og,end-vf->offset);
245 if(ret==OV_EREAD)return(OV_EREAD);
246 if(ret<0){
247 break;
248 }else{
249 ret_serialno=ogg_page_serialno(&og);
250 ret_gran=ogg_page_granulepos(&og);
251 offset=ret;
252
253 if(ret_serialno == *serialno){
254 prefoffset=ret;
255 *granpos=ret_gran;
256 }
257
258 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 prefoffset=-1;
264 }
265 }
266 }
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 if(!begin&&vf->offset<0)return OV_EBADLINK;
271 }
272
273 /* we're not interested in the page... just the serialno and granpos. */
274 if(prefoffset>=0)return(prefoffset);
275
276 *serialno = ret_serialno;
277 *granpos = ret_gran;
278 return(offset);
279
280}
281
282/* uses the local ogg_stream storage in vf; this is important for
283 non-streaming input sources */
284static int _fetch_headers(OggVorbis_File *vf,vorbis_info *vi,vorbis_comment *vc,
285 long **serialno_list, int *serialno_n,
286 ogg_page *og_ptr){
287 ogg_page og;
288 ogg_packet op;
289 int i,ret;
290 int allbos=0;
291
292 if(!og_ptr){
293 ogg_int64_t llret=_get_next_page(vf,&og,CHUNKSIZE);
294 if(llret==OV_EREAD)return(OV_EREAD);
295 if(llret<0)return(OV_ENOTVORBIS);
296 og_ptr=&og;
297 }
298
299 vorbis_info_init(vi);
300 vorbis_comment_init(vc);
301 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 while(ogg_page_bos(og_ptr)){
307 if(serialno_list){
308 if(_lookup_page_serialno(og_ptr,*serialno_list,*serialno_n)){
309 /* a dupe serialnumber in an initial header packet set == invalid stream */
310 if(*serialno_list)_ogg_free(*serialno_list);
311 *serialno_list=0;
312 *serialno_n=0;
313 ret=OV_EBADHEADER;
314 goto bail_header;
315 }
316
317 _add_serialno(og_ptr,serialno_list,serialno_n);
318 }
319
320 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 ogg_stream_reset_serialno(&vf->os,ogg_page_serialno(og_ptr));
324 ogg_stream_pagein(&vf->os,og_ptr);
325
326 if(ogg_stream_packetout(&vf->os,&op) > 0 &&
327 vorbis_synthesis_idheader(&op)){
328 /* vorbis header; continue setup */
329 vf->ready_state=STREAMSET;
330 if((ret=vorbis_synthesis_headerin(vi,vc,&op))){
331 ret=OV_EBADHEADER;
332 goto bail_header;
333 }
334 }
335 }
336
337 /* get next page */
338 {
339 ogg_int64_t llret=_get_next_page(vf,og_ptr,CHUNKSIZE);
340 if(llret==OV_EREAD){
341 ret=OV_EREAD;
342 goto bail_header;
343 }
344 if(llret<0){
345 ret=OV_ENOTVORBIS;
346 goto bail_header;
347 }
348
349 /* if this page also belongs to our vorbis stream, submit it and break */
350 if(vf->ready_state==STREAMSET &&
351 vf->os.serialno == ogg_page_serialno(og_ptr)){
352 ogg_stream_pagein(&vf->os,og_ptr);
353 break;
354 }
355 }
356 }
357
358 if(vf->ready_state!=STREAMSET){
359 ret = OV_ENOTVORBIS;
360 goto bail_header;
361 }
362
363 while(1){
364
365 i=0;
366 while(i<2){ /* get a page loop */
367
368 while(i<2){ /* get a packet loop */
369
370 int result=ogg_stream_packetout(&vf->os,&op);
371 if(result==0)break;
372 if(result==-1){
373 ret=OV_EBADHEADER;
374 goto bail_header;
375 }
376
377 if((ret=vorbis_synthesis_headerin(vi,vc,&op)))
378 goto bail_header;
379
380 i++;
381 }
382
383 while(i<2){
384 if(_get_next_page(vf,og_ptr,CHUNKSIZE)<0){
385 ret=OV_EBADHEADER;
386 goto bail_header;
387 }
388
389 /* if this page belongs to the correct stream, go parse it */
390 if(vf->os.serialno == ogg_page_serialno(og_ptr)){
391 ogg_stream_pagein(&vf->os,og_ptr);
392 break;
393 }
394
395 /* if we never see the final vorbis headers before the link
396 ends, abort */
397 if(ogg_page_bos(og_ptr)){
398 if(allbos){
399 ret = OV_EBADHEADER;
400 goto bail_header;
401 }else
402 allbos=1;
403 }
404
405 /* otherwise, keep looking */
406 }
407 }
408
409 return 0;
410 }
411
412 bail_header:
413 vorbis_info_clear(vi);
414 vorbis_comment_clear(vc);
415 vf->ready_state=OPENED;
416
417 return ret;
418}
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. */
424static ogg_int64_t _initial_pcmoffset(OggVorbis_File *vf, vorbis_info *vi){
425 ogg_page og;
426 ogg_int64_t accumulated=0;
427 long lastblock=-1;
428 int result;
429 int serialno = vf->os.serialno;
430
431 while(1){
432 ogg_packet op;
433 if(_get_next_page(vf,&og,-1)<0)
434 break; /* should not be possible unless the file is truncated/mangled */
435
436 if(ogg_page_bos(&og)) break;
437 if(ogg_page_serialno(&og)!=serialno) continue;
438
439 /* count blocksizes of all frames in the page */
440 ogg_stream_pagein(&vf->os,&og);
441 while((result=ogg_stream_packetout(&vf->os,&op))){
442 if(result>0){ /* ignore holes */
443 long thisblock=vorbis_packet_blocksize(vi,&op);
444 if(thisblock>=0){
445 if(lastblock!=-1)
446 accumulated+=(lastblock+thisblock)>>2;
447 lastblock=thisblock;
448 }
449 }
450 }
451
452 if(ogg_page_granulepos(&og)!=-1){
453 /* pcm offset of last packet on the first audio page */
454 accumulated= ogg_page_granulepos(&og)-accumulated;
455 break;
456 }
457 }
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 if(accumulated<0)accumulated=0;
463
464 return accumulated;
465}
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 */
471static 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 long m){
480 ogg_int64_t pcmoffset;
481 ogg_int64_t dataoffset=searched;
482 ogg_int64_t endsearched=end;
483 ogg_int64_t next=end;
484 ogg_int64_t searchgran=-1;
485 ogg_page og;
486 ogg_int64_t ret,last;
487 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 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 searched = end;
503 while(endserial != serialno){
504 endserial = serialno;
505 searched=_get_prev_page_serial(vf,searched,currentno_list,currentnos,&endserial,&endgran);
506 }
507
508 vf->links=m+1;
509 if(vf->offsets)_ogg_free(vf->offsets);
510 if(vf->serialnos)_ogg_free(vf->serialnos);
511 if(vf->dataoffsets)_ogg_free(vf->dataoffsets);
512
513 vf->offsets=_ogg_malloc((vf->links+1)*sizeof(*vf->offsets));
514 vf->vi=_ogg_realloc(vf->vi,vf->links*sizeof(*vf->vi));
515 vf->vc=_ogg_realloc(vf->vc,vf->links*sizeof(*vf->vc));
516 vf->serialnos=_ogg_malloc(vf->links*sizeof(*vf->serialnos));
517 vf->dataoffsets=_ogg_malloc(vf->links*sizeof(*vf->dataoffsets));
518 vf->pcmlengths=_ogg_malloc(vf->links*2*sizeof(*vf->pcmlengths));
519
520 vf->offsets[m+1]=end;
521 vf->offsets[m]=begin;
522 vf->pcmlengths[m*2+1]=(endgran<0?0:endgran);
523
524 }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 long *next_serialno_list=NULL;
531 int next_serialnos=0;
532 vorbis_info vi;
533 vorbis_comment vc;
534 int testserial = serialno+1;
535
536 /* the below guards against garbage seperating the last and
537 first pages of two links. */
538 while(searched<endsearched){
539 ogg_int64_t bisect;
540
541 if(endsearched-searched<CHUNKSIZE){
542 bisect=searched;
543 }else{
544 bisect=(searched+endsearched)/2;
545 }
546
547 ret=_seek_helper(vf,bisect);
548 if(ret)return(ret);
549
550 last=_get_next_page(vf,&og,-1);
551 if(last==OV_EREAD)return(OV_EREAD);
552 if(last<0 || !_lookup_page_serialno(&og,currentno_list,currentnos)){
553 endsearched=bisect;
554 if(last>=0)next=last;
555 }else{
556 searched=vf->offset;
557 }
558 }
559
560 /* Bisection point found */
561 /* for the time being, fetch end PCM offset the simple way */
562 searched = next;
563 while(testserial != serialno){
564 testserial = serialno;
565 searched = _get_prev_page_serial(vf,searched,currentno_list,currentnos,&testserial,&searchgran);
566 }
567
568 ret=_seek_helper(vf,next);
569 if(ret)return(ret);
570
571 ret=_fetch_headers(vf,&vi,&vc,&next_serialno_list,&next_serialnos,NULL);
572 if(ret)return(ret);
573 serialno = vf->os.serialno;
574 dataoffset = vf->offset;
575
576 /* this will consume a page, however the next bisection always
577 starts with a raw seek */
578 pcmoffset = _initial_pcmoffset(vf,&vi);
579
580 ret=_bisect_forward_serialno(vf,next,vf->offset,end,endgran,endserial,
581 next_serialno_list,next_serialnos,m+1);
582 if(ret)return(ret);
583
584 if(next_serialno_list)_ogg_free(next_serialno_list);
585
586 vf->offsets[m+1]=next;
587 vf->serialnos[m+1]=serialno;
588 vf->dataoffsets[m+1]=dataoffset;
589
590 vf->vi[m+1]=vi;
591 vf->vc[m+1]=vc;
592
593 vf->pcmlengths[m*2+1]=searchgran;
594 vf->pcmlengths[m*2+2]=pcmoffset;
595 vf->pcmlengths[m*2+3]-=pcmoffset;
596 if(vf->pcmlengths[m*2+3]<0)vf->pcmlengths[m*2+3]=0;
597 }
598 return(0);
599}
600
601static int _make_decode_ready(OggVorbis_File *vf){
602 if(vf->ready_state>STREAMSET)return 0;
603 if(vf->ready_state<STREAMSET)return OV_EFAULT;
604 if(vf->seekable){
605 if(vorbis_synthesis_init(&vf->vd,vf->vi+vf->current_link))
606 return OV_EBADLINK;
607 }else{
608 if(vorbis_synthesis_init(&vf->vd,vf->vi))
609 return OV_EBADLINK;
610 }
611 vorbis_block_init(&vf->vd,&vf->vb);
612 vf->ready_state=INITSET;
613 vf->bittrack=0.f;
614 vf->samptrack=0.f;
615 return 0;
616}
617
618static int _open_seekable2(OggVorbis_File *vf){
619 ogg_int64_t dataoffset=vf->dataoffsets[0],end,endgran=-1;
620 int endserial=vf->os.serialno;
621 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 ogg_int64_t pcmoffset = _initial_pcmoffset(vf,vf->vi);
628
629 /* we can seek, so set out learning all about this file */
630 if(vf->callbacks.seek_func && vf->callbacks.tell_func){
631 (vf->callbacks.seek_func)(vf->datasource,0,SEEK_END);
632 vf->offset=vf->end=(vf->callbacks.tell_func)(vf->datasource);
633 }else{
634 vf->offset=vf->end=-1;
635 }
636
637 /* If seek_func is implemented, tell_func must also be implemented */
638 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 end=_get_prev_page_serial(vf,vf->end,vf->serialnos+2,vf->serialnos[1],&endserial,&endgran);
644 if(end<0)return(end);
645
646 /* now determine bitstream structure recursively */
647 if(_bisect_forward_serialno(vf,0,dataoffset,end,endgran,endserial,
648 vf->serialnos+2,vf->serialnos[1],0)<0)return(OV_EREAD);
649
650 vf->offsets[0]=0;
651 vf->serialnos[0]=serialno;
652 vf->dataoffsets[0]=dataoffset;
653 vf->pcmlengths[0]=pcmoffset;
654 vf->pcmlengths[1]-=pcmoffset;
655 if(vf->pcmlengths[1]<0)vf->pcmlengths[1]=0;
656
657 return(ov_raw_seek(vf,dataoffset));
658}
659
660/* clear out the current logical bitstream decoder */
661static void _decode_clear(OggVorbis_File *vf){
662 vorbis_dsp_clear(&vf->vd);
663 vorbis_block_clear(&vf->vb);
664 vf->ready_state=OPENED;
665}
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
678static int _fetch_and_process_packet(OggVorbis_File *vf,
679 ogg_packet *op_in,
680 int readp,
681 int spanp){
682 ogg_page og;
683
684 /* handle one packet. Try to fetch it from current stream state */
685 /* extract packets from page */
686 while(1){
687
688 if(vf->ready_state==STREAMSET){
689 int ret=_make_decode_ready(vf);
690 if(ret<0)return ret;
691 }
692
693 /* process a packet if we can. */
694
695 if(vf->ready_state==INITSET){
696 int hs=vorbis_synthesis_halfrate_p(vf->vi);
697
698 while(1) {
699 ogg_packet op;
700 ogg_packet *op_ptr=(op_in?op_in:&op);
701 int result=ogg_stream_packetout(&vf->os,op_ptr);
702 ogg_int64_t granulepos;
703
704 op_in=NULL;
705 if(result==-1)return(OV_HOLE); /* hole in the data. */
706 if(result>0){
707 /* got a packet. process it */
708 granulepos=op_ptr->granulepos;
709 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 {
719 int oldsamples=vorbis_synthesis_pcmout(&vf->vd,NULL);
720 /* for proper use of libvorbis within libvorbisfile,
721 oldsamples will always be zero. */
722 if(oldsamples)return(OV_EFAULT);
723
724 vorbis_synthesis_blockin(&vf->vd,&vf->vb);
725 vf->samptrack+=(vorbis_synthesis_pcmout(&vf->vd,NULL)<<hs);
726 vf->bittrack+=op_ptr->bytes*8;
727 }
728
729 /* update the pcm offset. */
730 if(granulepos!=-1 && !op_ptr->e_o_s){
731 int link=(vf->seekable?vf->current_link:0);
732 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 if(vf->seekable && link>0)
748 granulepos-=vf->pcmlengths[link*2];
749 if(granulepos<0)granulepos=0; /* actually, this
750 shouldn't be possible
751 here unless the stream
752 is very broken */
753
754 samples=(vorbis_synthesis_pcmout(&vf->vd,NULL)<<hs);
755
756 granulepos-=samples;
757 for(i=0;i<link;i++)
758 granulepos+=vf->pcmlengths[i*2+1];
759 vf->pcm_offset=granulepos;
760 }
761 return(1);
762 }
763 }
764 else
765 break;
766 }
767 }
768
769 if(vf->ready_state>=OPENED){
770 ogg_int64_t ret;
771
772 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 if(!readp)return(0);
780 if((ret=_get_next_page(vf,&og,-1))<0){
781 return(OV_EOF); /* eof. leave unitialized */
782 }
783
784 /* bitrate tracking; add the header's bytes here, the body bytes
785 are done by packet above */
786 vf->bittrack+=og.header_len*8;
787
788 if(vf->ready_state==INITSET){
789 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 if(ogg_page_bos(&og)){
796 /* boundary case */
797 if(!spanp)
798 return(OV_EOF);
799
800 _decode_clear(vf);
801
802 if(!vf->seekable){
803 vorbis_info_clear(vf->vi);
804 vorbis_comment_clear(vf->vc);
805 }
806 break;
807
808 }else
809 continue; /* possibility #2 */
810 }
811 }
812
813 break;
814 }
815 }
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 if(vf->ready_state!=INITSET){
830 int link;
831
832 if(vf->ready_state<STREAMSET){
833 if(vf->seekable){
834 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 for(link=0;link<vf->links;link++)
841 if(vf->serialnos[link]==serialno)break;
842
843 if(link==vf->links) continue; /* not the desired Vorbis
844 bitstream section; keep
845 trying */
846
847 vf->current_serialno=serialno;
848 vf->current_link=link;
849
850 ogg_stream_reset_serialno(&vf->os,vf->current_serialno);
851 vf->ready_state=STREAMSET;
852
853 }else{
854 /* we're streaming */
855 /* fetch the three header packets, build the info struct */
856
857 int ret=_fetch_headers(vf,vf->vi,vf->vc,NULL,NULL,&og);
858 if(ret)return(ret);
859 vf->current_serialno=vf->os.serialno;
860 vf->current_link++;
861 link=0;
862 }
863 }
864 }
865
866 /* the buffered page is the data we want, and we're ready for it;
867 add it to the stream state */
868 ogg_stream_pagein(&vf->os,&og);
869
870 }
871}
872
873/* if, eg, 64 bit stdio is configured by default, this will build with
874 fseek64 */
875static int _fseek64_wrap(FILE *f,ogg_int64_t off,int whence){
876 if(f==NULL)return(-1);
877 return fseek(f,off,whence);
878}
879
880static int _ov_open1(void *f,OggVorbis_File *vf,const char *initial,
881 long ibytes, ov_callbacks callbacks){
882 int offsettest=((f && callbacks.seek_func)?callbacks.seek_func(f,0,SEEK_CUR):-1);
883 long *serialno_list=NULL;
884 int serialno_list_size=0;
885 int ret;
886
887 memset(vf,0,sizeof(*vf));
888 vf->datasource=f;
889 vf->callbacks = callbacks;
890
891 /* init the framing state */
892 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 if(initial){
899 char *buffer=ogg_sync_buffer(&vf->oy,ibytes);
900 memcpy(buffer,initial,ibytes);
901 ogg_sync_wrote(&vf->oy,ibytes);
902 }
903
904 /* can we seek? Stevens suggests the seek test was portable */
905 if(offsettest!=-1)vf->seekable=1;
906
907 /* No seeking yet; Set up a 'single' (current) logical bitstream
908 entry for partial open */
909 vf->links=1;
910 vf->vi=_ogg_calloc(vf->links,sizeof(*vf->vi));
911 vf->vc=_ogg_calloc(vf->links,sizeof(*vf->vc));
912 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 if((ret=_fetch_headers(vf,vf->vi,vf->vc,&serialno_list,&serialno_list_size,NULL))<0){
917 vf->datasource=NULL;
918 ov_clear(vf);
919 }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 vf->serialnos=_ogg_calloc(serialno_list_size+2,sizeof(*vf->serialnos));
924 vf->serialnos[0]=vf->current_serialno=vf->os.serialno;
925 vf->serialnos[1]=serialno_list_size;
926 memcpy(vf->serialnos+2,serialno_list,serialno_list_size*sizeof(*vf->serialnos));
927
928 vf->offsets=_ogg_calloc(1,sizeof(*vf->offsets));
929 vf->dataoffsets=_ogg_calloc(1,sizeof(*vf->dataoffsets));
930 vf->offsets[0]=0;
931 vf->dataoffsets[0]=vf->offset;
932
933 vf->ready_state=PARTOPEN;
934 }
935 if(serialno_list)_ogg_free(serialno_list);
936 return(ret);
937}
938
939static int _ov_open2(OggVorbis_File *vf){
940 if(vf->ready_state != PARTOPEN) return OV_EINVAL;
941 vf->ready_state=OPENED;
942 if(vf->seekable){
943 int ret=_open_seekable2(vf);
944 if(ret){
945 vf->datasource=NULL;
946 ov_clear(vf);
947 }
948 return(ret);
949 }else
950 vf->ready_state=STREAMSET;
951
952 return 0;
953}
954
955
956/* clear out the OggVorbis_File struct */
957int ov_clear(OggVorbis_File *vf){
958 if(vf){
959 vorbis_block_clear(&vf->vb);
960 vorbis_dsp_clear(&vf->vd);
961 ogg_stream_clear(&vf->os);
962
963 if(vf->vi && vf->links){
964 int i;
965 for(i=0;i<vf->links;i++){
966 vorbis_info_clear(vf->vi+i);
967 vorbis_comment_clear(vf->vc+i);
968 }
969 _ogg_free(vf->vi);
970 _ogg_free(vf->vc);
971 }
972 if(vf->dataoffsets)_ogg_free(vf->dataoffsets);
973 if(vf->pcmlengths)_ogg_free(vf->pcmlengths);
974 if(vf->serialnos)_ogg_free(vf->serialnos);
975 if(vf->offsets)_ogg_free(vf->offsets);
976 ogg_sync_clear(&vf->oy);
977 if(vf->datasource && vf->callbacks.close_func)
978 (vf->callbacks.close_func)(vf->datasource);
979 memset(vf,0,sizeof(*vf));
980 }
981#ifdef DEBUG_LEAKS
982 _VDBG_dump();
983#endif
984 return(0);
985}
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
995int ov_open_callbacks(void *f,OggVorbis_File *vf,
996 const char *initial,long ibytes,ov_callbacks callbacks){
997 int ret=_ov_open1(f,vf,initial,ibytes,callbacks);
998 if(ret)return ret;
999 return _ov_open2(vf);
1000}
1001
1002int ov_open(FILE *f,OggVorbis_File *vf,const char *initial,long ibytes){
1003 ov_callbacks callbacks = {
1004 (size_t (*)(void *, size_t, size_t, void *)) fread,
1005 (int (*)(void *, ogg_int64_t, int)) _fseek64_wrap,
1006 (int (*)(void *)) fclose,
1007 (long (*)(void *)) ftell
1008 };
1009
1010 return ov_open_callbacks((void *)f, vf, initial, ibytes, callbacks);
1011}
1012
1013int ov_fopen(const char *path,OggVorbis_File *vf){
1014 int ret;
1015 FILE *f = fopen(path,"rb");
1016 if(!f) return -1;
1017
1018 ret = ov_open(f,vf,NULL,0);
1019 if(ret) fclose(f);
1020 return ret;
1021}
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
1027int ov_halfrate(OggVorbis_File *vf,int flag){
1028 int i;
1029 if(vf->vi==NULL)return OV_EINVAL;
1030 if(vf->ready_state>STREAMSET){
1031 /* clear out stream state; dumping the decode machine is needed to
1032 reinit the MDCT lookups. */
1033 vorbis_dsp_clear(&vf->vd);
1034 vorbis_block_clear(&vf->vb);
1035 vf->ready_state=STREAMSET;
1036 if(vf->pcm_offset>=0){
1037 ogg_int64_t pos=vf->pcm_offset;
1038 vf->pcm_offset=-1; /* make sure the pos is dumped if unseekable */
1039 ov_pcm_seek(vf,pos);
1040 }
1041 }
1042
1043 for(i=0;i<vf->links;i++){
1044 if(vorbis_synthesis_halfrate(vf->vi+i,flag)){
1045 if(flag) ov_halfrate(vf,0);
1046 return OV_EINVAL;
1047 }
1048 }
1049 return 0;
1050}
1051
1052int ov_halfrate_p(OggVorbis_File *vf){
1053 if(vf->vi==NULL)return OV_EINVAL;
1054 return vorbis_synthesis_halfrate_p(vf->vi);
1055}
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
1066int ov_test_callbacks(void *f,OggVorbis_File *vf,
1067 const char *initial,long ibytes,ov_callbacks callbacks)
1068{
1069 return _ov_open1(f,vf,initial,ibytes,callbacks);
1070}
1071
1072int ov_test(FILE *f,OggVorbis_File *vf,const char *initial,long ibytes){
1073 ov_callbacks callbacks = {
1074 (size_t (*)(void *, size_t, size_t, void *)) fread,
1075 (int (*)(void *, ogg_int64_t, int)) _fseek64_wrap,
1076 (int (*)(void *)) fclose,
1077 (long (*)(void *)) ftell
1078 };
1079
1080 return ov_test_callbacks((void *)f, vf, initial, ibytes, callbacks);
1081}
1082
1083int ov_test_open(OggVorbis_File *vf){
1084 if(vf->ready_state!=PARTOPEN)return(OV_EINVAL);
1085 return _ov_open2(vf);
1086}
1087
1088/* How many logical bitstreams in this physical bitstream? */
1089long ov_streams(OggVorbis_File *vf){
1090 return vf->links;
1091}
1092
1093/* Is the FILE * associated with vf seekable? */
1094long ov_seekable(OggVorbis_File *vf){
1095 return vf->seekable;
1096}
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
1107long ov_bitrate(OggVorbis_File *vf,int i){
1108 if(vf->ready_state<OPENED)return(OV_EINVAL);
1109 if(i>=vf->links)return(OV_EINVAL);
1110 if(!vf->seekable && i!=0)return(ov_bitrate(vf,0));
1111 if(i<0){
1112 ogg_int64_t bits=0;
1113 int i;
1114 float br;
1115 for(i=0;i<vf->links;i++)
1116 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 br = bits/ov_time_total(vf,-1);
1122 return(rint(br));
1123 }else{
1124 if(vf->seekable){
1125 /* return the actual bitrate */
1126 return(rint((vf->offsets[i+1]-vf->dataoffsets[i])*8/ov_time_total(vf,i)));
1127 }else{
1128 /* return nominal if set */
1129 if(vf->vi[i].bitrate_nominal>0){
1130 return vf->vi[i].bitrate_nominal;
1131 }else{
1132 if(vf->vi[i].bitrate_upper>0){
1133 if(vf->vi[i].bitrate_lower>0){
1134 return (vf->vi[i].bitrate_upper+vf->vi[i].bitrate_lower)/2;
1135 }else{
1136 return vf->vi[i].bitrate_upper;
1137 }
1138 }
1139 return(OV_FALSE);
1140 }
1141 }
1142 }
1143}
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*/
1149long ov_bitrate_instant(OggVorbis_File *vf){
1150 int link=(vf->seekable?vf->current_link:0);
1151 long ret;
1152 if(vf->ready_state<OPENED)return(OV_EINVAL);
1153 if(vf->samptrack==0)return(OV_FALSE);
1154 ret=vf->bittrack/vf->samptrack*vf->vi[link].rate+.5;
1155 vf->bittrack=0.f;
1156 vf->samptrack=0.f;
1157 return(ret);
1158}
1159
1160/* Guess */
1161long ov_serialnumber(OggVorbis_File *vf,int i){
1162 if(i>=vf->links)return(ov_serialnumber(vf,vf->links-1));
1163 if(!vf->seekable && i>=0)return(ov_serialnumber(vf,-1));
1164 if(i<0){
1165 return(vf->current_serialno);
1166 }else{
1167 return(vf->serialnos[i]);
1168 }
1169}
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*/
1176ogg_int64_t ov_raw_total(OggVorbis_File *vf,int i){
1177 if(vf->ready_state<OPENED)return(OV_EINVAL);
1178 if(!vf->seekable || i>=vf->links)return(OV_EINVAL);
1179 if(i<0){
1180 ogg_int64_t acc=0;
1181 int i;
1182 for(i=0;i<vf->links;i++)
1183 acc+=ov_raw_total(vf,i);
1184 return(acc);
1185 }else{
1186 return(vf->offsets[i+1]-vf->offsets[i]);
1187 }
1188}
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*/
1195ogg_int64_t ov_pcm_total(OggVorbis_File *vf,int i){
1196 if(vf->ready_state<OPENED)return(OV_EINVAL);
1197 if(!vf->seekable || i>=vf->links)return(OV_EINVAL);
1198 if(i<0){
1199 ogg_int64_t acc=0;
1200 int i;
1201 for(i=0;i<vf->links;i++)
1202 acc+=ov_pcm_total(vf,i);
1203 return(acc);
1204 }else{
1205 return(vf->pcmlengths[i*2+1]);
1206 }
1207}
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*/
1214double ov_time_total(OggVorbis_File *vf,int i){
1215 if(vf->ready_state<OPENED)return(OV_EINVAL);
1216 if(!vf->seekable || i>=vf->links)return(OV_EINVAL);
1217 if(i<0){
1218 double acc=0;
1219 int i;
1220 for(i=0;i<vf->links;i++)
1221 acc+=ov_time_total(vf,i);
1222 return(acc);
1223 }else{
1224 return((double)(vf->pcmlengths[i*2+1])/vf->vi[i].rate);
1225 }
1226}
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
1235int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos){
1236 ogg_stream_state work_os;
1237
1238 if(vf->ready_state<OPENED)return(OV_EINVAL);
1239 if(!vf->seekable)
1240 return(OV_ENOSEEK); /* don't dump machine if we can't seek */
1241
1242 if(pos<0 || pos>vf->end)return(OV_EINVAL);
1243
1244 /* is the seek position outside our current link [if any]? */
1245 if(vf->ready_state>=STREAMSET){
1246 if(pos<vf->offsets[vf->current_link] || pos>=vf->offsets[vf->current_link+1])
1247 _decode_clear(vf); /* clear out stream state */
1248 }
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 vf->pcm_offset=-1;
1255 ogg_stream_reset_serialno(&vf->os,
1256 vf->current_serialno); /* must set serialno */
1257 vorbis_synthesis_restart(&vf->vd);
1258
1259 if(_seek_helper(vf,pos)) {
1260 /* dump the machine so we're in a known state */
1261 vf->pcm_offset=-1;
1262 _decode_clear(vf);
1263 return OV_EBADLINK;
1264 }
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 {
1282 ogg_page og;
1283 ogg_packet op;
1284 int lastblock=0;
1285 int accblock=0;
1286 int thisblock=0;
1287 int lastflag=0;
1288 int firstflag=0;
1289 ogg_int64_t pagepos=-1;
1290
1291 ogg_stream_init(&work_os,vf->current_serialno); /* get the memory ready */
1292 ogg_stream_reset(&work_os); /* eliminate the spurious OV_HOLE
1293 return from not necessarily
1294 starting from the beginning */
1295
1296 while(1){
1297 if(vf->ready_state>=STREAMSET){
1298 /* snarf/scan a packet if we can */
1299 int result=ogg_stream_packetout(&work_os,&op);
1300
1301 if(result>0){
1302
1303 if(vf->vi[vf->current_link].codec_setup){
1304 thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op);
1305 if(thisblock<0){
1306 ogg_stream_packetout(&vf->os,NULL);
1307 thisblock=0;
1308 }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 if(lastflag && !firstflag)
1318 ogg_stream_packetout(&vf->os,NULL);
1319 else
1320 if(lastblock)accblock+=(lastblock+thisblock)>>2;
1321 }
1322
1323 if(op.granulepos!=-1){
1324 int i,link=vf->current_link;
1325 ogg_int64_t granulepos=op.granulepos-vf->pcmlengths[link*2];
1326 if(granulepos<0)granulepos=0;
1327
1328 for(i=0;i<link;i++)
1329 granulepos+=vf->pcmlengths[i*2+1];
1330 vf->pcm_offset=granulepos-accblock;
1331 if(vf->pcm_offset<0)vf->pcm_offset=0;
1332 break;
1333 }
1334 lastblock=thisblock;
1335 continue;
1336 }else
1337 ogg_stream_packetout(&vf->os,NULL);
1338 }
1339 }
1340
1341 if(!lastblock){
1342 pagepos=_get_next_page(vf,&og,-1);
1343 if(pagepos<0){
1344 vf->pcm_offset=ov_pcm_total(vf,-1);
1345 break;
1346 }
1347 }else{
1348 /* huh? Bogus stream with packets but no granulepos */
1349 vf->pcm_offset=-1;
1350 break;
1351 }
1352
1353 /* has our decoding just traversed a bitstream boundary? */
1354 if(vf->ready_state>=STREAMSET){
1355 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 if(ogg_page_bos(&og)){
1362 /* we traversed */
1363 _decode_clear(vf); /* clear out stream state */
1364 ogg_stream_clear(&work_os);
1365 } /* else, do nothing; next loop will scoop another page */
1366 }
1367 }
1368
1369 if(vf->ready_state<STREAMSET){
1370 int link;
1371 long serialno = ogg_page_serialno(&og);
1372
1373 for(link=0;link<vf->links;link++)
1374 if(vf->serialnos[link]==serialno)break;
1375
1376 if(link==vf->links) continue; /* not the desired Vorbis
1377 bitstream section; keep
1378 trying */
1379 vf->current_link=link;
1380 vf->current_serialno=serialno;
1381 ogg_stream_reset_serialno(&vf->os,serialno);
1382 ogg_stream_reset_serialno(&work_os,serialno);
1383 vf->ready_state=STREAMSET;
1384 firstflag=(pagepos<=vf->dataoffsets[link]);
1385 }
1386
1387 ogg_stream_pagein(&vf->os,&og);
1388 ogg_stream_pagein(&work_os,&og);
1389 lastflag=ogg_page_eos(&og);
1390
1391 }
1392 }
1393
1394 ogg_stream_clear(&work_os);
1395 vf->bittrack=0.f;
1396 vf->samptrack=0.f;
1397 return(0);
1398}
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. */
1406int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
1407 int link=-1;
1408 ogg_int64_t result=0;
1409 ogg_int64_t total=ov_pcm_total(vf,-1);
1410
1411 if(vf->ready_state<OPENED)return(OV_EINVAL);
1412 if(!vf->seekable)return(OV_ENOSEEK);
1413
1414 if(pos<0 || pos>total)return(OV_EINVAL);
1415
1416 /* which bitstream section does this pcm offset occur in? */
1417 for(link=vf->links-1;link>=0;link--){
1418 total-=vf->pcmlengths[link*2+1];
1419 if(pos>=total)break;
1420 }
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 {
1435 ogg_int64_t end=vf->offsets[link+1];
1436 ogg_int64_t begin=vf->dataoffsets[link];
1437 ogg_int64_t begintime = vf->pcmlengths[link*2];
1438 ogg_int64_t endtime = vf->pcmlengths[link*2+1]+begintime;
1439 ogg_int64_t target=pos-total+begintime;
1440 ogg_int64_t best=-1;
1441 int got_page=0;
1442
1443 ogg_page og;
1444
1445 /* if we have only one page, there will be no bisection. Grab the page here */
1446 if(begin==end){
1447 result=_seek_helper(vf,begin);
1448 if(result) goto seek_error;
1449
1450 result=_get_next_page(vf,&og,1);
1451 if(result<0) goto seek_error;
1452
1453 got_page=1;
1454 }
1455
1456 /* bisection loop */
1457 while(begin<end){
1458 ogg_int64_t bisect;
1459
1460 if(end-begin<CHUNKSIZE){
1461 bisect=begin;
1462 }else{
1463 /* take a (pretty decent) guess. */
1464 bisect=begin +
1465 (ogg_int64_t)((double)(target-begintime)*(end-begin)/(endtime-begintime))
1466 - CHUNKSIZE;
1467 if(bisect<begin+CHUNKSIZE)
1468 bisect=begin;
1469 }
1470
1471 result=_seek_helper(vf,bisect);
1472 if(result) goto seek_error;
1473
1474 /* read loop within the bisection loop */
1475 while(begin<end){
1476 result=_get_next_page(vf,&og,end-vf->offset);
1477 if(result==OV_EREAD) goto seek_error;
1478 if(result<0){
1479 /* there is no next page! */
1480 if(bisect<=begin+1)
1481 /* No bisection left to perform. We've either found the
1482 best candidate already or failed. Exit loop. */
1483 end=begin;
1484 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 if(bisect==0) goto seek_error;
1488 bisect-=CHUNKSIZE;
1489
1490 /* don't repeat/loop on a read we've already performed */
1491 if(bisect<=begin)bisect=begin+1;
1492
1493 /* seek and cntinue bisection */
1494 result=_seek_helper(vf,bisect);
1495 if(result) goto seek_error;
1496 }
1497 }else{
1498 ogg_int64_t granulepos;
1499 got_page=1;
1500
1501 /* got a page. analyze it */
1502 /* only consider pages from primary vorbis stream */
1503 if(ogg_page_serialno(&og)!=vf->serialnos[link])
1504 continue;
1505
1506 /* only consider pages with the granulepos set */
1507 granulepos=ogg_page_granulepos(&og);
1508 if(granulepos==-1)continue;
1509
1510 if(granulepos<target){
1511 /* this page is a successful candidate! Set state */
1512
1513 best=result; /* raw offset of packet with granulepos */
1514 begin=vf->offset; /* raw offset of next page */
1515 begintime=granulepos;
1516
1517 /* if we're before our target but within a short distance,
1518 don't bisect; read forward */
1519 if(target-begintime>44100)break;
1520
1521 bisect=begin; /* *not* begin + 1 as above */
1522 }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 if(bisect<=begin+1){
1530 /* No bisection left to perform. We've either found the
1531 best candidate already or failed. Exit loop. */
1532 end=begin;
1533 }else{
1534 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 end=result;
1539 bisect-=CHUNKSIZE;
1540 if(bisect<=begin)bisect=begin+1;
1541 result=_seek_helper(vf,bisect);
1542 if(result) goto seek_error;
1543 }else{
1544 /* Normal bisection */
1545 end=bisect;
1546 endtime=granulepos;
1547 break;
1548 }
1549 }
1550 }
1551 }
1552 }
1553 }
1554
1555 /* Out of bisection: did it 'fail?' */
1556 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 if(got_page &&
1563 begin == vf->dataoffsets[link] &&
1564 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 vf->pcm_offset=total;
1571
1572 if(link!=vf->current_link){
1573 /* Different link; dump entire decode machine */
1574 _decode_clear(vf);
1575
1576 vf->current_link=link;
1577 vf->current_serialno=vf->serialnos[link];
1578 vf->ready_state=STREAMSET;
1579
1580 }else{
1581 vorbis_synthesis_restart(&vf->vd);
1582 }
1583
1584 ogg_stream_reset_serialno(&vf->os,vf->current_serialno);
1585 ogg_stream_pagein(&vf->os,&og);
1586
1587 }else
1588 goto seek_error;
1589
1590 }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 ogg_page og;
1596 ogg_packet op;
1597
1598 /* seek */
1599 result=_seek_helper(vf,best);
1600 vf->pcm_offset=-1;
1601 if(result) goto seek_error;
1602 result=_get_next_page(vf,&og,-1);
1603 if(result<0) goto seek_error;
1604
1605 if(link!=vf->current_link){
1606 /* Different link; dump entire decode machine */
1607 _decode_clear(vf);
1608
1609 vf->current_link=link;
1610 vf->current_serialno=vf->serialnos[link];
1611 vf->ready_state=STREAMSET;
1612
1613 }else{
1614 vorbis_synthesis_restart(&vf->vd);
1615 }
1616
1617 ogg_stream_reset_serialno(&vf->os,vf->current_serialno);
1618 ogg_stream_pagein(&vf->os,&og);
1619
1620 /* pull out all but last packet; the one with granulepos */
1621 while(1){
1622 result=ogg_stream_packetpeek(&vf->os,&op);
1623 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 result=best;
1633 while(result>vf->dataoffsets[link]){
1634 result=_get_prev_page(vf,result,&og);
1635 if(result<0) goto seek_error;
1636 if(ogg_page_serialno(&og)==vf->current_serialno &&
1637 (ogg_page_granulepos(&og)>-1 ||
1638 !ogg_page_continued(&og))){
1639 return ov_raw_seek(vf,result);
1640 }
1641 }
1642 }
1643 if(result<0){
1644 result = OV_EBADPACKET;
1645 goto seek_error;
1646 }
1647 if(op.granulepos!=-1){
1648 vf->pcm_offset=op.granulepos-vf->pcmlengths[vf->current_link*2];
1649 if(vf->pcm_offset<0)vf->pcm_offset=0;
1650 vf->pcm_offset+=total;
1651 break;
1652 }else
1653 result=ogg_stream_packetout(&vf->os,NULL);
1654 }
1655 }
1656 }
1657
1658 /* verify result */
1659 if(vf->pcm_offset>pos || pos>ov_pcm_total(vf,-1)){
1660 result=OV_EFAULT;
1661 goto seek_error;
1662 }
1663 vf->bittrack=0.f;
1664 vf->samptrack=0.f;
1665 return(0);
1666
1667 seek_error:
1668 /* dump machine so we're in a known state */
1669 vf->pcm_offset=-1;
1670 _decode_clear(vf);
1671 return (int)result;
1672}
1673
1674/* seek to a sample offset relative to the decompressed pcm stream
1675 returns zero on success, nonzero on failure */
1676
1677int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos){
1678 int thisblock,lastblock=0;
1679 int ret=ov_pcm_seek_page(vf,pos);
1680 if(ret<0)return(ret);
1681 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 while(1){
1687 ogg_packet op;
1688 ogg_page og;
1689
1690 int ret=ogg_stream_packetpeek(&vf->os,&op);
1691 if(ret>0){
1692 thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op);
1693 if(thisblock<0){
1694 ogg_stream_packetout(&vf->os,NULL);
1695 continue; /* non audio packet */
1696 }
1697 if(lastblock)vf->pcm_offset+=(lastblock+thisblock)>>2;
1698
1699 if(vf->pcm_offset+((thisblock+
1700 vorbis_info_blocksize(vf->vi,1))>>2)>=pos)break;
1701
1702 /* remove the packet from packet queue and track its granulepos */
1703 ogg_stream_packetout(&vf->os,NULL);
1704 vorbis_synthesis_trackonly(&vf->vb,&op); /* set up a vb with
1705 only tracking, no
1706 pcm_decode */
1707 vorbis_synthesis_blockin(&vf->vd,&vf->vb);
1708
1709 /* end of logical stream case is hard, especially with exact
1710 length positioning. */
1711
1712 if(op.granulepos>-1){
1713 int i;
1714 /* always believe the stream markers */
1715 vf->pcm_offset=op.granulepos-vf->pcmlengths[vf->current_link*2];
1716 if(vf->pcm_offset<0)vf->pcm_offset=0;
1717 for(i=0;i<vf->current_link;i++)
1718 vf->pcm_offset+=vf->pcmlengths[i*2+1];
1719 }
1720
1721 lastblock=thisblock;
1722
1723 }else{
1724 if(ret<0 && ret!=OV_HOLE)break;
1725
1726 /* suck in a new page */
1727 if(_get_next_page(vf,&og,-1)<0)break;
1728 if(ogg_page_bos(&og))_decode_clear(vf);
1729
1730 if(vf->ready_state<STREAMSET){
1731 long serialno=ogg_page_serialno(&og);
1732 int link;
1733
1734 for(link=0;link<vf->links;link++)
1735 if(vf->serialnos[link]==serialno)break;
1736 if(link==vf->links) continue;
1737 vf->current_link=link;
1738
1739 vf->ready_state=STREAMSET;
1740 vf->current_serialno=ogg_page_serialno(&og);
1741 ogg_stream_reset_serialno(&vf->os,serialno);
1742 ret=_make_decode_ready(vf);
1743 if(ret)return ret;
1744 lastblock=0;
1745 }
1746
1747 ogg_stream_pagein(&vf->os,&og);
1748 }
1749 }
1750
1751 vf->bittrack=0.f;
1752 vf->samptrack=0.f;
1753 /* discard samples until we reach the desired position. Crossing a
1754 logical bitstream boundary with abandon is OK. */
1755 {
1756 /* note that halfrate could be set differently in each link, but
1757 vorbisfile encoforces all links are set or unset */
1758 int hs=vorbis_synthesis_halfrate_p(vf->vi);
1759 while(vf->pcm_offset<((pos>>hs)<<hs)){
1760 ogg_int64_t target=(pos-vf->pcm_offset)>>hs;
1761 long samples=vorbis_synthesis_pcmout(&vf->vd,NULL);
1762
1763 if(samples>target)samples=target;
1764 vorbis_synthesis_read(&vf->vd,samples);
1765 vf->pcm_offset+=samples<<hs;
1766
1767 if(samples<target)
1768 if(_fetch_and_process_packet(vf,NULL,1,1)<=0)
1769 vf->pcm_offset=ov_pcm_total(vf,-1); /* eof */
1770 }
1771 }
1772 return 0;
1773}
1774
1775/* seek to a playback time relative to the decompressed pcm stream
1776 returns zero on success, nonzero on failure */
1777int ov_time_seek(OggVorbis_File *vf,double seconds){
1778 /* translate time to PCM position and call ov_pcm_seek */
1779
1780 int link=-1;
1781 ogg_int64_t pcm_total=0;
1782 double time_total=0.;
1783
1784 if(vf->ready_state<OPENED)return(OV_EINVAL);
1785 if(!vf->seekable)return(OV_ENOSEEK);
1786 if(seconds<0)return(OV_EINVAL);
1787
1788 /* which bitstream section does this time offset occur in? */
1789 for(link=0;link<vf->links;link++){
1790 double addsec = ov_time_total(vf,link);
1791 if(seconds<time_total+addsec)break;
1792 time_total+=addsec;
1793 pcm_total+=vf->pcmlengths[link*2+1];
1794 }
1795
1796 if(link==vf->links)return(OV_EINVAL);
1797
1798 /* enough information to convert time offset to pcm offset */
1799 {
1800 ogg_int64_t target=pcm_total+(seconds-time_total)*vf->vi[link].rate;
1801 return(ov_pcm_seek(vf,target));
1802 }
1803}
1804
1805/* page-granularity version of ov_time_seek
1806 returns zero on success, nonzero on failure */
1807int ov_time_seek_page(OggVorbis_File *vf,double seconds){
1808 /* translate time to PCM position and call ov_pcm_seek */
1809
1810 int link=-1;
1811 ogg_int64_t pcm_total=0;
1812 double time_total=0.;
1813
1814 if(vf->ready_state<OPENED)return(OV_EINVAL);
1815 if(!vf->seekable)return(OV_ENOSEEK);
1816 if(seconds<0)return(OV_EINVAL);
1817
1818 /* which bitstream section does this time offset occur in? */
1819 for(link=0;link<vf->links;link++){
1820 double addsec = ov_time_total(vf,link);
1821 if(seconds<time_total+addsec)break;
1822 time_total+=addsec;
1823 pcm_total+=vf->pcmlengths[link*2+1];
1824 }
1825
1826 if(link==vf->links)return(OV_EINVAL);
1827
1828 /* enough information to convert time offset to pcm offset */
1829 {
1830 ogg_int64_t target=pcm_total+(seconds-time_total)*vf->vi[link].rate;
1831 return(ov_pcm_seek_page(vf,target));
1832 }
1833}
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 */
1837ogg_int64_t ov_raw_tell(OggVorbis_File *vf){
1838 if(vf->ready_state<OPENED)return(OV_EINVAL);
1839 return(vf->offset);
1840}
1841
1842/* return PCM offset (sample) of next PCM sample to be read */
1843ogg_int64_t ov_pcm_tell(OggVorbis_File *vf){
1844 if(vf->ready_state<OPENED)return(OV_EINVAL);
1845 return(vf->pcm_offset);
1846}
1847
1848/* return time offset (seconds) of next PCM sample to be read */
1849double ov_time_tell(OggVorbis_File *vf){
1850 int link=0;
1851 ogg_int64_t pcm_total=0;
1852 double time_total=0.f;
1853
1854 if(vf->ready_state<OPENED)return(OV_EINVAL);
1855 if(vf->seekable){
1856 pcm_total=ov_pcm_total(vf,-1);
1857 time_total=ov_time_total(vf,-1);
1858
1859 /* which bitstream section does this time offset occur in? */
1860 for(link=vf->links-1;link>=0;link--){
1861 pcm_total-=vf->pcmlengths[link*2+1];
1862 time_total-=ov_time_total(vf,link);
1863 if(vf->pcm_offset>=pcm_total)break;
1864 }
1865 }
1866
1867 return((double)time_total+(double)(vf->pcm_offset-pcm_total)/vf->vi[link].rate);
1868}
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
1878vorbis_info *ov_info(OggVorbis_File *vf,int link){
1879 if(vf->seekable){
1880 if(link<0)
1881 if(vf->ready_state>=STREAMSET)
1882 return vf->vi+vf->current_link;
1883 else
1884 return vf->vi;
1885 else
1886 if(link>=vf->links)
1887 return NULL;
1888 else
1889 return vf->vi+link;
1890 }else{
1891 return vf->vi;
1892 }
1893}
1894
1895/* grr, strong typing, grr, no templates/inheritence, grr */
1896vorbis_comment *ov_comment(OggVorbis_File *vf,int link){
1897 if(vf->seekable){
1898 if(link<0)
1899 if(vf->ready_state>=STREAMSET)
1900 return vf->vc+vf->current_link;
1901 else
1902 return vf->vc;
1903 else
1904 if(link>=vf->links)
1905 return NULL;
1906 else
1907 return vf->vc+link;
1908 }else{
1909 return vf->vc;
1910 }
1911}
1912
1913static int host_is_big_endian() {
1914 ogg_int32_t pattern = 0xfeedface; /* deadbeef */
1915 unsigned char *bytewise = (unsigned char *)&pattern;
1916 if (bytewise[0] == 0xfe) return 1;
1917 return 0;
1918}
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
1956long ov_read_filter(OggVorbis_File *vf,char *buffer,int length,
1957 int bigendianp,int word,int sgned,int *bitstream,
1958 void (*filter)(float **pcm,long channels,long samples,void *filter_param),void *filter_param){
1959 int i,j;
1960 int host_endian = host_is_big_endian();
1961 int hs;
1962
1963 float **pcm;
1964 long samples;
1965
1966 if(vf->ready_state<OPENED)return(OV_EINVAL);
1967 if(word<=0)return(OV_EINVAL);
1968
1969 while(1){
1970 if(vf->ready_state==INITSET){
1971 samples=vorbis_synthesis_pcmout(&vf->vd,&pcm);
1972 if(samples)break;
1973 }
1974
1975 /* suck in another packet */
1976 {
1977 int ret=_fetch_and_process_packet(vf,NULL,1,1);
1978 if(ret==OV_EOF)
1979 return(0);
1980 if(ret<=0)
1981 return(ret);
1982 }
1983
1984 }
1985
1986 if(samples>0){
1987
1988 /* yay! proceed to pack data into the byte buffer */
1989
1990 long channels=ov_info(vf,-1)->channels;
1991 long bytespersample=word * channels;
1992 vorbis_fpu_control fpu;
1993
1994 if(channels<1||channels>255)return(OV_EINVAL);
1995 if(samples>length/bytespersample)samples=length/bytespersample;
1996
1997 if(samples <= 0)
1998 return OV_EINVAL;
1999
2000 /* Here. */
2001 if(filter)
2002 filter(pcm,channels,samples,filter_param);
2003
2004 /* a tight loop to pack each size */
2005 {
2006 int val;
2007 if(word==1){
2008 int off=(sgned?0:128);
2009 vorbis_fpu_setround(&fpu);
2010 for(j=0;j<samples;j++)
2011 for(i=0;i<channels;i++){
2012 val=vorbis_ftoi(pcm[i][j]*128.f);
2013 if(val>127)val=127;
2014 else if(val<-128)val=-128;
2015 *buffer++=val+off;
2016 }
2017 vorbis_fpu_restore(fpu);
2018 }else{
2019 int off=(sgned?0:32768);
2020
2021 if(host_endian==bigendianp){
2022 if(sgned){
2023
2024 vorbis_fpu_setround(&fpu);
2025 for(i=0;i<channels;i++) { /* It's faster in this order */
2026 float *src=pcm[i];
2027 short *dest=((short *)buffer)+i;
2028 for(j=0;j<samples;j++) {
2029 val=vorbis_ftoi(src[j]*32768.f);
2030 if(val>32767)val=32767;
2031 else if(val<-32768)val=-32768;
2032 *dest=val;
2033 dest+=channels;
2034 }
2035 }
2036 vorbis_fpu_restore(fpu);
2037
2038 }else{
2039
2040 vorbis_fpu_setround(&fpu);
2041 for(i=0;i<channels;i++) {
2042 float *src=pcm[i];
2043 short *dest=((short *)buffer)+i;
2044 for(j=0;j<samples;j++) {
2045 val=vorbis_ftoi(src[j]*32768.f);
2046 if(val>32767)val=32767;
2047 else if(val<-32768)val=-32768;
2048 *dest=val+off;
2049 dest+=channels;
2050 }
2051 }
2052 vorbis_fpu_restore(fpu);
2053
2054 }
2055 }else if(bigendianp){
2056
2057 vorbis_fpu_setround(&fpu);
2058 for(j=0;j<samples;j++)
2059 for(i=0;i<channels;i++){
2060 val=vorbis_ftoi(pcm[i][j]*32768.f);
2061 if(val>32767)val=32767;
2062 else if(val<-32768)val=-32768;
2063 val+=off;
2064 *buffer++=(val>>8);
2065 *buffer++=(val&0xff);
2066 }
2067 vorbis_fpu_restore(fpu);
2068
2069 }else{
2070 int val;
2071 vorbis_fpu_setround(&fpu);
2072 for(j=0;j<samples;j++)
2073 for(i=0;i<channels;i++){
2074 val=vorbis_ftoi(pcm[i][j]*32768.f);
2075 if(val>32767)val=32767;
2076 else if(val<-32768)val=-32768;
2077 val+=off;
2078 *buffer++=(val&0xff);
2079 *buffer++=(val>>8);
2080 }
2081 vorbis_fpu_restore(fpu);
2082
2083 }
2084 }
2085 }
2086
2087 vorbis_synthesis_read(&vf->vd,samples);
2088 hs=vorbis_synthesis_halfrate_p(vf->vi);
2089 vf->pcm_offset+=(samples<<hs);
2090 if(bitstream)*bitstream=vf->current_link;
2091 return(samples*bytespersample);
2092 }else{
2093 return(samples);
2094 }
2095}
2096
2097long ov_read(OggVorbis_File *vf,char *buffer,int length,
2098 int bigendianp,int word,int sgned,int *bitstream){
2099 return ov_read_filter(vf, buffer, length, bigendianp, word, sgned, bitstream, NULL, NULL);
2100}
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
2116long ov_read_float(OggVorbis_File *vf,float ***pcm_channels,int length,
2117 int *bitstream){
2118
2119 if(vf->ready_state<OPENED)return(OV_EINVAL);
2120
2121 while(1){
2122 if(vf->ready_state==INITSET){
2123 float **pcm;
2124 long samples=vorbis_synthesis_pcmout(&vf->vd,&pcm);
2125 if(samples){
2126 int hs=vorbis_synthesis_halfrate_p(vf->vi);
2127 if(pcm_channels)*pcm_channels=pcm;
2128 if(samples>length)samples=length;
2129 vorbis_synthesis_read(&vf->vd,samples);
2130 vf->pcm_offset+=samples<<hs;
2131 if(bitstream)*bitstream=vf->current_link;
2132 return samples;
2133
2134 }
2135 }
2136
2137 /* suck in another packet */
2138 {
2139 int ret=_fetch_and_process_packet(vf,NULL,1,1);
2140 if(ret==OV_EOF)return(0);
2141 if(ret<=0)return(ret);
2142 }
2143
2144 }
2145}
2146
2147extern const float *vorbis_window(vorbis_dsp_state *v,int W);
2148
2149static void _ov_splice(float **pcm,float **lappcm,
2150 int n1, int n2,
2151 int ch1, int ch2,
2152 const float *w1, const float *w2){
2153 int i,j;
2154 const float *w=w1;
2155 int n=n1;
2156
2157 if(n1>n2){
2158 n=n2;
2159 w=w2;
2160 }
2161
2162 /* splice */
2163 for(j=0;j<ch1 && j<ch2;j++){
2164 float *s=lappcm[j];
2165 float *d=pcm[j];
2166
2167 for(i=0;i<n;i++){
2168 float wd=w[i]*w[i];
2169 float ws=1.-wd;
2170 d[i]=d[i]*wd + s[i]*ws;
2171 }
2172 }
2173 /* window from zero */
2174 for(;j<ch2;j++){
2175 float *d=pcm[j];
2176 for(i=0;i<n;i++){
2177 float wd=w[i]*w[i];
2178 d[i]=d[i]*wd;
2179 }
2180 }
2181
2182}
2183
2184/* make sure vf is INITSET */
2185static int _ov_initset(OggVorbis_File *vf){
2186 while(1){
2187 if(vf->ready_state==INITSET)break;
2188 /* suck in another packet */
2189 {
2190 int ret=_fetch_and_process_packet(vf,NULL,1,0);
2191 if(ret<0 && ret!=OV_HOLE)return(ret);
2192 }
2193 }
2194 return 0;
2195}
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 */
2200static int _ov_initprime(OggVorbis_File *vf){
2201 vorbis_dsp_state *vd=&vf->vd;
2202 while(1){
2203 if(vf->ready_state==INITSET)
2204 if(vorbis_synthesis_pcmout(vd,NULL))break;
2205
2206 /* suck in another packet */
2207 {
2208 int ret=_fetch_and_process_packet(vf,NULL,1,0);
2209 if(ret<0 && ret!=OV_HOLE)return(ret);
2210 }
2211 }
2212 return 0;
2213}
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. */
2218static void _ov_getlap(OggVorbis_File *vf,vorbis_info *vi,vorbis_dsp_state *vd,
2219 float **lappcm,int lapsize){
2220 int lapcount=0,i;
2221 float **pcm;
2222
2223 /* try first to decode the lapping data */
2224 while(lapcount<lapsize){
2225 int samples=vorbis_synthesis_pcmout(vd,&pcm);
2226 if(samples){
2227 if(samples>lapsize-lapcount)samples=lapsize-lapcount;
2228 for(i=0;i<vi->channels;i++)
2229 memcpy(lappcm[i]+lapcount,pcm[i],sizeof(**pcm)*samples);
2230 lapcount+=samples;
2231 vorbis_synthesis_read(vd,samples);
2232 }else{
2233 /* suck in another packet */
2234 int ret=_fetch_and_process_packet(vf,NULL,1,0); /* do *not* span */
2235 if(ret==OV_EOF)break;
2236 }
2237 }
2238 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 int samples=vorbis_synthesis_lapout(&vf->vd,&pcm);
2243 if(samples==0){
2244 for(i=0;i<vi->channels;i++)
2245 memset(lappcm[i]+lapcount,0,sizeof(**pcm)*lapsize-lapcount);
2246 lapcount=lapsize;
2247 }else{
2248 if(samples>lapsize-lapcount)samples=lapsize-lapcount;
2249 for(i=0;i<vi->channels;i++)
2250 memcpy(lappcm[i]+lapcount,pcm[i],sizeof(**pcm)*samples);
2251 lapcount+=samples;
2252 }
2253 }
2254}
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 */
2258int ov_crosslap(OggVorbis_File *vf1, OggVorbis_File *vf2){
2259 vorbis_info *vi1,*vi2;
2260 float **lappcm;
2261 float **pcm;
2262 const float *w1,*w2;
2263 int n1,n2,i,ret,hs1,hs2;
2264
2265 if(vf1==vf2)return(0); /* degenerate case */
2266 if(vf1->ready_state<OPENED)return(OV_EINVAL);
2267 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 ret=_ov_initset(vf1);
2274 if(ret)return(ret);
2275 ret=_ov_initprime(vf2);
2276 if(ret)return(ret);
2277
2278 vi1=ov_info(vf1,-1);
2279 vi2=ov_info(vf2,-1);
2280 hs1=ov_halfrate_p(vf1);
2281 hs2=ov_halfrate_p(vf2);
2282
2283 lappcm=alloca(sizeof(*lappcm)*vi1->channels);
2284 n1=vorbis_info_blocksize(vi1,0)>>(1+hs1);
2285 n2=vorbis_info_blocksize(vi2,0)>>(1+hs2);
2286 w1=vorbis_window(&vf1->vd,0);
2287 w2=vorbis_window(&vf2->vd,0);
2288
2289 for(i=0;i<vi1->channels;i++)
2290 lappcm[i]=alloca(sizeof(**lappcm)*n1);
2291
2292 _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 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 _ov_splice(pcm,lappcm,n1,n2,vi1->channels,vi2->channels,w1,w2);
2306
2307 /* done */
2308 return(0);
2309}
2310
2311static int _ov_64_seek_lap(OggVorbis_File *vf,ogg_int64_t pos,
2312 int (*localseek)(OggVorbis_File *,ogg_int64_t)){
2313 vorbis_info *vi;
2314 float **lappcm;
2315 float **pcm;
2316 const float *w1,*w2;
2317 int n1,n2,ch1,ch2,hs;
2318 int i,ret;
2319
2320 if(vf->ready_state<OPENED)return(OV_EINVAL);
2321 ret=_ov_initset(vf);
2322 if(ret)return(ret);
2323 vi=ov_info(vf,-1);
2324 hs=ov_halfrate_p(vf);
2325
2326 ch1=vi->channels;
2327 n1=vorbis_info_blocksize(vi,0)>>(1+hs);
2328 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 lappcm=alloca(sizeof(*lappcm)*ch1);
2334 for(i=0;i<ch1;i++)
2335 lappcm[i]=alloca(sizeof(**lappcm)*n1);
2336 _ov_getlap(vf,vi,&vf->vd,lappcm,n1);
2337
2338 /* have lapping data; seek and prime the buffer */
2339 ret=localseek(vf,pos);
2340 if(ret)return ret;
2341 ret=_ov_initprime(vf);
2342 if(ret)return(ret);
2343
2344 /* Guard against cross-link changes; they're perfectly legal */
2345 vi=ov_info(vf,-1);
2346 ch2=vi->channels;
2347 n2=vorbis_info_blocksize(vi,0)>>(1+hs);
2348 w2=vorbis_window(&vf->vd,0);
2349
2350 /* consolidate and expose the buffer. */
2351 vorbis_synthesis_lapout(&vf->vd,&pcm);
2352
2353 /* splice */
2354 _ov_splice(pcm,lappcm,n1,n2,ch1,ch2,w1,w2);
2355
2356 /* done */
2357 return(0);
2358}
2359
2360int ov_raw_seek_lap(OggVorbis_File *vf,ogg_int64_t pos){
2361 return _ov_64_seek_lap(vf,pos,ov_raw_seek);
2362}
2363
2364int ov_pcm_seek_lap(OggVorbis_File *vf,ogg_int64_t pos){
2365 return _ov_64_seek_lap(vf,pos,ov_pcm_seek);
2366}
2367
2368int ov_pcm_seek_page_lap(OggVorbis_File *vf,ogg_int64_t pos){
2369 return _ov_64_seek_lap(vf,pos,ov_pcm_seek_page);
2370}
2371
2372static int _ov_d_seek_lap(OggVorbis_File *vf,double pos,
2373 int (*localseek)(OggVorbis_File *,double)){
2374 vorbis_info *vi;
2375 float **lappcm;
2376 float **pcm;
2377 const float *w1,*w2;
2378 int n1,n2,ch1,ch2,hs;
2379 int i,ret;
2380
2381 if(vf->ready_state<OPENED)return(OV_EINVAL);
2382 ret=_ov_initset(vf);
2383 if(ret)return(ret);
2384 vi=ov_info(vf,-1);
2385 hs=ov_halfrate_p(vf);
2386
2387 ch1=vi->channels;
2388 n1=vorbis_info_blocksize(vi,0)>>(1+hs);
2389 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 lappcm=alloca(sizeof(*lappcm)*ch1);
2395 for(i=0;i<ch1;i++)
2396 lappcm[i]=alloca(sizeof(**lappcm)*n1);
2397 _ov_getlap(vf,vi,&vf->vd,lappcm,n1);
2398
2399 /* have lapping data; seek and prime the buffer */
2400 ret=localseek(vf,pos);
2401 if(ret)return ret;
2402 ret=_ov_initprime(vf);
2403 if(ret)return(ret);
2404
2405 /* Guard against cross-link changes; they're perfectly legal */
2406 vi=ov_info(vf,-1);
2407 ch2=vi->channels;
2408 n2=vorbis_info_blocksize(vi,0)>>(1+hs);
2409 w2=vorbis_window(&vf->vd,0);
2410
2411 /* consolidate and expose the buffer. */
2412 vorbis_synthesis_lapout(&vf->vd,&pcm);
2413
2414 /* splice */
2415 _ov_splice(pcm,lappcm,n1,n2,ch1,ch2,w1,w2);
2416
2417 /* done */
2418 return(0);
2419}
2420
2421int ov_time_seek_lap(OggVorbis_File *vf,double pos){
2422 return _ov_d_seek_lap(vf,pos,ov_time_seek);
2423}
2424
2425int ov_time_seek_page_lap(OggVorbis_File *vf,double pos){
2426 return _ov_d_seek_lap(vf,pos,ov_time_seek_page);
2427}
2428