/** @return -1 for lost packet, 0 not enough data, or 1 for success */ private int processPacket(boolean readPage) { Page og = new Page(); while (true) { if (decodeReady) { Packet op = new Packet(); int result = os.packetout(op); if (result > 0) { int granulepos = (int) op.granulepos; if (vb.synthesis(op) == 0) { vd.synthesis_blockin(vb); if (granulepos != -1 && op.e_o_s == 0) { int samples = vd.synthesis_pcmout(null, null); granulepos -= samples; framePosition = granulepos; } return 1; } } } if (!readPage || getNextPage(og, -1) < 0) { return 0; } if (!decodeReady) { os.init(serialno); os.reset(); vd.synthesis_init(info); vb.init(vd); decodeReady = true; } os.pagein(og); } }
private void pcmOut() throws IOException { if (vorbisDspState == null) { mpcm = new float[1][][]; mindex = new int[vorbisInfo.channels]; vorbisDspState = new DspState(); vorbisDspState.synthesis_init(vorbisInfo); vorbisBlock = new Block(vorbisDspState); sampleBuffer = new byte[BUFFER_SIZE * 2]; } if (out == null) { openOutput(); } if (vorbisBlock.synthesis(oggPacket) == 0) { vorbisDspState.synthesis_blockin(vorbisBlock); } int n; int[] idx = mindex; int nch = vorbisInfo.channels; int max = sampleBuffer.length; while ((n = vorbisDspState.synthesis_pcmout(mpcm, idx)) > 0) { int len = (n < max ? n : max); float[][] pcm = mpcm[0]; int off = 0; for (int i = 0; i < len; i++) { for (int ch = 0; ch < nch; ch++) { int m = (int) (pcm[ch][idx[ch] + i] * SHORT_RANGE); if (m < Short.MIN_VALUE) { sampleBuffer[off++] = (byte) 0x00; sampleBuffer[off++] = (byte) 0x80; } else if (m > Short.MAX_VALUE) { sampleBuffer[off++] = (byte) 0xff; sampleBuffer[off++] = (byte) 0x7f; } else { short s = (short) m; sampleBuffer[off++] = (byte) s; sampleBuffer[off++] = (byte) (s >>> 8); } } } out.write(sampleBuffer, 0, 2 * nch * len); vorbisDspState.synthesis_read(len); } }
public void decodeDsp(Packet packet) { if (block.synthesis(packet) == 0) { dsp.synthesis_blockin(block); } int samplesAvail; int channels = info.channels; while ((samplesAvail = dsp.synthesis_pcmout(pcmAll, index)) > 0) { float[][] pcm = pcmAll[0]; int samplesCanRead = UNCOMP_BUFSIZE / (channels * 2); int samplesToRead = (samplesAvail < samplesCanRead ? samplesAvail : samplesCanRead); // convert floats to 16 bit signed ints and interleave for (int i = 0; i < channels; i++) { // each sample is two bytes, the sample for the 2nd // channel is at index 2, etc. int writeOff = i * 2; int readOff = index[i]; for (int j = 0; j < samplesToRead; j++) { int val = (int) (pcm[i][readOff + j] * 32767.0); // guard against clipping if (val > 32767) { val = 32767; } if (val < -32768) { val = -32768; } uncompBuf[writeOff] = (byte) (val); uncompBuf[writeOff + 1] = (byte) (val >> 8); writeOff += 2 * channels; // each sample is 2 bytes } } ringBuffer.write(uncompBuf, 0, samplesToRead * channels * 2); // tell vorbis how many samples were actualy consumed dsp.synthesis_read(samplesToRead); } }
/** @return number of frames skipped, or -1 on error. */ private int skip(int numFrames) { if (state == State.INIT) { open(); } if (state != State.OPEN) { return 0; } while (true) { if (decodeReady) { int frames = vd.synthesis_pcmout(_pcm, _index); if (frames != 0) { if (frames > numFrames) { frames = numFrames; } vd.synthesis_read(frames); framePosition += frames; return frames; } } if (processPacket(true) <= 0) { return -1; } } }
public void decode(Packet packet) { if (packetIndex < 3) { if (info.synthesis_headerin(comment, packet) < 0) { // error case; not a Vorbis header System.err.println("does not contain Vorbis audio data."); return; } if (packetIndex == 2) { dsp.synthesis_init(info); block.init(dsp); System.out.println("vorbis: " + info); System.out.println(comment.toString()); index = new int[info.channels]; if (stream == null) { stream = new AudioStream(); stream.setupFormat(info.channels, 16, info.rate); stream.updateData(this, -1); } if (masterClock instanceof SystemClock) { SystemClock clock = (SystemClock) masterClock; if (clock.needReset()) { clock.reset(); System.out.println("Note: master clock was reset by audio"); } } } } else { long gp = packet.granulepos; if (gp != -1) { lastPts = (gp * Clock.SECONDS_TO_NANOS) / info.rate; lastWritten = ringBuffer.getTotalWritten(); lastRead = ringBuffer.getTotalRead(); lastPtsWrite = System.nanoTime(); } decodeDsp(packet); } packetIndex++; }
/** * @param dest destination buffer * @param destOffset offset in the destination buffer * @param destChannels number of channels in the destination (either 1 or 2). * @param numFrames number of frames to read. * @return number of frames read, or -1 on error. Always fails if this Vorbis file has more than * two channels. */ public int read(byte[] dest, int destOffset, int destChannels, int numFrames) { if (state == State.INIT) { open(); } if (state == State.INVALID) { return -1; } else if (state != State.OPEN) { return 0; } while (true) { if (decodeReady) { int frames = vd.synthesis_pcmout(_pcm, _index); if (frames != 0) { int channels = info.channels; if (frames > numFrames) { frames = numFrames; } if (destChannels == channels) { // Mono-to-mono or stereo-to-stereo int frameSize = 2 * channels; for (int i = 0; i < channels; i++) { int ptr = destOffset + 2 * i; int mono = _index[i]; float[] pcm_row = _pcm[0][i]; for (int j = 0; j < frames; j++) { int sample = (int) (pcm_row[mono + j] * 32767); if (sample > 32767) { sample = 32767; } else if (sample < -32768) { sample = -32768; } dest[ptr] = (byte) sample; dest[ptr + 1] = (byte) (sample >> 8); ptr += frameSize; } } } else if (channels == 1 && destChannels == 2) { // Mono-to-stereo int ptr = destOffset; int mono = _index[0]; float[] pcm_row = _pcm[0][0]; for (int j = 0; j < frames; j++) { int sample = (int) (pcm_row[mono + j] * 32767); if (sample > 32767) { sample = 32767; } else if (sample < -32768) { sample = -32768; } byte a = (byte) sample; byte b = (byte) (sample >> 8); dest[ptr++] = a; dest[ptr++] = b; dest[ptr++] = a; dest[ptr++] = b; } } else if (destChannels == 1) { // Mix all channels to 1 (not tested) for (int j = 0; j < frames * 2; j++) { dest[destOffset + j] = 0; } for (int i = 0; i < channels; i++) { int ptr = destOffset; int mono = _index[i]; float[] pcm_row = _pcm[0][i]; for (int j = 0; j < frames; j++) { int oldSample = (dest[ptr] & 255) | (dest[ptr + 1] << 8); int sample = (int) (oldSample + pcm_row[mono + j] * 32767 / channels); if (sample > 32767) { sample = 32767; } else if (sample < -32768) { sample = -32768; } dest[ptr++] = (byte) sample; dest[ptr++] = (byte) (sample >> 8); } } } else { return -1; } vd.synthesis_read(frames); framePosition += frames; return frames; } } if (processPacket(true) <= 0) { return -1; } } }
/** * @return a negative number if not enough data available, 0 for failure or a positive number for * success. */ private int getHeaders(Info tempInfo, Comment tempComment) { Page og = new Page(); Packet op = new Packet(); boolean done = false; int packets = 0; // Parse the headers // Only interested in Vorbis stream while (!done) { int ret = getDataChunk(); if (ret <= 0) { return ret; } while (oy.pageout(og) > 0) { StreamState test = new StreamState(); // is this a mandated initial header? If not, stop parsing if (og.bos() == 0) { if (os != null) { os.pagein(og); } done = true; break; } int testSerialNo = og.serialno(); test.init(testSerialNo); test.pagein(og); test.packetout(op); if (packets == 0 && tempInfo.synthesis_headerin(tempComment, op) >= 0) { os = test; serialno = testSerialNo; packets = 1; } else { // Ignore unknown stream test.clear(); } } } if (packets == 0) { return 0; } // we've now identified all the bitstreams. parse the secondary header packets. while (packets < 3) { int ret; // look for more vorbis header packets while (packets < 3 && ((ret = os.packetout(op)) != 0)) { if (ret < 0 || tempInfo.synthesis_headerin(tempComment, op) != 0) { return 0; } packets++; } // The header pages/packets will arrive before anything else we // care about, or the stream is not obeying spec if (oy.pageout(og) > 0) { os.pagein(og); } else { ret = getDataChunk(); if (ret <= 0) { return ret; } } } vd.synthesis_init(tempInfo); return 1; }
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(); }