zenilib: zenilib/jni/external/libvorbis/lib/vorbisfile.c Source File

zenilib 0.5.3.0

- Main Page
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

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