From 7039a05147b8bbfc829babea1c65bd436450b505 Mon Sep 17 00:00:00 2001 From: Björn Stenberg Date: Mon, 8 Jan 2007 23:53:00 +0000 Subject: Splitting out songdbj git-svn-id: svn://svn.rockbox.org/rockbox/trunk@11953 a1c6a512-1295-4272-9138-f99709370657 --- songdbj/com/jcraft/jorbis/VorbisFile.java.new | 1240 ------------------------- 1 file changed, 1240 deletions(-) delete mode 100644 songdbj/com/jcraft/jorbis/VorbisFile.java.new (limited to 'songdbj/com/jcraft/jorbis/VorbisFile.java.new') diff --git a/songdbj/com/jcraft/jorbis/VorbisFile.java.new b/songdbj/com/jcraft/jorbis/VorbisFile.java.new deleted file mode 100644 index 1f822b0991..0000000000 --- a/songdbj/com/jcraft/jorbis/VorbisFile.java.new +++ /dev/null @@ -1,1240 +0,0 @@ -/* JOrbis - * Copyright (C) 2000 ymnk, JCraft,Inc. - * - * Written by: 2000 ymnk - * - * Many thanks to - * Monty and - * The XIPHOPHORUS Company http://www.xiph.org/ . - * JOrbis has been based on their awesome works, Vorbis codec. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public License - * as published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -package com.jcraft.jorbis; - -import com.jcraft.jogg.*; -import java.io.InputStream; - -public class VorbisFile{ - static final int CHUNKSIZE=4096; - static final int SEEK_SET=0; - - InputStream datasource; - boolean seekable=false; - long offset; - long end; - - SyncState oy=new SyncState(); - - int links; - Comment[] vc; - Info[] vi; - - long[] offsets; - long[] dataoffsets; - int[] serialnos; - long[] pcmlengths; - - - - // Decoding working state local storage - long pcm_offset; - boolean decode_ready=false; - int current_serialno; - int current_link; - - float bittrack; - float samptrack; - - StreamState os=new StreamState(); // take physical pages, weld into a logical - // stream of packets - DspState vd=new DspState(); // central working state for - // the packet->PCM decoder - Block vb=new Block(vd); // local working space for packet->PCM decode - - //ov_callbacks callbacks; - - public VorbisFile(String file) throws JOrbisException { - super(); - InputStream is=null; - try{ is=new java.io.BufferedInputStream(new java.io.FileInputStream(file));} - catch(Exception e){ - throw new JOrbisException("VorbisFile: "+e.toString()); - } - int ret=open(is, null, 0); - if(ret==-1){ - throw new JOrbisException("VorbisFile: open return -1"); - } - } - - public VorbisFile(InputStream is, byte[] initial, int ibytes) - throws JOrbisException { - super(); - int ret=open(is, initial, ibytes); - if(ret==-1){ - } - } - - private int get_data(){ - int index=oy.buffer(CHUNKSIZE); - byte[] buffer=oy.data; -// int bytes=callbacks.read_func(buffer, index, 1, CHUNKSIZE, datasource); - int bytes=0; - try{ - bytes=datasource.read(buffer, index, CHUNKSIZE); - } - catch(Exception e){System.err.println(e);} - oy.wrote(bytes); - return bytes; - } - - private void seek_helper(int offst){ - //callbacks.seek_func(datasource, offst, SEEK_SET); - fseek64_wrap(datasource, offst, SEEK_SET); - this.offset=offst; - oy.reset(); - } - - private int get_next_page(Page page, int boundary){ - if(boundary>0) boundary+=offset; - while(true){ - int more; - if(boundary>0 && offset>=boundary)return -1; - more=oy.pageseek(page); - if(more<0){offset-=more;} - else{ - if(more==0){ - if(boundary==0)return -1; - if(get_data()<=0)return -1; - } - else{ - int ret=(int)offset; //!!! - offset+=more; - return ret; - } - } - } - } - - private int get_prev_page(Page page){ - int begin=(int)offset; //!!! - int ret; - int offst=-1; - while(offst==-1){ - begin-=CHUNKSIZE; - seek_helper(begin); - while(offset=0)next=ret; - } - else{ - searched=ret+page.header_len+page.body_len; - } - } - seek_helper(next); - ret=get_next_page(page, -1); - - if(searched>=end || ret==-1){ - links=m+1; - offsets=new long[m+2]; - offsets[m+1]=searched; - } - else{ - bisect_forward_serialno(next, (int)offset, end, page.serialno(), m+1); - } - offsets[m]=begin; - } - - // uses the local ogg_stream storage in vf; this is important for - // non-streaming input sources - int fetch_headers(Info vi, Comment vc, int[] serialno){ - //System.err.println("fetch_headers"); - Page og=new Page(); - Packet op=new Packet(); - int ret; - - ret=get_next_page(og, CHUNKSIZE); - if(ret==-1){ - System.err.println("Did not find initial header for bitstream."); - return -1; - } - - if(serialno!=null)serialno[0]=og.serialno(); - - os.init(og.serialno()); - - // extract the initial header from the first page and verify that the - // Ogg bitstream is in fact Vorbis data - - vi.init(); - vc.init(); - - int i=0; - while(i<3){ - os.pagein(og); - while(i<3){ - int result=os.packetout(op); - if(result==0)break; - if(result==-1){ - System.err.println("Corrupt header in logical bitstream."); - //goto bail_header; - vi.clear(); - vc.clear(); - os.clear(); - return -1; - } - if(vi.synthesis_headerin(vc, op)!=0){ - System.err.println("Illegal header in logical bitstream."); - //goto bail_header; - vi.clear(); - vc.clear(); - os.clear(); - return -1; - } - i++; - } - if(i<3) - if(get_next_page(og, 1)<0){ - System.err.println("Missing header in logical bitstream."); - //goto bail_header; - vi.clear(); - vc.clear(); - os.clear(); - return -1; - } - } - return 0; - -// bail_header: -// vorbis_info_clear(vi); -// vorbis_comment_clear(vc); -// ogg_stream_clear(&vf->os); -// return -1; - } - - // last step of the OggVorbis_File initialization; get all the - // vorbis_info structs and PCM positions. Only called by the seekable - // initialization (local stream storage is hacked slightly; pay - // attention to how that's done) - void prefetch_all_headers(Info first_i,Comment first_c, int dataoffset){ - Page og=new Page(); - int ret; - - vi=new Info[links]; - vc=new Comment[links]; - dataoffsets=new long[links]; - pcmlengths=new long[links]; - serialnos=new int[links]; - - for(int i=0;ivi+i,first_i,sizeof(vorbis_info)); - vc[i]=first_c; - //memcpy(vf->vc+i,first_c,sizeof(vorbis_comment)); - dataoffsets[i]=dataoffset; - } - else{ - // seek to the location of the initial header - seek_helper((int)offsets[i]); //!!! - if(fetch_headers(vi[i], vc[i], null)==-1){ - System.err.println("Error opening logical bitstream #"+(i+1)+"\n"); - dataoffsets[i]=-1; - } - else{ - dataoffsets[i]=offset; - os.clear(); - } - } - - // get the serial number and PCM length of this link. To do this, - // get the last page of the stream - { - int end=(int)offsets[i+1]; //!!! - seek_helper(end); - - while(true){ - ret=get_prev_page(og); - if(ret==-1){ - // this should not be possible - System.err.println("Could not find last page of logical "+ - "bitstream #"+(i)+"\n"); - vi[i].clear(); - vc[i].clear(); - break; - } - if(og.granulepos()!=-1){ - serialnos[i]=og.serialno(); - pcmlengths[i]=og.granulepos(); - break; - } - } - } - } - } - - int make_decode_ready(){ - if(decode_ready)System.exit(1); - vd.synthesis_init(vi[0]); - vb.init(vd); - decode_ready=true; - return(0); - } - - int open_seekable(){ - Info initial_i=new Info(); - Comment initial_c=new Comment(); - int serialno,end; - int ret; - int dataoffset; - Page og=new Page(); -System.out.println("open_seekable"); - // is this even vorbis...? - int[] foo=new int[1]; - ret=fetch_headers(initial_i, initial_c, foo); - serialno=foo[0]; - dataoffset=(int)offset; //!! - os.clear(); - if(ret==-1)return(-1); - - // we can seek, so set out learning all about this file - seekable=true; - //(callbacks.seek_func)(datasource, 0, SEEK_END); - fseek64_wrap(datasource, (int)offset, SEEK_SET); - //offset=end=(callbacks.tell_func)(datasource); - end=(int)offset; - - // We get the offset for the last page of the physical bitstream. - // Most OggVorbis files will contain a single logical bitstream - end=get_prev_page(og); - - // moer than one logical bitstream? - if(og.serialno()!=serialno){ - // Chained bitstream. Bisect-search each logical bitstream - // section. Do so based on serial number only - bisect_forward_serialno(0,0,end+1,serialno,0); - } - else{ - // Only one logical bitstream - bisect_forward_serialno(0,end,end+1,serialno,0); - } - prefetch_all_headers(initial_i, initial_c, dataoffset); - -System.out.println("?"); - return(raw_seek(0)); - } - - int open_nonseekable(){ - //System.err.println("open_nonseekable"); - // we cannot seek. Set up a 'single' (current) logical bitstream entry - links=1; - vi=new Info[links]; vi[0]=new Info(); // ?? - vc=new Comment[links]; vc[0]=new Comment(); // ?? bug? - - // Try to fetch the headers, maintaining all the storage - int[]foo=new int[1]; - if(fetch_headers(vi[0], vc[0], foo)==-1)return(-1); - current_serialno=foo[0]; - make_decode_ready(); - return 0; - } - - // clear out the current logical bitstream decoder - void decode_clear(){ - os.clear(); - vd.clear(); - vb.clear(); - decode_ready=false; - bittrack=0.f; - samptrack=0.f; - } - - // fetch and process a packet. Handles the case where we're at a - // bitstream boundary and dumps the decoding machine. If the decoding - // machine is unloaded, it loads it. It also keeps pcm_offset up to - // date (seek and read both use this. seek uses a special hack with - // readp). - // - // return: -1) hole in the data (lost packet) - // 0) need more date (only if readp==0)/eof - // 1) got a packet - - int process_packet(int readp){ -System.out.println("porcess_packet:"+ readp+" , decode_ready="+decode_ready); - Page og=new Page(); - - // handle one packet. Try to fetch it from current stream state - // extract packets from page - while(true){ - // process a packet if we can. If the machine isn't loaded, - // neither is a page - if(decode_ready){ - Packet op=new Packet(); - int result=os.packetout(op); - long granulepos; - // if(result==-1)return(-1); // hole in the data. For now, swallow - // and go. We'll need to add a real - // error code in a bit. - if(result>0){ - // got a packet. process it - granulepos=op.granulepos; - if(vb.synthesis(op)==0){ // lazy check for lazy - // header handling. The - // header packets aren't - // audio, so if/when we - // submit them, - // vorbis_synthesis will - // reject them - // suck in the synthesis data and track bitrate - { - int oldsamples=vd.synthesis_pcmout(null, null); - vd.synthesis_blockin(vb); - samptrack+=vd.synthesis_pcmout(null, null)-oldsamples; - bittrack+=op.bytes*8; - } - - // update the pcm offset. - if(granulepos!=-1 && op.e_o_s==0){ - int link=(seekable?current_link:0); - int samples; - // this packet has a pcm_offset on it (the last packet - // completed on a page carries the offset) After processing - // (above), we know the pcm position of the *last* sample - // ready to be returned. Find the offset of the *first* - // - // As an aside, this trick is inaccurate if we begin - // reading anew right at the last page; the end-of-stream - // granulepos declares the last frame in the stream, and the - // last packet of the last page may be a partial frame. - // So, we need a previous granulepos from an in-sequence page - // to have a reference point. Thus the !op.e_o_s clause above - - samples=vd.synthesis_pcmout(null, null); - granulepos-=samples; - for(int i=0;icallbacks.close_func)(vf->datasource); - //memset(vf,0,sizeof(OggVorbis_File)); - return(0); - } - - static int fseek64_wrap(InputStream fis, - //int64_t off, - int off, - int whence){ - - if(!fis.markSupported()){ return -1; } - try{ - try{if(whence==0){ fis.reset(); }} - catch(Exception ee){System.out.println(ee);} - fis.skip(off); - } - catch(Exception e){ System.out.println(e); - //return -1; - } - return 0; - } - - // inspects the OggVorbis file and finds/documents all the logical - // bitstreams contained in it. Tries to be tolerant of logical - // bitstream sections that are truncated/woogie. - // - // return: -1) error - // 0) OK - - int open(InputStream is, byte[] initial, int ibytes){ - return open_callbacks(is, initial, ibytes//, callbacks - ); - } - - int open_callbacks(InputStream is, byte[] initial, - int ibytes//, callbacks callbacks - ){ -// int offset=callbacks.seek_func(f,0,SEEK_CUR); - int _offset=fseek64_wrap(is, (int)offset, SEEK_SET); - int ret; - // memset(vf,0,sizeof(OggVorbis_File)); - datasource=is; - //callbacks = _callbacks; - - // init the framing state - oy.init(); - - // perhaps some data was previously read into a buffer for testing - // against other stream types. Allow initialization from this - // previously read data (as we may be reading from a non-seekable - // stream) - if(initial!=null){ - int index=oy.buffer(ibytes); - System.arraycopy(initial, 0, oy.data, index, ibytes); - oy.wrote(ibytes); - } - -System.out.println("open_callbacks="+_offset); - // can we seek? Stevens suggests the seek test was portable - if(_offset!=-1){ ret=open_seekable(); } - else{ ret=open_nonseekable(); } - -System.out.println("ret="+ret); - - if(ret!=0){ - datasource=null; - clear(); - } - - return(ret); - } - - // How many logical bitstreams in this physical bitstream? - public int streams(){ - return links; - } - - // Is the FILE * associated with vf seekable? - public boolean seekable(){ - return seekable; - } - - // returns the bitrate for a given logical bitstream or the entire - // physical bitstream. If the file is open for random access, it will - // find the *actual* average bitrate. If the file is streaming, it - // returns the nominal bitrate (if set) else the average of the - // upper/lower bounds (if set) else -1 (unset). - // - // If you want the actual bitrate field settings, get them from the - // vorbis_info structs - - public int bitrate(int i){ - if(i>=links)return(-1); - if(!seekable && i!=0)return(bitrate(0)); - if(i<0){ - long bits=0; - for(int j=0;j0){ - return vi[i].bitrate_nominal; - } - else{ - if(vi[i].bitrate_upper>0){ - if(vi[i].bitrate_lower>0){ - return (vi[i].bitrate_upper+vi[i].bitrate_lower)/2; - }else{ - return vi[i].bitrate_upper; - } - } - return(-1); - } - } - } - } - - // returns the actual bitrate since last call. returns -1 if no - // additional data to offer since last call (or at beginning of stream) - public int bitrate_instant(){ - int _link=(seekable?current_link:0); - if(samptrack==0)return(-1); - int ret=(int)(bittrack/samptrack*vi[_link].rate+.5); - bittrack=0.f; - samptrack=0.f; - return(ret); - } - - public int serialnumber(int i){ - if(i>=links)return(-1); - if(!seekable && i>=0)return(serialnumber(-1)); - if(i<0){ - return(current_serialno); - } - else{ - return(serialnos[i]); - } - } - - // returns: total raw (compressed) length of content if i==-1 - // raw (compressed) length of that logical bitstream for i==0 to n - // -1 if the stream is not seekable (we can't know the length) - - public long raw_total(int i){ -System.out.println("raw_total: "+seekable); - if(!seekable || i>=links)return(-1); - if(i<0){ - long acc=0; // bug? - for(int j=0;j=links)return(-1); - if(i<0){ - long acc=0; - for(int j=0;j=links)return(-1); - if(i<0){ - float acc=0; - for(int j=0;joffsets[links]){ - //goto seek_error; - pcm_offset=-1; - decode_clear(); - return -1; - } -System.out.println("#1"); - // clear out decoding machine state - pcm_offset=-1; -System.out.println("#2"); - decode_clear(); -System.out.println("#3"); - // seek - seek_helper(pos); - - // we need to make sure the pcm_offset is set. We use the - // _fetch_packet helper to process one packet with readp set, then - // call it until it returns '0' with readp not set (the last packet - // from a page has the 'granulepos' field set, and that's how the - // helper updates the offset -System.out.println("#4"); - switch(process_packet(1)){ - case 0: -System.out.println("?0"); - // oh, eof. There are no packets remaining. Set the pcm offset to - // the end of file - pcm_offset=pcm_total(-1); - return(0); - case -1: -System.out.println("?-1"); - // error! missing data or invalid bitstream structure - //goto seek_error; - pcm_offset=-1; - decode_clear(); - return -1; - default: -System.out.println("?break"); - // all OK - break; - } -System.out.println("pcm_offset="+pcm_offset); - while(true){ - switch(process_packet(0)){ - case 0: - // the offset is set. If it's a bogus bitstream with no offset - // information, it's not but that's not our fault. We still run - // gracefully, we're just missing the offset - return(0); - case -1: - // error! missing data or invalid bitstream structure - //goto seek_error; - pcm_offset=-1; - decode_clear(); - return -1; - default: - // continue processing packets - break; - } - } - - // seek_error: - // dump the machine so we're in a known state - //pcm_offset=-1; - //decode_clear(); - //return -1; - } - - // seek to a sample offset relative to the decompressed pcm stream - // returns zero on success, nonzero on failure - - public int pcm_seek(long pos){ - int link=-1; - long total=pcm_total(-1); - - if(!seekable)return(-1); // don't dump machine if we can't seek - if(pos<0 || pos>total){ - //goto seek_error; - pcm_offset=-1; - decode_clear(); - return -1; - } - - // which bitstream section does this pcm offset occur in? - for(link=links-1;link>=0;link--){ - total-=pcmlengths[link]; - if(pos>=total)break; - } - - // search within the logical bitstream for the page with the highest - // pcm_pos preceeding (or equal to) pos. There is a danger here; - // missing pages or incorrect frame number information in the - // bitstream could make our task impossible. Account for that (it - // would be an error condition) - { - long target=pos-total; - int end=(int)offsets[link+1]; - int begin=(int)offsets[link]; - int best=begin; - - Page og=new Page(); - while(begin=pos){ - //goto seek_error; - pcm_offset=-1; - decode_clear(); - return -1; - } - if(pos>pcm_total(-1)){ - //goto seek_error; - pcm_offset=-1; - decode_clear(); - return -1; - } - - // discard samples until we reach the desired position. Crossing a - // logical bitstream boundary with abandon is OK. - while(pcm_offsettarget)samples=target; - vd.synthesis_read(samples); - pcm_offset+=samples; - - if(samplestime_total){ - //goto seek_error; - pcm_offset=-1; - decode_clear(); - return -1; - } - - // which bitstream section does this time offset occur in? - for(link=links-1;link>=0;link--){ - pcm_total-=pcmlengths[link]; - time_total-=time_total(link); - if(seconds>=time_total)break; - } - - // enough information to convert time offset to pcm offset - { - long target=(long)(pcm_total+(seconds-time_total)*vi[link].rate); - return(pcm_seek(target)); - } - - //seek_error: - // dump machine so we're in a known state - //pcm_offset=-1; - //decode_clear(); - //return -1; - } - - // tell the current stream offset cursor. Note that seek followed by - // tell will likely not give the set offset due to caching - public long raw_tell(){ - return(offset); - } - - // return PCM offset (sample) of next PCM sample to be read - public long pcm_tell(){ - return(pcm_offset); - } - - // return time offset (seconds) of next PCM sample to be read - public float time_tell(){ - // translate time to PCM position and call pcm_seek - - int link=-1; - long pcm_total=0; - float time_total=0.f; - - if(seekable){ - pcm_total=pcm_total(-1); - time_total=time_total(-1); - - // which bitstream section does this time offset occur in? - for(link=links-1;link>=0;link--){ - pcm_total-=pcmlengths[link]; - time_total-=time_total(link); - if(pcm_offset>=pcm_total)break; - } - } - - return((float)time_total+(float)(pcm_offset-pcm_total)/vi[link].rate); - } - - // link: -1) return the vorbis_info struct for the bitstream section - // currently being decoded - // 0-n) to request information for a specific bitstream section - // - // In the case of a non-seekable bitstream, any call returns the - // current bitstream. NULL in the case that the machine is not - // initialized - - public Info info(int link){ - if(seekable){ - if(link<0){ - if(decode_ready){ - return vi[current_link]; - } - else{ - return null; - } - } - else{ - if(link>=links){ - return null; - } - else{ - return vi[link]; - } - } - } - else{ - if(decode_ready){ - return vi[0]; - } - else{ - return null; - } - } - } - - public Comment comment(int link){ - if(seekable){ - if(link<0){ - if(decode_ready){ return vc[current_link]; } - else{ return null; } - } - else{ - if(link>=links){ return null;} - else{ return vc[link]; } - } - } - else{ - if(decode_ready){ return vc[0]; } - else{ return null; } - } - } - - int host_is_big_endian() { - return 1; -// short pattern = 0xbabe; -// unsigned char *bytewise = (unsigned char *)&pattern; -// if (bytewise[0] == 0xba) return 1; -// assert(bytewise[0] == 0xbe); -// return 0; - } - - // up to this point, everything could more or less hide the multiple - // logical bitstream nature of chaining from the toplevel application - // if the toplevel application didn't particularly care. However, at - // the point that we actually read audio back, the multiple-section - // nature must surface: Multiple bitstream sections do not necessarily - // have to have the same number of channels or sampling rate. - // - // read returns the sequential logical bitstream number currently - // being decoded along with the PCM data in order that the toplevel - // application can take action on channel/sample rate changes. This - // number will be incremented even for streamed (non-seekable) streams - // (for seekable streams, it represents the actual logical bitstream - // index within the physical bitstream. Note that the accessor - // functions above are aware of this dichotomy). - // - // input values: buffer) a buffer to hold packed PCM data for return - // length) the byte length requested to be placed into buffer - // bigendianp) should the data be packed LSB first (0) or - // MSB first (1) - // word) word size for output. currently 1 (byte) or - // 2 (16 bit short) - // - // return values: -1) error/hole in data - // 0) EOF - // n) number of bytes of PCM actually returned. The - // below works on a packet-by-packet basis, so the - // return length is not related to the 'length' passed - // in, just guaranteed to fit. - // - // *section) set to the logical bitstream number - - int read(byte[] buffer,int length, - int bigendianp, int word, int sgned, int[] bitstream){ - int host_endian = host_is_big_endian(); - int index=0; - - while(true){ - if(decode_ready){ - float[][] pcm; - float[][][] _pcm=new float[1][][]; - int[] _index=new int[info(-1).channels]; - int samples=vd.synthesis_pcmout(_pcm, _index); - pcm=_pcm[0]; - if(samples!=0){ - // yay! proceed to pack data into the byte buffer - int channels=info(-1).channels; - int bytespersample=word * channels; - if(samples>length/bytespersample)samples=length/bytespersample; - - // a tight loop to pack each size - { - int val; - if(word==1){ - int off=(sgned!=0?0:128); - for(int j=0;j127)val=127; - else if(val<-128)val=-128; - buffer[index++]=(byte)(val+off); - } - } - } - else{ - int off=(sgned!=0?0:32768); - - if(host_endian==bigendianp){ - if(sgned!=0){ - for(int i=0;i32767)val=32767; - else if(val<-32768)val=-32768; - buffer[dest]=(byte)(val>>>8); - buffer[dest+1]=(byte)(val); - dest+=channels*2; - } - } - } - else{ - for(int i=0;i32767)val=32767; - else if(val<-32768)val=-32768; - buffer[dest]=(byte)((val+off)>>>8); - buffer[dest+1]=(byte)(val+off); - dest+=channels*2; - } - } - } - } - else if(bigendianp!=0){ - for(int j=0;j32767)val=32767; - else if(val<-32768)val=-32768; - val+=off; - buffer[index++]=(byte)(val>>>8); - buffer[index++]=(byte)val; - } - } - } - else{ - //int val; - for(int j=0;j32767)val=32767; - else if(val<-32768)val=-32768; - val+=off; - buffer[index++]=(byte)val; - buffer[index++]=(byte)(val>>>8); - } - } - } - } - } - - vd.synthesis_read(samples); - pcm_offset+=samples; - if(bitstream!=null)bitstream[0]=current_link; - return(samples*bytespersample); - } - } - - // suck in another packet - switch(process_packet(1)){ - case 0: - return(0); - case -1: - return -1; - default: - break; - } - } - } - - public int getLinks(){return links;} - public Info[] getInfo(){return vi;} - public Comment[] getComment(){return vc;} - - public static void main(String[] arg){ - try{ - VorbisFile foo=new VorbisFile(arg[0]); - int links=foo.getLinks(); - System.out.println("links="+links); - Comment[] comment=foo.getComment(); - Info[] info=foo.getInfo(); - for(int i=0; i