/** * Open callbacks. * * @param is input stream * @param initial initial bytes * @param ibytes initial count * @return success flag * @throws JOrbisException if an error occurs */ int openCallbacks(InputStream is, byte[] initial, int ibytes) throws JOrbisException { int ret; datasource = is; 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); } // can we seek? Stevens suggests the seek test was portable if (is instanceof SeekableInputStream) { ret = openSeekable(); } else { ret = openNonseekable(); } if (ret != 0) { datasource = null; clear(); } return ret; }
/** * Get the data. * * @return the number of bytes read */ private int getData() { int index = oy.buffer(CHUNKSIZE); byte[] buffer = oy.data; int bytes = 0; try { bytes = datasource.read(buffer, index, CHUNKSIZE); } catch (Exception e) { return OV_EREAD; } oy.wrote(bytes); if (bytes == -1) { bytes = 0; } return bytes; }
private void pageOut() throws IOException { if (oggPage == null) { oggPage = new Page(); } for (; ; ) { switch (oggSyncState.pageout(oggPage)) { case 0: return; case 1: if (oggStreamState == null) { oggStreamState = new StreamState(); oggStreamState.init(oggPage.serialno()); oggStreamState.reset(); } if (oggStreamState.pagein(oggPage) < 0) { throw new IOException("error reading ogg page"); } else { packetOut(); if (oggPage.eos() != 0) { throw new EOFException(); } } break; default: throw new IOException("ogg input format error"); } } }
/** * Get next page. * * @param page the page * @param boundary the boundary * @return the offset or error code OV_* */ private int getNextPage(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; } int ret = getData(); if (ret == 0) { return OV_EOF; } if (ret < 0) { return OV_EREAD; } } else { int ret = (int) offset; // !!! offset += more; return ret; } } } }
/** Initializes all the jOrbis and jOgg vars that are used for song playback. */ private void init_jorbis() { oggSyncState_ = new SyncState(); oggStreamState_ = new StreamState(); oggPage_ = new Page(); oggPacket_ = new Packet(); vorbisInfo = new Info(); vorbisComment = new Comment(); vorbisDspState = new DspState(); vorbisBlock = new Block(vorbisDspState); buffer = null; bytes = 0; oggSyncState_.init(); }
/* * Taken from the JOrbis Player */ private void initJOrbis() { oy = new SyncState(); os = new StreamState(); og = new Page(); op = new Packet(); vi = new Info(); vc = new Comment(); vd = new DspState(); vb = new Block(vd); buffer = null; bytes = 0; oy.init(); }
/** * The helpers are over; it's all toplevel interface from here on out clear out the OggVorbis_File * struct. */ void clear() { vb.clear(); vd.clear(); os.clear(); if (vi != null && links != 0) { for (int i = 0; i < links; i++) { vi[i].clear(); vc[i].clear(); } vi = null; vc = null; } dataoffsets = null; pcmlengths = null; serialnos = null; offsets = null; oy.clear(); }
public void run() { if (Thread.currentThread() != this) { throw new IllegalStateException("not this thread"); } try { SyncState syncState = this.oggSyncState = new SyncState(); while (in != null) { int off = syncState.buffer(BUFFER_SIZE); int n = in.read(syncState.data, off, BUFFER_SIZE); if (n > 0) { syncState.wrote(n); pageOut(); } else { break; } } } catch (EOFException e) { } catch (IOException e) { failure = e; e.printStackTrace(); } finally { try { if (in != null) { in.close(); in = null; } } catch (IOException e) { if (failure != null) { failure = e; } e.printStackTrace(); } if (out != null) { out.stop(); out.close(); } if (vorbisBlock != null) { vorbisBlock.clear(); vorbisBlock = null; } if (vorbisDspState != null) { vorbisDspState.clear(); vorbisDspState = null; } if (vorbisInfo != null) { vorbisInfo.clear(); vorbisInfo = null; } if (oggStreamState != null) { oggStreamState.clear(); oggStreamState = null; } if (oggSyncState != null) { oggSyncState.clear(); oggSyncState = null; } synchronized (this) { notifyAll(); } } }
/* * Taken from the JOrbis Player */ private void playStream(Thread me) throws InternalException { boolean chained = false; initJOrbis(); while (true) { if (checkState()) { return; } int eos = 0; int index = oy.buffer(BUFSIZE); buffer = oy.data; try { bytes = bitStream.read(buffer, index, BUFSIZE); } catch (Exception e) { throw new InternalException(e); } oy.wrote(bytes); if (chained) { chained = false; } else { if (oy.pageout(og) != 1) { if (bytes < BUFSIZE) break; throw new InternalException("Input does not appear to be an Ogg bitstream."); } } os.init(og.serialno()); os.reset(); vi.init(); vc.init(); if (os.pagein(og) < 0) { // error; stream version mismatch perhaps throw new InternalException("Error reading first page of Ogg bitstream data."); } if (os.packetout(op) != 1) { // no page? must not be vorbis throw new InternalException("Error reading initial header packet."); } if (vi.synthesis_headerin(vc, op) < 0) { // error case; not a vorbis header throw new InternalException("This Ogg bitstream does not contain Vorbis audio data."); } int i = 0; while (i < 2) { while (i < 2) { if (checkState()) { return; } int result = oy.pageout(og); if (result == 0) break; // Need more data if (result == 1) { os.pagein(og); while (i < 2) { result = os.packetout(op); if (result == 0) break; if (result == -1) { throw new InternalException("Corrupt secondary header. Exiting."); } vi.synthesis_headerin(vc, op); i++; } } } index = oy.buffer(BUFSIZE); buffer = oy.data; try { bytes = bitStream.read(buffer, index, BUFSIZE); } catch (Exception e) { throw new InternalException(e); } if (bytes == 0 && i < 2) { throw new InternalException("End of file before finding all Vorbis headers!"); } oy.wrote(bytes); } convsize = BUFSIZE / vi.channels; vd.synthesis_init(vi); vb.init(vd); float[][][] _pcmf = new float[1][][]; int[] _index = new int[vi.channels]; getOutputLine(vi.channels, vi.rate); while (eos == 0) { while (eos == 0) { if (player != me) { return; } int result = oy.pageout(og); if (result == 0) break; // need more data if (result == -1) { // missing or corrupt data at this page // position // System.err.println("Corrupt or missing data in // bitstream; // continuing..."); } else { os.pagein(og); if (og.granulepos() == 0) { // chained = true; // eos = 1; // break; // } // while (true) { if (checkState()) { return; } result = os.packetout(op); if (result == 0) break; // need more data if (result == -1) { // missing or corrupt data at // this page position // no reason to complain; already complained // above // System.err.println("no reason to complain; // already complained above"); } else { // we have a packet. Decode it int samples; if (vb.synthesis(op) == 0) { // test for // success! vd.synthesis_blockin(vb); } while ((samples = vd.synthesis_pcmout(_pcmf, _index)) > 0) { if (checkState()) { return; } float[][] pcmf = _pcmf[0]; int bout = (samples < convsize ? samples : convsize); // convert doubles to 16 bit signed ints // (host order) and // interleave for (i = 0; i < vi.channels; i++) { int ptr = i * 2; // int ptr=i; int mono = _index[i]; for (int j = 0; j < bout; j++) { int val = (int) (pcmf[i][mono + j] * 32767.); if (val > 32767) { val = 32767; } if (val < -32768) { val = -32768; } if (val < 0) val = val | 0x8000; convbuffer[ptr] = (byte) (val); convbuffer[ptr + 1] = (byte) (val >>> 8); ptr += 2 * (vi.channels); } } outputLine.write(convbuffer, 0, 2 * vi.channels * bout); vd.synthesis_read(bout); } } } if (og.eos() != 0) eos = 1; } } if (eos == 0) { index = oy.buffer(BUFSIZE); buffer = oy.data; try { bytes = bitStream.read(buffer, index, BUFSIZE); } catch (Exception e) { throw new InternalException(e); } if (bytes == -1) { break; } oy.wrote(bytes); if (bytes == 0) eos = 1; } } os.clear(); vb.clear(); vd.clear(); vi.clear(); } oy.clear(); }
/** Reads headers and comments. */ private void readHeaders(HashMap aff_properties, HashMap af_properties) throws IOException { if (TDebug.TraceAudioConverter) TDebug.out("readHeaders("); index = oggSyncState_.buffer(bufferSize_); buffer = oggSyncState_.data; bytes = readFromStream(buffer, index, bufferSize_); if (bytes == -1) { if (TDebug.TraceAudioConverter) TDebug.out("Cannot get any data from selected Ogg bitstream."); throw new IOException("Cannot get any data from selected Ogg bitstream."); } oggSyncState_.wrote(bytes); if (oggSyncState_.pageout(oggPage_) != 1) { if (bytes < bufferSize_) { throw new IOException("EOF"); } if (TDebug.TraceAudioConverter) TDebug.out("Input does not appear to be an Ogg bitstream."); throw new IOException("Input does not appear to be an Ogg bitstream."); } oggStreamState_.init(oggPage_.serialno()); vorbisInfo.init(); vorbisComment.init(); aff_properties.put("ogg.serial", new Integer(oggPage_.serialno())); if (oggStreamState_.pagein(oggPage_) < 0) { // error; stream version mismatch perhaps if (TDebug.TraceAudioConverter) TDebug.out("Error reading first page of Ogg bitstream data."); throw new IOException("Error reading first page of Ogg bitstream data."); } if (oggStreamState_.packetout(oggPacket_) != 1) { // no page? must not be vorbis if (TDebug.TraceAudioConverter) TDebug.out("Error reading initial header packet."); throw new IOException("Error reading initial header packet."); } if (vorbisInfo.synthesis_headerin(vorbisComment, oggPacket_) < 0) { // error case; not a vorbis header if (TDebug.TraceAudioConverter) TDebug.out("This Ogg bitstream does not contain Vorbis audio data."); throw new IOException("This Ogg bitstream does not contain Vorbis audio data."); } int i = 0; while (i < 2) { while (i < 2) { int result = oggSyncState_.pageout(oggPage_); if (result == 0) { break; } // Need more data if (result == 1) { oggStreamState_.pagein(oggPage_); while (i < 2) { result = oggStreamState_.packetout(oggPacket_); if (result == 0) { break; } if (result == -1) { if (TDebug.TraceAudioConverter) TDebug.out("Corrupt secondary header. Exiting."); throw new IOException("Corrupt secondary header. Exiting."); } vorbisInfo.synthesis_headerin(vorbisComment, oggPacket_); i++; } } } index = oggSyncState_.buffer(bufferSize_); buffer = oggSyncState_.data; bytes = readFromStream(buffer, index, bufferSize_); if (bytes == -1) { break; } if (bytes == 0 && i < 2) { if (TDebug.TraceAudioConverter) TDebug.out("End of file before finding all Vorbis headers!"); throw new IOException("End of file before finding all Vorbis headers!"); } oggSyncState_.wrote(bytes); } // Read Ogg Vorbis comments. byte[][] ptr = vorbisComment.user_comments; String currComment = ""; int c = 0; for (int j = 0; j < ptr.length; j++) { if (ptr[j] == null) { break; } currComment = (new String(ptr[j], 0, ptr[j].length - 1, "UTF-8")).trim(); if (TDebug.TraceAudioConverter) TDebug.out(currComment); if (currComment.toLowerCase().startsWith("artist")) { aff_properties.put("author", currComment.substring(7)); } else if (currComment.toLowerCase().startsWith("title")) { aff_properties.put("title", currComment.substring(6)); } else if (currComment.toLowerCase().startsWith("album")) { aff_properties.put("album", currComment.substring(6)); } else if (currComment.toLowerCase().startsWith("date")) { aff_properties.put("date", currComment.substring(5)); } else if (currComment.toLowerCase().startsWith("copyright")) { aff_properties.put("copyright", currComment.substring(10)); } else if (currComment.toLowerCase().startsWith("comment")) { aff_properties.put("comment", currComment.substring(8)); } else if (currComment.toLowerCase().startsWith("genre")) { aff_properties.put("ogg.comment.genre", currComment.substring(6)); } else if (currComment.toLowerCase().startsWith("tracknumber")) { aff_properties.put("ogg.comment.track", currComment.substring(12)); } else { c++; aff_properties.put("ogg.comment.ext." + c, currComment); } aff_properties.put( "ogg.comment.encodedby", new String(vorbisComment.vendor, 0, vorbisComment.vendor.length - 1)); } }
/** * Seek helper function. * * @param offst the offset to seek */ private void seekHelper(long offst) { fseek(datasource, offst, SEEK_SET); this.offset = offst; oy.reset(); }