1 /********************************************************************
3 * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. *
5 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
6 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
7 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
9 * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2003 *
10 * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ *
12 ********************************************************************
14 function: stdio-based convenience library for opening/seeking/decoding
15 last mod: $Id: vorbisfile.c,v 1.6 2003/03/30 23:40:56 xiphmont Exp $
17 ********************************************************************/
25 #include "ivorbiscodec.h"
26 #include "ivorbisfile.h"
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) */
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. */
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. */
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. */
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 */
60 /* read a little more data from the file/pipe into the ogg_sync framer */
61 static long _get_data(OggVorbis_File
*vf
){
64 unsigned char *buffer
=ogg_sync_bufferin(vf
->oy
,CHUNKSIZE
);
65 long bytes
=(vf
->callbacks
.read_func
)(buffer
,1,CHUNKSIZE
,vf
->datasource
);
66 if(bytes
>0)ogg_sync_wrote(vf
->oy
,bytes
);
67 if(bytes
==0 && errno
)return(-1);
73 /* save a tiny smidge of verbosity to make the code more readable */
74 static void _seek_helper(OggVorbis_File
*vf
,ogg_int64_t offset
){
76 (vf
->callbacks
.seek_func
)(vf
->datasource
, offset
, SEEK_SET
);
78 ogg_sync_reset(vf
->oy
);
80 /* shouldn't happen unless someone writes a broken callback */
85 /* The read/seek functions track absolute position within the stream */
87 /* from the head of the stream, get the next page. boundary specifies
88 if the function is allowed to fetch more data from the stream (and
89 how much) or only use internally buffered data.
91 boundary: -1) unbounded search
92 0) read no additional data; use cached only
93 n) search for a new page beginning for n bytes
95 return: <0) did not find a page (OV_FALSE, OV_EOF, OV_EREAD)
96 n) found a page at absolute offset n
98 produces a refcounted page */
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
;
106 if(boundary
>0 && vf
->offset
>=boundary
)return(OV_FALSE
);
107 more
=ogg_sync_pageseek(vf
->oy
,og
);
110 /* skipped n bytes */
114 /* send more paramedics */
115 if(!boundary
)return(OV_FALSE
);
117 long ret
=_get_data(vf
);
118 if(ret
==0)return(OV_EOF
);
119 if(ret
<0)return(OV_EREAD
);
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
;
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
137 /* returns offset or OV_EREAD, OV_FAULT and produces a refcounted page */
139 static ogg_int64_t
_get_prev_page(OggVorbis_File
*vf
,ogg_page
*og
){
140 ogg_int64_t begin
=vf
->offset
;
141 ogg_int64_t end
=begin
;
143 ogg_int64_t offset
=-1;
149 _seek_helper(vf
,begin
);
150 while(vf
->offset
<end
){
151 ret
=_get_next_page(vf
,og
,end
-vf
->offset
);
152 if(ret
==OV_EREAD
)return(OV_EREAD
);
161 /* we have the offset. Actually snork and hold the page now */
162 _seek_helper(vf
,offset
);
163 ret
=_get_next_page(vf
,og
,CHUNKSIZE
);
165 /* this shouldn't be possible */
171 /* finds each bitstream link one at a time using a bisection search
172 (has to begin by knowing the offset of the lb's initial page).
173 Recurses for each link so it can alloc the link storage after
174 finding them all, then unroll and fill the cache at the same time */
175 static int _bisect_forward_serialno(OggVorbis_File
*vf
,
177 ogg_int64_t searched
,
179 ogg_uint32_t currentno
,
181 ogg_int64_t endsearched
=end
;
182 ogg_int64_t next
=end
;
183 ogg_page og
={0,0,0,0};
186 /* the below guards against garbage seperating the last and
187 first pages of two links. */
188 while(searched
<endsearched
){
191 if(endsearched
-searched
<CHUNKSIZE
){
194 bisect
=(searched
+endsearched
)/2;
197 _seek_helper(vf
,bisect
);
198 ret
=_get_next_page(vf
,&og
,-1);
199 if(ret
==OV_EREAD
)return(OV_EREAD
);
200 if(ret
<0 || ogg_page_serialno(&og
)!=currentno
){
204 searched
=ret
+og
.header_len
+og
.body_len
;
206 ogg_page_release(&og
);
209 _seek_helper(vf
,next
);
210 ret
=_get_next_page(vf
,&og
,-1);
211 if(ret
==OV_EREAD
)return(OV_EREAD
);
213 if(searched
>=end
|| ret
<0){
214 ogg_page_release(&og
);
216 vf
->offsets
=_ogg_malloc((vf
->links
+1)*sizeof(*vf
->offsets
));
217 vf
->serialnos
=_ogg_malloc(vf
->links
*sizeof(*vf
->serialnos
));
218 vf
->offsets
[m
+1]=searched
;
220 ret
=_bisect_forward_serialno(vf
,next
,vf
->offset
,
221 end
,ogg_page_serialno(&og
),m
+1);
222 ogg_page_release(&og
);
223 if(ret
==OV_EREAD
)return(OV_EREAD
);
226 vf
->offsets
[m
]=begin
;
227 vf
->serialnos
[m
]=currentno
;
231 /* uses the local ogg_stream storage in vf; this is important for
232 non-streaming input sources */
233 /* consumes the page that's passed in (if any) */
235 static int _fetch_headers(OggVorbis_File
*vf
,
238 ogg_uint32_t
*serialno
,
240 ogg_page og
={0,0,0,0};
241 ogg_packet op
={0,0,0,0,0,0};
245 ogg_int64_t llret
=_get_next_page(vf
,&og
,CHUNKSIZE
);
246 if(llret
==OV_EREAD
)return(OV_EREAD
);
247 if(llret
<0)return OV_ENOTVORBIS
;
251 ogg_stream_reset_serialno(vf
->os
,ogg_page_serialno(og_ptr
));
252 if(serialno
)*serialno
=vf
->os
->serialno
;
253 vf
->ready_state
=STREAMSET
;
255 /* extract the initial header from the first page and verify that the
256 Ogg bitstream is in fact Vorbis data */
258 vorbis_info_init(vi
);
259 vorbis_comment_init(vc
);
263 ogg_stream_pagein(vf
->os
,og_ptr
);
265 int result
=ogg_stream_packetout(vf
->os
,&op
);
271 if((ret
=vorbis_synthesis_headerin(vi
,vc
,&op
))){
277 if(_get_next_page(vf
,og_ptr
,CHUNKSIZE
)<0){
283 ogg_packet_release(&op
);
284 ogg_page_release(&og
);
288 ogg_packet_release(&op
);
289 ogg_page_release(&og
);
290 vorbis_info_clear(vi
);
291 vorbis_comment_clear(vc
);
292 vf
->ready_state
=OPENED
;
297 /* last step of the OggVorbis_File initialization; get all the
298 vorbis_info structs and PCM positions. Only called by the seekable
299 initialization (local stream storage is hacked slightly; pay
300 attention to how that's done) */
302 /* this is void and does not propogate errors up because we want to be
303 able to open and use damaged bitstreams as well as we can. Just
304 watch out for missing information for links in the OggVorbis_File
306 static void _prefetch_all_headers(OggVorbis_File
*vf
, ogg_int64_t dataoffset
){
307 ogg_page og
={0,0,0,0};
311 vf
->vi
=_ogg_realloc(vf
->vi
,vf
->links
*sizeof(*vf
->vi
));
312 vf
->vc
=_ogg_realloc(vf
->vc
,vf
->links
*sizeof(*vf
->vc
));
313 vf
->dataoffsets
=_ogg_malloc(vf
->links
*sizeof(*vf
->dataoffsets
));
314 vf
->pcmlengths
=_ogg_malloc(vf
->links
*2*sizeof(*vf
->pcmlengths
));
316 for(i
=0;i
<vf
->links
;i
++){
318 /* we already grabbed the initial header earlier. Just set the offset */
319 vf
->dataoffsets
[i
]=dataoffset
;
320 _seek_helper(vf
,dataoffset
);
324 /* seek to the location of the initial header */
326 _seek_helper(vf
,vf
->offsets
[i
]);
327 if(_fetch_headers(vf
,vf
->vi
+i
,vf
->vc
+i
,NULL
,NULL
)<0){
328 vf
->dataoffsets
[i
]=-1;
330 vf
->dataoffsets
[i
]=vf
->offset
;
334 /* fetch beginning PCM offset */
336 if(vf
->dataoffsets
[i
]!=-1){
337 ogg_int64_t accumulated
=0,pos
;
341 ogg_stream_reset_serialno(vf
->os
,vf
->serialnos
[i
]);
344 ogg_packet op
={0,0,0,0,0,0};
346 ret
=_get_next_page(vf
,&og
,-1);
348 /* this should not be possible unless the file is
352 if(ogg_page_serialno(&og
)!=vf
->serialnos
[i
])
355 pos
=ogg_page_granulepos(&og
);
357 /* count blocksizes of all frames in the page */
358 ogg_stream_pagein(vf
->os
,&og
);
359 while((result
=ogg_stream_packetout(vf
->os
,&op
))){
360 if(result
>0){ /* ignore holes */
361 long thisblock
=vorbis_packet_blocksize(vf
->vi
+i
,&op
);
363 accumulated
+=(lastblock
+thisblock
)>>2;
367 ogg_packet_release(&op
);
370 /* pcm offset of last packet on the first audio page */
371 accumulated
= pos
-accumulated
;
376 /* less than zero? This is a stream with samples trimmed off
377 the beginning, a normal occurrence; set the offset to zero */
378 if(accumulated
<0)accumulated
=0;
380 vf
->pcmlengths
[i
*2]=accumulated
;
383 /* get the PCM length of this link. To do this,
384 get the last page of the stream */
386 ogg_int64_t end
=vf
->offsets
[i
+1];
387 _seek_helper(vf
,end
);
390 ret
=_get_prev_page(vf
,&og
);
392 /* this should not be possible */
393 vorbis_info_clear(vf
->vi
+i
);
394 vorbis_comment_clear(vf
->vc
+i
);
397 if(ogg_page_granulepos(&og
)!=-1){
398 vf
->pcmlengths
[i
*2+1]=ogg_page_granulepos(&og
)-vf
->pcmlengths
[i
*2];
405 ogg_page_release(&og
);
408 static void _make_decode_ready(OggVorbis_File
*vf
){
409 if(vf
->ready_state
!=STREAMSET
)return;
411 vorbis_synthesis_init(&vf
->vd
,vf
->vi
+vf
->current_link
);
413 vorbis_synthesis_init(&vf
->vd
,vf
->vi
);
415 vorbis_block_init(&vf
->vd
,&vf
->vb
);
416 vf
->ready_state
=INITSET
;
422 static int _open_seekable2(OggVorbis_File
*vf
){
423 ogg_uint32_t serialno
=vf
->current_serialno
;
424 ogg_uint32_t tempserialno
;
425 ogg_int64_t dataoffset
=vf
->offset
, end
;
426 ogg_page og
={0,0,0,0};
428 /* we're partially open and have a first link header state in
430 /* we can seek, so set out learning all about this file */
431 (vf
->callbacks
.seek_func
)(vf
->datasource
,0,SEEK_END
);
432 vf
->offset
=vf
->end
=(vf
->callbacks
.tell_func
)(vf
->datasource
);
434 /* We get the offset for the last page of the physical bitstream.
435 Most OggVorbis files will contain a single logical bitstream */
436 end
=_get_prev_page(vf
,&og
);
437 if(end
<0)return(end
);
439 /* more than one logical bitstream? */
440 tempserialno
=ogg_page_serialno(&og
);
441 ogg_page_release(&og
);
443 if(tempserialno
!=serialno
){
445 /* Chained bitstream. Bisect-search each logical bitstream
446 section. Do so based on serial number only */
447 if(_bisect_forward_serialno(vf
,0,0,end
+1,serialno
,0)<0)return(OV_EREAD
);
451 /* Only one logical bitstream */
452 if(_bisect_forward_serialno(vf
,0,end
,end
+1,serialno
,0))return(OV_EREAD
);
456 /* the initial header memory is referenced by vf after; don't free it */
457 _prefetch_all_headers(vf
,dataoffset
);
458 return(ov_raw_seek(vf
,0));
461 /* clear out the current logical bitstream decoder */
462 static void _decode_clear(OggVorbis_File
*vf
){
463 vorbis_dsp_clear(&vf
->vd
);
464 vorbis_block_clear(&vf
->vb
);
465 vf
->ready_state
=OPENED
;
468 /* fetch and process a packet. Handles the case where we're at a
469 bitstream boundary and dumps the decoding machine. If the decoding
470 machine is unloaded, it loads it. It also keeps pcm_offset up to
471 date (seek and read both use this. seek uses a special hack with
474 return: <0) error, OV_HOLE (lost packet) or OV_EOF
475 0) need more data (only if readp==0)
479 static int _fetch_and_process_packet(OggVorbis_File
*vf
,
482 ogg_page og
={0,0,0,0};
483 ogg_packet op
={0,0,0,0,0,0};
486 /* handle one packet. Try to fetch it from current stream state */
487 /* extract packets from page */
490 /* process a packet if we can. If the machine isn't loaded,
492 if(vf
->ready_state
==INITSET
){
494 int result
=ogg_stream_packetout(vf
->os
,&op
);
495 ogg_int64_t granulepos
;
498 ret
=OV_HOLE
; /* hole in the data. */
502 /* got a packet. process it */
503 granulepos
=op
.granulepos
;
504 if(!vorbis_synthesis(&vf
->vb
,&op
,1)){ /* lazy check for lazy
506 header packets aren't
509 vorbis_synthesis will
512 /* suck in the synthesis data and track bitrate */
514 int oldsamples
=vorbis_synthesis_pcmout(&vf
->vd
,NULL
);
515 /* for proper use of libvorbis within libvorbisfile,
516 oldsamples will always be zero. */
522 vorbis_synthesis_blockin(&vf
->vd
,&vf
->vb
);
523 vf
->samptrack
+=vorbis_synthesis_pcmout(&vf
->vd
,NULL
)-oldsamples
;
524 vf
->bittrack
+=op
.bytes
*8;
527 /* update the pcm offset. */
528 if(granulepos
!=-1 && !op
.e_o_s
){
529 int link
=(vf
->seekable
?vf
->current_link
:0);
532 /* this packet has a pcm_offset on it (the last packet
533 completed on a page carries the offset) After processing
534 (above), we know the pcm position of the *last* sample
535 ready to be returned. Find the offset of the *first*
537 As an aside, this trick is inaccurate if we begin
538 reading anew right at the last page; the end-of-stream
539 granulepos declares the last frame in the stream, and the
540 last packet of the last page may be a partial frame.
541 So, we need a previous granulepos from an in-sequence page
542 to have a reference point. Thus the !op.e_o_s clause
545 if(vf
->seekable
&& link
>0)
546 granulepos
-=vf
->pcmlengths
[link
*2];
547 if(granulepos
<0)granulepos
=0; /* actually, this
548 shouldn't be possible
549 here unless the stream
552 samples
=vorbis_synthesis_pcmout(&vf
->vd
,NULL
);
556 granulepos
+=vf
->pcmlengths
[i
*2+1];
557 vf
->pcm_offset
=granulepos
;
568 if(vf
->ready_state
>=OPENED
){
574 if((ret
=_get_next_page(vf
,&og
,-1))<0){
575 ret
=OV_EOF
; /* eof. leave unitialized */
579 /* bitrate tracking; add the header's bytes here, the body bytes
580 are done by packet above */
581 vf
->bittrack
+=og
.header_len
*8;
583 /* has our decoding just traversed a bitstream boundary? */
584 if(vf
->ready_state
==INITSET
){
585 if(vf
->current_serialno
!=ogg_page_serialno(&og
)){
594 vorbis_info_clear(vf
->vi
);
595 vorbis_comment_clear(vf
->vc
);
601 /* Do we need to load a new machine before submitting the page? */
602 /* This is different in the seekable and non-seekable cases.
604 In the seekable case, we already have all the header
605 information loaded and cached; we just initialize the machine
606 with it and continue on our merry way.
608 In the non-seekable (streaming) case, we'll only be at a
609 boundary if we just left the previous logical bitstream and
610 we're now nominally at the header of the next bitstream
613 if(vf
->ready_state
!=INITSET
){
616 if(vf
->ready_state
<STREAMSET
){
618 vf
->current_serialno
=ogg_page_serialno(&og
);
620 /* match the serialno to bitstream section. We use this rather than
621 offset positions to avoid problems near logical bitstream
623 for(link
=0;link
<vf
->links
;link
++)
624 if(vf
->serialnos
[link
]==vf
->current_serialno
)break;
626 ret
=OV_EBADLINK
; /* sign of a bogus stream. error out,
627 leave machine uninitialized */
631 vf
->current_link
=link
;
633 ogg_stream_reset_serialno(vf
->os
,vf
->current_serialno
);
634 vf
->ready_state
=STREAMSET
;
637 /* we're streaming */
638 /* fetch the three header packets, build the info struct */
640 int ret
=_fetch_headers(vf
,vf
->vi
,vf
->vc
,&vf
->current_serialno
,&og
);
641 if(ret
) goto cleanup
;
647 _make_decode_ready(vf
);
649 ogg_stream_pagein(vf
->os
,&og
);
652 ogg_packet_release(&op
);
653 ogg_page_release(&og
);
657 /* if, eg, 64 bit stdio is configured by default, this will build with
659 static int _fseek64_wrap(FILE *f
,ogg_int64_t off
,int whence
){
660 if(f
==NULL
)return(-1);
661 return fseek(f
,off
,whence
);
664 static int _ov_open1(void *f
,OggVorbis_File
*vf
,char *initial
,
665 long ibytes
, ov_callbacks callbacks
){
666 int offsettest
=(f
?callbacks
.seek_func(f
,0,SEEK_CUR
):-1);
669 memset(vf
,0,sizeof(*vf
));
671 vf
->callbacks
= callbacks
;
673 /* init the framing state */
674 vf
->oy
=ogg_sync_create();
676 /* perhaps some data was previously read into a buffer for testing
677 against other stream types. Allow initialization from this
678 previously read data (as we may be reading from a non-seekable
681 unsigned char *buffer
=ogg_sync_bufferin(vf
->oy
,ibytes
);
682 memcpy(buffer
,initial
,ibytes
);
683 ogg_sync_wrote(vf
->oy
,ibytes
);
686 /* can we seek? Stevens suggests the seek test was portable */
687 if(offsettest
!=-1)vf
->seekable
=1;
689 /* No seeking yet; Set up a 'single' (current) logical bitstream
690 entry for partial open */
692 vf
->vi
=_ogg_calloc(vf
->links
,sizeof(*vf
->vi
));
693 vf
->vc
=_ogg_calloc(vf
->links
,sizeof(*vf
->vc
));
694 vf
->os
=ogg_stream_create(-1); /* fill in the serialno later */
696 /* Try to fetch the headers, maintaining all the storage */
697 if((ret
=_fetch_headers(vf
,vf
->vi
,vf
->vc
,&vf
->current_serialno
,NULL
))<0){
700 }else if(vf
->ready_state
< PARTOPEN
)
701 vf
->ready_state
=PARTOPEN
;
705 static int _ov_open2(OggVorbis_File
*vf
){
706 if(vf
->ready_state
< OPENED
)
707 vf
->ready_state
=OPENED
;
709 int ret
=_open_seekable2(vf
);
720 /* clear out the OggVorbis_File struct */
721 int ov_clear(OggVorbis_File
*vf
){
723 vorbis_block_clear(&vf
->vb
);
724 vorbis_dsp_clear(&vf
->vd
);
725 ogg_stream_destroy(vf
->os
);
727 if(vf
->vi
&& vf
->links
){
729 for(i
=0;i
<vf
->links
;i
++){
730 vorbis_info_clear(vf
->vi
+i
);
731 vorbis_comment_clear(vf
->vc
+i
);
736 if(vf
->dataoffsets
)_ogg_free(vf
->dataoffsets
);
737 if(vf
->pcmlengths
)_ogg_free(vf
->pcmlengths
);
738 if(vf
->serialnos
)_ogg_free(vf
->serialnos
);
739 if(vf
->offsets
)_ogg_free(vf
->offsets
);
740 ogg_sync_destroy(vf
->oy
);
742 if(vf
->datasource
)(vf
->callbacks
.close_func
)(vf
->datasource
);
743 memset(vf
,0,sizeof(*vf
));
751 /* inspects the OggVorbis file and finds/documents all the logical
752 bitstreams contained in it. Tries to be tolerant of logical
753 bitstream sections that are truncated/woogie.
759 int ov_open_callbacks(void *f
,OggVorbis_File
*vf
,char *initial
,long ibytes
,
760 ov_callbacks callbacks
){
761 int ret
=_ov_open1(f
,vf
,initial
,ibytes
,callbacks
);
763 return _ov_open2(vf
);
766 int ov_open(FILE *f
,OggVorbis_File
*vf
,char *initial
,long ibytes
){
767 ov_callbacks callbacks
= {
768 (size_t (*)(void *, size_t, size_t, void *)) fread
,
769 (int (*)(void *, ogg_int64_t
, int)) _fseek64_wrap
,
770 (int (*)(void *)) fclose
,
771 (long (*)(void *)) ftell
774 return ov_open_callbacks((void *)f
, vf
, initial
, ibytes
, callbacks
);
777 /* Only partially open the vorbis file; test for Vorbisness, and load
778 the headers for the first chain. Do not seek (although test for
779 seekability). Use ov_test_open to finish opening the file, else
780 ov_clear to close/free it. Same return codes as open. */
782 int ov_test_callbacks(void *f
,OggVorbis_File
*vf
,char *initial
,long ibytes
,
783 ov_callbacks callbacks
)
785 return _ov_open1(f
,vf
,initial
,ibytes
,callbacks
);
788 int ov_test(FILE *f
,OggVorbis_File
*vf
,char *initial
,long ibytes
){
789 ov_callbacks callbacks
= {
790 (size_t (*)(void *, size_t, size_t, void *)) fread
,
791 (int (*)(void *, ogg_int64_t
, int)) _fseek64_wrap
,
792 (int (*)(void *)) fclose
,
793 (long (*)(void *)) ftell
796 return ov_test_callbacks((void *)f
, vf
, initial
, ibytes
, callbacks
);
799 int ov_test_open(OggVorbis_File
*vf
){
800 if(vf
->ready_state
!=PARTOPEN
)return(OV_EINVAL
);
801 return _ov_open2(vf
);
804 /* How many logical bitstreams in this physical bitstream? */
805 long ov_streams(OggVorbis_File
*vf
){
809 /* Is the FILE * associated with vf seekable? */
810 long ov_seekable(OggVorbis_File
*vf
){
814 /* returns the bitrate for a given logical bitstream or the entire
815 physical bitstream. If the file is open for random access, it will
816 find the *actual* average bitrate. If the file is streaming, it
817 returns the nominal bitrate (if set) else the average of the
818 upper/lower bounds (if set) else -1 (unset).
820 If you want the actual bitrate field settings, get them from the
821 vorbis_info structs */
823 long ov_bitrate(OggVorbis_File
*vf
,int i
){
824 if(vf
->ready_state
<OPENED
)return(OV_EINVAL
);
825 if(i
>=vf
->links
)return(OV_EINVAL
);
826 if(!vf
->seekable
&& i
!=0)return(ov_bitrate(vf
,0));
830 for(i
=0;i
<vf
->links
;i
++)
831 bits
+=(vf
->offsets
[i
+1]-vf
->dataoffsets
[i
])*8;
832 /* This once read: return(rint(bits/ov_time_total(vf,-1)));
833 * gcc 3.x on x86 miscompiled this at optimisation level 2 and above,
834 * so this is slightly transformed to make it work.
836 return(bits
*1000/ov_time_total(vf
,-1));
839 /* return the actual bitrate */
840 return((vf
->offsets
[i
+1]-vf
->dataoffsets
[i
])*8000/ov_time_total(vf
,i
));
842 /* return nominal if set */
843 if(vf
->vi
[i
].bitrate_nominal
>0){
844 return vf
->vi
[i
].bitrate_nominal
;
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;
850 return vf
->vi
[i
].bitrate_upper
;
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
863 long ov_bitrate_instant(OggVorbis_File
*vf
){
864 int link
=(vf
->seekable
?vf
->current_link
:0);
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
;
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));
879 return(vf
->current_serialno
);
881 return(vf
->serialnos
[i
]);
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
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
);
896 for(i
=0;i
<vf
->links
;i
++)
897 acc
+=ov_raw_total(vf
,i
);
900 return(vf
->offsets
[i
+1]-vf
->offsets
[i
]);
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
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
);
915 for(i
=0;i
<vf
->links
;i
++)
916 acc
+=ov_pcm_total(vf
,i
);
919 return(vf
->pcmlengths
[i
*2+1]);
923 /* returns: total milliseconds of content if i==-1
924 milliseconds 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
928 ogg_int64_t
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
);
934 for(i
=0;i
<vf
->links
;i
++)
935 acc
+=ov_time_total(vf
,i
);
938 return(((ogg_int64_t
)vf
->pcmlengths
[i
*2+1])*1000/vf
->vi
[i
].rate
);
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).
947 returns zero on success, nonzero on failure */
949 int ov_raw_seek(OggVorbis_File
*vf
,ogg_int64_t pos
){
950 ogg_stream_state
*work_os
=NULL
;
951 ogg_page og
={0,0,0,0};
952 ogg_packet op
={0,0,0,0,0,0};
954 if(vf
->ready_state
<OPENED
)return(OV_EINVAL
);
956 return(OV_ENOSEEK
); /* don't dump machine if we can't seek */
958 if(pos
<0 || pos
>vf
->end
)return(OV_EINVAL
);
960 /* don't yet clear out decoding machine (if it's initialized), in
961 the case we're in the same link. Restart the decode lapping, and
962 let _fetch_and_process_packet deal with a potential bitstream
965 ogg_stream_reset_serialno(vf
->os
,
966 vf
->current_serialno
); /* must set serialno */
967 vorbis_synthesis_restart(&vf
->vd
);
969 _seek_helper(vf
,pos
);
971 /* we need to make sure the pcm_offset is set, but we don't want to
972 advance the raw cursor past good packets just to get to the first
973 with a granulepos. That's not equivalent behavior to beginning
974 decoding as immediately after the seek position as possible.
976 So, a hack. We use two stream states; a local scratch state and
977 the shared vf->os stream state. We use the local state to
978 scan, and the shared state as a buffer for later decode.
980 Unfortuantely, on the last page we still advance to last packet
981 because the granulepos on the last page is not necessarily on a
982 packet boundary, and we need to make sure the granpos is
992 work_os
=ogg_stream_create(vf
->current_serialno
); /* get the memory ready */
994 if(vf
->ready_state
>=STREAMSET
){
995 /* snarf/scan a packet if we can */
996 int result
=ogg_stream_packetout(work_os
,&op
);
1000 if(vf
->vi
[vf
->current_link
].codec_setup
){
1001 thisblock
=vorbis_packet_blocksize(vf
->vi
+vf
->current_link
,&op
);
1003 ogg_stream_packetout(vf
->os
,NULL
);
1008 ogg_stream_packetout(vf
->os
,NULL
);
1010 if(lastblock
)accblock
+=(lastblock
+thisblock
)>>2;
1013 if(op
.granulepos
!=-1){
1014 int i
,link
=vf
->current_link
;
1015 ogg_int64_t granulepos
=op
.granulepos
-vf
->pcmlengths
[link
*2];
1016 if(granulepos
<0)granulepos
=0;
1019 granulepos
+=vf
->pcmlengths
[i
*2+1];
1020 vf
->pcm_offset
=granulepos
-accblock
;
1023 lastblock
=thisblock
;
1026 ogg_stream_packetout(vf
->os
,NULL
);
1031 if(_get_next_page(vf
,&og
,-1)<0){
1032 vf
->pcm_offset
=ov_pcm_total(vf
,-1);
1036 /* huh? Bogus stream with packets but no granulepos */
1041 /* has our decoding just traversed a bitstream boundary? */
1042 if(vf
->ready_state
>=STREAMSET
)
1043 if(vf
->current_serialno
!=ogg_page_serialno(&og
)){
1044 _decode_clear(vf
); /* clear out stream state */
1045 ogg_stream_destroy(work_os
);
1048 if(vf
->ready_state
<STREAMSET
){
1051 vf
->current_serialno
=ogg_page_serialno(&og
);
1052 for(link
=0;link
<vf
->links
;link
++)
1053 if(vf
->serialnos
[link
]==vf
->current_serialno
)break;
1055 goto seek_error
; /* sign of a bogus stream. error out,
1056 leave machine uninitialized */
1058 vf
->current_link
=link
;
1060 ogg_stream_reset_serialno(vf
->os
,vf
->current_serialno
);
1061 ogg_stream_reset_serialno(work_os
,vf
->current_serialno
);
1062 vf
->ready_state
=STREAMSET
;
1068 ogg_page_dup(&dup
,&og
);
1069 eosflag
=ogg_page_eos(&og
);
1070 ogg_stream_pagein(vf
->os
,&og
);
1071 ogg_stream_pagein(work_os
,&dup
);
1076 ogg_packet_release(&op
);
1077 ogg_page_release(&og
);
1078 ogg_stream_destroy(work_os
);
1084 ogg_packet_release(&op
);
1085 ogg_page_release(&og
);
1087 /* dump the machine so we're in a known state */
1089 ogg_stream_destroy(work_os
);
1094 /* Page granularity seek (faster than sample granularity because we
1095 don't do the last bit of decode to find a specific sample).
1097 Seek to the last [granule marked] page preceeding the specified pos
1098 location, such that decoding past the returned point will quickly
1099 arrive at the requested position. */
1100 int ov_pcm_seek_page(OggVorbis_File
*vf
,ogg_int64_t pos
){
1102 ogg_int64_t result
=0;
1103 ogg_int64_t total
=ov_pcm_total(vf
,-1);
1104 ogg_page og
={0,0,0,0};
1105 ogg_packet op
={0,0,0,0,0,0};
1107 if(vf
->ready_state
<OPENED
)return(OV_EINVAL
);
1108 if(!vf
->seekable
)return(OV_ENOSEEK
);
1109 if(pos
<0 || pos
>total
)return(OV_EINVAL
);
1111 /* which bitstream section does this pcm offset occur in? */
1112 for(link
=vf
->links
-1;link
>=0;link
--){
1113 total
-=vf
->pcmlengths
[link
*2+1];
1114 if(pos
>=total
)break;
1117 /* search within the logical bitstream for the page with the highest
1118 pcm_pos preceeding (or equal to) pos. There is a danger here;
1119 missing pages or incorrect frame number information in the
1120 bitstream could make our task impossible. Account for that (it
1121 would be an error condition) */
1123 /* new search algorithm by HB (Nicholas Vinen) */
1125 ogg_int64_t end
=vf
->offsets
[link
+1];
1126 ogg_int64_t begin
=vf
->offsets
[link
];
1127 ogg_int64_t begintime
= vf
->pcmlengths
[link
*2];
1128 ogg_int64_t endtime
= vf
->pcmlengths
[link
*2+1]+begintime
;
1129 ogg_int64_t target
=pos
-total
+begintime
;
1130 ogg_int64_t best
=begin
;
1135 if(end
-begin
<CHUNKSIZE
){
1138 /* take a (pretty decent) guess. */
1140 (target
-begintime
)*(end
-begin
)/(endtime
-begintime
) - CHUNKSIZE
;
1145 _seek_helper(vf
,bisect
);
1148 result
=_get_next_page(vf
,&og
,end
-vf
->offset
);
1149 if(result
==OV_EREAD
) goto seek_error
;
1152 end
=begin
; /* found it */
1154 if(bisect
==0) goto seek_error
;
1156 if(bisect
<=begin
)bisect
=begin
+1;
1157 _seek_helper(vf
,bisect
);
1160 ogg_int64_t granulepos
=ogg_page_granulepos(&og
);
1161 if(granulepos
==-1)continue;
1162 if(granulepos
<target
){
1163 best
=result
; /* raw offset of packet with granulepos */
1164 begin
=vf
->offset
; /* raw offset of next page */
1165 begintime
=granulepos
;
1167 if(target
-begintime
>44100)break;
1168 bisect
=begin
; /* *not* begin + 1 */
1171 end
=begin
; /* found it */
1173 if(end
==vf
->offset
){ /* we're pretty close - we'd be stuck in */
1175 bisect
-=CHUNKSIZE
; /* an endless loop otherwise. */
1176 if(bisect
<=begin
)bisect
=begin
+1;
1177 _seek_helper(vf
,bisect
);
1189 /* found our page. seek to it, update pcm offset. Easier case than
1190 raw_seek, don't keep packets preceeding granulepos. */
1194 _seek_helper(vf
,best
);
1197 if(_get_next_page(vf
,&og
,-1)<0){
1198 ogg_page_release(&og
);
1199 return(OV_EOF
); /* shouldn't happen */
1202 if(link
!=vf
->current_link
){
1203 /* Different link; dump entire decode machine */
1206 vf
->current_link
=link
;
1207 vf
->current_serialno
=ogg_page_serialno(&og
);
1208 vf
->ready_state
=STREAMSET
;
1211 vorbis_synthesis_restart(&vf
->vd
);
1214 ogg_stream_reset_serialno(vf
->os
,vf
->current_serialno
);
1215 ogg_stream_pagein(vf
->os
,&og
);
1217 /* pull out all but last packet; the one with granulepos */
1219 result
=ogg_stream_packetpeek(vf
->os
,&op
);
1221 /* !!! the packet finishing this page originated on a
1222 preceeding page. Keep fetching previous pages until we
1223 get one with a granulepos or without the 'continued' flag
1224 set. Then just use raw_seek for simplicity. */
1226 _seek_helper(vf
,best
);
1229 result
=_get_prev_page(vf
,&og
);
1230 if(result
<0) goto seek_error
;
1231 if(ogg_page_granulepos(&og
)>-1 ||
1232 !ogg_page_continued(&og
)){
1233 return ov_raw_seek(vf
,result
);
1239 result
= OV_EBADPACKET
;
1242 if(op
.granulepos
!=-1){
1243 vf
->pcm_offset
=op
.granulepos
-vf
->pcmlengths
[vf
->current_link
*2];
1244 if(vf
->pcm_offset
<0)vf
->pcm_offset
=0;
1245 vf
->pcm_offset
+=total
;
1248 result
=ogg_stream_packetout(vf
->os
,NULL
);
1254 if(vf
->pcm_offset
>pos
|| pos
>ov_pcm_total(vf
,-1)){
1261 ogg_page_release(&og
);
1262 ogg_packet_release(&op
);
1267 ogg_page_release(&og
);
1268 ogg_packet_release(&op
);
1270 /* dump machine so we're in a known state */
1276 /* seek to a sample offset relative to the decompressed pcm stream
1277 returns zero on success, nonzero on failure */
1279 int ov_pcm_seek(OggVorbis_File
*vf
,ogg_int64_t pos
){
1280 ogg_packet op
={0,0,0,0,0,0};
1281 ogg_page og
={0,0,0,0};
1282 int thisblock
,lastblock
=0;
1283 int ret
=ov_pcm_seek_page(vf
,pos
);
1284 if(ret
<0)return(ret
);
1285 _make_decode_ready(vf
);
1287 /* discard leading packets we don't need for the lapping of the
1288 position we want; don't decode them */
1292 int ret
=ogg_stream_packetpeek(vf
->os
,&op
);
1294 thisblock
=vorbis_packet_blocksize(vf
->vi
+vf
->current_link
,&op
);
1296 ogg_stream_packetout(vf
->os
,NULL
);
1297 continue; /* non audio packet */
1299 if(lastblock
)vf
->pcm_offset
+=(lastblock
+thisblock
)>>2;
1301 if(vf
->pcm_offset
+((thisblock
+
1302 vorbis_info_blocksize(vf
->vi
,1))>>2)>=pos
)break;
1304 /* remove the packet from packet queue and track its granulepos */
1305 ogg_stream_packetout(vf
->os
,NULL
);
1306 vorbis_synthesis(&vf
->vb
,&op
,0); /* set up a vb with
1309 vorbis_synthesis_blockin(&vf
->vd
,&vf
->vb
);
1311 /* end of logical stream case is hard, especially with exact
1312 length positioning. */
1314 if(op
.granulepos
>-1){
1316 /* always believe the stream markers */
1317 vf
->pcm_offset
=op
.granulepos
-vf
->pcmlengths
[vf
->current_link
*2];
1318 if(vf
->pcm_offset
<0)vf
->pcm_offset
=0;
1319 for(i
=0;i
<vf
->current_link
;i
++)
1320 vf
->pcm_offset
+=vf
->pcmlengths
[i
*2+1];
1323 lastblock
=thisblock
;
1326 if(ret
<0 && ret
!=OV_HOLE
)break;
1328 /* suck in a new page */
1329 if(_get_next_page(vf
,&og
,-1)<0)break;
1330 if(vf
->current_serialno
!=ogg_page_serialno(&og
))_decode_clear(vf
);
1332 if(vf
->ready_state
<STREAMSET
){
1335 vf
->current_serialno
=ogg_page_serialno(&og
);
1336 for(link
=0;link
<vf
->links
;link
++)
1337 if(vf
->serialnos
[link
]==vf
->current_serialno
)break;
1338 if(link
==vf
->links
){
1339 ogg_page_release(&og
);
1340 ogg_packet_release(&op
);
1341 return(OV_EBADLINK
);
1343 vf
->current_link
=link
;
1345 ogg_stream_reset_serialno(vf
->os
,vf
->current_serialno
);
1346 vf
->ready_state
=STREAMSET
;
1347 _make_decode_ready(vf
);
1351 ogg_stream_pagein(vf
->os
,&og
);
1357 /* discard samples until we reach the desired position. Crossing a
1358 logical bitstream boundary with abandon is OK. */
1359 while(vf
->pcm_offset
<pos
){
1360 ogg_int64_t target
=pos
-vf
->pcm_offset
;
1361 long samples
=vorbis_synthesis_pcmout(&vf
->vd
,NULL
);
1363 if(samples
>target
)samples
=target
;
1364 vorbis_synthesis_read(&vf
->vd
,samples
);
1365 vf
->pcm_offset
+=samples
;
1368 if(_fetch_and_process_packet(vf
,1,1)<=0)
1369 vf
->pcm_offset
=ov_pcm_total(vf
,-1); /* eof */
1372 ogg_page_release(&og
);
1373 ogg_packet_release(&op
);
1377 /* seek to a playback time relative to the decompressed pcm stream
1378 returns zero on success, nonzero on failure */
1379 int ov_time_seek(OggVorbis_File
*vf
,ogg_int64_t milliseconds
){
1380 /* translate time to PCM position and call ov_pcm_seek */
1383 ogg_int64_t pcm_total
=ov_pcm_total(vf
,-1);
1384 ogg_int64_t time_total
=ov_time_total(vf
,-1);
1386 if(vf
->ready_state
<OPENED
)return(OV_EINVAL
);
1387 if(!vf
->seekable
)return(OV_ENOSEEK
);
1388 if(milliseconds
<0 || milliseconds
>time_total
)return(OV_EINVAL
);
1390 /* which bitstream section does this time offset occur in? */
1391 for(link
=vf
->links
-1;link
>=0;link
--){
1392 pcm_total
-=vf
->pcmlengths
[link
*2+1];
1393 time_total
-=ov_time_total(vf
,link
);
1394 if(milliseconds
>=time_total
)break;
1397 /* enough information to convert time offset to pcm offset */
1399 ogg_int64_t target
=pcm_total
+(milliseconds
-time_total
)*vf
->vi
[link
].rate
/1000;
1400 return(ov_pcm_seek(vf
,target
));
1404 /* page-granularity version of ov_time_seek
1405 returns zero on success, nonzero on failure */
1406 int ov_time_seek_page(OggVorbis_File
*vf
,ogg_int64_t milliseconds
){
1407 /* translate time to PCM position and call ov_pcm_seek */
1410 ogg_int64_t pcm_total
=ov_pcm_total(vf
,-1);
1411 ogg_int64_t time_total
=ov_time_total(vf
,-1);
1413 if(vf
->ready_state
<OPENED
)return(OV_EINVAL
);
1414 if(!vf
->seekable
)return(OV_ENOSEEK
);
1415 if(milliseconds
<0 || milliseconds
>time_total
)return(OV_EINVAL
);
1417 /* which bitstream section does this time offset occur in? */
1418 for(link
=vf
->links
-1;link
>=0;link
--){
1419 pcm_total
-=vf
->pcmlengths
[link
*2+1];
1420 time_total
-=ov_time_total(vf
,link
);
1421 if(milliseconds
>=time_total
)break;
1424 /* enough information to convert time offset to pcm offset */
1426 ogg_int64_t target
=pcm_total
+(milliseconds
-time_total
)*vf
->vi
[link
].rate
/1000;
1427 return(ov_pcm_seek_page(vf
,target
));
1431 /* tell the current stream offset cursor. Note that seek followed by
1432 tell will likely not give the set offset due to caching */
1433 ogg_int64_t
ov_raw_tell(OggVorbis_File
*vf
){
1434 if(vf
->ready_state
<OPENED
)return(OV_EINVAL
);
1438 /* return PCM offset (sample) of next PCM sample to be read */
1439 ogg_int64_t
ov_pcm_tell(OggVorbis_File
*vf
){
1440 if(vf
->ready_state
<OPENED
)return(OV_EINVAL
);
1441 return(vf
->pcm_offset
);
1444 /* return time offset (milliseconds) of next PCM sample to be read */
1445 ogg_int64_t
ov_time_tell(OggVorbis_File
*vf
){
1447 ogg_int64_t pcm_total
=0;
1448 ogg_int64_t time_total
=0;
1450 if(vf
->ready_state
<OPENED
)return(OV_EINVAL
);
1452 pcm_total
=ov_pcm_total(vf
,-1);
1453 time_total
=ov_time_total(vf
,-1);
1455 /* which bitstream section does this time offset occur in? */
1456 for(link
=vf
->links
-1;link
>=0;link
--){
1457 pcm_total
-=vf
->pcmlengths
[link
*2+1];
1458 time_total
-=ov_time_total(vf
,link
);
1459 if(vf
->pcm_offset
>=pcm_total
)break;
1463 return(time_total
+(1000*vf
->pcm_offset
-pcm_total
)/vf
->vi
[link
].rate
);
1466 /* link: -1) return the vorbis_info struct for the bitstream section
1467 currently being decoded
1468 0-n) to request information for a specific bitstream section
1470 In the case of a non-seekable bitstream, any call returns the
1471 current bitstream. NULL in the case that the machine is not
1474 vorbis_info
*ov_info(OggVorbis_File
*vf
,int link
){
1477 if(vf
->ready_state
>=STREAMSET
)
1478 return vf
->vi
+vf
->current_link
;
1491 /* grr, strong typing, grr, no templates/inheritence, grr */
1492 vorbis_comment
*ov_comment(OggVorbis_File
*vf
,int link
){
1495 if(vf
->ready_state
>=STREAMSET
)
1496 return vf
->vc
+vf
->current_link
;
1509 /* up to this point, everything could more or less hide the multiple
1510 logical bitstream nature of chaining from the toplevel application
1511 if the toplevel application didn't particularly care. However, at
1512 the point that we actually read audio back, the multiple-section
1513 nature must surface: Multiple bitstream sections do not necessarily
1514 have to have the same number of channels or sampling rate.
1516 ov_read returns the sequential logical bitstream number currently
1517 being decoded along with the PCM data in order that the toplevel
1518 application can take action on channel/sample rate changes. This
1519 number will be incremented even for streamed (non-seekable) streams
1520 (for seekable streams, it represents the actual logical bitstream
1521 index within the physical bitstream. Note that the accessor
1522 functions above are aware of this dichotomy).
1524 input values: buffer) a buffer to hold packed PCM data for return
1525 length) the byte length requested to be placed into buffer
1527 return values: <0) error/hole in data (OV_HOLE), partial open (OV_EINVAL)
1529 n) number of bytes of PCM actually returned. The
1530 below works on a packet-by-packet basis, so the
1531 return length is not related to the 'length' passed
1532 in, just guaranteed to fit.
1534 *section) set to the logical bitstream number */
1536 long ov_read(OggVorbis_File
*vf
,char *buffer
,int bytes_req
,int *bitstream
){
1542 if(vf
->ready_state
<OPENED
)return(OV_EINVAL
);
1545 if(vf
->ready_state
==INITSET
){
1546 samples
=vorbis_synthesis_pcmout(&vf
->vd
,&pcm
);
1550 /* suck in another packet */
1552 int ret
=_fetch_and_process_packet(vf
,1,1);
1563 /* yay! proceed to pack data into the byte buffer */
1565 long channels
=ov_info(vf
,-1)->channels
;
1567 if(samples
>(bytes_req
/(2*channels
)))
1568 samples
=bytes_req
/(2*channels
);
1570 for(i
=0;i
<channels
;i
++) { /* It's faster in this order */
1571 ogg_int32_t
*src
=pcm
[i
];
1572 short *dest
=((short *)buffer
)+i
;
1573 for(j
=0;j
<samples
;j
++) {
1574 *dest
=CLIP_TO_15(src
[j
]>>9);
1579 vorbis_synthesis_read(&vf
->vd
,samples
);
1580 vf
->pcm_offset
+=samples
;
1581 if(bitstream
)*bitstream
=vf
->current_link
;
1582 return(samples
*2*channels
);