VirtualBox

source: vbox/trunk/src/libs/libvorbis-1.3.7/lib/vorbisfile.c

Last change on this file was 96468, checked in by vboxsync, 22 months ago

libs/libvorbis-1.3.7: Re-exporting, hopefully this time everything is there. bugref:10275

File size: 74.4 KB
Line 
1/********************************************************************
2 * *
3 * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
4 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
5 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
6 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
7 * *
8 * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-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 float br;
1114 for(i=0;i<vf->links;i++)
1115 bits+=(vf->offsets[i+1]-vf->dataoffsets[i])*8;
1116 /* This once read: return(rint(bits/ov_time_total(vf,-1)));
1117 * gcc 3.x on x86 miscompiled this at optimisation level 2 and above,
1118 * so this is slightly transformed to make it work.
1119 */
1120 br = bits/ov_time_total(vf,-1);
1121 return(rint(br));
1122 }else{
1123 if(vf->seekable){
1124 /* return the actual bitrate */
1125 return(rint((vf->offsets[i+1]-vf->dataoffsets[i])*8/ov_time_total(vf,i)));
1126 }else{
1127 /* return nominal if set */
1128 if(vf->vi[i].bitrate_nominal>0){
1129 return vf->vi[i].bitrate_nominal;
1130 }else{
1131 if(vf->vi[i].bitrate_upper>0){
1132 if(vf->vi[i].bitrate_lower>0){
1133 return (vf->vi[i].bitrate_upper+vf->vi[i].bitrate_lower)/2;
1134 }else{
1135 return vf->vi[i].bitrate_upper;
1136 }
1137 }
1138 return(OV_FALSE);
1139 }
1140 }
1141 }
1142}
1143
1144/* returns the actual bitrate since last call. returns -1 if no
1145 additional data to offer since last call (or at beginning of stream),
1146 EINVAL if stream is only partially open
1147*/
1148long ov_bitrate_instant(OggVorbis_File *vf){
1149 int link=(vf->seekable?vf->current_link:0);
1150 long ret;
1151 if(vf->ready_state<OPENED)return(OV_EINVAL);
1152 if(vf->samptrack==0)return(OV_FALSE);
1153 ret=vf->bittrack/vf->samptrack*vf->vi[link].rate+.5;
1154 vf->bittrack=0.f;
1155 vf->samptrack=0.f;
1156 return(ret);
1157}
1158
1159/* Guess */
1160long ov_serialnumber(OggVorbis_File *vf,int i){
1161 if(i>=vf->links)return(ov_serialnumber(vf,vf->links-1));
1162 if(!vf->seekable && i>=0)return(ov_serialnumber(vf,-1));
1163 if(i<0){
1164 return(vf->current_serialno);
1165 }else{
1166 return(vf->serialnos[i]);
1167 }
1168}
1169
1170/* returns: total raw (compressed) length of content if i==-1
1171 raw (compressed) length of that logical bitstream for i==0 to n
1172 OV_EINVAL if the stream is not seekable (we can't know the length)
1173 or if stream is only partially open
1174*/
1175ogg_int64_t ov_raw_total(OggVorbis_File *vf,int i){
1176 if(vf->ready_state<OPENED)return(OV_EINVAL);
1177 if(!vf->seekable || i>=vf->links)return(OV_EINVAL);
1178 if(i<0){
1179 ogg_int64_t acc=0;
1180 for(i=0;i<vf->links;i++)
1181 acc+=ov_raw_total(vf,i);
1182 return(acc);
1183 }else{
1184 return(vf->offsets[i+1]-vf->offsets[i]);
1185 }
1186}
1187
1188/* returns: total PCM length (samples) of content if i==-1 PCM length
1189 (samples) of that logical bitstream for i==0 to n
1190 OV_EINVAL if the stream is not seekable (we can't know the
1191 length) or only partially open
1192*/
1193ogg_int64_t ov_pcm_total(OggVorbis_File *vf,int i){
1194 if(vf->ready_state<OPENED)return(OV_EINVAL);
1195 if(!vf->seekable || i>=vf->links)return(OV_EINVAL);
1196 if(i<0){
1197 ogg_int64_t acc=0;
1198 for(i=0;i<vf->links;i++)
1199 acc+=ov_pcm_total(vf,i);
1200 return(acc);
1201 }else{
1202 return(vf->pcmlengths[i*2+1]);
1203 }
1204}
1205
1206/* returns: total seconds of content if i==-1
1207 seconds in that logical bitstream for i==0 to n
1208 OV_EINVAL if the stream is not seekable (we can't know the
1209 length) or only partially open
1210*/
1211double ov_time_total(OggVorbis_File *vf,int i){
1212 if(vf->ready_state<OPENED)return(OV_EINVAL);
1213 if(!vf->seekable || i>=vf->links)return(OV_EINVAL);
1214 if(i<0){
1215 double acc=0;
1216 for(i=0;i<vf->links;i++)
1217 acc+=ov_time_total(vf,i);
1218 return(acc);
1219 }else{
1220 return((double)(vf->pcmlengths[i*2+1])/vf->vi[i].rate);
1221 }
1222}
1223
1224/* seek to an offset relative to the *compressed* data. This also
1225 scans packets to update the PCM cursor. It will cross a logical
1226 bitstream boundary, but only if it can't get any packets out of the
1227 tail of the bitstream we seek to (so no surprises).
1228
1229 returns zero on success, nonzero on failure */
1230
1231int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos){
1232 ogg_stream_state work_os;
1233
1234 if(vf->ready_state<OPENED)return(OV_EINVAL);
1235 if(!vf->seekable)
1236 return(OV_ENOSEEK); /* don't dump machine if we can't seek */
1237
1238 if(pos<0 || pos>vf->end)return(OV_EINVAL);
1239
1240 /* is the seek position outside our current link [if any]? */
1241 if(vf->ready_state>=STREAMSET){
1242 if(pos<vf->offsets[vf->current_link] || pos>=vf->offsets[vf->current_link+1])
1243 _decode_clear(vf); /* clear out stream state */
1244 }
1245
1246 /* don't yet clear out decoding machine (if it's initialized), in
1247 the case we're in the same link. Restart the decode lapping, and
1248 let _fetch_and_process_packet deal with a potential bitstream
1249 boundary */
1250 vf->pcm_offset=-1;
1251 ogg_stream_reset_serialno(&vf->os,
1252 vf->current_serialno); /* must set serialno */
1253 vorbis_synthesis_restart(&vf->vd);
1254
1255 if(_seek_helper(vf,pos)) {
1256 /* dump the machine so we're in a known state */
1257 vf->pcm_offset=-1;
1258 _decode_clear(vf);
1259 return OV_EBADLINK;
1260 }
1261
1262 /* we need to make sure the pcm_offset is set, but we don't want to
1263 advance the raw cursor past good packets just to get to the first
1264 with a granulepos. That's not equivalent behavior to beginning
1265 decoding as immediately after the seek position as possible.
1266
1267 So, a hack. We use two stream states; a local scratch state and
1268 the shared vf->os stream state. We use the local state to
1269 scan, and the shared state as a buffer for later decode.
1270
1271 Unfortuantely, on the last page we still advance to last packet
1272 because the granulepos on the last page is not necessarily on a
1273 packet boundary, and we need to make sure the granpos is
1274 correct.
1275 */
1276
1277 {
1278 ogg_page og;
1279 ogg_packet op;
1280 int lastblock=0;
1281 int accblock=0;
1282 int thisblock=0;
1283 int lastflag=0;
1284 int firstflag=0;
1285 ogg_int64_t pagepos=-1;
1286
1287 ogg_stream_init(&work_os,vf->current_serialno); /* get the memory ready */
1288 ogg_stream_reset(&work_os); /* eliminate the spurious OV_HOLE
1289 return from not necessarily
1290 starting from the beginning */
1291
1292 while(1){
1293 if(vf->ready_state>=STREAMSET){
1294 /* snarf/scan a packet if we can */
1295 int result=ogg_stream_packetout(&work_os,&op);
1296
1297 if(result>0){
1298
1299 if(vf->vi[vf->current_link].codec_setup){
1300 thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op);
1301 if(thisblock<0){
1302 ogg_stream_packetout(&vf->os,NULL);
1303 thisblock=0;
1304 }else{
1305
1306 /* We can't get a guaranteed correct pcm position out of the
1307 last page in a stream because it might have a 'short'
1308 granpos, which can only be detected in the presence of a
1309 preceding page. However, if the last page is also the first
1310 page, the granpos rules of a first page take precedence. Not
1311 only that, but for first==last, the EOS page must be treated
1312 as if its a normal first page for the stream to open/play. */
1313 if(lastflag && !firstflag)
1314 ogg_stream_packetout(&vf->os,NULL);
1315 else
1316 if(lastblock)accblock+=(lastblock+thisblock)>>2;
1317 }
1318
1319 if(op.granulepos!=-1){
1320 int i,link=vf->current_link;
1321 ogg_int64_t granulepos=op.granulepos-vf->pcmlengths[link*2];
1322 if(granulepos<0)granulepos=0;
1323
1324 for(i=0;i<link;i++)
1325 granulepos+=vf->pcmlengths[i*2+1];
1326 vf->pcm_offset=granulepos-accblock;
1327 if(vf->pcm_offset<0)vf->pcm_offset=0;
1328 break;
1329 }
1330 lastblock=thisblock;
1331 continue;
1332 }else
1333 ogg_stream_packetout(&vf->os,NULL);
1334 }
1335 }
1336
1337 if(!lastblock){
1338 pagepos=_get_next_page(vf,&og,-1);
1339 if(pagepos<0){
1340 vf->pcm_offset=ov_pcm_total(vf,-1);
1341 break;
1342 }
1343 }else{
1344 /* huh? Bogus stream with packets but no granulepos */
1345 vf->pcm_offset=-1;
1346 break;
1347 }
1348
1349 /* has our decoding just traversed a bitstream boundary? */
1350 if(vf->ready_state>=STREAMSET){
1351 if(vf->current_serialno!=ogg_page_serialno(&og)){
1352
1353 /* two possibilities:
1354 1) our decoding just traversed a bitstream boundary
1355 2) another stream is multiplexed into this logical section? */
1356
1357 if(ogg_page_bos(&og)){
1358 /* we traversed */
1359 _decode_clear(vf); /* clear out stream state */
1360 ogg_stream_clear(&work_os);
1361 } /* else, do nothing; next loop will scoop another page */
1362 }
1363 }
1364
1365 if(vf->ready_state<STREAMSET){
1366 int link;
1367 long serialno = ogg_page_serialno(&og);
1368
1369 for(link=0;link<vf->links;link++)
1370 if(vf->serialnos[link]==serialno)break;
1371
1372 if(link==vf->links) continue; /* not the desired Vorbis
1373 bitstream section; keep
1374 trying */
1375 vf->current_link=link;
1376 vf->current_serialno=serialno;
1377 ogg_stream_reset_serialno(&vf->os,serialno);
1378 ogg_stream_reset_serialno(&work_os,serialno);
1379 vf->ready_state=STREAMSET;
1380 firstflag=(pagepos<=vf->dataoffsets[link]);
1381 }
1382
1383 ogg_stream_pagein(&vf->os,&og);
1384 ogg_stream_pagein(&work_os,&og);
1385 lastflag=ogg_page_eos(&og);
1386
1387 }
1388 }
1389
1390 ogg_stream_clear(&work_os);
1391 vf->bittrack=0.f;
1392 vf->samptrack=0.f;
1393 return(0);
1394}
1395
1396/* Page granularity seek (faster than sample granularity because we
1397 don't do the last bit of decode to find a specific sample).
1398
1399 Seek to the last [granule marked] page preceding the specified pos
1400 location, such that decoding past the returned point will quickly
1401 arrive at the requested position. */
1402int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
1403 int link=-1;
1404 ogg_int64_t result=0;
1405 ogg_int64_t total=ov_pcm_total(vf,-1);
1406
1407 if(vf->ready_state<OPENED)return(OV_EINVAL);
1408 if(!vf->seekable)return(OV_ENOSEEK);
1409
1410 if(pos<0 || pos>total)return(OV_EINVAL);
1411
1412 /* which bitstream section does this pcm offset occur in? */
1413 for(link=vf->links-1;link>=0;link--){
1414 total-=vf->pcmlengths[link*2+1];
1415 if(pos>=total)break;
1416 }
1417
1418 /* Search within the logical bitstream for the page with the highest
1419 pcm_pos preceding pos. If we're looking for a position on the
1420 first page, bisection will halt without finding our position as
1421 it's before the first explicit granulepos fencepost. That case is
1422 handled separately below.
1423
1424 There is a danger here; missing pages or incorrect frame number
1425 information in the bitstream could make our task impossible.
1426 Account for that (it would be an error condition) */
1427
1428 /* new search algorithm originally by HB (Nicholas Vinen) */
1429
1430 {
1431 ogg_int64_t end=vf->offsets[link+1];
1432 ogg_int64_t begin=vf->dataoffsets[link];
1433 ogg_int64_t begintime = vf->pcmlengths[link*2];
1434 ogg_int64_t endtime = vf->pcmlengths[link*2+1]+begintime;
1435 ogg_int64_t target=pos-total+begintime;
1436 ogg_int64_t best=-1;
1437 int got_page=0;
1438
1439 ogg_page og;
1440
1441 /* if we have only one page, there will be no bisection. Grab the page here */
1442 if(begin==end){
1443 result=_seek_helper(vf,begin);
1444 if(result) goto seek_error;
1445
1446 result=_get_next_page(vf,&og,1);
1447 if(result<0) goto seek_error;
1448
1449 got_page=1;
1450 }
1451
1452 /* bisection loop */
1453 while(begin<end){
1454 ogg_int64_t bisect;
1455
1456 if(end-begin<CHUNKSIZE){
1457 bisect=begin;
1458 }else{
1459 /* take a (pretty decent) guess. */
1460 bisect=begin +
1461 (ogg_int64_t)((double)(target-begintime)*(end-begin)/(endtime-begintime))
1462 - CHUNKSIZE;
1463 if(bisect<begin+CHUNKSIZE)
1464 bisect=begin;
1465 }
1466
1467 result=_seek_helper(vf,bisect);
1468 if(result) goto seek_error;
1469
1470 /* read loop within the bisection loop */
1471 while(begin<end){
1472 result=_get_next_page(vf,&og,end-vf->offset);
1473 if(result==OV_EREAD) goto seek_error;
1474 if(result<0){
1475 /* there is no next page! */
1476 if(bisect<=begin+1)
1477 /* No bisection left to perform. We've either found the
1478 best candidate already or failed. Exit loop. */
1479 end=begin;
1480 else{
1481 /* We tried to load a fraction of the last page; back up a
1482 bit and try to get the whole last page */
1483 if(bisect==0) goto seek_error;
1484 bisect-=CHUNKSIZE;
1485
1486 /* don't repeat/loop on a read we've already performed */
1487 if(bisect<=begin)bisect=begin+1;
1488
1489 /* seek and cntinue bisection */
1490 result=_seek_helper(vf,bisect);
1491 if(result) goto seek_error;
1492 }
1493 }else{
1494 ogg_int64_t granulepos;
1495 got_page=1;
1496
1497 /* got a page. analyze it */
1498 /* only consider pages from primary vorbis stream */
1499 if(ogg_page_serialno(&og)!=vf->serialnos[link])
1500 continue;
1501
1502 /* only consider pages with the granulepos set */
1503 granulepos=ogg_page_granulepos(&og);
1504 if(granulepos==-1)continue;
1505
1506 if(granulepos<target){
1507 /* this page is a successful candidate! Set state */
1508
1509 best=result; /* raw offset of packet with granulepos */
1510 begin=vf->offset; /* raw offset of next page */
1511 begintime=granulepos;
1512
1513 /* if we're before our target but within a short distance,
1514 don't bisect; read forward */
1515 if(target-begintime>44100)break;
1516
1517 bisect=begin; /* *not* begin + 1 as above */
1518 }else{
1519
1520 /* This is one of our pages, but the granpos is
1521 post-target; it is not a bisection return
1522 candidate. (The only way we'd use it is if it's the
1523 first page in the stream; we handle that case later
1524 outside the bisection) */
1525 if(bisect<=begin+1){
1526 /* No bisection left to perform. We've either found the
1527 best candidate already or failed. Exit loop. */
1528 end=begin;
1529 }else{
1530 if(end==vf->offset){
1531 /* bisection read to the end; use the known page
1532 boundary (result) to update bisection, back up a
1533 little bit, and try again */
1534 end=result;
1535 bisect-=CHUNKSIZE;
1536 if(bisect<=begin)bisect=begin+1;
1537 result=_seek_helper(vf,bisect);
1538 if(result) goto seek_error;
1539 }else{
1540 /* Normal bisection */
1541 end=bisect;
1542 endtime=granulepos;
1543 break;
1544 }
1545 }
1546 }
1547 }
1548 }
1549 }
1550
1551 /* Out of bisection: did it 'fail?' */
1552 if(best == -1){
1553
1554 /* Check the 'looking for data in first page' special case;
1555 bisection would 'fail' because our search target was before the
1556 first PCM granule position fencepost. */
1557
1558 if(got_page &&
1559 begin == vf->dataoffsets[link] &&
1560 ogg_page_serialno(&og)==vf->serialnos[link]){
1561
1562 /* Yes, this is the beginning-of-stream case. We already have
1563 our page, right at the beginning of PCM data. Set state
1564 and return. */
1565
1566 vf->pcm_offset=total;
1567
1568 if(link!=vf->current_link){
1569 /* Different link; dump entire decode machine */
1570 _decode_clear(vf);
1571
1572 vf->current_link=link;
1573 vf->current_serialno=vf->serialnos[link];
1574 vf->ready_state=STREAMSET;
1575
1576 }else{
1577 vorbis_synthesis_restart(&vf->vd);
1578 }
1579
1580 ogg_stream_reset_serialno(&vf->os,vf->current_serialno);
1581 ogg_stream_pagein(&vf->os,&og);
1582
1583 }else
1584 goto seek_error;
1585
1586 }else{
1587
1588 /* Bisection found our page. seek to it, update pcm offset. Easier case than
1589 raw_seek, don't keep packets preceding granulepos. */
1590
1591 ogg_packet op;
1592
1593 /* seek */
1594 result=_seek_helper(vf,best);
1595 vf->pcm_offset=-1;
1596 if(result) goto seek_error;
1597 result=_get_next_page(vf,&og,-1);
1598 if(result<0) goto seek_error;
1599
1600 if(link!=vf->current_link){
1601 /* Different link; dump entire decode machine */
1602 _decode_clear(vf);
1603
1604 vf->current_link=link;
1605 vf->current_serialno=vf->serialnos[link];
1606 vf->ready_state=STREAMSET;
1607
1608 }else{
1609 vorbis_synthesis_restart(&vf->vd);
1610 }
1611
1612 ogg_stream_reset_serialno(&vf->os,vf->current_serialno);
1613 ogg_stream_pagein(&vf->os,&og);
1614
1615 /* pull out all but last packet; the one with granulepos */
1616 while(1){
1617 result=ogg_stream_packetpeek(&vf->os,&op);
1618 if(result==0){
1619 /* No packet returned; we exited the bisection with 'best'
1620 pointing to a page with a granule position, so the packet
1621 finishing this page ('best') originated on a preceding
1622 page. Keep fetching previous pages until we get one with
1623 a granulepos or without the 'continued' flag set. Then
1624 just use raw_seek for simplicity. */
1625 /* Do not rewind past the beginning of link data; if we do,
1626 it's either a bug or a broken stream */
1627 result=best;
1628 while(result>vf->dataoffsets[link]){
1629 result=_get_prev_page(vf,result,&og);
1630 if(result<0) goto seek_error;
1631 if(ogg_page_serialno(&og)==vf->current_serialno &&
1632 (ogg_page_granulepos(&og)>-1 ||
1633 !ogg_page_continued(&og))){
1634 return ov_raw_seek(vf,result);
1635 }
1636 }
1637 }
1638 if(result<0){
1639 result = OV_EBADPACKET;
1640 goto seek_error;
1641 }
1642 if(op.granulepos!=-1){
1643 vf->pcm_offset=op.granulepos-vf->pcmlengths[vf->current_link*2];
1644 if(vf->pcm_offset<0)vf->pcm_offset=0;
1645 vf->pcm_offset+=total;
1646 break;
1647 }else
1648 result=ogg_stream_packetout(&vf->os,NULL);
1649 }
1650 }
1651 }
1652
1653 /* verify result */
1654 if(vf->pcm_offset>pos || pos>ov_pcm_total(vf,-1)){
1655 result=OV_EFAULT;
1656 goto seek_error;
1657 }
1658 vf->bittrack=0.f;
1659 vf->samptrack=0.f;
1660 return(0);
1661
1662 seek_error:
1663 /* dump machine so we're in a known state */
1664 vf->pcm_offset=-1;
1665 _decode_clear(vf);
1666 return (int)result;
1667}
1668
1669/* seek to a sample offset relative to the decompressed pcm stream
1670 returns zero on success, nonzero on failure */
1671
1672int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos){
1673 int thisblock,lastblock=0;
1674 int ret=ov_pcm_seek_page(vf,pos);
1675 if(ret<0)return(ret);
1676 if((ret=_make_decode_ready(vf)))return ret;
1677
1678 /* discard leading packets we don't need for the lapping of the
1679 position we want; don't decode them */
1680
1681 while(1){
1682 ogg_packet op;
1683 ogg_page og;
1684
1685 ret=ogg_stream_packetpeek(&vf->os,&op);
1686 if(ret>0){
1687 thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op);
1688 if(thisblock<0){
1689 ogg_stream_packetout(&vf->os,NULL);
1690 continue; /* non audio packet */
1691 }
1692 if(lastblock)vf->pcm_offset+=(lastblock+thisblock)>>2;
1693
1694 if(vf->pcm_offset+((thisblock+
1695 vorbis_info_blocksize(vf->vi,1))>>2)>=pos)break;
1696
1697 /* remove the packet from packet queue and track its granulepos */
1698 ogg_stream_packetout(&vf->os,NULL);
1699 vorbis_synthesis_trackonly(&vf->vb,&op); /* set up a vb with
1700 only tracking, no
1701 pcm_decode */
1702 vorbis_synthesis_blockin(&vf->vd,&vf->vb);
1703
1704 /* end of logical stream case is hard, especially with exact
1705 length positioning. */
1706
1707 if(op.granulepos>-1){
1708 int i;
1709 /* always believe the stream markers */
1710 vf->pcm_offset=op.granulepos-vf->pcmlengths[vf->current_link*2];
1711 if(vf->pcm_offset<0)vf->pcm_offset=0;
1712 for(i=0;i<vf->current_link;i++)
1713 vf->pcm_offset+=vf->pcmlengths[i*2+1];
1714 }
1715
1716 lastblock=thisblock;
1717
1718 }else{
1719 if(ret<0 && ret!=OV_HOLE)break;
1720
1721 /* suck in a new page */
1722 if(_get_next_page(vf,&og,-1)<0)break;
1723 if(ogg_page_bos(&og))_decode_clear(vf);
1724
1725 if(vf->ready_state<STREAMSET){
1726 long serialno=ogg_page_serialno(&og);
1727 int link;
1728
1729 for(link=0;link<vf->links;link++)
1730 if(vf->serialnos[link]==serialno)break;
1731 if(link==vf->links) continue;
1732 vf->current_link=link;
1733
1734 vf->ready_state=STREAMSET;
1735 vf->current_serialno=ogg_page_serialno(&og);
1736 ogg_stream_reset_serialno(&vf->os,serialno);
1737 ret=_make_decode_ready(vf);
1738 if(ret)return ret;
1739 lastblock=0;
1740 }
1741
1742 ogg_stream_pagein(&vf->os,&og);
1743 }
1744 }
1745
1746 vf->bittrack=0.f;
1747 vf->samptrack=0.f;
1748 /* discard samples until we reach the desired position. Crossing a
1749 logical bitstream boundary with abandon is OK. */
1750 {
1751 /* note that halfrate could be set differently in each link, but
1752 vorbisfile encoforces all links are set or unset */
1753 int hs=vorbis_synthesis_halfrate_p(vf->vi);
1754 while(vf->pcm_offset<((pos>>hs)<<hs)){
1755 ogg_int64_t target=(pos-vf->pcm_offset)>>hs;
1756 long samples=vorbis_synthesis_pcmout(&vf->vd,NULL);
1757
1758 if(samples>target)samples=target;
1759 vorbis_synthesis_read(&vf->vd,samples);
1760 vf->pcm_offset+=samples<<hs;
1761
1762 if(samples<target)
1763 if(_fetch_and_process_packet(vf,NULL,1,1)<=0)
1764 vf->pcm_offset=ov_pcm_total(vf,-1); /* eof */
1765 }
1766 }
1767 return 0;
1768}
1769
1770/* seek to a playback time relative to the decompressed pcm stream
1771 returns zero on success, nonzero on failure */
1772int ov_time_seek(OggVorbis_File *vf,double seconds){
1773 /* translate time to PCM position and call ov_pcm_seek */
1774
1775 int link=-1;
1776 ogg_int64_t pcm_total=0;
1777 double time_total=0.;
1778
1779 if(vf->ready_state<OPENED)return(OV_EINVAL);
1780 if(!vf->seekable)return(OV_ENOSEEK);
1781 if(seconds<0)return(OV_EINVAL);
1782
1783 /* which bitstream section does this time offset occur in? */
1784 for(link=0;link<vf->links;link++){
1785 double addsec = ov_time_total(vf,link);
1786 if(seconds<time_total+addsec)break;
1787 time_total+=addsec;
1788 pcm_total+=vf->pcmlengths[link*2+1];
1789 }
1790
1791 if(link==vf->links)return(OV_EINVAL);
1792
1793 /* enough information to convert time offset to pcm offset */
1794 {
1795 ogg_int64_t target=pcm_total+(seconds-time_total)*vf->vi[link].rate;
1796 return(ov_pcm_seek(vf,target));
1797 }
1798}
1799
1800/* page-granularity version of ov_time_seek
1801 returns zero on success, nonzero on failure */
1802int ov_time_seek_page(OggVorbis_File *vf,double seconds){
1803 /* translate time to PCM position and call ov_pcm_seek */
1804
1805 int link=-1;
1806 ogg_int64_t pcm_total=0;
1807 double time_total=0.;
1808
1809 if(vf->ready_state<OPENED)return(OV_EINVAL);
1810 if(!vf->seekable)return(OV_ENOSEEK);
1811 if(seconds<0)return(OV_EINVAL);
1812
1813 /* which bitstream section does this time offset occur in? */
1814 for(link=0;link<vf->links;link++){
1815 double addsec = ov_time_total(vf,link);
1816 if(seconds<time_total+addsec)break;
1817 time_total+=addsec;
1818 pcm_total+=vf->pcmlengths[link*2+1];
1819 }
1820
1821 if(link==vf->links)return(OV_EINVAL);
1822
1823 /* enough information to convert time offset to pcm offset */
1824 {
1825 ogg_int64_t target=pcm_total+(seconds-time_total)*vf->vi[link].rate;
1826 return(ov_pcm_seek_page(vf,target));
1827 }
1828}
1829
1830/* tell the current stream offset cursor. Note that seek followed by
1831 tell will likely not give the set offset due to caching */
1832ogg_int64_t ov_raw_tell(OggVorbis_File *vf){
1833 if(vf->ready_state<OPENED)return(OV_EINVAL);
1834 return(vf->offset);
1835}
1836
1837/* return PCM offset (sample) of next PCM sample to be read */
1838ogg_int64_t ov_pcm_tell(OggVorbis_File *vf){
1839 if(vf->ready_state<OPENED)return(OV_EINVAL);
1840 return(vf->pcm_offset);
1841}
1842
1843/* return time offset (seconds) of next PCM sample to be read */
1844double ov_time_tell(OggVorbis_File *vf){
1845 int link=0;
1846 ogg_int64_t pcm_total=0;
1847 double time_total=0.f;
1848
1849 if(vf->ready_state<OPENED)return(OV_EINVAL);
1850 if(vf->seekable){
1851 pcm_total=ov_pcm_total(vf,-1);
1852 time_total=ov_time_total(vf,-1);
1853
1854 /* which bitstream section does this time offset occur in? */
1855 for(link=vf->links-1;link>=0;link--){
1856 pcm_total-=vf->pcmlengths[link*2+1];
1857 time_total-=ov_time_total(vf,link);
1858 if(vf->pcm_offset>=pcm_total)break;
1859 }
1860 }
1861
1862 return((double)time_total+(double)(vf->pcm_offset-pcm_total)/vf->vi[link].rate);
1863}
1864
1865/* link: -1) return the vorbis_info struct for the bitstream section
1866 currently being decoded
1867 0-n) to request information for a specific bitstream section
1868
1869 In the case of a non-seekable bitstream, any call returns the
1870 current bitstream. NULL in the case that the machine is not
1871 initialized */
1872
1873vorbis_info *ov_info(OggVorbis_File *vf,int link){
1874 if(vf->seekable){
1875 if(link<0)
1876 if(vf->ready_state>=STREAMSET)
1877 return vf->vi+vf->current_link;
1878 else
1879 return vf->vi;
1880 else
1881 if(link>=vf->links)
1882 return NULL;
1883 else
1884 return vf->vi+link;
1885 }else{
1886 return vf->vi;
1887 }
1888}
1889
1890/* grr, strong typing, grr, no templates/inheritence, grr */
1891vorbis_comment *ov_comment(OggVorbis_File *vf,int link){
1892 if(vf->seekable){
1893 if(link<0)
1894 if(vf->ready_state>=STREAMSET)
1895 return vf->vc+vf->current_link;
1896 else
1897 return vf->vc;
1898 else
1899 if(link>=vf->links)
1900 return NULL;
1901 else
1902 return vf->vc+link;
1903 }else{
1904 return vf->vc;
1905 }
1906}
1907
1908static int host_is_big_endian() {
1909 ogg_int32_t pattern = 0xfeedface; /* deadbeef */
1910 unsigned char *bytewise = (unsigned char *)&pattern;
1911 if (bytewise[0] == 0xfe) return 1;
1912 return 0;
1913}
1914
1915/* up to this point, everything could more or less hide the multiple
1916 logical bitstream nature of chaining from the toplevel application
1917 if the toplevel application didn't particularly care. However, at
1918 the point that we actually read audio back, the multiple-section
1919 nature must surface: Multiple bitstream sections do not necessarily
1920 have to have the same number of channels or sampling rate.
1921
1922 ov_read returns the sequential logical bitstream number currently
1923 being decoded along with the PCM data in order that the toplevel
1924 application can take action on channel/sample rate changes. This
1925 number will be incremented even for streamed (non-seekable) streams
1926 (for seekable streams, it represents the actual logical bitstream
1927 index within the physical bitstream. Note that the accessor
1928 functions above are aware of this dichotomy).
1929
1930 ov_read_filter is exactly the same as ov_read except that it processes
1931 the decoded audio data through a filter before packing it into the
1932 requested format. This gives greater accuracy than applying a filter
1933 after the audio has been converted into integral PCM.
1934
1935 input values: buffer) a buffer to hold packed PCM data for return
1936 length) the byte length requested to be placed into buffer
1937 bigendianp) should the data be packed LSB first (0) or
1938 MSB first (1)
1939 word) word size for output. currently 1 (byte) or
1940 2 (16 bit short)
1941
1942 return values: <0) error/hole in data (OV_HOLE), partial open (OV_EINVAL)
1943 0) EOF
1944 n) number of bytes of PCM actually returned. The
1945 below works on a packet-by-packet basis, so the
1946 return length is not related to the 'length' passed
1947 in, just guaranteed to fit.
1948
1949 *section) set to the logical bitstream number */
1950
1951long ov_read_filter(OggVorbis_File *vf,char *buffer,int length,
1952 int bigendianp,int word,int sgned,int *bitstream,
1953 void (*filter)(float **pcm,long channels,long samples,void *filter_param),void *filter_param){
1954 int i,j;
1955 int host_endian = host_is_big_endian();
1956 int hs;
1957
1958 float **pcm;
1959 long samples;
1960
1961 if(vf->ready_state<OPENED)return(OV_EINVAL);
1962 if(word<=0)return(OV_EINVAL);
1963
1964 while(1){
1965 if(vf->ready_state==INITSET){
1966 samples=vorbis_synthesis_pcmout(&vf->vd,&pcm);
1967 if(samples)break;
1968 }
1969
1970 /* suck in another packet */
1971 {
1972 int ret=_fetch_and_process_packet(vf,NULL,1,1);
1973 if(ret==OV_EOF)
1974 return(0);
1975 if(ret<=0)
1976 return(ret);
1977 }
1978
1979 }
1980
1981 if(samples>0){
1982
1983 /* yay! proceed to pack data into the byte buffer */
1984
1985 long channels=ov_info(vf,-1)->channels;
1986 long bytespersample=word * channels;
1987 vorbis_fpu_control fpu;
1988
1989 if(channels<1||channels>255)return(OV_EINVAL);
1990 if(samples>length/bytespersample)samples=length/bytespersample;
1991
1992 if(samples <= 0)
1993 return OV_EINVAL;
1994
1995 /* Here. */
1996 if(filter)
1997 filter(pcm,channels,samples,filter_param);
1998
1999 /* a tight loop to pack each size */
2000 {
2001 int val;
2002 if(word==1){
2003 int off=(sgned?0:128);
2004 vorbis_fpu_setround(&fpu);
2005 for(j=0;j<samples;j++)
2006 for(i=0;i<channels;i++){
2007 val=vorbis_ftoi(pcm[i][j]*128.f);
2008 if(val>127)val=127;
2009 else if(val<-128)val=-128;
2010 *buffer++=val+off;
2011 }
2012 vorbis_fpu_restore(fpu);
2013 }else{
2014 int off=(sgned?0:32768);
2015
2016 if(host_endian==bigendianp){
2017 if(sgned){
2018
2019 vorbis_fpu_setround(&fpu);
2020 for(i=0;i<channels;i++) { /* It's faster in this order */
2021 float *src=pcm[i];
2022 short *dest=((short *)buffer)+i;
2023 for(j=0;j<samples;j++) {
2024 val=vorbis_ftoi(src[j]*32768.f);
2025 if(val>32767)val=32767;
2026 else if(val<-32768)val=-32768;
2027 *dest=val;
2028 dest+=channels;
2029 }
2030 }
2031 vorbis_fpu_restore(fpu);
2032
2033 }else{
2034
2035 vorbis_fpu_setround(&fpu);
2036 for(i=0;i<channels;i++) {
2037 float *src=pcm[i];
2038 short *dest=((short *)buffer)+i;
2039 for(j=0;j<samples;j++) {
2040 val=vorbis_ftoi(src[j]*32768.f);
2041 if(val>32767)val=32767;
2042 else if(val<-32768)val=-32768;
2043 *dest=val+off;
2044 dest+=channels;
2045 }
2046 }
2047 vorbis_fpu_restore(fpu);
2048
2049 }
2050 }else if(bigendianp){
2051
2052 vorbis_fpu_setround(&fpu);
2053 for(j=0;j<samples;j++)
2054 for(i=0;i<channels;i++){
2055 val=vorbis_ftoi(pcm[i][j]*32768.f);
2056 if(val>32767)val=32767;
2057 else if(val<-32768)val=-32768;
2058 val+=off;
2059 *buffer++=(val>>8);
2060 *buffer++=(val&0xff);
2061 }
2062 vorbis_fpu_restore(fpu);
2063
2064 }else{
2065 vorbis_fpu_setround(&fpu);
2066 for(j=0;j<samples;j++)
2067 for(i=0;i<channels;i++){
2068 val=vorbis_ftoi(pcm[i][j]*32768.f);
2069 if(val>32767)val=32767;
2070 else if(val<-32768)val=-32768;
2071 val+=off;
2072 *buffer++=(val&0xff);
2073 *buffer++=(val>>8);
2074 }
2075 vorbis_fpu_restore(fpu);
2076
2077 }
2078 }
2079 }
2080
2081 vorbis_synthesis_read(&vf->vd,samples);
2082 hs=vorbis_synthesis_halfrate_p(vf->vi);
2083 vf->pcm_offset+=(samples<<hs);
2084 if(bitstream)*bitstream=vf->current_link;
2085 return(samples*bytespersample);
2086 }else{
2087 return(samples);
2088 }
2089}
2090
2091long ov_read(OggVorbis_File *vf,char *buffer,int length,
2092 int bigendianp,int word,int sgned,int *bitstream){
2093 return ov_read_filter(vf, buffer, length, bigendianp, word, sgned, bitstream, NULL, NULL);
2094}
2095
2096/* input values: pcm_channels) a float vector per channel of output
2097 length) the sample length being read by the app
2098
2099 return values: <0) error/hole in data (OV_HOLE), partial open (OV_EINVAL)
2100 0) EOF
2101 n) number of samples of PCM actually returned. The
2102 below works on a packet-by-packet basis, so the
2103 return length is not related to the 'length' passed
2104 in, just guaranteed to fit.
2105
2106 *section) set to the logical bitstream number */
2107
2108
2109
2110long ov_read_float(OggVorbis_File *vf,float ***pcm_channels,int length,
2111 int *bitstream){
2112
2113 if(vf->ready_state<OPENED)return(OV_EINVAL);
2114
2115 while(1){
2116 if(vf->ready_state==INITSET){
2117 float **pcm;
2118 long samples=vorbis_synthesis_pcmout(&vf->vd,&pcm);
2119 if(samples){
2120 int hs=vorbis_synthesis_halfrate_p(vf->vi);
2121 if(pcm_channels)*pcm_channels=pcm;
2122 if(samples>length)samples=length;
2123 vorbis_synthesis_read(&vf->vd,samples);
2124 vf->pcm_offset+=samples<<hs;
2125 if(bitstream)*bitstream=vf->current_link;
2126 return samples;
2127
2128 }
2129 }
2130
2131 /* suck in another packet */
2132 {
2133 int ret=_fetch_and_process_packet(vf,NULL,1,1);
2134 if(ret==OV_EOF)return(0);
2135 if(ret<=0)return(ret);
2136 }
2137
2138 }
2139}
2140
2141extern const float *vorbis_window(vorbis_dsp_state *v,int W);
2142
2143static void _ov_splice(float **pcm,float **lappcm,
2144 int n1, int n2,
2145 int ch1, int ch2,
2146 const float *w1, const float *w2){
2147 int i,j;
2148 const float *w=w1;
2149 int n=n1;
2150
2151 if(n1>n2){
2152 n=n2;
2153 w=w2;
2154 }
2155
2156 /* splice */
2157 for(j=0;j<ch1 && j<ch2;j++){
2158 float *s=lappcm[j];
2159 float *d=pcm[j];
2160
2161 for(i=0;i<n;i++){
2162 float wd=w[i]*w[i];
2163 float ws=1.-wd;
2164 d[i]=d[i]*wd + s[i]*ws;
2165 }
2166 }
2167 /* window from zero */
2168 for(;j<ch2;j++){
2169 float *d=pcm[j];
2170 for(i=0;i<n;i++){
2171 float wd=w[i]*w[i];
2172 d[i]=d[i]*wd;
2173 }
2174 }
2175
2176}
2177
2178/* make sure vf is INITSET */
2179static int _ov_initset(OggVorbis_File *vf){
2180 while(1){
2181 if(vf->ready_state==INITSET)break;
2182 /* suck in another packet */
2183 {
2184 int ret=_fetch_and_process_packet(vf,NULL,1,0);
2185 if(ret<0 && ret!=OV_HOLE)return(ret);
2186 }
2187 }
2188 return 0;
2189}
2190
2191/* make sure vf is INITSET and that we have a primed buffer; if
2192 we're crosslapping at a stream section boundary, this also makes
2193 sure we're sanity checking against the right stream information */
2194static int _ov_initprime(OggVorbis_File *vf){
2195 vorbis_dsp_state *vd=&vf->vd;
2196 while(1){
2197 if(vf->ready_state==INITSET)
2198 if(vorbis_synthesis_pcmout(vd,NULL))break;
2199
2200 /* suck in another packet */
2201 {
2202 int ret=_fetch_and_process_packet(vf,NULL,1,0);
2203 if(ret<0 && ret!=OV_HOLE)return(ret);
2204 }
2205 }
2206 return 0;
2207}
2208
2209/* grab enough data for lapping from vf; this may be in the form of
2210 unreturned, already-decoded pcm, remaining PCM we will need to
2211 decode, or synthetic postextrapolation from last packets. */
2212static void _ov_getlap(OggVorbis_File *vf,vorbis_info *vi,vorbis_dsp_state *vd,
2213 float **lappcm,int lapsize){
2214 int lapcount=0,i;
2215 float **pcm;
2216
2217 /* try first to decode the lapping data */
2218 while(lapcount<lapsize){
2219 int samples=vorbis_synthesis_pcmout(vd,&pcm);
2220 if(samples){
2221 if(samples>lapsize-lapcount)samples=lapsize-lapcount;
2222 for(i=0;i<vi->channels;i++)
2223 memcpy(lappcm[i]+lapcount,pcm[i],sizeof(**pcm)*samples);
2224 lapcount+=samples;
2225 vorbis_synthesis_read(vd,samples);
2226 }else{
2227 /* suck in another packet */
2228 int ret=_fetch_and_process_packet(vf,NULL,1,0); /* do *not* span */
2229 if(ret==OV_EOF)break;
2230 }
2231 }
2232 if(lapcount<lapsize){
2233 /* failed to get lapping data from normal decode; pry it from the
2234 postextrapolation buffering, or the second half of the MDCT
2235 from the last packet */
2236 int samples=vorbis_synthesis_lapout(&vf->vd,&pcm);
2237 if(samples==0){
2238 for(i=0;i<vi->channels;i++)
2239 memset(lappcm[i]+lapcount,0,sizeof(**pcm)*lapsize-lapcount);
2240 lapcount=lapsize;
2241 }else{
2242 if(samples>lapsize-lapcount)samples=lapsize-lapcount;
2243 for(i=0;i<vi->channels;i++)
2244 memcpy(lappcm[i]+lapcount,pcm[i],sizeof(**pcm)*samples);
2245 lapcount+=samples;
2246 }
2247 }
2248}
2249
2250/* this sets up crosslapping of a sample by using trailing data from
2251 sample 1 and lapping it into the windowing buffer of sample 2 */
2252int ov_crosslap(OggVorbis_File *vf1, OggVorbis_File *vf2){
2253 vorbis_info *vi1,*vi2;
2254 float **lappcm;
2255 float **pcm;
2256 const float *w1,*w2;
2257 int n1,n2,i,ret,hs1,hs2;
2258
2259 if(vf1==vf2)return(0); /* degenerate case */
2260 if(vf1->ready_state<OPENED)return(OV_EINVAL);
2261 if(vf2->ready_state<OPENED)return(OV_EINVAL);
2262
2263 /* the relevant overlap buffers must be pre-checked and pre-primed
2264 before looking at settings in the event that priming would cross
2265 a bitstream boundary. So, do it now */
2266
2267 ret=_ov_initset(vf1);
2268 if(ret)return(ret);
2269 ret=_ov_initprime(vf2);
2270 if(ret)return(ret);
2271
2272 vi1=ov_info(vf1,-1);
2273 vi2=ov_info(vf2,-1);
2274 hs1=ov_halfrate_p(vf1);
2275 hs2=ov_halfrate_p(vf2);
2276
2277 lappcm=alloca(sizeof(*lappcm)*vi1->channels);
2278 n1=vorbis_info_blocksize(vi1,0)>>(1+hs1);
2279 n2=vorbis_info_blocksize(vi2,0)>>(1+hs2);
2280 w1=vorbis_window(&vf1->vd,0);
2281 w2=vorbis_window(&vf2->vd,0);
2282
2283 for(i=0;i<vi1->channels;i++)
2284 lappcm[i]=alloca(sizeof(**lappcm)*n1);
2285
2286 _ov_getlap(vf1,vi1,&vf1->vd,lappcm,n1);
2287
2288 /* have a lapping buffer from vf1; now to splice it into the lapping
2289 buffer of vf2 */
2290 /* consolidate and expose the buffer. */
2291 vorbis_synthesis_lapout(&vf2->vd,&pcm);
2292
2293#if 0
2294 _analysis_output_always("pcmL",0,pcm[0],n1*2,0,0,0);
2295 _analysis_output_always("pcmR",0,pcm[1],n1*2,0,0,0);
2296#endif
2297
2298 /* splice */
2299 _ov_splice(pcm,lappcm,n1,n2,vi1->channels,vi2->channels,w1,w2);
2300
2301 /* done */
2302 return(0);
2303}
2304
2305static int _ov_64_seek_lap(OggVorbis_File *vf,ogg_int64_t pos,
2306 int (*localseek)(OggVorbis_File *,ogg_int64_t)){
2307 vorbis_info *vi;
2308 float **lappcm;
2309 float **pcm;
2310 const float *w1,*w2;
2311 int n1,n2,ch1,ch2,hs;
2312 int i,ret;
2313
2314 if(vf->ready_state<OPENED)return(OV_EINVAL);
2315 ret=_ov_initset(vf);
2316 if(ret)return(ret);
2317 vi=ov_info(vf,-1);
2318 hs=ov_halfrate_p(vf);
2319
2320 ch1=vi->channels;
2321 n1=vorbis_info_blocksize(vi,0)>>(1+hs);
2322 w1=vorbis_window(&vf->vd,0); /* window arrays from libvorbis are
2323 persistent; even if the decode state
2324 from this link gets dumped, this
2325 window array continues to exist */
2326
2327 lappcm=alloca(sizeof(*lappcm)*ch1);
2328 for(i=0;i<ch1;i++)
2329 lappcm[i]=alloca(sizeof(**lappcm)*n1);
2330 _ov_getlap(vf,vi,&vf->vd,lappcm,n1);
2331
2332 /* have lapping data; seek and prime the buffer */
2333 ret=localseek(vf,pos);
2334 if(ret)return ret;
2335 ret=_ov_initprime(vf);
2336 if(ret)return(ret);
2337
2338 /* Guard against cross-link changes; they're perfectly legal */
2339 vi=ov_info(vf,-1);
2340 ch2=vi->channels;
2341 n2=vorbis_info_blocksize(vi,0)>>(1+hs);
2342 w2=vorbis_window(&vf->vd,0);
2343
2344 /* consolidate and expose the buffer. */
2345 vorbis_synthesis_lapout(&vf->vd,&pcm);
2346
2347 /* splice */
2348 _ov_splice(pcm,lappcm,n1,n2,ch1,ch2,w1,w2);
2349
2350 /* done */
2351 return(0);
2352}
2353
2354int ov_raw_seek_lap(OggVorbis_File *vf,ogg_int64_t pos){
2355 return _ov_64_seek_lap(vf,pos,ov_raw_seek);
2356}
2357
2358int ov_pcm_seek_lap(OggVorbis_File *vf,ogg_int64_t pos){
2359 return _ov_64_seek_lap(vf,pos,ov_pcm_seek);
2360}
2361
2362int ov_pcm_seek_page_lap(OggVorbis_File *vf,ogg_int64_t pos){
2363 return _ov_64_seek_lap(vf,pos,ov_pcm_seek_page);
2364}
2365
2366static int _ov_d_seek_lap(OggVorbis_File *vf,double pos,
2367 int (*localseek)(OggVorbis_File *,double)){
2368 vorbis_info *vi;
2369 float **lappcm;
2370 float **pcm;
2371 const float *w1,*w2;
2372 int n1,n2,ch1,ch2,hs;
2373 int i,ret;
2374
2375 if(vf->ready_state<OPENED)return(OV_EINVAL);
2376 ret=_ov_initset(vf);
2377 if(ret)return(ret);
2378 vi=ov_info(vf,-1);
2379 hs=ov_halfrate_p(vf);
2380
2381 ch1=vi->channels;
2382 n1=vorbis_info_blocksize(vi,0)>>(1+hs);
2383 w1=vorbis_window(&vf->vd,0); /* window arrays from libvorbis are
2384 persistent; even if the decode state
2385 from this link gets dumped, this
2386 window array continues to exist */
2387
2388 lappcm=alloca(sizeof(*lappcm)*ch1);
2389 for(i=0;i<ch1;i++)
2390 lappcm[i]=alloca(sizeof(**lappcm)*n1);
2391 _ov_getlap(vf,vi,&vf->vd,lappcm,n1);
2392
2393 /* have lapping data; seek and prime the buffer */
2394 ret=localseek(vf,pos);
2395 if(ret)return ret;
2396 ret=_ov_initprime(vf);
2397 if(ret)return(ret);
2398
2399 /* Guard against cross-link changes; they're perfectly legal */
2400 vi=ov_info(vf,-1);
2401 ch2=vi->channels;
2402 n2=vorbis_info_blocksize(vi,0)>>(1+hs);
2403 w2=vorbis_window(&vf->vd,0);
2404
2405 /* consolidate and expose the buffer. */
2406 vorbis_synthesis_lapout(&vf->vd,&pcm);
2407
2408 /* splice */
2409 _ov_splice(pcm,lappcm,n1,n2,ch1,ch2,w1,w2);
2410
2411 /* done */
2412 return(0);
2413}
2414
2415int ov_time_seek_lap(OggVorbis_File *vf,double pos){
2416 return _ov_d_seek_lap(vf,pos,ov_time_seek);
2417}
2418
2419int ov_time_seek_page_lap(OggVorbis_File *vf,double pos){
2420 return _ov_d_seek_lap(vf,pos,ov_time_seek_page);
2421}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use