Removed dependency on JME for OggStreamDecoder (use JOrbis

directly).


git-svn-id: svn+ssh://src.earth.threerings.net/nenya/trunk@454 ed5b42cb-e716-0410-a449-f6a68f950b19
This commit is contained in:
Andrzej Kapolka
2008-03-21 02:00:20 +00:00
parent aaaebc4a2f
commit fcb5fa200c
3 changed files with 189 additions and 12 deletions
+4 -4
View File
@@ -17,9 +17,9 @@
classname="com.jmex.bui.BWindow" classpathref="classpath"/>
<echo level="info" message="Have JME-BUI: ${jme-bui.present}"/>
<available property="jme-sound.present"
classname="com.jmex.sound.openAL.SoundSystem" classpathref="classpath"/>
<echo level="info" message="Have OpenAL: ${jme-sound.present}"/>
<available property="jorbis.present"
classname="com.jcraft.jorbis.Info" classpathref="classpath"/>
<echo level="info" message="Have JOrbis: ${jorbis.present}"/>
<available property="jl.present"
classname="javazoom.jl.decoder.Decoder" classpathref="classpath"/>
@@ -39,7 +39,7 @@
<condition property="build.openal">
<and>
<isset property="lwjgl.present"/>
<isset property="jme-sound.present"/>
<isset property="jorbis.present"/>
<isset property="jl.present"/>
</and>
</condition>
+2
View File
@@ -27,6 +27,8 @@
<include name="jme-terrain.jar"/>
<include name="jme.jar"/>
<include name="jme-bui.jar"/>
<include name="jogg-0.0.7.jar"/>
<include name="jorbis-0.0.15.jar"/>
<include name="jl1.0.jar"/>
<!-- ActionScript dependencies -->
<include name="naryalib.swc"/>
@@ -25,43 +25,218 @@ import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ShortBuffer;
import org.lwjgl.openal.AL10;
import com.jmex.sound.openAL.objects.util.OggInputStream;
import com.jcraft.jogg.Packet;
import com.jcraft.jogg.Page;
import com.jcraft.jogg.StreamState;
import com.jcraft.jogg.SyncState;
import com.jcraft.jorbis.Block;
import com.jcraft.jorbis.Comment;
import com.jcraft.jorbis.DspState;
import com.jcraft.jorbis.Info;
/**
* Decodes Ogg Vorbis streams.
*/
public class OggStreamDecoder extends StreamDecoder
{
// documentation inherited
public void init (InputStream in)
throws IOException
{
_istream = new OggInputStream(in);
_in = in;
_sync.init();
_info.init();
// read the first packet "manually" to make sure everything's kosher
readChunk();
if (_sync.pageout(_page) != 1) {
throw new IOException("Input is not an Ogg bitstream.");
}
_stream.init(_page.serialno());
_stream.reset();
if (_stream.pagein(_page) < 0) {
throw new IOException("Error reading first page of Ogg bitstream data.");
}
if (_stream.packetout(_packet) != 1) {
throw new IOException("Error reading initial header packet.");
}
Comment comment = new Comment();
comment.init();
if (_info.synthesis_headerin(comment, _packet) < 0) {
throw new IOException("Ogg bitstream does not contain Vorbis audio data.");
}
// two more packets in header
for (int ii = 0; ii < 2; ii++) {
if (!readPacket()) {
throw new IOException("End of file before reading all Vorbis headers.");
}
_info.synthesis_headerin(comment, _packet);
}
_dsp.synthesis_init(_info);
_block.init(_dsp);
_offsets = new int[_info.channels];
}
// documentation inherited
public int getFormat ()
{
return (_istream.getFormat() == OggInputStream.FORMAT_MONO16) ?
AL10.AL_FORMAT_MONO16 : AL10.AL_FORMAT_STEREO16;
return (_info.channels == 1) ? AL10.AL_FORMAT_MONO16 : AL10.AL_FORMAT_STEREO16;
}
// documentation inherited
public int getFrequency ()
{
return _istream.getRate();
return _info.rate;
}
// documentation inherited
public int read (ByteBuffer buf)
throws IOException
{
return _istream.read(buf, buf.position(), buf.remaining());
ShortBuffer sbuf = buf.asShortBuffer();
int channels = _info.channels;
int total = 0;
while (sbuf.hasRemaining()) {
int samples = Math.min(readSamples(), sbuf.remaining() / channels);
if (samples == 0) {
break;
}
int length = samples * channels;
if (_data.length < length) {
_data = new short[length];
}
short[] data = _data;
for (int ii = 0; ii < channels; ii++) {
float[] pcm = _pcm[0][ii];
int sidx = _offsets[ii], didx = ii;
for (int jj = 0; jj < samples; jj++) {
float value = Math.min(Math.max(pcm[sidx], -1f), +1f);
data[didx] = (short)(value * 32767f);
sidx++;
didx += channels;
}
}
sbuf.put(_data, 0, length);
_dsp.synthesis_read(samples);
total += (length * 2);
}
buf.position(buf.position() + total);
return total;
}
/** The underlying Ogg input stream. */
protected OggInputStream _istream;
/**
* Reads a buffer's worth of samples.
*
* @return the number of samples read, or zero if we've reached the end of the stream.
*/
protected int readSamples ()
throws IOException
{
int samples;
while ((samples = _dsp.synthesis_pcmout(_pcm, _offsets)) <= 0) {
if (samples == 0 && !readPacket()) {
return 0;
}
if (_block.synthesis(_packet) == 0) {
_dsp.synthesis_blockin(_block);
}
}
return samples;
}
/**
* Reads a packet.
*
* @return true if a packet was read, false if we've reached the end of the stream.
*/
protected boolean readPacket ()
throws IOException
{
int result;
while ((result = _stream.packetout(_packet)) != 1) {
if (result == 0 && !readPage()) {
return false;
}
}
return true;
}
/**
* Reads in a page.
*
* @return true if a page was read, false if we've reached the end of the stream.
*/
protected boolean readPage ()
throws IOException
{
int result;
while ((result = _sync.pageout(_page)) != 1) {
if (result == 0 && !readChunk()) {
return false;
}
}
_stream.pagein(_page);
return true;
}
/**
* Reads in a chunk of data from the underlying input stream.
*
* @return true if a chunk was read, false if we've reached the end of the stream.
*/
protected boolean readChunk ()
throws IOException
{
int offset = _sync.buffer(BUFFER_SIZE);
int bytes = _in.read(_sync.data, offset, BUFFER_SIZE);
if (bytes > 0) {
_sync.wrote(bytes);
return true;
}
return false;
}
/** The underlying input stream. */
protected InputStream _in;
/** The sync state. */
protected SyncState _sync = new SyncState();
/** The stream state. */
protected StreamState _stream = new StreamState();
/** The output page. */
protected Page _page = new Page();
/** The output packet. */
protected Packet _packet = new Packet();
/** The stream info. */
protected Info _info = new Info();
/** The DSP state. */
protected DspState _dsp = new DspState();
/** The output block. */
protected Block _block = new Block(_dsp);
/** Holds the decoded PCM data buffers. */
protected float[][][] _pcm = new float[1][][];
/** The DSP offsets for each channel. */
protected int[] _offsets;
/** Intermediate storage for converted data. */
protected short[] _data = new short[0];
/** The decode buffer size. */
protected static final int BUFFER_SIZE = 4096 * 2;
}