📄 vorbisfile.java
字号:
/* JOrbis * Copyright (C) 2000 ymnk, JCraft,Inc. * * Written by: 2000 ymnk<ymnk@jcraft.com> * * Many thanks to * Monty <monty@xiph.org> 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;import java.io.IOException;public class VorbisFile{ static final int CHUNKSIZE=8500; static final int SEEK_SET=0; static final int SEEK_CUR=1; static final int SEEK_END=2; static final int OV_FALSE=-1; static final int OV_EOF=-2; static final int OV_HOLE=-3; static final int OV_EREAD=-128; static final int OV_EFAULT=-129; static final int OV_EIMPL=-130; static final int OV_EINVAL=-131; static final int OV_ENOTVORBIS=-132; static final int OV_EBADHEADER=-133; static final int OV_EVERSION=-134; static final int OV_ENOTAUDIO=-135; static final int OV_EBADPACKET=-136; static final int OV_EBADLINK=-137; static final int OV_ENOSEEK=-138; InputStream datasource; boolean seekable=false; long offset; long end; SyncState oy=new SyncState(); int links; long[] offsets; long[] dataoffsets; int[] serialnos; long[] pcmlengths; Info[] vi; Comment[] vc; // 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 SeekableInputStream(file); int ret=open(is, null, 0); if(ret==-1){ throw new JOrbisException("VorbisFile: open return -1"); } } catch(Exception e){ throw new JOrbisException("VorbisFile: "+e.toString()); } finally{ if(is != null){ try { is.close(); } catch (IOException e) { e.printStackTrace(); } } } } 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); return OV_EREAD; } oy.wrote(bytes); if(bytes==-1){// System.out.println("bytes="+bytes); bytes=0; } return bytes; } private void seek_helper(long offst){ //callbacks.seek_func(datasource, offst, SEEK_SET); fseek(datasource, offst, SEEK_SET); this.offset=offst; oy.reset(); } private int get_next_page(Page page, long boundary){ if(boundary>0) boundary+=offset; while(true){ int more; if(boundary>0 && offset>=boundary)return OV_FALSE; more=oy.pageseek(page); if(more<0){offset-=more;} else{ if(more==0){ if(boundary==0)return OV_FALSE;// if(get_data()<=0)return -1; int ret=get_data(); if(ret==0) return OV_EOF; if(ret<0) return OV_EREAD; } else{ int ret=(int)offset; //!!! offset+=more; return ret; } } } } private int get_prev_page(Page page) throws JOrbisException { long begin=offset; //!!! int ret; int offst=-1; while(offst==-1){ begin-=CHUNKSIZE; if(begin<0) begin=0; seek_helper(begin); while(offset<begin+CHUNKSIZE){ ret=get_next_page(page, begin+CHUNKSIZE-offset); if(ret==OV_EREAD){ return OV_EREAD; } if(ret<0){ if(offst == -1) throw new JOrbisException(); break; } else{ offst=ret; } } } seek_helper(offst); //!!! ret=get_next_page(page, CHUNKSIZE); if(ret<0){ //System.err.println("Missed page fencepost at end of logical bitstream Exiting"); //System.exit(1); return OV_EFAULT; } return offst; } int bisect_forward_serialno(long begin, long searched, long end, int currentno, int m){ long endsearched=end; long next=end; Page page=new Page(); int ret; while(searched<endsearched){ long bisect; if(endsearched-searched<CHUNKSIZE){ bisect=searched; } else{ bisect=(searched+endsearched)/2; } seek_helper(bisect); ret=get_next_page(page, -1); if(ret==OV_EREAD) return OV_EREAD; if(ret<0 || page.serialno()!=currentno){ endsearched=bisect; if(ret>=0)next=ret; } else{ searched=ret+page.header_len+page.body_len; } } seek_helper(next); ret=get_next_page(page, -1); if(ret==OV_EREAD) return OV_EREAD; if(searched>=end || ret==-1){ links=m+1; offsets=new long[m+2]; offsets[m+1]=searched; } else{ ret=bisect_forward_serialno(next, offset, end, page.serialno(), m+1); if(ret==OV_EREAD)return OV_EREAD; } offsets[m]=begin; return 0; } // 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, Page og_ptr){ //System.err.println("fetch_headers"); Page og=new Page(); Packet op=new Packet(); int ret; if(og_ptr==null){ ret=get_next_page(og, CHUNKSIZE); if(ret==OV_EREAD)return OV_EREAD; if(ret<0) return OV_ENOTVORBIS; og_ptr=og; } if(serialno!=null)serialno[0]=og_ptr.serialno(); os.init(og_ptr.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_ptr); 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_ptr, 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) throws JOrbisException { 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;i<links;i++){ if(first_i!=null && first_c!=null && i==0){ // we already grabbed the initial header earlier. This just // saves the waste of grabbing it again // !!!!!!!!!!!!! vi[i]=first_i; //memcpy(vf->vi+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(offsets[i]); //!!! vi[i]=new Info(); vc[i]=new Comment(); if(fetch_headers(vi[i], vc[i], null, 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 { long end=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() throws JOrbisException { Info initial_i=new Info(); Comment initial_c=new Comment(); int serialno; long end; int ret; int dataoffset; Page og=new Page(); // is this even vorbis...? int[] foo=new int[1]; ret=fetch_headers(initial_i, initial_c, foo, null); 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); fseek(datasource, 0, SEEK_END); //offset=end=(callbacks.tell_func)(datasource); offset=ftell(datasource); end=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 if(bisect_forward_serialno(0,0,end+1,serialno,0)<0){ clear(); return OV_EREAD; } } else{ // Only one logical bitstream if(bisect_forward_serialno(0,end,end+1,serialno,0)<0){ clear(); return OV_EREAD; } } prefetch_all_headers(initial_i, initial_c, dataoffset); 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, null)==-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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -