]> Joshua Wise's Git repositories - patchfork.git/blame_incremental - jorbis/src/com/jcraft/jorbis/VorbisFile.java
initial import from pitchfork-0.5.5
[patchfork.git] / jorbis / src / com / jcraft / jorbis / VorbisFile.java
... / ...
CommitLineData
1/* JOrbis
2 * Copyright (C) 2000 ymnk, JCraft,Inc.
3 *
4 * Written by: 2000 ymnk<ymnk@jcraft.com>
5 *
6 * Many thanks to
7 * Monty <monty@xiph.org> and
8 * The XIPHOPHORUS Company http://www.xiph.org/ .
9 * JOrbis has been based on their awesome works, Vorbis codec.
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Library General Public License
13 * as published by the Free Software Foundation; either version 2 of
14 * the License, or (at your option) any later version.
15
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Library General Public License for more details.
20 *
21 * You should have received a copy of the GNU Library General Public
22 * License along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 */
25
26package com.jcraft.jorbis;
27
28import com.jcraft.jogg.*;
29
30import java.io.InputStream;
31import java.io.IOException;
32
33public class VorbisFile{
34 static final int CHUNKSIZE=8500;
35 static final int SEEK_SET=0;
36 static final int SEEK_CUR=1;
37 static final int SEEK_END=2;
38
39 static final int OV_FALSE=-1;
40 static final int OV_EOF=-2;
41 static final int OV_HOLE=-3;
42
43 static final int OV_EREAD=-128;
44 static final int OV_EFAULT=-129;
45 static final int OV_EIMPL=-130;
46 static final int OV_EINVAL=-131;
47 static final int OV_ENOTVORBIS=-132;
48 static final int OV_EBADHEADER=-133;
49 static final int OV_EVERSION=-134;
50 static final int OV_ENOTAUDIO=-135;
51 static final int OV_EBADPACKET=-136;
52 static final int OV_EBADLINK=-137;
53 static final int OV_ENOSEEK=-138;
54
55 InputStream datasource;
56 boolean seekable=false;
57 long offset;
58 long end;
59
60 SyncState oy=new SyncState();
61
62 int links;
63 long[] offsets;
64 long[] dataoffsets;
65 int[] serialnos;
66 long[] pcmlengths;
67 Info[] vi;
68 Comment[] vc;
69
70 // Decoding working state local storage
71 long pcm_offset;
72 boolean decode_ready=false;
73 int current_serialno;
74 int current_link;
75
76 float bittrack;
77 float samptrack;
78
79 StreamState os=new StreamState(); // take physical pages, weld into a logical
80 // stream of packets
81 DspState vd=new DspState(); // central working state for
82 // the packet->PCM decoder
83 Block vb=new Block(vd); // local working space for packet->PCM decode
84
85 //ov_callbacks callbacks;
86
87 public VorbisFile(String file) throws JOrbisException {
88 super();
89 InputStream is=null;
90 try{
91 is=new SeekableInputStream(file);
92 int ret=open(is, null, 0);
93 if(ret==-1){
94 throw new JOrbisException("VorbisFile: open return -1");
95 }
96 }
97 catch(Exception e){
98 throw new JOrbisException("VorbisFile: "+e.toString());
99 }
100 finally{
101 if(is != null){
102 try {
103 is.close();
104 }
105 catch (IOException e) {
106 e.printStackTrace();
107 }
108 }
109 }
110 }
111
112 public VorbisFile(InputStream is, byte[] initial, int ibytes)
113 throws JOrbisException {
114 super();
115 int ret=open(is, initial, ibytes);
116 if(ret==-1){
117 }
118 }
119
120 private int get_data(){
121 int index=oy.buffer(CHUNKSIZE);
122 byte[] buffer=oy.data;
123// int bytes=callbacks.read_func(buffer, index, 1, CHUNKSIZE, datasource);
124 int bytes=0;
125 try{
126 bytes=datasource.read(buffer, index, CHUNKSIZE);
127 }
128 catch(Exception e){
129 //System.err.println(e);
130 return OV_EREAD;
131 }
132 oy.wrote(bytes);
133 if(bytes==-1){
134// System.out.println("bytes="+bytes);
135 bytes=0;
136 }
137 return bytes;
138 }
139
140 private void seek_helper(long offst){
141 //callbacks.seek_func(datasource, offst, SEEK_SET);
142 fseek(datasource, offst, SEEK_SET);
143 this.offset=offst;
144 oy.reset();
145 }
146
147 private int get_next_page(Page page, long boundary){
148 if(boundary>0) boundary+=offset;
149 while(true){
150 int more;
151 if(boundary>0 && offset>=boundary)return OV_FALSE;
152 more=oy.pageseek(page);
153 if(more<0){offset-=more;}
154 else{
155 if(more==0){
156 if(boundary==0)return OV_FALSE;
157// if(get_data()<=0)return -1;
158 int ret=get_data();
159 if(ret==0) return OV_EOF;
160 if(ret<0) return OV_EREAD;
161 }
162 else{
163 int ret=(int)offset; //!!!
164 offset+=more;
165 return ret;
166 }
167 }
168 }
169 }
170
171 private int get_prev_page(Page page) throws JOrbisException {
172 long begin=offset; //!!!
173 int ret;
174 int offst=-1;
175 while(offst==-1){
176 begin-=CHUNKSIZE;
177 if(begin<0)
178 begin=0;
179 seek_helper(begin);
180 while(offset<begin+CHUNKSIZE){
181 ret=get_next_page(page, begin+CHUNKSIZE-offset);
182 if(ret==OV_EREAD){ return OV_EREAD; }
183 if(ret<0){
184 if(offst == -1)
185 throw new JOrbisException();
186 break;
187 }
188 else{ offst=ret; }
189 }
190 }
191 seek_helper(offst); //!!!
192 ret=get_next_page(page, CHUNKSIZE);
193 if(ret<0){
194 //System.err.println("Missed page fencepost at end of logical bitstream Exiting");
195 //System.exit(1);
196 return OV_EFAULT;
197 }
198 return offst;
199 }
200
201 int bisect_forward_serialno(long begin, long searched, long end, int currentno, int m){
202 long endsearched=end;
203 long next=end;
204 Page page=new Page();
205 int ret;
206
207 while(searched<endsearched){
208 long bisect;
209 if(endsearched-searched<CHUNKSIZE){
210 bisect=searched;
211 }
212 else{
213 bisect=(searched+endsearched)/2;
214 }
215
216 seek_helper(bisect);
217 ret=get_next_page(page, -1);
218 if(ret==OV_EREAD) return OV_EREAD;
219 if(ret<0 || page.serialno()!=currentno){
220 endsearched=bisect;
221 if(ret>=0)next=ret;
222 }
223 else{
224 searched=ret+page.header_len+page.body_len;
225 }
226 }
227 seek_helper(next);
228 ret=get_next_page(page, -1);
229 if(ret==OV_EREAD) return OV_EREAD;
230
231 if(searched>=end || ret==-1){
232 links=m+1;
233 offsets=new long[m+2];
234 offsets[m+1]=searched;
235 }
236 else{
237 ret=bisect_forward_serialno(next, offset, end, page.serialno(), m+1);
238 if(ret==OV_EREAD)return OV_EREAD;
239 }
240 offsets[m]=begin;
241 return 0;
242 }
243
244 // uses the local ogg_stream storage in vf; this is important for
245 // non-streaming input sources
246 int fetch_headers(Info vi, Comment vc, int[] serialno, Page og_ptr){
247 //System.err.println("fetch_headers");
248 Page og=new Page();
249 Packet op=new Packet();
250 int ret;
251
252 if(og_ptr==null){
253 ret=get_next_page(og, CHUNKSIZE);
254 if(ret==OV_EREAD)return OV_EREAD;
255 if(ret<0) return OV_ENOTVORBIS;
256 og_ptr=og;
257 }
258
259 if(serialno!=null)serialno[0]=og_ptr.serialno();
260
261 os.init(og_ptr.serialno());
262
263 // extract the initial header from the first page and verify that the
264 // Ogg bitstream is in fact Vorbis data
265
266 vi.init();
267 vc.init();
268
269 int i=0;
270 while(i<3){
271 os.pagein(og_ptr);
272 while(i<3){
273 int result=os.packetout(op);
274 if(result==0)break;
275 if(result==-1){
276 //System.err.println("Corrupt header in logical bitstream.");
277 //goto bail_header;
278 vi.clear();
279 vc.clear();
280 os.clear();
281 return -1;
282 }
283 if(vi.synthesis_headerin(vc, op)!=0){
284 //System.err.println("Illegal header in logical bitstream.");
285 //goto bail_header;
286 vi.clear();
287 vc.clear();
288 os.clear();
289 return -1;
290 }
291 i++;
292 }
293 if(i<3)
294 if(get_next_page(og_ptr, 1)<0){
295 //System.err.println("Missing header in logical bitstream.");
296 //goto bail_header;
297 vi.clear();
298 vc.clear();
299 os.clear();
300 return -1;
301 }
302 }
303 return 0;
304
305// bail_header:
306// vorbis_info_clear(vi);
307// vorbis_comment_clear(vc);
308// ogg_stream_clear(&vf->os);
309// return -1;
310 }
311
312 // last step of the OggVorbis_File initialization; get all the
313 // vorbis_info structs and PCM positions. Only called by the seekable
314 // initialization (local stream storage is hacked slightly; pay
315 // attention to how that's done)
316 void prefetch_all_headers(Info first_i,Comment first_c,
317 int dataoffset) throws JOrbisException {
318 Page og=new Page();
319 int ret;
320
321 vi=new Info[links];
322 vc=new Comment[links];
323 dataoffsets=new long[links];
324 pcmlengths=new long[links];
325 serialnos=new int[links];
326
327 for(int i=0;i<links;i++){
328 if(first_i!=null && first_c!=null && i==0){
329 // we already grabbed the initial header earlier. This just
330 // saves the waste of grabbing it again
331 // !!!!!!!!!!!!!
332 vi[i]=first_i;
333 //memcpy(vf->vi+i,first_i,sizeof(vorbis_info));
334 vc[i]=first_c;
335 //memcpy(vf->vc+i,first_c,sizeof(vorbis_comment));
336 dataoffsets[i]=dataoffset;
337 }
338 else{
339 // seek to the location of the initial header
340 seek_helper(offsets[i]); //!!!
341 vi[i]=new Info();
342 vc[i]=new Comment();
343 if(fetch_headers(vi[i], vc[i], null, null)==-1){
344 //System.err.println("Error opening logical bitstream #"+(i+1)+"\n");
345 dataoffsets[i]=-1;
346 }
347 else{
348 dataoffsets[i]=offset;
349 os.clear();
350 }
351 }
352
353 // get the serial number and PCM length of this link. To do this,
354 // get the last page of the stream
355 {
356 long end=offsets[i+1]; //!!!
357 seek_helper(end);
358
359 while(true){
360 ret=get_prev_page(og);
361 if(ret==-1){
362 // this should not be possible
363 //System.err.println("Could not find last page of logical "+
364 // "bitstream #"+(i)+"\n");
365 vi[i].clear();
366 vc[i].clear();
367 break;
368 }
369 if(og.granulepos()!=-1){
370 serialnos[i]=og.serialno();
371 pcmlengths[i]=og.granulepos();
372 break;
373 }
374 }
375 }
376 }
377 }
378
379 int make_decode_ready(){
380 if(decode_ready)System.exit(1);
381 vd.synthesis_init(vi[0]);
382 vb.init(vd);
383 decode_ready=true;
384 return(0);
385 }
386
387 int open_seekable() throws JOrbisException {
388 Info initial_i=new Info();
389 Comment initial_c=new Comment();
390 int serialno;
391 long end;
392 int ret;
393 int dataoffset;
394 Page og=new Page();
395 // is this even vorbis...?
396 int[] foo=new int[1];
397 ret=fetch_headers(initial_i, initial_c, foo, null);
398 serialno=foo[0];
399 dataoffset=(int)offset; //!!
400 os.clear();
401 if(ret==-1)return(-1);
402 // we can seek, so set out learning all about this file
403 seekable=true;
404 //(callbacks.seek_func)(datasource, 0, SEEK_END);
405 fseek(datasource, 0, SEEK_END);
406 //offset=end=(callbacks.tell_func)(datasource);
407 offset=ftell(datasource);
408 end=offset;
409 // We get the offset for the last page of the physical bitstream.
410 // Most OggVorbis files will contain a single logical bitstream
411 end=get_prev_page(og);
412 // moer than one logical bitstream?
413 if(og.serialno()!=serialno){
414 // Chained bitstream. Bisect-search each logical bitstream
415 // section. Do so based on serial number only
416 if(bisect_forward_serialno(0,0,end+1,serialno,0)<0){
417 clear();
418 return OV_EREAD;
419 }
420 }
421 else{
422 // Only one logical bitstream
423 if(bisect_forward_serialno(0,end,end+1,serialno,0)<0){
424 clear();
425 return OV_EREAD;
426 }
427 }
428 prefetch_all_headers(initial_i, initial_c, dataoffset);
429 return(raw_seek(0));
430 }
431
432 int open_nonseekable(){
433 //System.err.println("open_nonseekable");
434 // we cannot seek. Set up a 'single' (current) logical bitstream entry
435 links=1;
436 vi=new Info[links]; vi[0]=new Info(); // ??
437 vc=new Comment[links]; vc[0]=new Comment(); // ?? bug?
438
439 // Try to fetch the headers, maintaining all the storage
440 int[]foo=new int[1];
441 if(fetch_headers(vi[0], vc[0], foo, null)==-1)return(-1);
442 current_serialno=foo[0];
443 make_decode_ready();
444 return 0;
445 }
446
447 // clear out the current logical bitstream decoder
448 void decode_clear(){
449 os.clear();
450 vd.clear();
451 vb.clear();
452 decode_ready=false;
453 bittrack=0.f;
454 samptrack=0.f;
455 }
456
457 // fetch and process a packet. Handles the case where we're at a
458 // bitstream boundary and dumps the decoding machine. If the decoding
459 // machine is unloaded, it loads it. It also keeps pcm_offset up to
460 // date (seek and read both use this. seek uses a special hack with
461 // readp).
462 //
463 // return: -1) hole in the data (lost packet)
464 // 0) need more date (only if readp==0)/eof
465 // 1) got a packet
466
467 int process_packet(int readp){
468 Page og=new Page();
469
470 // handle one packet. Try to fetch it from current stream state
471 // extract packets from page
472 while(true){
473 // process a packet if we can. If the machine isn't loaded,
474 // neither is a page
475 if(decode_ready){
476 Packet op=new Packet();
477 int result=os.packetout(op);
478 long granulepos;
479 // if(result==-1)return(-1); // hole in the data. For now, swallow
480 // and go. We'll need to add a real
481 // error code in a bit.
482 if(result>0){
483 // got a packet. process it
484 granulepos=op.granulepos;
485 if(vb.synthesis(op)==0){ // lazy check for lazy
486 // header handling. The
487 // header packets aren't
488 // audio, so if/when we
489 // submit them,
490 // vorbis_synthesis will
491 // reject them
492 // suck in the synthesis data and track bitrate
493 {
494 int oldsamples=vd.synthesis_pcmout(null, null);
495 vd.synthesis_blockin(vb);
496 samptrack+=vd.synthesis_pcmout(null, null)-oldsamples;
497 bittrack+=op.bytes*8;
498 }
499
500 // update the pcm offset.
501 if(granulepos!=-1 && op.e_o_s==0){
502 int link=(seekable?current_link:0);
503 int samples;
504 // this packet has a pcm_offset on it (the last packet
505 // completed on a page carries the offset) After processing
506 // (above), we know the pcm position of the *last* sample
507 // ready to be returned. Find the offset of the *first*
508 //
509 // As an aside, this trick is inaccurate if we begin
510 // reading anew right at the last page; the end-of-stream
511 // granulepos declares the last frame in the stream, and the
512 // last packet of the last page may be a partial frame.
513 // So, we need a previous granulepos from an in-sequence page
514 // to have a reference point. Thus the !op.e_o_s clause above
515
516 samples=vd.synthesis_pcmout(null, null);
517 granulepos-=samples;
518 for(int i=0;i<link;i++){
519 granulepos+=pcmlengths[i];
520 }
521 pcm_offset=granulepos;
522 }
523 return(1);
524 }
525 }
526 }
527
528 if(readp==0)return(0);
529 if(get_next_page(og,-1)<0)return(0); // eof. leave unitialized
530
531 // bitrate tracking; add the header's bytes here, the body bytes
532 // are done by packet above
533 bittrack+=og.header_len*8;
534
535 // has our decoding just traversed a bitstream boundary?
536 if(decode_ready){
537 if(current_serialno!=og.serialno()){
538 decode_clear();
539 }
540 }
541
542 // Do we need to load a new machine before submitting the page?
543 // This is different in the seekable and non-seekable cases.
544 //
545 // In the seekable case, we already have all the header
546 // information loaded and cached; we just initialize the machine
547 // with it and continue on our merry way.
548 //
549 // In the non-seekable (streaming) case, we'll only be at a
550 // boundary if we just left the previous logical bitstream and
551 // we're now nominally at the header of the next bitstream
552
553 if(!decode_ready){
554 int i;
555 if(seekable){
556 current_serialno=og.serialno();
557
558 // match the serialno to bitstream section. We use this rather than
559 // offset positions to avoid problems near logical bitstream
560 // boundaries
561 for(i=0;i<links;i++){
562 if(serialnos[i]==current_serialno)break;
563 }
564 if(i==links)return(-1); // sign of a bogus stream. error out,
565 // leave machine uninitialized
566 current_link=i;
567
568 os.init(current_serialno);
569 os.reset();
570
571 }
572 else{
573 // we're streaming
574 // fetch the three header packets, build the info struct
575 int foo[]=new int[1];
576 int ret=fetch_headers(vi[0], vc[0], foo, og);
577 current_serialno=foo[0];
578 if(ret!=0)return ret;
579 current_link++;
580 i=0;
581 }
582 make_decode_ready();
583 }
584 os.pagein(og);
585 }
586 }
587
588 //The helpers are over; it's all toplevel interface from here on out
589 // clear out the OggVorbis_File struct
590 int clear(){
591 vb.clear();
592 vd.clear();
593 os.clear();
594
595 if(vi!=null && links!=0){
596 for(int i=0;i<links;i++){
597 vi[i].clear();
598 vc[i].clear();
599 }
600 vi=null;
601 vc=null;
602 }
603 if(dataoffsets!=null)dataoffsets=null;
604 if(pcmlengths!=null)pcmlengths=null;
605 if(serialnos!=null)serialnos=null;
606 if(offsets!=null)offsets=null;
607 oy.clear();
608 //if(datasource!=null)(vf->callbacks.close_func)(vf->datasource);
609 //memset(vf,0,sizeof(OggVorbis_File));
610 return(0);
611 }
612
613 static int fseek(InputStream fis,
614 //int64_t off,
615 long off,
616 int whence){
617 if(fis instanceof SeekableInputStream){
618 SeekableInputStream sis=(SeekableInputStream)fis;
619 try{
620 if(whence==SEEK_SET){
621 sis.seek(off);
622 }
623 else if(whence==SEEK_END){
624 sis.seek(sis.getLength()-off);
625 }
626 else{
627 //System.out.println("seek: "+whence+" is not supported");
628 }
629 }
630 catch(Exception e){
631 }
632 return 0;
633 }
634 try{
635 if(whence==0){ fis.reset(); }
636 fis.skip(off);
637 }
638 catch(Exception e){return -1;}
639 return 0;
640 }
641
642 static long ftell(InputStream fis){
643 try{
644 if(fis instanceof SeekableInputStream){
645 SeekableInputStream sis=(SeekableInputStream)fis;
646 return (sis.tell());
647 }
648 }
649 catch(Exception e){
650 }
651 return 0;
652 }
653
654 // inspects the OggVorbis file and finds/documents all the logical
655 // bitstreams contained in it. Tries to be tolerant of logical
656 // bitstream sections that are truncated/woogie.
657 //
658 // return: -1) error
659 // 0) OK
660
661 int open(InputStream is, byte[] initial, int ibytes) throws JOrbisException {
662 //callbacks callbacks = {
663 // (size_t (*)(void *, size_t, size_t, void *)) fread,
664 // (int (*)(void *, int64_t, int)) _fseek,
665 // (int (*)(void *)) fclose,
666 // (long (*)(void *)) ftell
667 // };
668 return open_callbacks(is, initial, ibytes//, callbacks
669 );
670 }
671
672 int open_callbacks(InputStream is, byte[] initial,
673 int ibytes//, callbacks callbacks
674 ) throws JOrbisException {
675 int ret;
676 datasource=is;
677 //callbacks = _callbacks;
678 // init the framing state
679 oy.init();
680
681 // perhaps some data was previously read into a buffer for testing
682 // against other stream types. Allow initialization from this
683 // previously read data (as we may be reading from a non-seekable
684 // stream)
685 if(initial!=null){
686 int index=oy.buffer(ibytes);
687 System.arraycopy(initial, 0, oy.data, index, ibytes);
688 oy.wrote(ibytes);
689 }
690 // can we seek? Stevens suggests the seek test was portable
691 if(is instanceof SeekableInputStream){ ret=open_seekable(); }
692 else{ ret=open_nonseekable(); }
693 if(ret!=0){
694 datasource=null;
695 clear();
696 }
697 return ret;
698 }
699
700 // How many logical bitstreams in this physical bitstream?
701 public int streams(){
702 return links;
703 }
704
705 // Is the FILE * associated with vf seekable?
706 public boolean seekable(){
707 return seekable;
708 }
709
710 // returns the bitrate for a given logical bitstream or the entire
711 // physical bitstream. If the file is open for random access, it will
712 // find the *actual* average bitrate. If the file is streaming, it
713 // returns the nominal bitrate (if set) else the average of the
714 // upper/lower bounds (if set) else -1 (unset).
715 //
716 // If you want the actual bitrate field settings, get them from the
717 // vorbis_info structs
718
719 public int bitrate(int i){
720 if(i>=links)return(-1);
721 if(!seekable && i!=0)return(bitrate(0));
722 if(i<0){
723 long bits=0;
724 for(int j=0;j<links;j++){
725 bits+=(offsets[j+1]-dataoffsets[j])*8;
726 }
727 return((int)Math.rint(bits/time_total(-1)));
728 }
729 else{
730 if(seekable){
731 // return the actual bitrate
732 return((int)Math.rint((offsets[i+1]-dataoffsets[i])*8/time_total(i)));
733 }
734 else{
735 // return nominal if set
736 if(vi[i].bitrate_nominal>0){
737 return vi[i].bitrate_nominal;
738 }
739 else{
740 if(vi[i].bitrate_upper>0){
741 if(vi[i].bitrate_lower>0){
742 return (vi[i].bitrate_upper+vi[i].bitrate_lower)/2;
743 }else{
744 return vi[i].bitrate_upper;
745 }
746 }
747 return(-1);
748 }
749 }
750 }
751 }
752
753 // returns the actual bitrate since last call. returns -1 if no
754 // additional data to offer since last call (or at beginning of stream)
755 public int bitrate_instant(){
756 int _link=(seekable?current_link:0);
757 if(samptrack==0)return(-1);
758 int ret=(int)(bittrack/samptrack*vi[_link].rate+.5);
759 bittrack=0.f;
760 samptrack=0.f;
761 return(ret);
762 }
763
764 public int serialnumber(int i){
765 if(i>=links)return(-1);
766 if(!seekable && i>=0)return(serialnumber(-1));
767 if(i<0){
768 return(current_serialno);
769 }
770 else{
771 return(serialnos[i]);
772 }
773 }
774
775 // returns: total raw (compressed) length of content if i==-1
776 // raw (compressed) length of that logical bitstream for i==0 to n
777 // -1 if the stream is not seekable (we can't know the length)
778
779 public long raw_total(int i){
780 if(!seekable || i>=links)return(-1);
781 if(i<0){
782 long acc=0; // bug?
783 for(int j=0;j<links;j++){
784 acc+=raw_total(j);
785 }
786 return(acc);
787 }
788 else{
789 return(offsets[i+1]-offsets[i]);
790 }
791 }
792
793 // returns: total PCM length (samples) of content if i==-1
794 // PCM length (samples) of that logical bitstream for i==0 to n
795 // -1 if the stream is not seekable (we can't know the length)
796 public long pcm_total(int i){
797 if(!seekable || i>=links)return(-1);
798 if(i<0){
799 long acc=0;
800 for(int j=0;j<links;j++){
801 acc+=pcm_total(j);
802 }
803 return(acc);
804 }
805 else{
806 return(pcmlengths[i]);
807 }
808 }
809
810 // returns: total seconds of content if i==-1
811 // seconds in that logical bitstream for i==0 to n
812 // -1 if the stream is not seekable (we can't know the length)
813 public float time_total(int i){
814 if(!seekable || i>=links)return(-1);
815 if(i<0){
816 float acc=0;
817 for(int j=0;j<links;j++){
818 acc+=time_total(j);
819 }
820 return(acc);
821 }
822 else{
823 return((float)(pcmlengths[i])/vi[i].rate);
824 }
825 }
826
827 // seek to an offset relative to the *compressed* data. This also
828 // immediately sucks in and decodes pages to update the PCM cursor. It
829 // will cross a logical bitstream boundary, but only if it can't get
830 // any packets out of the tail of the bitstream we seek to (so no
831 // surprises).
832 //
833 // returns zero on success, nonzero on failure
834
835 public int raw_seek(int pos){
836 if(!seekable)return(-1); // don't dump machine if we can't seek
837 if(pos<0 || pos>offsets[links]){
838 //goto seek_error;
839 pcm_offset=-1;
840 decode_clear();
841 return -1;
842 }
843
844 // clear out decoding machine state
845 pcm_offset=-1;
846 decode_clear();
847
848 // seek
849 seek_helper(pos);
850
851 // we need to make sure the pcm_offset is set. We use the
852 // _fetch_packet helper to process one packet with readp set, then
853 // call it until it returns '0' with readp not set (the last packet
854 // from a page has the 'granulepos' field set, and that's how the
855 // helper updates the offset
856
857 switch(process_packet(1)){
858 case 0:
859 // oh, eof. There are no packets remaining. Set the pcm offset to
860 // the end of file
861 pcm_offset=pcm_total(-1);
862 return(0);
863 case -1:
864 // error! missing data or invalid bitstream structure
865 //goto seek_error;
866 pcm_offset=-1;
867 decode_clear();
868 return -1;
869 default:
870 // all OK
871 break;
872 }
873 while(true){
874 switch(process_packet(0)){
875 case 0:
876 // the offset is set. If it's a bogus bitstream with no offset
877 // information, it's not but that's not our fault. We still run
878 // gracefully, we're just missing the offset
879 return(0);
880 case -1:
881 // error! missing data or invalid bitstream structure
882 //goto seek_error;
883 pcm_offset=-1;
884 decode_clear();
885 return -1;
886 default:
887 // continue processing packets
888 break;
889 }
890 }
891
892 // seek_error:
893 // dump the machine so we're in a known state
894 //pcm_offset=-1;
895 //decode_clear();
896 //return -1;
897 }
898
899 // seek to a sample offset relative to the decompressed pcm stream
900 // returns zero on success, nonzero on failure
901
902 public int pcm_seek(long pos){
903 int link=-1;
904 long total=pcm_total(-1);
905
906 if(!seekable)return(-1); // don't dump machine if we can't seek
907 if(pos<0 || pos>total){
908 //goto seek_error;
909 pcm_offset=-1;
910 decode_clear();
911 return -1;
912 }
913
914 // which bitstream section does this pcm offset occur in?
915 for(link=links-1;link>=0;link--){
916 total-=pcmlengths[link];
917 if(pos>=total)break;
918 }
919
920 // search within the logical bitstream for the page with the highest
921 // pcm_pos preceeding (or equal to) pos. There is a danger here;
922 // missing pages or incorrect frame number information in the
923 // bitstream could make our task impossible. Account for that (it
924 // would be an error condition)
925 {
926 long target=pos-total;
927 long end=offsets[link+1];
928 long begin=offsets[link];
929 int best=(int)begin;
930
931 Page og=new Page();
932 while(begin<end){
933 long bisect;
934 int ret;
935
936 if(end-begin<CHUNKSIZE){
937 bisect=begin;
938 }
939 else{
940 bisect=(end+begin)/2;
941 }
942
943 seek_helper(bisect);
944 ret=get_next_page(og,end-bisect);
945
946 if(ret==-1){
947 end=bisect;
948 }
949 else{
950 long granulepos=og.granulepos();
951 if(granulepos<target){
952 best=ret; // raw offset of packet with granulepos
953 begin=offset; // raw offset of next packet
954 }
955 else{
956 end=bisect;
957 }
958 }
959 }
960 // found our page. seek to it (call raw_seek).
961 if(raw_seek(best)!=0){
962 //goto seek_error;
963 pcm_offset=-1;
964 decode_clear();
965 return -1;
966 }
967 }
968
969 // verify result
970 if(pcm_offset>=pos){
971 //goto seek_error;
972 pcm_offset=-1;
973 decode_clear();
974 return -1;
975 }
976 if(pos>pcm_total(-1)){
977 //goto seek_error;
978 pcm_offset=-1;
979 decode_clear();
980 return -1;
981 }
982
983 // discard samples until we reach the desired position. Crossing a
984 // logical bitstream boundary with abandon is OK.
985 while(pcm_offset<pos){
986 float[][] pcm;
987 int target=(int)(pos-pcm_offset);
988 float[][][] _pcm=new float[1][][];
989 int[] _index=new int[getInfo(-1).channels];
990 int samples=vd.synthesis_pcmout(_pcm, _index);
991 pcm=_pcm[0];
992
993 if(samples>target)samples=target;
994 vd.synthesis_read(samples);
995 pcm_offset+=samples;
996
997 if(samples<target)
998 if(process_packet(1)==0){
999 pcm_offset=pcm_total(-1); // eof
1000 }
1001 }
1002 return 0;
1003
1004 // seek_error:
1005 // dump machine so we're in a known state
1006 //pcm_offset=-1;
1007 //decode_clear();
1008 //return -1;
1009 }
1010
1011 // seek to a playback time relative to the decompressed pcm stream
1012 // returns zero on success, nonzero on failure
1013 int time_seek(float seconds){
1014 // translate time to PCM position and call pcm_seek
1015
1016 int link=-1;
1017 long pcm_total=pcm_total(-1);
1018 float time_total=time_total(-1);
1019
1020 if(!seekable)return(-1); // don't dump machine if we can't seek
1021 if(seconds<0 || seconds>time_total){
1022 //goto seek_error;
1023 pcm_offset=-1;
1024 decode_clear();
1025 return -1;
1026 }
1027
1028 // which bitstream section does this time offset occur in?
1029 for(link=links-1;link>=0;link--){
1030 pcm_total-=pcmlengths[link];
1031 time_total-=time_total(link);
1032 if(seconds>=time_total)break;
1033 }
1034
1035 // enough information to convert time offset to pcm offset
1036 {
1037 long target=(long)(pcm_total+(seconds-time_total)*vi[link].rate);
1038 return(pcm_seek(target));
1039 }
1040
1041 //seek_error:
1042 // dump machine so we're in a known state
1043 //pcm_offset=-1;
1044 //decode_clear();
1045 //return -1;
1046 }
1047
1048 // tell the current stream offset cursor. Note that seek followed by
1049 // tell will likely not give the set offset due to caching
1050 public long raw_tell(){
1051 return(offset);
1052 }
1053
1054 // return PCM offset (sample) of next PCM sample to be read
1055 public long pcm_tell(){
1056 return(pcm_offset);
1057 }
1058
1059 // return time offset (seconds) of next PCM sample to be read
1060 public float time_tell(){
1061 // translate time to PCM position and call pcm_seek
1062
1063 int link=-1;
1064 long pcm_total=0;
1065 float time_total=0.f;
1066
1067 if(seekable){
1068 pcm_total=pcm_total(-1);
1069 time_total=time_total(-1);
1070
1071 // which bitstream section does this time offset occur in?
1072 for(link=links-1;link>=0;link--){
1073 pcm_total-=pcmlengths[link];
1074 time_total-=time_total(link);
1075 if(pcm_offset>=pcm_total)break;
1076 }
1077 }
1078
1079 return((float)time_total+(float)(pcm_offset-pcm_total)/vi[link].rate);
1080 }
1081
1082 // link: -1) return the vorbis_info struct for the bitstream section
1083 // currently being decoded
1084 // 0-n) to request information for a specific bitstream section
1085 //
1086 // In the case of a non-seekable bitstream, any call returns the
1087 // current bitstream. NULL in the case that the machine is not
1088 // initialized
1089
1090 public Info getInfo(int link){
1091 if(seekable){
1092 if(link<0){
1093 if(decode_ready){
1094 return vi[current_link];
1095 }
1096 else{
1097 return null;
1098 }
1099 }
1100 else{
1101 if(link>=links){
1102 return null;
1103 }
1104 else{
1105 return vi[link];
1106 }
1107 }
1108 }
1109 else{
1110 if(decode_ready){
1111 return vi[0];
1112 }
1113 else{
1114 return null;
1115 }
1116 }
1117 }
1118
1119 public Comment getComment(int link){
1120 if(seekable){
1121 if(link<0){
1122 if(decode_ready){ return vc[current_link]; }
1123 else{ return null; }
1124 }
1125 else{
1126 if(link>=links){ return null;}
1127 else{ return vc[link]; }
1128 }
1129 }
1130 else{
1131 if(decode_ready){ return vc[0]; }
1132 else{ return null; }
1133 }
1134 }
1135
1136 int host_is_big_endian() {
1137 return 1;
1138// short pattern = 0xbabe;
1139// unsigned char *bytewise = (unsigned char *)&pattern;
1140// if (bytewise[0] == 0xba) return 1;
1141// assert(bytewise[0] == 0xbe);
1142// return 0;
1143 }
1144
1145 // up to this point, everything could more or less hide the multiple
1146 // logical bitstream nature of chaining from the toplevel application
1147 // if the toplevel application didn't particularly care. However, at
1148 // the point that we actually read audio back, the multiple-section
1149 // nature must surface: Multiple bitstream sections do not necessarily
1150 // have to have the same number of channels or sampling rate.
1151 //
1152 // read returns the sequential logical bitstream number currently
1153 // being decoded along with the PCM data in order that the toplevel
1154 // application can take action on channel/sample rate changes. This
1155 // number will be incremented even for streamed (non-seekable) streams
1156 // (for seekable streams, it represents the actual logical bitstream
1157 // index within the physical bitstream. Note that the accessor
1158 // functions above are aware of this dichotomy).
1159 //
1160 // input values: buffer) a buffer to hold packed PCM data for return
1161 // length) the byte length requested to be placed into buffer
1162 // bigendianp) should the data be packed LSB first (0) or
1163 // MSB first (1)
1164 // word) word size for output. currently 1 (byte) or
1165 // 2 (16 bit short)
1166 //
1167 // return values: -1) error/hole in data
1168 // 0) EOF
1169 // n) number of bytes of PCM actually returned. The
1170 // below works on a packet-by-packet basis, so the
1171 // return length is not related to the 'length' passed
1172 // in, just guaranteed to fit.
1173 //
1174 // *section) set to the logical bitstream number
1175
1176 int read(byte[] buffer,int length,
1177 int bigendianp, int word, int sgned, int[] bitstream){
1178 int host_endian = host_is_big_endian();
1179 int index=0;
1180
1181 while(true){
1182 if(decode_ready){
1183 float[][] pcm;
1184 float[][][] _pcm=new float[1][][];
1185 int[] _index=new int[getInfo(-1).channels];
1186 int samples=vd.synthesis_pcmout(_pcm, _index);
1187 pcm=_pcm[0];
1188 if(samples!=0){
1189 // yay! proceed to pack data into the byte buffer
1190 int channels=getInfo(-1).channels;
1191 int bytespersample=word * channels;
1192 if(samples>length/bytespersample)samples=length/bytespersample;
1193
1194 // a tight loop to pack each size
1195 {
1196 int val;
1197 if(word==1){
1198 int off=(sgned!=0?0:128);
1199 for(int j=0;j<samples;j++){
1200 for(int i=0;i<channels;i++){
1201 val=(int)(pcm[i][_index[i]+j]*128. + 0.5);
1202 if(val>127)val=127;
1203 else if(val<-128)val=-128;
1204 buffer[index++]=(byte)(val+off);
1205 }
1206 }
1207 }
1208 else{
1209 int off=(sgned!=0?0:32768);
1210
1211 if(host_endian==bigendianp){
1212 if(sgned!=0){
1213 for(int i=0;i<channels;i++) { // It's faster in this order
1214 int src=_index[i];
1215 int dest=i;
1216 for(int j=0;j<samples;j++) {
1217 val=(int)(pcm[i][src+j]*32768. + 0.5);
1218 if(val>32767)val=32767;
1219 else if(val<-32768)val=-32768;
1220 buffer[dest]=(byte)(val>>>8);
1221 buffer[dest+1]=(byte)(val);
1222 dest+=channels*2;
1223 }
1224 }
1225 }
1226 else{
1227 for(int i=0;i<channels;i++) {
1228 float[] src=pcm[i];
1229 int dest=i;
1230 for(int j=0;j<samples;j++) {
1231 val=(int)(src[j]*32768. + 0.5);
1232 if(val>32767)val=32767;
1233 else if(val<-32768)val=-32768;
1234 buffer[dest]=(byte)((val+off)>>>8);
1235 buffer[dest+1]=(byte)(val+off);
1236 dest+=channels*2;
1237 }
1238 }
1239 }
1240 }
1241 else if(bigendianp!=0){
1242 for(int j=0;j<samples;j++){
1243 for(int i=0;i<channels;i++){
1244 val=(int)(pcm[i][j]*32768. + 0.5);
1245 if(val>32767)val=32767;
1246 else if(val<-32768)val=-32768;
1247 val+=off;
1248 buffer[index++]=(byte)(val>>>8);
1249 buffer[index++]=(byte)val;
1250 }
1251 }
1252 }
1253 else{
1254 //int val;
1255 for(int j=0;j<samples;j++){
1256 for(int i=0;i<channels;i++){
1257 val=(int)(pcm[i][j]*32768. + 0.5);
1258 if(val>32767)val=32767;
1259 else if(val<-32768)val=-32768;
1260 val+=off;
1261 buffer[index++]=(byte)val;
1262 buffer[index++]=(byte)(val>>>8);
1263 }
1264 }
1265 }
1266 }
1267 }
1268
1269 vd.synthesis_read(samples);
1270 pcm_offset+=samples;
1271 if(bitstream!=null)bitstream[0]=current_link;
1272 return(samples*bytespersample);
1273 }
1274 }
1275
1276 // suck in another packet
1277 switch(process_packet(1)){
1278 case 0:
1279 return(0);
1280 case -1:
1281 return -1;
1282 default:
1283 break;
1284 }
1285 }
1286 }
1287
1288 public Info[] getInfo(){return vi;}
1289 public Comment[] getComment(){return vc;}
1290
1291/*
1292 public static void main(String[] arg){
1293 try{
1294 VorbisFile foo=new VorbisFile(arg[0]);
1295 int links=foo.streams();
1296 System.out.println("links="+links);
1297 Comment[] comment=foo.getComment();
1298 Info[] info=foo.getInfo();
1299 for(int i=0; i<links; i++){
1300 System.out.println(info[i]);
1301 System.out.println(comment[i]);
1302 }
1303 System.out.println("raw_total: "+foo.raw_total(-1));
1304 System.out.println("pcm_total: "+foo.pcm_total(-1));
1305 System.out.println("time_total: "+foo.time_total(-1));
1306 }
1307 catch(Exception e){
1308 System.err.println(e);
1309 }
1310 }
1311*/
1312
1313 public void close() throws java.io.IOException {
1314 datasource.close();
1315 }
1316
1317 class SeekableInputStream extends InputStream {
1318 java.io.RandomAccessFile raf=null;
1319 final String mode="r";
1320 private SeekableInputStream(){
1321 }
1322 SeekableInputStream(String file) throws java.io.IOException{
1323 raf=new java.io.RandomAccessFile(file, mode);
1324 }
1325 public int read() throws java.io.IOException{
1326 return raf.read();
1327 }
1328 public int read(byte[] buf) throws java.io.IOException{
1329 return raf.read(buf);
1330 }
1331 public int read(byte[] buf , int s, int len) throws java.io.IOException{
1332 return raf.read(buf, s, len);
1333 }
1334 public long skip(long n) throws java.io.IOException{
1335 return (long)(raf.skipBytes((int)n));
1336 }
1337 public long getLength() throws java.io.IOException{
1338 return raf.length();
1339 }
1340 public long tell() throws java.io.IOException{
1341 return raf.getFilePointer();
1342 }
1343 public int available() throws java.io.IOException{
1344 return (raf.length()==raf.getFilePointer())? 0 : 1;
1345 }
1346 public void close() throws java.io.IOException{
1347 raf.close();
1348 }
1349 public synchronized void mark(int m){
1350 }
1351 public synchronized void reset() throws java.io.IOException{
1352 }
1353 public boolean markSupported(){
1354 return false;
1355 }
1356 public void seek(long pos) throws java.io.IOException{
1357 raf.seek(pos);
1358 }
1359 }
1360
1361}
This page took 0.113296 seconds and 4 git commands to generate.