📄 vorbisfile.java.new
字号:
// 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<end){ int bisect; int ret; if(end-begin<CHUNKSIZE){ bisect=begin; } else{ bisect=(end+begin)/2; } seek_helper(bisect); ret=get_next_page(og,end-bisect); if(ret==-1){ end=bisect; } else{ long granulepos=og.granulepos(); if(granulepos<target){ best=ret; // raw offset of packet with granulepos begin=(int)offset; // raw offset of next packet } else{ end=bisect; } } } // found our page. seek to it (call raw_seek). if(raw_seek(best)!=0){ //goto seek_error; pcm_offset=-1; decode_clear(); return -1; } } // verify result if(pcm_offset>=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_offset<pos){ float[][] pcm; int target=(int)(pos-pcm_offset); float[][][] _pcm=new float[1][][]; int[] _index=new int[info(-1).channels]; int samples=vd.synthesis_pcmout(_pcm, _index); pcm=_pcm[0]; if(samples>target)samples=target; vd.synthesis_read(samples); pcm_offset+=samples; if(samples<target) if(process_packet(1)==0){ pcm_offset=pcm_total(-1); // eof } } return 0; // seek_error: // dump machine so we're in a known state //pcm_offset=-1; //decode_clear(); //return -1; } // seek to a playback time relative to the decompressed pcm stream // returns zero on success, nonzero on failure public int time_seek(float seconds){ // translate time to PCM position and call pcm_seek int link=-1; long pcm_total=pcm_total(-1); float time_total=time_total(-1); if(!seekable)return(-1); // don't dump machine if we can't seek if(seconds<0 || seconds>time_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;j<samples;j++){ for(int i=0;i<channels;i++){ val=(int)(pcm[i][_index[i]+j]*128. + 0.5); if(val>127)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;i<channels;i++) { // It's faster in this order int src=_index[i]; int dest=i; for(int j=0;j<samples;j++) { val=(int)(pcm[i][src+j]*32768. + 0.5); if(val>32767)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;i<channels;i++) { float[] src=pcm[i]; int dest=i; for(int j=0;j<samples;j++) { val=(int)(src[j]*32768. + 0.5); if(val>32767)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;j<samples;j++){ for(int i=0;i<channels;i++){ val=(int)(pcm[i][j]*32768. + 0.5); if(val>32767)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;j<samples;j++){ for(int i=0;i<channels;i++){ val=(int)(pcm[i][j]*32768. + 0.5); if(val>32767)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<links; i++){ System.out.println(info[i]); System.out.println(comment[i]); } System.out.println("raw_total: "+foo.raw_total(-1)); System.out.println("pcm_total: "+foo.pcm_total(-1)); System.out.println("time_total: "+foo.time_total(-1)); } catch(Exception e){ System.err.println(e); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -