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