dbf-halloween2015
view libs/vorbis/vorbisfile.c @ 3:c37fe5d8a4ed
windows port
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sun, 01 Nov 2015 06:04:28 +0200 |
parents | |
children |
line source
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 ********************************************************************
13 function: stdio-based convenience library for opening/seeking/decoding
14 last mod: $Id: vorbisfile.c 17573 2010-10-27 14:53:59Z xiphmont $
16 ********************************************************************/
18 #include <stdlib.h>
19 #include <stdio.h>
20 #include <errno.h>
21 #include <string.h>
22 #include <math.h>
24 #include "vorbis/codec.h"
26 /* we don't need or want the static callback symbols here */
27 #define OV_EXCLUDE_STATIC_CALLBACKS
28 #include "vorbis/vorbisfile.h"
30 #include "os.h"
31 #include "misc.h"
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) */
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. */
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. */
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. */
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 */
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. */
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 }
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 }
95 /* The read/seek functions track absolute position within the stream */
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.
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
105 return: <0) did not find a page (OV_FALSE, OV_EOF, OV_EREAD)
106 n) found a page at absolute offset n */
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;
114 if(boundary>0 && vf->offset>=boundary)return(OV_FALSE);
115 more=ogg_sync_pageseek(&vf->oy,og);
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);
136 }
137 }
138 }
139 }
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;
152 while(offset==-1){
153 begin-=CHUNKSIZE;
154 if(begin<0)
155 begin=0;
157 ret=_seek_helper(vf,begin);
158 if(ret)return(ret);
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 }
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);
179 ret=_get_next_page(vf,og,CHUNKSIZE);
180 if(ret<0)
181 /* this shouldn't be possible */
182 return(OV_EFAULT);
183 }
185 return(offset);
186 }
188 static void _add_serialno(ogg_page *og,long **serialno_list, int *n){
189 long s = ogg_page_serialno(og);
190 (*n)++;
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 }
198 (*serialno_list)[(*n)-1] = s;
199 }
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 }
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 }
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;
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;
236 while(offset==-1){
237 begin-=CHUNKSIZE;
238 if(begin<0)
239 begin=0;
241 ret=_seek_helper(vf,begin);
242 if(ret)return(ret);
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;
254 if(ret_serialno == *serialno){
255 prefoffset=ret;
256 *granpos=ret_gran;
257 }
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 }
270 /* we're not interested in the page... just the serialno and granpos. */
271 if(prefoffset>=0)return(prefoffset);
273 *serialno = ret_serialno;
274 *granpos = ret_gran;
275 return(offset);
277 }
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;
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 }
296 vorbis_info_init(vi);
297 vorbis_comment_init(vc);
298 vf->ready_state=OPENED;
300 /* extract the serialnos of all BOS pages + the first set of vorbis
301 headers we see in the link */
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 }
314 _add_serialno(og_ptr,serialno_list,serialno_n);
315 }
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);
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 }
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 }
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 }
355 if(vf->ready_state!=STREAMSET){
356 ret = OV_ENOTVORBIS;
357 goto bail_header;
358 }
360 while(1){
362 i=0;
363 while(i<2){ /* get a page loop */
365 while(i<2){ /* get a packet loop */
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 }
374 if((ret=vorbis_synthesis_headerin(vi,vc,&op)))
375 goto bail_header;
377 i++;
378 }
380 while(i<2){
381 if(_get_next_page(vf,og_ptr,CHUNKSIZE)<0){
382 ret=OV_EBADHEADER;
383 goto bail_header;
384 }
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 }
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 }
402 /* otherwise, keep looking */
403 }
404 }
406 return 0;
407 }
409 bail_header:
410 vorbis_info_clear(vi);
411 vorbis_comment_clear(vc);
412 vf->ready_state=OPENED;
414 return ret;
415 }
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;
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 */
433 if(ogg_page_bos(&og)) break;
434 if(ogg_page_serialno(&og)!=serialno) continue;
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 }
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 }
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;
459 return accumulated;
460 }
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;
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 */
490 /* Is the last page in our list of current serialnumbers? */
491 if(_lookup_serialno(endserial,currentno_list,currentnos)){
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. */
498 while(endserial != serialno){
499 endserial = serialno;
500 vf->offset=_get_prev_page_serial(vf,currentno_list,currentnos,&endserial,&endgran);
501 }
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);
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));
515 vf->offsets[m+1]=end;
516 vf->offsets[m]=begin;
517 vf->pcmlengths[m*2+1]=(endgran<0?0:endgran);
519 }else{
521 long *next_serialno_list=NULL;
522 int next_serialnos=0;
523 vorbis_info vi;
524 vorbis_comment vc;
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;
531 if(endsearched-searched<CHUNKSIZE){
532 bisect=searched;
533 }else{
534 bisect=(searched+endsearched)/2;
535 }
537 if(bisect != vf->offset){
538 ret=_seek_helper(vf,bisect);
539 if(ret)return(ret);
540 }
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 }
552 /* Bisection point found */
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 }
564 if(vf->offset!=next){
565 ret=_seek_helper(vf,next);
566 if(ret)return(ret);
567 }
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;
574 /* this will consume a page, however the next bistection always
575 starts with a raw seek */
576 pcmoffset = _initial_pcmoffset(vf,&vi);
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);
582 if(next_serialno_list)_ogg_free(next_serialno_list);
584 vf->offsets[m+1]=next;
585 vf->serialnos[m+1]=serialno;
586 vf->dataoffsets[m+1]=dataoffset;
588 vf->vi[m+1]=vi;
589 vf->vc[m+1]=vc;
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 }
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 }
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;
621 /* we're partially open and have a first link header state in
622 storage in vf */
624 /* fetch initial PCM offset */
625 ogg_int64_t pcmoffset = _initial_pcmoffset(vf,vf->vi);
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 }
635 /* If seek_func is implemented, tell_func must also be implemented */
636 if(vf->end==-1) return(OV_EINVAL);
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);
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);
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;
655 return(ov_raw_seek(vf,dataoffset));
656 }
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 }
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).
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 */
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;
682 /* handle one packet. Try to fetch it from current stream state */
683 /* extract packets from page */
684 while(1){
686 if(vf->ready_state==STREAMSET){
687 int ret=_make_decode_ready(vf);
688 if(ret<0)return ret;
689 }
691 /* process a packet if we can. */
693 if(vf->ready_state==INITSET){
694 int hs=vorbis_synthesis_halfrate_p(vf->vi);
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;
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 */
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);
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 }
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;
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*
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 */
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 */
752 samples=(vorbis_synthesis_pcmout(&vf->vd,NULL)<<hs);
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 }
767 if(vf->ready_state>=OPENED){
768 ogg_int64_t ret;
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 */
777 if(!readp)return(0);
778 if((ret=_get_next_page(vf,&og,-1))<0){
779 return(OV_EOF); /* eof. leave unitialized */
780 }
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;
786 if(vf->ready_state==INITSET){
787 if(vf->current_serialno!=ogg_page_serialno(&og)){
789 /* two possibilities:
790 1) our decoding just traversed a bitstream boundary
791 2) another stream is multiplexed into this logical section */
793 if(ogg_page_bos(&og)){
794 /* boundary case */
795 if(!spanp)
796 return(OV_EOF);
798 _decode_clear(vf);
800 if(!vf->seekable){
801 vorbis_info_clear(vf->vi);
802 vorbis_comment_clear(vf->vc);
803 }
804 break;
806 }else
807 continue; /* possibility #2 */
808 }
809 }
811 break;
812 }
813 }
815 /* Do we need to load a new machine before submitting the page? */
816 /* This is different in the seekable and non-seekable cases.
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.
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 */
827 if(vf->ready_state!=INITSET){
828 int link;
830 if(vf->ready_state<STREAMSET){
831 if(vf->seekable){
832 long serialno = ogg_page_serialno(&og);
834 /* match the serialno to bitstream section. We use this rather than
835 offset positions to avoid problems near logical bitstream
836 boundaries */
838 for(link=0;link<vf->links;link++)
839 if(vf->serialnos[link]==serialno)break;
841 if(link==vf->links) continue; /* not the desired Vorbis
842 bitstream section; keep
843 trying */
845 vf->current_serialno=serialno;
846 vf->current_link=link;
848 ogg_stream_reset_serialno(&vf->os,vf->current_serialno);
849 vf->ready_state=STREAMSET;
851 }else{
852 /* we're streaming */
853 /* fetch the three header packets, build the info struct */
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 }
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);
868 }
869 }
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 }
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;
885 memset(vf,0,sizeof(*vf));
886 vf->datasource=f;
887 vf->callbacks = callbacks;
889 /* init the framing state */
890 ogg_sync_init(&vf->oy);
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 }
902 /* can we seek? Stevens suggests the seek test was portable */
903 if(offsettest!=-1)vf->seekable=1;
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 */
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));
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;
931 vf->ready_state=PARTOPEN;
932 }
933 if(serialno_list)_ogg_free(serialno_list);
934 return(ret);
935 }
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;
950 return 0;
951 }
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);
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 }
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.
989 return: -1) error
990 0) OK
991 */
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 }
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 };
1008 return ov_open_callbacks((void *)f, vf, initial, ibytes, callbacks);
1009 }
1011 int ov_fopen(const char *path,OggVorbis_File *vf){
1012 int ret;
1013 FILE *f = fopen(path,"rb");
1014 if(!f) return -1;
1016 ret = ov_open(f,vf,NULL,0);
1017 if(ret) fclose(f);
1018 return ret;
1019 }
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. */
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 }
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 }
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 }
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. */
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 }
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 };
1074 return ov_test_callbacks((void *)f, vf, initial, ibytes, callbacks);
1075 }
1077 int ov_test_open(OggVorbis_File *vf){
1078 if(vf->ready_state!=PARTOPEN)return(OV_EINVAL);
1079 return _ov_open2(vf);
1080 }
1082 /* How many logical bitstreams in this physical bitstream? */
1083 long ov_streams(OggVorbis_File *vf){
1084 return vf->links;
1085 }
1087 /* Is the FILE * associated with vf seekable? */
1088 long ov_seekable(OggVorbis_File *vf){
1089 return vf->seekable;
1090 }
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).
1098 If you want the actual bitrate field settings, get them from the
1099 vorbis_info structs */
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 }
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 }
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 }
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 }
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 }
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 }
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).
1227 returns zero on success, nonzero on failure */
1229 int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos){
1230 ogg_stream_state work_os;
1231 int ret;
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 */
1237 if(pos<0 || pos>vf->end)return(OV_EINVAL);
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 }
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);
1254 ret=_seek_helper(vf,pos);
1255 if(ret)goto seek_error;
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.
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.
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 */
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;
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 */
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);
1292 if(result>0){
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{
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 }
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;
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 }
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 }
1344 /* has our decoding just traversed a bitstream boundary? */
1345 if(vf->ready_state>=STREAMSET){
1346 if(vf->current_serialno!=ogg_page_serialno(&og)){
1348 /* two possibilities:
1349 1) our decoding just traversed a bitstream boundary
1350 2) another stream is multiplexed into this logical section? */
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 }
1360 if(vf->ready_state<STREAMSET){
1361 int link;
1362 long serialno = ogg_page_serialno(&og);
1364 for(link=0;link<vf->links;link++)
1365 if(vf->serialnos[link]==serialno)break;
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 }
1378 ogg_stream_pagein(&vf->os,&og);
1379 ogg_stream_pagein(&work_os,&og);
1380 lastflag=ogg_page_eos(&og);
1382 }
1383 }
1385 ogg_stream_clear(&work_os);
1386 vf->bittrack=0.f;
1387 vf->samptrack=0.f;
1388 return(0);
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 }
1398 /* Page granularity seek (faster than sample granularity because we
1399 don't do the last bit of decode to find a specific sample).
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);
1409 if(vf->ready_state<OPENED)return(OV_EINVAL);
1410 if(!vf->seekable)return(OV_ENOSEEK);
1412 if(pos<0 || pos>total)return(OV_EINVAL);
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 }
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) */
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;
1435 ogg_page og;
1436 while(begin<end){
1437 ogg_int64_t bisect;
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 }
1450 if(bisect!=vf->offset){
1451 result=_seek_helper(vf,bisect);
1452 if(result) goto seek_error;
1453 }
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;
1471 if(ogg_page_serialno(&og)!=vf->serialnos[link])
1472 continue;
1474 granulepos=ogg_page_granulepos(&og);
1475 if(granulepos==-1)continue;
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;
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 }
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;
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;
1518 if(link!=vf->current_link){
1519 /* Different link; dump entire decode machine */
1520 _decode_clear(vf);
1522 vf->current_link=link;
1523 vf->current_serialno=vf->serialnos[link];
1524 vf->ready_state=STREAMSET;
1526 }else{
1527 vorbis_synthesis_restart(&vf->vd);
1528 }
1530 ogg_stream_reset_serialno(&vf->os,vf->current_serialno);
1531 ogg_stream_pagein(&vf->os,&og);
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. */
1542 result=_seek_helper(vf,best);
1543 if(result<0) goto seek_error;
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 }
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);
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 }
1587 /* seek to a sample offset relative to the decompressed pcm stream
1588 returns zero on success, nonzero on failure */
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;
1596 /* discard leading packets we don't need for the lapping of the
1597 position we want; don't decode them */
1599 while(1){
1600 ogg_packet op;
1601 ogg_page og;
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;
1612 if(vf->pcm_offset+((thisblock+
1613 vorbis_info_blocksize(vf->vi,1))>>2)>=pos)break;
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);
1622 /* end of logical stream case is hard, especially with exact
1623 length positioning. */
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 }
1634 lastblock=thisblock;
1636 }else{
1637 if(ret<0 && ret!=OV_HOLE)break;
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);
1643 if(vf->ready_state<STREAMSET){
1644 long serialno=ogg_page_serialno(&og);
1645 int link;
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;
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 }
1660 ogg_stream_pagein(&vf->os,&og);
1661 }
1662 }
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);
1676 if(samples>target)samples=target;
1677 vorbis_synthesis_read(&vf->vd,samples);
1678 vf->pcm_offset+=samples<<hs;
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 }
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 */
1693 int link=-1;
1694 ogg_int64_t pcm_total=0;
1695 double time_total=0.;
1697 if(vf->ready_state<OPENED)return(OV_EINVAL);
1698 if(!vf->seekable)return(OV_ENOSEEK);
1699 if(seconds<0)return(OV_EINVAL);
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 }
1709 if(link==vf->links)return(OV_EINVAL);
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 }
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 */
1723 int link=-1;
1724 ogg_int64_t pcm_total=0;
1725 double time_total=0.;
1727 if(vf->ready_state<OPENED)return(OV_EINVAL);
1728 if(!vf->seekable)return(OV_ENOSEEK);
1729 if(seconds<0)return(OV_EINVAL);
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 }
1739 if(link==vf->links)return(OV_EINVAL);
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 }
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 }
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 }
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;
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);
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 }
1780 return((double)time_total+(double)(vf->pcm_offset-pcm_total)/vf->vi[link].rate);
1781 }
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
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 */
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 }
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 }
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 }
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.
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).
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.
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)
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.
1867 *section) set to the logical bitstream number */
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;
1876 float **pcm;
1877 long samples;
1879 if(vf->ready_state<OPENED)return(OV_EINVAL);
1881 while(1){
1882 if(vf->ready_state==INITSET){
1883 samples=vorbis_synthesis_pcmout(&vf->vd,&pcm);
1884 if(samples)break;
1885 }
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 }
1896 }
1898 if(samples>0){
1900 /* yay! proceed to pack data into the byte buffer */
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;
1907 if(samples <= 0)
1908 return OV_EINVAL;
1910 /* Here. */
1911 if(filter)
1912 filter(pcm,channels,samples,filter_param);
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);
1931 if(host_endian==bigendianp){
1932 if(sgned){
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);
1948 }else{
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);
1964 }
1965 }else if(bigendianp){
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);
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);
1993 }
1994 }
1995 }
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 }
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 }
2012 /* input values: pcm_channels) a float vector per channel of output
2013 length) the sample length being read by the app
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.
2022 *section) set to the logical bitstream number */
2026 long ov_read_float(OggVorbis_File *vf,float ***pcm_channels,int length,
2027 int *bitstream){
2029 if(vf->ready_state<OPENED)return(OV_EINVAL);
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;
2044 }
2045 }
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 }
2054 }
2055 }
2057 extern float *vorbis_window(vorbis_dsp_state *v,int W);
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;
2067 if(n1>n2){
2068 n=n2;
2069 w=w2;
2070 }
2072 /* splice */
2073 for(j=0;j<ch1 && j<ch2;j++){
2074 float *s=lappcm[j];
2075 float *d=pcm[j];
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 }
2092 }
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 }
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;
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 }
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;
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 }
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;
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);
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 */
2183 ret=_ov_initset(vf1);
2184 if(ret)return(ret);
2185 ret=_ov_initprime(vf2);
2186 if(ret)return(ret);
2188 vi1=ov_info(vf1,-1);
2189 vi2=ov_info(vf2,-1);
2190 hs1=ov_halfrate_p(vf1);
2191 hs2=ov_halfrate_p(vf2);
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);
2199 for(i=0;i<vi1->channels;i++)
2200 lappcm[i]=alloca(sizeof(**lappcm)*n1);
2202 _ov_getlap(vf1,vi1,&vf1->vd,lappcm,n1);
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);
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
2214 /* splice */
2215 _ov_splice(pcm,lappcm,n1,n2,vi1->channels,vi2->channels,w1,w2);
2217 /* done */
2218 return(0);
2219 }
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;
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);
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 */
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);
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);
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);
2260 /* consolidate and expose the buffer. */
2261 vorbis_synthesis_lapout(&vf->vd,&pcm);
2263 /* splice */
2264 _ov_splice(pcm,lappcm,n1,n2,ch1,ch2,w1,w2);
2266 /* done */
2267 return(0);
2268 }
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 }
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 }
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 }
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;
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);
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 */
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);
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);
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);
2321 /* consolidate and expose the buffer. */
2322 vorbis_synthesis_lapout(&vf->vd,&pcm);
2324 /* splice */
2325 _ov_splice(pcm,lappcm,n1,n2,ch1,ch2,w1,w2);
2327 /* done */
2328 return(0);
2329 }
2331 int ov_time_seek_lap(OggVorbis_File *vf,double pos){
2332 return _ov_d_seek_lap(vf,pos,ov_time_seek);
2333 }
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 }